From c86ec80332ac575d940606b57b40cf017a38c9d3 Mon Sep 17 00:00:00 2001 From: David Freese Date: Thu, 19 Nov 2015 05:31:01 -0600 Subject: [PATCH] dock macros * add dockable macros in a 4x12 matrix - provides access to all 48 macros. - group of 48 can be dragged to/from it's default position just below the main menu bar * change vertical raster height to 20 vice 60 - decreased minimum vertical main dialog dimension for small netbook screens * update to documentation --- fldigi_doxygen/images/macro-matrix.png | Bin 0 -> 34699 bytes fldigi_doxygen/images/macro-scheme-4.png | Bin 0 -> 16047 bytes fldigi_doxygen/images/view-hide-48.png | Bin 0 -> 8153 bytes .../user_src_docs/ConfigUI-macros.txt | 32 +- fldigi_doxygen/user_src_docs/Macros.txt | 32 +- src/Makefile.am | 11 + src/dialogs/fl_digi.cxx | 429 +++++++++++++----- src/feld/feld.cxx | 3 + src/include/dock_events.h | 9 + src/include/dock_gp.h | 31 ++ src/include/drag_btn.h | 27 ++ src/include/dropwin.h | 39 ++ src/include/feld.h | 14 +- src/include/fl_digi.h | 5 +- src/include/raster.h | 1 + src/include/status.h | 2 + src/include/toolgrp.h | 72 +++ src/include/toolwin.h | 37 ++ src/misc/status.cxx | 7 + src/waterfall/raster.cxx | 2 +- src/widgets/dock_gp.cxx | 59 +++ src/widgets/drag_btn.cxx | 144 ++++++ src/widgets/dropwin.cxx | 67 +++ src/widgets/toolgrp.cxx | 204 +++++++++ src/widgets/toolwin.cxx | 101 +++++ 25 files changed, 1203 insertions(+), 125 deletions(-) create mode 100644 fldigi_doxygen/images/macro-matrix.png create mode 100644 fldigi_doxygen/images/macro-scheme-4.png create mode 100644 fldigi_doxygen/images/view-hide-48.png create mode 100644 src/include/dock_events.h create mode 100644 src/include/dock_gp.h create mode 100644 src/include/drag_btn.h create mode 100644 src/include/dropwin.h create mode 100644 src/include/toolgrp.h create mode 100644 src/include/toolwin.h create mode 100644 src/widgets/dock_gp.cxx create mode 100644 src/widgets/drag_btn.cxx create mode 100644 src/widgets/dropwin.cxx create mode 100644 src/widgets/toolgrp.cxx create mode 100644 src/widgets/toolwin.cxx diff --git a/fldigi_doxygen/images/macro-matrix.png b/fldigi_doxygen/images/macro-matrix.png new file mode 100644 index 0000000000000000000000000000000000000000..05d92de537b8b8681bd2fce600524685a9373dc8 GIT binary patch literal 34699 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 k-V!Z07*qoM6N<$f^$nduK)l5 literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/images/macro-scheme-4.png b/fldigi_doxygen/images/macro-scheme-4.png new file mode 100644 index 0000000000000000000000000000000000000000..ab945e7d896555accb50218e26b4b6242e480be7 GIT binary patch literal 16047 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 literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/images/view-hide-48.png b/fldigi_doxygen/images/view-hide-48.png new file mode 100644 index 0000000000000000000000000000000000000000..6e866f2e6cbf2f050d50a66f39cc51b6cbc503f0 GIT binary patch literal 8153 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 literal 0 HcmV?d00001 diff --git a/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt b/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt index 44fb270c..212c5c12 100644 --- a/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt +++ b/fldigi_doxygen/user_src_docs/ConfigUI-macros.txt @@ -30,9 +30,16 @@ fldigi macro bar positions will change immediately so you can see the selection.
-With 2 rows shown you obtain access to the primary set with normal -Function key press. The secondary set is accessed by a -SHIFT-Function-key press. +
+\image html macrobuttons.png "Macro Buttons" +\image latex macrobuttons.png "Macro Buttons" width=6.0in +
+
+ +
+\image html macro-scheme-4.png "Macro Buttons - Scheme 4" +\image latex macro-scheme-4.png "Macro Buttons - Scheme 4" width=6.0in +

You edit any macro definition by using a mouse right-click on it's button. @@ -43,6 +50,25 @@ sub-sets. When checked you simply hover the mouse over the macro bar and roll the mouse wheel.
+All 48 macro buttons can be displayed in a matrix. + +\image html macro-matrix.png "Macro Buttons Matrix" +\image latex macro-matrix.png "Macro Buttons Matrix" width=6.0in +
+ +The matrix display is toggled on and off using the menu item +
+\image html view-hide-48.png "" +\image latex view-hide-48.png "" width=1.0in +
+
+ +The matrix display can be dragged off and restored to it's position below +the main menu. The drag button is the knurled vertical button on the left +edge of the matrix. Left click on the drag button and drag the matrix with +the mouse. +
+ Fldigi manages multiple files that contain macro definitions. You may want to have the last used macro file be the one available the next time you start fldigi. If so, simply enable the "load last used Macro file on diff --git a/fldigi_doxygen/user_src_docs/Macros.txt b/fldigi_doxygen/user_src_docs/Macros.txt index bbbdf193..32990359 100644 --- a/fldigi_doxygen/user_src_docs/Macros.txt +++ b/fldigi_doxygen/user_src_docs/Macros.txt @@ -4,9 +4,17 @@ \tableofcontents Macros are short text statements that contain imbedded references to text -data used by the program fldigi. Macro definition files(s) are located -in the $HOME/.fldigi/macros/ directory and all have the extention ".mdf". The -default set of macros are contained in the +data used by the program fldigi. A macro is accessed via the macro button +bar or function key. + +
+\image html macrobuttons.png "Macro Buttons" +\image latex macrobuttons.png "Macro Buttons" width=6.0in +
+
+ +Macro definition files(s) are located in the $HOME/.fldigi/macros/ directory +and all have the extention ".mdf". The default set of macros are contained in the file $HOME/.fldigi/macros/macros.mdf. Fldigi will create this file with a set of default macros on its first @@ -15,7 +23,23 @@ execution. Fldigi supports up to 48 macro definitions in sets of 12. Macro definitions are not recursive, that is; a macro cannot reference -another macro or itself. +another macro or itself. All 48 macro buttons can be displayed in a matrix. + +\image html macro-matrix.png "Macro Buttons Matrix" +\image latex macro-matrix.png "Macro Buttons Matrix" width=6.0in +
+ +The matrix display is toggled on and off using the menu item +
+\image html view-hide-48.png "" +\image latex view-hide-48.png "" width=1.0in +
+
+ +The matrix display can be dragged off and restored to it's position below +the main menu. The drag button is the knurled vertical button on the left +edge of the matrix. Left click on the drag button and drag the matrix with +the mouse.
The imbedded references are similar to those used by DigiPan and other diff --git a/src/Makefile.am b/src/Makefile.am index 8a39ab87..7d2b0e48 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -493,6 +493,12 @@ fldigi_SOURCES += \ include/psk_browser.h \ include/utf8file_io.h \ include/weather.h \ + include/dock_events.h \ + include/dock_gp.h \ + include/drag_btn.h \ + include/dropwin.h \ + include/toolgrp.h \ + include/toolwin.h \ irrxml/CXMLReaderImpl.h \ irrxml/fast_atof.h \ irrxml/heapsort.h \ @@ -605,6 +611,11 @@ fldigi_SOURCES += \ widgets/psk_browser.cxx \ widgets/smeter.cxx \ widgets/pwrmeter.cxx \ + widgets/dock_gp.cxx \ + widgets/drag_btn.cxx \ + widgets/dropwin.cxx \ + widgets/toolgrp.cxx \ + widgets/toolwin.cxx \ fsq/fsq.cxx \ ifkp/ifkp.cxx \ ifkp/tux.cxx \ diff --git a/src/dialogs/fl_digi.cxx b/src/dialogs/fl_digi.cxx index 7facfb3c..492c57ae 100644 --- a/src/dialogs/fl_digi.cxx +++ b/src/dialogs/fl_digi.cxx @@ -163,6 +163,10 @@ #include "record_loader.h" #include "record_browse.h" +#include "toolgrp.h" +#include "dropwin.h" +#include "dock_events.h" + #define CB_WHEN FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED | FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE #define LOG_TO_FILE_MLABEL _("Log all RX/TX text") @@ -216,7 +220,14 @@ fre_t seek_re("CQ", REG_EXTENDED | REG_ICASE | REG_NOSUB); bool bWF_only = false; bool withnoise = false; -Fl_Double_Window *fl_digi_main = (Fl_Double_Window *)0; +//Fl_Double_Window *fl_digi_main = (Fl_Double_Window *)0; +dropwin *fl_digi_main; + +dockgroup *dock; // the macro buttons dock + +Fl_Button *btnDockMacro[48]; +toolgrp *tgroup; + Fl_Help_Dialog *help_dialog = (Fl_Help_Dialog *)0; Fl_Double_Window *scopeview = (Fl_Double_Window *)0; @@ -230,6 +241,7 @@ Fl_Light_Button *btnTxRSID = (Fl_Light_Button *)0; static Fl_Button *btnMacroTimer = (Fl_Button *)0; Fl_Group *center_group = (Fl_Group *)0; +Fl_Group *text_group; Fl_Group *wefax_group = 0; Fl_Group *mvgroup = 0; @@ -412,8 +424,10 @@ static const int Wbtn = Hentry; static int x_qsoframe = Wbtn; int Hmenu = 22; static const int Hqsoframe = pad + 3 * (Hentry + pad); -int Hstatus = 22; -int Hmacros = 22; +int Hstatus = 22; +int Hmacros = 22; + +#define TB_HEIGHT (20*4 + 6) static const int sw = 22; static const int wf1 = 395; @@ -424,7 +438,9 @@ static const int w_inpRstIn2 = 30; static const int w_inpRstOut2 = 30; // minimum height for raster display, FeldHell, is 66 pixels -static const int minhtext = 66*2+4; // 66 : raster min height x 2 : min panel box, 4 : frame +// )FELD-HELL raster min height) + frame width * 2 +static const int minhtext = FELD_RX_COLUMN_LEN * 2 + 6; +static const int mintxtext = 80; static int main_hmin = HMIN; @@ -1116,25 +1132,32 @@ void startup_modem(modem* m, int f) if (!bWF_only) { if (id >= MODE_WEFAX_FIRST && id <= MODE_WEFAX_LAST) { - center_group->hide(); +// center_group->hide(); + text_group->hide(); fsq_group->hide(); ifkp_group->hide(); wefax_group->show(); - wefax_group->redraw(); +// wefax_group->redraw(); + center_group->redraw(); } else if (id == MODE_FSQ) { - center_group->hide(); +// center_group->hide(); + text_group->hide(); wefax_group->hide(); ifkp_group->hide(); fsq_group->show(); - fsq_group->redraw(); +// fsq_group->redraw(); + center_group->redraw(); } else if (id == MODE_IFKP) { - center_group->hide(); +// center_group->hide(); + text_group->hide(); wefax_group->hide(); fsq_group->hide(); ifkp_group->show(); - ifkp_group->redraw(); +// ifkp_group->redraw(); + center_group->redraw(); } else { - center_group->show(); +// center_group->show(); + text_group->show(); wefax_group->hide(); fsq_group->hide(); ifkp_group->hide(); @@ -1321,6 +1344,7 @@ void remove_windows() fsqMonitor->hide(); delete fsqMonitor; } + tgroup->hide_all(); // if (fsqDebug) { // fsqDebug->hide(); @@ -1825,6 +1849,41 @@ void macro_cb(Fl_Widget *w, void *v) restoreFocus(5); } +void colorize_docked_macros(int i) +{ + if (progdefaults.useGroupColors == true) { + int k = i / 4; + if (k == 0 || k == 3 || k == 6 || k == 9) + btnDockMacro[i]->color(fl_rgb_color( + progdefaults.btnGroup1.R, + progdefaults.btnGroup1.G, + progdefaults.btnGroup1.B)); + else if (k == 1 || k == 4 || k == 7 || k == 10) + btnDockMacro[i]->color(fl_rgb_color( + progdefaults.btnGroup2.R, + progdefaults.btnGroup2.G, + progdefaults.btnGroup2.B)); + else + btnDockMacro[i]->color(fl_rgb_color( + progdefaults.btnGroup3.R, + progdefaults.btnGroup3.G, + progdefaults.btnGroup3.B)); + btnDockMacro[i]->labelcolor( + fl_rgb_color( + progdefaults.btnFkeyTextColor.R, + progdefaults.btnFkeyTextColor.G, + progdefaults.btnFkeyTextColor.B )); + btnDockMacro[i]->labelcolor(progdefaults.MacroBtnFontcolor); + btnDockMacro[i]->labelfont(progdefaults.MacroBtnFontnbr); + btnDockMacro[i]->labelsize(progdefaults.MacroBtnFontsize); + } else { + btnDockMacro[i]->color(FL_BACKGROUND_COLOR); + btnDockMacro[i]->labelcolor(FL_FOREGROUND_COLOR); + btnDockMacro[i]->labelfont(progdefaults.MacroBtnFontnbr); + btnDockMacro[i]->labelsize(progdefaults.MacroBtnFontsize); + } +} + void colorize_macro(int i) { int j = i % NUMMACKEYS; @@ -1865,10 +1924,8 @@ void colorize_macro(int i) void colorize_macros() { FL_LOCK_D(); - for (int i = 0; i < NUMMACKEYS * NUMKEYROWS; i++) { - colorize_macro(i); - btnMacro[i]->redraw_label(); - } + for (int i = 0; i < NUMMACKEYS * NUMKEYROWS; i++) colorize_macro(i); + for (int i = 0; i < 48; i++) colorize_docked_macros(i); btnAltMacros1->labelsize(progdefaults.MacroBtnFontsize); btnAltMacros1->redraw_label(); btnAltMacros2->labelsize(progdefaults.MacroBtnFontsize); @@ -2104,8 +2161,13 @@ void cb_view_hide_channels(Fl_Menu_ *w, void *d) progStatus.tile_x = save_mvx; } - if (progdefaults.rxtx_swap) progStatus.tile_y = TransmitText->h(); - else progStatus.tile_y = ReceiveText->h(); + if (progdefaults.rxtx_swap) { + progStatus.tile_y = TransmitText->h(); + progStatus.tile_y_ratio = 1.0 * TransmitText->h() / text_panel->h(); + } else { + progStatus.tile_y = ReceiveText->h(); + progStatus.tile_y_ratio = 1.0 * ReceiveText->h() / text_panel->h(); + } UI_select(); return; @@ -2311,7 +2373,7 @@ void cb_mnuCheckUpdate(Fl_Widget *, void *) if (is_ok) fl_message2(_("You are running the latest version")); else { - int choice = + int choice = fl_choice2(_("Version %s is available at Source Forge\n\nWhat would you like to do?"), _("Close"), _("Visit URL"), _("Copy URL"), version_str.c_str()); @@ -2577,6 +2639,10 @@ void set_macroLabels() btnMacro[i]->redraw_label(); } } + for (int i = 0; i < 48; i++) { + btnDockMacro[i]->label(macros.name[i].c_str()); + btnDockMacro[i]->redraw_label(); + } } void cb_mnuPicViewer(Fl_Menu_ *, void *) { @@ -2837,7 +2903,7 @@ if (bWF_only) return; if (active_modem->get_mode() == MODE_IFKP) ifkp_load_avatar(inpCall->value()); - if (active_modem->get_mode() >= MODE_THOR11 && + if (active_modem->get_mode() >= MODE_THOR11 && active_modem->get_mode() <= MODE_THOR22) thor_load_avatar(inpCall->value()); @@ -3419,6 +3485,7 @@ void UI_check_swap() text_panel->add(minbox); text_panel->resizable(minbox); progStatus.tile_y = TransmitText->h(); + progStatus.tile_y_ratio = 1.0 * TransmitText->h() / text_panel->h(); } if (!progdefaults.rxtx_swap && ReceiveText->y() > TransmitText->y()) { rx_y = TransmitText->y(); @@ -3452,6 +3519,7 @@ void UI_check_swap() text_panel->add(minbox); text_panel->resizable(minbox); progStatus.tile_y = ReceiveText->h(); + progStatus.tile_y_ratio = 1.0 * ReceiveText->h() / text_panel->h(); } // resize fsq UI @@ -3521,12 +3589,14 @@ void resize_macroframe1(int x, int y, int w, int h) { macroFrame1->resize(x, y, w, h); macroFrame1->init_sizes(); + macroFrame1->redraw(); } void resize_macroframe2(int x, int y, int w, int h) { macroFrame2->resize(x, y, w, h); macroFrame2->init_sizes(); + macroFrame2->redraw(); } int UI_position_macros(int x, int y1, int w, int HTh) @@ -3534,18 +3604,41 @@ int UI_position_macros(int x, int y1, int w, int HTh) int mh = progdefaults.macro_height; int mh2 = progdefaults.macro_height / 2; +// docked macro's + + if (progStatus.tbar_is_docked) { + resize_macroframe2(x,y1,w,mh2); + macroFrame2->hide(); + btnAltMacros2->deactivate(); + resize_macroframe1(x,y1,w,mh2); + macroFrame1->hide(); + HTh += mh; + center_group->resize(x, y1, w, HTh); + wefax_group->resize(x, y1, w, HTh); + fsq_group->resize(x, y1, w, HTh); + ifkp_group->resize(x, y1, w, HTh); + UI_select_central_frame(y1, HTh); + y1 += HTh; + wfpack->position(x, y1); + y1 += wfpack->h(); + hpack->position(x, y1); + fl_digi_main->workspace->init_sizes(); + return y1; + } + switch (progdefaults.mbar_scheme) { // 0, 1, 2 one bar schema case 0: - macroFrame2->size(macroFrame2->w(), 0); + resize_macroframe2(x,y1,w,mh); macroFrame2->hide(); btnAltMacros2->deactivate(); - resize_macroframe1(0, y1, w, mh); + resize_macroframe1(x, y1, w, mh); + macroFrame1->show(); btnAltMacros1->activate(); y1 += mh; - center_group->resize(0, y1, w, HTh); - wefax_group->resize(0, y1, w, HTh); - fsq_group->resize(0, y1, w, HTh); - ifkp_group->resize(0, y1, w, HTh); + center_group->resize(x, y1, w, HTh); + wefax_group->resize(x, y1, w, HTh); + fsq_group->resize(x, y1, w, HTh); + ifkp_group->resize(x, y1, w, HTh); UI_select_central_frame(y1, HTh); y1 += HTh; wfpack->position(x, y1); @@ -3554,7 +3647,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) break; default: case 1: - macroFrame2->size(macroFrame2->w(), 0); + resize_macroframe2(x,y1,w,mh); macroFrame2->hide(); btnAltMacros2->deactivate(); center_group->resize(0, y1, w, HTh); @@ -3564,6 +3657,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) UI_select_central_frame(y1, HTh); y1 += HTh; resize_macroframe1(0, y1, w, mh); + macroFrame1->show(); btnAltMacros1->activate(); y1 += mh; wfpack->position(x, y1); @@ -3571,7 +3665,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) hpack->position(x, y1); break; case 2: - macroFrame2->size(macroFrame2->w(), 0); + resize_macroframe2(x,y1,w,mh); macroFrame2->hide(); btnAltMacros2->deactivate(); center_group->resize(0, y1, w, HTh); @@ -3583,12 +3677,14 @@ int UI_position_macros(int x, int y1, int w, int HTh) wfpack->position(x, y1); y1 += wfpack->h(); resize_macroframe1(0, y1, w, mh); + macroFrame1->show(); btnAltMacros1->activate(); y1 += mh; hpack->position(x, y1); break; case 3: resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; resize_macroframe2(0, y1, w, mh2); @@ -3611,6 +3707,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) btnAltMacros2->activate(); y1 += mh2; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; center_group->resize(0, y1, w, HTh); @@ -3631,6 +3728,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) UI_select_central_frame(y1, HTh); y1 += HTh; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; resize_macroframe2(0, y1, w, mh2); @@ -3652,6 +3750,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) btnAltMacros2->activate(); y1 += mh2; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; wfpack->position(x, y1); @@ -3666,6 +3765,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) UI_select_central_frame(y1, HTh); y1 += HTh; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; wfpack->position(x, y1); @@ -3687,6 +3787,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) wfpack->position(x, y1); y1 += wfpack->h(); resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; hpack->position(x, y1); @@ -3701,6 +3802,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) wfpack->position(x, y1); y1 += wfpack->h(); resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; resize_macroframe2(0, y1, w, mh2); @@ -3723,6 +3825,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) btnAltMacros2->activate(); y1 += mh2; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; hpack->position(x, y1); @@ -3739,6 +3842,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) UI_select_central_frame(y1, HTh); y1 += HTh; resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; wfpack->position(x, y1); @@ -3747,6 +3851,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) break; case 12: resize_macroframe1(0, y1, w, mh2); + macroFrame1->show(); btnAltMacros1->deactivate(); y1 += mh2; center_group->resize(0, y1, w, HTh); @@ -3764,6 +3869,7 @@ int UI_position_macros(int x, int y1, int w, int HTh) hpack->position(x, y1); break; } + fl_digi_main->workspace->init_sizes(); return y1; } @@ -3785,10 +3891,10 @@ void UI_select() getMenuItem(RIGLOG_FULL_MLABEL)->setonly(); } - int x = macroFrame1->x(); - int y1 = TopFrame1->y(); - int w = fl_digi_main->w(); - int HTh; + int x = fl_digi_main->workspace->x();//macroFrame1->x(); + int y1 = fl_digi_main->workspace->y();//TopFrame1->y(); + int w = fl_digi_main->workspace->w();//fl_digi_main->w(); + int HTh = fl_digi_main->workspace->h(); if (cnt_macro_height) { if (progdefaults.mbar_scheme > MACRO_SINGLE_BAR_MAX) { // 2 bars @@ -3803,10 +3909,8 @@ void UI_select() cnt_macro_height->value(progdefaults.macro_height); } - HTh = fl_digi_main->h(); HTh -= wfpack->h(); HTh -= hpack->h(); - HTh -= Hstatus; HTh -= progdefaults.macro_height; if (progStatus.NO_RIGLOG && !restore_minimize) { @@ -3882,7 +3986,7 @@ UI_return: int orgx = text_panel->orgx(); int orgy = text_panel->orgy(); int nux = text_panel->x() + progStatus.tile_x; - int nuy = text_panel->y() + progStatus.tile_y; + int nuy = text_panel->y() + progStatus.tile_y_ratio * text_group->h(); text_panel->position( orgx, orgy, nux, nuy); @@ -3900,6 +4004,11 @@ UI_return: } +void cb_docked(Fl_Widget*, void*) +{ + UI_select(); +} + void cb_mnu_wf_all(Fl_Menu_* w, void *d) { wf->UI_select(progStatus.WF_UI = w->mvalue()->value()); @@ -3983,6 +4092,14 @@ void cb_menu_make_default_scripts(Fl_Widget*, void*) cb_create_default_script(); } +void cb_view_hide_macros(Fl_Widget*, void*) +{ + progStatus.tile_y = progdefaults.rxtx_swap ? TransmitText->h() : ReceiveText->h(); + progStatus.tile_y_ratio = 1.0 * progStatus.tile_y / text_group->h(); + + progStatus.tbar_is_docked = progStatus.tbar_is_docked ? 0 : 1; + tgroup->hide_show(); +} static void cb_opmode_show(Fl_Widget* w, void*); @@ -4257,6 +4374,7 @@ _FL_MULTI_LABEL, 0, 14, 0}, { VIEW_MLABEL, 0, 0, 0, FL_SUBMENU, FL_NORMAL_LABEL, 0, 14, 0}, { icons::make_icon_label(_("View/Hide Channels")), 'v', (Fl_Callback*)cb_view_hide_channels, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, +{ icons::make_icon_label(_("View/Hide 48 macros")), 0, (Fl_Callback*)cb_view_hide_macros, 0, FL_MENU_DIVIDER, _FL_MULTI_LABEL, 0, 14, 0}, { icons::make_icon_label(_("Floating scope"), utilities_system_monitor_icon), 'd', (Fl_Callback*)cb_mnuDigiscope, 0, 0, _FL_MULTI_LABEL, 0, 14, 0}, { icons::make_icon_label(MFSK_IMAGE_MLABEL, image_icon), 'm', (Fl_Callback*)cb_mnuPicViewer, 0, FL_MENU_INACTIVE, _FL_MULTI_LABEL, 0, 14, 0}, @@ -5290,6 +5408,38 @@ inline int next_to(Fl_Widget* w) return w->x() + w->w() + pad; } +static void add_docked(dockgroup *dock) +{ + // Create a docked toolgroup + int w = dock->w(); + int h = dock->h(); + int Wbtn = (w-18) / 12; + int Hbtn = (h-4) / 4; + int xpos = 16; + int ypos = 2; + + tgroup = new toolgrp(dock, 0, w, h); + + for (int i = 0; i < 48; i++) { + btnDockMacro[i] = new Fl_Button( + xpos, ypos, + ((i % 12) == 11) ? w - xpos - 4 : Wbtn, Hbtn, ""); + btnDockMacro[i]->box(FL_THIN_UP_BOX); + btnDockMacro[i]->tooltip(_("Left Click - execute\nRight Click - edit")); + btnDockMacro[i]->callback(macro_cb, reinterpret_cast(i)); + + xpos += Wbtn; + if (i == 11 || i == 23 || i == 35) { + xpos = 16; + ypos += Hbtn; + if (i == 35) Hbtn = tgroup->h() - ypos - 2; + } + } + + tgroup->end(); + tgroup->box(FL_FLAT_BOX);//ENGRAVED_BOX);//NO_BOX);//BORDER_BOX); +} + void create_fl_digi_main_primary() { // bx used as a temporary spacer Fl_Box *bx; @@ -5317,16 +5467,27 @@ void create_fl_digi_main_primary() { Wwfall = progStatus.mainW - 2 * DEFAULT_SW; - main_hmin = minhtext + Hwfall + Hmenu + Hstatus + Hmacros*3 + Hqsoframe + 3; + int fixed_height = + Hmenu + + TB_HEIGHT + + Hqsoframe + + Hmacros*3 + + Hwfall + + Hstatus + + 16; // inter group spacings + + main_hmin = minhtext + mintxtext + 5 + fixed_height; + if (progStatus.mainH < main_hmin) progStatus.mainH = main_hmin; - int Htext = progStatus.mainH - Hwfall - Hmenu - Hstatus - Hmacros*NUMKEYROWS - Hqsoframe - 3; + int Htext = main_hmin - fixed_height; + if (progStatus.tile_y > Htext) progStatus.tile_y = Htext / 2; - fl_digi_main = new Fl_Double_Window(progStatus.mainW, progStatus.mainH); + fl_digi_main = new dropwin(progStatus.mainW, main_hmin);//progStatus.mainH); mnuFrame = new Fl_Group(0,0,progStatus.mainW, Hmenu); - mnu = new Fl_Menu_Bar(0, 0, progStatus.mainW - 250 - pad, Hmenu); + mnu = new Fl_Menu_Bar(pad, 0, progStatus.mainW - 250 - 2*pad, Hmenu); // do some more work on the menu for (size_t i = 0; i < sizeof(menu_)/sizeof(menu_[0]); i++) { // FL_NORMAL_SIZE may have changed; update the menu items @@ -5367,6 +5528,26 @@ void create_fl_digi_main_primary() { mnuFrame->resizable(mnu); mnuFrame->end(); +// add draggable toolbar with 4 rows of 12 macros each + dock = new dockgroup(pad, mnu->h() + 2, fl_digi_main->w() - 2*pad, TB_HEIGHT); + dock->box(FL_THIN_DOWN_BOX); + dock->end(); + dock->set_window(fl_digi_main); + + // Create a toolgroup already docked in this dock + add_docked(dock); + dock->redraw(); + + // Record in the dropwin which dock to use + fl_digi_main->set_dock(dock); + + fl_digi_main->begin(); + +// docked window workspace + fl_digi_main->workspace = new Fl_Group( + pad, dock->y() + dock->h(), + dock->w(), fl_digi_main->h() - dock->h() - dock->y() - pad); + // reset the message dialog font fl_message_font(FL_HELVETICA, FL_NORMAL_SIZE); @@ -5375,7 +5556,9 @@ void create_fl_digi_main_primary() { Fl_Tooltip::size(FL_NORMAL_SIZE); Fl_Tooltip::enable(progdefaults.tooltips); - TopFrame1 = new Fl_Group(0, Hmenu, progStatus.mainW, Hqsoframe); + TopFrame1 = new Fl_Group( + 0, fl_digi_main->workspace->y(), + fl_digi_main->workspace->w(), Hqsoframe); int fnt1 = progdefaults.FreqControlFontnbr; int freqheight1 = 2 * Hentry + pad; @@ -5387,12 +5570,14 @@ void create_fl_digi_main_primary() { int rig_control_frame_width = freqwidth1 + 3 * pad; RigControlFrame = new Fl_Group( - 0, Hmenu, rig_control_frame_width, Hqsoframe); + 0, fl_digi_main->workspace->y(), + rig_control_frame_width, Hqsoframe); RigControlFrame->box(FL_FLAT_BOX); qsoFreqDisp1 = new cFreqControl( - pad, Hmenu + pad, freqwidth1, freqheight1, "10"); + pad, RigControlFrame->y() + pad, + freqwidth1, freqheight1, "10"); qsoFreqDisp1->box(FL_DOWN_BOX); qsoFreqDisp1->color(FL_BACKGROUND_COLOR); qsoFreqDisp1->selection_color(FL_BACKGROUND_COLOR); @@ -5444,8 +5629,8 @@ void create_fl_digi_main_primary() { qso_opMODE->end(); qso_opBW = new Fl_ComboBox( - qso_opMODE->x() + mode_cbo_w + pad, - smeter->y(), + qso_opMODE->x() + mode_cbo_w + pad, + smeter->y(), bw_cbo_w, Hentry); qso_opBW->box(FL_DOWN_BOX); qso_opBW->color(FL_BACKGROUND2_COLOR); @@ -5460,8 +5645,8 @@ void create_fl_digi_main_primary() { qso_opBW->end(); qso_opGROUP = new Fl_Group( - qso_opMODE->x() + mode_cbo_w + pad, - smeter->y(), + qso_opMODE->x() + mode_cbo_w + pad, + smeter->y(), bw_cbo_w, Hentry); qso_opGROUP->box(FL_FLAT_BOX); @@ -5533,53 +5718,53 @@ void create_fl_digi_main_primary() { int opB_w = wf1 - 2 * (Wbtn + pad) + pad; RigViewerFrame = new Fl_Group( - rightof(RigControlFrame) + pad, Hmenu, + rightof(RigControlFrame) + pad, RigControlFrame->y(), wf1, Hqsoframe); qso_btnSelFreq = new Fl_Button( - RigViewerFrame->x(), Hmenu + pad, + RigViewerFrame->x(), RigViewerFrame->y() + pad, Wbtn, Hentry); qso_btnSelFreq->image(new Fl_Pixmap(left_arrow_icon)); qso_btnSelFreq->tooltip(_("Select")); qso_btnSelFreq->callback((Fl_Callback*)cb_qso_btnSelFreq); qso_btnAddFreq = new Fl_Button( - rightof(qso_btnSelFreq) + pad, Hmenu + pad, + rightof(qso_btnSelFreq) + pad, RigViewerFrame->y() + pad, Wbtn, Hentry); qso_btnAddFreq->image(new Fl_Pixmap(plus_icon)); qso_btnAddFreq->tooltip(_("Add current frequency")); qso_btnAddFreq->callback((Fl_Callback*)cb_qso_btnAddFreq); qso_btnClearList = new Fl_Button( - RigViewerFrame->x(), Hmenu + Hentry + 2 * pad, + RigViewerFrame->x(), RigViewerFrame->y() + Hentry + 2 * pad, Wbtn, Hentry); qso_btnClearList->image(new Fl_Pixmap(trash_icon)); qso_btnClearList->tooltip(_("Clear list")); qso_btnClearList->callback((Fl_Callback*)cb_qso_btnClearList); qso_btnDelFreq = new Fl_Button( - rightof(qso_btnClearList) + pad, Hmenu + Hentry + 2 * pad, + rightof(qso_btnClearList) + pad, RigViewerFrame->y() + Hentry + 2 * pad, Wbtn, Hentry); qso_btnDelFreq->image(new Fl_Pixmap(minus_icon)); qso_btnDelFreq->tooltip(_("Delete from list")); qso_btnDelFreq->callback((Fl_Callback*)cb_qso_btnDelFreq); qso_btnAct = new Fl_Button( - RigViewerFrame->x(), Hmenu + 2*(Hentry + pad) + pad, + RigViewerFrame->x(), RigViewerFrame->y() + 2*(Hentry + pad) + pad, Wbtn, Hentry); qso_btnAct->image(new Fl_Pixmap(chat_icon)); qso_btnAct->callback(cb_qso_inpAct); qso_btnAct->tooltip("Show active frequencies"); qso_inpAct = new Fl_Input2( - rightof(qso_btnAct) + pad, Hmenu + 2*(Hentry + pad) + pad, + rightof(qso_btnAct) + pad, RigViewerFrame->y() + 2*(Hentry + pad) + pad, Wbtn, Hentry); qso_inpAct->when(FL_WHEN_ENTER_KEY | FL_WHEN_NOT_CHANGED); qso_inpAct->callback(cb_qso_inpAct); qso_inpAct->tooltip("Grid prefix for activity list"); qso_opBrowser = new Fl_Browser( - rightof(qso_btnDelFreq) + pad, Hmenu + pad, + rightof(qso_btnDelFreq) + pad, RigViewerFrame->y() + pad, opB_w, Hqsoframe - 2 * pad ); // use fixed column widths of 28%, 20%, 30% ... remainder is 4th column static int opB_widths[] = {28*opB_w/100, 20*opB_w/100, 30*opB_w/100, 0}; @@ -5603,13 +5788,13 @@ void create_fl_digi_main_primary() { RigViewerFrame->end(); RigViewerFrame->hide(); - int y2 = Hmenu + Hentry + 2 * pad; - int y3 = Hmenu + 2 * (Hentry + pad) + pad; + int y2 = fl_digi_main->workspace->y() + Hentry + 2 * pad; + int y3 = fl_digi_main->workspace->y() + 2 * (Hentry + pad) + pad; x_qsoframe = RigViewerFrame->x(); QsoInfoFrame = new Fl_Group( - x_qsoframe, Hmenu, + x_qsoframe, fl_digi_main->workspace->y(), progStatus.mainW - x_qsoframe - pad, Hqsoframe); btnQRZ = new Fl_Button( @@ -5632,40 +5817,41 @@ void create_fl_digi_main_primary() { QsoInfoFrame1 = new Fl_Group( rightof(btnQRZ) + pad, - Hmenu, wf1, Hqsoframe); + fl_digi_main->workspace->y(), wf1, Hqsoframe); inpFreq1 = new Fl_Input2( QsoInfoFrame1->x() + 25, - Hmenu + pad, 90, Hentry, _("Frq")); + fl_digi_main->workspace->y() + pad, 90, Hentry, _("Frq")); inpFreq1->type(FL_NORMAL_OUTPUT); inpFreq1->tooltip(_("frequency kHz")); inpFreq1->align(FL_ALIGN_LEFT); btnTimeOn = new Fl_Button( - next_to(inpFreq1), Hmenu + pad, Hentry, Hentry, _("On")); + next_to(inpFreq1), fl_digi_main->workspace->y() + pad, + Hentry, Hentry, _("On")); btnTimeOn->tooltip(_("Press to update QSO start time")); btnTimeOn->callback(cb_btnTimeOn); inpTimeOn1 = new Fl_Input2( - next_to(btnTimeOn), Hmenu + pad, + next_to(btnTimeOn), fl_digi_main->workspace->y() + pad, 40, Hentry, ""); inpTimeOn1->tooltip(_("QSO start time")); inpTimeOn1->align(FL_ALIGN_LEFT); inpTimeOn1->type(FL_INT_INPUT); inpTimeOff1 = new Fl_Input2( - next_to(inpTimeOn1) + 20, Hmenu + pad, 40, Hentry, _("Off")); + next_to(inpTimeOn1) + 20, fl_digi_main->workspace->y() + pad, 40, Hentry, _("Off")); inpTimeOff1->tooltip(_("QSO end time")); inpTimeOff1->align(FL_ALIGN_LEFT); inpTimeOff1->type(FL_NORMAL_OUTPUT); inpRstIn1 = new Fl_Input2( - next_to(inpTimeOff1) + 40, Hmenu + pad, 40, Hentry, _("In")); + next_to(inpTimeOff1) + 40, fl_digi_main->workspace->y() + pad, 40, Hentry, _("In")); inpRstIn1->tooltip("RST in"); inpRstIn1->align(FL_ALIGN_LEFT); inpRstOut1 = new Fl_Input2( - next_to(inpRstIn1) + 30, Hmenu + pad, 40, Hentry, _("Out")); + next_to(inpRstIn1) + 30, fl_digi_main->workspace->y() + pad, 40, Hentry, _("Out")); inpRstOut1->tooltip("RST out"); inpRstOut1->align(FL_ALIGN_LEFT); @@ -5740,11 +5926,11 @@ void create_fl_digi_main_primary() { QsoInfoFrame1->end(); QsoInfoFrame2 = new Fl_Group( - rightof(QsoInfoFrame1) + pad, Hmenu, + rightof(QsoInfoFrame1) + pad, fl_digi_main->workspace->y(), progStatus.mainW - rightof(QsoInfoFrame1) - 2*pad, Hqsoframe); inpCountry = new Fl_Input2( - rightof(QsoInfoFrame1) + pad, Hmenu + pad, + rightof(QsoInfoFrame1) + pad, fl_digi_main->workspace->y() + pad, QsoInfoFrame2->w(), Hentry, ""); inpCountry->tooltip(_("Country")); @@ -5759,7 +5945,7 @@ void create_fl_digi_main_primary() { QsoInfoFrame->resizable(QsoInfoFrame2); ifkp_avatar = new picture( - QsoInfoFrame2->x() + QsoInfoFrame2->w() - 59, Hmenu + pad, 59, 74); + QsoInfoFrame2->x() + QsoInfoFrame2->w() - 59, fl_digi_main->workspace->y() + pad, 59, 74); ifkp_avatar->box(FL_FLAT_BOX); ifkp_avatar->noslant(); ifkp_avatar->callback(cb_ifkp_send_avatar); @@ -5768,7 +5954,7 @@ void create_fl_digi_main_primary() { ifkp_avatar->hide(); thor_avatar = new picture( - QsoInfoFrame2->x() + QsoInfoFrame2->w() - 59, Hmenu + pad, 59, 74); + QsoInfoFrame2->x() + QsoInfoFrame2->w() - 59, fl_digi_main->workspace->y() + pad, 59, 74); thor_avatar->box(FL_FLAT_BOX); thor_avatar->noslant(); thor_avatar->callback(cb_thor_send_avatar); @@ -5782,9 +5968,9 @@ void create_fl_digi_main_primary() { TopFrame1->end(); - TopFrame2 = new Fl_Group(0, Hmenu, progStatus.mainW, Hentry + 2 * pad); + TopFrame2 = new Fl_Group(0, fl_digi_main->workspace->y(), progStatus.mainW, Hentry + 2 * pad); { - int y = Hmenu + pad; + int y = fl_digi_main->workspace->y() + pad; int h = Hentry; qsoFreqDisp2 = new cFreqControl( pad, y, @@ -5894,9 +6080,9 @@ void create_fl_digi_main_primary() { TopFrame2->end(); TopFrame2->hide(); - TopFrame3 = new Fl_Group(0, Hmenu, progStatus.mainW, Hentry + 2 * pad); + TopFrame3 = new Fl_Group(0, fl_digi_main->workspace->y(), progStatus.mainW, Hentry + 2 * pad); { - int y = Hmenu + pad; + int y = fl_digi_main->workspace->y() + pad; int h = Hentry; qsoFreqDisp3 = new cFreqControl( pad, y, @@ -6035,9 +6221,9 @@ void create_fl_digi_main_primary() { qsoFreqDisp2->set_lsd(progdefaults.sel_lsd); qsoFreqDisp3->set_lsd(progdefaults.sel_lsd); - Y = Hmenu + Hqsoframe + pad; + Y = fl_digi_main->workspace->y() + Hqsoframe + pad; -int alt_btn_width = 2 * DEFAULT_SW; + int alt_btn_width = 2 * DEFAULT_SW; macroFrame2 = new Fl_Group(0, Y, progStatus.mainW, Hmacros); macroFrame2->box(FL_FLAT_BOX); mf_group2 = new Fl_Group(0, Y, progStatus.mainW - alt_btn_width, Hmacros); @@ -6070,12 +6256,12 @@ int alt_btn_width = 2 * DEFAULT_SW; Y += Hmacros; - int Hrcvtxt = Htext / 2; - int Hxmttxt = Htext - Hrcvtxt; - center_group = new Fl_Group(0, Y, progStatus.mainW, Htext); center_group->box(FL_FLAT_BOX); + text_group = new Fl_Group(0, Y, center_group->w(), center_group->h()); + text_group->box(FL_FLAT_BOX); + text_panel = new Panel(0, Y, progStatus.mainW, Htext); text_panel->box(FL_FLAT_BOX); @@ -6147,7 +6333,9 @@ int alt_btn_width = 2 * DEFAULT_SW; mvgroup->end(); save_mvx = mvgroup->w(); - int rh = text_panel->h() / 2 + 0.5; + int rh = progStatus.tile_y_ratio * text_panel->h(); + if (progdefaults.rxtx_swap) rh = text_panel->h() - rh; + ReceiveText = new FTextRX( text_panel->x() + mvgroup->w(), text_panel->y(), text_panel->w() - mvgroup->w(), rh, "" ); @@ -6190,15 +6378,17 @@ int alt_btn_width = 2 * DEFAULT_SW; TransmitText->align(FL_ALIGN_CLIP); minbox = new Fl_Box( - text_panel->x(), text_panel->y() + 66, // fixed by Raster min height - text_panel->w() - 100, text_panel->h() - 2 * 66); // fixed by HMIN & Hwfall max + text_panel->x(), + text_panel->y() + rh, // fixed by Raster min height + text_panel->w() - 100, + text_panel->h() - rh - mintxtext ); // fixed by HMIN & Hwfall max minbox->hide(); text_panel->resizable(minbox); text_panel->end(); - center_group->resizable(text_panel); - center_group->end(); + text_group->end(); + text_group->resizable(text_panel); wefax_group = new Fl_Group(0, Y, progStatus.mainW, Htext); wefax_group->box(FL_FLAT_BOX); @@ -6209,7 +6399,7 @@ int alt_btn_width = 2 * DEFAULT_SW; fsq_group->box(FL_FLAT_BOX); // left, resizable rx/tx widgets fsq_left = new Panel( - 0, Y, + 0, Y, progStatus.mainW - 180, Htext); fsq_left->box(FL_FLAT_BOX); @@ -6235,7 +6425,7 @@ int alt_btn_width = 2 * DEFAULT_SW; fsq_rx_text->setFontColor(progdefaults.fsq_undirected_color, FTextBase::FSQ_UND); fsq_tx_text = new FTextTX( - 0, Y + fsq_rx_text->h(), + 0, Y + fsq_rx_text->h(), fsq_left->w(), fsq_left->h() - fsq_rx_text->h()); fsq_tx_text->color( fl_rgb_color( @@ -6265,9 +6455,9 @@ int alt_btn_width = 2 * DEFAULT_SW; fsq_left->w(), Y, 180, fsq_left->h()); fsq_right->box(FL_FLAT_BOX); - static int heard_widths[] = - { 40*fsq_right->w()/100, - 30*fsq_right->w()/100, + static int heard_widths[] = + { 40*fsq_right->w()/100, + 30*fsq_right->w()/100, 0 }; fsq_heard = new Fl_Browser( fsq_right->x(), fsq_right->y(), @@ -6392,7 +6582,7 @@ int alt_btn_width = 2 * DEFAULT_SW; ifkp_group->box(FL_FLAT_BOX); // upper, receive ifkp widgets ifkp_left = new Panel( - 0, Y, + 0, Y, progStatus.mainW - (image_s2n.w()+4), Htext); // add rx & tx ifkp_rx_text = new FTextRX( @@ -6413,7 +6603,7 @@ int alt_btn_width = 2 * DEFAULT_SW; ifkp_rx_text->setFontColor(progdefaults.ALTRcolor, FTextBase::ALTR); ifkp_tx_text = new FTextTX( - 0, Y + ifkp_rx_text->h(), + 0, Y + ifkp_rx_text->h(), ifkp_rx_text->w(), ifkp_group->h() - ifkp_rx_text->h()); ifkp_tx_text->color( fl_rgb_color( @@ -6439,13 +6629,13 @@ int alt_btn_width = 2 * DEFAULT_SW; ifkp_left->end(); ifkp_right = new Fl_Group( - ifkp_left->w(), Y, + ifkp_left->w(), Y, image_s2n.w()+4, ifkp_group->h()); ifkp_right->box(FL_FLAT_BOX); - static int ifkp_heard_widths[] = - { 40*ifkp_right->w()/100, - 30*ifkp_right->w()/100, + static int ifkp_heard_widths[] = + { 40*ifkp_right->w()/100, + 30*ifkp_right->w()/100, 0 }; ifkp_heard = new Fl_Browser( ifkp_right->x(), ifkp_right->y(), @@ -6502,13 +6692,14 @@ int alt_btn_width = 2 * DEFAULT_SW; ifkp_group->resizable(ifkp_left); ifkp_group->end(); + center_group->end(); - center_group->show(); + text_group->show(); wefax_group->hide(); fsq_group->hide(); ifkp_group->hide(); - Y += Htext; + Y += center_group->h();//Htext; Fl::add_handler(default_handler); @@ -6574,7 +6765,7 @@ int alt_btn_width = 2 * DEFAULT_SW; hpack = new Fl_Pack(0, Y, progStatus.mainW, Hstatus); hpack->type(1); - MODEstatus = new Fl_Button(0,Hmenu+Hrcvtxt+Hxmttxt+Hwfall, Wmode+30, Hstatus, ""); + MODEstatus = new Fl_Button(0,fl_digi_main->workspace->y()+Htext+Hwfall, Wmode+30, Hstatus, ""); MODEstatus->box(FL_DOWN_BOX); MODEstatus->color(FL_BACKGROUND2_COLOR); MODEstatus->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); @@ -6621,7 +6812,7 @@ int alt_btn_width = 2 * DEFAULT_SW; // see corner_box below // corner_box used to leave room for OS X corner drag handle -#ifdef __APPLE__ +#ifdef __APPLE__ StatusBar = new Fl_Box( rightof(Status2), Y, fl_digi_main->w() @@ -6738,8 +6929,15 @@ int alt_btn_width = 2 * DEFAULT_SW; inpNotes->when(FL_WHEN_RELEASE); + fl_digi_main->workspace->end(); + fl_digi_main->workspace->resizable(center_group); +// end of dockable workspace + fl_digi_main->end(); - fl_digi_main->resizable(center_group); + fl_digi_main->resizable(fl_digi_main->workspace); + + dock->callback(cb_docked); + fl_digi_main->callback(cb_wMain); scopeview = new Fl_Double_Window(0,0,140,140, _("Scope")); @@ -6780,7 +6978,13 @@ int alt_btn_width = 2 * DEFAULT_SW; toggle_smeter(); - UI_select(); + if (progStatus.tbar_is_docked) // do not change interface state + UI_select(); + else { + progStatus.tbar_is_docked = true; // for tbar toggle + cb_view_hide_macros((Fl_Widget *)0, (void *)0); + } + wf->UI_select(progStatus.WF_UI); clearQSO(); @@ -6805,6 +7009,9 @@ int alt_btn_width = 2 * DEFAULT_SW; case 7: btn_scheme_7->setonly(); break; case 8: btn_scheme_8->setonly(); break; case 9: btn_scheme_9->setonly(); break; + case 10: btn_scheme_10->setonly(); break; + case 11: btn_scheme_11->setonly(); break; + case 12: btn_scheme_12->setonly(); break; } colorize_macros(); @@ -7005,6 +7212,9 @@ void noop_controls() // create and then hide all controls not being used for (int i = 0; i < NUMMACKEYS * NUMKEYROWS; i++) { btnMacro[i] = new Fl_Button(defwidget); btnMacro[i]->hide(); } + for (int i = 0; i < 48; i++) { + btnDockMacro[i] = new Fl_Button(defwidget); btnMacro[i]->hide(); + } inpQth = new Fl_Input2(defwidget); inpQth->hide(); inpLoc = new Fl_Input2(defwidget); inpLoc->hide(); @@ -7130,13 +7340,14 @@ void create_fl_digi_main_WF_only() { IMAGE_WIDTH = 4000;//progdefaults.HighFreqCutoff; Hwfall = progdefaults.wfheight; Wwfall = progStatus.mainW - 2 * DEFAULT_SW - 2 * pad; - WF_only_height = Hmenu + Hwfall + Hstatus + 4 * pad; + WF_only_height = fl_digi_main->workspace->y() + Hwfall + Hstatus + 4 * pad; - fl_digi_main = new Fl_Double_Window(progStatus.mainW, WF_only_height); +// fl_digi_main = new Fl_Double_Window(progStatus.mainW, WF_only_height); + fl_digi_main = new dropwin(progStatus.mainW, WF_only_height); - mnuFrame = new Fl_Group(0,0,progStatus.mainW, Hmenu); + mnuFrame = new Fl_Group(0,0,progStatus.mainW, fl_digi_main->workspace->y()); - mnu = new Fl_Menu_Bar(0, 0, progStatus.mainW - 200 - pad, Hmenu); + mnu = new Fl_Menu_Bar(0, 0, progStatus.mainW - 200 - pad, fl_digi_main->workspace->y()); // do some more work on the menu for (size_t i = 0; i < sizeof(alt_menu_)/sizeof(alt_menu_[0]); i++) { // FL_NORMAL_SIZE may have changed; update the menu items @@ -7149,29 +7360,29 @@ void create_fl_digi_main_WF_only() { } mnu->menu(alt_menu_); - btnAutoSpot = new Fl_Light_Button(progStatus.mainW - 200 - pad, 0, 50, Hmenu, "Spot"); + btnAutoSpot = new Fl_Light_Button(progStatus.mainW - 200 - pad, 0, 50, fl_digi_main->workspace->y(), "Spot"); btnAutoSpot->selection_color(progdefaults.SpotColor); btnAutoSpot->callback(cbAutoSpot, 0); btnAutoSpot->deactivate(); - btnRSID = new Fl_Light_Button(progStatus.mainW - 150 - pad, 0, 50, Hmenu, "RxID"); + btnRSID = new Fl_Light_Button(progStatus.mainW - 150 - pad, 0, 50, fl_digi_main->workspace->y(), "RxID"); btnRSID->selection_color(progdefaults.RxIDColor); btnRSID->tooltip("Receive RSID"); btnRSID->callback(cbRSID, 0); - btnTxRSID = new Fl_Light_Button(progStatus.mainW - 100 - pad, 0, 50, Hmenu, "TxID"); + btnTxRSID = new Fl_Light_Button(progStatus.mainW - 100 - pad, 0, 50, fl_digi_main->workspace->y(), "TxID"); btnTxRSID->selection_color(progdefaults.TxIDColor); btnTxRSID->tooltip("Transmit RSID"); btnTxRSID->callback(cbTxRSID, 0); - btnTune = new Fl_Light_Button(progStatus.mainW - 50 - pad, 0, 50, Hmenu, "TUNE"); + btnTune = new Fl_Light_Button(progStatus.mainW - 50 - pad, 0, 50, fl_digi_main->workspace->y(), "TUNE"); btnTune->selection_color(progdefaults.TuneColor); btnTune->callback(cbTune, 0); mnuFrame->resizable(mnu); mnuFrame->end(); - Y = Hmenu + pad; + Y = fl_digi_main->workspace->y() + pad; Fl_Pack *wfpack = new Fl_Pack(0, Y, progStatus.mainW, Hwfall); wfpack->type(1); @@ -7377,7 +7588,7 @@ void create_fl_digi_main(int argc, char** argv) if (bWF_only) fl_digi_main->size_range(WMIN, WF_only_height, 0, WF_only_height); else - fl_digi_main->size_range(WMIN, main_hmin, 0, 0);//HMIN, 0, 0); + fl_digi_main->size_range(WMIN, main_hmin, 0, 0); set_colors(); } @@ -9218,6 +9429,6 @@ void cbFSQCALL(Fl_Widget *w, void *d) btn->label("FSQ-ON"); btn->redraw_label(); } - } + } restoreFocus(); } diff --git a/src/feld/feld.cxx b/src/feld/feld.cxx index edafb5f5..02745476 100644 --- a/src/feld/feld.cxx +++ b/src/feld/feld.cxx @@ -55,6 +55,9 @@ LOG_FILE_SOURCE(debug::LOG_MODEM); char feldmsg[80]; +int feld::RxColumnLen = FELD_RX_COLUMN_LEN; +int feld::TxColumnLen = 14; + void feld::tx_init(SoundBase *sc) { scard = sc; diff --git a/src/include/dock_events.h b/src/include/dock_events.h new file mode 100644 index 00000000..32943258 --- /dev/null +++ b/src/include/dock_events.h @@ -0,0 +1,9 @@ +#ifndef _HAVE_DOCK_EVENTS_HDR_ +#define _HAVE_DOCK_EVENTS_HDR_ + +# define FX_DROP_EVENT (FL_DND_RELEASE + 100) + +# define DROP_REGION_HEIGHT 60 + +#endif + diff --git a/src/include/dock_gp.h b/src/include/dock_gp.h new file mode 100644 index 00000000..f04c82c4 --- /dev/null +++ b/src/include/dock_gp.h @@ -0,0 +1,31 @@ +#ifndef _HAVE_DOCK_GRP_HDR_ +#define _HAVE_DOCK_GRP_HDR_ + +#include +#include + +class dockgroup : public Fl_Group +{ +protected: + Fl_Window *win; + Fl_Pack *pack; + int children; + int vis_h; + +public: + // Normal FLTK constructors + dockgroup(int x, int y, int w, int h, const char *l = 0); + + // point back to our parent + void set_window(Fl_Window *w) {win = w;} + + // methods for adding or removing toolgroups from the dock + void add(Fl_Widget *w); + void remove(Fl_Widget *w); + + // dock diagnostic + char *dock_check(void); +}; + +#endif // _HAVE_DOCK_GRP_HDR_ + diff --git a/src/include/drag_btn.h b/src/include/drag_btn.h new file mode 100644 index 00000000..61c5cc46 --- /dev/null +++ b/src/include/drag_btn.h @@ -0,0 +1,27 @@ +#ifndef _HAVE_DRAG_BTN_HDR_ +#define _HAVE_DRAG_BTN_HDR_ + +#include + +class drag_btn : public Fl_Box +{ +private: + int x1, y1; // click posn., used for dragging and docking checks + int xoff, yoff; // origin used for dragging calcs + int was_docked; // used in handle to note that we have just undocked + +protected: + // override box draw method to do our textured dragger look + void draw(); + // override handle method to catch drag/dock operations + int handle(int event); + +public: + // basic constructor + drag_btn(int x, int y, int w, int h, const char *l = 0); +}; + +#endif // _HAVE_DRAG_BTN_HDR_ + +/* End of File */ + diff --git a/src/include/dropwin.h b/src/include/dropwin.h new file mode 100644 index 00000000..abab7081 --- /dev/null +++ b/src/include/dropwin.h @@ -0,0 +1,39 @@ +#ifndef _HAVE_DROP_WIN_HDR_ +#define _HAVE_DROP_WIN_HDR_ + +#include +#include + +#include "dock_gp.h" + +class dropwin : public Fl_Double_Window +{ +protected: + void init_dropwin(void); + dockgroup *dock; + int Wdrop; + int Hdrop; + +public: + // Normal FLTK constructors + dropwin(int x, int y, int w, int h, const char *l = 0); + dropwin(int w, int h, const char *l = 0); + + // The working area of this window + Fl_Group *workspace; + + // override handle method to capture "drop" events + int handle(int); + + // assign a dock widget to this window + void set_dock(dockgroup *d) {dock = d;} + + // Resize the workspace area if the dock closes/opens + void dock_resize(int h); + + void set_drop(int w, int h) { Wdrop = w; Hdrop = h; } + +}; + +#endif // _HAVE_DROP_WIN_HDR_ + diff --git a/src/include/feld.h b/src/include/feld.h index 4c077fbf..6143f271 100644 --- a/src/include/feld.h +++ b/src/include/feld.h @@ -37,15 +37,15 @@ #define FeldSampleRate 8000 #define FeldMaxSymLen 1024 -#define RxColumnLen 30 -#define TxColumnLen 14 - -#define PIXMAP_W 14 -#define PIXMAP_H (TxColumnLen) #define MAXLEN 512 +#define FELD_RX_COLUMN_LEN 20 + class feld : public modem { enum FELD_STATE {PREAMBLE, POSTAMBLE, DATA}; +public: +static int RxColumnLen; +static int TxColumnLen; protected: //rx double rxphacc; @@ -55,7 +55,7 @@ protected: double peakval; double peakhold; double minhold; - + double rxpixrate; double txpixrate; double downsampleinc; @@ -89,7 +89,7 @@ protected: double OnShape[MAXLEN]; double OffShape[MAXLEN]; - mbuffer col_data; + mbuffer col_data; int col_pointer; int fntnbr; diff --git a/src/include/fl_digi.h b/src/include/fl_digi.h index 92d590ea..642b7ab8 100644 --- a/src/include/fl_digi.h +++ b/src/include/fl_digi.h @@ -46,10 +46,13 @@ #include "smeter.h" #include "pwrmeter.h" #include "picture.h" +#include "dropwin.h" extern fre_t seek_re; -extern Fl_Double_Window *fl_digi_main; +//extern Fl_Double_Window *fl_digi_main; +extern dropwin *fl_digi_main; + extern Fl_Double_Window *scopeview; //extern Fl_Double_Window *opBrowserView; diff --git a/src/include/raster.h b/src/include/raster.h index 7098fc4c..c7becf5f 100644 --- a/src/include/raster.h +++ b/src/include/raster.h @@ -24,6 +24,7 @@ #define _RASTER_H #include +#include "feld.h" class Raster : public Fl_Widget { public: diff --git a/src/include/status.h b/src/include/status.h index 14ca7496..f6308bd3 100644 --- a/src/include/status.h +++ b/src/include/status.h @@ -37,6 +37,7 @@ struct status { bool Rig_Log_UI; bool Rig_Contest_UI; bool DOCKEDSCOPE; + bool tbar_is_docked; int RxTextHeight; int tiled_group_x; @@ -71,6 +72,7 @@ struct status { int tile_w; int tile_y; int tile_h; + double tile_y_ratio; double fsq_ratio; double ifkp_ratio; bool LOGenabled; diff --git a/src/include/toolgrp.h b/src/include/toolgrp.h new file mode 100644 index 00000000..580d6de9 --- /dev/null +++ b/src/include/toolgrp.h @@ -0,0 +1,72 @@ +#ifndef _HAVE_TOOL_GROUP_HDR_ +#define _HAVE_TOOL_GROUP_HDR_ + +#include +#include + +#include "dock_gp.h" +#include "drag_btn.h" + +class toolgrp : public Fl_Group +{ +private: + // control variables + short _docked; + dockgroup *dock; + + // constructor helper function + void create_dockable_group(void); + void create_docked(dockgroup *d); + void create_floating(dockgroup *d, int state, int x, int y, int w, int h, const char *l); + +protected: + // Widgets used by the toolbar +// Fl_Button *dismiss; + drag_btn *dragger; + Fl_Group *inner_group; + + // Sets whether window is docked or not. + void docked(short r); + + // Defines which dock the group can dock into + void set_dock(dockgroup *w) {dock = w;} + // get the dock group ID + dockgroup *get_dock(void) {return dock;} + + // generic callback function for the dismiss button +// static void cb_dismiss(Fl_Button*, void* v); + +public: + // Constructors for docked/floating window + toolgrp(dockgroup *d, int f, int w, int h, const char *l = 0); + toolgrp(dockgroup *d, int f, int x, int y, int w, int h, const char *l = 0); + + // methods for hiding/showing *all* the floating windows + static void show_all(void); + static void hide_all(void); + + // Tests whether window is docked, undocked or hidden + short docked() { return _docked; } + + // generic callback function for the dock/undock checkbox + void dock_grp(void* v); + void undock_grp(void* v); + void hide_show(); + + // wrap some basic Fl_Group functions to access the enclosed inner_group + inline void begin() {inner_group->begin(); } + inline void end() {inner_group->end(); Fl_Group::end(); } + inline void resizable(Fl_Widget *box) {inner_group->resizable(box); } + inline void resizable(Fl_Widget &box) {inner_group->resizable(box); } + inline Fl_Widget *resizable() const { return inner_group->resizable(); } + inline void add( Fl_Widget &w ) { inner_group->add( w ); } + inline void add( Fl_Widget *w ) { inner_group->add( w ); } + inline void insert( Fl_Widget &w, int n ) { inner_group->insert( w, n ); } + inline void insert( Fl_Widget &w, Fl_Widget* beforethis ) { inner_group->insert( w, beforethis ); } + inline void remove( Fl_Widget &w ) { inner_group->remove( w ); } + inline void remove( Fl_Widget *w ) { inner_group->remove( w ); } +// inline void add_resizable( Fl_Widget &box ) { inner_group->add_resizable( box ); } +}; + +#endif // _HAVE_TOOL_GROUP_HDR_ + diff --git a/src/include/toolwin.h b/src/include/toolwin.h new file mode 100644 index 00000000..f679524c --- /dev/null +++ b/src/include/toolwin.h @@ -0,0 +1,37 @@ +#ifndef _HAVE_TOOLWIN_HDR_ +#define _HAVE_TOOLWIN_HDR_ + +/* fltk includes */ +#include +#include + +class toolwin : public Fl_Double_Window +{ +#define TW_MAX_FLOATERS 16 + +protected: + void create_dockable_window(void); + short idx; + static toolwin* active_list[TW_MAX_FLOATERS]; + static short active; + void *tool_group; + +public: + // Normal FLTK constructors + toolwin(int w, int h, const char *l = 0); + toolwin(int x, int y, int w, int h, const char *l = 0); + + // destructor + ~toolwin(); + + // methods for hiding/showing *all* the floating windows + static void show_all(void); + static void hide_all(void); + + // set the inner group + void set_inner(void *v) {tool_group = v;} +}; + +#endif // _HAVE_TOOLWIN_HDR_ + +// End of file // diff --git a/src/misc/status.cxx b/src/misc/status.cxx index 25b7d202..a224ff9c 100644 --- a/src/misc/status.cxx +++ b/src/misc/status.cxx @@ -78,6 +78,7 @@ status progStatus = { false, // bool Rig_Log_UI; false, // bool Rig_Contest_UI; false, // bool DOCKEDSCOPE; + false, // bool tbar_is_docked; 50, // int RxTextHeight; WMIN/2, // int tiled_group_x; false, // bool show_channels; @@ -110,6 +111,7 @@ status progStatus = { 200, // int tile_w; 90, // int tile_y; 150, // int tile_h; + 0.5, // double tile_y_ratio; 0.5, // double fsq_ratio; 0.5, // double ifkp_ratio; false, // bool LOGenabled @@ -251,6 +253,7 @@ void status::saveLastState() tile_w = text_panel->w(); tile_y = progdefaults.rxtx_swap ? TransmitText->h() : ReceiveText->h(); tile_h = text_panel->h(); + tile_y_ratio = 1.0 * tile_y / text_group->h(); if (text_panel->w() != ReceiveText->w()) tile_x = mvgroup->w(); fsq_ratio = 1.0 * fsq_rx_text->h() / fsq_group->h(); @@ -363,6 +366,7 @@ if (!bWF_only) { spref.set("rigcontest_ui", Rig_Contest_UI); spref.set("noriglog", NO_RIGLOG); spref.set("docked_scope", DOCKEDSCOPE); + spref.set("tbar_is_docked", tbar_is_docked); spref.set("rigctl_x", rigX); spref.set("rigctl_y", rigY); @@ -387,6 +391,7 @@ if (!bWF_only) { spref.set("tile_y", tile_y); spref.set("tile_w", tile_w); spref.set("tile_h", tile_h); + spref.set("tile_y_ratio", tile_y_ratio); spref.set("fsq_ratio", fsq_ratio); spref.set("ifkp_ratio", ifkp_ratio); @@ -565,6 +570,7 @@ void status::loadLastState() spref.get("rigcontest_ui", i, Rig_Contest_UI); Rig_Contest_UI = i; spref.get("noriglog", i, NO_RIGLOG); NO_RIGLOG = i; spref.get("docked_scope", i, DOCKEDSCOPE); DOCKEDSCOPE = i; + spref.get("tbar_is_docked", i, tbar_is_docked); tbar_is_docked = i; spref.get("rigctl_x", rigX, rigX); spref.get("rigctl_y", rigY, rigY); @@ -589,6 +595,7 @@ void status::loadLastState() spref.get("tile_y", tile_y, tile_y); spref.get("tile_w", tile_w, tile_w); spref.get("tile_h", tile_h, tile_h); + spref.get("tile_y_ratio", tile_y_ratio, tile_y_ratio); spref.get("fsq_ratio", fsq_ratio, fsq_ratio); spref.get("ifkp_ratio", ifkp_ratio, ifkp_ratio); diff --git a/src/waterfall/raster.cxx b/src/waterfall/raster.cxx index 383bdd90..1badf2e9 100644 --- a/src/waterfall/raster.cxx +++ b/src/waterfall/raster.cxx @@ -40,7 +40,7 @@ Raster::Raster (int X, int Y, int W, int H) : width = W - 4; height = H - 4; space = 2; - rowheight = 60; + rowheight = 2 * FELD_RX_COLUMN_LEN;//40;//60; Nrows = (int)(height / (rowheight + space) - 0.5); vidbuf = new unsigned char[width * height]; memset(vidbuf, 255, width * height); diff --git a/src/widgets/dock_gp.cxx b/src/widgets/dock_gp.cxx new file mode 100644 index 00000000..fe161e95 --- /dev/null +++ b/src/widgets/dock_gp.cxx @@ -0,0 +1,59 @@ +#include + +#include + +#include "dock_gp.h" +#include "dropwin.h" + +// basic fltk constructors +dockgroup::dockgroup(int x, int y, int w, int h, const char *l) + : Fl_Group(x, y, w, h, l) +{ + pack = new Fl_Pack(x, y, w, h); + pack->type(Fl_Pack::HORIZONTAL); + children = 0; + resizable(pack); + vis_h = h; +} + +void dockgroup::add(Fl_Widget *grp) +{ + int wd = w(); + int ht = h(); + + // if the dock is "closed", open it back up + if (ht < vis_h) + { + dropwin *dw = (dropwin *)win; + size(wd, vis_h); + pack->size(wd, vis_h); + dw->dock_resize(ht - vis_h); + } + pack->add(grp); + pack->resizable(grp); + children++; + if (callback() != NULL) do_callback(); +} + +void dockgroup::remove(Fl_Widget *grp) +{ + int wd = w(); + pack->remove(grp); + children--; + pack->resizable(pack->child(pack->children() - 1)); + // If the dock is empty, close it down + if (children <= 0) { + dropwin *dw = (dropwin *)win; + children = 0; + size(wd, 2); + dw->dock_resize(vis_h - 2); + } + if (callback() != NULL) do_callback(); +} + +char *dockgroup::dock_check(void) +{ + static char szcheck[50]; + snprintf(szcheck, sizeof(szcheck), "DG: %d - %dx%d", children, pack->w(), pack->h()); + return szcheck; +} diff --git a/src/widgets/drag_btn.cxx b/src/widgets/drag_btn.cxx new file mode 100644 index 00000000..0a488d19 --- /dev/null +++ b/src/widgets/drag_btn.cxx @@ -0,0 +1,144 @@ +#include + +#include +#include +#include + +#include "drag_btn.h" +#include "dock_events.h" +#include "toolgrp.h" + +static const char * grip_tile_xpm[] = { +"6 6 4 1", +" c None", +". c #FCFEFC", +"+ c #D4D6D4", +"@ c #9C9294", +".+++++", +"+@+.++", +"++++@+", +".+++++", +"+@+.++", +"++++@+"}; + +drag_btn::drag_btn(int x, int y, int w, int h, const char *l) + : Fl_Box(x, y, w, h, l) +{ + was_docked = 0; // Assume we have NOT just undocked... +} + +void drag_btn::draw() +{ + int xo = x(); + int yo = y(); + + // Draw the button box + draw_box(box(), color()); + + // set the clip region so we only "tile" the box + fl_push_clip(xo+1, yo+1, w()-3, h()-3); + + // tile the pixmap onto the button face... there must be a better way + for(int i = 2; i <= w(); i += 6) + for(int j = 2; j <= h(); j += 6) + fl_draw_pixmap(grip_tile_xpm, (xo + i), (yo + j)); + + fl_pop_clip(); +} // draw + +int drag_btn::handle(int event) +{ + toolgrp *tg = (toolgrp *)parent(); + int docked = tg->docked(); + int ret = 0; + int x2 = 0, y2 = 0; + int cx, cy; + + // If we are not docked, deal with dragging the toolwin around + if (!docked) { + // get the enclosing parent widget + Fl_Widget *tw = (Fl_Widget *)(tg->parent()); + if(!tw) return 0; + + switch (event) { + case FL_PUSH: // downclick in button creates cursor offsets + x1 = Fl::event_x_root(); + y1 = Fl::event_y_root(); + xoff = tw->x() - x1; + yoff = tw->y() - y1; + ret = 1; + break; + case FL_DRAG: // drag the button (and its parent window) around the screen + if (was_docked) { + // Need to init offsets, we probably got here following a drag + // from the dock, so the PUSH (above) will not have happened. + was_docked = 0; + x1 = Fl::event_x_root(); + y1 = Fl::event_y_root(); + xoff = tw->x() - x1; + yoff = tw->y() - y1; + } + tw->position(xoff + Fl::event_x_root(), yoff + Fl::event_y_root()); + tw->redraw(); + ret = 1; + break; + + case FL_RELEASE: + cx = Fl::event_x_root(); // Where did the release occur... + cy = Fl::event_y_root(); + x2 = x1 - cx; + y2 = y1 - cy; + x2 = (x2 > 0) ? x2 : (-x2); + y2 = (y2 > 0) ? y2 : (-y2); + // See if anyone is able to accept a dock with this widget + // How to find the dock window? Search 'em all for now... + for(Fl_Window *win = Fl::first_window(); win; win = Fl::next_window(win)) { + // Get the co-ordinates of each window + int ex = win->x_root(); + int ey = win->y_root(); + // Are we inside the boundary of the window? + if (win->visible() && + abs(cx - ex) < DROP_REGION_HEIGHT && + abs(cy - ey) < DROP_REGION_HEIGHT) { + // Send the found window a message that we want to dock with it. + if(Fl::handle(FX_DROP_EVENT, win)) { + tg->dock_grp(tg); + break; + } + } + } + //show(); + ret = 1; + break; + default: + break; + } + return(ret); + } + + // OK, so we must be docked - are we being dragged out of the dock? + switch(event) { + case FL_PUSH: // downclick in button creates cursor offsets + x1 = Fl::event_x_root(); + y1 = Fl::event_y_root(); + ret = 1; + break; + case FL_DRAG: + // IF the drag has moved further than the drag_min distance + // THEN invoke an un-docking + x2 = Fl::event_x_root() - x1; + y2 = Fl::event_y_root() - y1; + x2 = (x2 > 0) ? x2 : (-x2); + y2 = (y2 > 0) ? y2 : (-y2); + if ((x2 > 10) || (y2 > 10)) { + tg->undock_grp((void *)tg); // undock the window + was_docked = -1; // note that we *just now* undocked + } + ret = 1; + break; + default: + break; + } + return ret; +} // handle + diff --git a/src/widgets/dropwin.cxx b/src/widgets/dropwin.cxx new file mode 100644 index 00000000..17599e81 --- /dev/null +++ b/src/widgets/dropwin.cxx @@ -0,0 +1,67 @@ +#include +#include + +#include "dropwin.h" +#include "dock_events.h" + +// basic fltk constructors +dropwin::dropwin(int x, int y, int w, int h, const char *l) + : Fl_Double_Window(x, y, w, h, l) +{ + init_dropwin(); +} + +dropwin::dropwin(int w, int h, const char *l) + : Fl_Double_Window(w, h, l) +{ + init_dropwin(); +} + +void dropwin::init_dropwin(void) +{ + dock = (dockgroup *)0; + workspace = (Fl_Group *)0; + Wdrop = DROP_REGION_HEIGHT; + Hdrop = DROP_REGION_HEIGHT; +} + +void dropwin::dock_resize(int delta_h) +{ + int xo = workspace->x(); + int yo = workspace->y(); + int wo = workspace->w(); + int ho = workspace->h(); + + yo = yo - delta_h; + ho = ho + delta_h; + workspace->resize(xo, yo, wo, ho); + workspace->redraw(); + redraw(); +} + + +int dropwin::handle(int evt) +{ + int res = Fl_Double_Window::handle(evt); + + // Is this a dock_drop event? + if((evt == FX_DROP_EVENT) && (dock)) { + // Did the drop happen on us? + // Get our co-ordinates + int ex = x_root() + dock->x(); + int ey = y_root() + dock->y(); + // get the drop event co-ordinates + int cx = Fl::event_x_root(); + int cy = Fl::event_y_root(); + // Is the event inside the boundary of this window? + if (visible() && + abs(cx - ex) < Wdrop && + abs(cy - ey) < Hdrop) { + res = 1; + } else { + res = 0; + } + } + return res; +} + diff --git a/src/widgets/toolgrp.cxx b/src/widgets/toolgrp.cxx new file mode 100644 index 00000000..ec3f0372 --- /dev/null +++ b/src/widgets/toolgrp.cxx @@ -0,0 +1,204 @@ +#include + +/* fltk includes */ +#include + +#include "toolgrp.h" +#include "toolwin.h" +#include "dropwin.h" +#include "dock_gp.h" + +// function to handle the dock actions +void toolgrp::dock_grp(void* v) +{ // dock CB + toolgrp *gp = (toolgrp *)v; + dockgroup *dock = gp->get_dock(); + + // we can only dock a group that's not already docked... + // and only if a dock exists for it + if((gp->docked() == 0) && (dock)) + { //re-dock the group + toolwin *cur_parent = (toolwin *)gp->parent(); + dock->add(gp); // move the toolgroup into the dock + dock->redraw(); + gp->docked(-1); // toolgroup is docked... + // so we no longer need the tool window. + cur_parent->hide(); + delete cur_parent; + } +} + +// static CB to handle the undock actions +void toolgrp::undock_grp(void* v) +{ // undock CB + toolgrp *gp = (toolgrp *)v; + dockgroup *dock = gp->get_dock(); + + if(gp->docked() == -1) + { // undock the group into its own non-modal tool window + int w = gp->w(); + int h = gp->h(); + Fl_Group::current(0); + toolwin *new_parent = new toolwin(Fl::event_x_root() - 10, Fl::event_y_root() - 35, w + 3, h + 3); + new_parent->end(); + dock->remove(gp); + new_parent->add(gp);// move the tool group into the floating window + new_parent->set_inner((void *)gp); + gp->position(1, 1); // align group in floating window + new_parent->show(); // show floating window + gp->docked(0); // toolgroup is no longer docked + dock->redraw(); // update the dock, to show the group has gone... + } +} + +void toolgrp::hide_show() +{ +// if (docked() == 0) return; + + dockgroup *dock = get_dock(); + if (docked() == 0) { + toolwin *cur_parent = (toolwin *)parent(); + dock->add(this); // move the toolgroup into the dock + dock->redraw(); + cur_parent->remove(this); + cur_parent->hide(); // remove current parent window + delete cur_parent; + dock->remove(this); // remove toolgroup from docked parent + docked(-2); + dock->redraw(); + } + else if (docked() == -1) { + dock->remove(this); + docked(-2); + dock->redraw(); + } else { // docked() == -2 // the unassigned state + dock->add(this); + docked(-1); + dock->redraw(); + } +} + +// static CB to handle the dismiss action +//void toolgrp::cb_dismiss(Fl_Button*, void* v) +//{ +// toolgrp *gp = (toolgrp *)v; +// dockgroup *dock = gp->get_dock(); + +// if(gp->docked()) +// { // remove the group from the dock +// dock->remove(gp); +// gp->docked(0); +// dock->redraw(); // update the dock, to show the group has gone... +// Fl::delete_widget(gp); +// } +// else +// { // remove the group from the floating window, +// // and remove the floating window +// toolwin *cur_parent = (toolwin *)gp->parent(); +// cur_parent->remove(gp); +// //delete cur_parent; // we no longer need the tool window. +// Fl::delete_widget(cur_parent); +// Fl::delete_widget(gp); +// } +//} + +// Constructors for docked/floating window +// WITH x, y co-ordinates +toolgrp::toolgrp(dockgroup *dk, int floater, int x, int y, int w, int h, const char *lbl) + : Fl_Group(1, 1, w - 2 , h - 2, lbl) +{ + if((floater) && (dk)) // create floating + { + create_floating(dk, 1, x, y, w, h, lbl); + } + else if(dk) // create docked + { + create_docked(dk); + } +// else //do nothing... +} + +// WITHOUT x, y co-ordinates +toolgrp::toolgrp(dockgroup *dk, int floater, int w, int h, const char *lbl) + : Fl_Group(1, 1, w - 2, h - 2, lbl) +{ + if((floater) && (dk)) // create floating + { + create_floating(dk, 0, 0, 0, w, h, lbl); + } + else if(dk) // create docked + { + create_docked(dk); + } +// else //do nothing... +} + +// construction function +void toolgrp::create_dockable_group() +{ + + dragger = new drag_btn(2, 2, 12, h() - 4); + dragger->type(FL_TOGGLE_BUTTON); + dragger->box(FL_ENGRAVED_FRAME); + dragger->tooltip("Drag Box"); + dragger->clear_visible_focus(); + dragger->when(FL_WHEN_CHANGED); + + inner_group = new Fl_Group(16, 2, w() - 18, h() - 4); + inner_group->box(FL_FLAT_BOX); +// inner_group->box(FL_ENGRAVED_FRAME); +} + +void toolgrp::create_docked(dockgroup *dk) +{ + // create the group itself + create_dockable_group(); + // place it in the dock + dk->add(this); + set_dock(dk); // define where the toolgroup is allowed to dock + docked(-1); // docked + dk->redraw(); + Fl_Group::resizable(inner_group); +} + +void toolgrp::create_floating(dockgroup *dk, int full, int x, int y, int w, int h, const char *lbl) +{ + toolwin *tw; + // create the group itself + create_dockable_group(); + // create a floating toolbar window + // Ensure the window is not created as a child of its own inner group! + Fl_Group::current(0); + if(full) + tw = new toolwin(x, y, w + 4, h + 4, lbl); + else + tw = new toolwin(w + 4, h + 4, lbl); + tw->end(); + tw->add(this); // move the tool group into the floating window + docked(0); // NOT docked + set_dock(dk); // define where the toolgroup is allowed to dock + tw->set_inner((void *)this); + tw->show(); + Fl_Group::current(inner_group); // leave this group open when we leave the constructor... + Fl_Group::resizable(inner_group); +} + +// function for setting the docked state and checkbox +void toolgrp::docked(short r) +{ + _docked = r; +} + +// methods for hiding/showing *all* the floating windows +// show all the active floating windows +void toolgrp::show_all(void) +{ + toolwin::show_all(); +} + +// hide all the active floating windows +void toolgrp::hide_all(void) +{ + toolwin::hide_all(); +} + diff --git a/src/widgets/toolwin.cxx b/src/widgets/toolwin.cxx new file mode 100644 index 00000000..29beed38 --- /dev/null +++ b/src/widgets/toolwin.cxx @@ -0,0 +1,101 @@ +#include + +#include "toolwin.h" +#include "toolgrp.h" +#include "dock_events.h" + +#include + +#define NTW (toolwin*)0 // Null Tool Window + +// HACK:: This just stores the toolwindows in a static array. I'm too lazy +// to make a proper linked list to store these in... +toolwin* toolwin::active_list[TW_MAX_FLOATERS]; // list of active toolwins +short toolwin::active = 0; // count of active tool windows + +// Dummy close button callback +static void cb_ignore(void) +{ + // Just shrug off the close callback... +} + +// constructors +toolwin::toolwin(int x, int y, int w, int h, const char *l) + : Fl_Double_Window(x, y, w, h, l) +{ + create_dockable_window(); +} + +toolwin::toolwin(int w, int h, const char *l) + : Fl_Double_Window(w, h, l) +{ + create_dockable_window(); +} + +// destructor +toolwin::~toolwin() +{ + active_list[idx] = NTW; + active --; +} + +// construction function +void toolwin::create_dockable_window() +{ + static int first_window = 1; + tool_group = (void *)0; + // window list intialisation... + // this is a nasty hack, should make a proper list + if(first_window) + { + first_window = 0; + for(short i = 0; i < TW_MAX_FLOATERS; i++) + active_list[i] = NTW; + } + // find an empty index + for(short i = 0; i < TW_MAX_FLOATERS; i++) + { + if(!active_list[i]) + { + idx = i; + active_list[idx] = this; + active ++; + clear_border(); + set_non_modal(); + callback((Fl_Callback *)cb_ignore); + return; + } + } + // if we get here, the list is probably full, what a hack. + // FIX THIS:: At present, we will get a non-modal window with + // decorations as a default instead... + set_non_modal(); +} + +// show all the active floating windows +void toolwin::show_all(void) +{ + if (active) + { + for(short i = 0; i < TW_MAX_FLOATERS; i++) + { + if(active_list[i]) + active_list[i]->show(); + } + } +} + +// hide all the active floating windows +void toolwin::hide_all(void) +{ + if (active) + { + for(short i = 0; i < TW_MAX_FLOATERS; i++) + { + if(active_list[i]) + active_list[i]->hide(); + } + } +} + +