From d2f9dfbc9e5ba94d94df9069e4f7af41604fa7b1 Mon Sep 17 00:00:00 2001 From: Dan McMahill Date: Fri, 20 Apr 2007 11:31:12 +0000 Subject: [PATCH] Merge the usermenu branch. This reworks how the menus and hotkeys are defined and handled for the gtk HID. In particular, instead of being hard coded, the menus are loaded from a menu resource file like in the lesstif gui. All hotkeys are defined via the menu hotkeys and thus are visually presented in the menus. The gtk HID looks for "gpcb-menu.res" instead of "pcb-menu.res" so that the menu organization may be different between the lesstif and gtk HID's. --- config.h.in | 3 + configure | 157 ++ configure.ac | 8 + src/Makefile.am | 20 +- src/Makefile.in | 20 +- src/action.c | 75 + src/gpcb-menu.res | 529 ++++++ src/hid/gtk/gtkhid-main.c | 856 ++++++++- src/hid/gtk/gui-config.c | 4 +- src/hid/gtk/gui-output-events.c | 561 +----- src/hid/gtk/gui-top-window.c | 3658 ++++++++++++++++++--------------------- src/hid/gtk/gui.h | 10 +- src/misc.c | 2 - src/pcbtest.sh.in | 3 + src/set.c | 3 - src/todo | 276 ++- 16 files changed, 3582 insertions(+), 2603 deletions(-) create mode 100644 src/gpcb-menu.res diff --git a/config.h.in b/config.h.in index 022aa6854b..9810d918fa 100644 --- a/config.h.in +++ b/config.h.in @@ -36,6 +36,9 @@ /* Define to 1 if you have the `gdImagePng' function. */ #undef HAVE_GDIMAGEPNG +/* Define to 1 if you have the header file. */ +#undef HAVE_GDK_GDKX_H + /* Define to 1 if you have the header file. */ #undef HAVE_GD_H diff --git a/configure b/configure index 3db69e1524..f3ad8fcfad 100755 --- a/configure +++ b/configure @@ -9526,6 +9526,163 @@ $GTK_PKG_ERRORS" >&2;} GTK_VERSION=`$PKG_CONFIG gtk+-2.0 --modversion` + # if we are building for gtk >= 2.8.0, we can use gdk_display_warp_pointer() + # otherwise we need XWarpPointer and we'll pull in the required headers with + # gdk/gdkx.h and we'll need to link with X11 + if ! $PKG_CONFIG gtk+-2.0 --atleast-version=2.8.0 ; then + CPPFLAGS="$CFLAGS $GTK_CFLAGS" + +for ac_header in gdk/gdkx.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + fi + # Search for glib succeeded=no diff --git a/configure.ac b/configure.ac index 90821cae23..b18424ca18 100644 --- a/configure.ac +++ b/configure.ac @@ -381,6 +381,14 @@ Please review the following errors: $GTK_PKG_ERRORS])] ) GTK_VERSION=`$PKG_CONFIG gtk+-2.0 --modversion` + + # if we are building for gtk >= 2.8.0, we can use gdk_display_warp_pointer() + # otherwise we need XWarpPointer and we'll pull in the required headers with + # gdk/gdkx.h and we'll need to link with X11 + if ! $PKG_CONFIG gtk+-2.0 --atleast-version=2.8.0 ; then + CPPFLAGS="$CFLAGS $GTK_CFLAGS" + AC_CHECK_HEADERS([gdk/gdkx.h]) + fi # Search for glib PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.4.0, , diff --git a/src/Makefile.am b/src/Makefile.am index 4b80ae03f9..c6cb21c9b9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,4 @@ +## -*- makefile -*- ## $Id$ ## @@ -15,6 +16,7 @@ EXTRA_LIBRARIES = \ pcblib_DATA= \ default_font \ + gpcb-menu.res \ pcb-menu.res bin_PROGRAMS= pcb @@ -147,6 +149,7 @@ DBUS_SRCS= \ BUILT_SOURCES = \ core_lists.h \ + gpcb-menu.h \ hid/gtk/gtk_lists.h \ hid/lesstif/lesstif_lists.h \ hid/batch/batch_lists.h \ @@ -184,6 +187,7 @@ EXTRA_DIST= \ $(srcdir)/hid/png/hid.conf \ $(srcdir)/hid/nelma/hid.conf \ $(srcdir)/hid/ps/hid.conf \ + gpcb-menu.res \ pcb-menu.res \ pcbtest.sh.in \ dbus.xml @@ -193,10 +197,16 @@ AM_YFLAGS= -d all-local: pcbtest.sh pcb-menu.h : pcb-menu.res - echo '/* AUTOMATICALLY GENERATED FROM pcb-menu.res DO NOT EDIT */' > pcb-menu.h - echo 'const char *pcb_menu_default[] = {' >> pcb-menu.h - sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/pcb-menu.res >> pcb-menu.h - echo '0};' >> pcb-menu.h + echo '/* AUTOMATICALLY GENERATED FROM pcb-menu.res DO NOT EDIT */' > $@ + echo 'const char *pcb_menu_default[] = {' >> $@ + sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/pcb-menu.res >> $@ + echo '0};' >> $@ + +gpcb-menu.h : gpcb-menu.res + echo '/* AUTOMATICALLY GENERATED FROM gpcb-menu.res DO NOT EDIT */' > $@ + echo 'const char *gpcb_menu_default[] = {' >> $@ + sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/gpcb-menu.res >> $@ + echo '0};' >> $@ hid/common/hidlist.h : Makefile true > $@ @@ -343,7 +353,7 @@ liblpr_a_SOURCES = \ hid/hidint.h \ hid/lpr/lpr.c -DISTCLEANFILES= pcbtest.sh pcb-menu.h \ +DISTCLEANFILES= pcbtest.sh gpcb-menu.h pcb-menu.h \ hid/batch/batch_lists.h \ hid/common/hidlist.h \ hid/gtk/gtk_lists.h \ diff --git a/src/Makefile.in b/src/Makefile.in index f6e3db8acf..37c7e58cec 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -366,6 +366,7 @@ EXTRA_LIBRARIES = \ pcblib_DATA = \ default_font \ + gpcb-menu.res \ pcb-menu.res AM_CFLAGS = -DNDEBUG @@ -396,7 +397,7 @@ DBUS_SRCS = \ dbus.h \ dbus.c -BUILT_SOURCES = core_lists.h hid/gtk/gtk_lists.h \ +BUILT_SOURCES = core_lists.h gpcb-menu.h hid/gtk/gtk_lists.h \ hid/lesstif/lesstif_lists.h hid/batch/batch_lists.h \ hid/png/png_lists.h hid/nelma/nelma_lists.h hid/ps/ps_lists.h \ parse_y.h pcb-menu.h res_parse.h hid/common/hidlist.h \ @@ -420,6 +421,7 @@ EXTRA_DIST = \ $(srcdir)/hid/png/hid.conf \ $(srcdir)/hid/nelma/hid.conf \ $(srcdir)/hid/ps/hid.conf \ + gpcb-menu.res \ pcb-menu.res \ pcbtest.sh.in \ dbus.xml @@ -505,7 +507,7 @@ liblpr_a_SOURCES = \ hid/hidint.h \ hid/lpr/lpr.c -DISTCLEANFILES = pcbtest.sh pcb-menu.h \ +DISTCLEANFILES = pcbtest.sh gpcb-menu.h pcb-menu.h \ hid/batch/batch_lists.h \ hid/common/hidlist.h \ hid/gtk/gtk_lists.h \ @@ -1608,10 +1610,16 @@ core_lists.h : ${PCB_SRCS} Makefile all-local: pcbtest.sh pcb-menu.h : pcb-menu.res - echo '/* AUTOMATICALLY GENERATED FROM pcb-menu.res DO NOT EDIT */' > pcb-menu.h - echo 'const char *pcb_menu_default[] = {' >> pcb-menu.h - sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/pcb-menu.res >> pcb-menu.h - echo '0};' >> pcb-menu.h + echo '/* AUTOMATICALLY GENERATED FROM pcb-menu.res DO NOT EDIT */' > $@ + echo 'const char *pcb_menu_default[] = {' >> $@ + sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/pcb-menu.res >> $@ + echo '0};' >> $@ + +gpcb-menu.h : gpcb-menu.res + echo '/* AUTOMATICALLY GENERATED FROM gpcb-menu.res DO NOT EDIT */' > $@ + echo 'const char *gpcb_menu_default[] = {' >> $@ + sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/",/' < ${srcdir}/gpcb-menu.res >> $@ + echo '0};' >> $@ hid/common/hidlist.h : Makefile true > $@ diff --git a/src/action.c b/src/action.c index 5f9071311b..4d05947d02 100644 --- a/src/action.c +++ b/src/action.c @@ -106,6 +106,7 @@ typedef enum F_ElementByName, F_ElementConnections, F_ElementToBuffer, + F_Escape, F_Find, F_FlipElement, F_FoundPins, @@ -334,6 +335,7 @@ static FunctionType Functions[] = { {"ElementByName", F_ElementByName}, {"ElementConnections", F_ElementConnections}, {"ElementToBuffer", F_ElementToBuffer}, + {"Escape", F_Escape}, {"Find", F_Find}, {"FlipElement", F_FlipElement}, {"FoundPins", F_FoundPins}, @@ -2824,6 +2826,10 @@ Cancels any pending tool activity, allowing you to restart elsewhere. For example, this allows you to start a new line rather than attach a line to the previous line. +@item Escape +Similar to Cancel but calling this action a second time will return +to the Arrow tool. + @item Stroke If your @code{pcb} was built with libstroke, this invokes the stroke input method. If not, this will restart a drawing mode if you were @@ -2843,6 +2849,7 @@ static int ActionMode (int argc, char **argv, int x, int y) { char *function = ARG (0); + if (function) { Note.X = Crosshair.X; @@ -2881,6 +2888,74 @@ ActionMode (int argc, char **argv, int x, int y) SetMode (saved_mode); } break; + case F_Escape: + { + switch (Settings.Mode) + { + case VIA_MODE: + case PASTEBUFFER_MODE: + case TEXT_MODE: + case ROTATE_MODE: + case REMOVE_MODE: + case MOVE_MODE: + case COPY_MODE: + case INSERTPOINT_MODE: + case RUBBERBANDMOVE_MODE: + case THERMAL_MODE: + case LOCK_MODE: + SetMode (NO_MODE); + SetMode (ARROW_MODE); + break; + + case LINE_MODE: + if (Crosshair.AttachedLine.State == STATE_FIRST) + SetMode (ARROW_MODE); + else + { + SetMode (NO_MODE); + SetMode (LINE_MODE); + } + break; + + case RECTANGLE_MODE: + if (Crosshair.AttachedBox.State == STATE_FIRST) + SetMode (ARROW_MODE); + else + { + SetMode (NO_MODE); + SetMode (RECTANGLE_MODE); + } + break; + + case POLYGON_MODE: + if (Crosshair.AttachedLine.State == STATE_FIRST) + SetMode (ARROW_MODE); + else + { + SetMode (NO_MODE); + SetMode (POLYGON_MODE); + } + break; + + case ARC_MODE: + if (Crosshair.AttachedBox.State == STATE_FIRST) + SetMode (ARROW_MODE); + else + { + SetMode (NO_MODE); + SetMode (ARC_MODE); + } + break; + + case ARROW_MODE: + break; + + default: + break; + } + } + break; + case F_Notify: NotifyMode (); break; diff --git a/src/gpcb-menu.res b/src/gpcb-menu.res new file mode 100644 index 0000000000..a9a9ac87fc --- /dev/null +++ b/src/gpcb-menu.res @@ -0,0 +1,529 @@ +# -*- c -*- +# Note - gpcb-menu.res is used to build gpcb-menu.h +# Note - parameters are sensitive to extra spaces around the commas + +# +# NOTE: I have not figured out what to do with this +# section yet. The Mouse section is currently ignored until +# I figure out how to handle it. +# + +Mouse = +{ + Left = { + Mode(Notify) + up = Mode(Release) + } + Right = { + { Mode(Save) Mode(Rotate) Mode(Notify) Mode(Release) Mode(Restore) } + } + Middle = { + Pan(1) + up = Pan(0) + ctrl = Pan(thumb,1) + ctrl-up = Pan(thumb,0) + } + Up = Zoom(0.8) + Down = Zoom(1.25) +# If you want zoom to center, do this instead. +#Up = { {Zoom(0.8) Center()} } +#Down = { {Zoom(1.25) Center()} } +} + +MainMenu = +{ + +# +# File Menu +# + + {File m=F + {"Save layout" Save(Layout) tip="Saves current layout"} + {"Save layout as..." Save(LayoutAs) tip="Saves current layout into a new file"} + - + {"Revert" Load(Revert,none) tip="Revert to the layout stored on disk"} + - + {"Load layout" Load(Layout) tip="Load a layout from a file"} + {"Load element data to paste-buffer" PasteBuffer(Clear) Load(ElementTobuffer)} + {"Load layout data to paste-buffer" PasteBuffer(Clear) Load(LayoutTobuffer)} + {"Load netlist file" Load(Netlist)} + {"Load vendor resource file" LoadVendor()} + - + {"Save connection data of" + {" a single element" GetXY(press a button at the element location) Save(ElementConnections)} + {" all elements" Save(AllConnections)} + {" unused pins" Save(AllUnusedPins)} + } + - + {"Print layout..." Print()} + {"Export layout..." Export()} + {"Calibrate Printer..." PrintCalibrate()} + - + {"Start new layout" New()} + - + {"Preferences..." DoWindows(Preferences)} + - + {"Quit Program" Quit() m=Q a={"Ctrl-Q" "Ctrlq"}} + } + +# +# Edit Menu +# + + {Edit m=E + {"Undo last operation" Undo() a={"U" "u"}} + {"Redo last undone operation" Redo() a={"Shift-R" "Shiftr"}} + {"Clear undo-buffer" Undo(ClearList) a={"Shift-Ctrl-U" "Shift Ctrlu"}} + - + {"Cut selection to buffer" GetXY(Press a button at the reference location) + PasteBuffer(Clear) PasteBuffer(AddSelected) RemoveSelected() Mode(PasteBuffer) + a={"Shift-Ctrl-X" "Shift Ctrlx"}} + {"Copy selection to buffer" GetXY(Press a button at the reference location) + PasteBuffer(Clear) PasteBuffer(AddSelected) Mode(PasteBuffer) + a={"Ctrl-X" "Ctrlx"}} + {"Paste buffer to layout" Mode(PasteBuffer) } + - + {"Unselect all" Unselect(All) a={"Shift-Alt-A" "Shift Alta"}} + {"Select all" Select(All) a={"Alt-A" "Alta"}} + - + {"Edit name of" + {"text on layout" ChangeName(Object) a={"N" "n"}} + {"layout" ChangeName(Layout)} + {"active layer" ChangeName(Layer)} + } + - + {"Move to current layer" MoveToCurrentLayer(Object) a={"M" "m"}} + {"Move selected to current layer" MoveToCurrentLayer(Selected) a={"Shift-M" "Shiftm"}} + {"Route Styles" @routestyles + - + {"Edit..." AdjustStyle(0)} + } + } + +# +# View Menu +# + + {View m=V + {"Enable visible grid" checked=drawgrid Display(Grid)} + {"Grid units" + {"mils" checked=grid_units_mm,0 SetUnits(mil)} + {"mms" checked=grid_units_mm,1 SetUnits(mm)} + } + {"Grid size" + {"No Grid" checked=gridsize,1 SetValue(Grid,1)} + - + { "0.1 mil" checked=gridsize,10 SetUnits(mil) SetValue(Grid,10)} + { "1 mil" checked=gridsize,100 SetUnits(mil) SetValue(Grid,100)} + { "5 mil" checked=gridsize,500 SetUnits(mil) SetValue(Grid,500)} + { "10 mil" checked=gridsize,1000 SetUnits(mil) SetValue(Grid,1000)} + { "25 mil" checked=gridsize,2500 SetUnits(mil) SetValue(Grid,2500)} + {"100 mil" checked=gridsize,10000 SetUnits(mil) SetValue(Grid,10000)} + - + {"0.01 mm" checked=gridsize,39 SetUnits(mm) SetValue(Grid,39.37007874)} + {"0.05 mm" checked=gridsize,197 SetUnits(mm) SetValue(Grid,196.85039370)} + {"0.1 mm" checked=gridsize,394 SetUnits(mm) SetValue(Grid,393.70078740)} + {"0.25 mm" checked=gridsize,984 SetUnits(mm) SetValue(Grid,984.25197)} + {"0.5 mm" checked=gridsize,1969 SetUnits(mm) SetValue(Grid,1968.503937)} + {"1 mm" checked=gridsize,3937 SetUnits(mm) SetValue(Grid,3937.00787400)} + - + {"Grid -5mil" SetValue(Grid,-5,mil) a={"Shift-G" "Shiftg"}} + {"Grid +5mil" SetValue(Grid,+5,mil) a={"G" "g"}} + {"Grid -0.05mm" SetValue(Grid,-0.05,mm) a={"Shift-Ctrl-G" "Shift Ctrlg"}} + {"Grid +0.05mm" SetValue(Grid,+0.05,mm) a={"Ctrl-G" "Ctrlg"}} + } + {"Realign grid" GetXY(Press a button at a grid point) Display(ToggleGrid)} + - + {"Displayed element name" + {"Description" Display(Description) checked=elementname,1} + {"Reference Designator" Display(NameOnPCB) checked=elementname,2} + {"Value" Display(Value) checked=elementname,3} + } + {"Enable Pinout shows number" checked=shownumber Display(ToggleName)} + {"Pins/Via show Name/Number" Display(PinOrPadName) a={"D" "d"}} + {"Open pinout menu" Display(Pinout) a={"Shift+D" "Shiftd"}} + - + {"Zoom In 20%" Zoom(-1.2) m=Z a={"Z" "z"}} + {"Zoom Out 20%" Zoom(+1.2) m=O a={"Shift-Z" "Shiftz"}} + {"More zooms and view changes" + {"Zoom Max" Zoom() m=M a={"V" "v"}} + {"Zoom In 2X" Zoom(-2)} + {"Zoom Out 2X" Zoom(+2)} + {"Zoom to 0.1mil/px" Zoom(=10)} + {"Zoom to 0.01mm/px" Zoom(=39.37)} + {"Zoom to 1mil/px" Zoom(=100)} + {"Zoom to 0.05mm/px" Zoom(=196.8504)} + {"Zoom to 2.5mil/px" Zoom(=250)} + {"Zoom to 0.1mm/px" Zoom(=393.7)} + {"Zoom to 10mil/px" Zoom(=1000)} + {"Zoom In 20% and center" Zoom(-1.2) Center() m=Z } + {"Zoom Out 20% and center" Zoom(+1.2) Center() m=O } + {"Flip up/down" checked=flip_y SwapSides(V) } + {"Flip left/right" checked=flip_x SwapSides(H)} + {"Spin 180 degrees" SwapSides(R) } + {"Swap Sides" SwapSides() } + {"Center cursor" Center() a={"C" "c"}} + } + - + {"Shown Layers" + @layerview + - + {"Edit Layer Groups" EditLayerGroups()} + } + {"Current Layer" + @layerpick + - + {"Delete current layer" MoveLayer(c,-1)} + {"Add new layer" MoveLayer(-1,c)} + {"Move current layer up" MoveLayer(c,up)} + {"Move current layer down" MoveLayer(c,down)} + } + } + +# +# Settings menu +# + {Settings m=S + {"'All-direction' lines" checked=alldirection Display(Toggle45Degree) a={"." "."}} + {"Auto swap line start angle" checked=swapstartdir Display(ToggleStartDirection)} + {"Orthogonal moves" checked=orthomove Display(ToggleOrthoMove)} + {"Crosshair snaps to pins and pads" checked=snappin Display(ToggleSnapPin)} + {"Crosshair shows DRC clearance" checked=showdrc Display(ToggleShowDRC)} + {"Auto enforce DRC clearance" checked=autodrc Display(ToggleAutoDRC)} + - + {"Rubber band mode" checked=rubberband Display(ToggleRubberBandMode)} + {"Require unique element names" checked=uniquename Display(ToggleUniqueNames)} + {"Auto-zero delta measurements" checked=localref Display(ToggleLocalRef)} + {"New lines, arcs clear polygons" checked=clearnew Display(ToggleClearLine)} + {"Show autorouter trials" checked=liveroute Display(ToggleLiveRoute)} + {"Thin draw" checked=thindraw Display(ToggleThindraw) a={"|" "|"}} + {"Thin draw poly" checked=thindrawpoly Display(ToggleThindrawPoly) a={"Ctrl-Shift-P" "Ctrl Shiftp"}} + {"Check polygons" checked=checkplanes Display(ToggleCheckPlanes)} + - + {"Vendor drill mapping" ToggleVendor() checked=VendorMapOn} + } + +# +# Select menu +# + {Select m=l + {"Select all objects" Select(All)} + {"Select all connected objects" Select(Connection)} + - + {"Unselect all objects" Unselect(All)} + {"unselect all connected objects" Unselect(Connection)} + - + {"Select by name" + {"All objects" Select(ObjectByName) ActiveWhen(have_regex)} + {"Elements" Select(ElementByName) ActiveWhen(have_regex)} + {"Pads" Select(PadByName) ActiveWhen(have_regex)} + {"Pins" Select(PinByName) ActiveWhen(have_regex)} + {"Text" Select(TextByName) ActiveWhen(have_regex)} + {"Vias" Select(ViaByName) ActiveWhen(have_regex)} + } + - + {"Auto-place selected elements" AutoPlaceSelected() a={"Ctrl-P" "Ctrlp"}} + {"Disperse all elements" DisperseElements(All)} + {"Disperse selected elements" DisperseElements(Selected)} + - + {"Move selected elements to other side" Flip(SelectedElements) a={"Shift-B" "Shiftb"}} + {"Remove selected objects" RemoveSelected()} + {"Convert selection to element" Select(Convert)} + - + {"Optimize selected rats" DeleteRats(SelectedRats) AddRats(SelectedRats)} + {"Auto-route selected rats" AutoRoute(SelectedRats) a={"Alt-R" "Altr"}} + {"Rip-up selected auto-routed tracks" RipUp(Selected)} + - + {"Change size of selected objects" + {"Lines -10 mil" ChangeSize(SelectedLines,-10,mil) ChangeSize(SelectedArcs,-10,mil)} + {"Lines +10 mil" ChangeSize(SelectedLines,+10,mil) ChangeSize(SelectedArcs,+10,mil)} + {"Pads -10 mil" ChangeSize(SelectedPads,-10,mil)} + {"Pads +10 mil" ChangeSize(SelectedPads,+10,mil)} + {"Pins -10 mil" ChangeSize(SelectedPins,-10,mil)} + {"Pins +10 mil" ChangeSize(SelectedPins,+10,mil)} + {"Texts -10 mil" ChangeSize(SelectedTexts,-10,mil)} + {"Texts +10 mil" ChangeSize(SelectedTexts,+10,mil)} + {"Vias -10 mil" ChangeSize(SelectedVias,-10,mil)} + {"Vias +10 mil" ChangeSize(SelectedVias,+10,mil)} + } + - + {"Change drilling hole of selected objects" + {"Vias -10 mil" ChangeDrillSize(SelectedVias,-10,mil)} + {"Vias +10 mil" ChangeDrillSize(SelectedVias,+10,mil)} + {"Pins -10 mil" ChangeDrillSize(SelectedPins,-10,mil)} + {"Pins +10 mil" ChangeDrillSize(SelectedPins,+10,mil)} + } + - + {"Change square-flag of selected objects" + {"Elements" ChangeSquare(SelectedElements)} + {"Pins" ChangeSquare(SelectedPins)} + } + } + +# +# Buffer menu +# + {Buffer m=B + {"Copy selection to buffer" GetXY(Press a button at the element location) + PasteBuffer(Clear) PasteBuffer(AddSelected) Unselect(All) Mode(PasteBuffer) + a={"Ctrl-C" "Ctrlc"} + } + {"Cut selection to buffer" GetXY(Press a button at the element location) + PasteBuffer(Clear) PasteBuffer(AddSelected) RemoveSelected() Mode(PasteBuffer)} + {"Paste buffer to layout" Mode(PasteBuffer)} + - + {"Rotate buffer 90 deg CCW" Mode(PasteBuffer) PasteBuffer(Rotate,1) + a={"Shift-F7" "ShiftF7"}} + {"Rotate buffer 90 deg CW" Mode(PasteBuffer) PasteBuffer(Rotate,3)} + {"Mirror buffer (up/down)" Mode(PasteBuffer) PasteBuffer(Mirror)} + {"Mirror buffer (left/right)" Mode(PasteBuffer) PasteBuffer(Rotate,1) + PasteBuffer(Mirror) PasteBuffer(Rotate,3)} + - + {"Clear buffer" PasteBuffer(Clear)} + {"Convert buffer to element" PasteBuffer(Convert)} + {"Break buffer elements to pieces" PasteBuffer(Restore)} + {"Save buffer elements to file" Save(PasteBuffer)} + - + {"Select current buffer" foreground=grey50 sensitive=false} + {"#1" CheckWhen(buffer,1) PasteBuffer(1) a={"Shift-1" "Shift1"}} + {"#2" CheckWhen(buffer,2) PasteBuffer(2) a={"Shift-2" "Shift2"}} + {"#3" CheckWhen(buffer,3) PasteBuffer(3) a={"Shift-3" "Shift3"}} + {"#4" CheckWhen(buffer,4) PasteBuffer(4) a={"Shift-4" "Shift4"}} + {"#5" CheckWhen(buffer,5) PasteBuffer(5) a={"Shift-5" "Shift5"}} + } + +# +# Connects menu +# + {Connects m=C + {"Lookup connection to object" GetXY(Select the object) Connection(Find) a={"Ctrl-F" "Ctrlf"}} + {"Reset scanned pads/pins/vias" Connection(ResetPinsViasAndPads) Display(Redraw)} + {"Reset scanned lines/polygons" Connection(ResetLinesAndPolygons) Display(Redraw)} + {"Reset all connections" Connection(Reset) Display(Redraw) a={"Shift-F" "Shiftf"}} + - + {"Optimize rats nest" Atomic(Save) DeleteRats(AllRats) + Atomic(Restore) AddRats(AllRats) Atomic(Block) a={"O" "o"}} + {"Erase rats nest" DeleteRats(AllRats) a={"E" "e"}} + {"Erase selected rats" DeleteRats(SelectedRats) a={"Shift-E" "Shifte"}} + - + {"Auto-route selected rats" AutoRoute(Selected)} + {"Auto-route all rats" AutoRoute(AllRats)} + {"Rip up all auto-routed tracks" RipUp(All)} + - + {"Optimize routed tracks" + {"Auto-Optimize" djopt(auto) a={"Shift-=" "Shift="}} + {"Debumpify" djopt(debumpify) } + {"Unjaggy" djopt(unjaggy) } + {"Vianudge" djopt(vianudge) } + {"Viatrim" djopt(viatrim) } + {"Ortho pull" djopt(orthopull) } + {"Simple optimization" djopt(simple) a={"=" "="}} + {"Miter" djopt(miter) } + {"Puller" a={"Y" "y"} Puller() } + - + {"Only autorouted nets" OptAutoOnly() checked=optautoonly} + } + - + {"Design Rule Checker" DRC()} + - + {"Apply vendor drill mapping" ApplyVendor()} + } + +# +# Info Menu +# + {Info m=I + {"Generate object report" ReportObject() a={"Ctrl-R" "Ctrlr"}} + {"Generate drill summary" Report(DrillReport)} + {"Report found pins/pads" Report(FoundPins)} + {"Key Bindings" + {"Remove" a={"Backspace" "BackSpace"} + Mode(Save) + Mode(Remove) + Mode(Notify) + Mode(Restore) + } + {"Remove" a={"Delete" "Delete"} + Mode(Save) + Mode(Remove) + Mode(Notify) + Mode(Restore) + } + {"Remove Connected" a={"Shift-Backspace" "ShiftBackSpace"} + Atomic(Save) + Connection(Reset) + Atomic(Restore) + Unselect(All) + Atomic(Restore) + Connection(Find) + Atomic(Restore) + Select(Connection) + Atomic(Restore) + RemoveSelected() + Atomic(Restore) + Connection(Reset) + Atomic(Restore) + Unselect(All) + Atomic(Block) + } + {"Remove Connected" a={"Shift-Delete" "ShiftDelete"} + Atomic(Save) + Connection(Reset) + Atomic(Restore) + Unselect(All) + Atomic(Restore) + Connection(Find) + Atomic(Restore) + Select(Connection) + Atomic(Restore) + RemoveSelected() + Atomic(Restore) + Connection(Reset) + Atomic(Restore) + Unselect(All) + Atomic(Block) + } + {"Set Same" a={"A" "a"} SetSame()} + {"Flip Object" a={"B" "b"} Flip(Object)} + {"Find Connections" a={"F" "f"} Connection(Reset) Connection(Find)} + {"ToggleHideName Object" a={"H" "h"} ToggleHideName(Object)} + {"ToggleHideName SelectedElement" a={"Shift-H" "Shifth"} ToggleHideName(SelectedElements)} + {"ChangeHole Object" a={"Ctrl-H" "Ctrlh"} ChangeHole(Object)} + {"ChangeJoin Object" a={"J" "j"} ChangeJoin(Object)} + {"ChangeJoin SelectedObject" a={"Shift-J" "Shiftj"} ChangeJoin(SelectedObjects)} + {"Clear Object +2 mil" a={"K" "k"} ChangeClearSize(Object,+2,mil)} + {"Clear Object -2 mil" a={"Shift-K" "Shiftk"} ChangeClearSize(Object,-2,mil)} + {"Clear Selected +2 mil" a={"Ctrl-K" "Ctrlk"} ChangeClearSize(SelectedObjects,+2,mil)} + {"Clear Selected -2 mil" a={"Shift-Ctrl-K" "Shift Ctrlk"} ChangeClearSize(SelectedObjects,-2,mil)} + {"Linesize +5 mil" a={"L" "l"} SetValue(LineSize,+5,mil)} + {"Linesize -5 mil" a={"Shift-L" "Shiftl"} SetValue(LineSize,-5,mil)} + {"MarkCrosshair" a={"Ctrl-M" "Ctrlm"} MarkCrosshair()} + {"Select shortest rat" a={"Shift-N" "Shiftn"} AddRats(Close)} + {"AddRats to selected pins" a={"Shift-O" "Shifto"} + Atomic(Save) + DeleteRats(AllRats) + Atomic(Restore) + AddRats(SelectedRats) + Atomic(Block) } + {"ChangeOctagon Object" a={"Ctrl-O" "Ctrlo"} ChangeOctagon(Object)} + {"Polygon PreviousPoint" a={"P" "p"} Polygon(PreviousPoint)} + {"Polygon Close" a={"Shift-P" "Shiftp"} Polygon(Close)} + {"ChangeSquare Object" a={"Q" "q"} ChangeSquare(ToggleObject)} + {"ChangeSize +5 mil" a={"S" "s"} ChangeSize(Object,+5,mil)} + {"ChangeSize -5 mil" a={"Shift-S" "Shifts"} ChangeSize(Object,-5,mil)} + {"ChangeDrill +5 mil" a={"Alt-S" "Alts"} ChangeDrillSize(Object,+5,mil)} + {"ChangeDrill -5 mil" a={"Alt-Shift-S" "Alt Shifts"} ChangeDrillSize(Object,-5,mil)} + {"TextScale +10 mil" a={"T" "t"} SetValue(TextScale,+10,mil)} + {"TextScale -10 mil" a={"Shift-T" "Shiftt"} SetValue(TextScale,-10,mil)} + {"ViaSize +5 mil" a={"Ctrl-V" "Ctrlv"} SetValue(ViaSize,+5,mil)} + {"ViaSize -5 mil" a={"Shift-Ctrl-V" "Shift Ctrlv"} SetValue(ViaSize,-5,mil)} + {"ViaDrill +5 mil" a={"Alt-V" "Altv"} SetValue(ViaDrillingHole,+5,mil)} + {"ViaDrill -5 mil" a={"Alt-Shift-V" "Alt Shiftv"} SetValue(ViaDrillingHole,-5,mil)} + {"AddRats Selected" a={"Shift-W" "Shiftw"} AddRats(SelectedRats)} + {"Add All Rats" a={"W" "w"} AddRats(AllRats)} + {"Cycle Clip" a={"/" "/"} Display(CycleClip)} + {"Arrow Mode" a={"Space" "space"} Mode(Arrow) checked=arrowmode,1} + {"Temp Arrow ON" a={"[" "["} Mode(Save) Mode(Arrow) Mode(Notify)} + {"Temp Arrow OFF" a={"]" "]"} Mode(Release) Mode(Restore)} + - + {"Step Up" a={"Up" "Up"} Cursor(Warp,0,1,grid)} + {"Step Down" a={"Down" "Down"} Cursor(Warp,0,-1,grid)} + {"Step Left" a={"Left" "Left"} Cursor(Warp,-1,0,grid)} + {"Step Right" a={"Right" "Right"} Cursor(Warp,1,0,grid)} + {"Step +Up" a={"Up" "ShiftUp"} Cursor(Pan,0,50,view)} + {"Step +Down" a={"Down" "ShiftDown"} Cursor(Pan,0,-50,view)} + {"Step +Left" a={"Left" "ShiftLeft"} Cursor(Pan,-50,0,view)} + {"Step +Right" a={"Right" "ShiftRight"} Cursor(Pan,50,0,view)} + {'"Click"' a={"Enter" "Enter"} Mode(Notify) Mode(Release) } + } + } +# +# Window Menu +# + {Window + {"Library" DoWindows(Library)} + {"Message Log" DoWindows(Log)} + {"Netlist" DoWindows(Netlist)} + {"Command Entry" Command() a={":" ":"}} + {"Pinout" Display(Pinout) a={"Shift-D" "Shiftd"}} + {"Board Layout" DoWindows(Layout)} + - + {"About..." About()} + } +} + +PopupMenus = + { + Popup1 = + { + {"Operations on selections" + {"Unselect all objects" Unselect(All)} + {"Remove selected objects" RemoveSelected()} + {"Copy selection to buffer" + GetXY(Press a button on a reference point for your selection) + PasteBuffer(Clear) + PasteBuffer(AddSelected) + Mode(PasteBuffer) + } + {"Cut selection to buffer" + GetXY(Press a button on a reference point for your selection) + PasteBuffer(Clear) + PasteBuffer(AddSelected) + RemoveSelected() + Mode(PasteBuffer) + } + {"Convert selection to element" Select(Convert)} + {"Auto place selected elements" AutoPlaceSelected()} + {"Autoroute selected elements" AutoRoute(SelectedRats)} + {"Rip up selected auto routed tracks" RipUp(Selected)} + } + {"Operations on this location" + {"Generate object report" GetXY(Select the object) Report(Object)} + } + - + {"Undo last operation" Undo()} + {"Redo last undone operation" Redo()} + - + {Tools + {"None" checked=nomode,1 Mode(None)} + {"Via" checked=viamode,1 Mode(Via) a={"F1" "F1"}} + {"Line" checked=linemode,1 Mode(Line) a={"F2" "F2"}} + {"Arc" checked=arcmode,1 Mode(Arc) a={"F3" "F3"}} + {"Text" checked=textmode,1 Mode(Text) a={"F4" "F4"}} + {"Rectangle" checked=rectanglemode,1 Mode(Rectangle) a={"F5" "F5"}} + {"Polygon" checked=polygonmode,1 Mode(Polygon) a={"F6" "F6"}} + {"Buffer" checked=pastebuffermode,1 Mode(PasteBuffer) a={"F7" "F7"}} + {"Remove" checked=removemode,1 Mode(Remove) a={"F8" "F8"}} + {"Rotate" checked=rotatemode,1 Mode(Rotate) a={"F9" "F9"}} + {"Thermal" checked=thermalmode,1 Mode(Thermal) a={"F10" "F10"}} + {"Arrow" checked=arrowmode,1 Mode(Arrow) a={"F11" "F11"}} + {"Insert Point" checked=insertpointmode,1 Mode(InsertPoint) a={"Insert" "Insert"}} + {"Move" checked=movemode,1 Mode(Move)} + {"Copy" checked=copymode,1 Mode(Copy)} + {"Lock" checked=lockmode,1 Mode(Lock)} + {"Cancel" Mode(Escape) a={"Esc" "Escape"}} + } + } + +# +# A dummy popup menu to help test out the parser and also +# it will be used to help test the Popup() action when +# I get around to writing it. +# + Popup2 = + { + {"Submenu1" + {"Choice1a"} + {"Choice1b"} + {"Choice1c"} + {"Choice1d"} + } + {"Submenu2" + {"Choice2a"} + {"Choice2b"} + } + {"Choice1"} + {"Choice2"} + } + } + diff --git a/src/hid/gtk/gtkhid-main.c b/src/hid/gtk/gtkhid-main.c index 40fe9773e6..b1d8ab0c07 100644 --- a/src/hid/gtk/gtkhid-main.c +++ b/src/hid/gtk/gtkhid-main.c @@ -12,10 +12,13 @@ #include #include -#include "global.h" -#include "data.h" + #include "action.h" #include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "global.h" #include "mymem.h" #include "draw.h" #include "clip.h" @@ -24,6 +27,11 @@ #include "../hidint.h" #include "gui.h" + +#if !GTK_CHECK_VERSION(2,8,0) && defined(HAVE_GDK_GDKX_H) +#include +#endif + #ifdef HAVE_LIBDMALLOC #include #endif @@ -35,6 +43,9 @@ RCSID ("$Id$"); extern HID ghid_hid; +static void zoom_to (double factor, int x, int y); +static void zoom_by (double factor, int x, int y); + /* Sets gport->u_gc to the "right" GC to use (wrt mask or window) */ #define USE_GC(gc) if (!use_gc(gc)) return @@ -42,32 +53,281 @@ extern HID ghid_hid; static int cur_mask = -1; static int mask_seq = 0; +int ghid_flip_x = 0, ghid_flip_y = 0; + +/* ------------------------------------------------------------ */ + +/* Px converts view->pcb, Vx converts pcb->view */ + +static inline int +Vx (int x) +{ + int rv; + if (ghid_flip_x) + rv = (PCB->MaxWidth - x - gport->view_x0) / gport->zoom + 0.5; + else + rv = (x - gport->view_x0) / gport->zoom + 0.5; + return rv; +} + +static inline int +Vx2 (int x) +{ + return (x - gport->view_x0) / gport->zoom + 0.5; +} + +static inline int +Vy (int y) +{ + int rv; + if (ghid_flip_y) + rv = (PCB->MaxHeight - y - gport->view_y0) / gport->zoom + 0.5; + else + rv = (y - gport->view_y0) / gport->zoom + 0.5; + return rv; +} + +static inline int +Vy2 (int y) +{ + return (y - gport->view_y0) / gport->zoom + 0.5; +} + +static inline int +Vz (int z) +{ + return z / gport->zoom + 0.5; +} + +static inline int +Px (int x) +{ + int rv = x * gport->zoom + gport->view_x0; + if (ghid_flip_x) + rv = PCB->MaxWidth - (x * gport->zoom + gport->view_x0); + return rv; +} + +static inline int +Py (int y) +{ + int rv = y * gport->zoom + gport->view_y0; + if (ghid_flip_y) + rv = PCB->MaxHeight - (y * gport->zoom + gport->view_y0); + return rv; +} + +/* ------------------------------------------------------------ */ static const char zoom_syntax[] = -"Zoom(gtk)"; +"Zoom()\n" +"Zoom(factor)"; + static const char zoom_help[] = -"this is the gtk zoom"; +"Various zoom factor changes."; /* %start-doc actions Zoom +Changes the zoom (magnification) of the view of the board. If no +arguments are passed, the view is scaled such that the board just fits +inside the visible window (i.e. ``view all''). Otherwise, +@var{factor} specifies a change in zoom factor. It may be prefixed by +@code{+}, @code{-}, or @code{=} to change how the zoom factor is +modified. The @var{factor} is a floating point number, such as +@code{1.5} or @code{0.75}. + +@table @code + +@item +@var{factor} +Values greater than 1.0 cause the board to be drawn smaller; more of +the board will be visible. Values between 0.0 and 1.0 cause the board +to be drawn bigger; less of the board will be visible. + +@item -@var{factor} +Values greater than 1.0 cause the board to be drawn bigger; less of +the board will be visible. Values between 0.0 and 1.0 cause the board +to be drawn smaller; more of the board will be visible. + +@item =@var{factor} + +The @var{factor} is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +@var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a @var{factor} of 100 gives you a 10x actual +size. + +@end table + +Note that zoom factors of zero are silently ignored. + -This is for the gtk zoom. %end-doc */ -/* FIXME */ static int Zoom (int argc, char **argv, int x, int y) { double factor; + const char *vp; + double v; + + if (argc > 1) + AFAIL (zoom); + + if (x == 0 && y == 0) + { + x = gport->view_width / 2; + y = gport->view_height / 2; + } + else + { + /* Px converts view->pcb, Vx converts pcb->view */ + x = Vx (x); + y = Vy (y); + } + if (argc < 1) + { + zoom_to (1000000, 0, 0); + return 0; + } + + vp = argv[0]; + if (*vp == '+' || *vp == '-' || *vp == '=') + vp++; + v = strtod (vp, 0); + if (v <= 0) return 1; - factor = strtod (argv[0], 0); - ghid_port_ranges_zoom (gport->zoom * factor); + switch (argv[0][0]) + { + case '-': + factor = 1 / v; + zoom_by (1 / v, x, y); + break; + default: + case '+': + factor = v; + zoom_by (v, x, y); + break; + case '=': + /* this needs to set the scale factor absolutely*/ + factor = 1.0; + zoom_to (v, x, y); + break; + } + return 0; } +static void +zoom_to (double new_zoom, int x, int y) +{ + double max_zoom, xfrac, yfrac; + int cx, cy; + + /* gport->zoom: + * zoom value is PCB units per screen pixel. Larger numbers mean zooming + * out - the largest value means you are looking at the whole board. + * + * PCB units per screen pixel + * + * gport->view_width and gport->view_height are in PCB coordinates + */ + +#ifdef DEBUG + printf ("\nzoom_to( %g, %d, %d)\n", new_zoom, x, y); +#endif + + xfrac = (double) x / (double) gport->view_width; + yfrac = (double) y / (double) gport->view_height; + + if (ghid_flip_x) + xfrac = 1-xfrac; + if (ghid_flip_y) + yfrac = 1-yfrac; + + /* Find the zoom that would just make the entire board fit */ + max_zoom = PCB->MaxWidth / gport->width; + if (max_zoom < PCB->MaxHeight / gport->height) + max_zoom = PCB->MaxHeight / gport->height; + +#ifdef DEBUG + printf ("zoom_to(): max_zoom = %g\n", max_zoom); +#endif + + /* + * clip the zooming so we can never have more than 1 pixel per PCB + * unit and never zoom out more than viewing the entire board + */ + + if (new_zoom < 1) + new_zoom = 1; + if (new_zoom > max_zoom) + new_zoom = max_zoom; + +#ifdef DEBUG + printf ("max_zoom = %g, xfrac = %g, yfrac = %g, new_zoom = %g\n", + max_zoom, xfrac, yfrac, new_zoom); +#endif + + /* find center x and y */ + cx = gport->view_x0 + gport->view_width * xfrac * gport->zoom; + cy = gport->view_y0 + gport->view_height * yfrac * gport->zoom; + +#ifdef DEBUG + printf ("zoom_to(): x0 = %d, cx = %d\n", gport->view_x0, cx); + printf ("zoom_to(): y0 = %d, cy = %d\n", gport->view_y0, cy); +#endif + + if (gport->zoom != new_zoom) + { + gdouble xtmp, ytmp; + gint x0, y0; + + xtmp = (gport->view_x - gport->view_x0) / (gdouble) gport->view_width; + ytmp = (gport->view_y - gport->view_y0) / (gdouble) gport->view_height; + + gport->zoom = new_zoom; + pixel_slop = new_zoom; + ghid_port_ranges_scale(FALSE); + + x0 = gport->view_x - xtmp * gport->view_width; + if (x0 < 0) + x0 = 0; + gport->view_x0 = x0; + + y0 = gport->view_y - ytmp * gport->view_height; + if (y0 < 0) + y0 = 0; + gport->view_y0 = y0; + + ghidgui->adjustment_changed_holdoff = TRUE; + gtk_range_set_value (GTK_RANGE (ghidgui->h_range), gport->view_x0); + gtk_range_set_value (GTK_RANGE (ghidgui->v_range), gport->view_y0); + ghidgui->adjustment_changed_holdoff = FALSE; + + ghid_port_ranges_changed(); + } + +#ifdef DEBUG + printf ("zoom_to(): new x0 = %d\n", gport->view_x0); + printf ("zoom_to(): new y0 = %d\n", gport->view_y0); +#endif + ghid_set_status_line_label (); +} + +void +zoom_by (double factor, int x, int y) +{ +#ifdef DEBUG + printf ("\nzoom_by( %g, %d, %d). old gport->zoom = %g\n", + factor, x, y, gport->zoom); +#endif + zoom_to (gport->zoom * factor, x, y); +} + /* ------------------------------------------------------------ */ static void @@ -80,7 +340,7 @@ draw_grid () if (!Settings.DrawGrid) return; - if (DRAW_Z (PCB->Grid) < MIN_GRID_DISTANCE) + if (Vz (PCB->Grid) < MIN_GRID_DISTANCE) return; if (!gport->grid_gc) { @@ -95,10 +355,10 @@ draw_grid () gdk_gc_set_function (gport->grid_gc, GDK_XOR); gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color); } - x1 = GRIDFIT_X (SIDE_X(gport->view_x0), PCB->Grid); - y1 = GRIDFIT_Y (gport->view_y0, PCB->Grid); - x2 = GRIDFIT_X (SIDE_X(gport->view_x0 + gport->view_width - 1), PCB->Grid); - y2 = GRIDFIT_Y (gport->view_y0 + gport->view_height - 1, PCB->Grid); + x1 = GRIDFIT_X (SIDE_X (gport->view_x0), PCB->Grid); + y1 = GRIDFIT_Y (SIDE_Y (gport->view_y0), PCB->Grid); + x2 = GRIDFIT_X (SIDE_X (gport->view_x0 + gport->view_width - 1), PCB->Grid); + y2 = GRIDFIT_Y (SIDE_Y (gport->view_y0 + gport->view_height - 1), PCB->Grid); if (x1 > x2) { int tmp = x1; @@ -111,13 +371,13 @@ draw_grid () y1 = y2; y2 = tmp; } - if (DRAW_X (x1) < 0) + if (Vx (x1) < 0) x1 += PCB->Grid; - if (DRAW_Y (y1) < 0) + if (Vy (y1) < 0) y1 += PCB->Grid; - if (DRAW_X (x2) >= gport->width) + if (Vx (x2) >= gport->width) x2 -= PCB->Grid; - if (DRAW_Y (y2) >= gport->height) + if (Vy (y2) >= gport->height) y2 -= PCB->Grid; n = (int) ((x2 - x1) / PCB->Grid + 0.5) + 1; if (n > npoints) @@ -129,12 +389,12 @@ draw_grid () n = 0; for (x = x1; x <= x2; x += PCB->Grid) { - points[n].x = DRAW_X (x); + points[n].x = Vx (x); n++; } for (y = y1; y <= y2; y += PCB->Grid) { - int vy = DRAW_Y (y); + int vy = Vy (y); for (i = 0; i < n; i++) points[i].y = vy; gdk_draw_points (gport->drawable, gport->grid_gc, points, n); @@ -209,15 +469,15 @@ ghid_invalidate_all () if (!gport->pixmap) return; - region.X1 = MIN(VIEW_X(0), VIEW_X(gport->width + 1)); - region.Y1 = MIN(VIEW_Y(0), VIEW_Y(gport->height + 1)); - region.X2 = MAX(VIEW_X(0), VIEW_X(gport->width + 1)); - region.Y2 = MAX(VIEW_Y(0), VIEW_Y(gport->height + 1)); + region.X1 = MIN(Px(0), Px(gport->width + 1)); + region.Y1 = MIN(Py(0), Py(gport->height + 1)); + region.X2 = MAX(Px(0), Px(gport->width + 1)); + region.Y2 = MAX(Py(0), Py(gport->height + 1)); - eleft = DRAW_X (0); - eright = DRAW_X (PCB->MaxWidth); - etop = DRAW_Y (0); - ebottom = DRAW_Y (PCB->MaxHeight); + eleft = Vx (0); + eright = Vx (PCB->MaxWidth); + etop = Vy (0); + ebottom = Vy (PCB->MaxHeight); if (eleft > eright) { int tmp = eleft; @@ -546,7 +806,7 @@ ghid_set_line_cap (hidGC gc, EndCapStyle style) } if (gc->gc) gdk_gc_set_line_attributes (WHICH_GC (gc), - DRAW_Z (gc->width), GDK_LINE_SOLID, + Vz (gc->width), GDK_LINE_SOLID, gc->cap, gc->join); } @@ -557,7 +817,7 @@ ghid_set_line_width (hidGC gc, int width) gc->width = width; if (gc->gc) gdk_gc_set_line_attributes (WHICH_GC (gc), - DRAW_Z (gc->width), GDK_LINE_SOLID, + Vz (gc->width), GDK_LINE_SOLID, gc->cap, gc->join); } @@ -613,10 +873,10 @@ ghid_draw_line (hidGC gc, int x1, int y1, int x2, int y2) { double dx1, dy1, dx2, dy2; - dx1 = DRAW_X ((double)x1); - dy1 = DRAW_Y ((double)y1); - dx2 = DRAW_X ((double)x2); - dy2 = DRAW_Y ((double)y2); + dx1 = Vx ((double)x1); + dy1 = Vy ((double)y1); + dx2 = Vx ((double)x2); + dy2 = Vy ((double)y2); if (! ClipLine (0, 0, gport->width, gport->height, &dx1, &dy1, &dx2, &dy2, gc->width / gport->zoom)) @@ -632,25 +892,36 @@ ghid_draw_arc (hidGC gc, int cx, int cy, { gint vrx, vry; gint w, h, radius; - + w = gport->width * gport->zoom; h = gport->height * gport->zoom; radius = (xradius > yradius) ? xradius : yradius; if (SIDE_X (cx) < gport->view_x0 - radius || SIDE_X (cx) > gport->view_x0 + w + radius - || cy < gport->view_y0 - radius || cy > gport->view_y0 + h + radius) + || SIDE_Y (cy) < gport->view_y0 - radius + || SIDE_Y (cy) > gport->view_y0 + h + radius) return; - + USE_GC (gc); - vrx = DRAW_Z (xradius); - vry = DRAW_Z (yradius); - if (Settings.ShowSolderSide) - { - start_angle =-start_angle + 180;; - delta_angle = -delta_angle;; - } + vrx = Vz (xradius); + vry = Vz (yradius); + + + /* make sure we fall in the -180 to +180 range */ + start_angle = (start_angle + 360 + 180) % 360 - 180; + if (ghid_flip_x) + { + start_angle = 180 - start_angle; + delta_angle = - delta_angle; + } + if (ghid_flip_y) + { + start_angle = - start_angle; + delta_angle = - delta_angle; + } + gdk_draw_arc (gport->drawable, gport->u_gc, 0, - DRAW_X (cx) - vrx, DRAW_Y (cy) - vry, + Vx (cx) - vrx, Vy (cy) - vry, vrx * 2, vry * 2, (start_angle + 180) * 64, delta_angle * 64); } @@ -667,14 +938,16 @@ ghid_draw_rect (hidGC gc, int x1, int y1, int x2, int y2) && SIDE_X (x2) < gport->view_x0 - lw) || (SIDE_X (x1) > gport->view_x0 + w + lw && SIDE_X (x2) > gport->view_x0 + w + lw) - || (y1 < gport->view_y0 - lw && y2 < gport->view_y0 - lw) - || (y1 > gport->view_y0 + h + lw && y2 > gport->view_y0 + h + lw)) + || (SIDE_Y (y1) < gport->view_y0 - lw + && SIDE_Y (y2) < gport->view_y0 - lw) + || (SIDE_Y (y1) > gport->view_y0 + h + lw + && SIDE_Y (y2) > gport->view_y0 + h + lw)) return; - x1 = DRAW_X (x1); - y1 = DRAW_Y (y1); - x2 = DRAW_X (x2); - y2 = DRAW_Y (y2); + x1 = Vx (x1); + y1 = Vy (y1); + x2 = Vx (x2); + y2 = Vy (y2); if (x1 > x2) { gint xt = x1; x1 = x2; x2 = xt; } if (y1 > y2) { gint yt = y1; y1 = y2; y2 = yt; } @@ -694,13 +967,14 @@ ghid_fill_circle (hidGC gc, int cx, int cy, int radius) h = gport->height * gport->zoom; if (SIDE_X (cx) < gport->view_x0 - radius || SIDE_X (cx) > gport->view_x0 + w + radius - || cy < gport->view_y0 - radius || cy > gport->view_y0 + h + radius) + || SIDE_Y (cy) < gport->view_y0 - radius + || SIDE_Y (cy) > gport->view_y0 + h + radius) return; USE_GC (gc); - vr = DRAW_Z (radius); + vr = Vz (radius); gdk_draw_arc (gport->drawable, gport->u_gc, TRUE, - DRAW_X (cx) - vr, DRAW_Y (cy) - vr, + Vx (cx) - vr, Vy (cy) - vr, vr * 2, vr * 2, 0, 360 * 64); } @@ -720,8 +994,8 @@ ghid_fill_polygon (hidGC gc, int n_coords, int *x, int *y) } for (i = 0; i < n_coords; i++) { - points[i].x = DRAW_X (x[i]); - points[i].y = DRAW_Y (y[i]); + points[i].x = Vx (x[i]); + points[i].y = Vy (y[i]); } gdk_draw_polygon (gport->drawable, gport->u_gc, 1, points, n_coords); } @@ -739,14 +1013,16 @@ ghid_fill_rect (hidGC gc, int x1, int y1, int x2, int y2) && SIDE_X (x2) < gport->view_x0 - lw) || (SIDE_X (x1) > gport->view_x0 + w + lw && SIDE_X (x2) > gport->view_x0 + w + lw) - || (y1 < gport->view_y0 - lw && y2 < gport->view_y0 - lw) - || (y1 > gport->view_y0 + h + lw && y2 > gport->view_y0 + h + lw)) + || (SIDE_Y (y1) < gport->view_y0 - lw + && SIDE_Y (y2) < gport->view_y0 - lw) + || (SIDE_Y (y1) > gport->view_y0 + h + lw + && SIDE_Y (y2) > gport->view_y0 + h + lw)) return; - x1 = DRAW_X (x1); - y1 = DRAW_Y (y1); - x2 = DRAW_X (x2); - y2 = DRAW_Y (y2); + x1 = Vx (x1); + y1 = Vy (y1); + x2 = Vx (x2); + y2 = Vy (y2); if (x2 < x1) { xx = x1; @@ -1183,6 +1459,54 @@ HID ghid_extents = { 0 /* ghid_progress */ }; +/* ------------------------------------------------------------ + * + * Actions specific to the GTK HID follow from here + * + */ + + +/* ------------------------------------------------------------ */ +static const char about_syntax[] = +"About()"; + +static const char about_help[] = +"Tell the user about this version of PCB."; + +/* %start-doc actions About + +This just pops up a dialog telling the user which version of +@code{pcb} they're running. + +%end-doc */ + + +static int +About (int argc, char **argv, int x, int y) +{ + ghid_dialog_about (); + return 0; +} + +/* ------------------------------------------------------------ */ +static const char getxy_syntax[] = +"GetXY()"; + +static const char getxy_help[] = +"Get a coordinate."; + +/* %start-doc actions GetXY + +Prompts the user for a coordinate, if one is not already selected. + +%end-doc */ + +static int +GetXY (int argc, char **argv, int x, int y) +{ + return 0; +} + /* ---------------------------------------------------------------------- */ static int PointCursor (int argc, char **argv, int x, int y) @@ -1197,6 +1521,8 @@ static int PointCursor (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int RouteStylesChanged (int argc, char **argv, int x, int y) { @@ -1208,6 +1534,8 @@ RouteStylesChanged (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + int PCBChanged (int argc, char **argv, int x, int y) { @@ -1227,6 +1555,8 @@ PCBChanged (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int LayerGroupsChanged (int argc, char **argv, int x, int y) { @@ -1234,6 +1564,8 @@ LayerGroupsChanged (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int LibraryChanged (int argc, char **argv, int x, int y) { @@ -1241,6 +1573,8 @@ LibraryChanged (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int Command (int argc, char **argv, int x, int y) { @@ -1248,6 +1582,8 @@ Command (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int Load (int argc, char **argv, int x, int y) { @@ -1301,6 +1637,8 @@ Load (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int LoadVendor (int argc, char **argv, int x, int y) { @@ -1326,6 +1664,8 @@ LoadVendor (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ + static int Save (int argc, char **argv, int x, int y) { @@ -1385,11 +1725,51 @@ Save (int argc, char **argv, int x, int y) return 0; } +/* ---------------------------------------------------------------------- */ +static const char swapsides_syntax[] = +"SwapSides(|v|h|r)"; + +static const char swapsides_help[] = +"Swaps the side of the board you're looking at."; + +/* %start-doc actions SwapSides + +This action changes the way you view the board. + +@table @code + +@item v +Flips the board over vertically (up/down). + +@item h +Flips the board over horizontally (left/right), like flipping pages in +a book. + +@item r +Rotates the board 180 degrees without changing sides. + +@end table + +If no argument is given, the board isn't moved but the opposite side +is shown. + +Normally, this action changes which pads and silk layer are drawn as +true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. + +As a special case, if the layer group for the side you're looking at +is visible and currently active, and the layer group for the opposite +is not visible (i.e. disabled), then this action will also swap which +layer group is visible and active, effectively swapping the ``working +side'' of the board. + +%end-doc */ + + static int SwapSides (int argc, char **argv, int x, int y) { gint dx; - int comp_group = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER); int solder_group = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER); int active_group = GetLayerGroupNumberByNumber (LayerStack[0]); @@ -1398,8 +1778,30 @@ SwapSides (int argc, char **argv, int x, int y) int solder_showing = PCB->Data->Layer[PCB->LayerGroups.Entries[solder_group][0]].On; - if (argc && strcasecmp (argv[0], "lr") == 0) - ; + + if (argc > 0) + { + switch (argv[0][0]) { + case 'h': + case 'H': + ghid_flip_x = ! ghid_flip_x; + break; + case 'v': + case 'V': + ghid_flip_y = ! ghid_flip_y; + break; + case 'r': + case 'R': + ghid_flip_x = ! ghid_flip_x; + ghid_flip_y = ! ghid_flip_y; + break; + default: + return 1; + } + /* SwapSides will swap this */ + Settings.ShowSolderSide = (ghid_flip_x == ghid_flip_y); + } + Settings.ShowSolderSide = !Settings.ShowSolderSide; if (Settings.ShowSolderSide) { @@ -1421,8 +1823,12 @@ SwapSides (int argc, char **argv, int x, int y) 1); } } + + /* what does this do? */ dx = PCB->MaxWidth / 2 - gport->view_x; ghid_port_ranges_pan (2 * dx, 0, TRUE); + + ghid_invalidate_all (); return 0; } @@ -1504,24 +1910,282 @@ Benchmark (int argc, char **argv, int x, int y) } /* ------------------------------------------------------------ */ -static const char about_syntax[] = -"About()"; -static const char about_help[] = -"Tell the user about this version of PCB."; +static const char center_syntax[] = +"Center()\n"; -/* %start-doc actions About +static const char center_help[] = +"Moves the pointer to the center of the window."; -This just pops up a dialog telling the user which version of -@code{pcb} they're running. +/* %start-doc actions Center + +Move the pointer to the center of the window, but only if it's +currently within the window already. %end-doc */ +static int +Center(int argc, char **argv, int x, int y) +{ + int x0, y0, w2, h2, dx, dy; + + if (argc != 0) + AFAIL (center); + + x = GRIDFIT_X (SIDE_X (x), PCB->Grid); + y = GRIDFIT_Y (SIDE_Y (y), PCB->Grid); + + w2 = gport->view_width / 2; + h2 = gport->view_height / 2; + x0 = x - w2; + y0 = y - h2; + + if (x0 < 0) + { + x0 = 0; + x = x0 + w2; + } + + if (y0 < 0) + { + y0 = 0; + y = y0 + w2; + } + + dx = (x0 - gport->view_x0) / gport->zoom ; + dy = (y0 - gport->view_y0) / gport->zoom; + gport->view_x0 = x0; + gport->view_y0 = y0; + + + /* FIXME -- do I need something like the pan_fixup here? */ + /* lesstif_pan_fixup (); */ + + /* Move the pointer to the center of the window, but only if it's + currently within the window already. Watch out for edges, + though. */ + +#if GTK_CHECK_VERSION(2,8,0) + { + GdkDisplay *display; + GdkScreen *screen; + gint cx, cy; + + display = gdk_display_get_default (); + screen = gdk_display_get_default_screen (display); + + /* figure out where the pointer is and then move it from there by the specified delta */ + gdk_display_get_pointer (display, NULL, &cx, &cy, NULL); + gdk_display_warp_pointer (display, screen, cx - dx, cy - dy); + + /* + * Note that under X11, gdk_display_warp_pointer is just a wrapper around XWarpPointer, but + * hopefully by avoiding the direct call to an X function we might still work under windows + * and other non-X11 based gdk's + */ + } +#else +# ifdef HAVE_GDK_GDKX_H + { + + Window w_src, w_dst; + w_src = GDK_WINDOW_XID (gport->drawing_area->window); + w_dst = w_src; + + /* don't warp with the auto drc - that creates auto-scroll chaos */ + if (TEST_FLAG (AUTODRCFLAG, PCB) && Settings.Mode == LINE_MODE + && Crosshair.AttachedLine.State != STATE_FIRST) + return 0; + + XWarpPointer (GDK_DRAWABLE_XDISPLAY (gport->drawing_area->window), + w_src, w_dst, + 0, 0, 0, 0, + Vx2 (x), Vy2 (y)); + + /* XWarpPointer creates Motion events normally bound to + * EventMoveCrosshair. + * We don't do any updates when EventMoveCrosshair + * is called the next time to prevent from rounding errors + */ + /* FIXME? + * IgnoreMotionEvents = ignore; + */ + } +# endif +#endif + + return 0; +} +/* ------------------------------------------------------------ */ + +static const char dowindows_syntax[] = +"DoWindows(1|2|3|4)\n" +"DoWindows(Layout|Library|Log|Netlist|Preferences)"; + +static const char dowindows_help[] = +"Open various GUI windows."; + +/* %start-doc actions DoWindows + +@table @code + +@item 1 +@itemx Layout +Open the layout window. Since the layout window is always shown +anyway, this has no effect. + +@item 2 +@itemx Library +Open the library window. + +@item 3 +@itemx Log +Open the log window. + +@item 4 +@itemx Netlist +Open the netlist window. + +@item 5 +@itemx Preferences +Open the preferences window. + +@end table + +%end-doc */ static int -About (int argc, char **argv, int x, int y) +DoWindows (int argc, char **argv, int x, int y) { - ghid_dialog_about (); + char *a = argc == 1 ? argv[0] : ""; + + if (strcmp (a, "1") == 0 || strcasecmp (a, "Layout") == 0) + { + } + else if (strcmp (a, "2") == 0 || strcasecmp (a, "Library") == 0) + { + ghid_library_window_show (gport, TRUE); + } + else if (strcmp (a, "3") == 0 || strcasecmp (a, "Log") == 0) + { + ghid_log_window_show (TRUE); + } + else if (strcmp (a, "4") == 0 || strcasecmp (a, "Netlist") == 0) + { + ghid_netlist_window_show (gport, TRUE); + } + else if (strcmp (a, "5") == 0 || strcasecmp (a, "Preferences") == 0) + { + ghid_config_window_show (); + } + else + { + AFAIL (dowindows); + } + + return 0; +} + +/* ------------------------------------------------------------ */ +static const char setunits_syntax[] = +"SetUnits(mm|mil)"; + +static const char setunits_help[] = +"Set the default measurement units."; + +/* %start-doc actions SetUnits + +@table @code + +@item mil +Sets the display units to mils (1/1000 inch). + +@item mm +Sets the display units to millimeters. + +@end table + +%end-doc */ + +static int +SetUnits (int argc, char **argv, int x, int y) +{ + if (argc == 0) + return 0; + if (strcmp (argv[0], "mil") == 0) + Settings.grid_units_mm = 0; + if (strcmp (argv[0], "mm") == 0) + Settings.grid_units_mm = 1; + + ghid_config_handle_units_changed (); + + ghid_set_status_line_label (); + + /* FIXME ? + * lesstif_sizes_reset (); + * lesstif_styles_update_values (); + */ + return 0; +} + +/* ------------------------------------------------------------ */ +static const char popup_syntax[] = +"Popup(MenuName, [Button])"; + +static const char popup_help[] = +"Bring up the popup menu specified by @code{MenuName}.\n" +"If called by a mouse event then the mouse button number\n" +"must be specified as the optional second argument."; + +/* %start-doc actions Popup + +This just pops up the specified menu. The menu must have been defined +as a named subresource of the Popups resource in the menu resource +file. If called as a response to a mouse button click, the mouse +button number must be specified as the second argument. + +%end-doc */ + + +static int +Popup (int argc, char **argv, int x, int y) +{ + GtkWidget *menu; + char *element; + guint button; + + if (argc != 1 && argc != 2) + AFAIL (popup); + + if (argc == 1) + button = 0; + else + button = atoi (argv[1]); + + if ( (element = (char *) malloc ( (strlen (argv[0]) + 2) * sizeof (char))) == NULL ) + { + fprintf (stderr, "Popup(): malloc failed\n"); + exit (1); + } + + sprintf (element, "/%s", argv[0]); + printf ("Loading popup \"%s\". Button = %u\n", element, button); + + menu = gtk_ui_manager_get_widget (ghidgui->ui_manager, element); + free (element); + + if (! GTK_IS_MENU (menu)) + { + Message ("The specified popup menu \"%s\" has not been defined.\n", argv[0]); + return 1; + } + else + { + ghidgui->in_popup = TRUE; + gtk_widget_grab_focus (ghid_port.drawing_area); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, + gtk_get_current_event_time()); + } return 0; } @@ -1533,28 +2197,50 @@ Busy (int argc, char **argv, int x, int y) } HID_Action ghid_main_action_list[] = { - {"About", 0, About, - about_help, about_syntax}, + {"About", 0, About, about_help, about_syntax}, + {"Benchmark", 0, Benchmark}, + {"Busy", 0, Busy}, + {"Center", "Click on a location to center", Center, center_help, center_syntax}, + {"Command", 0, Command}, + {"DoWindows", 0, DoWindows, dowindows_help, dowindows_syntax}, {"Export", 0, Export}, + {"GetXY", "", GetXY, getxy_help, getxy_syntax}, + {"LayerGroupsChanged", 0, LayerGroupsChanged}, + {"LibraryChanged", 0, LibraryChanged}, {"Load", 0, Load}, {"LoadVendor", 0, LoadVendor}, {"PCBChanged", 0, PCBChanged}, - {"RouteStylesChanged", 0, RouteStylesChanged}, - {"LayerGroupsChanged", 0, LayerGroupsChanged}, - {"LibraryChanged", 0, LibraryChanged}, + {"PointCursor", 0, PointCursor}, + {"Popup", 0, Popup, popup_help, popup_syntax}, {"Print", 0, Print}, + {"RouteStylesChanged", 0, RouteStylesChanged}, {"Save", 0, Save}, - {"SwapSides", 0, SwapSides}, - {"Zoom", "Click on zoom focus", Zoom, - zoom_help, zoom_syntax}, - {"Command", 0, Command}, - {"Benchmark", 0, Benchmark}, - {"PointCursor", 0, PointCursor}, - {"Busy", 0, Busy}, + {"SetUnits", 0, SetUnits, setunits_help, setunits_syntax}, + {"SwapSides", 0, SwapSides, swapsides_help, swapsides_syntax}, + {"Zoom", "Click on zoom focus", Zoom, zoom_help, zoom_syntax} }; REGISTER_ACTIONS (ghid_main_action_list) + +static int +flag_flipx (int x) +{ + return ghid_flip_x; +} +static int +flag_flipy (int x) +{ + return ghid_flip_y; +} + +HID_Flag ghid_main_flag_list[] = { + {"flip_x", flag_flipx, 0}, + {"flip_y", flag_flipy, 0} +}; + +REGISTER_FLAGS (ghid_main_flag_list) + #include "dolists.h" /* diff --git a/src/hid/gtk/gui-config.c b/src/hid/gtk/gui-config.c index 71dcb73ad1..08f1e41c24 100644 --- a/src/hid/gtk/gui-config.c +++ b/src/hid/gtk/gui-config.c @@ -1152,9 +1152,7 @@ increment_spin_button_cb (GtkSpinButton * spin, gdouble * dst) value = gtk_spin_button_get_value (spin); *dst = value; /* Not using PCB units */ - if (dst == &Settings.size_increment_mm - || dst == &Settings.size_increment_mil) - ghid_change_selected_update_menu_actions (); + ghidgui->config_modified = TRUE; } diff --git a/src/hid/gtk/gui-output-events.c b/src/hid/gtk/gui-output-events.c index c8ab591e35..42538e4333 100644 --- a/src/hid/gtk/gui-output-events.c +++ b/src/hid/gtk/gui-output-events.c @@ -157,9 +157,16 @@ ghid_port_ranges_zoom (gdouble zoom) gdouble xtmp, ytmp; gint x0, y0; + /* figure out zoom values in that would just make the width fit and + * that would just make the height fit + */ xtmp = (gdouble) PCB->MaxWidth / gport->width; ytmp = (gdouble) PCB->MaxHeight / gport->height; + /* if we've tried to zoom further out than what would make the + * entire board fit or we passed 0, then pick a zoom that just makes + * the board fit. + */ if ((zoom > xtmp && zoom > ytmp) || zoom == 0.0) zoom = (xtmp > ytmp) ? xtmp : ytmp; @@ -200,8 +207,8 @@ ghid_get_coords (const char *msg, int *x, int *y) { if (!ghid_port.has_entered) ghid_get_user_xy (msg); - *x = SIDE_X(gport->view_x); - *y = gport->view_y; + *x = SIDE_X (gport->view_x); + *y = SIDE_Y (gport->view_y); } gboolean @@ -224,7 +231,8 @@ ghid_note_event_location (GdkEventButton * ev) gport->view_x = event_x * gport->zoom + gport->view_x0; gport->view_y = event_y * gport->zoom + gport->view_y0; - moved = MoveCrosshairAbsolute (SIDE_X (gport->view_x), gport->view_y); + moved = MoveCrosshairAbsolute (SIDE_X (gport->view_x), + SIDE_Y (gport->view_y)); if (moved) { AdjustAttachedObjects (); @@ -354,6 +362,8 @@ ghid_idle_cb (gpointer data) ghid_mode_buttons_update (); } ghidgui->settings_mode = Settings.Mode; + + ghid_update_toggle_flags (); return FALSE; } @@ -375,15 +385,12 @@ ghid_port_key_release_cb (GtkWidget * drawing_area, GdkEventKey * kev, return FALSE; } - /* Handle user keys in the output drawing area. - | Note that there are some menu shortcuts in gui-top-window.c and it's - | possible there's overlap with key actions coded here and menu shortcut - | actions. If the menu handles it, we won't see the key and code here - | won't be called. I've commented the cases below, but probably have - | missed some. - | If a method of allowing user defined keys is implemented, it will have - | to deal somehow with the menu shortcuts. - */ +/* Handle user keys in the output drawing area. + * Note that the default is for all hotkeys to be handled by the + * menu accelerators. + * + * Key presses not handled by the menus will show up here. + */ gboolean ghid_port_key_press_cb (GtkWidget * drawing_area, @@ -405,529 +412,23 @@ ghid_port_key_press_cb (GtkWidget * drawing_area, handled = TRUE; /* Start off assuming we handle it */ switch (ksym) { - case GDK_a: - case GDK_A: - if (mk == NONE_PRESSED) - hid_action ("SetSame"); - else - handled = FALSE; - break; - - case GDK_b: - case GDK_B: - if (mk == NONE_PRESSED) - hid_actionl ("Flip", "Object", NULL); - else - handled = FALSE; - break; - - case GDK_c: - case GDK_C: - if (mk == CONTROL_PRESSED) - { - hid_actionl ("PasteBuffer", "Clear", NULL); - hid_actionl ("PasteBuffer", "AddSelected", NULL); - hid_actionl ("Unselect", "All", NULL); - hid_actionl ("Mode", "PasteBuffer", NULL); - } - else - handled = FALSE; - break; - - case GDK_d: - case GDK_D: - if (mk == NONE_PRESSED) - hid_actionl ("Display", "PinOrPadName", NULL); - else - handled = FALSE; - break; - - case GDK_e: - case GDK_E: - if (mk == NONE_PRESSED) /* XXX handled in menu */ - hid_actionl ("DeleteRats", "AllRats", NULL); - else if (mk == SHIFT_PRESSED) - hid_actionl ("DeleteRats", "SelectedRats", NULL); - else - handled = FALSE; - break; - - case GDK_f: - case GDK_F: - if (mk == NONE_PRESSED) - { - hid_actionl ("Connection", "Reset", NULL); - hid_actionl ("Connection", "Find", NULL); - } - else if (mk == SHIFT_PRESSED) - hid_actionl ("Connection", "Reset", NULL); - else if (mk == CONTROL_PRESSED) - hid_actionl ("Connection", "Find", NULL); - else - handled = FALSE; - break; - - case GDK_g: - case GDK_G: - value = Settings.grid_units_mm ? - Settings.grid_increment_mm : Settings.grid_increment_mil; - if (mk == NONE_PRESSED) - arg = g_strdup_printf ("+%f", value); - else if (mk == SHIFT_PRESSED) - arg = g_strdup_printf ("-%f", value); - else - { - handled = FALSE; - break; - } - hid_actionl ("SetValue", "Grid", arg, - Settings.grid_units_mm ? "mm" : "mil", NULL); - g_free (arg); - - /* User set grid may no longer match grid setting menu. - */ - ghid_grid_setting_update_menu_actions (); - break; - - case GDK_h: - case GDK_H: - if (mk == CONTROL_PRESSED) - hid_actionl ("ChangeHole", "Object", NULL); - else if (mk == SHIFT_PRESSED) - hid_actionl ("ToggleHideName", "SelectedElements", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("ToggleHideName", "Object", NULL); - else - handled = FALSE; - break; - - case GDK_j: - case GDK_J: - if (mk == SHIFT_PRESSED) - hid_actionl ("ChangeJoin", "SelectedObjects", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("ChangeJoin", "Object", NULL); - else - handled = FALSE; - break; - - case GDK_k: - case GDK_K: - if (mk == CONTROL_PRESSED || mk == SHIFT_CONTROL_PRESSED) - { - ghid_clear_increment_get_value ((mk == CONTROL_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("ChangeClearSize", "SelectedObjects", arg, units, NULL); - } - else - { - ghid_clear_increment_get_value ((mk == NONE_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("ChangeClearSize", "Object", arg, units, NULL); - } + case GDK_Alt_L: + case GDK_Alt_R: + case GDK_Control_L: + case GDK_Control_R: + case GDK_Shift_L: + case GDK_Shift_R: + case GDK_Shift_Lock: break; - case GDK_l: - case GDK_L: - if (mk == SHIFT_PRESSED) - { - ghid_line_increment_get_value ("-", &arg, &units); - hid_actionl ("SetValue", "LineSize", arg, units, NULL); - } - else if (mk == NONE_PRESSED) - { - ghid_line_increment_get_value ("+", &arg, &units); - hid_actionl ("SetValue", "LineSize", arg, units, NULL); - } - else - handled = FALSE; - break; - - case GDK_m: - case GDK_M: - if (mk == CONTROL_PRESSED) - hid_action ("MarkCrosshair"); - else if (mk == SHIFT_PRESSED) - hid_actionl ("MoveToCurrentLayer", "SelectedObjects", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("MoveToCurrentLayer", "Object", NULL); - else - handled = FALSE; - break; - - case GDK_n: - case GDK_N: - if (mk == SHIFT_PRESSED) - hid_actionl ("AddRats", "Close", NULL); - else - handled = FALSE; - break; - - case GDK_o: - case GDK_O: - if (mk == NONE_PRESSED) /* XXX handled in menu */ - { - hid_actionl ("Atomic", "Save", NULL); - hid_actionl ("DeleteRats", "AllRats", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("AddRats", "AllRats", NULL); - hid_actionl ("Atomic", "Block", NULL); - } - else if (mk == CONTROL_PRESSED) - hid_actionl ("ChangeOctagon", "Object", NULL); - else if (mk == SHIFT_PRESSED) - { - hid_actionl ("Atomic", "Save", NULL); - hid_actionl ("DeleteRats", "AllRats", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("AddRats", "SelectedRats", NULL); - hid_actionl ("Atomic", "Block", NULL); - } - else - handled = FALSE; - break; - - case GDK_p: - case GDK_P: - if (mk == SHIFT_PRESSED) - hid_actionl ("Polygon", "Close", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("Polygon", "PreviousPoint", NULL); - else - handled = FALSE; - break; - - case GDK_q: - case GDK_Q: - if (mk == NONE_PRESSED) - hid_actionl ("ChangeSquare", "ToggleObject", NULL); - else - handled = FALSE; - break; - - case GDK_s: - case GDK_S: - if (mk == MOD1_PRESSED || mk == SHIFT_MOD1_PRESSED) - { - ghid_size_increment_get_value ((mk == MOD1_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("ChangeDrillSize", "Object", arg, units, NULL); - } - else - { - ghid_size_increment_get_value ((mk == NONE_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("ChangeSize", "Object", arg, units, NULL); - } - break; - - case GDK_t: - case GDK_T: - if (mk == SHIFT_PRESSED) - { - ghid_size_increment_get_value ("-", &arg, &units); - hid_actionl ("SetValue", "TextScale", arg, units, NULL); - } - else if (mk == NONE_PRESSED) - { - ghid_size_increment_get_value ("+", &arg, &units); - hid_actionl ("SetValue", "TextScale", arg, units, NULL); - } - else - handled = FALSE; - break; - - case GDK_u: - case GDK_U: - if (mk == NONE_PRESSED) /* XXX handled in menu */ - hid_action ("Undo"); - else - handled = FALSE; - break; - - case GDK_v: - case GDK_V: - if (mk == NONE_PRESSED) - ghid_port_ranges_zoom (0); - else if (mk == MOD1_PRESSED || mk == SHIFT_MOD1_PRESSED) - { - ghid_size_increment_get_value ((mk == MOD1_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("SetValue", "ViaDrillingHole", arg, units, NULL); - } - else if (mk == CONTROL_PRESSED || mk == SHIFT_CONTROL_PRESSED) - { - ghid_size_increment_get_value ((mk == CONTROL_PRESSED) ? "+" : "-", - &arg, &units); - hid_actionl ("SetValue", "ViaSize", arg, units, NULL); - } - else - handled = FALSE; - break; - - case GDK_w: - case GDK_W: - if (mk == SHIFT_PRESSED) - hid_actionl ("AddRats", "SelectedRats", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("AddRats", "AllRats", NULL); - else - handled = FALSE; - break; - - case GDK_z: - case GDK_Z: - if (mk == NONE_PRESSED) /* XXX handled in menu */ - hid_actionl ("SetValue", "Zoom", "-1", NULL); - else /* z handled in menu shortcut */ - handled = FALSE; - break; - - case GDK_bar: - case GDK_backslash: - hid_actionl ("Display", "ToggleThindraw", NULL); - ghid_set_menu_toggle_button (ghidgui->main_actions, - "ToggleThinDraw", TEST_FLAG (THINDRAWFLAG, - PCB)); - break; - - case GDK_Tab: - hid_action ("SwapSides"); - ghid_set_menu_toggle_button (ghidgui->main_actions, - "ToggleViewSolderSide", - Settings.ShowSolderSide); - break; - - case GDK_Escape: - switch (Settings.Mode) - { - case VIA_MODE: - case PASTEBUFFER_MODE: - case TEXT_MODE: - case ROTATE_MODE: - case REMOVE_MODE: - case MOVE_MODE: - case COPY_MODE: - case INSERTPOINT_MODE: - case RUBBERBANDMOVE_MODE: - case THERMAL_MODE: - case LOCK_MODE: - hid_actionl ("Mode", "Arrow", NULL); - break; - - case LINE_MODE: - if (Crosshair.AttachedLine.State == STATE_FIRST) - hid_actionl ("Mode", "Arrow", NULL); - else - hid_actionl ("Mode", "Line", NULL); - break; - - case RECTANGLE_MODE: - if (Crosshair.AttachedBox.State == STATE_FIRST) - hid_actionl ("Mode", "Arrow", NULL); - else - hid_actionl ("Mode", "Rectangle", NULL); - break; - - case POLYGON_MODE: - if (Crosshair.AttachedLine.State == STATE_FIRST) - hid_actionl ("Mode", "Arrow", NULL); - else - hid_actionl ("Mode", "Polygon", NULL); - break; - - case ARC_MODE: - if (Crosshair.AttachedBox.State == STATE_FIRST) - hid_actionl ("Mode", "Arrow", NULL); - else - hid_actionl ("Mode", "Arc", NULL); - break; - - case ARROW_MODE: - break; - - default: - gui->log ("Mode %d not handled by ESC\n", Settings.Mode); - break; - } - - break; - - case GDK_space: - hid_actionl ("Mode", "Arrow", NULL); - break; - - case GDK_colon: - hid_action ("Command"); - break; - - case GDK_period: - hid_actionl ("Display", "Toggle45Degree", NULL); - ghid_set_menu_toggle_button (ghidgui->main_actions, - "Toggle45degree", - TEST_FLAG (ALLDIRECTIONFLAG, PCB)); - break; - - case GDK_slash: - hid_actionl ("Display", "CycleClip", NULL); - break; - - case GDK_Up: - if (mk == CONTROL_PRESSED) - { - hid_actionl ("Display", "Scroll", "8", NULL); - hid_actionl ("Display", "Scroll", "0", NULL); - } - else if (mk == SHIFT_PRESSED) - hid_actionl ("MovePointer", "0", "-10", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("MovePointer", "0", "-1", NULL); - break; - - case GDK_Down: - if (mk == CONTROL_PRESSED) - { - hid_actionl ("Display", "Scroll", "2", NULL); - hid_actionl ("Display", "Scroll", "0", NULL); - } - else if (mk == SHIFT_PRESSED) - hid_actionl ("MovePointer", "0", "10", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("MovePointer", "0", "1", NULL); - break; - - case GDK_Left: - if (mk == CONTROL_PRESSED) - { - hid_actionl ("Display", "Scroll", "4", NULL); - hid_actionl ("Display", "Scroll", "0", NULL); - } - else if (mk == SHIFT_PRESSED) - hid_actionl ("MovePointer", "-10", "0", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("MovePointer", "-1", "0", NULL); - break; - - case GDK_Right: - if (mk == CONTROL_PRESSED) - { - hid_actionl ("Display", "Scroll", "6", NULL); - hid_actionl ("Display", "Scroll", "0", NULL); - } - else if (mk == SHIFT_PRESSED) - hid_actionl ("MovePointer", "10", "0", NULL); - else if (mk == NONE_PRESSED) - hid_actionl ("MovePointer", "1", "0", NULL); - break; - - case GDK_BackSpace: - case GDK_Delete: - if (mk == SHIFT_PRESSED) - { - hid_actionl ("Atomic", "Save", NULL); - hid_actionl ("Connection", "Reset", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("Unselect", "All", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("Connection", "Find", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("Select", "Connection", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_action ("RemoveSelected"); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("Connection", "Reset", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("Unselect", "All", NULL); - hid_actionl ("Atomic", "Block", NULL); - } - else if (mk == NONE_PRESSED) - { - hid_actionl ("Mode", "Save", NULL); - hid_actionl ("Mode", "Remove", NULL); - hid_actionl ("Mode", "Notify", NULL); - hid_actionl ("Mode", "Restore", NULL); - } - break; - - case GDK_Insert: - if (mk == NONE_PRESSED) - hid_actionl ("Mode", "InsertPoint", NULL); - break; - - case GDK_1: - case GDK_2: - case GDK_3: - case GDK_4: - case GDK_5: - case GDK_6: - case GDK_7: - case GDK_8: - case GDK_9: - tmp = ksym - GDK_1; - if (mk == NONE_PRESSED) - ghid_layer_button_select (tmp); - else - handled = FALSE; - break; - - case GDK_F1: - hid_actionl ("Mode", "Via", NULL); - break; - - case GDK_F2: - hid_actionl ("Mode", "Line", NULL); - break; - - case GDK_F3: - hid_actionl ("Mode", "Arc", NULL); - break; - - case GDK_F4: - hid_actionl ("Mode", "Text", NULL); - break; - - case GDK_F5: - hid_actionl ("Mode", "Rectangle", NULL); - break; - - case GDK_F6: - hid_actionl ("Mode", "Polygon", NULL); - break; - - case GDK_F7: - hid_actionl ("Mode", "PasteBuffer", NULL); - break; - - case GDK_F8: - hid_actionl ("Mode", "Remove", NULL); - break; - - case GDK_F9: - hid_actionl ("Mode", "Rotate", NULL); - break; - - case GDK_F10: - hid_actionl ("Mode", "Thermal", NULL); - break; - - case GDK_F11: - hid_actionl ("Mode", "Arrow", NULL); - break; - - case GDK_bracketleft: - hid_actionl ("Mode", "Save", NULL); - hid_actionl ("Mode", "Arrow", NULL); - hid_actionl ("Mode", "Notify", NULL); - break; - - case GDK_bracketright: - hid_actionl ("Mode", "Release", NULL); - hid_actionl ("Mode", "Restore", NULL); - break; default: + gui->log ("keysym %d (0x%x) has not been defined\n", ksym, ksym); handled = FALSE; } + /* FIXME -- since we usually don't make it here, does this code need + to go somewhere else? + */ HideCrosshair (TRUE); AdjustAttachedObjects (); ghid_invalidate_all (); @@ -961,7 +462,7 @@ gboolean ghid_port_button_press_cb (GtkWidget * drawing_area, GdkEventButton * ev, GtkUIManager * ui) { - GtkWidget *menu = gtk_ui_manager_get_widget (ui, "/PopupMenu"); + GtkWidget *menu = gtk_ui_manager_get_widget (ui, "/Popup1"); ModifierKeysState mk; gboolean drag, start_pan = FALSE; diff --git a/src/hid/gtk/gui-top-window.c b/src/hid/gtk/gui-top-window.c index e573676f3a..43895907c2 100644 --- a/src/hid/gtk/gui-top-window.c +++ b/src/hid/gtk/gui-top-window.c @@ -22,7 +22,37 @@ * */ -/* This file written by Bill Wilson for the PCB Gtk port */ +/* #define DEBUG_MENUS */ + +#ifdef DAN_FIXME +TODO: + +- figure out when we need to call this: + ghid_set_status_line_label (); + Everytime? + +- the old quit callback had: + + ghid_config_files_write (); + hid_action ("Quit"); + +- what about stuff like this: + + /* Set to ! because ActionDisplay toggles it */ + Settings.DrawGrid = !gtk_toggle_action_get_active (action); + ghidgui->config_modified = TRUE; + hid_actionl ("Display", "Grid", "", NULL); + ghid_set_status_line_label (); + +- do not forget I can use + if (!ghidgui->toggle_holdoff) + +#endif + +/* This file was originally written by Bill Wilson for the PCB Gtk + * port. It was later heavily modified by Dan McMahill to provide + * user customized menus. +*/ /* gui-top-window.c @@ -41,6 +71,8 @@ #include "config.h" #endif +#include + #include "gtkhid.h" #include "gui.h" #include "hid.h" @@ -59,6 +91,7 @@ #include "error.h" #include "file.h" #include "find.h" +#include "gpcb-menu.h" #include "insert.h" #include "line.h" #include "mymem.h" @@ -68,6 +101,7 @@ #include "rats.h" #include "remove.h" #include "report.h" +#include "resource.h" #include "rotate.h" #include "rubberband.h" #include "search.h" @@ -85,17 +119,217 @@ RCSID ("$Id$"); +/* --------------------------------------------------------------------------- + * local types + */ + +/* Used by the menuitems that are toggle actions */ +typedef struct +{ + const char *actionname; + const char *flagname; + int oldval; + char *xres; +} ToggleFlagType; + +/* Used by the route style buttons and menu */ +typedef struct +{ + GtkWidget *button; + RouteStyleType route_style; + gboolean shown; /* For temp buttons */ +} +RouteStyleButton; + +/* Used by the layer buttons */ +typedef struct +{ + GtkWidget *radio_select_button, + *layer_enable_button, *layer_enable_ebox, *label; + gchar *text; + gint index; +} +LayerButtonSet; + + +/* --------------------------------------------------------------------------- + * local macros + */ + +/* --------------------------------------------------------------------------- + * local prototypes + */ + + +#define N_ROUTE_STYLES (NUM_STYLES + 3) + +static void ghid_load_menus (void); +static void ghid_ui_info_append (const gchar *); +static void ghid_ui_info_indent (int); + +static gchar * new_ui_info; +static size_t new_ui_info_sz = 0; + +/* the array of actions for "normal" menuitems */ +static GtkActionEntry *new_entries = NULL; +static gint menuitem_cnt = 0; + +/* the array of actions for "toggle" menuitems */ +static GtkToggleActionEntry *new_toggle_entries = NULL; +static gint tmenuitem_cnt = 0; + +static Resource **action_resources = NULL; +static Resource **toggle_action_resources = NULL; + +/* actions for the @layerview menuitems */ +static GtkToggleActionEntry layerview_toggle_entries[N_LAYER_BUTTONS]; +static Resource *layerview_resources[N_LAYER_BUTTONS]; + +/* actions for the @layerpick menuitems */ +static GtkToggleActionEntry layerpick_toggle_entries[N_LAYER_BUTTONS]; +static Resource *layerpick_resources[N_LAYER_BUTTONS]; + +/* actions for the @routestyles menuitems */ +static GtkToggleActionEntry routestyle_toggle_entries[N_ROUTE_STYLES]; +static Resource *routestyle_resources[N_ROUTE_STYLES]; + +#define MENUITEM "MenuItem" +#define TMENUITEM "TMenuItem" +#define LAYERPICK "LayerPick" +#define LAYERVIEW "LayerView" +#define ROUTESTYLE "RouteStyle" + + +static ToggleFlagType *tflags = 0; +static int n_tflags = 0; +static int max_tflags = 0; + extern HID ghid_hid; GhidGui _ghidgui, *ghidgui = NULL; - GHidPort ghid_port, *gport; static GdkColor WhitePixel, BlackPixel; static gchar *bg_image_file; + +/* ------------------------------------------------------------------ + * Route style buttons + */ + +/* Make 3 extra route style radio buttons. 2 for the extra Temp route + * styles, and the 3rd is an always invisible button selected when the + * route style settings in use don't match any defined route style (the + * user can hit 'l', 'v', etc keys to change the settings without selecting + * a new defined style. + */ + +static RouteStyleButton route_style_button[N_ROUTE_STYLES]; +static gint route_style_index; + +static GtkWidget *route_style_edit_button; + + +/* ------------------------------------------------------------------ + * note_toggle_flag() + */ + +static void +note_toggle_flag (const char *actionname, char *name) +{ + +#ifdef DEBUG_MENUS + printf ("note_toggle_flag(\"%s\", \"%s\")\n", actionname, name); +#endif + + if (n_tflags >= max_tflags) + { + max_tflags += 20; + tflags = + MyRealloc (tflags, max_tflags * sizeof (ToggleFlagType), + __FUNCTION__); + } + tflags[n_tflags].actionname = actionname; + tflags[n_tflags].flagname = name; + tflags[n_tflags].oldval = -1; + tflags[n_tflags].xres = "none"; + n_tflags++; +} + + +void +ghid_update_toggle_flags () +{ + int i; + + GtkAction *a; + gboolean old_holdoff; + gboolean active; + char tmpnm[40]; + GValue setfalse = { 0 }; + GValue settrue = { 0 }; + GValue setlabel = { 0 }; + + g_value_init (&setfalse, G_TYPE_BOOLEAN); + g_value_init (&settrue, G_TYPE_BOOLEAN); + g_value_set_boolean (&setfalse, FALSE); + g_value_set_boolean (&settrue, TRUE); + g_value_init (&setlabel, G_TYPE_STRING); + + /* mask the callbacks */ + old_holdoff = ghidgui->toggle_holdoff; + ghidgui->toggle_holdoff = TRUE; + + for (i = 0; i < n_tflags; i++) + { + int v = hid_get_flag (tflags[i].flagname); + a = gtk_action_group_get_action (ghidgui->main_actions, tflags[i].actionname); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (a), v? TRUE : FALSE); + tflags[i].oldval = v; + } + + + /* FIXME -- this probably needs to go somewhere else */ +#ifdef notdef + for (i = 0; i < N_LAYER_BUTTONS; i++) + { + sprintf (tmpnm, "%s%d", LAYERVIEW, i); + a = gtk_action_group_get_action (ghidgui->main_actions, tmpnm); + if (a != NULL) + { + g_object_set_property (G_OBJECT (a), "visible", (i >= max_layer && i < MAX_LAYER) ? &setfalse : &settrue); + } + + } +#endif + + for (i = 0; i < N_ROUTE_STYLES; i++) + { + sprintf (tmpnm, "%s%d", ROUTESTYLE, i); + a = gtk_action_group_get_action (ghidgui->main_actions, tmpnm); + if (i >= NUM_STYLES) + { + g_object_set_property (G_OBJECT (a), "visible", &setfalse); + } + + /* Update the toggle states */ + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (route_style_button[i].button)); +#ifdef DEBUG_MENUS + printf ("ghid_update_toggle_flags(): route style %d, value is %d\n", i, active); +#endif + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (a), active); + + } + + g_value_unset (&setfalse); + g_value_unset (&settrue); + g_value_unset (&setlabel); + ghidgui->toggle_holdoff = old_holdoff; + +} + #define N_GRID_SETTINGS 11 #define MM_TO_PCB(mm) ((mm) * 100000 / 25.4) @@ -142,6 +376,7 @@ get_grid_value_index (gboolean allow_fail) gdouble *value; gint i; + printf ("get_grid_value_index()\n"); value = Settings.grid_units_mm ? &grid_mm_values[0] : &grid_mil_values[0]; for (i = 0; i < N_GRID_SETTINGS; ++i, ++value) if (PCB->Grid < *value + 1.0 && PCB->Grid > *value - 1.0) @@ -197,1767 +432,232 @@ top_window_configure_event_cb (GtkWidget * widget, GdkEventConfigure * ev, } -/* ========================================================================= -| Here are the menu callbacks. To use the "Save layout as" menu item as -| an example of Gtk ui_manager menu handling, here's how it would be added: -| 1) In the XML ui_info string, add a menuitem: -| -| which says that a menu item should appear as defined by the -| 'SaveLayoutAs' action. -| 2) So a GtkActionEntry for this must exist in one of the action arrays -| to be loaded into the ui_manager. For this there is the entry: -| { "SaveLayoutAs", NULL, N_("Save layout as"), NULL, NULL, -| G_CALLBACK(save_layout_as_cb) }, -| which connects the menu position (via the name SaveLayoutAs) to the -| text to display and the callback function to call. -| 3) And the callback function must be written. -| -| Actions can be removed, modified and reloaded. This is how the menus -| can be updated, for example, to display grid units appropriate when the -| grid units are toggle from mil<->mm. At toggles, the relevant actions are -| removed, the string to display is updated, and the actions are added -| back in. There are several other similar dynamic menu adjustments here. -| -| Some of the callbacks that need to get a location when invoked from the -| menu need to work differently and not get a location when invoked via -| a keyboard shortcut. That's done by checking shift or control state -| in the callback to determine which indicates keyboard being used. -*/ - -/* ============== FileMenu callbacks =============== */ -static void -save_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Save", "Layout", NULL); - ghid_set_status_line_label (); -} +/* + * This is the main menu callback function. The callback looks at + * the gtk action name to figure out which menuitem was chosen. Then + * it looks up in a table to find the pcb actions which should be + * executed. All menus go through this callback. The tables of + * actions are loaded from the menu resource file at startup. + * + * In addition, all hotkeys go through the menus which means they go + * through here. + */ static void -save_layout_as_cb (GtkAction * action, GHidPort * port) +ghid_menu_cb (GtkAction * action, GHidPort * port) { - hid_actionl ("Save", "LayoutAs", NULL); - ghid_set_status_line_label (); -} - -static void revert_cb(GtkAction *action, GHidPort *port) - { - hid_actionl ("LoadFrom", "Revert", "none", 0); - ghid_set_status_line_label (); - } - - + const gchar * name; + int id = 0; + int vi; + Resource *node = NULL; + static int in_cb = 0; + gboolean old_holdoff; -static void -load_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Load", "Layout", NULL); -} + /* If we don't do this then we can end up in loops where changing + * the state of the toggle actions triggers the callbacks and + * the call back updates the state of the actions. + */ + if (in_cb) + return; + else + in_cb = 1; -static void -load_element_data_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Clear", "", NULL); - hid_actionl ("Load", "ElementTobuffer", NULL); -} + name = gtk_action_get_name (action); -static void -load_layout_data_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Clear", "", NULL); - hid_actionl ("Load", "LayoutTobuffer", NULL); -} + if ( strncmp (name, MENUITEM, strlen (MENUITEM)) == 0) + { + /* This is a "normal" menuitem as opposed to a toggle menuitem + */ + id = atoi (name + strlen (MENUITEM)); + node = action_resources[id]; + } + else if ( strncmp (name, TMENUITEM, strlen (TMENUITEM)) == 0) + { + /* This is a "toggle" menuitem */ + id = atoi (name + strlen (TMENUITEM)); -static void -load_netlist_file_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Load", "Netlist", NULL); -} + /* toggle_holdoff lets us update the state of the menus without + * actually triggering all the callbacks + */ + if (ghidgui->toggle_holdoff == TRUE) + node = NULL; + else + node = toggle_action_resources[id]; + } + else if ( strncmp (name, LAYERPICK, strlen (LAYERPICK)) == 0) + { + id = atoi (name + strlen (LAYERPICK)); -static void -load_vendor_file_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("LoadVendor"); -} + if (ghidgui->toggle_holdoff == TRUE) + node = NULL; + else + node = layerpick_resources[id]; + } + else if ( strncmp (name, LAYERVIEW, strlen (LAYERVIEW)) == 0) + { + id = atoi (name + strlen (LAYERVIEW)); -static void -print_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("Print"); -} + if (ghidgui->toggle_holdoff == TRUE) + node = NULL; + else + node = layerview_resources[id]; + } + else if ( strncmp (name, ROUTESTYLE, strlen (ROUTESTYLE)) == 0) + { + id = atoi (name + strlen (ROUTESTYLE)); + if (ghidgui->toggle_holdoff != TRUE) + ghid_route_style_button_set_active (id); + node = NULL; + } + else + { + fprintf (stderr, "ERROR: ghid_menu_cb(): name = \"%s\" is unknown\n", name); + } + -static void -export_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("Export"); -} +#ifdef DEBUG_MENUS + printf ("ghid_menu_cb(): name = \"%s\", id = %d\n", name, id); +#endif -static void -connections_single_element_cb (GtkAction * action, GHidPort * port) -{ - int x, y; - gui->get_coords ("Press a button at the element's location", &x, &y); - hid_actionl ("Save", "ElementConnections", NULL); -} + /* Now we should have a pointer to the actions to execute */ + if (node != NULL) + { + for (vi = 1; vi < node->c; vi++) + if (resource_type (node->v[vi]) == 10) + { +#ifdef DEBUG_MENUS + printf (" %s\n", node->v[vi].value); +#endif + hid_parse_actions (node->v[vi].value, NULL); + } + } + else { +#ifdef DEBUG_MENUS + printf (" NOOP\n"); +#endif + } -static void -connections_all_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Save", "AllConnections", NULL); -} -static void -connections_unused_pins_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Save", "AllUnusedPins", NULL); + /* + * Now mask off any callbacks and update the state of any toggle + * menuitems. This is where we do things like sync the layer or + * tool checks marks in the menus with the layer or tool buttons + */ + old_holdoff = ghidgui->toggle_holdoff; + ghidgui->toggle_holdoff = TRUE; + ghid_update_toggle_flags (); + ghidgui->toggle_holdoff = old_holdoff; + + in_cb = 0; } -static void -new_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("New"); -} -static void -quit_cb (GtkAction * action, GHidPort * port) -{ - ghid_config_files_write (); - hid_action ("Quit"); -} +/* ============== ViewMenu callbacks =============== */ -/* ============== EditMenu callbacks =============== */ + /* Do grid units handling common to a grid units change from the menu or + | the grid units button. + */ static void -undo_cb (GtkAction * action, GHidPort * port) +handle_grid_units_change (gboolean active) { - hid_action ("Undo"); -} + gchar *grid; + gint i; -static void -redo_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("Redo"); -} + printf ("handle_grid_units_change()\n"); + i = get_grid_value_index (FALSE); + Settings.grid_units_mm = active; + PCB->Grid = Settings.grid_units_mm ? grid_mm_values[i] : grid_mil_values[i]; -static void -clear_undo_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Undo", "ClearList", NULL); -} + ghid_grid_setting_update_menu_actions (); + grid = g_strdup_printf ("%f", PCB->Grid); + hid_actionl ("SetValue", "Grid", grid, "", NULL); + g_free (grid); -static void -edit_text_on_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("ChangeName", "Object", NULL); -} + ghid_config_handle_units_changed (); -static void -edit_name_of_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("ChangeName", "Layout", NULL); + ghid_set_status_line_label (); } static void -edit_name_of_active_layer_cb (GtkAction * action, GHidPort * port) +radio_grid_mil_setting_cb (GtkAction * action, GtkRadioAction * current) { - hid_actionl ("ChangeName", "Layer", NULL); -} - - + gdouble value; + gchar *grid; + gint index; -/* ============== ViewMenu callbacks =============== */ -static void -toggle_draw_grid_cb (GtkToggleAction * action, GHidPort * port) -{ - if (ghidgui->toggle_holdoff) /* If setting initial condition */ + printf ("radio_grid_mil_setting_cb()\n"); + if (ghidgui->toggle_holdoff) return; - - /* Set to ! because ActionDisplay toggles it */ - Settings.DrawGrid = !gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - hid_actionl ("Display", "Grid", "", NULL); + index = gtk_radio_action_get_current_value (current); + value = grid_mil_values[index]; + grid = g_strdup_printf ("%f", value); + hid_actionl ("SetValue", "Grid", grid, "", NULL); + g_free (grid); ghid_set_status_line_label (); } static void -realign_grid_cb (GtkAction * action, GHidPort * port) +radio_grid_mm_setting_cb (GtkAction * action, GtkRadioAction * current) { - int x, y; - gui->get_coords ("Press a button at a grid point", &x, &y); - hid_actionl ("Display", "ToggleGrid", "", NULL); - ghid_set_status_line_label (); -} - -static void -zoom_cb (GtkAction * action, GtkRadioAction * current) -{ - gint px, py; - const gchar *saction = gtk_action_get_name (action); - gdouble zoom_factor; - - zoom_factor = !strcmp (saction, "ZoomIn") ? 0.8 : 1.25; - ghid_get_coords ("Click on zoom focus", &px, &py); - ghid_port_ranges_zoom (gport->zoom * zoom_factor); - ghid_set_status_line_label (); -} - - -static void -toggle_view_solder_side_cb (GtkAction * action, GHidPort * port) -{ - /* If get here from the menu, ask for a locaton. - */ - if (ghidgui->toggle_holdoff) - return; - if (!ghid_shift_is_pressed ()) - { - int x, y; - gui->get_coords (_("Press a button at the desired point"), &x, &y); - } - hid_action ("SwapSides"); - ghid_set_status_line_label (); -} - -static void -toggle_pinout_shows_number_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.ShowNumber = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleName", "", NULL); -} - -static void -pinout_menu_cb (GtkAction * action, GHidPort * port) -{ - if (!ghid_shift_is_pressed ()) - { - int x, y; - gui->get_coords ("Select an element", &x, &y); - } - hid_actionl ("Display", "Pinout", "", NULL); -} - - /* Do grid units handling common to a grid units change from the menu or - | the grid units button. - */ -static void -handle_grid_units_change (gboolean active) -{ - gchar *grid; - gint i; - - i = get_grid_value_index (FALSE); - Settings.grid_units_mm = active; - PCB->Grid = Settings.grid_units_mm ? grid_mm_values[i] : grid_mil_values[i]; - - ghid_grid_setting_update_menu_actions (); - - grid = g_strdup_printf ("%f", PCB->Grid); - hid_actionl ("SetValue", "Grid", grid, "", NULL); - g_free (grid); - - ghid_config_handle_units_changed (); - - ghid_change_selected_update_menu_actions (); - ghid_set_status_line_label (); -} - -static void -toggle_grid_units_cb (GtkToggleAction * action, GHidPort * port) -{ - if (ghidgui->toggle_holdoff) /* If setting initial condition */ - return; - handle_grid_units_change (gtk_toggle_action_get_active (action)); -} - -static void -radio_grid_mil_setting_cb (GtkAction * action, GtkRadioAction * current) -{ - gdouble value; - gchar *grid; - gint index; - - if (ghidgui->toggle_holdoff) - return; - index = gtk_radio_action_get_current_value (current); - value = grid_mil_values[index]; - grid = g_strdup_printf ("%f", value); - hid_actionl ("SetValue", "Grid", grid, "", NULL); - g_free (grid); - ghid_set_status_line_label (); -} - -static void -radio_grid_mm_setting_cb (GtkAction * action, GtkRadioAction * current) -{ - gdouble value; - gchar *grid; - gint index; + gdouble value; + gchar *grid; + gint index; + printf ("radio_grid_mm_setting_cb()\n"); if (ghidgui->toggle_holdoff) return; index = gtk_radio_action_get_current_value (current); value = grid_mm_values[index]; grid = g_strdup_printf ("%f", value); hid_actionl ("SetValue", "Grid", grid, "", NULL); - g_free (grid); - ghid_set_status_line_label (); -} - -static void -radio_displayed_element_name_cb (GtkAction * action, GtkRadioAction * current) -{ - gint value; - static gchar *doit[] = { "Description", "NameOnPCB", "Value" }; - - value = gtk_radio_action_get_current_value (current); - if (value >= 0 && value < 4) - hid_actionl ("Display", doit[value], "", NULL); -} - - - -/* ============== SettingsMenu callbacks =============== */ -static void -toggle_45_degree_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.AllDirectionLines = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "Toggle45Degree", "", NULL); - ghid_set_status_line_label (); -} - -static void -toggle_start_direction_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.SwapStartDirection = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleStartDirection", "", NULL); - ghid_set_status_line_label (); -} - -static void -toggle_orthogonal_moves_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.OrthogonalMoves = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleOrthoMove", "", NULL); - ghid_set_status_line_label (); -} - -static void -toggle_snap_pin_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.SnapPin = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleSnapPin", "", NULL); -} - -static void -toggle_show_DRC_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.ShowDRC = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleShowDRC", "", NULL); -} - -static void -toggle_auto_DRC_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.AutoDRC = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleAutoDRC", "", NULL); -} - -static void -toggle_rubber_band_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.RubberBandMode = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleRubberBandMode", "", NULL); -} - -static void -toggle_unique_names_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.UniqueNames = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleUniqueNames", "", NULL); -} - -static void -toggle_local_ref_cb (GtkAction * action, GHidPort * port) -{ - /* Transient setting, not saved in Settings & not used for new PCB flag. */ - hid_actionl ("Display", "ToggleLocalRef", "", NULL); -} - -static void -toggle_clear_line_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.ClearLine = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleClearLine", "", NULL); -} - -static void -toggle_live_route_cb (GtkToggleAction * action, GHidPort * port) -{ - /* Toggle existing PCB flag and use setting to initialize new PCB flag */ - Settings.liveRouting = gtk_toggle_action_get_active (action); - ghidgui->config_modified = TRUE; - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleLiveRoute", "", NULL); -} - -static void -toggle_thin_draw_cb (GtkAction * action, GHidPort * port) -{ - /* Transient setting, not saved in Settings & not used for new PCB flag. */ - if (!ghidgui->toggle_holdoff) - hid_actionl ("Display", "ToggleThindraw", "", NULL); -} - -static void -toggle_check_planes_cb (GtkAction * action, GHidPort * port) -{ - /* Transient setting, not saved in Settings & not used for new PCB flag. */ - hid_actionl ("Display", "ToggleCheckPlanes", "", NULL); -} - -static void -toggle_vendor_drill_mapping_cb (GtkAction * action, GHidPort * port) -{ - /* Transient setting, not saved in Settings & not used for new PCB flag. */ - hid_action ("ToggleVendor"); -} - -/* ============== SelectMenu callbacks =============== */ -static void -select_all_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "All", NULL); -} - -static void -select_all_connected_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "Connection", NULL); -} - -static void -unselect_all_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Unselect", "All", NULL); -} - -static void -unselect_all_connected_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Unselect", "Connection", NULL); -} - -static void -select_objects_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "ObjectByName", NULL); -} - -static void -select_elements_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "ElementByName", NULL); -} - -static void -select_pads_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "PadByName", NULL); -} - -static void -select_pins_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "PinByName", NULL); -} - -static void -select_text_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "TextByName", NULL); -} - -static void -select_vias_by_name_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "ViaByName", NULL); -} - -static void -auto_place_selected_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("AutoPlaceSelected"); -} - -static void -disperse_all_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("DisperseElements", "All", NULL); -} - -static void -disperse_selected_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("DisperseElements", "Selected", NULL); -} - -static void -move_selected_other_side_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Flip", "SelectedElements", NULL); -} - -static void -remove_selected_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("RemoveSelected"); -} - -static void -convert_selected_to_element_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Select", "Convert", NULL); -} - -static void -optimize_selected_rats_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("DeleteRats", "SelectedRats", NULL); - hid_actionl ("AddRats", "SelectedRats", NULL); -} - - -static void -rip_up_selected_tracks_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("RipUp", "Selected", NULL); -} - - -static void -selected_lines_size_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeSize", "SelectedLines", value, units, NULL); - hid_actionl ("ChangeSize", "SelectedArcs", value, units, NULL); -} - -static void -selected_pads_size_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeSize", "SelectedPads", value, units, NULL); -} - -static void -selected_pins_size_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeSize", "SelectedPins", value, units, NULL); -} - -static void -selected_text_size_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeSize", "SelectedText", value, units, NULL); -} - -static void -selected_vias_size_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeSize", "SelectedVias", value, units, NULL); -} - -static void -selected_vias_drill_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeDrillSize", "SelectedVias", value, units, NULL); -} - -static void -selected_pins_drill_change_cb (GtkAction * action, GHidPort * port) -{ - gchar *value, *units; - - ghid_size_increment_get_value (gtk_action_get_name (action), &value, - &units); - hid_actionl ("ChangeDrillSize", "SelectedPins", value, units, NULL); -} - -static void -selected_change_square_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("ChangeSquare", "SelectedElements", NULL); -} - -static void -selected_change_square_pins_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("ChangeSquare", "SelectedPins", NULL); -} - - -/* ============== BufferMenu callbacks =============== */ -#define PRESS_BUTTON_ELEMENT_PROMPT \ - _("Press a button on a reference point for your selection") - -static void -copy_selection_to_buffer_cb (GtkAction * action, GHidPort * port) -{ - if (!ghid_control_is_pressed ()) - { - int x, y; - gui->get_coords (PRESS_BUTTON_ELEMENT_PROMPT, &x, &y); - } - hid_actionl ("PasteBuffer", "Clear", "", NULL); - hid_actionl ("PasteBuffer", "AddSelected", "", NULL); - hid_actionl ("Mode", "PasteBuffer", NULL); -} - - -static void -cut_selection_to_buffer_cb (GtkAction * action, GHidPort * port) -{ - if (!ghid_control_is_pressed ()) - { - int x, y; - gui->get_coords (PRESS_BUTTON_ELEMENT_PROMPT, &x, &y); - } - hid_actionl ("PasteBuffer", "Clear", "", NULL); - hid_actionl ("PasteBuffer", "AddSelected", "", NULL); - hid_action ("RemoveSelected"); - hid_actionl ("Mode", "PasteBuffer", NULL); -} - -static void -paste_buffer_to_layout_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Mode", "PasteBuffer", NULL); -} - -static void -rotate_buffer_CCW_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Mode", "PasteBuffer", NULL); - hid_actionl ("PasteBuffer", "Rotate", "1", NULL); -} - -static void -rotate_buffer_CW_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Mode", "PasteBuffer", NULL); - hid_actionl ("PasteBuffer", "Rotate", "3", NULL); -} - -static void -mirror_buffer_up_down_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Mode", "PasteBuffer", NULL); - hid_actionl ("PasteBuffer", "Mirror", "", NULL); -} - -static void -mirror_buffer_left_right_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Mode", "PasteBuffer", NULL); - hid_actionl ("PasteBuffer", "Rotate", "1", NULL); - hid_actionl ("PasteBuffer", "Mirror", "", NULL); - hid_actionl ("PasteBuffer", "Rotate", "3", NULL); -} - -/* ============== ConnectsMenu callbacks =============== */ -static void -clear_buffer_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Clear", NULL); -} - -static void -convert_buffer_to_element_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Convert", NULL); -} - -static void -break_buffer_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Restore", NULL); -} - -static void -save_buffer_elements_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("PasteBuffer", "Save", NULL); -} - -static void -radio_select_current_buffer_cb (GtkAction * action, GtkRadioAction * current) -{ - gchar buf[16]; - gint value; - - value = gtk_radio_action_get_current_value (current); - if (value >= 1 && value <= 5) - { - sprintf (buf, "%d", value); - hid_actionl ("PasteBuffer", buf, "", NULL); - } - ghid_set_status_line_label (); -} - - -/* ============== ConnectsMenu callbacks =============== */ -static void -lookup_connection_cb (GtkAction * action, GHidPort * port) -{ - if (!ghid_control_is_pressed ()) - { - int x, y; - gui->get_coords ("Select the object", &x, &y); - } - hid_actionl ("Connection", "Find", NULL); -} - -static void -reset_scanned_pads_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Connection", "ResetPinsViasAndPads", NULL); - ghid_invalidate_all(); -} - -static void -reset_scanned_lines_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Connection", "ResetLinesAndPolygons", NULL); - ghid_invalidate_all(); -} - -static void -reset_all_connections_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Connection", "Reset", NULL); - ghid_invalidate_all(); -} - -static void -optimize_rats_nest_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Atomic", "Save", NULL); - hid_actionl ("DeleteRats", "AllRats", NULL); - hid_actionl ("Atomic", "Restore", NULL); - hid_actionl ("AddRats", "AllRats", NULL); - hid_actionl ("Atomic", "Block", NULL); -} - -static void -erase_rats_nest_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("DeleteRats", "AllRats", NULL); -} - -static void -auto_route_selected_rats_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("AutoRoute", "Selected", NULL); -} - -static void -auto_route_all_rats_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("AutoRoute", "AllRats", NULL); -} - -static void -rip_up_auto_routed_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("RipUp", "All", NULL); -} - -static void -optimize_routes_cb (GtkAction * action, GHidPort * port) -{ - const gchar *saction; - - saction = gtk_action_get_name (action); - if (!strcmp (saction, "AutoOptimize")) - hid_actionl ("DJopt", "auto", NULL); - else if (!strcmp (saction, "Debumpify")) - hid_actionl ("DJopt", "debumpify", NULL); - else if (!strcmp (saction, "Unjaggy")) - hid_actionl ("DJopt", "unjaggy", NULL); - else if (!strcmp (saction, "ViaNudge")) - hid_actionl ("DJopt", "vianudge", NULL); - else if (!strcmp (saction, "ViaTrim")) - hid_actionl ("DJopt", "viatrim", NULL); - else if (!strcmp (saction, "OrthoPull")) - hid_actionl ("DJopt", "orthopull", NULL); - else if (!strcmp (saction, "SimpleOpts")) - hid_actionl ("DJopt", "simple", NULL); - else if (!strcmp (saction, "Miter")) - hid_actionl ("DJopt", "miter", NULL); - - ghid_invalidate_all(); -} - -static void -toggle_only_auto_routed_cb (GtkAction * action, GHidPort * port) -{ - /* Transient setting, not saved in Settings. Not a PCB flag */ - hid_action ("OptAutoOnly"); -} - -static void -design_rule_check_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("DRC"); -} - -static void -apply_vendor_mapping_cb (GtkAction * action, GHidPort * port) -{ - hid_action ("ApplyVendor"); -} - - - -/* ============== InfoMenu callbacks =============== */ -static void -object_report_cb (GtkAction * action, GHidPort * port) -{ - if (!ghid_control_is_pressed ()) - { - int x, y; - gui->get_coords ("Select the object", &x, &y); - } - hid_actionl ("Report", "Object", NULL); -} - -static void -drill_summary_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Report", "DrillReport", NULL); -} - -static void -found_pins_pads_cb (GtkAction * action, GHidPort * port) -{ - hid_actionl ("Report", "FoundPins", NULL); -} - - -/* ============== WindowMenu callbacks =============== */ -static void -about_dialog_cb (GtkAction * action, GHidPort * port) -{ - ghid_dialog_about (); -} - -static void -keyref_window_cb (GtkAction * action, GHidPort * port) -{ - ghid_keyref_window_show (TRUE); -} - -static void -library_window_cb (GtkAction * action, GHidPort * port) -{ - ghid_library_window_show (port, TRUE); -} - -static void -message_window_cb (GtkAction * action, GHidPort * port) -{ - ghid_log_window_show (TRUE); -} - -static void -netlist_window_cb (GtkAction * action, GHidPort * port) -{ - ghid_netlist_window_show (gport, TRUE); -} - -static void -command_entry_cb (GtkAction * action, GHidPort * port) -{ - ghid_handle_user_command (TRUE); -} - - -/* ============== PopupMenu callbacks =============== */ - -static void -radio_select_tool_cb (GtkAction * action, GtkRadioAction * current) -{ - const gchar *saction; - - saction = gtk_action_get_name (GTK_ACTION (current)); - g_message ("Grid setting action: \"%s\"", saction); -} - - - -/* ====================================================================== -| Here are the action entries that connect menuitems to the -| above callbacks. -*/ - -static GtkActionEntry entries[] = { - /* name, stock_id, label, accelerator, tooltip callback */ - {"FileMenu", NULL, N_("File")}, - {"SaveConnectionMenu", NULL, N_("Save connection data of")}, - -/* FileMenu */ - {"SaveLayout", NULL, N_("Save layout"), NULL, NULL, - G_CALLBACK (save_layout_cb)}, - {"SaveLayoutAs", NULL, N_("Save layout as"), NULL, NULL, - G_CALLBACK (save_layout_as_cb)}, - { "Revert", NULL, N_("Revert"), NULL, NULL, G_CALLBACK(revert_cb)}, - {"LoadLayout", NULL, N_("Load layout"), NULL, NULL, - G_CALLBACK (load_layout_cb)}, - {"LoadElementData", NULL, N_("Load element data to paste-buffer"), - NULL, NULL, - G_CALLBACK (load_element_data_cb)}, - {"LoadLayoutData", NULL, N_("Load layout data to paste-buffer"), - NULL, NULL, - G_CALLBACK (load_layout_data_cb)}, - {"LoadNetlistFile", NULL, N_("Load netlist file"), NULL, NULL, - G_CALLBACK (load_netlist_file_cb)}, - {"LoadVendorFile", NULL, N_("Load vendor resource file"), NULL, NULL, - G_CALLBACK (load_vendor_file_cb)}, - {"PrintLayout", NULL, N_("Print layout"), NULL, NULL, - G_CALLBACK (print_layout_cb)}, - {"ExportLayout", NULL, N_("Export layout"), NULL, NULL, - G_CALLBACK (export_layout_cb)}, - {"SingleElement", NULL, N_("a single element"), NULL, NULL, - G_CALLBACK (connections_single_element_cb)}, - {"AllElements", NULL, N_("all elements"), NULL, NULL, - G_CALLBACK (connections_all_elements_cb)}, - {"UnusedPins", NULL, N_("unused pins"), NULL, NULL, - G_CALLBACK (connections_unused_pins_cb)}, - {"NewLayout", NULL, N_("Start new layout"), NULL, NULL, - G_CALLBACK (new_layout_cb)}, - {"Preferences", NULL, N_("Preferences"), NULL, NULL, - G_CALLBACK (ghid_config_window_show)}, - {"Quit", NULL, N_("Quit Program"), NULL, NULL, - G_CALLBACK (quit_cb)}, - -/* EditMenu */ - {"EditMenu", NULL, N_("Edit")}, - {"Undo", NULL, N_("Undo last operation"), - "u", NULL, - G_CALLBACK (undo_cb)}, - {"Redo", NULL, N_("Redo last undone operation"), - "r", NULL, - G_CALLBACK (redo_cb)}, - {"ClearUndo", NULL, N_("Clear undo-buffer"), - "u", NULL, - G_CALLBACK (clear_undo_cb)}, - /* CutSelectionToBuffer CopySelectionToBuffer PasteBufferToLayout - | are in BufferMenu - */ - /* UnselectAll SelectAll are in SelectMenu - */ - {"EditNamesMenu", NULL, N_("Edit name of")}, - {"EditTextOnLayout", NULL, "text on layout", "n", NULL, - G_CALLBACK (edit_text_on_layout_cb)}, - {"EditNameOfLayout", NULL, N_("layout"), NULL, NULL, - G_CALLBACK (edit_name_of_layout_cb)}, - {"EditNameOfActiveLayer", NULL, N_("active layer"), NULL, NULL, - G_CALLBACK (edit_name_of_active_layer_cb)}, - -/* ViewMenu */ - {"ViewMenu", NULL, N_("View")}, - {"RealignGrid", NULL, N_("Realign grid"), NULL, NULL, - G_CALLBACK (realign_grid_cb)}, - {"GridSettingMenu", NULL, N_("Grid setting")}, - /* Some radio actions */ - {"AdjustGridMenu", NULL, N_("Adjust grid")}, - {"ZoomIn", NULL, "Zoom in", - "z", NULL, - G_CALLBACK (zoom_cb)}, - {"ZoomOut", NULL, N_("Zoom out"), - "z", NULL, - G_CALLBACK (zoom_cb)}, - {"DisplayedElementNameMenu", NULL, N_("Displayed element name")}, - /* Radio actions */ - {"PinoutMenu", NULL, N_("Open pinout menu"), - "d", NULL, - G_CALLBACK (pinout_menu_cb)}, - -/* SizesMenu */ - {"SizesMenu", NULL, N_("Sizes")}, - -/* SettingsMenu */ - {"SettingsMenu", NULL, N_("Settings")}, - -/* SelectMenu */ - {"SelectMenu", NULL, N_("Select")}, - {"SelectAll", NULL, N_("Select all objects"), - "a", NULL, - G_CALLBACK (select_all_cb)}, - {"SelectAllConnected", NULL, N_("Select all connected objects"), - NULL, NULL, - G_CALLBACK (select_all_connected_cb)}, - {"UnselectAll", NULL, N_("Unselect all objects"), - "a", NULL, - G_CALLBACK (unselect_all_cb)}, - {"UnselectAllConnected", NULL, N_("Unselect all connected objects"), - NULL, NULL, - G_CALLBACK (unselect_all_connected_cb)}, - {"SelectByNameMenu", NULL, N_("Select by name")}, - {"SelectObjectsByName", NULL, N_("All objects"), NULL, NULL, - G_CALLBACK (select_objects_by_name_cb)}, - {"SelectElementsByName", NULL, N_("Elements"), NULL, NULL, - G_CALLBACK (select_elements_by_name_cb)}, - {"SelectPadsByName", NULL, N_("Pads"), NULL, NULL, - G_CALLBACK (select_pads_by_name_cb)}, - {"SelectPinsByName", NULL, N_("Pins"), NULL, NULL, - G_CALLBACK (select_pins_by_name_cb)}, - {"SelectTextByName", NULL, N_("Text"), NULL, NULL, - G_CALLBACK (select_text_by_name_cb)}, - {"SelectViasByName", NULL, N_("Vias"), NULL, NULL, - G_CALLBACK (select_vias_by_name_cb)}, - {"AutoPlaceSelected", NULL, N_("Auto place selected elements"), - "p", NULL, - G_CALLBACK (auto_place_selected_cb)}, - {"DisperseAllElements", NULL, N_("Disperse all elements"), NULL, NULL, - G_CALLBACK (disperse_all_elements_cb)}, - {"DisperseSelectedElements", NULL, N_("Disperse selected elements"), - NULL, NULL, - G_CALLBACK (disperse_selected_elements_cb)}, - {"MoveSelectedOtherSide", NULL, N_("Move selected elements to other side"), - "b", NULL, - G_CALLBACK (move_selected_other_side_cb)}, - {"RemoveSelected", NULL, N_("Remove selected objects"), NULL, NULL, - G_CALLBACK (remove_selected_cb)}, - {"ConvertSelectionToElement", NULL, N_("Convert selection to element"), - NULL, NULL, - G_CALLBACK (convert_selected_to_element_cb)}, - {"OptimizeSelectedRats", NULL, N_("Optimize selected rats"), NULL, NULL, - G_CALLBACK (optimize_selected_rats_cb)}, - {"AutoRouteSelectedRats", NULL, N_("Auto route selected rats"), - "r", NULL, - G_CALLBACK (auto_route_selected_rats_cb)}, - {"RipUpSelectedTracks", NULL, N_("Rip up selected auto routed tracks"), - NULL, NULL, - G_CALLBACK (rip_up_selected_tracks_cb)}, - {"ChangeSelectedSizeMenu", NULL, N_("Change size of selected objects")}, - /* Actions in change_selected_entries[] to handle dynamic labels */ - {"ChangeSelectedDrillMenu", NULL, - N_("Change drill hole of selected objects")}, - /* Actions in change_selected_entries[] to handle dynamic labels */ - {"ChangeSelectedSquareMenu", NULL, - N_("Change square flag of selected objects")}, - {"ChangeSquareElements", NULL, N_("Elements"), NULL, NULL, - G_CALLBACK (selected_change_square_elements_cb)}, - {"ChangeSquarePins", NULL, N_("Pins"), NULL, NULL, - G_CALLBACK (selected_change_square_pins_cb)}, - -/* BufferMenu */ - {"BufferMenu", NULL, "Buffer"}, - {"CopySelectionToBuffer", NULL, N_("Copy selection to buffer"), - "x", NULL, - G_CALLBACK (copy_selection_to_buffer_cb)}, - {"CutSelectionToBuffer", NULL, N_("Cut selection to buffer"), - "x", NULL, - G_CALLBACK (cut_selection_to_buffer_cb)}, - {"PasteBufferToLayout", NULL, N_("Paste buffer to layout"), - NULL, NULL, - G_CALLBACK (paste_buffer_to_layout_cb)}, - {"RotateBufferCCW", NULL, N_("Rotate buffer 90 deg CCW"), NULL, NULL, - G_CALLBACK (rotate_buffer_CCW_cb)}, - {"RotateBufferCW", NULL, N_("Rotate buffer 90 deg CW"), NULL, NULL, - G_CALLBACK (rotate_buffer_CW_cb)}, - {"MirrorBufferUpDown", NULL, N_("Mirror buffer (up/down)"), NULL, NULL, - G_CALLBACK (mirror_buffer_up_down_cb)}, - {"MirrorBufferLeftRight", NULL, N_("Mirror buffer (left/right)"), - NULL, NULL, - G_CALLBACK (mirror_buffer_left_right_cb)}, - {"ClearBuffer", NULL, N_("Clear buffer"), NULL, NULL, - G_CALLBACK (clear_buffer_cb)}, - {"ConvertBufferToElement", NULL, N_("Convert buffer to element"), - NULL, NULL, - G_CALLBACK (convert_buffer_to_element_cb)}, - {"BreakBufferElements", NULL, N_("Break buffer elements to pieces"), - NULL, NULL, - G_CALLBACK (break_buffer_elements_cb)}, - {"SaveBufferElements", NULL, N_("Save buffer elements to file"), - NULL, NULL, - G_CALLBACK (save_buffer_elements_cb)}, - {"SelectCurrentBufferMenu", NULL, N_("Select current buffer")}, - /* Radio action menu */ - -/* ConnectsMenu */ - {"ConnectsMenu", NULL, "Connects"}, - {"LookupConnections", NULL, N_("Lookup connection to object"), - "f", NULL, - G_CALLBACK (lookup_connection_cb)}, - {"ResetScannedPads", NULL, N_("Reset scanned pads/pins/vias"), NULL, NULL, - G_CALLBACK (reset_scanned_pads_cb)}, - {"ResetScannedLines", NULL, N_("Reset scanned lines/polygons"), NULL, NULL, - G_CALLBACK (reset_scanned_lines_cb)}, - {"ResetAllConnections", NULL, N_("Reset all connections"), - "f", NULL, - G_CALLBACK (reset_all_connections_cb)}, - {"OptimizeRatsNest", NULL, N_("Optimize rats nest"), - "o", NULL, - G_CALLBACK (optimize_rats_nest_cb)}, - {"EraseRatsNest", NULL, N_("Erase rats nest"), - "e", NULL, - G_CALLBACK (erase_rats_nest_cb)}, - {"AutoRouteSelectedRats", NULL, N_("Auto route selected rats"), NULL, NULL, - G_CALLBACK (auto_route_selected_rats_cb)}, - {"AutoRouteAllRats", NULL, N_("Auto route all rats"), NULL, NULL, - G_CALLBACK (auto_route_all_rats_cb)}, - {"RipUpAutoRouted", NULL, N_("Rip up all auto routed tracks"), NULL, NULL, - G_CALLBACK (rip_up_auto_routed_cb)}, - {"OptimizeTracksMenu", NULL, N_("Optimize routed tracks")}, - {"AutoOptimize", NULL, N_("Auto optimize"), - /* "=" */ NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"Debumpify", NULL, N_("Debumpify"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"Unjaggy", NULL, N_("Unjaggy"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"ViaNudge", NULL, N_("Via nudge"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"ViaTrim", NULL, N_("Via trim"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"OrthoPull", NULL, N_("Ortho pull"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"SimpleOpts", NULL, N_("Simple optimizations"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"Miter", NULL, N_("Miter"), NULL, NULL, - G_CALLBACK (optimize_routes_cb)}, - {"DesignRuleCheck", NULL, N_("Design Rule Checker"), NULL, NULL, - G_CALLBACK (design_rule_check_cb)}, - {"ApplyVendorMapping", NULL, N_("Apply vendor drill mapping"), NULL, NULL, - G_CALLBACK (apply_vendor_mapping_cb)}, - -/* InfoMenu */ - {"InfoMenu", NULL, N_("Info")}, - {"ObjectReport", NULL, N_("Generate object report"), - "r", NULL, - G_CALLBACK (object_report_cb)}, - {"DrillSummary", NULL, N_("Generate drill summary"), NULL, NULL, - G_CALLBACK (drill_summary_cb)}, - {"FoundPinsPads", NULL, N_("Report found pins/pads"), NULL, NULL, - G_CALLBACK (found_pins_pads_cb)}, - -/* WindowMenu */ - {"WindowMenu", NULL, N_("Window")}, - {"LibraryWindow", NULL, N_("Library"), NULL, NULL, - G_CALLBACK (library_window_cb)}, - {"MessageLogWindow", NULL, N_("Message Log"), NULL, NULL, - G_CALLBACK (message_window_cb)}, - {"NetlistWindow", NULL, N_("Netlist"), NULL, NULL, - G_CALLBACK (netlist_window_cb)}, - {"CommandWindow", NULL, N_("Command Entry"), NULL, NULL, - G_CALLBACK (command_entry_cb)}, - {"KeyrefWindow", NULL, N_("Key Reference"), NULL, NULL, - G_CALLBACK (keyref_window_cb)}, - {"AboutDialog", NULL, N_("About"), NULL, NULL, - G_CALLBACK (about_dialog_cb)}, - -/* PopupMenu */ - {"SelectionOperationMenu", NULL, N_("Operations on selections")}, - {"LocationOperationMenu", NULL, N_("Operations on this location")}, - {"SelectToolMenu", NULL, N_("Select tool")}, - -}; - -static gint n_entries = G_N_ELEMENTS (entries); - - - - /* These get NULL labels because labels are dynamically set in - | ghid_change_selected_update_menu_actions() - */ -static GtkActionEntry change_selected_entries[] = { - /* name, stock_id, label, accelerator, tooltip callback */ - {"-LinesChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_lines_size_change_cb)}, - {"+LinesChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_lines_size_change_cb)}, - {"-PadsChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pads_size_change_cb)}, - {"+PadsChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pads_size_change_cb)}, - {"-PinsChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pins_size_change_cb)}, - {"+PinsChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pins_size_change_cb)}, - {"-TextChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_text_size_change_cb)}, - {"+TextChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_text_size_change_cb)}, - {"-ViasChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_vias_size_change_cb)}, - {"+ViasChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_vias_size_change_cb)}, - - {"-ViasDrillChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_vias_drill_change_cb)}, - {"+ViasDrillChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_vias_drill_change_cb)}, - {"-PinsDrillChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pins_drill_change_cb)}, - {"+PinsDrillChange", NULL, NULL, NULL, NULL, - G_CALLBACK (selected_pins_drill_change_cb)}, -}; - -static gint n_change_selected_entries = -G_N_ELEMENTS (change_selected_entries); - - -static GtkRadioActionEntry radio_grid_mil_setting_entries[] = { - /* name, stock_id, label, accelerator, tooltip, value */ - {"grid-user", NULL, "user value", NULL, NULL, 0}, - {"grid0", NULL, "0.1 mil", NULL, NULL, 0}, - {"grid1", NULL, "0.2 mil", NULL, NULL, 1}, - {"grid2", NULL, "0.5 mil", NULL, NULL, 2}, - {"grid3", NULL, "1 mil", NULL, NULL, 3}, - {"grid4", NULL, "2 mil", NULL, NULL, 4}, - {"grid5", NULL, "5 mil", NULL, NULL, 5}, - {"grid6", NULL, "10 mil", NULL, NULL, 6}, - {"grid7", NULL, "20 mil", NULL, NULL, 7}, - {"grid8", NULL, "25 mil", NULL, NULL, 8}, - {"grid9", NULL, "50 mil", NULL, NULL, 9}, - {"grid10", NULL, "100 mil", NULL, NULL, 10} -}; - -static gint n_radio_grid_mil_setting_entries - = G_N_ELEMENTS (radio_grid_mil_setting_entries); - - -static GtkRadioActionEntry radio_grid_mm_setting_entries[] = { - /* name, stock_id, label, accelerator, tooltip, value */ - {"grid-user", NULL, "user value", NULL, NULL, 0}, - {"grid0", NULL, "0.002 mm", NULL, NULL, 0}, - {"grid1", NULL, "0.005 mm", NULL, NULL, 1}, - {"grid2", NULL, "0.01 mm", NULL, NULL, 2}, - {"grid3", NULL, "0.02 mm", NULL, NULL, 3}, - {"grid4", NULL, "0.05 mm", NULL, NULL, 4}, - {"grid5", NULL, "0.1 mm", NULL, NULL, 5}, - {"grid6", NULL, "0.2 mm", NULL, NULL, 6}, - {"grid7", NULL, "0.25 mm", NULL, NULL, 7}, - {"grid8", NULL, "0.5 mm", NULL, NULL, 8}, - {"grid9", NULL, "1 mm", NULL, NULL, 9}, - {"grid10", NULL, "2 mm", NULL, NULL, 10}, -}; - -static gint n_radio_grid_mm_setting_entries - = G_N_ELEMENTS (radio_grid_mm_setting_entries); - - -static GtkRadioActionEntry radio_displayed_element_name_entries[] = { - /* name, stock_id, label, accelerator, tooltip, value */ - {"Description", NULL, N_("Description"), NULL, NULL, 0}, - {"ReferenceDesignator", NULL, N_("Reference designator"), - NULL, NULL, 1}, - {"Value", NULL, N_("Value"), NULL, NULL, 2} -}; - -static gint n_radio_displayed_element_name_entries - = G_N_ELEMENTS (radio_displayed_element_name_entries); - - -static GtkRadioActionEntry radio_select_current_buffer_entries[] = { - /* name, stock_id, label, accelerator, tooltip, value */ - {"SelectBuffer1", NULL, "#1", "1", NULL, 1}, - {"SelectBuffer2", NULL, "#2", "2", NULL, 2}, - {"SelectBuffer3", NULL, "#3", "3", NULL, 3}, - {"SelectBuffer4", NULL, "#4", "4", NULL, 4}, - {"SelectBuffer5", NULL, "#5", "5", NULL, 5} -}; - -static gint n_radio_select_current_buffer_entries - = G_N_ELEMENTS (radio_select_current_buffer_entries); - -static GtkRadioActionEntry radio_select_tool_entries[] = { - /* name, stock_id, label, accelerator, tooltip, value */ - {"SelectLineTool", NULL, N_("Line"), NULL, NULL, 0}, - {"SelectViaTool", NULL, N_("Via"), NULL, NULL, 0}, - {"SelectRectangleTool", NULL, N_("Rectangle"), NULL, NULL, 0}, - {"SelectSelectionTool", NULL, N_("Selection"), NULL, NULL, 0}, - {"SelectTextTool", NULL, N_("Text"), NULL, NULL, 0}, - {"SelectPannerTool", NULL, N_("Panner"), NULL, NULL, 0}, -}; - -static gint n_radio_select_tool_entries - = G_N_ELEMENTS (radio_select_tool_entries); - - -static GtkToggleActionEntry toggle_entries[] = { - /* name, stock_id, label, accelerator, tooltip, callback, is_active */ - - /* ViewMenu */ - {"ToggleDrawGrid", NULL, N_("Enable visible grid"), NULL, NULL, - G_CALLBACK (toggle_draw_grid_cb), FALSE}, - {"ToggleGridUnitsMm", NULL, N_("Enable millimeter grid units"), NULL, NULL, - G_CALLBACK (toggle_grid_units_cb), FALSE}, - {"ToggleViewSolderSide", NULL, N_("Enable view solder side"), - NULL, NULL, - G_CALLBACK (toggle_view_solder_side_cb)}, - {"TogglePinoutShowsNumber", NULL, N_("Enable pinout shows number"), - NULL, NULL, - G_CALLBACK (toggle_pinout_shows_number_cb)}, - -/* SettingsMenu */ - {"Toggle45degree", NULL, N_("All direction lines"), - NULL /* gtk wont take "." */ , NULL, - G_CALLBACK (toggle_45_degree_cb)}, - {"ToggleStartDirection", NULL, N_("Auto swap line start angle"), - NULL, NULL, - G_CALLBACK (toggle_start_direction_cb)}, - {"ToggleOrthogonalMoves", NULL, N_("Orthogonal moves"), NULL, NULL, - G_CALLBACK (toggle_orthogonal_moves_cb)}, - {"ToggleSnapPin", NULL, N_("Crosshair snaps to pins and pads"), - NULL, NULL, - G_CALLBACK (toggle_snap_pin_cb)}, - {"ToggleShowDRC", NULL, N_("Crosshair shows DRC clearance"), - NULL, NULL, - G_CALLBACK (toggle_show_DRC_cb)}, - {"ToggleAutoDrC", NULL, N_("Auto enforce DRC clearance"), - NULL, NULL, - G_CALLBACK (toggle_auto_DRC_cb)}, - {"ToggleRubberBand", NULL, N_("Rubber band mode"), NULL, NULL, - G_CALLBACK (toggle_rubber_band_cb)}, - {"ToggleUniqueNames", NULL, N_("Require unique element names"), - NULL, NULL, - G_CALLBACK (toggle_unique_names_cb)}, - {"ToggleLocalRef", NULL, N_("Auto zero delta measurements"), - NULL, NULL, - G_CALLBACK (toggle_local_ref_cb)}, - {"ToggleClearLine", NULL, N_("New lines, arcs clear polygons"), - NULL, NULL, - G_CALLBACK (toggle_clear_line_cb)}, - {"ToggleLiveRoute", NULL, N_("Show autorouter trials"), NULL, NULL, - G_CALLBACK (toggle_live_route_cb)}, - {"ToggleThinDraw", NULL, N_("Thin line draw"), - NULL /* Gtk can't take '\' or '|' */ , NULL, - G_CALLBACK (toggle_thin_draw_cb)}, - {"ToggleCheckPlanes", NULL, N_("Check polygons"), NULL, NULL, - G_CALLBACK (toggle_check_planes_cb)}, - {"ToggleVendorDrillMapping", NULL, N_("Vendor drill mapping"), - NULL, NULL, - G_CALLBACK (toggle_vendor_drill_mapping_cb)}, - -/* ConnectsMenu */ - {"ToggleOnlyAutoRoutedNets", NULL, N_("Enable only autorouted nets"), - NULL, NULL, - G_CALLBACK (toggle_only_auto_routed_cb)}, -}; - -static gint n_toggle_entries = G_N_ELEMENTS (toggle_entries); - - - -/* ====================================================================== -| Here is the ui_manager string that defines the order of items displayed -| in the menus. -*/ - -static const gchar *ui_info = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " -/*" "*/ - " " - " " - " " - " " " " -/*" "*/ -/*" "*/ - " " -/*" "*/ -/*" "*/ -/*" "*/ -/*" "*/ -/*" "*/ - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " -#if 0 - " " - " " - " " - " " -#endif - " " ""; - - - /* When user toggles grid units mil<->mm or when a new layout is loaded - | that might use different units, the "Change size of selected" menu - | displayed text muxt be changed. - */ -void -ghid_change_selected_update_menu_actions (void) -{ - gchar size_buf[32], buf[128]; - - if (ghidgui->change_selected_actions) - { - /* Remove the existing change selected actions from the menu. - */ - gtk_ui_manager_remove_action_group (ghidgui->ui_manager, - ghidgui->change_selected_actions); - g_object_unref (ghidgui->change_selected_actions); - } - - /* And create a new action group for the changed selection actions. - */ - ghidgui->change_selected_actions = - gtk_action_group_new ("ChangeSelActions"); - gtk_action_group_set_translation_domain (ghidgui->change_selected_actions, - NULL); - gtk_ui_manager_insert_action_group (ghidgui->ui_manager, - ghidgui->change_selected_actions, 0); - - /* Update the labels to match current units and increment values settings. - */ - if (Settings.grid_units_mm) - snprintf (size_buf, sizeof (size_buf), "%.2f mm", - Settings.size_increment_mm); - else - snprintf (size_buf, sizeof (size_buf), "%.0f mil", - Settings.size_increment_mil); - - snprintf (buf, sizeof (buf), _("Decrement lines by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[0].label, buf); - - snprintf (buf, sizeof (buf), _("Increment lines by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[1].label, buf); - - snprintf (buf, sizeof (buf), _("Decrement pads by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[2].label, buf); - - snprintf (buf, sizeof (buf), _("Increment pads by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[3].label, buf); - - snprintf (buf, sizeof (buf), _("Decrement pins by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[4].label, buf); - - snprintf (buf, sizeof (buf), _("Increment pins by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[5].label, buf); - - snprintf (buf, sizeof (buf), _("Decrement text by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[6].label, buf); + g_free (grid); + ghid_set_status_line_label (); +} - snprintf (buf, sizeof (buf), _("Increment text by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[7].label, buf); - snprintf (buf, sizeof (buf), _("Decrement vias by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[8].label, buf); +static GtkRadioActionEntry radio_grid_mil_setting_entries[] = { + /* name, stock_id, label, accelerator, tooltip, value */ + {"grid-user", NULL, "user value", NULL, NULL, 0}, + {"grid0", NULL, "0.1 mil", NULL, NULL, 0}, + {"grid1", NULL, "0.2 mil", NULL, NULL, 1}, + {"grid2", NULL, "0.5 mil", NULL, NULL, 2}, + {"grid3", NULL, "1 mil", NULL, NULL, 3}, + {"grid4", NULL, "2 mil", NULL, NULL, 4}, + {"grid5", NULL, "5 mil", NULL, NULL, 5}, + {"grid6", NULL, "10 mil", NULL, NULL, 6}, + {"grid7", NULL, "20 mil", NULL, NULL, 7}, + {"grid8", NULL, "25 mil", NULL, NULL, 8}, + {"grid9", NULL, "50 mil", NULL, NULL, 9}, + {"grid10", NULL, "100 mil", NULL, NULL, 10} +}; - snprintf (buf, sizeof (buf), _("Increment vias by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[9].label, buf); +static gint n_radio_grid_mil_setting_entries + = G_N_ELEMENTS (radio_grid_mil_setting_entries); - /* -- Drill size changes */ - snprintf (buf, sizeof (buf), _("Decrement vias by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[10].label, buf); - snprintf (buf, sizeof (buf), _("Increment vias by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[11].label, buf); +static GtkRadioActionEntry radio_grid_mm_setting_entries[] = { + /* name, stock_id, label, accelerator, tooltip, value */ + {"grid-user", NULL, "user value", NULL, NULL, 0}, + {"grid0", NULL, "0.002 mm", NULL, NULL, 0}, + {"grid1", NULL, "0.005 mm", NULL, NULL, 1}, + {"grid2", NULL, "0.01 mm", NULL, NULL, 2}, + {"grid3", NULL, "0.02 mm", NULL, NULL, 3}, + {"grid4", NULL, "0.05 mm", NULL, NULL, 4}, + {"grid5", NULL, "0.1 mm", NULL, NULL, 5}, + {"grid6", NULL, "0.2 mm", NULL, NULL, 6}, + {"grid7", NULL, "0.25 mm", NULL, NULL, 7}, + {"grid8", NULL, "0.5 mm", NULL, NULL, 8}, + {"grid9", NULL, "1 mm", NULL, NULL, 9}, + {"grid10", NULL, "2 mm", NULL, NULL, 10}, +}; - snprintf (buf, sizeof (buf), _("Decrement pins by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[12].label, buf); +static gint n_radio_grid_mm_setting_entries + = G_N_ELEMENTS (radio_grid_mm_setting_entries); - snprintf (buf, sizeof (buf), _("Increment pins by %s"), size_buf); - dup_string ((gchar **) & change_selected_entries[13].label, buf); - /* And add the actions with new labels back in. - */ - gtk_action_group_add_actions (ghidgui->change_selected_actions, - change_selected_entries, - n_change_selected_entries, &Output); -} /* Grid setting labels must also match user and new layout unit changes. */ @@ -2010,49 +710,6 @@ ghid_grid_setting_update_menu_actions (void) } - /* When a new layout is loaded, must set the radio state to the current - | "Displayed element name". Now I unload and reload the actions so - | an initial value can be set, but there must be a better way? - */ -static void -update_displayed_name_actions (void) -{ - gint i; - - if (ghidgui->displayed_name_actions) - { - /* Remove the existing radio actions from the menu. - */ - gtk_ui_manager_remove_action_group (ghidgui->ui_manager, - ghidgui->displayed_name_actions); - g_object_unref (ghidgui->displayed_name_actions); - } - - /* And add back actions just to get the initial one set. - */ - ghidgui->displayed_name_actions = gtk_action_group_new ("DispNameActions"); - gtk_action_group_set_translation_domain (ghidgui->displayed_name_actions, - NULL); - gtk_ui_manager_insert_action_group (ghidgui->ui_manager, - ghidgui->displayed_name_actions, 0); - - /* Get the index of the radio button to set - */ - if (TEST_FLAG (DESCRIPTIONFLAG, PCB)) - i = 0; - else if (TEST_FLAG (NAMEONPCBFLAG, PCB)) - i = 1; - else - i = 2; - - gtk_action_group_add_radio_actions (ghidgui->displayed_name_actions, - radio_displayed_element_name_entries, - n_radio_displayed_element_name_entries, - i, - G_CALLBACK - (radio_displayed_element_name_cb), - NULL); -} void ghid_set_menu_toggle_button (GtkActionGroup * ag, gchar * name, @@ -2085,81 +742,7 @@ ghid_sync_with_new_layout (void) old_holdoff = ghidgui->toggle_holdoff; ghidgui->toggle_holdoff = TRUE; - action = - gtk_action_group_get_action (ghidgui->main_actions, "ToggleDrawGrid"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - Settings.DrawGrid); -/* g_object_set(action, "sensitive", Settings.XXX, NULL); */ - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleGridUnitsMm"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - Settings.grid_units_mm); - - /* Toggle actions in the menu which set a PCB flag must be set to - | the new layout PCB flag states. Transient toggle buttons which - | do not set a PCB flag don't need setting here. - */ - action = gtk_action_group_get_action (ghidgui->main_actions, - "TogglePinoutShowsNumber"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (SHOWNUMBERFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "Toggle45degree"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (ALLDIRECTIONFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleRubberBand"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (RUBBERBANDFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleStartDirection"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (SWAPSTARTDIRFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleUniqueNames"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (UNIQUENAMEFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleSnapPin"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (SNAPPINFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleClearLine"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (CLEARNEWFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleOrthogonalMoves"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (ORTHOMOVEFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleLiveRoute"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (LIVEROUTEFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleShowDRC"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (SHOWDRCFLAG, PCB)); - - action = gtk_action_group_get_action (ghidgui->main_actions, - "ToggleAutoDrC"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), - TEST_FLAG (AUTODRCFLAG, PCB)); - - /* Not sure if I can set a radio button without loading actions, so - | load the actions. - */ - ghid_grid_setting_update_menu_actions (); - update_displayed_name_actions (); + /* FIXME - need toggle_holdoff? Need other calls to sync here? */ ghidgui->toggle_holdoff = old_holdoff; @@ -2167,7 +750,7 @@ ghid_sync_with_new_layout (void) ghid_route_style_button_set_active (0); ghid_config_handle_units_changed (); - ghid_change_selected_update_menu_actions (); + ghid_set_status_line_label (); } @@ -2254,37 +837,196 @@ ghid_init_toggle_states (void) ghid_set_status_line_label (); } +/* --------------------------------------------------------------------------- + * + * layer_process() + * + * Takes the index into the layers and produces the text string for + * the layer and if the layer is currently visible or not. This is + * used by a couple of functions. + * + */ +static void +layer_process (gchar **color_string, char **text, int *set, int i) +{ + int tmp; + char *tmps; + gchar *tmpc; + + /* cheap hack to let users pass in NULL for either text or set if + * they don't care about the result + */ + + if (color_string == NULL) + color_string = &tmpc; + + if (text == NULL) + text = &tmps; + + if (set == NULL) + set = &tmp; + + switch (i) + { + case LAYER_BUTTON_SILK: + *color_string = PCB->ElementColor; + *text = _( "silk"); + *set = PCB->ElementOn; + break; + case LAYER_BUTTON_RATS: + *color_string = PCB->RatColor; + *text = _( "rat lines"); + *set = PCB->RatOn; + break; + case LAYER_BUTTON_PINS: + *color_string = PCB->PinColor; + *text = _( "pins/pads"); + *set = PCB->PinOn; + break; + case LAYER_BUTTON_VIAS: + *color_string = PCB->ViaColor; + *text = _( "vias"); + *set = PCB->ViaOn; + break; + case LAYER_BUTTON_FARSIDE: + *color_string = PCB->InvisibleObjectsColor; + *text = _( "far side"); + *set = PCB->InvisibleObjectsOn; + break; + case LAYER_BUTTON_MASK: + *color_string = PCB->MaskColor; + *text = _( "solder mask"); + *set = TEST_FLAG (SHOWMASKFLAG, PCB); + break; + default: /* layers */ + *color_string = PCB->Data->Layer[i].Color; + *text = UNKNOWN (PCB->Data->Layer[i].Name); + *set = PCB->Data->Layer[i].On; + break; + } +} + /* * The intial loading of all actions at startup. */ static void +ghid_make_programmed_menu_actions () +{ + int i; + gchar * text; + + Resource *ar; + char av[30]; + + for (i = 0; i < N_LAYER_BUTTONS; i++) + { + layer_process (NULL, &text, NULL, i); +#ifdef DEBUG_MENUS + printf ("ghid_make_programmed_menu_actions(): Added #%2d \"%s\". max_layer = %d, MAX_LAYER = %d\n", i, text, max_layer, MAX_LAYER); +#endif + /* name, stock_id, label, accelerator, tooltip, callback */ + layerview_toggle_entries[i].name = g_strdup_printf ("%s%d", LAYERVIEW, i); + layerview_toggle_entries[i].stock_id = NULL; + layerview_toggle_entries[i].label = g_strdup (text); + layerview_toggle_entries[i].accelerator = NULL; + layerview_toggle_entries[i].tooltip = NULL; + layerview_toggle_entries[i].callback = G_CALLBACK (ghid_menu_cb); + layerview_toggle_entries[i].is_active = FALSE; + + ar = resource_create (0); + sprintf (av, "ToggleView(%d)", i + 1); + resource_add_val (ar, 0, strdup (av), 0); + resource_add_val (ar, 0, strdup (av), 0); + ar->flags |= FLAG_V; + layerview_resources[i] = ar; + + /* name, stock_id, label, accelerator, tooltip, callback */ + layerpick_toggle_entries[i].name = g_strdup_printf ("%s%d", LAYERPICK, i); + layerpick_toggle_entries[i].stock_id = NULL; + layerpick_toggle_entries[i].label = g_strdup (text); + layerpick_toggle_entries[i].accelerator = NULL; + layerpick_toggle_entries[i].tooltip = NULL; + layerpick_toggle_entries[i].callback = G_CALLBACK (ghid_menu_cb); + layerpick_toggle_entries[i].is_active = FALSE; + + ar = resource_create (0); + switch (i) + { + case LAYER_BUTTON_SILK: + sprintf (av, "SelectLayer(Silk) LayersChanged()"); + break; + case LAYER_BUTTON_RATS: + sprintf (av, "SelectLayer(Rats) LayersChanged()"); + break; + default: + if (i <= 8) + layerpick_toggle_entries[i].accelerator = + g_strdup_printf ("%d", i + 1); + + sprintf (av, "SelectLayer(%d) LayersChanged()", + i + 1); + + break; + } + resource_add_val (ar, 0, strdup (av), 0); + resource_add_val (ar, 0, strdup (av), 0); + ar->flags |= FLAG_V; + layerpick_resources[i] = ar; + } + + for (i = 0; i < N_ROUTE_STYLES; i++) + { + routestyle_toggle_entries[i].name = g_strdup_printf ("%s%d", ROUTESTYLE, i); + routestyle_toggle_entries[i].stock_id = NULL; + if (i < NUM_STYLES && PCB) + { + routestyle_toggle_entries[i].label = g_strdup ( (PCB->RouteStyle)[i].Name); + } + else + { + routestyle_toggle_entries[i].label = g_strdup (routestyle_toggle_entries[i].name); + } + routestyle_toggle_entries[i].accelerator = NULL; + routestyle_toggle_entries[i].tooltip = NULL; + routestyle_toggle_entries[i].callback = G_CALLBACK (ghid_menu_cb); + routestyle_toggle_entries[i].is_active = FALSE; + + ar = resource_create (0); + sprintf (av, "RouteStyle(%d)", i + 1); + resource_add_val (ar, 0, strdup (av), 0); + resource_add_val (ar, 0, strdup (av), 0); + ar->flags |= FLAG_V; + routestyle_resources[i] = ar; + + // FIXME + //sprintf (av, "current_style,%d", i + 1); + //note_toggle_flag (routestyle_toggle_entries[i].name, strdup (av)); + + } +} + +static void make_menu_actions (GtkActionGroup * actions, GHidPort * port) { - gtk_action_group_add_actions (actions, entries, n_entries, port); + gtk_action_group_add_actions (actions, new_entries, menuitem_cnt, port); - /* Handle menu actions with dynamic content. - */ - ghid_change_selected_update_menu_actions (); - ghid_grid_setting_update_menu_actions (); - update_displayed_name_actions (); - - gtk_action_group_add_radio_actions (actions, - radio_select_current_buffer_entries, - n_radio_select_current_buffer_entries, - 0, - G_CALLBACK - (radio_select_current_buffer_cb), NULL); - - gtk_action_group_add_radio_actions (actions, - radio_select_tool_entries, - n_radio_select_tool_entries, - 0, - G_CALLBACK (radio_select_tool_cb), - NULL); + gtk_action_group_add_toggle_actions (actions, new_toggle_entries, + tmenuitem_cnt, port); + + ghid_make_programmed_menu_actions (); + + gtk_action_group_add_toggle_actions (actions, + layerpick_toggle_entries, + N_LAYER_BUTTONS, port); + + gtk_action_group_add_toggle_actions (actions, + layerview_toggle_entries, + N_LAYER_BUTTONS, port); gtk_action_group_add_toggle_actions (actions, - toggle_entries, n_toggle_entries, - port); + routestyle_toggle_entries, + N_ROUTE_STYLES, port); + } @@ -2315,20 +1057,18 @@ make_top_menubar (GtkWidget * hbox, GHidPort * port) make_menu_actions (actions, port); gtk_ui_manager_insert_action_group (ui, actions, 0); + gtk_window_add_accel_group (GTK_WINDOW (gport->top_window), gtk_ui_manager_get_accel_group (ui)); - /* For user customization, we could add - | gtk_menu_item_set_accel_path(), gtk_accel_map_save (), etc - | But probably can't do this because of command combo box interaction. - */ - - if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error)) + if (!gtk_ui_manager_add_ui_from_string (ui, new_ui_info, -1, &error)) { g_message ("building menus failed: %s", error->message); g_error_free (error); } + gtk_ui_manager_set_add_tearoffs (ui, TRUE); + gtk_container_add (GTK_CONTAINER (frame), gtk_ui_manager_get_widget (ui, "/MenuBar")); } @@ -2465,15 +1205,6 @@ make_cursor_position_labels (GtkWidget * hbox, GHidPort * port) /* ------------------------------------------------------------------ | Handle the layer buttons. */ -typedef struct -{ - GtkWidget *radio_select_button, - *layer_enable_button, *layer_enable_ebox, *label; - gchar *text; - gint index; -} -LayerButtonSet; - static LayerButtonSet layer_buttons[N_LAYER_BUTTONS]; static gint layer_select_button_index; @@ -2485,10 +1216,13 @@ static void layer_select_button_cb (GtkWidget * widget, LayerButtonSet * lb) { gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)); + static gboolean in_cb = FALSE; - if (!active || layer_select_button_cb_hold_off) + if (!active || layer_select_button_cb_hold_off || in_cb) return; + in_cb = TRUE; + PCB->SilkActive = (lb->index == LAYER_BUTTON_SILK); PCB->RatDraw = (lb->index == LAYER_BUTTON_RATS); @@ -2497,7 +1231,14 @@ layer_select_button_cb (GtkWidget * widget, LayerButtonSet * lb) layer_select_button_index = lb->index; + layer_select_button_cb_hold_off = TRUE; + layer_enable_button_cb_hold_off = TRUE; + ghid_layer_buttons_update (); + layer_select_button_cb_hold_off = FALSE; + layer_enable_button_cb_hold_off = FALSE; + ghid_invalidate_all (); + in_cb = FALSE; } static void @@ -2580,6 +1321,13 @@ layer_enable_button_cb (GtkWidget * widget, gpointer data) redraw = TRUE; break; } + + layer_select_button_cb_hold_off = TRUE; + layer_enable_button_cb_hold_off = TRUE; + ghid_layer_buttons_update (); + layer_select_button_cb_hold_off = FALSE; + layer_enable_button_cb_hold_off = FALSE; + if (redraw) ghid_invalidate_all(); } @@ -2674,51 +1422,8 @@ make_layer_buttons (GtkWidget * vbox, GHidPort * port) G_CALLBACK (layer_select_button_cb), lb); } - switch (i) - { - case LAYER_BUTTON_SILK: - color_string = PCB->ElementColor; - text = _("silk"); - active = PCB->ElementOn; - break; - - case LAYER_BUTTON_RATS: - color_string = PCB->RatColor; - text = _("rat lines"); - active = PCB->RatOn; - break; - - case LAYER_BUTTON_PINS: - color_string = PCB->PinColor; - text = _("pins/pads"); - active = PCB->PinOn; - break; - - case LAYER_BUTTON_VIAS: - color_string = PCB->ViaColor; - text = _("vias"); - active = PCB->ViaOn; - break; - - case LAYER_BUTTON_FARSIDE: - color_string = PCB->InvisibleObjectsColor; - text = _("far side"); - active = PCB->InvisibleObjectsOn; - break; - - case LAYER_BUTTON_MASK: - color_string = PCB->MaskColor; - text = _("solder mask"); - active = TEST_FLAG (SHOWMASKFLAG, PCB); - break; - - default: - color_string = PCB->Data->Layer[i].Color; - text = UNKNOWN (PCB->Data->Layer[i].Name); - text = _(text); - active = PCB->Data->Layer[i].On; - break; - } + layer_process (&color_string, &text, &active, i); + button = gtk_check_button_new (); label = gtk_label_new (""); gtk_label_set_use_markup (GTK_LABEL (label), TRUE); @@ -2742,9 +1447,12 @@ make_layer_buttons (GtkWidget * vbox, GHidPort * port) g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (layer_enable_button_cb), GINT_TO_POINTER (i)); + + } } + /* If new color scheme is loaded from the config or user changes a color | in the preferences, make sure our layer button colors get updated. */ @@ -2767,20 +1475,7 @@ ghid_layer_buttons_color_update (void) { lb = &layer_buttons[i]; - if (i == LAYER_BUTTON_SILK) - color_string = PCB->ElementColor; - else if (i == LAYER_BUTTON_RATS) - color_string = PCB->RatColor; - else if (i == LAYER_BUTTON_PINS) - color_string = PCB->PinColor; - else if (i == LAYER_BUTTON_VIAS) - color_string = PCB->ViaColor; - else if (i == LAYER_BUTTON_FARSIDE) - color_string = PCB->InvisibleObjectsColor; - else if (i == LAYER_BUTTON_MASK) - color_string = PCB->MaskColor; - else - color_string = PCB->Data->Layer[i].Color; + layer_process (&color_string, NULL, NULL, i); layer_button_set_color (lb, color_string); } @@ -2796,6 +1491,9 @@ ghid_layer_enable_buttons_update (void) gchar *s; gint i; +#ifdef DEBUG_MENUS + printf ("ghid_layer_enable_buttons_update()\n"); +#endif /* Update layer button labels and active state to state inside of PCB */ @@ -2866,11 +1564,31 @@ ghid_layer_button_select (gint layer) | user toggles layer visibility or changes drawing layer or when internal | PCB code changes layer visibility. */ + void ghid_layer_buttons_update (void) { gint layer; gboolean active = FALSE; + gboolean old_holdoff; + char tmpnm[40]; + int i; + int set; + gchar *text; + GtkAction *a; + GValue setfalse = { 0 }; + GValue settrue = { 0 }; + GValue setlabel = { 0 }; + + g_value_init (&setfalse, G_TYPE_BOOLEAN); + g_value_init (&settrue, G_TYPE_BOOLEAN); + g_value_set_boolean (&setfalse, FALSE); + g_value_set_boolean (&settrue, TRUE); + g_value_init (&setlabel, G_TYPE_STRING); + +#ifdef DEBUG_MENUS + printf ("ghid_layer_buttons_update()\n"); +#endif if (!ghidgui || ghidgui->creating) return; @@ -2899,49 +1617,60 @@ ghid_layer_buttons_update (void) if (active && layer != layer_select_button_index) printf ("\tActivating button %d\n", layer); } - if (active && layer != layer_select_button_index) + + /* mask the callbacks */ + old_holdoff = ghidgui->toggle_holdoff; + ghidgui->toggle_holdoff = TRUE; + + /* update the check marks in the layer pick menu */ + for (i = 0; i < N_LAYER_BUTTONS ; i++) { - layer_select_button_cb_hold_off = TRUE; - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON - (layer_buttons[layer]. - radio_select_button), TRUE); - layer_select_button_index = layer; - layer_select_button_cb_hold_off = FALSE; - } -} + sprintf (tmpnm, "%s%d", LAYERPICK, i); + a = gtk_action_group_get_action (ghidgui->main_actions, tmpnm); + layer_process (NULL, &text, &set, i); + g_value_set_string (&setlabel, text); + + if (a != NULL) + { + g_object_set_property (G_OBJECT (a), "visible", (i >= max_layer && i < MAX_LAYER) ? &setfalse : &settrue); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (a), (set && (i == layer) ) ? TRUE : FALSE); + g_object_set_property (G_OBJECT (a), "label", &setlabel); + } + + sprintf (tmpnm, "%s%d", LAYERVIEW, i); + a = gtk_action_group_get_action (ghidgui->main_actions, tmpnm); + if (a != NULL) + { + g_object_set_property (G_OBJECT (a), "visible", (i >= max_layer && i < MAX_LAYER) ? &setfalse : &settrue); + gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (a), set ? TRUE : FALSE); + g_value_set_string (&setlabel, text); + g_object_set_property (G_OBJECT (a), "label", &setlabel); + } - /* ------------------------------------------------------------------ - | Route style buttons - */ -typedef struct -{ - GtkWidget *button; - RouteStyleType route_style; - gboolean shown; /* For temp buttons */ -} -RouteStyleButton; - /* Make 3 extra route style radio buttons. 2 for the extra Temp route - | styles, and the 3rd is an always invisible button selected when the - | route style settings in use don't match any defined route style (the - | user can hit 'l', 'v', etc keys to change the settings without selecting - | a new defined style. - */ -static RouteStyleButton route_style_button[NUM_STYLES + 3]; -static gint route_style_index; + } + g_value_unset (&setfalse); + g_value_unset (&settrue); + g_value_unset (&setlabel); + ghidgui->toggle_holdoff = old_holdoff; -static GtkWidget *route_style_edit_button; + if (active && layer != layer_select_button_index) + { + layer_select_button_cb_hold_off = TRUE; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON + (layer_buttons[layer]. + radio_select_button), TRUE); + layer_select_button_index = layer; + layer_select_button_cb_hold_off = FALSE; + } +} static void route_style_edit_cb (GtkWidget * widget, GHidPort * port) { - RouteStyleType *rst = NULL; - - if (route_style_index >= NUM_STYLES) - rst = &route_style_button[route_style_index].route_style; - ghid_route_style_dialog (route_style_index, rst); + hid_action("AdjustStyle"); } static void @@ -3002,7 +1731,7 @@ make_route_style_buttons (GtkWidget * vbox, GHidPort * port) G_CALLBACK (route_style_edit_cb), port); route_style_edit_button = button; - for (i = 0; i < NUM_STYLES + 3; ++i) + for (i = 0; i < N_ROUTE_STYLES; ++i) { RouteStyleType *rst; gchar buf[32]; @@ -3033,7 +1762,7 @@ make_route_style_buttons (GtkWidget * vbox, GHidPort * port) void ghid_route_style_button_set_active (gint n) { - if (n < 0 || n >= NUM_STYLES + 3) + if (n < 0 || n >= N_ROUTE_STYLES) return; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON @@ -3331,6 +2060,7 @@ ghid_build_pcb_top_window (void) hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + ghid_load_menus (); make_top_menubar(hbox, port); frame = gtk_frame_new(NULL); @@ -3670,7 +2400,8 @@ ghid_create_pcb_widgets (void) g_error_free(err); } ghid_build_pcb_top_window (); - ghid_init_toggle_states (); + ghid_update_toggle_flags (); + ghid_init_icons (port); SetMode (ARROW_MODE); ghid_mode_buttons_update (); @@ -3878,6 +2609,12 @@ ghid_do_export (HID_Attr_Val * options) { ghid_create_pcb_widgets (); + /* These are needed to make sure the @layerpick and @layerview menus + * are properly initialized and synchronized with the current PCB. + */ + ghid_layer_buttons_update (); + ghid_show_layer_buttons(); + if (stdin_listen) ghid_create_listener (); @@ -3901,8 +2638,1001 @@ LayersChanged (int argc, char **argv, int px, int py) return 0; } +static const char toggleview_syntax[] = +"ToggleView(1..MAXLAYER)\n" +"ToggleView(layername)\n" +"ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)"; + +static const char toggleview_help[] = +"Toggle the visibility of the specified layer or layer group."; + +/* %start-doc actions ToggleView + +If you pass an integer, that layer is specified by index (the first +layer is @code{1}, etc). If you pass a layer name, that layer is +specified by name. When a layer is specified, the visibility of the +layer group containing that layer is toggled. + +If you pass a special layer name, the visibility of those components +(silk, rats, etc) is toggled. Note that if you have a layer named +the same as a special layer, the layer is chosen over the special layer. + +%end-doc */ + +static int +ToggleView (int argc, char **argv, int x, int y) +{ + int i, l; + static gboolean in_toggle_view = 0; + gboolean active; + +#ifdef DEBUG_MENUS + printf ("Starting ToggleView(). in_toggle_view = %d\n", in_toggle_view); +#endif + if (in_toggle_view) + { + fprintf (stderr, "ToggleView() called on top of another ToggleView()\n" + "Please report this and how it happened\n"); + return 0; + } + + in_toggle_view = 1; + + if (argc == 0) + { + in_toggle_view = 0; + AFAIL (toggleview); + } + if (isdigit ((int) argv[0][0])) + { + l = atoi (argv[0]) - 1; + } + else if (strcmp (argv[0], "Silk") == 0) + l = LAYER_BUTTON_SILK; + else if (strcmp (argv[0], "Rats") == 0) + l = LAYER_BUTTON_RATS; + else if (strcmp (argv[0], "Pins") == 0) + l = LAYER_BUTTON_PINS; + else if (strcmp (argv[0], "Vias") == 0) + l = LAYER_BUTTON_VIAS; + else if (strcmp (argv[0], "Mask") == 0) + l = LAYER_BUTTON_MASK; + else if (strcmp (argv[0], "BackSide") == 0) + l = LAYER_BUTTON_FARSIDE; + else + { + l = -1; + for (i = 0; i < max_layer + 2; i++) + if (strcmp (argv[0], PCB->Data->Layer[i].Name) == 0) + { + l = i; + break; + } + if (l == -1) + { + in_toggle_view = 0; + AFAIL (toggleview); + } + + } + + printf ("ToggleView(): l = %d\n", l); + + /* Now that we've figured out which toggle button ought to control + * this layer, simply hit the button and let the pre-existing code deal + */ + active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (layer_buttons[l].layer_enable_button)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (layer_buttons[l].layer_enable_button), + active == TRUE ? FALSE : TRUE); + in_toggle_view = 0; + return 0; +} + +static const char selectlayer_syntax[] = +"SelectLayer(1..MAXLAYER|Silk|Rats)"; + +static const char selectlayer_help[] = +"Select which layer is the current layer."; + +/* %start-doc actions SelectLayer + +The specified layer becomes the currently active layer. It is made +visible if it is not already visible + +%end-doc */ + +static int +SelectLayer (int argc, char **argv, int x, int y) +{ + int newl; + if (argc == 0) + AFAIL (selectlayer); + + if (strcasecmp (argv[0], "silk") == 0) + newl = LAYER_BUTTON_SILK; + else if (strcasecmp (argv[0], "rats") == 0) + newl = LAYER_BUTTON_RATS; + else + newl = atoi (argv[0]) - 1; + +#ifdef DEBUG_MENUS + printf ("SelectLayer(): newl = %d\n", newl); +#endif + + /* Now that we've figured out which radio button ought to select + * this layer, simply hit the button and let the pre-existing code deal + */ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (layer_buttons[newl].radio_select_button), + TRUE); + + return 0; +} + + HID_Action gtk_topwindow_action_list[] = { - {"LayersChanged", 0, LayersChanged} + {"LayersChanged", 0, LayersChanged, + layerschanged_help, layerschanged_syntax}, + {"SelectLayer", 0, SelectLayer, + selectlayer_help, selectlayer_syntax}, + {"ToggleView", 0, ToggleView, + toggleview_help, toggleview_syntax} }; REGISTER_ACTIONS (gtk_topwindow_action_list) + +static char *pcbmenu_path = "gpcb-menu.res"; + +static HID_Attribute pcbmenu_attr[] = { +{"pcb-menu", "Location of gpcb-menu.res file", + HID_String, 0, 0, {0, PCBLIBDIR "/gpcb-menu.res", 0}, 0, &pcbmenu_path} +}; + +REGISTER_ATTRIBUTES (pcbmenu_attr) + +#define INDENT_INC 5 + +static void +ghid_append_action (const char * name, const char *stock_id, + const char *label, const char *accelerator, + const char *tooltip) +{ + +#ifdef DEBUG_MENUS + printf ("ghid_append_action(\"%s\", \"%s\", \"%s\", \"%s\", \"%s\")\n", + UNKNOWN (name), + UNKNOWN (stock_id), + UNKNOWN (label), + UNKNOWN (accelerator), + UNKNOWN (tooltip)); +#endif + + if ( (new_entries = realloc (new_entries, + (menuitem_cnt + 1) * sizeof (GtkActionEntry))) == NULL) + { + fprintf (stderr, "ghid_append_action(): realloc of new_entries failed\n"); + exit (1); + } + + + if ( (action_resources = realloc (action_resources, + (menuitem_cnt + 1) * sizeof (Resource *))) == NULL) + { + fprintf (stderr, "ghid_append_action(): realloc of action_resources failed\n"); + exit (1); + } + action_resources[menuitem_cnt] = NULL; + + /* name, stock_id, label, accelerator, tooltip, callback */ + new_entries[menuitem_cnt].name = strdup (name); + new_entries[menuitem_cnt].stock_id = (stock_id == NULL ? NULL : strdup (stock_id)); + new_entries[menuitem_cnt].label = strdup (label); + new_entries[menuitem_cnt].accelerator = ( (accelerator == NULL || *accelerator == '\0') + ? NULL : strdup (accelerator)); + new_entries[menuitem_cnt].tooltip = (tooltip == NULL ? NULL : strdup (tooltip)); + new_entries[menuitem_cnt].callback = G_CALLBACK (ghid_menu_cb); + menuitem_cnt++; +} + +static void +ghid_append_toggle_action (const char * name, const char *stock_id, + const char *label, const char *accelerator, + const char *tooltip, int active) +{ + + if ( (new_toggle_entries = realloc (new_toggle_entries, + (tmenuitem_cnt + 1) * sizeof (GtkToggleActionEntry))) == NULL) + { + fprintf (stderr, "ghid_append_toggle_action(): realloc of new_toggle_entries failed\n"); + exit (1); + } + + + if ( (toggle_action_resources = realloc (toggle_action_resources, + (tmenuitem_cnt + 1) * sizeof (Resource *))) == NULL) + { + fprintf (stderr, "ghid_append_toggle_action(): realloc of toggle_action_resources failed\n"); + exit (1); + } + toggle_action_resources[tmenuitem_cnt] = NULL; + + /* name, stock_id, label, accelerator, tooltip, callback */ + new_toggle_entries[tmenuitem_cnt].name = strdup (name); + new_toggle_entries[tmenuitem_cnt].stock_id = (stock_id == NULL ? NULL : strdup (stock_id)); + new_toggle_entries[tmenuitem_cnt].label = strdup (label); + new_toggle_entries[tmenuitem_cnt].accelerator = (accelerator == NULL ? NULL : strdup (accelerator)); + new_toggle_entries[tmenuitem_cnt].tooltip = (tooltip == NULL ? NULL : strdup (tooltip)); + new_toggle_entries[tmenuitem_cnt].callback = G_CALLBACK (ghid_menu_cb); + new_toggle_entries[tmenuitem_cnt].is_active = active ? TRUE : FALSE; + tmenuitem_cnt++; +} + +/* + * Some keys need to be replaced by a name for the gtk accelerators to + * work. This table contains the translations. The "in" character is + * what would appear in gpcb-menu.res and the "out" string is what we + * have to feed to gtk. I was able to find these by using xev to find + * the keycode and then looked at gtk+-2.10.9/gdk/keynames.txt (from the + * gtk source distribution) to figure out the names that go with the + * codes. + */ +typedef struct +{ + const char in; + const char *out; +} KeyTable; +static KeyTable key_table[] = + { + {':', "colon"}, + {'=', "equal"}, + {'/', "slash"}, + {'[', "bracketleft"}, + {']', "bracketright"}, + {'.', "period"}, + {'|', "bar"} + }; +static int n_key_table = sizeof (key_table) / sizeof (key_table[0]); + +static void +add_resource_to_menu (char * menu, Resource * node, void * callback, int indent) +{ + int i, j; + char *v; + Resource *r; + char tmps[32]; + char accel[64]; + char *menulabel = NULL; + char ch[2]; + char m = '\0'; + + ch[1] = '\0'; + + for (i = 0; i < node->c; i++) + switch (resource_type (node->v[i])) + { + case 101: /* named subnode */ + add_resource_to_menu (node->v[i].name, node->v[i].subres, + callback, indent + INDENT_INC); + break; + + case 1: /* unnamed subres */ + accel[0] = '\0'; + /* This is a menu choice. The first value in the unnamed + * subres is what the menu choice gets called. + * + * This may be a top level menu on the menubar, + * a menu choice under, say the File menu, or + * a menu choice under a submenu of a menu choice. + * + * We need to pick off an "m" named resource which is + * the menu accelerator key and an "a" named subresource + * which contains the information for the hotkey. + */ + if ((v = resource_value (node->v[i].subres, "m"))) + { +#ifdef DEBUG_MENUS + printf (" found resource value m=\"%s\"\n", v); +#endif + m = *v; + } + if ((r = resource_subres (node->v[i].subres, "a"))) + { + /* for the accelerator, it has 2 values like + * + * a={"Ctrl-Q" "Ctrlq"} + * The first one is what's displayed in the menu and the + * second actually defines the hotkey. Actually, the + * first value is only used by the lesstif HID and is + * ignored by the gtk HID. The second value is used by both. + * + * We have to translate some strings. See + * gtk+-2.10.9/gdk/keynames.txt from the gtk distribution + * as well as the output from xev(1). + * + * Modifiers: + * + * "Ctrl" -> "" + * "Shift" -> "" + * "Alt" -> "" + * "" -> "" + * + * keys: + * + * " " -> "" + * "Enter" -> "Return" + * "Tab" -> clear out the accelerator entirely. Gtk's + * accessability features take over Tab so we can't use it. + * + */ + char *p; + int j; + enum {KEY, MOD} state; + + state = MOD; +#ifdef DEBUG_MENUS + printf (" accelerator a=%p. r->v[0].value = \"%s\", r->v[1].value = \"%s\" ", + r, r->v[0].value, r->v[1].value); +#endif + p = r->v[1].value; + while (*p != '\0') + { + switch (state) + { + case MOD: + if (*p == ' ') + { + p++; + } + else if (strncmp (p, "", 5) == 0) + { + state = KEY; + p += 5; + } + else if (strncmp (p, "Ctrl", 4) == 0) + { + strncat (accel, "", sizeof (accel)); + p += 4; + } + else if (strncmp (p, "Shift", 5) == 0) + { + strncat (accel, "", sizeof (accel)); + p += 5; + } + else if (strncmp (p, "Alt", 3) == 0) + { + strncat (accel, "", sizeof (accel)); + p += 3; + } + else + { + Message ("Don't know how to parse \"%c\"\n", + *p); +; } + break; + + case KEY: + if (strncmp (p, "Enter", 5) == 0) + { + strncat (accel, "Return", sizeof (accel)); + p += 5; + } + else if (strncmp (p, "Tab", 3) == 0) + { + Message ("GTK does not allow the use of Tab for menu accelerators\n" + "Hotkey \"%s\" will be dropped\n", r->v[1].value); + accel[0] = '\0'; + p += 3; + } + else + { + ch[0] = *p; + for (j = 0; j < n_key_table; j++) + { + if ( *p == key_table[j].in) + { + strncat (accel, key_table[j].out, sizeof (accel)); + j = n_key_table; + } + } + + if (j == n_key_table) + strncat (accel, ch, sizeof (accel)); + + p++; + } + break; + + } + } +#ifdef DEBUG_MENUS + printf ("\n translated = \"%s\"\n", accel); +#endif + } + v = "button"; + + /* Now look for the first unnamed value (not a subresource) to + * figure out the name of the menu or the menuitem. + * + * After this loop, v will be the name of the menu or menuitem. + * + */ + for (j = 0; j < node->v[i].subres->c; j++) + if (resource_type (node->v[i].subres->v[j]) == 10) + { + v = node->v[i].subres->v[j].value; + break; + } + + if (m == '\0') + menulabel = strdup (v); + else + { + /* we've been given a mneumonic so we need to insert an + * "_" into the label. For example if the string is + * "Quit Program" and we have m=Q, we'd need to produce + * "_Quit Program". + */ + char *s1, *s2; + size_t l; + + l = strlen (v) + 2; +#ifdef DEBUG_MENUS + printf ("allocate %ld bytes\n", l); +#endif + if ( (menulabel = (char *) malloc ( l * sizeof (char))) + == NULL) + { + fprintf (stderr, "add_resource_to_menu(): malloc failed\n"); + exit (1); + } + + s1 = menulabel; + s2 = v; + while (*s2 != '\0') + { + if (*s2 == m) + { + /* add the underscore and quit looking for more + * matches since we only want to add 1 underscore + */ + *s1 = '_'; + s1++; + m = '\0'; + } + *s1 = *s2; + s1++; + s2++; + } + *s1 = '\0'; + } +#ifdef DEBUG_MENUS + printf ("v = \"%s\", label = \"%s\"\n", v, menulabel); +#endif + /* if the subresource we're processing also has unnamed + * subresources then this is either a menu (that goes on the + * menu bar) or it is a submenu. It isn't a menuitem. + */ + if (node->v[i].subres->flags & FLAG_S) + { + /* This is a menu */ + + /* add menus to the same entries list as the "normal" + * menuitems. We'll just use NULL for what happens so the + * callback doesn't have anything to do. + */ + + sprintf (tmps, "%s%d", MENUITEM, menuitem_cnt); + + /* add to the action entries */ + /* name, stock_id, label, accelerator, tooltip */ + ghid_append_action (tmps, NULL, menulabel, accel, NULL); + + /* and add to the user interfact XML description */ + ghid_ui_info_indent (indent); + ghid_ui_info_append ("\n"); + + + /* recursively add more submenus or menuitems to this + * menu/submenu + */ + add_resource_to_menu ("sub menu", node->v[i].subres, + callback, indent + INDENT_INC); + ghid_ui_info_indent (indent); + + /* and close this menu */ + ghid_ui_info_append ("\n"); + } + else + { + /* We are in a specific menu choice and need to figure out + * if it is a "normal" one + * or if there is some condtion under which it is checked + * or if it has sensitive=false which is simply a label + */ + + char *checked = resource_value (node->v[i].subres, "checked"); + char *label = resource_value (node->v[i].subres, "sensitive"); + char *tip = resource_value (node->v[i].subres, "tip"); + if (checked) + { + /* We have the "checked=" named value for this + * menuitem. Now see if it is + * checked=foo + * or + * checked=foo,bar + * + * where the former is just a binary flag and the + * latter is checking a flag against a value + */ +#ifdef DEBUG_MENUS + printf ("Found a \"checked\" menu choice \"%s\", \"%s\"\n", v, checked); +#endif + if (strchr (checked, ',')) + { + /* we're comparing a flag against a value */ +#ifdef DEBUG_MENUS + printf ("Found checked comparing a flag to a value\n"); +#endif + } + else + { + /* we're looking at a binary flag */ + /* name, stock_id, label, accelerator, tooltip, callback, is_active + printf ("Found checked using a flag as a binary\n"); + + */ + } + + sprintf (tmps, "%s%d", TMENUITEM, tmenuitem_cnt); + + /* add to the action entries */ + /* name, stock_id, label, accelerator, tooltip, is_active */ + ghid_append_toggle_action (tmps, NULL, menulabel, accel, tip, 1); + + ghid_ui_info_indent (indent); + ghid_ui_info_append ("\n"); + + + toggle_action_resources[tmenuitem_cnt-1] = node->v[i].subres; + + } + else if (label && strcmp (label, "false") == 0) + { + /* we have sensitive=false so just put a label in the + * GUI -- FIXME -- actually do something here.... + */ + } + else + { + /* + * Here we are finally at the rest of an actual + * menuitem. So, we need to get the subresource + * that has all the actions in it (actually, it will + * be the entire subresource that defines the + * menuitem, the callbacks later will pick out the + * actions part. + * + * We add this resource to an array of action + * resources that is used by the main menu callback to + * figure out what really needs to be done. + */ + + sprintf (tmps, "%s%d", MENUITEM, menuitem_cnt); + + /* add to the action entries */ + /* name, stock_id, label, accelerator, tooltip */ + ghid_append_action (tmps, NULL, menulabel, accel, tip); + + ghid_ui_info_indent (indent); + ghid_ui_info_append ("\n"); + + + action_resources[menuitem_cnt-1] = node->v[i].subres; + +#ifdef DEBUG_MENUS + /* Print out the actions to help with debugging */ + { + int vi; + Resource *mynode = node->v[i].subres; + + /* Start at the 2nd sub resource because the first + * is the text that shows up in the menu. + * + * We're looking for the unnamed values since those + * are the ones which are actions. + */ + for (vi = 1; vi < mynode->c; vi++) + if (resource_type (mynode->v[vi]) == 10) + printf(" action value=\"%s\"\n", mynode->v[vi].value); + } +#endif + + + } + + + /* now keep looking over our menuitem to see if there is + * any more work. + */ + for (j = 0; j < node->v[i].subres->c; j++) + switch (resource_type (node->v[i].subres->v[j])) + { + case 110: /* named value = X resource */ + { + char *n = node->v[i].subres->v[j].name; + /* allow fg and bg to be abbreviations for + * foreground and background + */ + if (strcmp (n, "fg") == 0) + n = "foreground"; + if (strcmp (n, "bg") == 0) + n = "background"; + + /* ignore special named values (m, a, sensitive) */ + if (strcmp (n, "m") == 0 + || strcmp (n, "a") == 0 + || strcmp (n, "sensitive") == 0 + || strcmp (n, "tip") == 0 + ) + break; + + /* log checked and active special values */ + if (strcmp (n, "checked") == 0) + { +#ifdef DEBUG_MENUS + printf ("%s is checked\n", node->v[i].subres->v[j].value); +#endif + note_toggle_flag (new_toggle_entries[tmenuitem_cnt-1].name, + node->v[i].subres->v[j].value); + break; + } + if (strcmp (n, "active") == 0) + { + Message ("The gtk gui currently ignores \"%s\"", + node->v[i].subres->v[j].value); + Message ("as part of a menuitem resource.\n" + "Feel free to provide patches\n"); + break; + } + + /* if we got this far it is supposed to be an X + * resource. For now ignore it and warn the user + */ + Message ("The gtk gui currently ignores \"%s\"", + node->v[i].subres->v[j].value); + Message ("as part of a menuitem resource.\n" + "Feel free to provide patches\n"); + + } + break; + } + + } + break; + + case 10: /* unnamed value */ + /* in the resource file we may have something like: + * + * {File + * {Open OpenAction()} + * {Close CloseAction()} + * - + * {"Some Choice" MyAction()} + * {"Some Other Choice" MyOtherAction()} + * @foo + * {Quit QuitAction()} + * } + * + * If we get here in the code it is becuase we found the "-" + * or the "@foo". + * + */ +#ifdef DEBUG_MENUS + printf ("resource_type for node #%d is 10 (unnamed value). value=\"%s\"\n", + i, node->v[i].value); +#endif + + if (node->v[i].value[0] == '@') + { + if (strcmp (node->v[i].value, "@layerview") == 0) + { + int i; + char tmpid[40]; + for (i = 0 ; i < N_LAYER_BUTTONS; i++) + { + sprintf (tmpid, "\n", + LAYERVIEW, i); + ghid_ui_info_indent (indent); + ghid_ui_info_append (tmpid); + } + } + else if (strcmp (node->v[i].value, "@layerpick") == 0) + { + int i; + char tmpid[40]; + for (i = 0 ; i < N_SELECTABLE_LAYER_BUTTONS; i++) + { + sprintf (tmpid, "\n", + LAYERPICK, i); + ghid_ui_info_indent (indent); + ghid_ui_info_append (tmpid); + } + } + else if (strcmp (node->v[i].value, "@routestyles") == 0) + { + int i; + char tmpid[40]; + for (i = 0 ; i < N_ROUTE_STYLES; i++) + { + sprintf (tmpid, "\n", + ROUTESTYLE, i); + ghid_ui_info_indent (indent); + ghid_ui_info_append (tmpid); + } + } + else + { + Message ("GTK GUI currently ignores \"%s\" in the menu\n", + node->v[i].value); + Message ("resource file.\n"); + } + + } + + else if (strcmp (node->v[i].value, "-") == 0) + { + ghid_ui_info_indent (indent); + ghid_ui_info_append ("\n"); + } + else if (i > 0) + { + /* This is where you get with an action-less menuitem. + * It is really just useful when you're starting to build + * a new menu and you're looking to get the layout + * right. + */ + sprintf (tmps, "%s%d", MENUITEM, menuitem_cnt); + + /* add to the action entries + * name, stock_id, label, accelerator, tooltip + * Note that we didn't get the mneumonic added in here, + * but since this is really for a dummy menu (no + * associated actions), I'm not concerned. + */ + + ghid_append_action (tmps, NULL, node->v[i].value, accel, NULL); + + ghid_ui_info_indent (indent); + ghid_ui_info_append ("\n"); + + action_resources[menuitem_cnt-1] = NULL; + + } + break; + } + + if (menulabel != NULL) + free (menulabel); +} + + +static void +ghid_ui_info_indent (int indent) +{ + int i; + + for (i = 0; i < indent ; i++) + { + ghid_ui_info_append (" "); + } +} + +/* + *appends a string to the ui_info string + * This function is used + */ + +static void +ghid_ui_info_append (const gchar * new) +{ + gchar *p; + + if (new_ui_info_sz == 0) + { + new_ui_info_sz = 1024; + new_ui_info = (gchar *) calloc ( new_ui_info_sz, sizeof (gchar)); + } + + while (strlen (new_ui_info) + strlen (new) + 1 > new_ui_info_sz) + { + size_t n; + gchar * np; + + n = new_ui_info_sz + 1024; + if ( (np = realloc (new_ui_info, n)) == NULL) + { + fprintf (stderr, "ghid_ui_info_append(): realloc of size %ld failed\n", + n); + exit (1); + } + new_ui_info = np; + new_ui_info_sz = n; + } + + p = new_ui_info + strlen (new_ui_info) ; + while (*new != '\0') + { + *p = *new; + p++; + new++; + } + + *p = '\0'; +} + + +static void +ghid_load_menus (void) +{ + char *filename; + Resource *r = 0, *bir; + char *home_pcbmenu; + Resource *mr; + + home_pcbmenu = Concat (getenv ("HOME"), "/.pcb/gpcb-menu.res", NULL); + + if (access ("gpcb-menu.res", R_OK) == 0) + filename = "gpcb-menu.res"; + else if (access (home_pcbmenu, R_OK) == 0) + filename = home_pcbmenu; + else if (access (pcbmenu_path, R_OK) == 0) + filename = pcbmenu_path; + else + filename = 0; + + bir = resource_parse (0, gpcb_menu_default); + if (!bir) + { + fprintf (stderr, "Error: internal menu resource didn't parse\n"); + exit(1); + } + + if (filename) + r = resource_parse (filename, 0); + + if (!r) + r = bir; + + mr = resource_subres (r, "MainMenu"); + if (!mr) + mr = resource_subres (bir, "MainMenu"); + + if (mr) + { + ghid_ui_info_append ("\n"); + ghid_ui_info_indent (INDENT_INC); + ghid_ui_info_append ("\n"); + add_resource_to_menu ("Initial Call", mr, 0, 2*INDENT_INC); + ghid_ui_info_indent (INDENT_INC); + ghid_ui_info_append ("\n"); + } + + mr = resource_subres (r, "PopupMenus"); + if (!mr) + mr = resource_subres (bir, "PopupMenus"); + + if (mr) + { + int i; + + for (i = 0; i < mr->c; i++) + { + if (resource_type (mr->v[i]) == 101) + { + /* This is a named resource which defines a popup menu */ + ghid_ui_info_indent (INDENT_INC); + ghid_ui_info_append ("\n"); + add_resource_to_menu ("Initial Call", mr->v[i].subres, + 0, 2*INDENT_INC); + ghid_ui_info_indent (INDENT_INC); + ghid_ui_info_append ("\n"); + } + else + { + } + } + } + + ghid_ui_info_append ("\n"); + +#ifdef DEBUG_MENUS + printf ("Finished loading menus. ui_info = \n"); + printf ("%s\n", new_ui_info); +#endif + + mr = resource_subres (r, "Mouse"); + if (!mr) + mr = resource_subres (bir, "Mouse"); + if (mr) + Message ("ghid_load_menus(): Mouse resources are currently ignored by the GTK HID.\n" + "Please feel free to submit a patch to implement this!\n" + ); + +} + +/* ------------------------------------------------------------ */ + +static const char adjuststyle_syntax[] = +"AdjustStyle()\n"; + +static const char adjuststyle_help[] = +"Open the window which allows editing of the route styles"; + +/* %start-doc actions AdjustStyle + +Opens the window which allows editing of the route styles. + +%end-doc */ + +static int +AdjustStyle(int argc, char **argv, int x, int y) +{ + RouteStyleType *rst = NULL; + + if (argc > 1) + AFAIL (adjuststyle); + + if (route_style_index >= NUM_STYLES) + rst = &route_style_button[route_style_index].route_style; + ghid_route_style_dialog (route_style_index, rst); + + return 0; +} + +/* ------------------------------------------------------------ */ + +static const char editlayergroups_syntax[] = +"EditLayerGroups()\n"; + +static const char editlayergroups_help[] = +"Open the preferences window which allows editing of the layer groups"; + +/* %start-doc actions EditLayerGroups + +Opens the preferences window which is where the layer groups +are edited. This action is primarily provides to provide menu +resource compatibility with the lesstif HID. + +%end-doc */ + +static int +EditLayerGroups(int argc, char **argv, int x, int y) +{ + + if (argc != 0) + AFAIL (editlayergroups); + + hid_actionl ("DoWindows", "Preferences", NULL); + + return 0; +} + +/* ------------------------------------------------------------ */ + +HID_Action ghid_menu_action_list[] = { + {"AdjustStyle", 0, AdjustStyle, adjuststyle_help, adjuststyle_syntax}, + {"EditLayerGroups", 0, EditLayerGroups, editlayergroups_help, editlayergroups_syntax} +}; + +REGISTER_ACTIONS (ghid_menu_action_list) + diff --git a/src/hid/gtk/gui.h b/src/hid/gtk/gui.h index 3b770c3e14..06029b9b17 100644 --- a/src/hid/gtk/gui.h +++ b/src/hid/gtk/gui.h @@ -83,14 +83,16 @@ #define TO_PCB_UNITS(v) (Settings.grid_units_mm ? \ ((v) / 0.000254 + 0.5) : ((v) * 100.0 + 0.5)) -#define SIDE_X(x) ((Settings.ShowSolderSide ? PCB->MaxWidth - (x) : (x))) +extern int ghid_flip_x, ghid_flip_y; +#define SIDE_X(x) ((ghid_flip_x ? PCB->MaxWidth - (x) : (x))) +#define SIDE_Y(y) ((ghid_flip_y ? PCB->MaxHeight - (y) : (y))) #define DRAW_X(x) (gint)((SIDE_X(x) - gport->view_x0) / gport->zoom) -#define DRAW_Y(y) (gint)(((y) - gport->view_y0) / gport->zoom) +#define DRAW_Y(y) (gint)((SIDE_Y(y) - gport->view_y0) / gport->zoom) #define DRAW_Z(z) (gint)((z) / gport->zoom) #define VIEW_X(x) SIDE_X((gint)((x) * gport->zoom + gport->view_x0)) -#define VIEW_Y(y) (gint)((y) * gport->zoom + gport->view_y0) +#define VIEW_Y(y) SIDE_Y((gint)((y) * gport->zoom + gport->view_y0)) #define VIEW_Z(z) (gint)((z) * gport->zoom) @@ -374,7 +376,7 @@ void ghid_route_style_set_button_label (gchar * name, gint index); void ghid_route_style_set_temp_style (RouteStyleType * rst, gint which); void ghid_route_style_button_set_active (gint number); void ghid_route_style_buttons_update (void); - +void ghid_update_toggle_flags (void); /* gui-utils.c */ diff --git a/src/misc.c b/src/misc.c index 257b265f9e..96c8c56234 100644 --- a/src/misc.c +++ b/src/misc.c @@ -81,8 +81,6 @@ RCSID ("$Id$"); - - /* forward declarations */ static char *BumpName (char *); static void RightAngles (int, float *, float *); diff --git a/src/pcbtest.sh.in b/src/pcbtest.sh.in index aab6f751a3..82e68962ca 100755 --- a/src/pcbtest.sh.in +++ b/src/pcbtest.sh.in @@ -33,6 +33,9 @@ # If the first argument is "-gdb" then run PCB inside the gdb # debugger. +# +# Use --g-fatal-warnings with the gtk HID to cause gtk-WARNING's to +# abort. TEST_PATHS="--lib-path ../lib --lib-newlib @TOPSRCDIR@/newlib:../lib/pcblib-newlib --element-path ../lib --font-path @TOPSRCDIR@/src" TEST_CMDS="--lib-command-dir ../lib" diff --git a/src/set.c b/src/set.c index 81d50ab247..e923a5447f 100644 --- a/src/set.c +++ b/src/set.c @@ -62,9 +62,6 @@ RCSID ("$Id$"); - - - static int mode_position = 0; static int mode_stack[MAX_MODESTACK_DEPTH]; diff --git a/src/todo b/src/todo index 4c103ddd32..3f908ae5d6 100644 --- a/src/todo +++ b/src/todo @@ -5,9 +5,51 @@ MoveLayers - undo of deleting a layer with stuff on it. [gtk] +[user controlled menus for gtk] + +- Why doesn't the Tab key work??? I get complaints that the keysym + is undefined. Maybe it is the old version of gtk I'm using? Looking + in more recent sources seems to indicate that Tab should be Just Fine + as a hot key. + +- sometimes after using the command window, the hotkeys all seem to + quit working. Why??? + +- Test all menu actions (again) + +- Compare all hotkeys from the hard coded system to the new resource file + controlled system. We're looking for no/minimal user visible change + when the usermenu branch is merged + +- Make sure loading a new board updates all the displayed menu checkmarks + +- play around with the route style buttons and menus to see if it gets + confused ever. + +- make sure settings are always saved + +- make sure that we're compatible with the lesstif hid as far as being able to + load the same menu resource file if we want + +- compare performace before and after over a slow link or on a slow computer. + +- make the ui append code more printf()-like. It will simplify the code + and make it nicer to read. + +- look for code duplication in hid/gtk/gui-top-window.c, especially related to + layers and tools. Don't duplicate code if at all possible. + +Known issues: + +- Mouse section in the resource file is ignored. I need to learn about how the mouse buttons are handled in the gtk HID currently so I can hook up that section. + +- A fair amount of now obsolete code still exists in gui-top-window.c. I need to do some major house keeping. + + +[existing before user controlled menus] + Do something with LayerGroupsChanged action. -Test all menu actions. Verify all config items are saved/loaded properly. @@ -65,3 +107,235 @@ structures; convert most internal functions to use this AnyObject type instead of N functions for N object types. (Prelude to C++ objects?) Win32 and MacOS HIDs. + +-------------------- Punch list from sdb -------------------- + + +I played around with an existing design: the two-sided optical proximity +sensor board I wrote about in Circuit Cellar. A tarball of this project is +available on my website. Here are some notes + +* Grab a single track and move it around. Sometimes, PCB prevents me from + moving it beyond a point above and to the left of the track's original + starting point. This happens regularly if I do this: + 1. Click on teh track. It lights up. + 2. Grab the track with the left mouse button. Then drag it with left + mouse button down. The track won't move above or to the left of its + start point. + Maybe this has something to do with preventing motion to negative + coordinates, and PCB is looking at component-relative coordinates instead + of absolute board coords? + +dm: there in 20070208 + +* Bug or feature? I run the DRC checker. The DRCs are written out to the + pcb.log file. However, the pcb.log window does not rise to the top. + Rather, it remains hidden behind my main PCB window. + +dm: there in 20070208 + +* "File -> revert" removes all my silk refdes text, and replaces it with the + component description from the element file. It looks like this action + tries to put text(3) on the baord, when it should put text(2). + +dm: can't reproduce on my board. Need to investigate. Looks like no change. + +* "File -> revert" also changes many of my SMT pads from rectangular to round + end. + +dm: can't reproduce. + + +* "Edit -> cut/copy/paste selection to buffer". Is there any reason the key + bindings for these are not the standard bindings: + cut: -X + copy: -C + paste: -V + Yes, it may be in a .gtkrc file now, but IMO these should be the default. + +dm: will switch after usermenu merge. + +* We have "edit -> select/unselect all", and we have "select -> + select/unselect all objects". Do we need two menu items doing the same + thing? Or if they do different things, can we make the text reflect what + they do? + +dm: They are identical. I have mixed feelings. It is wierd to have 2. Yet, it seems like they go under select but most programs have edit->select all.... I'll make a note, but this is the same as in the trunk right now. + +* "Edit -> move selected to current layer" doesn't seem to do anything. + +dm: existing bug. confirmed. + +* "View -> open pinout menu" does nothing. No spew appears on console. + +dm: need to select something or have crosshair over an element. + +* "View -> pin/via show name/number" does nothing. No spew appears on + console. + +dm: same deal +* If I do "view -> current layer -> delete current layer", the layer is + deleted. However, the remaining layers are re-colored. It looks like the + current layer is deleted from a list, but the colors are based upon list + position, so the remaining layers are re-colored if they live after teh + deleted layer. + + Anyway, the layers shouldn't be recolored when I delete a layer. + +dm: existing bug in gtk HID only (lesstif works right) + +actually.... lesstif doesn't recolor until you restart pcb and then it +is recolored. It is because we don't store the color with the layer +in the pcb file. + +* Again, "view -> current layer -> move current layer up/down" re-colors my + layers. I'd rather have the color follow the layer so that e.g. my GND + planes remain green. + +dm: see above + +* "Settings -> orthogonal moves" doesn't work correctly. If I start a track, + it will only go in an orthogonal direction, but then if I plant the track + by clicking once and try to veer off in an orthogonal direction, then the + track won't go orthogonal relative to my planted point. Rather, it still + wants to move in an orthogonal relative to my start point. + +* "Settings -> all directions lines" and "settings -> orthogonal moves" can + both be selected at once. These are incompatible settings. I suggest these + drawing settings should be in an menu section with radio buttons which + prohibit checking more than one box at a time. + + + +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +* WHile fiddling with a different setting, + I just noticed that trying to optimize rats only highlights pads now. I + suspect this has to do with when I removed a layer. The code which used to + tell the rats to light up is now telling the pads to light up, probably + because it is pointing to the wrong element in the layer list. + +* "Select -> move selected elements to other side" doesn't move a selected + element to the other side. Rather, it asks you to click on the objects you + want to move. That is, it is "verb noun" rather than "noun verb". Bug or + feature? These days, most UIs use the "noun verb" convention for one-step + actions like this. + +* "Select -> remove selected objects" is "noun verb". This is good. + However, it's the same as selecting an object and hitting , right? + Why should it appear here. Isn't this action under "edit" in most modern + UIs? + +* On the same topic: As you pointed out, hitting the key deletes + the object under the cursor. This is not the expected behavior nowadays. + What should happen is that all selected objects (i.e. those which are lit + up) should be deleted. + +* A general observation: If I use the "lock" tool to lock down a component, + then I can't select it. That's OK. However, it would be nice if a dialog + box would pop up and tell me that the component is locked. Right now it + can be very confusing if I locked a component and then forgot it was + locked. I can't figure out why I can't select it...... + +* This is weird. "Select -> convert selection to element" asks me to select + the mark. I click in the middle of a component. THen, depending upon luck + or perhaps history, PCB lights up a component *next to* the one I just + clicked. And it also lights up a piece of etch in the vicinity of the + component I just clicked. ??? + +* "Select -> optimize selected rats" -- what does this do? Is it the same as + "Connects -> optimize rats nest?". If so, then it should be removed form + the "select" menu. + +* A general comment: Lots of things in the "select" pull-down don't belong + under the heading of "select". Rather, I'd call this menu "actions", or + possibly "tools". THen, lots of the nice actions only available via the + command line widget can be grouped under this menu title. As for a name, I + prefer "actions" 'cause that's what they are. + +* "Select -> auto route" and "select -> rip up autorouted tracks" also + appear under "connections". They don't need to be under the "select" menu. + + + +* General comment: the way the buffer works has alwyas bugged me. When you + copy or cut somthing to the buffer, you get a ghost image of hte + footprint. This is OK. However, the ghost follows the cursor around while + you go to the menu to select the next action. This is a PITA since the + view field of the design moves when you get to the top of the window while + reaching for the menu. (Yes, I realize we all use + the hotkeys to trigger actions, but newbies don't know to do this yet.) + +* "Buffer -> #1/#2/etc" What do they do? OK, I realize they allow you to + select one of five buffers to operate on. Maybe this should be renamed + "Buffer -> operate on buf 1", "Buffer -> operate on buf2", etc. + +* "Connects -> apply vendor drill mapping" doesn't report success of + failure. In my case, I have no vendor drill file, but when I do "connects + -> apply vendor drill mapping" nothing happens. I'd expect a pop-up box to + tell me about my error (no file). + +* "Connects -> report found pins/pads" throws up box saying "the following + pins/pads are FOUND:" with nothing after that. + + +* On the upper right, teh box whihc holds the cursor's coordinates resizes as + you move the cursor around and the + coordinate numbers grow and shrink. This + makes the text to the left of the box jump around. It would look better if + the coordinate box was a fixed size, holding space for e.g. 8 digits each + (i.e. XXXXXX.XX). + +* Next to the cursor coordinate box is another box which looks like it should + hold some coordinates. However, it holds nothing. What is it for? + Unimplemented feature? + +* An annoyance: Eariler, I tested the "disperse elements" menu item. It + placed some components below the white drawing area, in the grey no-go + area. Now I can't grab them because the cursor is prevented from moving + into the grey area. + + IMO, the cursor should be permitted to move into the grey area. Also you + should be permitted to drag components, etch, or anything else into the + grey area. Yes, the grey area is outside the bounds of the board, but the + only things that should do is clip any graphic objects to the edge of the + white area when you generate Gerbers. From teh standpoint of drawing, you + should have full access to the grey area. + + One strong reason in favor of this is that it's quite common to put + unplaced components outside the board during placement stage. You can sort + and segregate them out there. Then, as + you place the components, you can grab them from outside the board and + place them where you want. Right now, that's more of a PITA since the + components are initially imported all on top of one anther. Then, if you + disperse them, they cover the board area where you want to eventually place + them. + +* Finally, a general comment. I've never been 100% happy with the top-level + menus in PCB. In my opinion, I'd make them as follows: + +-- File +-- Edit +-- View +-- Settings +-- Actions (currently is selections, but should hold items related to acting + on things you have selected.) +-- Footprints -- currently is buffer. Should permit manipulations related to + editing, creating, saving, rotating, mirroring, etc. of footprints. + Might add other menu items related to dealing with footprints. +-- Routing -- currently is connects, but should be renamed to reflect that its + primary purpose is related to things related to laying down physical + tracks and + dealing with the autorouter. Could also include anything related to + changing track size or other etch manipulations. +-- Nets -- Deals with highlighting connections, maybe toggling rats, opening + the nets dialog, etc. Also, anything + else related to the abstract connections between circuit + elements. -- Info -- Window + +The idea is to make the menus reflect the physical things on teh board which +the user is concerned with. Right now the menus are more a reflection of +PCB's internals (i.e. connections, buffer, etc.) + +Once the top level menus are re-named, then I'd do some re-factoring/shuffling +of functionality into the new menus. -- 2.11.4.GIT