clevic 0.13.0.b9 → 0.13.0.b10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/lib/clevic/action_builder.rb +16 -16
- data/lib/clevic/ar_methods.rb +22 -22
- data/lib/clevic/attribute_list.rb +5 -5
- data/lib/clevic/cache_table.rb +18 -18
- data/lib/clevic/dataset_roller.rb +3 -3
- data/lib/clevic/default_view.rb +4 -4
- data/lib/clevic/delegate.rb +8 -8
- data/lib/clevic/delegates/combo_delegate.rb +22 -22
- data/lib/clevic/delegates/distinct_delegate.rb +5 -5
- data/lib/clevic/delegates/relational_delegate.rb +6 -6
- data/lib/clevic/delegates/set_delegate.rb +3 -3
- data/lib/clevic/dirty.rb +1 -1
- data/lib/clevic/emitter.rb +3 -3
- data/lib/clevic/extensions.rb +4 -4
- data/lib/clevic/field.rb +68 -68
- data/lib/clevic/field_valuer.rb +26 -26
- data/lib/clevic/filter_command.rb +6 -6
- data/lib/clevic/framework.rb +3 -3
- data/lib/clevic/generic_format.rb +2 -2
- data/lib/clevic/many_field.rb +3 -3
- data/lib/clevic/model_builder.rb +88 -84
- data/lib/clevic/model_column.rb +13 -13
- data/lib/clevic/ordered_dataset.rb +7 -7
- data/lib/clevic/qt/action_builder.rb +3 -3
- data/lib/clevic/qt/browser.rb +28 -28
- data/lib/clevic/qt/clipboard.rb +5 -5
- data/lib/clevic/qt/combo_delegate.rb +12 -12
- data/lib/clevic/qt/distinct_delegate.rb +1 -1
- data/lib/clevic/qt/extensions.rb +4 -4
- data/lib/clevic/qt/qt_combo_box.rb +7 -7
- data/lib/clevic/qt/relational_delegate.rb +5 -5
- data/lib/clevic/qt/search_dialog.rb +15 -15
- data/lib/clevic/qt/simplest_delegate.rb +2 -2
- data/lib/clevic/qt/table_model.rb +46 -46
- data/lib/clevic/qt/table_view.rb +48 -48
- data/lib/clevic/qt/text_delegate.rb +9 -9
- data/lib/clevic/rails_models_loaders.rb +3 -3
- data/lib/clevic/record.rb +8 -8
- data/lib/clevic/sampler.rb +6 -6
- data/lib/clevic/sequel_ar_adapter.rb +22 -22
- data/lib/clevic/sequel_clevic.rb +10 -10
- data/lib/clevic/sequel_meta.rb +5 -5
- data/lib/clevic/sequel_naked.rb +4 -4
- data/lib/clevic/swing/action.rb +20 -20
- data/lib/clevic/swing/action_builder.rb +2 -2
- data/lib/clevic/swing/boolean_delegate.rb +3 -3
- data/lib/clevic/swing/browser.rb +37 -37
- data/lib/clevic/swing/cell_editor.rb +13 -13
- data/lib/clevic/swing/cell_renderer.rb +7 -7
- data/lib/clevic/swing/clipboard.rb +19 -19
- data/lib/clevic/swing/combo_delegate.rb +26 -26
- data/lib/clevic/swing/confirm_dialog.rb +7 -7
- data/lib/clevic/swing/delegate.rb +4 -4
- data/lib/clevic/swing/extensions.rb +24 -24
- data/lib/clevic/swing/field.rb +1 -1
- data/lib/clevic/swing/relational_delegate.rb +2 -2
- data/lib/clevic/swing/row_header.rb +32 -32
- data/lib/clevic/swing/search_dialog.rb +31 -31
- data/lib/clevic/swing/selection_model.rb +12 -12
- data/lib/clevic/swing/swing_table_index.rb +6 -6
- data/lib/clevic/swing/table_model.rb +30 -30
- data/lib/clevic/swing/table_view.rb +54 -54
- data/lib/clevic/swing/table_view_focus.rb +4 -4
- data/lib/clevic/swing/tag_delegate.rb +14 -14
- data/lib/clevic/swing/tag_editor.rb +4 -4
- data/lib/clevic/swing/text_area_delegate.rb +6 -6
- data/lib/clevic/swing/text_delegate.rb +4 -4
- data/lib/clevic/table_index.rb +14 -14
- data/lib/clevic/table_model.rb +30 -30
- data/lib/clevic/table_searcher.rb +19 -19
- data/lib/clevic/table_view.rb +92 -92
- data/lib/clevic/table_view_paste.rb +19 -19
- data/lib/clevic/version.rb +1 -1
- data/lib/clevic/view.rb +22 -22
- data/models/accounts_models.rb +10 -10
- data/models/examples.rb +2 -2
- data/models/times_models.rb +32 -32
- data/models/values_models.rb +2 -2
- data/test/test_cache_table.rb +15 -15
- data/test/test_helper.rb +7 -7
- data/test/test_model_index_extensions.rb +6 -6
- data/test/test_table_model.rb +6 -6
- data/test/test_table_searcher.rb +25 -25
- metadata +33 -35
data/lib/clevic/delegate.rb
CHANGED
@@ -11,37 +11,37 @@ class Delegate
|
|
11
11
|
super()
|
12
12
|
@field = field
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# This is the ORM entity instance for which this delegate
|
16
16
|
# is editing a single field. It needs to be the entire entity
|
17
17
|
# so we can set the edited field value on it.
|
18
18
|
attr_accessor :entity
|
19
|
-
|
19
|
+
|
20
20
|
# The parent widget of this delegate / this delegate's widget
|
21
21
|
attr_accessor :parent
|
22
|
-
|
22
|
+
|
23
23
|
# the Clevic::Field instance which this delegate edits.
|
24
24
|
attr_reader :field
|
25
|
-
|
25
|
+
|
26
26
|
def attribute
|
27
27
|
field.attribute
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def entity_class
|
31
31
|
field.entity_class
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# assume this is not a combo delegate. That will come later.
|
35
35
|
def is_combo?
|
36
36
|
false
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# change the visual state of the editor to the biggest / most
|
40
40
|
# space-consuming it can be. This grew out of combo boxes having
|
41
41
|
# a drop-down that can show or hide.
|
42
42
|
def full_edit
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# change the visual state of the editor to the smallest / least
|
46
46
|
# space-consuming it can be. This grew out of combo boxes having
|
47
47
|
# a drop-down that can show or hide.
|
@@ -12,23 +12,23 @@ class ComboDelegate
|
|
12
12
|
# in some cases.
|
13
13
|
# if editor is a combo it must support no_insert=( bool )
|
14
14
|
attr_reader :editor
|
15
|
-
|
15
|
+
|
16
16
|
# Return a string to be shown to the user.
|
17
17
|
# model_value is an item stored in the combo box model.
|
18
18
|
def display_for( model_value )
|
19
19
|
field.transform_attribute( model_value )
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# Some GUIs (Qt) can just set this. Swing can't.
|
23
23
|
def configure_prefix
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# TODO kinda redundant because all combos must be editable
|
27
27
|
# to support prefix matching
|
28
28
|
def configure_editable
|
29
29
|
editor.editable = true
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# this will create the actual combo box widget
|
33
33
|
framework_responsibility :create_combo_box
|
34
34
|
|
@@ -38,13 +38,13 @@ class ComboDelegate
|
|
38
38
|
# to the combo box without having to deal with events triggered
|
39
39
|
# by setup code.
|
40
40
|
framework_responsibility :framework_setup
|
41
|
-
|
41
|
+
|
42
42
|
# This is called by the combo box to convert an item
|
43
43
|
# to something that the combo can insert into
|
44
44
|
# itself. Usually this will be a display value
|
45
45
|
# and a storage value.
|
46
46
|
framework_responsibility :item_to_editor
|
47
|
-
|
47
|
+
|
48
48
|
# This is called by the combo box when it needs to convert a
|
49
49
|
# storage value to an item, which is something that the delegate
|
50
50
|
# will understand.
|
@@ -59,26 +59,26 @@ class ComboDelegate
|
|
59
59
|
if needs_combo?
|
60
60
|
@editor = create_combo_box( *args )
|
61
61
|
@editor.delegate = self
|
62
|
-
|
62
|
+
|
63
63
|
# add all entries from population
|
64
64
|
population.each do |item|
|
65
65
|
editor << item
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
# create a nil entry if necessary
|
69
69
|
if allow_null? && !editor.include?( nil )
|
70
70
|
editor << nil
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
# don't allow inserts if the delegate is restricted
|
74
74
|
editor.no_insert = restricted?
|
75
|
-
|
75
|
+
|
76
76
|
# set the correct value in the list
|
77
77
|
editor.selected_item = entity.nil? ? nil : attribute_value
|
78
|
-
|
78
|
+
|
79
79
|
# set up prefix matching when typing in the editor
|
80
80
|
configure_prefix
|
81
|
-
|
81
|
+
|
82
82
|
framework_setup( *args )
|
83
83
|
else
|
84
84
|
@editor =
|
@@ -93,26 +93,26 @@ class ComboDelegate
|
|
93
93
|
end
|
94
94
|
editor
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# open the combo box, just like if F4 was pressed
|
98
98
|
framework_responsibility :full_edit
|
99
|
-
|
99
|
+
|
100
100
|
# show only the text editor part, not the drop-down
|
101
101
|
def minimal_edit
|
102
102
|
editor.hide_popup if is_combo?
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
# returns true if the editor allows values outside of a predefined
|
106
106
|
# range, false otherwise.
|
107
107
|
def restricted?
|
108
108
|
false
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
# TODO fetch this from the model definition
|
112
112
|
def allow_null?
|
113
113
|
true
|
114
114
|
end
|
115
|
-
|
115
|
+
|
116
116
|
# Subclasses should override this to prove a list of
|
117
117
|
# values to be used by the combo box. Values could
|
118
118
|
# be pretty much anything, depending on the delegate.
|
@@ -120,7 +120,7 @@ class ComboDelegate
|
|
120
120
|
# of entity objects, most other delegates will have collections
|
121
121
|
# of strings.
|
122
122
|
subclass_responsibility :population
|
123
|
-
|
123
|
+
|
124
124
|
# Return true if this delegate needs a combo, false otherwise
|
125
125
|
# ie if there are no values yet and it's not restricted, then a
|
126
126
|
# full combo doesn't make sense
|
@@ -129,23 +129,23 @@ class ComboDelegate
|
|
129
129
|
# return true if this delegate has/needs a combo widget
|
130
130
|
# or false if it's a plain text field.
|
131
131
|
framework_responsibility :is_combo?
|
132
|
-
|
132
|
+
|
133
133
|
# return true if this field has no data (needs_combo? is false)
|
134
134
|
# and is at the same time restricted (ie needs data from somewhere else)
|
135
135
|
def empty_set?
|
136
136
|
!needs_combo? && restricted?
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
# the message to display if the set is empty, and
|
140
140
|
# the delegate is restricted to a predefined set.
|
141
141
|
subclass_responsibility :empty_set_message
|
142
|
-
|
142
|
+
|
143
143
|
# if this delegate has an empty set, return the message, otherwise
|
144
144
|
# return nil.
|
145
145
|
def if_empty_message
|
146
146
|
empty_set_message if empty_set?
|
147
147
|
end
|
148
|
-
|
148
|
+
|
149
149
|
# the value represented by the combo, ie either
|
150
150
|
# the current attribute_value of the field
|
151
151
|
# this combo is editing, or an object that could
|
@@ -7,12 +7,12 @@ module Clevic
|
|
7
7
|
# :frequency can be set as an option. Boolean. If it's true
|
8
8
|
# the options are sorted in order of most frequently used first.
|
9
9
|
class DistinctDelegate
|
10
|
-
|
10
|
+
|
11
11
|
def needs_combo?
|
12
12
|
# works except when there is a null in the column
|
13
13
|
dataset.count > 0
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
# TODO move away from ar_methods. Partly done.
|
17
17
|
# TODO ordering by either recentness, or frequency. OR both.
|
18
18
|
# TODO make sure nil is in the list. And the current item is at the top.
|
@@ -31,7 +31,7 @@ class DistinctDelegate
|
|
31
31
|
else
|
32
32
|
field.dataset_roller.dataset
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# now pull out the field and the distinct values
|
36
36
|
base_dataset. \
|
37
37
|
distinct. \
|
@@ -39,11 +39,11 @@ class DistinctDelegate
|
|
39
39
|
order( field.attribute ). \
|
40
40
|
naked
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def population
|
44
44
|
dataset.map( field.attribute )
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
@@ -9,18 +9,18 @@ class RelationalDelegate
|
|
9
9
|
def needs_combo?
|
10
10
|
dataset.count > 0
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def empty_set_message
|
14
14
|
"There must be records in #{field.related_class} for this field to be editable."
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def population
|
18
18
|
# dataset contains the set of all possible related entities,
|
19
|
-
|
19
|
+
|
20
20
|
# dataset is defined in Delegate
|
21
21
|
# entity is set in init_component
|
22
22
|
# field and entity are used by FieldValuer
|
23
|
-
|
23
|
+
|
24
24
|
# including the current entity.
|
25
25
|
# Could also use
|
26
26
|
# dataset.or( entity_class.primary_key => entity_key.pk )
|
@@ -35,7 +35,7 @@ class RelationalDelegate
|
|
35
35
|
values.unshift( attribute_value )
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# don't allow new values
|
40
40
|
def restricted?; true; end
|
41
41
|
|
@@ -53,7 +53,7 @@ protected
|
|
53
53
|
field.dataset_roller.dataset
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
end
|
58
58
|
|
59
59
|
end
|
@@ -11,15 +11,15 @@ class SetDelegate
|
|
11
11
|
raise "SetDelegate must have a :set in options" if field.set.nil?
|
12
12
|
super
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def needs_combo?
|
16
16
|
true
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def restricted?
|
20
20
|
field.restricted || false
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
# Items here could either be single values,
|
24
24
|
# or two-value arrays (from a hash-like set), so use key as db value
|
25
25
|
# and value as display value
|
data/lib/clevic/dirty.rb
CHANGED
data/lib/clevic/emitter.rb
CHANGED
@@ -6,14 +6,14 @@ module Clevic
|
|
6
6
|
def self.included( base )
|
7
7
|
base.extend( ClassMethods )
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
module ClassMethods
|
11
11
|
def emitter( emitter_name )
|
12
12
|
line, st = __LINE__, <<-EOF
|
13
13
|
def #{emitter_name}_listeners
|
14
14
|
@#{emitter_name}_listeners ||= Set.new
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# If msg is provided, yield to stored block.
|
18
18
|
# If block is provided, store it for later.
|
19
19
|
def emit_#{emitter_name}( *args, ¬ifier_block )
|
@@ -26,7 +26,7 @@ module Clevic
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def remove_#{emitter_name}( ¬ifier_block )
|
31
31
|
#{emitter_name}_listeners.delete( notifier_block )
|
32
32
|
end
|
data/lib/clevic/extensions.rb
CHANGED
@@ -9,7 +9,7 @@ class Object
|
|
9
9
|
value.nil? ? nil : value.send( att )
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# pass self to the block and return the results of the block.
|
14
14
|
def with( &block )
|
15
15
|
yield( self )
|
@@ -59,7 +59,7 @@ class Array
|
|
59
59
|
index if include?( index )
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def section
|
64
64
|
return [] if empty?
|
65
65
|
rv = [first]
|
@@ -69,7 +69,7 @@ class Array
|
|
69
69
|
end
|
70
70
|
rv
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
# group by ascending values
|
74
74
|
def group
|
75
75
|
parts = []
|
@@ -81,7 +81,7 @@ class Array
|
|
81
81
|
parts + self[section.size..-1].group
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
def range
|
86
86
|
first..last
|
87
87
|
end
|
data/lib/clevic/field.rb
CHANGED
@@ -19,10 +19,10 @@ will allow
|
|
19
19
|
|
20
20
|
# reader
|
21
21
|
instance.ixnay
|
22
|
-
|
22
|
+
|
23
23
|
# writer
|
24
24
|
instance.ixnay = 'nix, baby'
|
25
|
-
|
25
|
+
|
26
26
|
# writer
|
27
27
|
instance.ixnay 'nix baby'
|
28
28
|
|
@@ -42,10 +42,10 @@ And so it the #-- above.
|
|
42
42
|
class Field
|
43
43
|
# For defining properties
|
44
44
|
include Gather
|
45
|
-
|
45
|
+
|
46
46
|
# for formatting values
|
47
47
|
include GenericFormat
|
48
|
-
|
48
|
+
|
49
49
|
##
|
50
50
|
# :attr:
|
51
51
|
# The value to be displayed after being optionally format-ed
|
@@ -62,33 +62,33 @@ class Field
|
|
62
62
|
#
|
63
63
|
# Defaults to nil, in other words the value of the attribute for this field.
|
64
64
|
property :display
|
65
|
-
|
65
|
+
|
66
66
|
##
|
67
67
|
# :attr:
|
68
68
|
# The label to be displayed in the column headings. Defaults to the humanised field name.
|
69
69
|
property :label
|
70
|
-
|
70
|
+
|
71
71
|
##
|
72
72
|
# :attr:
|
73
73
|
# One of the alignment specifiers - :left, :centre, :right or :justified.
|
74
74
|
# Defaults to right for numeric fields, centre for boolean, and left for
|
75
75
|
# other values.
|
76
76
|
property :alignment
|
77
|
-
|
77
|
+
|
78
78
|
##
|
79
79
|
# :attr:
|
80
80
|
# something to do with the icon that Qt displays. Not implemented yet.
|
81
81
|
property :decoration
|
82
|
-
|
82
|
+
|
83
83
|
##
|
84
84
|
# :attr:
|
85
85
|
# This defines how to format the value returned by :display. It takes a string or a Proc.
|
86
|
-
# Generally the string is something
|
87
|
-
# that can be understood by strftime (for time and date fields) or understood
|
88
|
-
# by % (for everything else). It can also be a Proc that has one parameter -
|
86
|
+
# Generally the string is something
|
87
|
+
# that can be understood by strftime (for time and date fields) or understood
|
88
|
+
# by % (for everything else). It can also be a Proc that has one parameter -
|
89
89
|
# the current entity. There are sensible defaults for common field types.
|
90
90
|
property :format
|
91
|
-
|
91
|
+
|
92
92
|
##
|
93
93
|
# :attr:
|
94
94
|
# This is just like format, except that it's used to format the value just
|
@@ -96,12 +96,12 @@ class Field
|
|
96
96
|
# but edit them with a 4 digit year.
|
97
97
|
# Defaults to a sensible value for some fields, for others it will default to the value of :format.
|
98
98
|
property :edit_format
|
99
|
-
|
99
|
+
|
100
100
|
##
|
101
101
|
# :attr:
|
102
102
|
# Whether the field is currently visible or not.
|
103
103
|
property :visible
|
104
|
-
|
104
|
+
|
105
105
|
##
|
106
106
|
# :attr:
|
107
107
|
# Sample is used if the programmer wishes to provide a value (that will be converted
|
@@ -111,12 +111,12 @@ class Field
|
|
111
111
|
# doesn't always work properly. So we
|
112
112
|
# have the option to override that if we wish.
|
113
113
|
property :sample
|
114
|
-
|
114
|
+
|
115
115
|
##
|
116
116
|
# :attr:
|
117
117
|
# Takes a boolean. Set the field to read-only.
|
118
118
|
property :read_only
|
119
|
-
|
119
|
+
|
120
120
|
##
|
121
121
|
# :attr:
|
122
122
|
# The foreground and background colors.
|
@@ -125,10 +125,10 @@ class Field
|
|
125
125
|
# - A String is treated as a constant which may be one of the string constants understood by Qt::Color
|
126
126
|
# - A symbol is treated as a method to be call on an entity
|
127
127
|
#
|
128
|
-
# The result can be a Qt::Color, or one of the strings in
|
128
|
+
# The result can be a Qt::Color, or one of the strings in
|
129
129
|
# http://www.w3.org/TR/SVG/types.html#ColorKeywords.
|
130
130
|
property :foreground, :background
|
131
|
-
|
131
|
+
|
132
132
|
##
|
133
133
|
# :attr:
|
134
134
|
# Can take a Proc, a string, or a symbol.
|
@@ -136,7 +136,7 @@ class Field
|
|
136
136
|
# - A String is treated as a constant
|
137
137
|
# - A symbol is treated as a method to be call on an entity
|
138
138
|
property :tooltip
|
139
|
-
|
139
|
+
|
140
140
|
##
|
141
141
|
# :attr:
|
142
142
|
# An Enumerable of allowed values for restricted fields. If each yields
|
@@ -144,7 +144,7 @@ class Field
|
|
144
144
|
# first will be stored in the db, and the second displayed in the UI.
|
145
145
|
# If it's a proc, that must return an Enumerable as above.
|
146
146
|
property :set
|
147
|
-
|
147
|
+
|
148
148
|
##
|
149
149
|
# :attr:
|
150
150
|
# When this is true, only the values in the combo may be entered.
|
@@ -152,7 +152,7 @@ class Field
|
|
152
152
|
# non-listed values. Default is true if a set is explicitly specified.
|
153
153
|
# Otherwise depends on the field type.
|
154
154
|
property :restricted
|
155
|
-
|
155
|
+
|
156
156
|
##
|
157
157
|
# :attr:
|
158
158
|
# Only for the distinct field type. The values will be sorted either with the
|
@@ -160,21 +160,21 @@ class Field
|
|
160
160
|
# alphabetical order (:description => true).
|
161
161
|
# FIXME re-implement this with Dataset
|
162
162
|
property :frequency, :description
|
163
|
-
|
163
|
+
|
164
164
|
##
|
165
165
|
# :attr:
|
166
166
|
# Default value for this field for new records.
|
167
167
|
# Can be a Proc or a value. A value will just be
|
168
168
|
# set, a proc will be executed with the entity as a parameter.
|
169
169
|
property :default
|
170
|
-
|
170
|
+
|
171
171
|
##
|
172
172
|
# :attr:
|
173
173
|
# The property used for finding the field, ie by TableModel#field_column.
|
174
174
|
# Defaults to the attribute. If there are several display fields based on
|
175
175
|
# one db field, their attribute will be the same, but their id must be different.
|
176
176
|
property :id
|
177
|
-
|
177
|
+
|
178
178
|
##
|
179
179
|
# :attr:
|
180
180
|
# Called when the data in this field changes.
|
@@ -189,13 +189,13 @@ class Field
|
|
189
189
|
def dataset
|
190
190
|
dataset_roller
|
191
191
|
end
|
192
|
-
|
192
|
+
|
193
193
|
# TODO Still getting the Builder/Built conflict
|
194
194
|
def dataset_roller
|
195
195
|
# related class if it's an association, entity_class otherwise
|
196
196
|
@dataset_roller ||= DatasetRoller.new( ( association? ? related_class : entity_class ).dataset )
|
197
197
|
end
|
198
|
-
|
198
|
+
|
199
199
|
# The list of properties for ActiveRecord options.
|
200
200
|
# There are actually from ActiveRecord::Base.VALID_FIND_OPTIONS, but it's protected.
|
201
201
|
# Each element becomes a property.
|
@@ -203,7 +203,7 @@ class Field
|
|
203
203
|
# TODO warn or raise if these are used together with a dataset call
|
204
204
|
AR_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from, :lock ]
|
205
205
|
AR_FIND_OPTIONS.each{|x| property x}
|
206
|
-
|
206
|
+
|
207
207
|
# Return a list of find options and their values, but only
|
208
208
|
# if the values are not nil
|
209
209
|
def find_options
|
@@ -215,25 +215,25 @@ class Field
|
|
215
215
|
ha
|
216
216
|
end
|
217
217
|
end
|
218
|
-
|
218
|
+
|
219
219
|
# The model object (eg TableModel) this field is part of.
|
220
220
|
# Set to TableModel by ModelBuilder#build
|
221
221
|
attr_accessor :model
|
222
|
-
|
222
|
+
|
223
223
|
# The UI delegate class for the field. The delegate class knows how to create a UI
|
224
224
|
# for this field using whatever GUI toolkit is selected
|
225
225
|
attr_accessor :delegate
|
226
|
-
|
226
|
+
|
227
227
|
# The attribute on the entity that forms the basis for this field.
|
228
228
|
# Accessing the returned attribute (using send, or the [] method on an entity)
|
229
229
|
# will give a simple value, or another entity in the case of relational fields.
|
230
230
|
# In other words, this is *not* the same as the name of the field in the DB, which
|
231
231
|
# would normally have an _id suffix for relationships.
|
232
232
|
attr_accessor :attribute
|
233
|
-
|
233
|
+
|
234
234
|
# The Object Relational Model this field uses to get data from.
|
235
235
|
attr_reader :entity_class
|
236
|
-
|
236
|
+
|
237
237
|
# Create a new Field object that displays the contents of a database field in
|
238
238
|
# the UI using the given parameters.
|
239
239
|
# - attribute is the symbol for the attribute on the entity_class.
|
@@ -244,11 +244,11 @@ class Field
|
|
244
244
|
unless attribute.is_a?( Symbol )
|
245
245
|
raise "attribute #{attribute.inspect} must be a symbol"
|
246
246
|
end
|
247
|
-
|
247
|
+
|
248
248
|
unless entity_class.ancestors.include?( Clevic.base_entity_class )
|
249
249
|
raise "#{entity_class} is not a Clevic.base_entity_class: #{Clevic.base_entity_class}"
|
250
250
|
end
|
251
|
-
|
251
|
+
|
252
252
|
# TODO this comes down to method_defined, really
|
253
253
|
unless entity_class.has_attribute?( attribute ) or entity_class.method_defined?( attribute )
|
254
254
|
raise <<EOF
|
@@ -256,20 +256,20 @@ class Field
|
|
256
256
|
#{entity_class.attribute_names.inspect}
|
257
257
|
EOF
|
258
258
|
end
|
259
|
-
|
259
|
+
|
260
260
|
# instance variables
|
261
261
|
@attribute = attribute
|
262
262
|
# default to attribute, can be overwritten later
|
263
263
|
@id = attribute
|
264
264
|
@entity_class = entity_class
|
265
265
|
@visible = true
|
266
|
-
|
266
|
+
|
267
267
|
# initialise
|
268
268
|
@value_cache = {}
|
269
|
-
|
269
|
+
|
270
270
|
# handle options
|
271
271
|
gather( options, &block )
|
272
|
-
|
272
|
+
|
273
273
|
# set various sensible defaults. They're not lazy accessors because
|
274
274
|
# they might stay nil, and we don't want to keep evaluating them.
|
275
275
|
default_label!
|
@@ -278,7 +278,7 @@ EOF
|
|
278
278
|
default_alignment!
|
279
279
|
default_display! if association?
|
280
280
|
end
|
281
|
-
|
281
|
+
|
282
282
|
# Return the attribute value for the given Object Relational Model instance, or nil
|
283
283
|
# if entity is nil. Will call transform_attribute.
|
284
284
|
def value_for( entity )
|
@@ -290,7 +290,7 @@ EOF
|
|
290
290
|
puts e.backtrace
|
291
291
|
end
|
292
292
|
end
|
293
|
-
|
293
|
+
|
294
294
|
# Apply the value of the display property to the given
|
295
295
|
# attribute value. Otherwise just return the
|
296
296
|
# attribute_value itself.
|
@@ -299,47 +299,47 @@ EOF
|
|
299
299
|
case display
|
300
300
|
when Proc
|
301
301
|
display.call( attribute_value )
|
302
|
-
|
302
|
+
|
303
303
|
when String
|
304
304
|
attribute_value.evaluate_path( display.split( '.' ) )
|
305
|
-
|
305
|
+
|
306
306
|
when Symbol
|
307
307
|
attribute_value.send( display )
|
308
|
-
|
308
|
+
|
309
309
|
else
|
310
310
|
attribute_value
|
311
311
|
end
|
312
312
|
end
|
313
|
-
|
313
|
+
|
314
314
|
# return true if this is a field for a related table, false otherwise.
|
315
315
|
def association?
|
316
316
|
meta.andand.association?
|
317
317
|
end
|
318
|
-
|
318
|
+
|
319
319
|
# Clevic::ModelColumn object
|
320
320
|
def meta
|
321
321
|
entity_class.meta[attribute] || ModelColumn.new( attribute, {} )
|
322
322
|
end
|
323
|
-
|
323
|
+
|
324
324
|
# return true if this field can be used in a filter
|
325
325
|
# virtual fields (ie those that don't exist in this field's
|
326
326
|
# table) can't be used to filter on.
|
327
327
|
def filterable?
|
328
328
|
!meta.nil?
|
329
329
|
end
|
330
|
-
|
330
|
+
|
331
331
|
# return the result of the attribute + the path
|
332
332
|
def column
|
333
333
|
[attribute.to_s, path].compact.join('.')
|
334
334
|
end
|
335
|
-
|
335
|
+
|
336
336
|
# Return the class object of a related class if this is a relational
|
337
337
|
# field, otherwise nil.
|
338
338
|
def related_class
|
339
339
|
return nil unless association? && entity_class.meta.has_key?( attribute )
|
340
340
|
@related_class ||= eval( entity_class.meta[attribute].class_name || attribute.to_s.classify )
|
341
341
|
end
|
342
|
-
|
342
|
+
|
343
343
|
# return an array of the various attribute parts
|
344
344
|
# TODO not used much. Deprecate and remove.
|
345
345
|
def attribute_path
|
@@ -347,23 +347,23 @@ EOF
|
|
347
347
|
pieces.concat( display.to_s.split( '.' ) ) unless display.is_a? Proc
|
348
348
|
pieces.map{|x| x.to_sym}
|
349
349
|
end
|
350
|
-
|
350
|
+
|
351
351
|
# Return true if the field is read-only. Defaults to false.
|
352
352
|
def read_only?
|
353
353
|
@read_only || false
|
354
354
|
end
|
355
|
-
|
355
|
+
|
356
356
|
# Called by Clevic::FieldValuer (and others) to format the display value.
|
357
357
|
def do_format( value )
|
358
358
|
do_generic_format( format, value )
|
359
359
|
end
|
360
|
-
|
360
|
+
|
361
361
|
# Called by Clevic::FieldValuer to format the field to a string value
|
362
362
|
# that can be used for editing.
|
363
363
|
def do_edit_format( value )
|
364
364
|
do_generic_format( edit_format, value )
|
365
365
|
end
|
366
|
-
|
366
|
+
|
367
367
|
# Set or return a sample for the field which can be used to size the UI field widget.
|
368
368
|
# If this is called as an accessor, and there is no value yet, a Clevic::Sampler
|
369
369
|
# instance is created to compute a sample.
|
@@ -389,7 +389,7 @@ EOF
|
|
389
389
|
@sample
|
390
390
|
end
|
391
391
|
end
|
392
|
-
|
392
|
+
|
393
393
|
# Called by Clevic::TableModel to get the tooltip value
|
394
394
|
def tooltip_for( entity )
|
395
395
|
cache_value_for( :tooltip, entity )
|
@@ -399,22 +399,22 @@ EOF
|
|
399
399
|
def decoration_for( entity )
|
400
400
|
nil
|
401
401
|
end
|
402
|
-
|
402
|
+
|
403
403
|
# Called by Clevic::TableModel to get the foreground color value
|
404
404
|
def foreground_for( entity )
|
405
405
|
cache_value_for( :foreground, entity ) {|x| string_or_color(x)}
|
406
406
|
end
|
407
|
-
|
407
|
+
|
408
408
|
# Called by Clevic::TableModel to get the background color value
|
409
409
|
def background_for( entity )
|
410
410
|
cache_value_for( :background, entity ) {|x| string_or_color(x)}
|
411
411
|
end
|
412
|
-
|
412
|
+
|
413
413
|
# called when a new entity object is created to set default values
|
414
414
|
# specified by the default property.
|
415
415
|
def set_default_for( entity )
|
416
416
|
begin
|
417
|
-
entity[attribute] =
|
417
|
+
entity[attribute] =
|
418
418
|
case default
|
419
419
|
when String
|
420
420
|
default
|
@@ -426,31 +426,31 @@ EOF
|
|
426
426
|
puts e.backtrace
|
427
427
|
end
|
428
428
|
end
|
429
|
-
|
429
|
+
|
430
430
|
# fetch the permitted set of values for a restricted field.
|
431
431
|
def set_for( entity )
|
432
432
|
case set
|
433
433
|
when Proc
|
434
434
|
# the Proc should return an enumerable
|
435
435
|
set.call( entity )
|
436
|
-
|
436
|
+
|
437
437
|
when Symbol
|
438
438
|
entity.send( set )
|
439
|
-
|
439
|
+
|
440
440
|
else
|
441
441
|
# assume its an Enumerable
|
442
442
|
set
|
443
443
|
end
|
444
444
|
end
|
445
|
-
|
445
|
+
|
446
446
|
def to_s
|
447
447
|
"#{entity_class}.#{id}"
|
448
448
|
end
|
449
|
-
|
449
|
+
|
450
450
|
def inspect
|
451
451
|
"#<Clevic::Field #{entity_class} id=#{id} attribute=#{attribute}>"
|
452
452
|
end
|
453
|
-
|
453
|
+
|
454
454
|
protected
|
455
455
|
|
456
456
|
# call the conversion_block with the value, or just return the
|
@@ -462,7 +462,7 @@ protected
|
|
462
462
|
conversion_block.call( value )
|
463
463
|
end
|
464
464
|
end
|
465
|
-
|
465
|
+
|
466
466
|
# symbol is the property name to fetch a value for.
|
467
467
|
# It can be a Proc, a symbol, or a value responding to to_s.
|
468
468
|
# In all cases, conversion block will be called
|
@@ -478,10 +478,10 @@ protected
|
|
478
478
|
else; @value_cache[symbol] ||=convert_or_identity( value, &conversion_block )
|
479
479
|
end
|
480
480
|
end
|
481
|
-
|
481
|
+
|
482
482
|
# the label if it's not defined. Based on the attribute.
|
483
483
|
def default_label!
|
484
|
-
@label ||= attribute.to_s.humanize
|
484
|
+
@label ||= ( id || attribute ).to_s.humanize
|
485
485
|
end
|
486
486
|
|
487
487
|
# sensible display format defaults if they're not defined.
|
@@ -494,7 +494,7 @@ protected
|
|
494
494
|
when :decimal, :float; "%.2f"
|
495
495
|
end
|
496
496
|
end
|
497
|
-
|
497
|
+
|
498
498
|
# sensible edit format defaults if they're not defined.
|
499
499
|
def default_edit_format!
|
500
500
|
@edit_format ||=
|