clevic 0.13.0.b9 → 0.13.0.b10
Sign up to get free protection for your applications and to get access to all the features.
- 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 ||=
|