1 # vim: ft=tcl foldmarker=<<<,>>>
4 # onselect(row) - when a row is single clicked, passes row list
5 # onselect_id(id) - when a row is single clicked, passes id from row
6 # doubleclick(row) - as onselect, but double click
7 # doubleclick_id(row) - as onselect_id, but double click
8 # datachanged() - notification that the list has been refreshed
10 class tlc
::Browsegeneric {
17 variable datasource
{} showds
19 variable filterpos
{9,10 -anchor nw
}
20 variable listpos
{10,10 -fill both
}
21 variable criteriapos
{10,11 -fill y
}
22 variable criteria_label
""
23 variable showfilter
1 ;# TODO: perhaps implement
24 # metaphone searching on the filter?
25 variable filter_label
""
26 variable show_criteria
0
27 variable pop_follows_actions
1
28 variable add_item_header
"Add new thingymabob"
29 variable update_item_header
"Edit this thingymabob"
30 variable add_item_about
"This is where you can add a new thingymabob. Make sure it's nice!"
31 variable update_item_about
"This is where you can edit that pesky thingymabob that you dislike so much."
33 variable filter_mode
1
34 variable filter_insensitive
1
35 variable filter_allow_sense_change
0
36 variable filter_allow_mode_change
0
38 method selected_ref
{}
42 # for the following commands, the inheriting widget is expected to
43 # * take care of the interfacing with the datasource, and should take
44 # * optional parameters for programmatic manipulation from the host app
45 # * the behaviour when there are no parameters is as follows:
46 # add_item: client widget should implement a form that
47 # works with the relevant fields
48 # update_item: client widget should update current selection
50 # remove_item: client widget should remove current selection
52 # The client widget does not have to actually
53 # implement the functionality (in fact, it may not be possible for
54 # the client to implement the functionality, since the datasource may
55 # not be able to implement it, or may not have been configured to do
56 # so. This, of course, the parent app *should know*
57 method add_item
{{row
{}} {col_list
""}}
58 method update_item
{{oldrow
{}} {newrow
{}} {old_col_list
""} {new_col_list
""}}
59 method remove_item
{{row
{}}}
60 method select_items
{itemlist
}
61 method filter
{{searchstring
""} {matchcode
""}}
62 method get_selected_items
{}
64 method action_add
{args
}
65 method action_attach_signal
{label signal
{sense normal
}}
66 method gen_popup
{{pop_commands
""}}
67 method filter_add
{label varinfo
{matchcode
{}}}
68 method need_refresh
{}
72 variable item_selected
74 variable id_col
;# should be a pair of {index} {name}
75 variable olddatasource
77 method refresh_pending
{}
79 method need_relayout
{}
85 variable refresh_afterid
""
86 variable relayout_afterid
""
93 body tlc
::Browsegeneric::constructor {} { #<<<1
94 tlc
::Signal #auto item_selected -name "$this item_selected"
97 body tlc
::Browsegeneric::destructor {} { #<<<1
98 if {$datasource != "" && [itcl
::is object
$datasource]} {
99 $datasource deregister_handler destroyed
\
100 [code
$this configure
-datasource ""]
101 $datasource deregister_handler onchange
\
102 [code
$this need_refresh
]
104 after cancel
$refresh_afterid; set refresh_afterid
""
105 after cancel
$relayout_afterid; set relayout_afterid
""
109 body tlc
::Browsegeneric::selected_ref {} { #<<<1
110 # expected: reference to a signal that marks whether or not something is
111 # selected in the viewing widget
112 return $item_selected
115 body tlc
::Browsegeneric::refresh {} { #<<<1
116 # expected: this will reload the viewing widget with the latest
117 # version of the criteria in place requires a requery on the
121 body tlc
::Browsegeneric::clear {} { #<<<1
122 # expected: this will clear the viewing portal of the browse widget
125 body tlc
::Browsegeneric::select_items {itemlist
} { #<<<1
126 # expected: the inheriting widget will (without any barfing) select all
127 # rows that correspond to the itemlist, which will be a list
128 # of id_col range values. So something like: {1 4} 6 8 {13
129 # 15} will select 1,2,3,4,6,8,13,15
132 body tlc
::Browsegeneric::add_item {{row
{}} {col_list
""}} { #<<<1
135 body tlc
::Browsegeneric::update_item {{oldrow
{}} {newrow
{}} {old_col_list
""} {new_col_list
""}} { #<<<1
138 body tlc
::Browsegeneric::remove_item {{row
{}}} { #<<<1
141 body tlc
::Browsegeneric::filter {{searchstring
""} {matchcode
""}} { #<<<1
142 # inputs: string to search with, code to execute to determine a match.
143 # The code could just be a straight string of code or a function
144 # call -- i don't care which, but the code should return 1 for a
145 # match, and zero otherwise. the token %value% can be used to
146 # place the search string in the code, and the code can assume
147 # that an array row is loaded with the values of the current row
148 # to be tested, indexed by the column names
151 body tlc
::Browsegeneric::showds {} { #<<<1
152 if {[info exists olddatasource
] && [itcl
::is object
$olddatasource]} {
153 $olddatasource deregister_handler destroyed
\
154 [code
$this configure
-datasource ""]
155 $olddatasource deregister_handler onchange
\
156 [code
$this need_refresh
]
158 if {$datasource != "" && [itcl
::is object
$datasource]} {
159 $datasource register_handler destroyed
\
160 [code
$this configure
-datasource ""]
161 $datasource register_handler onchange
\
162 [code
$this need_refresh
]
164 set olddatasource
$datasource
168 body tlc
::Browsegeneric::get_selected_items {} { #<<<1
169 # the inheriting widget must return the selected item(s), as a list of lists
172 body tlc
::Browsegeneric::action_add {args
} { #<<<1
173 # it's up to the inheriting widget to implement action addition, signals and the populatio of the $actions var
176 body tlc
::Browsegeneric::action_attach_signal {label signal
{sense normal
}} { #<<<1
179 body tlc
::Browsegeneric::get_actions {} { #<<<1
180 # this var should be a simple list of format: action_name action_proc ...
184 body tlc
::Browsegeneric::gen_popup {{pop_commands
""}} { #<<<1
185 # this funciton is called if the host wants a popup menu on the
186 # relevant part of the browse widget
189 body tlc
::Browsegeneric::filter_add {label varinfo
{matchcode
{}}} { #<<<1
190 # adds a filter into the browser's interface
191 # inputs: formdesc: the description necessary for the filter to
192 # be added to a standard form widget
193 # matchcode: tcl code to be executed such that the code returns
194 # true if the criteria in it are met, and the row is
195 # displayed. Available to this code are:
196 # row: a local array, which is the current row being
197 # considered, and has the same layout as the row
198 # (ie the same fileds/indeces)
199 # filter: a local array, which has available, all elements
204 body tlc
::Browsegeneric::need_refresh {} { #<<<1
205 if {$refresh_afterid != ""} return
207 set refresh_afterid
[after idle
[code
$this do_refresh
]]
211 body tlc
::Browsegeneric::do_refresh {} { #<<<1
212 after cancel
$refresh_afterid; set refresh_afterid
""
217 body tlc
::Browsegeneric::refresh_pending {} { #<<<1
218 return [expr {$refresh_afterid != ""}]
222 body tlc
::Browsegeneric::need_relayout {} { #<<<1
223 if {$relayout_afterid != ""} return
225 set relayout_afterid
[after idle
[code
$this do_relayout
]]
229 body tlc
::Browsegeneric::do_relayout {} { #<<<1
230 after cancel
$relayout_afterid; set relayout_afterid
""
235 body tlc
::Browsegeneric::relayout {} { #<<<1