1#-----------------------------------------------------
2# Magic/TCL general-purpose toolkit procedures
3#-----------------------------------------------------
4# Tim Edwards
5# February 11, 2007
6# Revision 0
7#--------------------------------------------------------------
8# Sets up the environment for a toolkit.  The toolkit must
9# supply a namespace that is the "library name".  For each
10# parameter-defined device ("gencell") type, the toolkit must
11# supply three procedures:
12#
13# 1. ${library}::${gencell_type}_params {gname} {...}
14# 2. ${library}::${gencell_type}_check  {gname} {...}
15# 3. ${library}::${gencell_type}_draw   {gname} {...}
16#
17# The first defines the parameters used by the gencell, and
18# declares default parameters to use when first generating
19# the window that prompts for the device parameters prior to
20# creating the device.  The second checks the parameters for
21# legal values.  The third draws the device.
22#--------------------------------------------------------------
23
24# Initialize toolkit menus to the wrapper window
25
26global Opts
27
28#----------------------------------------------------------------
29# Add a menu button to the Magic wrapper window for the toolkit
30#----------------------------------------------------------------
31
32proc magic::add_toolkit_menu {framename button_text} {
33   menubutton ${framename}.titlebar.mbuttons.toolkit \
34		-text $button_text \
35		-relief raised \
36		-menu ${framename}.titlebar.mbuttons.toolkit.toolmenu \
37		-borderwidth 2
38
39   menu ${framename}.titlebar.mbuttons.toolkit.toolmenu -tearoff 0
40   pack ${framename}.titlebar.mbuttons.toolkit -side left
41}
42
43#----------------------------------------------------------------
44# Add a menu item to the toolkit menu
45#----------------------------------------------------------------
46
47proc magic::add_toolkit_button {framename button_text gencell_type library} {
48   set m ${framename}.titlebar.mbuttons.toolkit.toolmenu
49   $m add command -label "$button_text" -command \
50	"magic::gencell_params {} $gencell_type $library"
51}
52
53#-----------------------------------------------------
54# Device selection
55#-----------------------------------------------------
56
57proc magic::gen_params {} {
58
59    # Find selected item  (to-do:  handle multiple selections)
60    set wlist [what -list]
61    set clist [lindex $wlist 2]
62    set ccell [lindex $clist 0]
63    set cdef [lindex $ccell 1]
64    if {[regexp {^(.*_[0-9]*)$} $cdef valid gname] != 0} {
65       set library [cellname property $gname library]
66       if {$library == {}} {
67	  error "Gencell has no associated library!"
68       } else {
69          regexp {^(.*)_[0-9]*$} $cdef valid gencell_type
70	  magic::gencell_params $gname $gencell_type $library
71       }
72    } else {
73       # Error message
74       error "No gencell device is selected!"
75    }
76}
77
78#-----------------------------------------------------
79# Add "Ctrl-P" key callback for device selection
80#-----------------------------------------------------
81
82magic::macro ^P magic::gen_params
83
84#-------------------------------------------------------------
85# gencell_setparams
86#
87#   Go through the parameter window and collect all of the
88#   named parameters and their values, and generate the
89#   associated properties in celldef "$gname".
90#-------------------------------------------------------------
91
92proc magic::gencell_setparams {gname} {
93   set slist [grid slaves .params.edits]
94   foreach s $slist {
95      if {[regexp {^.params.edits.(.*)_ent$} $s valid pname] != 0} {
96	 set value [$s get]
97	 cellname property $gname $pname $value
98      }
99   }
100}
101
102#-------------------------------------------------------------
103# gencell_getparam
104#
105#   Go through the parameter window, find the named parameter,
106#   and return its value.
107#-------------------------------------------------------------
108
109proc magic::gencell_getparam {gname pname} {
110   set slist [grid slaves .params.edits]
111   foreach s $slist {
112      if {[regexp {^.params.edits.(.*)_ent$} $s valid ptest] != 0} {
113	 if {$pname == $ptest} {
114	    return [$s get]
115	 }
116      }
117   }
118}
119
120#-------------------------------------------------------------
121# gencell_change
122#
123#   Redraw a gencell with new parameters.
124#-------------------------------------------------------------
125
126proc magic::gencell_change {gname gencell_type library} {
127    if {[cellname list exists $gname] != 0} {
128	if {[eval "${library}::${gencell_type}_check $gname"]} {
129	    suspendall
130	    pushstack $gname
131	    select cell
132	    erase *
133	    magic::gencell_draw $gname $gencell_type $library
134	    popstack
135	    resumeall
136	} else {
137	    error "Parameter out of range!"
138	}
139    } else {
140	error "Cell $gname does not exist!"
141    }
142}
143
144#-------------------------------------------------------------
145# gencell_create
146#
147#   Instantiate a new gencell called $gname.  If $gname
148#   does not already exist, create it by calling its
149#   drawing routine.
150#
151#   Don't rely on pushbox/popbox since we don't know what
152#   the drawing routine is going to do to the stack!
153#-------------------------------------------------------------
154
155proc magic::gencell_create {gname gencell_type library} {
156    suspendall
157    if {[cellname list exists $gname] == 0} {
158	cellname create $gname
159	set snaptype [snap list]
160	snap internal
161	set savebox [box values]
162	pushstack $gname
163	magic::gencell_draw $gname $gencell_type $library
164	popstack
165	eval "box values $savebox"
166	snap $snaptype
167    }
168    getcell $gname
169    expand
170    resumeall
171}
172
173#-------------------------------------------------------------
174#-------------------------------------------------------------
175
176proc magic::gencell_check {gname gencell_type library} {
177    return [eval "${library}::${gencell_type}_check $gname"]
178}
179
180#-------------------------------------------------------------
181#-------------------------------------------------------------
182
183proc magic::gencell_draw {gname gencell_type library} {
184
185   # Set the parameters passed from the window text entries
186   magic::gencell_setparams $gname
187
188   # Call the draw routine
189   eval "${library}::${gencell_type}_draw $gname"
190
191   # Find the namespace of the draw procedure and set propery "library"
192   cellname property $gname library $library
193}
194
195#-----------------------------------------------------
196#  Add a standard parameter to the gencell window
197#-----------------------------------------------------
198
199proc magic::add_param {gname pname ptext default_value} {
200
201   # Check if the parameter exists.  If so, override the default
202   # value with the current value.
203
204   set value {}
205   if {[cellname list exists $gname] != 0} {
206      set value [cellname property $gname $pname]
207   }
208   if {$value == {}} {set value $default_value}
209
210   set numrows [lindex [grid size .params.edits] 0]
211   label .params.edits.${pname}_lab -text $ptext
212   entry .params.edits.${pname}_ent -background white
213   grid .params.edits.${pname}_lab -row $numrows -column 0
214   grid .params.edits.${pname}_ent -row $numrows -column 1
215   .params.edits.${pname}_ent insert end $value
216}
217
218#-----------------------------------------------------
219# Update the properties of a cell
220#-----------------------------------------------------
221
222proc magic::update_params {gname ptext default_value} {
223}
224
225#-------------------------------------------------------------
226# gencell_params ---
227# 1) If gname is NULL and gencell_type is set, then we
228#    create a new cell of type gencell_type.
229# 2) If gname is non-NULL, then we edit the existing
230#    cell of type $gname.
231# 3) If gname is non-NULL and gencell_type or library
232#    is NULL or unspecified, then we derive the gencell_type
233#    and library from the existing cell's property strings
234#-------------------------------------------------------------
235
236proc magic::gencell_params {gname {gencell_type {}} {library {}}} {
237
238   if {$gname == {}} {
239      set pidx 1
240      while {[cellname list exists ${gencell_type}_$pidx] != 0} {
241	  incr pidx
242      }
243      set gname ${gencell_type}_$pidx
244
245      set ttext "New device"
246      set btext "Create"
247      set bcmd "magic::gencell_create $gname $gencell_type $library"
248   } else {
249      if {$gencell_type == {}} {
250	 set gencell_type [cellname property ${gname} gencell]
251      }
252      if {$library == {}} {
253	 set library [cellname property ${gname} library]
254      }
255
256      set ttext "Edit device"
257      set btext "Apply"
258      set bcmd "magic::gencell_change $gname $gencell_type $library"
259   }
260
261   catch {destroy .params}
262   toplevel .params
263   label .params.title -text "$ttext $gname"
264   frame .params.edits
265   frame .params.buttons
266   pack .params.title
267   pack .params.edits
268   pack .params.buttons
269
270   button .params.buttons.apply \
271	-text "$btext" \
272	-command [subst { $bcmd ; \
273	.params.buttons.apply configure -text Apply}]
274   button .params.buttons.close -text "Close" -command {destroy .params}
275
276   pack .params.buttons.apply -padx 10 -side left
277   pack .params.buttons.close -padx 10 -side right
278
279   # Invoke the callback procedure that creates the parameter entries
280
281   eval "${library}::${gencell_type}_params $gname"
282}
283
284#-------------------------------------------------------------
285