######################################################################## #### #### Title: update_cb.magik #### Author: Mark Cederholm #### Last Revised: 28-Apr-2004 Updated for 3.3 #### list_view behavior fixed #### #### Notes: #### #### Perform bulk update on clipboard contents. #### ######################################################################## #********************************************************************** # Exemplar #********************************************************************** remex(:clipboard_update_utility) $ def_slotted_exemplar(:clipboard_update_utility, { {:grs, _unset}, {:items, _unset}, {:clipboard, _unset}, {:table_list, _unset}, {:rwo_list, _unset}, {:field_list, _unset}, {:field_type, _unset} }, :model) $ #********************************************************************** # Method to launch clipboard update utility #********************************************************************** _method graphics_system.launch_clipboard_update_utility() menu_key << :clipboard_update_utility _if (menu << .sub_menus[menu_key]) _is _unset _then menu << .sub_menus[menu_key] << clipboard_update_utility.new(_self) _endif menu.activate() >> menu _endmethod $ #********************************************************************** # Public methods #********************************************************************** _method clipboard_update_utility.new(a_grs) >> _clone.init(a_grs) _endmethod _method clipboard_update_utility.activate_in(a_frame) # set up dialog _self.title << "Update clipboard contents" p << panel.new(a_frame) .items << hash_table.new() .items[:status] << label_item.new(p, "OK") p.start_row() .items[:table] << list_view.new(_self, p, :get_tables|()|, :select_table|()|, :external_name, 3, 30, :one) p.start_row() .items[:field] << list_view.new(_self, p, :get_fields|()|, :select_field|()|, :external_name, 6, 30, :one) p.start_row() .items[:format] << label_item.new(p, "(Format)") p.start_row() label_item.new(p, "New Value:") i << .items[:pick] << button_item.new(p,"?",_self,:pick_enum|()|) i.visibility << _false i << .items[:value] << text_item.new(p) i.display_length << 20 p.start_row() .items[:do_all] << toggle_item.new(p,"Update all objects having field", :value, _false) # p.start_row() # .items[:update_geom] << toggle_item.new(p,"Force geometry update", :value, _false) p.start_row() button_item.new(p,"Paste",_self,:refresh_cb|()|) button_item.new(p,"Update",_self,:do_it|()|) button_item.new(p,"Quit",_self,:quit|()|) # _self.refresh_cb() _endmethod _method clipboard_update_utility.get_tables() # populate table list _if (cb << .clipboard) _is _unset _then .table_list << {} _else cb_tables << cb.sources().as_simple_vector() tlist << rope.new() _for t _over cb_tables.fast_elements() _loop # If table has no relevant attributes, skip it _if _self.get_fields(t).size = 0 _then _continue _endif tlist.add(t) _endloop sort_proc << _proc(t1, t2) >> t1.external_name _cf t2.external_name _endproc sorted_tables << sorted_collection.new(tlist.size, sort_proc) sorted_tables.add_all(tlist) .table_list << sorted_tables.as_simple_vector() _endif >> .table_list _endmethod _method clipboard_update_utility.get_fields(_optional a_table) # get supported field list _if a_table _isnt _unset _then t << a_table _else i << .items[:table].current_index _if i _is _unset _then .field_list << {} _return .field_list _endif t << .table_list[i] _endif flist << rope.new() _for f _over t.visible_fields.fast_elements() _loop _if f.is_physical? _then flist.add(f) _elif f.is_join? _then _if f.join_type _is :text _then flist.add(f) _continue _endif _endif _endloop _if a_table _isnt _unset _then _return flist _else .field_list << flist.as_simple_vector() _return .field_list _endif _endmethod _method clipboard_update_utility.refresh_cb() # clear items .table_list << {} .items[:table].clear_selection() .items[:table].update_list(.table_list,_unset) .field_list << {} .items[:field].clear_selection() .items[:field].update_list(.field_list,_unset) .items[:format].label << "(Format)" .items[:pick].visibility << _false .items[:value].value << "" .rwo_list << hash_table.new() # check for features in clipboard .items[:status].label << "Working..." cb << .clipboard << gis_program_manager.scrapbook().clipboard _if cb _is _unset _orif cb.record_read_stream().get() _is _unset _then .items[:status].label << "No features in clipboard." _return _endif # restrict record read stream to relevant tables _local tlist << _self.get_tables() _if tlist.size = 0 _then .items[:status].label << "No updateable tables found." _return _endif # copy rwos into .rwo_list # max << !maximum_collection_size! rset << cb.record_read_stream() recnum << 0 _loop r << rset.get() _if r _is _unset _then _leave _endif _if ~ tlist.includes?(r.source_collection) _then _continue _endif recnum +<< 1 _if recnum _mod 100 = 0 _then msg << "Retrieving record " + recnum.write_string + "..." .items[:status].label << msg _endif k << r.class_name _if (rlist << .rwo_list[k]) _is _unset _then rlist << .rwo_list[k] << rope.new() _endif # _if rlist.size = max # _then # msg << "Greater than " + max.write_string + " objects." # _self.show_alert(msg) # .rwo_list << hash_table.new() # .items[:status].label << "ERROR" # _return # _endif rlist.add(r.detached()) _endloop # update menu and finish .items[:table].update_list(tlist,_unset) .items[:table].current_index << 1 msg << recnum.write_string + " records retrieved." .items[:status].label << msg _endmethod _method clipboard_update_utility.select_table(i) _if i _is _unset _then _return _endif t << .table_list[i] # update status item n << .clipboard.record_counts_by_table[t] .items[:status].label << n.write_string + " records" .items[:field].update_list(_self.get_fields(),_unset) .items[:field].current_index << 1 _endmethod _method clipboard_update_utility.select_field(i) _if i _is _unset _then .items[:pick].visibility << _false _return _endif # activate pick item if enumerated field f << .field_list[i] t << f.type _if t _is _unset _orif t.enumerator _is _unset _then .items[:pick].visibility << _false _else .items[:pick].visibility << _true _endif # clear value item contents .items[:value].value << "" # set format label label << "(Format)" .field_type << _unset _if f.is_physical? _then _if t.enumerator _isnt _unset _then label << "(Enumeration)" .field_type << :enum _elif t.is_string? _then label << "(Alphanumeric)" .field_type << :char _elif t.phys_type _is :ds_float _then label << "(Floating Point)" .field_type << :float _elif t.phys_type _is :ds_int _then label << "(Integer)" .field_type << :int _elif t.phys_type _is :ds_date _then label << "(Date MM/DD/YYYY)" .field_type << :date _elif t.phys_type _is :ds_bool _then label << "(TRUE or FALSE)" .field_type << :bool _endif _elif f.is_join? _then _if f.join_type _is :text _then label << "(Alphanumeric)" .field_type << :text _endif _endif .items[:format].label << label _endmethod _method clipboard_update_utility.pick_enum() # Put up a choice lister of enumeration values to pick i << .items[:field].current_index f << .field_list[i] enum << f.type.enumerator cl << choice_lister.new() vals << rope.new_from(enum.sorted_values) cl.activate_on(vals, _self, :select_enum|()|) cl.title << "Select " + f.external_name _endmethod _method clipboard_update_utility.select_enum(val) # Set value item to returned enum value .items[:value].value << val.write_string _endmethod _method clipboard_update_utility.do_it() .items[:status].label << "Working..." # check for required parameters i << .items[:table].current_index _if i _is _unset _then _self.show_alert("ERROR: No table selected") .items[:status].label << "ERROR" _return _endif t << .table_list[i] i << .items[:field].current_index _if i _is _unset _then _self.show_alert("ERROR: No field selected") .items[:status].label << "ERROR" _return _endif f << .field_list[i] fname << f.name # if value is unset, check if user really wants to clear fields val << .items[:value].value.trim_spaces() _if val = "" _then msg << "No value has been entered. Do you wish to erase values?" erase? << _self.show_question("Yes", "No", msg) _if ~ erase? _then .items[:status].label << "Cancelled" _return _endif val << _unset _endif # check that value is valid for field _if val _is _unset _then the_value << val _else valid? << _true _if .field_type _is :int _then the_value << val.as_integer() valid? << (the_value _isnt _unset) _elif .field_type _is :float _then the_value << val.as_number() valid? << (the_value _isnt _unset) _elif .field_type _is :bool _then val << val.uppercase _if val = "TRUE" _or val = "T" _then the_value << _true _elif val = "FALSE" _or val = "F" _then the_value << _false _else valid? << _false _endif _elif .field_type _is :date _then _try _with the_condition the_value << date.new_from_string(val) _when error valid? << _false _endtry _elif .field_type _is :enum _then valid? << _false enums << rope.new_from(f.type.enumerator.sorted_values) _for e _over enums.fast_elements() _loop the_value << e _if the_value.write_string = val _then valid? << _true _leave _endif _endloop _else the_value << val _endif _if ~ valid? _then _self.show_alert("ERROR: Invalid value entered") .items[:status].label << "ERROR" _return _endif _endif # check for writable alternative v << t.source_view _if ~ v.writable? _then _self.show_alert("ERROR: Alternative not writable") .items[:status].label << "ERROR" _return _endif _dynamic !current_grs! << .grs # get record set and loop through it _if (do_all? << .items[:do_all].value) _then rset << .rwo_list.as_simple_vector() _else e << t.an_element() rset << {.rwo_list[e.class_name]} _endif recnum << 0 _for rlist _over rset.fast_elements() _loop _if do_all? _then e << rlist.an_element() _if e.field(fname) _is _unset _then _continue _endif _endif _for r _over rlist.fast_elements() _loop recnum +<< 1 _if recnum _mod 100 = 0 _then msg << "Updating record " + recnum.write_string + "..." .items[:status].label << msg _endif _if ~ (result? << _self.update(r, fname, the_value)) _then _return _endif _endloop _endloop msg << recnum.write_string + " records updated." .items[:status].label << msg _endmethod #********************************************************************** # Private methods #********************************************************************** _private _method clipboard_update_utility.init(a_grs) # initialize .grs and .view .grs << a_grs >> _super.init() _endmethod _private _method clipboard_update_utility.update(r, fname, the_value) t << r.source_collection v << t.source_view _dynamic !current_dsview! << v _dynamic !current_world! << v.world _try _with the_condition ok? << v.start_lwt() _protect r.perform(fname.with_chevron, the_value) t.update(r) ok? << _true _protection v.end_lwt(ok?) _endprotect _when error _self.show_alert("ERROR: Could not set value") .items[:status].label << "ERROR" _return _false _endtry >> true _endmethod