::qw::itcl::class ::QW::GUI::WIDGET_CANVAS_TREE::NODE { public method odb_database {} {return [$tree odb_database];} public method odb_path {} {return [$tree odb_path];} public method cpp_is_destroyed {} {::return 0;} public method cpp_is_destroying {} {::return 0;} public method puts_pgq {Arg} { ::if {!$::qw::verbose(gui_tree)} {::return $Arg;} ::if {$tree eq ""} { ::uplevel 1 ::puts $Arg; } else { ::puts -nonewline "[[$tree odb_database] cpp_directory]-[$tree odb_path],"; ::uplevel 1 ::puts $Arg; } } public variable id {""} { } public variable tree "" { $tree nodesAttach $this; $tree structure_data [::sargs::set [$tree structure_data] \ $id {._qw_isExpandable 1 ._qw_isExpanded 0 ._qw_isSelected 0 ._qw_parent {} ._qw_observer_database {} ._qw_observer_database_index {}}]; ::set _canvas [[$tree ".client"] tkPath]; } public variable parent "" { ::if {$parent ne ""} { $parent kids_attach $this; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_parent [$parent id]]; } } public method id {} {::return $id;} protected variable _isLeaf ""; protected variable _kids ""; protected variable _isExpandable 1; protected variable _isExpanded 0; protected variable _isSelected 0; protected variable _canvas ""; protected variable _text ""; public variable prev ""; protected variable _odb_observers; protected variable _is_collapsing 0; method constructor1 {args} { ::eval configure $args odb_observer_create database; odb_observer_create database_index; odb_observer_create database_range [::qw::odb::factory range]; ::set Object [::sargs::get [$tree structure_data] $id._qw_observer_database]; ::if {$Object eq ""} { ::return $this; } odb_observer_set database $Object; ::if {[::sargs::get [$tree structure_data] $id._qw_observer_database_index] eq ""} { ::return $this; } odb_observer_set database_index [::sargs::get [$tree structure_data] $id._qw_observer_database_index]; [odb_observer_get database_range] cpp_configure -index [::sargs::get [$tree structure_data] $id._qw_observer_database_index]; ::return $this; } destructor { kids_destroy; undraw; ::if {[::info exists _odb_observers(database_range)]} { ::if {[odb_observer_get database_range] ne ""} { [odb_observer_get database_range] cpp_destroy; } } ::if {[::info exists _odb_observers(database_cell_range)]} { ::if {[odb_observer_get database_cell_range] ne ""} { [odb_observer_get database_cell_range] cpp_destroy; } } odb_observers_destroy; ::if {$parent ne ""} {$parent kids_detach $this;} $tree nodesDetach $this; ::if {![$tree is_destroying]} { $tree structure_data [::sargs::unset [$tree structure_data] $id]; } ::if {[is_active]} { ::if {![$tree is_destroying]} {::if {$parent ne ""} {$parent activate;}} } } method odb_observer_create {Tag {Handle ""} {Commands ""}} @qw_odb_object_odb_observer_create; method odb_observer_destroy {Tag} @qw_odb_object_odb_observer_destroy; method odb_observer_set {Tag Handle} @qw_odb_object_odb_observer_set; method odb_observer_get {Tag} @qw_odb_object_odb_observer_get; public method odb_observers_destroy {} { ::foreach Tag [::array names _odb_observers] {odb_observer_destroy $Tag;} } public method observer_database_handle {} { ::return [odb_observer_get database]; } public method observer_database {{Src get}} { ::if {$Src eq "get"} { ::return [::sargs::get [$tree structure_data] $id._qw_observer_database]; } ::if {$Src eq [::sargs::get [$tree structure_data] $id._qw_observer_database]} { ::return $this; } odb_observer_set database $Src; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_observer_database $Src]; ::return $this; } public method signal_receive {s_args} { ::switch -- [::sargs::get $s_args .tag] { "database" {::return [signal_receive_database $s_args];} "database_index" {::return [signal_receive_database_index $s_args];} "database_range" { ::return [signal_receive_database_index $s_args]; } "database_cell_range" {::return [signal_receive_database $s_args];} } ::return ""; } public method signal_receive_database {s_args} { ::switch -- [::sargs::get $s_args .command] { "odb_change_before" { ::return ""; } "odb_change_after" { ::if {![isAncestorCollapsed]} { ::switch [::sargs::get $s_args ".field_path"] { ".name" - ".description" { } default { ::return ""; } } undraw; #// The "smearing" paint job is back! Try this. draw; } ::return ""; } "odb_destroy_after" { ::if {$parent eq ""} {::qw::itcl_delete_object $this;} ;#// commit suicide ::return ""; } } ::return ""; } public method observer_database_index_handle {} {::return [odb_observer_get database_index];} public method observer_database_range_handle {} {::return [odb_observer_get database_range];} public method observer_database_index {{Src get}} { ::if {$Src eq "get"} { ::return [::sargs::get [$tree structure_data] $id._qw_observer_database_index]; } ::if {$Src==[::sargs::get [$tree structure_data] $id._qw_observer_database_index]} { ::return $this; } odb_observer_set database_index $Src; [odb_observer_get database_range] cpp_configure -index $Src; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_observer_database_index $Src]; ::return $this; } public method signal_receive_database_index {s_args} { ::switch -- [::sargs::get $s_args .command] { "odb_change_after" { ::if {![isAncestorCollapsed]} { ::set WasExpanded 0; ::if {[isExpanded]} { ::set WasExpanded 1; collapse; } } kids_destroy; ::if {[isAncestorCollapsed]} { ::if {[$tree items $id]==0} {isExpanded 0;} ::return ""; } undraw; draw; ::if {$WasExpanded} {expand;} ::return ""; } } ::return ""; } public method signal_receive_database_range {s_args} { ::switch -- [::sargs::get $s_args .command] { "odb_change_after" { ::if {![isAncestorCollapsed]} { undraw; #// The "smearing" paint job is back! Try this. draw; } ::return ""; } } ::return ""; } protected method kids_destroy {} { ::if {$_kids ne ""} { ::eval ::qw::itcl_delete_object $_kids; } ::qw::assert {![::llength $_kids]} ::return $this; } protected method kids_attach {Kid} { ::if {[::llength $_kids]} { $Kid configure -prev [::lindex $_kids end]; } ::lappend _kids $Kid; } protected method kids_detach {Kid} { ::set Index [::lsearch -exact $_kids $Kid]; ::qw::assert {$Index>=0} ::set NextKid [$Kid next]; ::if {$NextKid ne ""} { $NextKid configure -prev [$Kid prev]; } ::set _kids [::lreplace $_kids $Index $Index]; ::return $this; } public method parent {} { ::return $parent; } public method kids {} { ::if {![::llength $_kids]} { ::set Kids [$tree kids $id]; ::foreach Kid [::sargs::names .structure $Kids .glob ".*"] { ::set Node [::QW::GUI::WIDGET_CANVAS_TREE::NODE ::QW::GUI::WIDGET_CANVAS_TREE::NODE::#auto]; $Node constructor1 -id [::sargs::get $Kids "$Kid.id"] -tree $tree -parent $this; $Node observer_database [::sargs::get $Kids "$Kid.odb_address"]; $Node observer_database_index [::sargs::get $Kids "$Kid.odb_address_index"]; } } ::return $_kids; } public method isLeaf {} { ::if {[$tree items $id]>500} {::return 1;} ::return [::expr {[$tree items $id]==0}]; } public method isBranch {} {return [::expr {![isLeaf]}];} public method isExpandable {{Src get}} { ::if {$Src eq "get"} {::return $_isExpandable;} ::if {$Src==$_isExpandable} {::return $this;} ::if {$_isExpandable} { ::if {[isExpanded]} {collapse_all;} kids_destroy; } ::set _isExpandable $Src; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_isExpandable $Src]; ::return $this; } public method isExpanded {{Src get}} { ::if {$Src eq "get"} {::return $_isExpanded;} ::if {$Src==$_isExpanded} {::return $this;} ::set _isExpanded $Src; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_isExpanded $Src]; ::return $this; } public method select {} { ::if {$_isSelected} {::return [deselect];} $tree clearSelections; ::set _isSelected 1; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_isSelected 1]; $_canvas itemconfigure $this-hilite -fill green $tree makeSelected $this; ::return $this; } public method deselect {} { $_canvas itemconfigure $this-hilite -fill "" $tree makeDeselected $this; ::set _isSelected 0; $tree structure_data [::sargs::set [$tree structure_data] $id._qw_isSelected 0]; ::return $this; } public method expand_toggle {} { ::if {[isLeaf]} {::return $this;} ::set _folder ""; ::if {[isExpanded]} {::return [collapse];} ::return [expand]; } public method is_active {} { ::if {[$tree active_node_id]==$id} {::return 1;} ::return 0; } public method is_collapsing {} { ::return $_is_collapsing; } public method activate {} { ::if {$::qw::control(is_low_level_window_copy)} { ::return $this; } ::set CurrentNode [$tree active_node]; ::qw::try { $tree active_node $this; ::if {[::winfo exists $_canvas]} { ::if {[::qw::command_exists $this]} { active_toggle; $_canvas itemconfigure $this-hilite -fill [::QW::GUI::color_darken #bae8c9 -20]; } } } catch Exception { ::qw::throw $Exception; } ::return $this; } public method active_node_select {} { $this activate; ::if {[::winfo exists $_canvas]} { ::if {[::qw::command_exists $this]} { $tree active_node_select $this; } } ::return $this; } public method deactivate {} { ::if {[isAncestorCollapsed]} {::return $this;} ;#// this node is not visible active_toggle; $_canvas itemconfigure $this-hilite -fill "" ::return $this; } public method isAncestorCollapsed {} { ::if {$parent ne ""} { ::if {![$parent isExpanded]} {::return 1;} ::return [$parent isAncestorCollapsed]; } ::return 0; #// we've hit (or been called on) the root } public method isAncestorCollapsing {} { ::if {$parent ne ""} { ::if {![$parent is_active]} {::return 1;} ::return [$parent isAncestorActive]; } ::return 0; #// we've hit (or been called on) the root } public method active_toggle {} { ::if {[isAncestorCollapsed]} {::return $this;} ;#// this node is not visible (see deactivate - wait for someone to activate invisible node) ::set x [left $this-text]; ::set y [top $this-text]; ::if {$x eq ""} {::return $this;} ::incr x 3; $_canvas delete $this-text; $_canvas create text $x $y -text [$tree text $id] -anchor nw -tags [list $this $this-text] -font [$tree font $id]; ::set x [left $this-icon]; ::set y [top $this-icon]; $_canvas delete $this-icon; $_canvas create image $x $y -image [$tree icon $id] -anchor nw -tags [::list $this $this-icon]; ::return $this; } public method draw {} { ::if {$parent eq ""} { ::set BoxX [::expr [$tree box_width]/2]; } else { ::set BoxX [$parent center_x $parent-icon]; } ::set Top 0; ::set Prev [prev]; ::if {$Prev ne ""} { ::set Top [$Prev kids_bottom]; } else { ::if {$parent ne ""} {::set Top [$parent bottom $parent];} } ::if {[isBranch]} { ::set BoxImage [$tree box $id]; $_canvas create image $BoxX $Top -image $BoxImage -anchor n -tags [list $this $this-box]; } ::set Left [::expr $BoxX+[$tree box_width]/2]; ::incr Left 5; $_canvas create image $Left $Top -image [$tree icon $id] -anchor nw -tags [list $this $this-icon]; ::set Left [right $this-icon]; $_canvas create text $Left $Top -text [$tree text $id] -anchor nw -tags [list $this $this-text] -font [$tree font $id]; ::set Height [height $this]; ::if {!$::qw::control(bind_replace)} { $_canvas bind $this-icon [::qw::itcl::code $this activate]; $_canvas bind $this-text [::qw::itcl::code $this activate]; $_canvas bind $this-text [::qw::itcl::code $this select]; $_canvas bind $this-icon [::qw::itcl::code $tree active_node_select $this]; $_canvas bind $this-text [::qw::itcl::code $tree active_node_select $this]; $_canvas bind $this-icon [::qw::itcl::code $this active_node_select]; $_canvas bind $this-text [::qw::itcl::code $this active_node_select]; ::if {[isBranch]} { ::set Script [::qw::itcl::code $this puts_pgq {"tcl8401b1 bug 01"};];::append Script ";"; #// this works! I want an honourary tcl degree! ::append Script [::qw::itcl::code $this expand_toggle]; $_canvas bind $this-box $Script; } } else { ::set Script [::qw::itcl::code $this activate]; ::set NewCode {::if {[::qw_gui_event_processing_is_enabled %_args0 %_args1 ]} {%_script}}; ::set NewCode [::string map [::list %_args0 $_canvas %_args1 [[$tree .client] pathAsTag] %_script $Script] $NewCode]; $_canvas bind $this-icon $NewCode; $_canvas bind $this-text $NewCode; ::set Script [::qw::itcl::code $this select]; ::set NewCode {::if {[::qw_gui_event_processing_is_enabled %_args0 %_args1 ]} {%_script}}; ::set NewCode [::string map [::list %_args0 $_canvas %_args1 [[$tree .client] pathAsTag] %_script $Script] $NewCode]; $_canvas bind $this-text $NewCode; ::set Script [::qw::itcl::code $tree active_node_select $this]; ::set NewCode {::if {[::qw_gui_event_processing_is_enabled %_args0 %_args1 ]} {%_script}}; ::set NewCode [::string map [::list %_args0 $_canvas %_args1 [[$tree .client] pathAsTag] %_script $Script] $NewCode]; $_canvas bind $this-icon $NewCode; $_canvas bind $this-text $NewCode; ::set Script [::qw::itcl::code $this active_node_select]; ::set NewCode {::if {[::qw_gui_event_processing_is_enabled %_args0 %_args1 ]} {%_script}}; ::set NewCode [::string map [::list %_args0 $_canvas %_args1 [[$tree .client] pathAsTag] %_script $Script] $NewCode]; $_canvas bind $this-icon $NewCode; $_canvas bind $this-text $NewCode; ::if {[isBranch]} { ::set Script [::qw::itcl::code $this expand_toggle]; ::set NewCode {::if {[::qw_gui_event_processing_is_enabled %_args0 %_args1 ]} {%_script}}; ::set NewCode [::string map [::list %_args0 $_canvas %_args1 [[$tree .client] pathAsTag] %_script $Script] $NewCode]; $_canvas bind $this-box $NewCode; } } ::if {[isBranch]} { $_canvas move $this-box 0 [::expr ($Height-[height $this-box])/2+1]; } $_canvas move $this-icon 0 [::expr ($Height-[height $this-icon])/2]; $_canvas move $this-text 0 [::expr ($Height-[height $this-text])/2]; ::set CenterY [center_y $this]; $_canvas lower [$_canvas create line [left $this-icon] $CenterY $BoxX $CenterY -fill grey -tags [list $this $this-line_h]]; draw_vertical_line; ::set Fill white; ::if {$_isSelected} {::set Fill green}; ::if {[is_active]} {::set Fill [::QW::GUI::color_darken #bae8c9 -20];} ::set SelectBackground [::eval $_canvas create rectangle [bounding_box $this-text]]; $_canvas itemconfigure $SelectBackground -fill $Fill -outline "" -tags [::list $this hilite $this-hilite]; $_canvas lower $SelectBackground; ::if {![isExpanded]} {::return $this;} ::return [kids_draw]; } public method draw_vertical_line {} { if {$parent eq ""} {return;} $_canvas delete $this-line_v; ::set x [::expr [$parent center_x $parent-icon]-1]; ::set Prev [prev]; if {$Prev ne ""} { ::set y [$Prev center_y $Prev]; } else { ::set y [$parent center_y $parent]; } $_canvas lower [$_canvas create line $x [center_y $this] $x $y -fill grey -tags $this-line_v]; } public method kids_draw {} { ::foreach Kid [kids] { $Kid draw; } ::return $this; } public method bounding_box {Tag} {return [$_canvas bbox $Tag];} public method height {Tag} { ::return [::expr [bottom $Tag]-[top $Tag]]; } public method width {Tag} { ::return [::expr [right $Tag]-[left $Tag]]; } public method top {Tag} {return [::lindex [bounding_box $Tag] 1];} public method left {Tag} {return [::lindex [bounding_box $Tag] 0];} public method bottom {Tag} { return [::lindex [bounding_box $Tag] 3]; } public method right {Tag} {return [::lindex [bounding_box $Tag] 2];} public method center_x {Tag} {return [::expr [left $Tag]+[width $Tag]/2];} public method center_y {Tag} {return [::expr [top $Tag]+[height $Tag]/2];} public method expand {} { ::if {[isLeaf]} { ::return $this; } ::if {[isExpanded]} { ::return $this; } ::if {![$tree expanding_all]} { ::if {![isExpandable]} { ::qw::throw [::sargs \ .text "Attempted to expand a tree branch that has expand disabled." \ .help_id 271820050404140220 \ ]; } } else { ::if {![isExpandable]} {::return $this;} } isExpanded 1; ::set Sandwich_wait_cursor [::itcl::local ::QW::GUI::SANDWICH_WAIT_CURSOR #auto $tree "wait"]; $_canvas addtag _about_to_move_ overlapping 0 [bottom $this] [right all] [bottom all]; kids_draw; $_canvas move _about_to_move_ 0 [::expr [kids_bottom] - [bottom $this]]; $_canvas dtag _about_to_move_ _about_to_move_ ::for {::set Parent $this} {$Parent ne ""} {::set Parent [$Parent cget -parent]} { ::if {[$Parent next] ne ""} {[$Parent next] draw_vertical_line;} } ::set x [left $this-box]; ::set y [top $this-box]; $_canvas delete $this-box; ::set BoxImage [$tree box $id]; $_canvas create image $x $y -image $BoxImage -anchor nw -tags [list $this $this-box]; $tree scroll_update; return $this; } public method expand_all {} { ::if {![isExpandable]} {::return $this;} expand; foreach Kid [kids] {$Kid expand_all} $tree scroll_update; return $this; } public method collapse_all {} { ::if {![isExpanded]} {::return $this;} ::foreach Kid [kids] {$Kid collapse_all} collapse; $tree scroll_update; ::return $this; } public method expand_path {Path} { ::if {$id eq $Path} { ::return $this; } ::if {![::string match "$id*" $Path]} {::return $this;} ;#// we have a Path that doesn't work here expand; ::foreach Kid [kids] { ::if {[::string match "[$Kid id]*" $Path]} { ::set PathRemainder [::string map "[$Kid id] {}" $Path]; ::if {$PathRemainder eq ""||[::string first "/" $PathRemainder]==0||[::string first "." $PathRemainder]==0} { $Kid expand_path $Path; ::break; } } } $tree scroll_update; ::return $this; } public method kids_undraw {} { ::if {![isExpanded]} {::return;} ::foreach Kid $_kids {$Kid undraw;} } public method undraw {} { kids_undraw; $_canvas delete $this $this-line_v; } public method kids_bottom {} { ::if {![isExpanded]} {::return [bottom $this];} ::if {[$tree items $id]==0&&$_kids eq ""} {::return [bottom $this];} ::return [[kid_last] kids_bottom]; } public method collapse {} { ::if {[isLeaf]&&$_kids eq ""} {::return $this;} ::if {![isExpanded]} {::return $this;} $_canvas addtag _about_to_move_ overlapping 0 [::expr [kids_bottom]+1] [right all] [bottom all]; ::set Distance_y [::expr [bottom $this]-[kids_bottom]]; ::set Sandwich_wait_cursor [::itcl::local ::QW::GUI::SANDWICH_WAIT_CURSOR #auto $tree "wait"]; ::set _is_collapsing 1; kids_undraw; isExpanded 0; $_canvas move _about_to_move_ 0 $Distance_y; $_canvas dtag _about_to_move_ _about_to_move_ ::for {::set Parent $this} {$Parent ne ""} {::set Parent [$Parent cget -parent]} { ::if {[$Parent next] ne ""} {[$Parent next] draw_vertical_line;} } ::set x [left $this-box] ::set y [top $this-box] $_canvas delete $this-box; ::set BoxImage [$tree box $id]; $_canvas create image $x $y -image $BoxImage -anchor nw -tags [list $this $this-box]; $tree scroll_update; $tree collapse $this; ::set _is_collapsing 0; ::return $this; } public method kid_first {} { if {[$tree items $id]!=0||$_kids ne ""} {return [::lindex [kids] 0];} return ""; } public method kid_last {} { ::if {[$tree items $id]!=0||$_kids ne ""} {::return [::lindex [kids] end];} ::return ""; } public method kid_next {Kid} { ::set Kids [kids]; ::set Index [::lsearch -exact $Kids $Kid]; ::qw::assert {$Index>=0} ::incr Index 1; ::if {$Index==[::llength $Kids]} {::return "";} ::return [::lindex $Kids $Index]; } public method kid_prev {Kid} { ::return [$Kid prev]; } public method next {} { ::if {$parent eq ""} {::return "";} ::return [$parent kid_next $this]; } public method prev {} { ::return $prev; } public method observer_database_cell_range_handle {} { ::if {![::info exists _odb_observers(database_cell_range)]} { odb_observer_create database_cell_range [::qw::odb::factory range]; } ::set Index [[observer_database_handle] [[$tree ".range_index_path"] odb_get]]; ::set RangeBegin [[$tree ".range_begin"] odb_get]; ::set RangeEnd [[$tree ".range_end"] odb_get]; ::if {$RangeBegin eq ""} {::set RangeBegin ".tag financial";} ::if {$RangeEnd eq ""} {::set RangeEnd ".tag financial";} [odb_observer_get database_cell_range] cpp_configure -index $Index -begin $RangeBegin -end $RangeEnd; ::return [odb_observer_get database_cell_range]; } }