Added custom field type support to Form
[tcl-tlc.git] / scripts / browsegeneric.itcl
blobfaa6e5783e7995af3cce5032ee61e8669728de20
1 # vim: ft=tcl foldmarker=<<<,>>>
3 # Signals:
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 {
11 inherit tlc::Handlers
13 constructor {} {}
14 destructor {}
16 public {
17 variable datasource {} showds
18 # widget layout
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 {}
39 method refresh {}
40 method clear {}
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
49 # (if any)
50 # remove_item: client widget should remove current selection
51 # (if any)
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 {}
63 method get_actions {}
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 {}
71 protected {
72 variable item_selected
73 variable actions ""
74 variable id_col ;# should be a pair of {index} {name}
75 variable olddatasource
77 method refresh_pending {}
78 method do_refresh {}
79 method need_relayout {}
80 method do_relayout {}
81 method relayout {}
84 private {
85 variable refresh_afterid ""
86 variable relayout_afterid ""
88 method showds {}
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
118 # datasource
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
165 need_refresh
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 ...
181 return $actions
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
200 # of the filter form
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 ""
213 refresh
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 ""
231 relayout
235 body tlc::Browsegeneric::relayout {} { #<<<1