source: tol/tolbase/lib/byswidget/fmenu/fmenu.tcl

devel
Last change on this file was 6d7779d, checked in by Jorge Pérez <josp.jorge@…>, 18 years ago

initial import

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@1 be4846ae-f051-483a-831f-b64e7d08527f

  • Property mode set to 100644
File size: 6.9 KB
RevLine 
[6d7779d]1# ----------------------------------------------------------------------------
2# fmenu.tcl --
3#
4# This file implement a new widget to create a top level menu from a menu
5# definition given as menudef object (see menudef.tcl). The top level menu is
6# a frame containing a row of menubuttons an separators. Normaly only one
7# separator is used to set the Help menu to the right side of the frame.
8# ----------------------------------------------------------------------------
9
10package require Tk 8.4
11package require snit
12package require struct
13
14snit::type menudef {
15  # definition tree
16  variable tdef
17  delegate method = to tdef
18  delegate method serialize to tdef
19  delegate method entries to tdef as children
20  delegate method delete to tdef
21 
22  typemethod validate_type {t isroot} {
23    if {$isroot && [lsearch {cascade separator} $t]==-1} {
24      error "invalid type \"$t\": only \"cascade\" or \"separator\" type can be used at root level in a menudef"
25    }
26    if {[lsearch {cascade checkbutton command radiobutton separator} \
27             $t] == -1} {
28      error "invalid type \"$t\": only \"cascade, checkbutton, command, radiobutton, or separator\" type can be used in a menudef"
29     
30    }
31  }
32
33  method clear { } {
34    foreach n [$tdef children root] {
35      $tdef delete $n
36    }
37  }
38
39  method add {parent t args} {
40    menudef validate_type $t [expr {$parent eq "root"}]
41    if {[expr {[llength $args] % 2}]} {
42      set entryid [lindex $args 0]
43      set node_entry  [$tdef insert $parent end $entryid]
44      set option_list [lrange $args 1 end]
45    } else {
46      set node_entry  [$tdef insert $parent end]
47      set option_list $args
48    }
49    if { [lsearch {separator} $t]==-1 } {
50        set label [from option_list -label ""]
51        set underline [lsearch [split $label {}] &]
52        set label [string map {& ""} $label]
53        set option_list [lappend option_list -label $label -underline $underline]
54    }
55    $tdef set $node_entry options $option_list
56    $tdef set $node_entry type $t
57    return $node_entry
58  }
59
60  method insert {node_ref t args} {
61    set parent [$tdef parent $node_ref]
62    menudef validate_type $t [expr {$parent eq "root"}]
63    set index [$tdef index $node_ref]
64    if {[expr {[llength $args] % 2}]} {
65      set entryid [lindex $args 0]
66      set node_entry  [$tdef insert $parent $index $entryid]
67      set option_list [lrange $args 1 end]
68    } else {
69      set node_entry  [$tdef insert $parent $index]
70      set option_list $args
71    }
72    if { [lsearch {separator} $t]==-1 } {
73        set label [from option_list -label ""]
74        set underline [lsearch [split $label {}] &]
75        set label [string map {& ""} $label]
76        set option_list [lappend option_list -label $label -underline $underline]
77    }
78    $tdef set $node_entry options $option_list
79    $tdef set $node_entry type $t
80    return $node_entry
81  }
82
83  method get_options {entry_id} {
84    $tdef get $entry_id options
85  }
86
87  method get_type {entry_id} {
88    $tdef get $entry_id type
89  }
90
91  constructor {} {
92    set tdef [::struct::tree]
93  }
94  destructor {
95    $tdef destroy
96  }
97}
98
99snit::method menudef dump {} {
100  $tdef walk root n {
101    set info $n
102    if {$n ne "root"} {
103      append info " =  [$tdef get $n type] [$tdef get $n options]"
104    }
105    #puts $info
106  }
107}
108
109snit::widget fmenu {
110  delegate method * to hull
111  delegate option * to hull
112  option -definition ""
113
114  variable allTops {}
115 
116  onconfigure -definition {newdef} {
117    if {$options(-definition) eq ""} {
118      set options(-definition) [menudef create %AUTO%]
119    }
120    if {$newdef ne ""} {
121      $options(-definition) = $newdef
122    } else {
123      $options(-definition) clear
124    }
125    $self draw
126  }
127
128  method draw {} {
129    set c 1 
130    foreach mb $allTops {
131      destroy $mb
132    }
133    set allTops {}
134    set def $options(-definition)
135    foreach mb [$def entries root] {
136      if {[$def get_type $mb] eq "separator"} {
137        grid columnconfigure $win $c -weight 1
138      } else {
139        set mbopt(-label) ""
140        set lopt [$def get_options $mb]
141        set label [from lopt -label ""]
142        set underline [from lopt -underline -1]
143        set post [from lopt -postcommand ""]
144        if {0 && [llength $lopt]} {
145          #puts "mbopt = $lopt"
146          array set mbopt $lopt
147        }
148        #puts $lopt
149        if {[llength $label] > 1} {
150          set label [list $label]
151        }
152        eval menubutton $win.mb$c -text $label \
153            -menu $win.mb$c.menu -underline $underline $lopt
154        bind $win.mb$c <Enter> [list $win.mb$c configure -relief raised]
155        bind $win.mb$c <Leave> [list $win.mb$c configure -relief flat]
156        bind $win.mb$c <ButtonPress-1> [list $win.mb$c configure -relief flat]
157        if {$post eq ""} {
158          $self drawsub $mb [menu $win.mb$c.menu -tearoff 0]
159        } else {
160          set post [string map "%W $win.mb$c.menu" $post]
161          menu $win.mb$c.menu -postcommand $post -tearoff 0
162        }
163        grid $win.mb$c -row 0 -column $c -sticky "nw"
164                grid columnconfigure $win $c -weight 0
165        lappend allTops $win.mb$c
166      }
167      incr c
168    }
169  }
170
171  method drawsub {menuid m} {
172    set def $options(-definition)
173    #puts "a crear los hijos de $menuid [$def get_options $menuid]"
174    set i 0   
175    foreach entry [$def entries $menuid] {
176      set entry_type [$def get_type $entry]
177      set entry_opt [$def get_options $entry]
178      set post [from entry_opt -postcommand ""]
179      if {$entry_type eq "cascade"} {
180        menu $m.m$i -tearoff 0
181        eval $m add cascade -menu $m.m$i $entry_opt
182        if {$post eq ""} {
183          $self drawsub $entry $m.m$i
184        } else {
185          set post [string map "%W $m.m$i" $post]
186          $m.m$i configure -postcommand $post
187        }
188      } else {
189        eval $m add $entry_type $entry_opt
190      }
191      incr i
192    }
193  }
194 
195 
196  constructor {args} {
197    set def [from args -definition]
198    $self configure -definition $def
199    $self configurelist $args
200  }
201}
202
203
204package provide fmenu 0.1
205
206# ------- TEST CODE ----
207
208proc do_post {m} {
209  $m delete 0 end
210  $m add command -label "Subentry 1"
211}
212
213proc test_fmenu { } {
214  set md [menudef create %AUTO%]
215  set id [$md add root cascade -label "&File"]
216  $md add $id command -label "&Open ..."
217  $md add $id command -label "&Close"
218  $md add $id separator
219  $md add $id command -label "&Exit"
220  set id [$md add root cascade -label "F&oo"]
221  $md add $id command -label "&Bar"
222  $md add $id separator
223  $md add $id command -label "B&e Be"
224  $md add $id cascade -label "&Postcommand" -postcommand "do_post %W"
225  $md add root separator
226  set id [$md add root cascade -label "&Help"]
227  $md add $id command -label "&Contents ..."
228  $md add $id separator
229  $md add $id command -label "&About ..." 
230
231  #$md dump
232  #return
233  if {[winfo exists .tmf]} {
234    .tmf.m configure -definition $md
235  } else {
236    toplevel .tmf
237    fmenu .tmf.m -definition $md
238    grid .tmf.m -row 0 -column 0 -sticky new
239    grid columnconfigure .tmf 0 -weight 1
240    grid rowconfigure .tmf 1 -weight 1
241  }
242  $md destroy
243}
244
245#test_fmenu
Note: See TracBrowser for help on using the repository browser.