Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/html/box.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ <H3>Summary:</H3>
These versions of the command implement the standard mouse
button bindings for the "box tool" in layout windows. <P>

In the Tcl/Tk GUI wrapper, the Cursor tool also supports creating
a box by pressing the left mouse button and dragging to the
opposite corner. The box is normalized while dragging, so the
initial point may be any corner; dragging toward the left, right,
top, or bottom produces the corresponding lower-left and upper-right
coordinates. The upper-right corner is updated continuously until
the button is released. <P></P>

For a discussion of valid directions, see the page
<A HREF=direction.html><B>direction</B></A>.
Note that special cases <B>box grow center</B> and
Expand Down
21 changes: 15 additions & 6 deletions doc/html/maketoolbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,21 @@ <H3>Summary:</H3>
<BLOCKQUOTE>
The <B>maketoolbar</B> command generates the toolbar for the
GUI layout window. The toolbar contains a set of buttons
representing each layer type in the technology file.
Each toolbar button has bindings for mouse buttons and
keys to implement shortcut commands in <B>magic</B>.
While the mouse pointer is inside the boundary of the
toolbar button, the name of the layer represented by the
toolbar is printed in the title bar of the window.<P>
The toolbar contains a set of interaction-tool buttons and a
set of buttons representing each layer type in the technology file.
The interaction buttons select the Cursor, Wire, Net, and Pick
tools. The Ruler button creates a ruler from the current cursor
box. Selecting a different tool while an unfinished Wire or Pick
interaction is active cancels that interaction before switching.
Each layer toolbar button has bindings for mouse buttons and keys
to implement shortcut commands in <B>magic</B>. While the mouse
pointer is inside the boundary of a toolbar button, its name is
printed in the title bar of the window.<P>

The Options menu also provides the <B></B>Embedded Console</B> toggle.
It opens a Tcl command console docked at the bottom of the layout
window and hides it again when disabled. The console supports
command history and displays Magic output and errors.<P></P>

<BLOCKQUOTE>
<CENTER>
Expand Down
6 changes: 5 additions & 1 deletion doc/html/zoom.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ <H3>Usage:</H3>
<H3>Summary:</H3>
<BLOCKQUOTE>
The <B>zoom</B> command implements view scaling in the layout
window in and out by the indicated magnification factor. <P>
window in and out by the indicated magnification factor. When
invoked from a layout window, the point under the cursor remains
fixed on the screen while the view is scaled. This makes it
possible to zoom into a particular layout feature without first
recentering the window. <P>

Note that several other commands effect a change in the view scale
factor, including <B>findbox zoom</B> and <B>view</B> with
Expand Down
61 changes: 59 additions & 2 deletions tcltk/toolbar.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ proc magic::maketoolbar {framename} {
set all_layers [concat $special_layers [magic::tech unlocked]]
}

# Add clickable buttons for the available interaction tools.
magic::makeToolButtons $framename

# Create a canvas for the toolbar
if {![winfo exists ${framename}.toolbar.canvas]} {
canvas ${framename}.toolbar.canvas
}
grid ${framename}.toolbar.canvas -row 0 -column 0 -sticky "news"
grid ${framename}.toolbar.canvas -row 1 -column 0 -sticky "news"

# Add a frame to the canvas, on which the layer buttons and
# labels are placed
Expand Down Expand Up @@ -90,7 +93,7 @@ proc magic::maketoolbar {framename} {
scrollbar ${framename}.toolbar.vscroll -orient "vertical" \
-command [list ${framename}.toolbar.canvas yview]

grid ${framename}.toolbar.vscroll -row 0 -column 1 -sticky "nws"
grid ${framename}.toolbar.vscroll -row 1 -column 1 -sticky "nws"

# Configure the canvas to use the scrollbar
${framename}.toolbar.canvas configure -yscrollcommand \
Expand All @@ -100,6 +103,60 @@ proc magic::maketoolbar {framename} {
bind ${framename} <Configure> "updateCanvasScrollRegion ${framename}"
}

# Create the compact interaction-tool strip above the layer toolbar.
proc magic::makeToolButtons {framename} {
global Opts
set Opts(toolframe) $framename

if {[winfo exists ${framename}.toolbar.tools]} {
destroy ${framename}.toolbar.tools
}
frame ${framename}.toolbar.tools -relief groove -borderwidth 1
grid ${framename}.toolbar.tools -row 0 -column 0 -columnspan 2 -sticky "ew"

set tools {
{box "Cursor" "Select and move the cursor box"}
{wiring "Wire" "Draw and edit wires"}
{nettool "Net" "Select and edit nets"}
{pick "Pick" "Select and move layout objects"}
}
foreach toolinfo $tools {
lassign $toolinfo tool label help
set button ${framename}.toolbar.tools.$tool
button $button -text $label -width 7 -padx 2 -pady 1 \
-command [list magic::selectToolFromToolbar $tool]
pack $button -side top -fill x -padx 2 -pady 1
bind $button <Enter> [list ${framename}.titlebar.message configure -text $help]
bind $button <Leave> [list ${framename}.titlebar.message configure -text ""]
}

# Ruler is an action rather than a persistent button tool. It uses the
# current cursor box and therefore does not change the active tool.
set ruler ${framename}.toolbar.tools.ruler
button $ruler -text "Ruler" -width 7 -padx 2 -pady 1 \
-command {magic::ruler}
pack $ruler -side top -fill x -padx 2 -pady 1
bind $ruler <Enter> [list ${framename}.titlebar.message configure \
-text "Create a ruler from the cursor box"]
bind $ruler <Leave> [list ${framename}.titlebar.message configure -text ""]

magic::updateToolButtons $framename
}

# Keep the selected tool visibly highlighted after a click or keyboard change.
proc magic::updateToolButtons {framename} {
global Opts
foreach tool {box wiring nettool pick} {
set button ${framename}.toolbar.tools.$tool
if {![winfo exists $button]} { continue }
if {[info exists Opts(tool)] && $Opts(tool) == $tool} {
$button configure -relief sunken -bg lightblue
} else {
$button configure -relief raised -bg [${framename}.toolbar cget -background]
}
}
}

# Function to place layer frame with a button and label
# on the toolbar, at a specific row $i
proc createLayerFrame {framename layername i} {
Expand Down
32 changes: 31 additions & 1 deletion tcltk/tools.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,35 @@ proc magic::cancelselect {window} {
}
}

# Switch tools from the GUI toolbar. A toolbar click is an explicit request
# to leave the current interaction, so cancel an unfinished wire or pick first.
proc magic::selectToolFromToolbar {type} {
global Opts

if {[info exists Opts(motion)] && $Opts(motion) != {}} {
# Opts(focus) is the layout toplevel (for example .layout1).
# The Magic canvas is nested below the paned window.
if {[info exists Opts(focus)]} {
set window ${Opts(focus)}.pane.top.magic
if {[info exists Opts(tool)] && $Opts(tool) == "wiring"} {
magic::trackwire $window cancel
} elseif {[info exists Opts(tool)] && $Opts(tool) == "pick"} {
magic::cancelselect $window
}
}
}
magic::tool $type

# Keep keyboard shortcuts such as `g` (grid) directed to the layout
# canvas after a toolbar button is clicked.
if {[info exists Opts(focus)]} {
set window ${Opts(focus)}.pane.top.magic
if {[winfo exists $window]} {
focus $window
}
}
}

#---------------------------------------------------------------------
# tool --- A scripted replacement for the "tool"
# command, as handling of button events has been modified
Expand Down Expand Up @@ -782,7 +811,8 @@ proc magic::tool {{type next}} {
}
}

# Update window captions with the new tool info
# Update window captions and the clickable toolbar state.
catch {magic::captions}
catch {magic::updateToolButtons $Opts(toolframe)}
return
}
124 changes: 100 additions & 24 deletions tcltk/wrapper.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,54 @@ proc magic::repaintwrapper { win } {

}

# Start a modern click-drag box gesture. Return "break" only for the
# box tool so that wiring, picking, and netlist tools retain their bindings.
proc magic::startboxdrag {win x y} {
global Opts
if {![info exists Opts(tool)] || $Opts(tool) != "box"} {return}
*bypass setpoint $x $y $win
set point [${win} cursor internal]
${win} box values {*}$point {*}$point
set Opts(boxdrag) $win
set Opts(boxdrag_start) $point
return break
}

proc magic::handlelayoutmotion {win x y} {
*bypass setpoint $x $y $win
set result [magic::updateboxdrag $win $x $y]
magic::cursorview $win
return $result
}

proc magic::updateboxdrag {win x y} {
global Opts
if {![info exists Opts(boxdrag)] || $Opts(boxdrag) != $win} {return}

set start $Opts(boxdrag_start)
set current [${win} cursor internal]
set x1 [lindex $start 0]
set y1 [lindex $start 1]
set x2 [lindex $current 0]
set y2 [lindex $current 1]
set llx [expr {min($x1, $x2)}]
set lly [expr {min($y1, $y2)}]
set urx [expr {max($x1, $x2)}]
set ury [expr {max($y1, $y2)}]
${win} box values $llx $lly $urx $ury
return break
}

proc magic::endboxdrag {win x y} {
global Opts
if {![info exists Opts(boxdrag)] || $Opts(boxdrag) != $win} {return}
*bypass setpoint $x $y $win
magic::updateboxdrag $win $x $y
set Opts(boxdrag) {}
set Opts(boxdrag_start) {}
return break
}

# Coordinate display callback function
# Because "box" calls "box", use the "info level" command to avoid
# infinite recursion.
Expand Down Expand Up @@ -683,8 +731,13 @@ proc magic::boxview {win {cmdstr ""}} {
if {[expr {$blly == int($blly)}]} {set blly [expr {int($blly)}]}
if {[expr {$burx == int($burx)}]} {set burx [expr {int($burx)}]}
if {[expr {$bury == int($bury)}]} {set bury [expr {int($bury)}]}
set titletext [format "box (%+g %+g) to (%+g %+g) microns" \
$bllx $blly $burx $bury]
set width [expr {$burx - $bllx}]
set height [expr {$bury - $blly}]
set area [expr {$width * $height}]
set centerx [expr {($bllx + $burx) / 2.0}]
set centery [expr {($blly + $bury) / 2.0}]
set titletext [format "box LL (%+g,%+g) UR (%+g,%+g) | size %g x %g um | center (%+g,%+g) | area %g um2" \
$bllx $blly $burx $bury $width $height $centerx $centery $area]
units {*}$curunits
${framename}.titlebar.pos configure -text $titletext
}
Expand Down Expand Up @@ -712,13 +765,18 @@ proc magic::cursorview {win} {
if {$gotbox} {
set curunits [${win} units list]
${win} units microns noprint
set dlst [${win} box position]

set dx [expr {$olstx - [lindex $dlst 0]}]
set dy [expr {$olsty - [lindex $dlst 1]}]
if {[expr {$dx == int($dx)}]} {set dx [expr {int($dx)}]}
if {[expr {$dy == int($dy)}]} {set dy [expr {int($dy)}]}
set titletext [format "(%+g %+g) %+g %+g microns" $olstx $olsty $dx $dy]
set bval [${win} box values]
set bllx [lindex $bval 0]
set blly [lindex $bval 1]
set burx [lindex $bval 2]
set bury [lindex $bval 3]
set width [expr {$burx - $bllx}]
set height [expr {$bury - $blly}]
set area [expr {$width * $height}]
set dx [expr {$olstx - $bllx}]
set dy [expr {$olsty - $blly}]
set titletext [format "cursor (%+g,%+g) um | box LL (%+g,%+g) UR (%+g,%+g) | size %g x %g um | delta %+g,%+g | area %g um2" \
$olstx $olsty $bllx $blly $burx $bury $width $height $dx $dy $area]
${framename}.titlebar.pos configure -text $titletext
${win} units {*}$curunits
} else {
Expand Down Expand Up @@ -1186,14 +1244,15 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
magic::repaintwrapper ${layoutframe}

grid ${layoutframe}.titlebar -row 0 -column 0 -columnspan 3 -sticky news
grid ${layoutframe}.yscroll -row 1 -column 0 -sticky ns
grid $winname -row 1 -column 1 -sticky news
grid ${layoutframe}.zb -row 2 -column 0
grid ${layoutframe}.xscroll -row 2 -column 1 -sticky ew
grid ${layoutframe}.toolbar -row 1 -column 0 -rowspan 2 -sticky nws
grid ${layoutframe}.yscroll -row 1 -column 1 -sticky ns
grid $winname -row 1 -column 2 -sticky news
grid ${layoutframe}.zb -row 2 -column 1
grid ${layoutframe}.xscroll -row 2 -column 2 -sticky ew
# The toolbar is not attached by default

grid rowconfigure ${layoutframe} 1 -weight 1
grid columnconfigure ${layoutframe} 1 -weight 1
grid columnconfigure ${layoutframe} 2 -weight 1

grid ${layoutframe}.titlebar.mbuttons -row 0 -column 0 -sticky news
grid ${layoutframe}.titlebar.drcbutton -row 0 -column 1 -sticky news
Expand All @@ -1210,8 +1269,16 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
# this command with the "bypass" command such that it does not
# reset any current input redirection to the terminal.

bind ${winname} <Motion> "*bypass setpoint %x %y ${winname}; \
magic::cursorview ${winname}"
bind ${winname} <Motion> \
[list magic::handlelayoutmotion $winname %x %y]

# Modern box-tool gesture: left-drag creates a new box from the
# press point to the current cursor position. Other tools continue
# to use their normal button macros.
bind $winname <ButtonPress-1> \
[list magic::startboxdrag $winname %x %y]
bind $winname <ButtonRelease-1> \
[list magic::endboxdrag $winname %x %y]

if {[catch {set Winopts(${framename},toolbar)}]} {
set Winopts(${framename},toolbar) 1
Expand Down Expand Up @@ -1373,7 +1440,7 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
$m add check -label "Toolbar" -variable Winopts(${framename},toolbar) \
-command [subst {if { \$Winopts(${framename},toolbar) } { \
magic::maketoolbar ${layoutframe} ; \
grid ${layoutframe}.toolbar -row 1 -column 2 -rowspan 2 -sticky new ; \
grid ${layoutframe}.toolbar -row 1 -column 0 -rowspan 2 -sticky nws ; \
} else { \
grid forget ${layoutframe}.toolbar } }]

Expand Down Expand Up @@ -1439,12 +1506,9 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
magic::render3d \[${winname} cellname list window\] \
} }]

$m add check -label "Window Command Entry" \
$m add check -label "Embedded Console" \
-variable Winopts(${framename},cmdentry) \
-command [subst { if { \$Winopts(${framename},cmdentry) } { \
addcommandentry $framename \
} else { \
deletecommandentry $framename } }]
-command [list magic::togglecommandentry $framename]

$m add check -label "Crosshair" \
-variable Opts(crosshair) \
Expand All @@ -1462,7 +1526,7 @@ proc magic::openwrapper {{cell ""} {framename ""}} {
# If the toolbar is turned on, invoke the toolbar button
if { $Winopts(${framename},toolbar) == 1} {
magic::maketoolbar ${layoutframe}
grid ${layoutframe}.toolbar -row 1 -column 2 -rowspan 2 -sticky new
grid ${layoutframe}.toolbar -row 1 -column 0 -rowspan 2 -sticky nws
}

# If the command entry window is enabled, create it now
Expand Down Expand Up @@ -1535,8 +1599,20 @@ proc magic::closewrapper { framename } {
destroy $framename
}

# Toggle the embedded Tcl console in the bottom pane of a wrapper window.
# This is the in-application alternative to the external TkCon window.
proc magic::togglecommandentry { framename } {
global Winopts

if {$Winopts(${framename},cmdentry)} {
magic::addcommandentry $framename
} else {
magic::deletecommandentry $framename
}
}

# This procedure adds a command-line entry window to the bottom of
# a wrapper window (rudimentary functionality---incomplete)
# a wrapper window.

proc magic::addcommandentry { framename } {
set commandframe ${framename}.pane.bot
Expand Down
4 changes: 2 additions & 2 deletions windows/windClient.c
Original file line number Diff line number Diff line change
Expand Up @@ -468,13 +468,13 @@ windFrameButtons(w, cmd)
switch (cmd->tx_button)
{
case TX_LEFT_BUTTON:
WindZoom(w, 2.0);
WindZoomAt(w, 2.0, &cmd->tx_p);
break;
case TX_MIDDLE_BUTTON:
WindView(w);
break;
case TX_RIGHT_BUTTON:
WindZoom(w, 0.5);
WindZoomAt(w, 0.5, &cmd->tx_p);
break;
}
return TRUE;
Expand Down
Loading