diff --git a/fldigi_doxygen/images/macro-matrix.png b/fldigi_doxygen/images/macro-matrix.png new file mode 100644 index 00000000..05d92de5 Binary files /dev/null and b/fldigi_doxygen/images/macro-matrix.png differ diff --git a/fldigi_doxygen/images/macro-scheme-4.png b/fldigi_doxygen/images/macro-scheme-4.png new file mode 100644 index 00000000..ab945e7d Binary files /dev/null and b/fldigi_doxygen/images/macro-scheme-4.png differ diff --git a/fldigi_doxygen/images/view-hide-48.png b/fldigi_doxygen/images/view-hide-48.png new file mode 100644 index 00000000..6e866f2e Binary files /dev/null and b/fldigi_doxygen/images/view-hide-48.png differ 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(); + } + } +} + +