summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <github@matthiasm.com>2023-03-18 17:33:27 +0100
committerGitHub <noreply@github.com>2023-03-18 17:33:27 +0100
commit5c482f9d9b357e098f955351f425bc985254ff28 (patch)
treec410588ac915886aea4bef3478a12d682bb5ad9f
parenta9fb6a979fbcf31c2405d61ea720879bd5507d02 (diff)
Fix and update alignment #346 (#701)
* interactive layout alignment rewritten * interface for new alignment rules * new alignment dialog box * user defined layout rules added * layout rules can be stored in projects, settings, and external files * Valgrind verification
-rw-r--r--FL/Fl_Gl_Window.H3
-rw-r--r--FL/Fl_Group.H1
-rw-r--r--FL/Fl_Menu_Item.H6
-rw-r--r--FL/Fl_Widget.H9
-rw-r--r--FL/Fl_Window.H1
-rw-r--r--fluid/CMakeLists.txt2
-rw-r--r--fluid/Fd_Snap_Action.cxx1565
-rw-r--r--fluid/Fd_Snap_Action.h168
-rw-r--r--fluid/Fl_Group_Type.h6
-rw-r--r--fluid/Fl_Menu_Type.cxx3
-rw-r--r--fluid/Fl_Type.cxx3
-rw-r--r--fluid/Fl_Type.h1
-rw-r--r--fluid/Fl_Widget_Type.cxx57
-rw-r--r--fluid/Fl_Widget_Type.h3
-rw-r--r--fluid/Fl_Window_Type.cxx611
-rw-r--r--fluid/Fl_Window_Type.h13
-rw-r--r--fluid/Makefile1
-rw-r--r--fluid/align_widget.cxx28
-rw-r--r--fluid/align_widget.h1
-rw-r--r--fluid/alignment_panel.cxx749
-rw-r--r--fluid/alignment_panel.fl589
-rw-r--r--fluid/alignment_panel.h29
-rw-r--r--fluid/factory.cxx9
-rw-r--r--fluid/file.cxx22
-rw-r--r--fluid/file.h2
-rw-r--r--fluid/fluid.cxx52
-rw-r--r--fluid/fluid.h13
-rw-r--r--fluid/widget_browser.cxx2
-rw-r--r--fluid/widget_panel.cxx36
-rw-r--r--fluid/widget_panel.fl27
-rw-r--r--fluid/widget_panel.h3
-rw-r--r--src/Fl_Menu_.cxx10
-rw-r--r--src/fl_draw.cxx6
-rw-r--r--src/fl_symbols.cxx40
-rw-r--r--test/symbols.cxx4
35 files changed, 3197 insertions, 878 deletions
diff --git a/FL/Fl_Gl_Window.H b/FL/Fl_Gl_Window.H
index c33bed8db..8889a086b 100644
--- a/FL/Fl_Gl_Window.H
+++ b/FL/Fl_Gl_Window.H
@@ -207,7 +207,8 @@ public:
void make_overlay_current();
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
- Fl_Gl_Window* as_gl_window() FL_OVERRIDE {return this;}
+ Fl_Gl_Window* as_gl_window() FL_OVERRIDE { return this; }
+ Fl_Gl_Window const* as_gl_window() const FL_OVERRIDE { return this; }
float pixels_per_unit();
/** Gives the window width in OpenGL pixels.
diff --git a/FL/Fl_Group.H b/FL/Fl_Group.H
index 1e21b20ba..173f8754b 100644
--- a/FL/Fl_Group.H
+++ b/FL/Fl_Group.H
@@ -228,6 +228,7 @@ public:
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
Fl_Group* as_group() FL_OVERRIDE { return this; }
+ Fl_Group const* as_group() const FL_OVERRIDE { return this; }
// back compatibility functions:
diff --git a/FL/Fl_Menu_Item.H b/FL/Fl_Menu_Item.H
index 0f1083a9a..4bca0e1ce 100644
--- a/FL/Fl_Menu_Item.H
+++ b/FL/Fl_Menu_Item.H
@@ -317,6 +317,10 @@ struct FL_EXPORT Fl_Menu_Item {
before FLTK 1.4.0.
*/
int value() const {return (flags & FL_MENU_VALUE) ? 1 : 0;}
+
+ /** Sets the current value of the check or radio item. */
+ void value(int v) { v ? set() : clear(); }
+
/**
Turns the check or radio item "on" for the menu item. Note that this
does not turn off any adjacent radio items like setonly() does.
@@ -326,7 +330,7 @@ struct FL_EXPORT Fl_Menu_Item {
/** Turns the check or radio item "off" for the menu item. */
void clear() {flags &= ~FL_MENU_VALUE;}
- void setonly();
+ void setonly(Fl_Menu_Item const* first = NULL);
/** Gets the visibility of an item. */
int visible() const {return !(flags&FL_MENU_INVISIBLE);}
diff --git a/FL/Fl_Widget.H b/FL/Fl_Widget.H
index b0317dc6e..969aee6fa 100644
--- a/FL/Fl_Widget.H
+++ b/FL/Fl_Widget.H
@@ -1091,7 +1091,8 @@ public:
\note This method is provided to avoid dynamic_cast.
\see Fl_Widget::as_window(), Fl_Widget::as_gl_window()
*/
- virtual Fl_Group* as_group() {return 0;}
+ virtual Fl_Group* as_group() { return NULL; }
+ virtual Fl_Group const* as_group() const { return NULL; }
/** Returns an Fl_Window pointer if this widget is an Fl_Window.
@@ -1105,7 +1106,8 @@ public:
\note This method is provided to avoid dynamic_cast.
\see Fl_Widget::as_group(), Fl_Widget::as_gl_window()
*/
- virtual Fl_Window* as_window() {return 0;}
+ virtual Fl_Window* as_window() { return 0; }
+ virtual Fl_Window const* as_window() const { return NULL; }
/** Returns an Fl_Gl_Window pointer if this widget is an Fl_Gl_Window.
@@ -1117,7 +1119,8 @@ public:
\note This method is provided to avoid dynamic_cast.
\see Fl_Widget::as_group(), Fl_Widget::as_window()
*/
- virtual class Fl_Gl_Window* as_gl_window() {return 0;}
+ virtual class Fl_Gl_Window* as_gl_window() { return NULL; }
+ virtual class Fl_Gl_Window const* as_gl_window() const { return NULL; }
/** Returns non zero if MAC_USE_ACCENTS_MENU flag is set, 0 otherwise.
*/
diff --git a/FL/Fl_Window.H b/FL/Fl_Window.H
index ef4d78007..a6709a216 100644
--- a/FL/Fl_Window.H
+++ b/FL/Fl_Window.H
@@ -560,6 +560,7 @@ public:
// Note: Doxygen docs in Fl_Widget.H to avoid redundancy.
Fl_Window* as_window() FL_OVERRIDE { return this; }
+ Fl_Window const* as_window() const FL_OVERRIDE { return this; }
/**
Return non-null if this is an Fl_Overlay_Window object.
diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt
index ab891a67c..e8b10a1fc 100644
--- a/fluid/CMakeLists.txt
+++ b/fluid/CMakeLists.txt
@@ -17,6 +17,7 @@
set (CPPFILES
CodeEditor.cxx
StyleParse.cxx
+ Fd_Snap_Action.cxx
Fl_Function_Type.cxx
Fl_Group_Type.cxx
Fl_Menu_Type.cxx
@@ -45,6 +46,7 @@ set (CPPFILES
set (HEADERFILES
CodeEditor.h
+ Fd_Snap_Action.h
Fl_Function_Type.h
Fl_Group_Type.h
Fl_Menu_Type.h
diff --git a/fluid/Fd_Snap_Action.cxx b/fluid/Fd_Snap_Action.cxx
new file mode 100644
index 000000000..a2b3917b3
--- /dev/null
+++ b/fluid/Fd_Snap_Action.cxx
@@ -0,0 +1,1565 @@
+//
+// Snap action code file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2023 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+// https://www.fltk.org/bugs.php
+//
+
+#include "Fd_Snap_Action.h"
+
+#include "Fl_Group_Type.h"
+#include "alignment_panel.h"
+#include "file.h"
+
+#include <FL/fl_draw.H>
+#include <FL/Fl_Menu_Bar.H>
+#include <FL/fl_string_functions.h>
+#include <math.h>
+#include <string.h>
+#include <assert.h>
+
+// TODO: warning if the user wants to change builtin layouts
+// TODO: move panel to global settings panel (move load & save to main pulldown, or to toolbox?)
+// INFO: how about a small tool box for quick preset selection and diabeling of individual snaps?
+
+void select_layout_suite_cb(Fl_Widget *, void *user_data);
+
+int Fd_Snap_Action::eex = 0;
+int Fd_Snap_Action::eey = 0;
+
+static Fd_Layout_Preset fltk_app = {
+ 15, 15, 15, 15, 0, 0, // window: l, r, t, b, gx, gy
+ 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy
+ 25, 25, // tabs: t, b
+ 20, 10, 4, // widget_x: min, inc, gap
+ 20, 4, 8, // widget_y: min, inc, gap
+ 0, 14, 0, 14 // labelfont/size, textfont/size
+};
+static Fd_Layout_Preset fltk_dlg = {
+ 10, 10, 10, 10, 0, 0, // window: l, r, t, b, gx, gy
+ 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy
+ 20, 20, // tabs: t, b
+ 20, 10, 5, // widget_x: min, inc, gap
+ 20, 5, 5, // widget_y: min, inc, gap
+ 0, 11, 0, 11 // labelfont/size, textfont/size
+};
+static Fd_Layout_Preset fltk_tool = {
+ 10, 10, 10, 10, 0, 0, // window: l, r, t, b, gx, gy
+ 10, 10, 10, 10, 0, 0, // group: l, r, t, b, gx, gy
+ 18, 18, // tabs: t, b
+ 16, 8, 2, // widget_x: min, inc, gap
+ 16, 4, 2, // widget_y: min, inc, gap
+ 0, 10, 0, 10 // labelfont/size, textfont/size
+};
+
+static Fd_Layout_Preset grid_app = {
+ 12, 12, 12, 12, 12, 12, // window: l, r, t, b, gx, gy
+ 12, 12, 12, 12, 12, 12, // group: l, r, t, b, gx, gy
+ 24, 24, // tabs: t, b
+ 12, 6, 6, // widget_x: min, inc, gap
+ 12, 6, 6, // widget_y: min, inc, gap
+ 0, 14, 0, 14 // labelfont/size, textfont/size
+};
+
+static Fd_Layout_Preset grid_dlg = {
+ 10, 10, 10, 10, 10, 10, // window: l, r, t, b, gx, gy
+ 10, 10, 10, 10, 10, 10, // group: l, r, t, b, gx, gy
+ 20, 20, // tabs: t, b
+ 10, 5, 5, // widget_x: min, inc, gap
+ 10, 5, 5, // widget_y: min, inc, gap
+ 0, 12, 0, 12 // labelfont/size, textfont/size
+};
+
+static Fd_Layout_Preset grid_tool = {
+ 8, 8, 8, 8, 8, 8, // window: l, r, t, b, gx, gy
+ 8, 8, 8, 8, 8, 8, // group: l, r, t, b, gx, gy
+ 16, 16, // tabs: t, b
+ 8, 4, 4, // widget_x: min, inc, gap
+ 8, 4, 4, // widget_y: min, inc, gap
+ 0, 10, 0, 10 // labelfont/size, textfont/size
+};
+
+static Fd_Layout_Suite static_suite_list[] = {
+ { (char*)"FLTK", (char*)"@fd_beaker FLTK", { &fltk_app, &fltk_dlg, &fltk_tool }, FD_STORE_INTERNAL },
+ { (char*)"Grid", (char*)"@fd_beaker Grid", { &grid_app, &grid_dlg, &grid_tool }, FD_STORE_INTERNAL }
+};
+
+static Fl_Menu_Item static_main_menu[] = {
+ { static_suite_list[0].menu_label, 0, select_layout_suite_cb, (void*)0, FL_MENU_RADIO|FL_MENU_VALUE },
+ { static_suite_list[1].menu_label, 0, select_layout_suite_cb, (void*)1, FL_MENU_RADIO },
+ { NULL }
+};
+
+static Fl_Menu_Item static_choice_menu[] = {
+ { static_suite_list[0].menu_label },
+ { static_suite_list[1].menu_label },
+ { NULL }
+};
+
+Fd_Layout_Preset *layout = &fltk_app;
+Fd_Layout_List g_layout_list;
+
+// ---- Callbacks ------------------------------------------------------ MARK: -
+
+void layout_suite_marker(Fl_Widget *, void *) {
+ assert(0);
+ // intentionally left empty
+}
+
+void select_layout_suite_cb(Fl_Widget *, void *user_data) {
+ int index = (int)(fl_intptr_t)user_data;
+ assert(index >= 0);
+ assert(index < g_layout_list.list_size_);
+ g_layout_list.current_suite(index);
+ g_layout_list.update_dialogs();
+}
+
+void select_layout_preset_cb(Fl_Widget *, void *user_data) {
+ int index = (int)(fl_intptr_t)user_data;
+ assert(index >= 0);
+ assert(index < 3);
+ g_layout_list.current_preset(index);
+ g_layout_list.update_dialogs();
+}
+
+void edit_layout_preset_cb(Fl_Button *w, long user_data) {
+ int index = (int)w->argument();
+ assert(index >= 0);
+ assert(index < 3);
+ if (user_data == (long)(fl_intptr_t)LOAD) {
+ w->value(g_layout_list.current_preset() == index);
+ } else {
+ g_layout_list.current_preset(index);
+ g_layout_list.update_dialogs();
+ }
+}
+
+// ---- Fd_Layout_Suite ------------------------------------------------ MARK: -
+
+void Fd_Layout_Preset::write(Fl_Preferences &prefs) {
+ assert(this);
+ Fl_Preferences p_win(prefs, "Window");
+ p_win.set("left_margin", left_window_margin);
+ p_win.set("right_margin", right_window_margin);
+ p_win.set("top_margin", top_window_margin);
+ p_win.set("bottom_margin", bottom_window_margin);
+ p_win.set("grid_x", window_grid_x);
+ p_win.set("grid_y", window_grid_y);
+
+ Fl_Preferences p_grp(prefs, "Group");
+ p_grp.set("left_margin", left_group_margin);
+ p_grp.set("right_margin", right_group_margin);
+ p_grp.set("top_margin", top_group_margin);
+ p_grp.set("bottom_margin", bottom_group_margin);
+ p_grp.set("grid_x", group_grid_x);
+ p_grp.set("grid_y", group_grid_y);
+
+ Fl_Preferences p_tbs(prefs, "Tabs");
+ p_tbs.set("top_margin", top_tabs_margin);
+ p_tbs.set("bottom_margin", bottom_tabs_margin);
+
+ Fl_Preferences p_wgt(prefs, "Widget");
+ p_wgt.set("min_w", widget_min_w);
+ p_wgt.set("inc_w", widget_inc_w);
+ p_wgt.set("gap_x", widget_gap_x);
+ p_wgt.set("min_h", widget_min_h);
+ p_wgt.set("inc_h", widget_inc_h);
+ p_wgt.set("gap_y", widget_gap_y);
+
+ Fl_Preferences p_lyt(prefs, "Layout");
+ p_lyt.set("labelfont", labelfont);
+ p_lyt.set("labelsize", labelsize);
+ p_lyt.set("textfont", textfont);
+ p_lyt.set("textsize", textsize);
+}
+
+void Fd_Layout_Preset::read(Fl_Preferences &prefs) {
+ assert(this);
+ Fl_Preferences p_win(prefs, "Window");
+ p_win.get("left_margin", left_window_margin, 15);
+ p_win.get("right_margin", right_window_margin, 15);
+ p_win.get("top_margin", top_window_margin, 15);
+ p_win.get("bottom_margin", bottom_window_margin, 15);
+ p_win.get("grid_x", window_grid_x, 0);
+ p_win.get("grid_y", window_grid_y, 0);
+
+ Fl_Preferences p_grp(prefs, "Group");
+ p_grp.get("left_margin", left_group_margin, 10);
+ p_grp.get("right_margin", right_group_margin, 10);
+ p_grp.get("top_margin", top_group_margin, 10);
+ p_grp.get("bottom_margin", bottom_group_margin, 10);
+ p_grp.get("grid_x", group_grid_x, 0);
+ p_grp.get("grid_y", group_grid_y, 0);
+
+ Fl_Preferences p_tbs(prefs, "Tabs");
+ p_tbs.get("top_margin", top_tabs_margin, 25);
+ p_tbs.get("bottom_margin", bottom_tabs_margin, 25);
+
+ Fl_Preferences p_wgt(prefs, "Widget");
+ p_wgt.get("min_w", widget_min_w, 20);
+ p_wgt.get("inc_w", widget_inc_w, 10);
+ p_wgt.get("gap_x", widget_gap_x, 4);
+ p_wgt.get("min_h", widget_min_h, 20);
+ p_wgt.get("inc_h", widget_inc_h, 4);
+ p_wgt.get("gap_y", widget_gap_y, 8);
+
+ Fl_Preferences p_lyt(prefs, "Layout");
+ p_lyt.get("labelfont", labelfont, 0);
+ p_lyt.get("labelsize", labelsize, 14);
+ p_lyt.get("textfont", textfont, 0);
+ p_lyt.get("textsize", textsize, 14);
+}
+
+void Fd_Layout_Preset::write(Fd_Project_Writer *out) {
+ out->write_string(" preset { 1\n"); // preset format version
+ out->write_string(" %d %d %d %d %d %d\n",
+ left_window_margin, right_window_margin,
+ top_window_margin, bottom_window_margin,
+ window_grid_x, window_grid_y);
+ out->write_string(" %d %d %d %d %d %d\n",
+ left_group_margin, right_group_margin,
+ top_group_margin, bottom_group_margin,
+ group_grid_x, group_grid_y);
+ out->write_string(" %d %d\n", top_tabs_margin, bottom_tabs_margin);
+ out->write_string(" %d %d %d %d %d %d\n",
+ widget_min_w, widget_inc_w, widget_gap_x,
+ widget_min_h, widget_inc_h, widget_gap_y);
+ out->write_string(" %d %d %d %d\n",
+ labelfont, labelsize, textfont, textsize);
+ out->write_string(" }\n"); // preset format version
+}
+
+void Fd_Layout_Preset::read(Fd_Project_Reader *in) {
+ const char *key;
+ key = in->read_word(1);
+ if (key && !strcmp(key, "{")) {
+ for (;;) {
+ key = in->read_word();
+ if (!key) return;
+ if (key[0] == '}') break;
+ int ver = atoi(key);
+ if (ver == 0) {
+ continue;
+ } else if (ver == 1) {
+ left_window_margin = in->read_int();
+ right_window_margin = in->read_int();
+ top_window_margin = in->read_int();
+ bottom_window_margin = in->read_int();
+ window_grid_x = in->read_int();
+ window_grid_y = in->read_int();
+
+ left_group_margin = in->read_int();
+ right_group_margin = in->read_int();
+ top_group_margin = in->read_int();
+ bottom_group_margin = in->read_int();
+ group_grid_x = in->read_int();
+ group_grid_y = in->read_int();
+
+ top_tabs_margin = in->read_int();
+ bottom_tabs_margin = in->read_int();
+
+ widget_min_w = in->read_int();
+ widget_inc_w = in->read_int();
+ widget_gap_x = in->read_int();
+ widget_min_h = in->read_int();
+ widget_inc_h = in->read_int();
+ widget_gap_y = in->read_int();
+
+ labelfont = in->read_int();
+ labelsize = in->read_int();
+ textfont = in->read_int();
+ textsize = in->read_int();
+ } else { // skip unknown chunks
+ for (;;) {
+ key = in->read_word(1);
+ if (key && (key[0] == '}'))
+ return;
+ }
+ }
+ }
+ } else {
+ // format error
+ }
+}
+
+
+// ---- Fd_Layout_Suite ------------------------------------------------ MARK: -
+
+void Fd_Layout_Suite::write(Fl_Preferences &prefs) {
+ assert(this);
+ assert(name_);
+ prefs.set("name", name_);
+ for (int i = 0; i < 3; ++i) {
+ Fl_Preferences prefs_preset(prefs, Fl_Preferences::Name(i));
+ assert(layout[i]);
+ layout[i]->write(prefs_preset);
+ }
+}
+
+void Fd_Layout_Suite::read(Fl_Preferences &prefs) {
+ assert(this);
+ for (int i = 0; i < 3; ++i) {
+ Fl_Preferences prefs_preset(prefs, Fl_Preferences::Name(i));
+ assert(layout[i]);
+ layout[i]->read(prefs_preset);
+ }
+}
+
+void Fd_Layout_Suite::write(Fd_Project_Writer *out) {
+ out->write_string(" suite {\n");
+ out->write_string(" name "); out->write_word(name_); out->write_string("\n");
+ for (int i = 0; i < 3; ++i) {
+ layout[i]->write(out);
+ }
+ out->write_string(" }\n");
+}
+
+void Fd_Layout_Suite::read(Fd_Project_Reader *in) {
+ const char *key;
+ key = in->read_word(1);
+ if (key && !strcmp(key, "{")) {
+ int ix = 0;
+ for (;;) {
+ key = in->read_word();
+ if (!key) return;
+ if (!strcmp(key, "name")) {
+ name(in->read_word());
+ } else if (!strcmp(key, "preset")) {
+ if (ix >= 3) return; // file format error
+ layout[ix++]->read(in);
+ } else if (!strcmp(key, "}")) {
+ break;
+ } else {
+ in->read_word(); // unknown key, ignore, hopefully a key-value pair
+ }
+ }
+ } else {
+ // file format error
+ }
+}
+
+void Fd_Layout_Suite::update_label() {
+ Fl_String sym;
+ switch (storage_) {
+ case FD_STORE_INTERNAL: sym.assign("@fd_beaker "); break;
+ case FD_STORE_USER: sym.assign("@fd_user "); break;
+ case FD_STORE_PROJECT: sym.assign("@fd_project "); break;
+ case FD_STORE_FILE: sym.assign("@fd_file "); break;
+ }
+ sym.append(name_);
+ if (menu_label)
+ ::free(menu_label);
+ menu_label = fl_strdup(sym.c_str());
+ g_layout_list.update_menu_labels();
+}
+
+void Fd_Layout_Suite::name(const char *n) {
+ if (name_)
+ ::free(name_);
+ if (n)
+ name_ = fl_strdup(n);
+ else
+ name_ = NULL;
+ update_label();
+}
+
+void Fd_Layout_Suite::init() {
+ name_ = NULL;
+ menu_label = NULL;
+ layout[0] = layout[1] = layout[2] = NULL;
+ storage_ = 0;
+}
+
+Fd_Layout_Suite::~Fd_Layout_Suite() {
+ if (storage_ == FD_STORE_INTERNAL) return;
+ if (name_) ::free(name_);
+ for (int i = 0; i < 3; ++i) {
+ delete layout[i];
+ }
+}
+
+// ---- Fd_Layout_List ------------------------------------------------- MARK: -
+
+static void fd_beaker(Fl_Color c) {
+ fl_color(221);
+ fl_begin_polygon();
+ fl_vertex(-0.6, 0.2);
+ fl_vertex(-0.9, 0.8);
+ fl_vertex(-0.8, 0.9);
+ fl_vertex( 0.8, 0.9);
+ fl_vertex( 0.9, 0.8);
+ fl_vertex( 0.6, 0.2);
+ fl_end_polygon();
+ fl_color(c);
+ fl_begin_line();
+ fl_vertex(-0.3, -0.9);
+ fl_vertex(-0.2, -0.8);
+ fl_vertex(-0.2, -0.2);
+ fl_vertex(-0.9, 0.8);
+ fl_vertex(-0.8, 0.9);
+ fl_vertex( 0.8, 0.9);
+ fl_vertex( 0.9, 0.8);
+ fl_vertex( 0.2, -0.2);
+ fl_vertex( 0.2, -0.8);
+ fl_vertex( 0.3, -0.9);
+ fl_end_line();
+}
+
+static void fd_user(Fl_Color c) {
+ fl_color(245);
+ fl_begin_complex_polygon();
+ fl_arc( 0.1, 0.9, 0.8, 0.0, 80.0);
+ fl_arc( 0.0, -0.5, 0.4, -65.0, 245.0);
+ fl_arc(-0.1, 0.9, 0.8, 100.0, 180.0);
+ fl_end_complex_polygon();
+ fl_color(c);
+ fl_begin_line();
+ fl_arc( 0.1, 0.9, 0.8, 0.0, 80.0);
+ fl_arc( 0.0, -0.5, 0.4, -65.0, 245.0);
+ fl_arc(-0.1, 0.9, 0.8, 100.0, 180.0);
+ fl_end_line();
+}
+
+static void fd_project(Fl_Color c) {
+ Fl_Color fc = FL_LIGHT2;
+ fl_color(fc);
+ fl_begin_complex_polygon();
+ fl_vertex(-0.7, -1.0);
+ fl_vertex(0.1, -1.0);
+ fl_vertex(0.1, -0.4);
+ fl_vertex(0.7, -0.4);
+ fl_vertex(0.7, 1.0);
+ fl_vertex(-0.7, 1.0);
+ fl_end_complex_polygon();
+
+ fl_color(fl_lighter(fc));
+ fl_begin_polygon();
+ fl_vertex(0.1, -1.0);
+ fl_vertex(0.1, -0.4);
+ fl_vertex(0.7, -0.4);
+ fl_end_polygon();
+
+ fl_color(fl_darker(c));
+ fl_begin_loop();
+ fl_vertex(-0.7, -1.0);
+ fl_vertex(0.1, -1.0);
+ fl_vertex(0.1, -0.4);
+ fl_vertex(0.7, -0.4);
+ fl_vertex(0.7, 1.0);
+ fl_vertex(-0.7, 1.0);
+ fl_end_loop();
+
+ fl_begin_line();
+ fl_vertex(0.1, -1.0);
+ fl_vertex(0.7, -0.4);
+ fl_end_line();
+}
+
+void fd_file(Fl_Color c) {
+ Fl_Color fl = FL_LIGHT2;
+ Fl_Color fc = FL_DARK3;
+ fl_color(fc);
+ fl_begin_polygon(); // case
+ fl_vertex(-0.9, -1.0);
+ fl_vertex(0.9, -1.0);
+ fl_vertex(1.0, -0.9);
+ fl_vertex(1.0, 0.9);
+ fl_vertex(0.9, 1.0);
+ fl_vertex(-0.9, 1.0);
+ fl_vertex(-1.0, 0.9);
+ fl_vertex(-1.0, -0.9);
+ fl_end_polygon();
+
+ fl_color(fl_lighter(fl));
+ fl_begin_polygon();
+ fl_vertex(-0.7, -1.0); // slider
+ fl_vertex(0.7, -1.0);
+ fl_vertex(0.7, -0.4);
+ fl_vertex(-0.7, -0.4);
+ fl_end_polygon();
+
+ fl_begin_polygon(); // label
+ fl_vertex(-0.7, 0.0);
+ fl_vertex(0.7, 0.0);
+ fl_vertex(0.7, 1.0);
+ fl_vertex(-0.7, 1.0);
+ fl_end_polygon();
+
+ fl_color(fc);
+ fl_begin_polygon();
+ fl_vertex(-0.5, -0.9); // slot
+ fl_vertex(-0.3, -0.9);
+ fl_vertex(-0.3, -0.5);
+ fl_vertex(-0.5, -0.5);
+ fl_end_polygon();
+
+ fl_color(fl_darker(c));
+ fl_begin_loop();
+ fl_vertex(-0.9, -1.0);
+ fl_vertex(0.9, -1.0);
+ fl_vertex(1.0, -0.9);
+ fl_vertex(1.0, 0.9);
+ fl_vertex(0.9, 1.0);
+ fl_vertex(-0.9, 1.0);
+ fl_vertex(-1.0, 0.9);
+ fl_vertex(-1.0, -0.9);
+ fl_end_loop();
+}
+
+
+Fd_Layout_List::Fd_Layout_List()
+: main_menu_(static_main_menu),
+ choice_menu_(static_choice_menu),
+ list_(static_suite_list),
+ list_size_(2),
+ list_capacity_(2),
+ list_is_static_(true),
+ current_suite_(0),
+ current_preset_(0),
+ filename_(NULL)
+{
+ fl_add_symbol("fd_beaker", fd_beaker, 1);
+ fl_add_symbol("fd_user", fd_user, 1);
+ fl_add_symbol("fd_project", fd_project, 1);
+ fl_add_symbol("fd_file", fd_file, 1);
+}
+
+Fd_Layout_List::~Fd_Layout_List() {
+ assert(this);
+ if (!list_is_static_) {
+ ::free(main_menu_);
+ ::free(choice_menu_);
+ for (int i = 0; i < list_size_; i++) {
+ Fd_Layout_Suite &suite = list_[i];
+ if (suite.storage_ != FD_STORE_INTERNAL)
+ suite.~Fd_Layout_Suite();
+ }
+ ::free(list_);
+ }
+ if (filename_) ::free(filename_);
+}
+
+void Fd_Layout_List::update_dialogs() {
+ static Fl_Menu_Item *preset_menu = NULL;
+ if (!preset_menu) {
+ preset_menu = (Fl_Menu_Item*)main_menubar->find_item(select_layout_preset_cb);
+ assert(preset_menu);
+ }
+ assert(this);
+ assert(current_suite_ >= 0 );
+ assert(current_suite_ < list_size_);
+ assert(current_preset_ >= 0 );
+ assert(current_preset_ < 3);
+ layout = list_[current_suite_].layout[current_preset_];
+ assert(layout);
+ if (grid_window) {
+ grid_window->do_callback(grid_window, LOAD);
+ layout_choice->redraw();
+ }
+ preset_menu[current_preset_].setonly(preset_menu);
+ main_menu_[current_suite_].setonly(main_menu_);
+}
+
+void Fd_Layout_List::update_menu_labels() {
+ for (int i=0; i<list_size_; i++) {
+ main_menu_[i].label(list_[i].menu_label);
+ choice_menu_[i].label(list_[i].menu_label);
+ }
+}
+
+int Fd_Layout_List::load(const char *filename) {
+ remove_all(FD_STORE_FILE);
+ Fl_Preferences prefs(filename, "layout.fluid.fltk.org", NULL);
+ read(prefs, FD_STORE_FILE);
+ return 0;
+}
+
+int Fd_Layout_List::save(const char *filename) {
+ assert(this);
+ assert(filename);
+ Fl_Preferences prefs(filename, "layout.fluid.fltk.org", NULL);
+ prefs.clear();
+ write(prefs, FD_STORE_FILE);
+ return 0;
+}
+
+void Fd_Layout_List::write(Fl_Preferences &prefs, int storage) {
+ Fl_Preferences prefs_list(prefs, "Layouts");
+ prefs_list.clear();
+ prefs_list.set("current_suite", list_[current_suite()].name_);
+ prefs_list.set("current_preset", current_preset());
+ int n = 0;
+ for (int i = 0; i < list_size_; ++i) {
+ Fd_Layout_Suite &suite = list_[i];
+ if (suite.storage_ == storage) {
+ Fl_Preferences prefs_suite(prefs_list, Fl_Preferences::Name(n++));
+ suite.write(prefs_suite);
+ }
+ }
+}
+
+void Fd_Layout_List::read(Fl_Preferences &prefs, int storage) {
+ Fl_Preferences prefs_list(prefs, "Layouts");
+ Fl_String cs;
+ int cp = 0;
+ prefs_list.get("current_suite", cs, "");
+ prefs_list.get("current_preset", cp, 0);
+ for (int i = 0; i < prefs_list.groups(); ++i) {
+ Fl_Preferences prefs_suite(prefs_list, Fl_Preferences::Name(i));
+ char *new_name = NULL;
+ prefs_suite.get("name", new_name, NULL);
+ if (new_name) {
+ int n = add(new_name);
+ list_[n].read(prefs_suite);
+ list_[n].storage(storage);
+ ::free(new_name);
+ }
+ }
+ current_suite(cs);
+ current_preset(cp);
+ update_dialogs();
+}
+
+void Fd_Layout_List::write(Fd_Project_Writer *out) {
+ out->write_string("\nsnap {\n ver 1\n");
+ out->write_string(" current_suite "); out->write_word(list_[current_suite()].name_); out->write_string("\n");
+ out->write_string(" current_preset %d\n", current_preset());
+ for (int i=0; i<list_size_; i++) {
+ Fd_Layout_Suite &suite = list_[i];
+ if (suite.storage_ == FD_STORE_PROJECT)
+ suite.write(out);
+ }
+ out->write_string("}");
+}
+
+void Fd_Layout_List::read(Fd_Project_Reader *in) {
+ const char *key;
+ key = in->read_word(1);
+ if (key && !strcmp(key, "{")) {
+ Fl_String cs;
+ int cp = 0;
+ for (;;) {
+ key = in->read_word();
+ if (!key) return;
+ if (!strcmp(key, "ver")) {
+ in->read_int();
+ } else if (!strcmp(key, "current_suite")) {
+ cs = in->read_word();
+ } else if (!strcmp(key, "current_preset")) {
+ cp = in->read_int();
+ } else if (!strcmp(key, "suite")) {
+ int n = add(in->filename_name());
+ list_[n].read(in);
+ list_[n].storage(FD_STORE_PROJECT);
+ } else if (!strcmp(key, "}")) {
+ break;
+ } else {
+ in->read_word(); // unknown key, ignore, hopefully a key-value pair
+ }
+ }
+ current_suite(cs);
+ current_preset(cp);
+ update_dialogs();
+ } else {
+ // old style "snap" is followed by an integer. Ignore.
+ }
+}
+
+void Fd_Layout_List::current_suite(int ix) {
+ assert(ix >= 0);
+ assert(ix < list_size_);
+ current_suite_ = ix;
+ layout = list_[current_suite_].layout[current_preset_];
+}
+
+void Fd_Layout_List::current_suite(Fl_String arg_name) {
+ if (arg_name.empty()) return;
+ for (int i = 0; i < list_size_; ++i) {
+ Fd_Layout_Suite &suite = list_[i];
+ if (suite.name_ && (strcmp(suite.name_, arg_name.c_str()) == 0)) {
+ current_suite(i);
+ break;
+ }
+ }
+}
+
+void Fd_Layout_List::current_preset(int ix) {
+ assert(ix >= 0);
+ assert(ix < 3);
+ current_preset_ = ix;
+ layout = list_[current_suite_].layout[current_preset_];
+}
+
+/**
+ Allocate enough space for n entries in the list.
+ */
+void Fd_Layout_List::capacity(int n) {
+ static Fl_Menu_Item *suite_menu = NULL;
+ if (!suite_menu)
+ suite_menu = (Fl_Menu_Item*)main_menubar->find_item(layout_suite_marker);
+
+ int old_n = list_size_;
+ int i;
+
+ Fd_Layout_Suite *new_list = (Fd_Layout_Suite*)::calloc(n, sizeof(Fd_Layout_Suite));
+ for (i = 0; i < old_n; i++)
+ new_list[i] = list_[i];
+ if (!list_is_static_) ::free(list_);
+ list_ = new_list;
+
+ Fl_Menu_Item *new_main_menu = (Fl_Menu_Item*)::calloc(n+1, sizeof(Fl_Menu_Item));
+ for (i = 0; i < old_n; i++)
+ new_main_menu[i] = main_menu_[i];
+ if (!list_is_static_) ::free(main_menu_);
+ main_menu_ = new_main_menu;
+ suite_menu->user_data(main_menu_);
+
+ Fl_Menu_Item *new_choice_menu = (Fl_Menu_Item*)::calloc(n+1, sizeof(Fl_Menu_Item));
+ for (i = 0; i < old_n; i++)
+ new_choice_menu[i] = choice_menu_[i];
+ if (!list_is_static_) ::free(choice_menu_);
+ choice_menu_ = new_choice_menu;
+ layout_choice->menu(choice_menu_);
+
+ list_capacity_ = n;
+ list_is_static_ = false;
+}
+
+/**
+ Clone the currently selected suite and append it to the list.
+ Selectes the new layout and updates the UI.
+ */
+int Fd_Layout_List::add(const char *name) {
+ if (list_size_ == list_capacity_) {
+ capacity(list_capacity_ * 2);
+ }
+ int n = list_size_;
+ Fd_Layout_Suite &old_suite = list_[current_suite_];
+ Fd_Layout_Suite &new_suite = list_[n];
+ new_suite.init();
+ new_suite.name(name);
+ for (int i=0; i<3; ++i) {
+ new_suite.layout[i] = new Fd_Layout_Preset;
+ ::memcpy(new_suite.layout[i], old_suite.layout[i], sizeof(Fd_Layout_Preset));
+ }
+ int new_storage = old_suite.storage_;
+ if (new_storage == FD_STORE_INTERNAL)
+ new_storage = FD_STORE_USER;
+ new_suite.storage(new_storage);
+ main_menu_[n].label(new_suite.menu_label);
+ main_menu_[n].callback(main_menu_[0].callback());
+ main_menu_[n].argument(n);
+ main_menu_[n].flags = main_menu_[0].flags;
+ choice_menu_[n].label(new_suite.menu_label);
+ list_size_++;
+ current_suite(n);
+ return n;
+}
+
+void Fd_Layout_List::rename(const char *name) {
+ int n = current_suite();
+ list_[n].name(name);
+ main_menu_[n].label(list_[n].menu_label);
+ choice_menu_[n].label(list_[n].menu_label);
+}
+
+void Fd_Layout_List::remove(int ix) {
+ int tail = list_size_-ix-1;
+ if (tail) {
+ for (int i = ix; i < list_size_-1; i++)
+ list_[i] = list_[i+1];
+ }
+ ::memmove(main_menu_+ix, main_menu_+ix+1, (tail+1) * sizeof(Fl_Menu_Item));
+ ::memmove(choice_menu_+ix, choice_menu_+ix+1, (tail+1) * sizeof(Fl_Menu_Item));
+ list_size_--;
+ if (current_suite() >= list_size_)
+ current_suite(list_size_ - 1);
+}
+
+void Fd_Layout_List::remove_all(int storage) {
+ for (int i=list_size_-1; i>=0; --i) {
+ if (list_[i].storage_ == storage)
+ remove(i);
+ }
+}
+
+// ---- Helper --------------------------------------------------------- MARK: -
+
+static void draw_h_arrow(int, int, int);
+static void draw_v_arrow(int x, int y1, int y2);
+static void draw_left_brace(const Fl_Widget *w);
+static void draw_right_brace(const Fl_Widget *w);
+static void draw_top_brace(const Fl_Widget *w);
+static void draw_bottom_brace(const Fl_Widget *w);
+static void draw_grid(int x, int y, int dx, int dy);
+static void draw_width(int x, int y, int r, Fl_Align a);
+static void draw_height(int x, int y, int b, Fl_Align a);
+
+static int nearest(int x, int left, int grid, int right=0x7fff) {
+ int grid_x = ((x-left+grid/2)/grid)*grid+left;
+ if (grid_x < left+grid/2) return left; // left+grid/2;
+ if (grid_x > right-grid/2) return right; // right-grid/2;
+ return grid_x;
+}
+
+static bool in_window(Fd_Snap_Data &d) {
+ return (d.wgt && d.wgt->parent == d.win);
+}
+
+static bool in_group(Fd_Snap_Data &d) {
+ return (d.wgt && d.wgt->parent && d.wgt->parent->is_group() && d.wgt->parent != d.win);
+}
+
+static bool in_tabs(Fd_Snap_Data &d) {
+ return (d.wgt && d.wgt->parent && d.wgt->parent->is_tabs());
+}
+
+static Fl_Group *parent(Fd_Snap_Data &d) {
+ return (d.wgt->o->parent());
+}
+
+// ---- Fd_Snap_Action ------------------------------------------------- MARK: -
+
+/** \class Fd_Snap_Action
+ */
+
+int Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) {
+ int dd = x_ref + d.dx - x_snap;
+ int d2 = abs(dd);
+ if (d2 > d.x_dist) return 1;
+ dx = d.dx_out = d.dx - dd;
+ ex = d.ex_out = x_snap;
+ if (d2 == d.x_dist) return 0;
+ d.x_dist = d2;
+ return -1;
+}
+
+int Fd_Snap_Action::check_y_(Fd_Snap_Data &d, int y_ref, int y_snap) {
+ int dd = y_ref + d.dy - y_snap;
+ int d2 = abs(dd);
+ if (d2 > d.y_dist) return 1;
+ dy = d.dy_out = d.dy - dd;
+ ey = d.ey_out = y_snap;
+ if (d2 == d.y_dist) return 0;
+ d.y_dist = d2;
+ return -1;
+}
+
+void Fd_Snap_Action::check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_ref, int y_snap) {
+ int ddx = x_ref + d.dx - x_snap;
+ int d2x = abs(ddx);
+ int ddy = y_ref + d.dy - y_snap;
+ int d2y = abs(ddy);
+ if ((d2x <= d.x_dist) && (d2y <= d.y_dist)) {
+ dx = d.dx_out = d.dx - ddx;
+ ex = d.ex_out = x_snap;
+ d.x_dist = d2x;
+ dy = d.dy_out = d.dy - ddy;
+ ey = d.ey_out = y_snap;
+ d.y_dist = d2y;
+ }
+}
+
+bool Fd_Snap_Action::matches(Fd_Snap_Data &d) {
+ switch (type) {
+ case 1: return (d.drag & mask) && (eex == ex) && (d.dx == dx);
+ case 2: return (d.drag & mask) && (eey == ey) && (d.dy == dy);
+ case 3: return (d.drag & mask) && (eex == ex) && (d.dx == dx) && (eey == ey) && (d.dy == dy);
+ }
+ return false;
+}
+
+void Fd_Snap_Action::check_all(Fd_Snap_Data &data) {
+ for (int i=0; list[i]; i++) {
+ if (list[i]->mask & data.drag)
+ list[i]->check(data);
+ }
+ eex = data.ex_out;
+ eey = data.ey_out;
+}
+
+void Fd_Snap_Action::draw_all(Fd_Snap_Data &data) {
+ for (int i=0; list[i]; i++) {
+ if (list[i]->matches(data))
+ list[i]->draw(data);
+ }
+}
+
+/** Return a sensible step size for resizing a widget. */
+void Fd_Snap_Action::get_resize_stepsize(int &x_step, int &y_step) {
+ if ((layout->widget_inc_w > 1) && (layout->widget_inc_h > 1)) {
+ x_step = layout->widget_inc_w;
+ y_step = layout->widget_inc_h;
+ } else if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) {
+ x_step = layout->group_grid_x;
+ y_step = layout->group_grid_y;
+ } else {
+ x_step = layout->window_grid_x;
+ y_step = layout->window_grid_y;
+ }
+}
+
+/** Return a sensible step size for moving a widget. */
+void Fd_Snap_Action::get_move_stepsize(int &x_step, int &y_step) {
+ if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) {
+ x_step = layout->group_grid_x;
+ y_step = layout->group_grid_y;
+ } else if ((layout->window_grid_x > 1) && (layout->window_grid_y > 1)) {
+ x_step = layout->window_grid_x;
+ y_step = layout->window_grid_y;
+ } else {
+ x_step = layout->widget_gap_x;
+ y_step = layout->widget_gap_y;
+ }
+}
+
+// ---- snapping prototypes -------------------------------------------- MARK: -
+
+class Fd_Snap_Left : public Fd_Snap_Action {
+public:
+ Fd_Snap_Left() { type = 1; mask = FD_LEFT|FD_DRAG; }
+};
+
+class Fd_Snap_Right : public Fd_Snap_Action {
+public:
+ Fd_Snap_Right() { type = 1; mask = FD_RIGHT|FD_DRAG; }
+};
+
+class Fd_Snap_Top : public Fd_Snap_Action {
+public:
+ Fd_Snap_Top() { type = 2; mask = FD_TOP|FD_DRAG; }
+};
+
+class Fd_Snap_Bottom : public Fd_Snap_Action {
+public:
+ Fd_Snap_Bottom() { type = 2; mask = FD_BOTTOM|FD_DRAG; }
+};
+
+// ---- window snapping ------------------------------------------------ MARK: -
+
+class Fd_Snap_Left_Window_Edge : public Fd_Snap_Left {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_x_(d, d.bx, 0); }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_left_brace(d.win->o); };
+};
+Fd_Snap_Left_Window_Edge snap_left_window_edge;
+
+class Fd_Snap_Right_Window_Edge : public Fd_Snap_Right {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_x_(d, d.br, d.win->o->w()); }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_right_brace(d.win->o); };
+};
+Fd_Snap_Right_Window_Edge snap_right_window_edge;
+
+class Fd_Snap_Top_Window_Edge : public Fd_Snap_Top {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_y_(d, d.by, 0); }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_top_brace(d.win->o); };
+};
+Fd_Snap_Top_Window_Edge snap_top_window_edge;
+
+class Fd_Snap_Bottom_Window_Edge : public Fd_Snap_Bottom {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE { clr(); check_y_(d, d.bt, d.win->o->h()); }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE { draw_bottom_brace(d.win->o); };
+};
+Fd_Snap_Bottom_Window_Edge snap_bottom_window_edge;
+
+class Fd_Snap_Left_Window_Margin : public Fd_Snap_Left {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_window(d)) check_x_(d, d.bx, layout->left_window_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_h_arrow(d.bx, (d.by+d.bt)/2, 0);
+ };
+};
+Fd_Snap_Left_Window_Margin snap_left_window_margin;
+
+class Fd_Snap_Right_Window_Margin : public Fd_Snap_Right {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_window(d)) check_x_(d, d.br, d.win->o->w()-layout->right_window_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_h_arrow(d.br, (d.by+d.bt)/2, d.win->o->w()-1);
+ };
+};
+Fd_Snap_Right_Window_Margin snap_right_window_margin;
+
+class Fd_Snap_Top_Window_Margin : public Fd_Snap_Top {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_window(d)) check_y_(d, d.by, layout->top_window_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_v_arrow((d.bx+d.br)/2, d.by, 0);
+ };
+};
+Fd_Snap_Top_Window_Margin snap_top_window_margin;
+
+class Fd_Snap_Bottom_Window_Margin : public Fd_Snap_Bottom {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_window(d)) check_y_(d, d.bt, d.win->o->h()-layout->bottom_window_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_v_arrow((d.bx+d.br)/2, d.bt, d.win->o->h()-1);
+ };
+};
+Fd_Snap_Bottom_Window_Margin snap_bottom_window_margin;
+
+// ---- group snapping ------------------------------------------------- MARK: -
+
+class Fd_Snap_Left_Group_Edge : public Fd_Snap_Left {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_x_(d, d.bx, parent(d)->x());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_left_brace(parent(d));
+ };
+};
+Fd_Snap_Left_Group_Edge snap_left_group_edge;
+
+class Fd_Snap_Right_Group_Edge : public Fd_Snap_Right {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_x_(d, d.br, parent(d)->x() + parent(d)->w());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_right_brace(parent(d));
+ };
+};
+Fd_Snap_Right_Group_Edge snap_right_group_edge;
+
+class Fd_Snap_Top_Group_Edge : public Fd_Snap_Top {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_y_(d, d.by, parent(d)->y());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_top_brace(parent(d));
+ };
+};
+Fd_Snap_Top_Group_Edge snap_top_group_edge;
+
+class Fd_Snap_Bottom_Group_Edge : public Fd_Snap_Bottom {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_y_(d, d.bt, parent(d)->y() + parent(d)->h());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_bottom_brace(parent(d));
+ };
+};
+Fd_Snap_Bottom_Group_Edge snap_bottom_group_edge;
+
+
+class Fd_Snap_Left_Group_Margin : public Fd_Snap_Left {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_x_(d, d.bx, parent(d)->x() + layout->left_group_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_left_brace(parent(d));
+ draw_h_arrow(d.bx, (d.by+d.bt)/2, parent(d)->x());
+ };
+};
+Fd_Snap_Left_Group_Margin snap_left_group_margin;
+
+class Fd_Snap_Right_Group_Margin : public Fd_Snap_Right {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d)) check_x_(d, d.br, parent(d)->x()+parent(d)->w()-layout->right_group_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_right_brace(parent(d));
+ draw_h_arrow(d.br, (d.by+d.bt)/2, parent(d)->x()+parent(d)->w()-1);
+ };
+};
+Fd_Snap_Right_Group_Margin snap_right_group_margin;
+
+class Fd_Snap_Top_Group_Margin : public Fd_Snap_Top {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d) && !in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_group_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_top_brace(parent(d));
+ draw_v_arrow((d.bx+d.br)/2, d.by, parent(d)->y());
+ };
+};
+Fd_Snap_Top_Group_Margin snap_top_group_margin;
+
+class Fd_Snap_Bottom_Group_Margin : public Fd_Snap_Bottom {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_group(d) && !in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_group_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_bottom_brace(parent(d));
+ draw_v_arrow((d.bx+d.br)/2, d.bt, parent(d)->y()+parent(d)->h()-1);
+ };
+};
+Fd_Snap_Bottom_Group_Margin snap_bottom_group_margin;
+
+// ----- tabs snapping ------------------------------------------------- MARK: -
+
+class Fd_Snap_Top_Tabs_Margin : public Fd_Snap_Top_Group_Margin {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_tabs_margin);
+ }
+};
+Fd_Snap_Top_Tabs_Margin snap_top_tabs_margin;
+
+class Fd_Snap_Bottom_Tabs_Margin : public Fd_Snap_Bottom_Group_Margin {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_tabs_margin);
+ }
+};
+Fd_Snap_Bottom_Tabs_Margin snap_bottom_tabs_margin;
+
+// ----- grid snapping ------------------------------------------------- MARK: -
+
+class Fd_Snap_Grid : public Fd_Snap_Action {
+protected:
+ int nearest_x, nearest_y;
+public:
+ Fd_Snap_Grid() { type = 3; mask = FD_LEFT|FD_TOP|FD_DRAG; }
+ void check_grid(Fd_Snap_Data &d, int left, int grid_x, int right, int top, int grid_y, int bottom) {
+ if ((grid_x <= 1) || (grid_y <= 1)) return;
+ int suggested_x = d.bx + d.dx;
+ nearest_x = nearest(suggested_x, left, grid_x, right);
+ int suggested_y = d.by + d.dy;
+ nearest_y = nearest(suggested_y, top, grid_y, bottom);
+ if (d.drag == FD_LEFT)
+ check_x_(d, d.bx, nearest_x);
+ else if (d.drag == FD_TOP)
+ check_y_(d, d.by, nearest_y);
+ else
+ check_x_y_(d, d.bx, nearest_x, d.by, nearest_y);
+ }
+ bool matches(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (d.drag == FD_LEFT) return (eex == ex);
+ if (d.drag == FD_TOP) return (eey == ey) && (d.dx == dx);
+ return (d.drag & mask) && (eex == ex) && (d.dx == dx) && (eey == ey) && (d.dy == dy);
+ }
+};
+
+class Fd_Snap_Window_Grid : public Fd_Snap_Grid {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (in_window(d)) check_grid(d, layout->left_window_margin, layout->window_grid_x, d.win->o->w()-layout->right_window_margin,
+ layout->top_window_margin, layout->window_grid_y, d.win->o->h()-layout->bottom_window_margin);
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_grid(nearest_x, nearest_y, layout->window_grid_x, layout->window_grid_y);
+ };
+};
+Fd_Snap_Window_Grid snap_window_grid;
+
+class Fd_Snap_Group_Grid : public Fd_Snap_Grid {
+public:
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (in_group(d)) {
+ clr();
+ Fl_Widget *g = parent(d);
+ check_grid(d, g->x()+layout->left_group_margin, layout->group_grid_x, g->x()+g->w()-layout->right_group_margin,
+ g->y()+layout->top_group_margin, layout->group_grid_y, g->y()+g->h()-layout->bottom_group_margin);
+ }
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_grid(nearest_x, nearest_y, layout->group_grid_x, layout->group_grid_y);
+ };
+};
+Fd_Snap_Group_Grid snap_group_grid;
+
+// ----- sibling snapping ---------------------------------------------- MARK: -
+
+class Fd_Snap_Sibling : public Fd_Snap_Action {
+protected:
+ Fl_Widget *best_match;
+public:
+ Fd_Snap_Sibling() : best_match(NULL) { }
+ virtual int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) = 0;
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ best_match = NULL;
+ if (!d.wgt) return;
+ if (!d.wgt->parent->is_group()) return;
+ int dsib_min = 1024;
+ Fl_Group_Type *gt = (Fl_Group_Type*)d.wgt->parent;
+ Fl_Group *g = (Fl_Group*)gt->o;
+ Fl_Widget *w = d.wgt->o;
+ for (int i=0; i<g->children(); i++) {
+ Fl_Widget *c = g->child(i);
+ if (c == w) continue;
+ int sret = sibling_check(d, c);
+ if (sret < 1) {
+ int dsib;
+ if (type==1)
+ dsib = abs( ((d.by+d.bt)/2+d.dy) - (c->y()+c->h()/2) );
+ else
+ dsib = abs( ((d.bx+d.br)/2+d.dx) - (c->x()+c->w()/2) );
+ if (sret == -1 || (dsib < dsib_min)) {
+ dsib_min = dsib;
+ best_match = c;
+ }
+ }
+ }
+ }
+};
+
+class Fd_Snap_Siblings_Left_Same : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Left_Same() { type = 1; mask = FD_LEFT|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return check_x_(d, d.bx, s->x());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_left_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Left_Same snap_siblings_left_same;
+
+class Fd_Snap_Siblings_Left : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Left() { type = 1; mask = FD_LEFT|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return fd_min(check_x_(d, d.bx, s->x()+s->w()),
+ check_x_(d, d.bx, s->x()+s->w()+layout->widget_gap_x) );
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_right_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Left snap_siblings_left;
+
+class Fd_Snap_Siblings_Right_Same : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Right_Same() { type = 1; mask = FD_RIGHT|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return check_x_(d, d.br, s->x()+s->w());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_right_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Right_Same snap_siblings_right_same;
+
+class Fd_Snap_Siblings_Right : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Right() { type = 1; mask = FD_RIGHT|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return fd_min(check_x_(d, d.br, s->x()),
+ check_x_(d, d.br, s->x()-layout->widget_gap_x));
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_left_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Right snap_siblings_right;
+
+class Fd_Snap_Siblings_Top_Same : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Top_Same() { type = 2; mask = FD_TOP|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return check_y_(d, d.by, s->y());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_top_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Top_Same snap_siblings_top_same;
+
+class Fd_Snap_Siblings_Top : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Top() { type = 2; mask = FD_TOP|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return fd_min(check_y_(d, d.by, s->y()+s->h()),
+ check_y_(d, d.by, s->y()+s->h()+layout->widget_gap_y));
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_bottom_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Top snap_siblings_top;
+
+class Fd_Snap_Siblings_Bottom_Same : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Bottom_Same() { type = 2; mask = FD_BOTTOM|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return check_y_(d, d.bt, s->y()+s->h());
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_bottom_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Bottom_Same snap_siblings_bottom_same;
+
+class Fd_Snap_Siblings_Bottom : public Fd_Snap_Sibling {
+public:
+ Fd_Snap_Siblings_Bottom() { type = 2; mask = FD_BOTTOM|FD_DRAG; }
+ int sibling_check(Fd_Snap_Data &d, Fl_Widget *s) FL_OVERRIDE {
+ return fd_min(check_y_(d, d.bt, s->y()),
+ check_y_(d, d.bt, s->y()-layout->widget_gap_y));
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ if (best_match) draw_top_brace(best_match);
+ };
+};
+Fd_Snap_Siblings_Bottom snap_siblings_bottom;
+
+
+// ------ widget snapping ---------------------------------------------- MARK: -
+
+class Fd_Snap_Widget_Ideal_Width : public Fd_Snap_Action {
+public:
+ Fd_Snap_Widget_Ideal_Width() { type = 1; mask = FD_LEFT|FD_RIGHT; }
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (!d.wgt) return;
+ int iw = 15, ih = 15;
+ d.wgt->ideal_size(iw, ih);
+ if (d.drag == FD_RIGHT) {
+ check_x_(d, d.br, d.bx+iw);
+ iw = layout->widget_min_w;
+ if (iw > 0) iw = nearest(d.br-d.bx+d.dx, layout->widget_min_w, layout->widget_inc_w);
+ check_x_(d, d.br, d.bx+iw);
+ } else {
+ check_x_(d, d.bx, d.br-iw);
+ iw = layout->widget_min_w;
+ if (iw > 0) iw = nearest(d.br-d.bx-d.dx, layout->widget_min_w, layout->widget_inc_w);
+ check_x_(d, d.bx, d.br-iw);
+ }
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_width(d.bx, d.bt+7, d.br, 0);
+ };
+};
+Fd_Snap_Widget_Ideal_Width snap_widget_ideal_width;
+
+class Fd_Snap_Widget_Ideal_Height : public Fd_Snap_Action {
+public:
+ Fd_Snap_Widget_Ideal_Height() { type = 2; mask = FD_TOP|FD_BOTTOM; }
+ void check(Fd_Snap_Data &d) FL_OVERRIDE {
+ clr();
+ if (!d.wgt) return;
+ int iw, ih;
+ d.wgt->ideal_size(iw, ih);
+ if (d.drag == FD_BOTTOM) {
+ check_y_(d, d.bt, d.by+ih);
+ ih = layout->widget_min_h;
+ if (ih > 0) ih = nearest(d.bt-d.by+d.dy, layout->widget_min_h, layout->widget_inc_h);
+ check_y_(d, d.bt, d.by+ih);
+ } else {
+ check_y_(d, d.by, d.bt-ih);
+ ih = layout->widget_min_h;
+ if (ih > 0) ih = nearest(d.bt-d.by-d.dy, layout->widget_min_h, layout->widget_inc_h);
+ check_y_(d, d.by, d.bt-ih);
+ }
+ }
+ void draw(Fd_Snap_Data &d) FL_OVERRIDE {
+ draw_height(d.br+7, d.by, d.bt, 0);
+ };
+};
+Fd_Snap_Widget_Ideal_Height snap_widget_ideal_height;
+
+// ---- snap actions list ---------------------------------------------- MARK: -
+
+Fd_Snap_Action *Fd_Snap_Action::list[] = {
+ &snap_left_window_edge,
+ &snap_right_window_edge,
+ &snap_top_window_edge,
+ &snap_bottom_window_edge,
+
+ &snap_left_window_margin,
+ &snap_right_window_margin,
+ &snap_top_window_margin,
+ &snap_bottom_window_margin,
+
+ &snap_window_grid,
+ &snap_group_grid,
+
+ &snap_left_group_edge,
+ &snap_right_group_edge,
+ &snap_top_group_edge,
+ &snap_bottom_group_edge,
+
+ &snap_left_group_margin,
+ &snap_right_group_margin,
+ &snap_top_group_margin,
+ &snap_bottom_group_margin,
+
+ &snap_top_tabs_margin,
+ &snap_bottom_tabs_margin,
+
+ &snap_siblings_left_same, &snap_siblings_left,
+ &snap_siblings_right_same, &snap_siblings_right,
+ &snap_siblings_top_same, &snap_siblings_top,
+ &snap_siblings_bottom_same, &snap_siblings_bottom,
+
+ &snap_widget_ideal_width,
+ &snap_widget_ideal_height,
+
+ NULL
+};
+
+// ---- draw alignment marks ------------------------------------------- MARK: -
+
+static void draw_v_arrow(int x, int y1, int y2) {
+ int dy = (y1>y2) ? -1 : 1 ;
+ fl_yxline(x, y1, y2);
+ fl_xyline(x-4, y2, x+4);
+ fl_line(x-2, y2-dy*5, x, y2-dy);
+ fl_line(x+2, y2-dy*5, x, y2-dy);
+}
+
+static void draw_h_arrow(int x1, int y, int x2) {
+ int dx = (x1>x2) ? -1 : 1 ;
+ fl_xyline(x1, y, x2);
+ fl_yxline(x2, y-4, y+4);
+ fl_line(x2-dx*5, y-2, x2-dx, y);
+ fl_line(x2-dx*5, y+2, x2-dx, y);
+}
+
+static void draw_top_brace(const Fl_Widget *w) {
+ int x = w->as_window() ? 0 : w->x();
+ int y = w->as_window() ? 0 : w->y();
+ fl_yxline(x, y-2, y+6);
+ fl_yxline(x+w->w()-1, y-2, y+6);
+ fl_xyline(x-2, y, x+w->w()+1);
+}
+
+static void draw_left_brace(const Fl_Widget *w) {
+ int x = w->as_window() ? 0 : w->x();
+ int y = w->as_window() ? 0 : w->y();
+ fl_xyline(x-2, y, x+6);
+ fl_xyline(x-2, y+w->h()-1, x+6);
+ fl_yxline(x, y-2, y+w->h()+1);
+}
+
+static void draw_right_brace(const Fl_Widget *w) {
+ int x = w->as_window() ? w->w() - 1 : w->x() + w->w() - 1;
+ int y = w->as_window() ? 0 : w->y();
+ fl_xyline(x-6, y, x+2);
+ fl_xyline(x-6, y+w->h()-1, x+2);
+ fl_yxline(x, y-2, y+w->h()+1);
+}
+
+static void draw_bottom_brace(const Fl_Widget *w) {
+ int x = w->as_window() ? 0 : w->x();
+ int y = w->as_window() ? w->h() - 1 : w->y() + w->h() - 1;
+ fl_yxline(x, y-6, y+2);
+ fl_yxline(x+w->w()-1, y-6, y+2);
+ fl_xyline(x-2, y, x+w->w()+1);
+}
+
+static void draw_height(int x, int y, int b, Fl_Align a) {
+ char buf[16];
+ int h = b - y;
+ sprintf(buf, "%d", h);
+ fl_font(FL_HELVETICA, 9);
+ int lw = (int)fl_width(buf);
+ int lx;
+
+ b --;
+ if (h < 30) {
+ // Move height to the side...
+ if (a == FL_ALIGN_LEFT) lx = x - lw - 2;
+ else lx = x + 2;
+ fl_yxline(x, y, b);
+ } else {
+ // Put height inside the arrows...
+ if (a == FL_ALIGN_LEFT) lx = x - lw + 2;
+ else lx = x - lw / 2;
+ fl_yxline(x, y, y + (h - 11) / 2);
+ fl_yxline(x, y + (h + 11) / 2, b);
+ }
+
+ // Draw the height...
+ fl_draw(buf, lx, y + (h + 7) / 2);
+
+ // Draw the arrowheads...
+ fl_line(x-2, y+5, x, y+1, x+2, y+5);
+ fl_line(x-2, b-5, x, b-1, x+2, b-5);
+
+ // Draw the end lines...
+ fl_xyline(x - 4, y, x + 4);
+ fl_xyline(x - 4, b, x + 4);
+}
+
+static void draw_width(int x, int y, int r, Fl_Align a) {
+ char buf[16];
+ int w = r-x;
+ sprintf(buf, "%d", w);
+ fl_font(FL_HELVETICA, 9);
+ int lw = (int)fl_width(buf);
+ int ly = y + 4;
+
+ r--;
+
+ if (lw > (w - 20)) {
+ // Move width above/below the arrows...
+ if (a == FL_ALIGN_TOP) ly -= 10;
+ else ly += 10;
+
+ fl_xyline(x, y, r);
+ } else {
+ // Put width inside the arrows...
+ fl_xyline(x, y, x + (w - lw - 2) / 2);
+ fl_xyline(x + (w + lw + 2) / 2, y, r);
+ }
+
+ // Draw the width...
+ fl_draw(buf, x + (w - lw) / 2, ly-2);
+
+ // Draw the arrowheads...
+ fl_line(x+5, y-2, x+1, y, x+5, y+2);
+ fl_line(r-5, y-2, r-1, y, r-5, y+2);
+
+ // Draw the end lines...
+ fl_yxline(x, y - 4, y + 4);
+ fl_yxline(r, y - 4, y + 4);
+}
+
+static void draw_grid(int x, int y, int dx, int dy) {
+ int dx2 = 1, dy2 = 1;
+ const int n = 2;
+ for (int i=-n; i<=n; i++) {
+ for (int j=-n; j<=n; j++) {
+ if (abs(i)+abs(j) < 4) {
+ int xx = x + i*dx , yy = y + j*dy;
+ fl_xyline(xx-dx2, yy, xx+dx2);
+ fl_yxline(xx, yy-dy2, yy+dy2);
+ }
+ }
+ }
+}
diff --git a/fluid/Fd_Snap_Action.h b/fluid/Fd_Snap_Action.h
new file mode 100644
index 000000000..d107e957a
--- /dev/null
+++ b/fluid/Fd_Snap_Action.h
@@ -0,0 +1,168 @@
+//
+// Snap action header file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2023 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+// https://www.fltk.org/bugs.php
+//
+
+#ifndef _FLUID_FD_SNAP_ACTION_H
+#define _FLUID_FD_SNAP_ACTION_H
+
+#include "Fl_Window_Type.h"
+
+struct Fl_Menu_Item;
+
+enum {
+ FD_STORE_INTERNAL,
+ FD_STORE_USER,
+ FD_STORE_PROJECT,
+ FD_STORE_FILE,
+};
+
+class Fd_Layout_Preset {
+public:
+ int left_window_margin;
+ int right_window_margin;
+ int top_window_margin;
+ int bottom_window_margin;
+ int window_grid_x;
+ int window_grid_y;
+
+ int left_group_margin;
+ int right_group_margin;
+ int top_group_margin;
+ int bottom_group_margin;
+ int group_grid_x;
+ int group_grid_y;
+
+ int top_tabs_margin;
+ int bottom_tabs_margin;
+
+ int widget_min_w;
+ int widget_inc_w;
+ int widget_gap_x;
+ int widget_min_h;
+ int widget_inc_h;
+ int widget_gap_y;
+
+ int labelfont;
+ int labelsize;
+ int textfont;
+ int textsize;
+
+ void write(Fl_Preferences &prefs);
+ void read(Fl_Preferences &prefs);
+ void write(Fd_Project_Writer*);
+ void read(Fd_Project_Reader*);
+};
+
+extern Fd_Layout_Preset *layout;
+
+class Fd_Layout_Suite {
+public:
+ char *name_;
+ char *menu_label;
+ Fd_Layout_Preset *layout[3]; // application, dialog, toolbox;
+ int storage_;
+ void write(Fl_Preferences &prefs);
+ void read(Fl_Preferences &prefs);
+ void write(Fd_Project_Writer*);
+ void read(Fd_Project_Reader*);
+ void update_label();
+ void storage(int s) { storage_ = s; update_label(); }
+ void name(const char *n);
+ void init();
+ ~Fd_Layout_Suite();
+public:
+
+};
+
+class Fd_Layout_List {
+public:
+ Fl_Menu_Item *main_menu_;
+ Fl_Menu_Item *choice_menu_;
+ Fd_Layout_Suite *list_;
+ int list_size_;
+ int list_capacity_;
+ bool list_is_static_;
+ int current_suite_;
+ int current_preset_;
+ char *filename_;
+public:
+ Fd_Layout_List();
+ ~Fd_Layout_List();
+ void update_dialogs();
+ void update_menu_labels();
+ int current_suite() const { return current_suite_; }
+ void current_suite(int ix);
+ void current_suite(Fl_String);
+ int current_preset() const { return current_preset_; }
+ void current_preset(int ix);
+ Fd_Layout_Suite &operator[](int ix) { return list_[ix]; }
+ int add(const char *name);
+ void rename(const char *name);
+ void capacity(int);
+
+ int load(const char *filename);
+ int save(const char *filename);
+ void write(Fl_Preferences &prefs, int storage);
+ void read(Fl_Preferences &prefs, int storage);
+ void write(Fd_Project_Writer*);
+ void read(Fd_Project_Reader*);
+ int add(Fd_Layout_Suite*);
+ void remove(int index);
+ void remove_all(int storage);
+ Fd_Layout_Preset *at(int);
+ int size();
+};
+
+extern Fd_Layout_List g_layout_list;
+
+/**
+ \brief Structure holding all the data to perform interactive alignment operations.
+ */
+typedef struct Fd_Snap_Data {
+ int dx, dy; ///< distance of the mouse from its initial PUSH event
+ int bx, by, br, bt; ///< bounding box of the original push event or current bounding box when drawing
+ int drag; ///< drag event mask
+ int x_dist, y_dist; ///< current closest snapping distance in x and y
+ int dx_out, dy_out; ///< current closest snapping point as a delta
+ Fl_Widget_Type *wgt; ///< first selected widget
+ Fl_Window_Type *win; ///< window that handles the drag action
+ int ex_out, ey_out; ///< chosen snap position
+} Fd_Snap_Data;
+
+/**
+ \brief Find points of interest when moving the bounding box of all selected widgets.
+ */
+class Fd_Snap_Action {
+protected:
+ int check_x_(Fd_Snap_Data &d, int x_ref, int x_snap);
+ int check_y_(Fd_Snap_Data &d, int y_ref, int y_snap);
+ void check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_ref, int y_snap);
+ void clr() { ex = dx = 0x7fff; }
+public:
+ int ex, ey, dx, dy, type, mask;
+ Fd_Snap_Action() : ex(0x7fff), ey(0x7fff), dx(128), dy(128), type(0), mask(0) { }
+ virtual void check(Fd_Snap_Data &d) = 0;
+ virtual void draw(Fd_Snap_Data &d) { }
+ virtual bool matches(Fd_Snap_Data &d);
+public:
+ static int eex, eey;
+ static Fd_Snap_Action *list[];
+ static void check_all(Fd_Snap_Data &d);
+ static void draw_all(Fd_Snap_Data &d);
+ static void get_resize_stepsize(int &x_step, int &y_step);
+ static void get_move_stepsize(int &x_step, int &y_step);
+};
+
+#endif // _FLUID_FD_SNAP_ACTION_H
diff --git a/fluid/Fl_Group_Type.h b/fluid/Fl_Group_Type.h
index e8c879141..e0c52b5c9 100644
--- a/fluid/Fl_Group_Type.h
+++ b/fluid/Fl_Group_Type.h
@@ -137,11 +137,6 @@ public:
class Fl_Tabs_Type : public Fl_Group_Type {
public:
- void ideal_spacing(int &x, int &y) FL_OVERRIDE {
- x = 10;
- fl_font(o->labelfont(), o->labelsize());
- y = fl_height() + o->labelsize() - 6;
- }
const char *type_name() FL_OVERRIDE {return tabs_type_name;}
const char *alt_type_name() FL_OVERRIDE {return "fltk::TabGroup";}
Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {
@@ -152,6 +147,7 @@ public:
void remove_child(Fl_Type*) FL_OVERRIDE;
int pixmapID() FL_OVERRIDE { return 13; }
Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE;
+ int is_tabs() const FL_OVERRIDE {return 1;}
};
// ---- Fl_Scroll_Type ------------------------------------------------- MARK: -
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
index 2f89c9572..604b9f9fd 100644
--- a/fluid/Fl_Menu_Type.cxx
+++ b/fluid/Fl_Menu_Type.cxx
@@ -164,7 +164,8 @@ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) {
}
if (!o) {
o = new Fl_Button(0,0,100,20); // create template widget
- o->labelsize(Fl_Widget_Type::default_size);
+ o->labelsize(layout->labelsize);
+ o->labelfont(layout->labelfont);
}
Fl_Menu_Item_Type* t = submenuflag ? new Fl_Submenu_Type() : new Fl_Menu_Item_Type();
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index c3b1cbbf4..9ca23a7af 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -34,6 +34,7 @@ copied or otherwise examined.
#include "Fl_Type.h"
#include "fluid.h"
+#include "Fd_Snap_Action.h"
#include "Fl_Function_Type.h"
#include "Fl_Widget_Type.h"
#include "Fl_Window_Type.h"
@@ -193,6 +194,8 @@ void delete_all(int selected_only) {
shell_settings_write();
widget_browser->hposition(0);
widget_browser->vposition(0);
+ g_layout_list.remove_all(FD_STORE_PROJECT);
+ g_layout_list.update_dialogs();
}
selection_changed(0);
widget_browser->redraw();
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
index d52ffa5f7..763a29d26 100644
--- a/fluid/Fl_Type.h
+++ b/fluid/Fl_Type.h
@@ -160,6 +160,7 @@ public:
virtual int is_menu_item() const {return 0;}
virtual int is_menu_button() const {return 0;}
virtual int is_group() const {return 0;}
+ virtual int is_tabs() const {return 0;}
virtual int is_flex() const {return 0;}
virtual int is_window() const {return 0;}
virtual int is_code() const {return 0;}
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
index 3fb265975..dad196b4f 100644
--- a/fluid/Fl_Widget_Type.cxx
+++ b/fluid/Fl_Widget_Type.cxx
@@ -1,7 +1,7 @@
//
// Widget type code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2021 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -49,8 +49,6 @@
// instance, sets the widget pointers, and makes all the display
// update correctly...
-int Fl_Widget_Type::default_size = FL_NORMAL_SIZE;
-
int Fl_Widget_Type::is_widget() const {return 1;}
int Fl_Widget_Type::is_public() const {return public_;}
@@ -82,17 +80,6 @@ Fl_Widget_Type::ideal_size(int &w, int &h) {
if (h < 15) h = 15;
}
-// Return the ideal widget spacing...
-void
-Fl_Widget_Type::ideal_spacing(int &x, int &y) {
- if (o->labelsize() < 10)
- x = y = 0;
- else if (o->labelsize() < 14)
- x = y = 5;
- else
- x = y = 10;
-}
-
/**
Make a new Widget node.
\param[in] strategy is kAddAsLastChild or kAddAfterCurrent
@@ -146,16 +133,6 @@ Fl_Type *Fl_Widget_Type::make(Strategy strategy) {
W = H = B;
}
- // satisfy the grid requirements (otherwise it edits really strangely):
- if (gridx>1) {
- X = (X/gridx)*gridx;
- W = ((W-1)/gridx+1)*gridx;
- }
- if (gridy>1) {
- Y = (Y/gridy)*gridy;
- H = ((H-1)/gridy+1)*gridy;
- }
-
// Construct the Fl_Type:
Fl_Widget_Type *t = _make();
if (!o) o = widget(0,0,100,100); // create template widget
@@ -1366,6 +1343,7 @@ void labelfont_cb(Fl_Choice* i, void *v) {
} else {
int mod = 0;
int n = i->value();
+ if (n <= 0) n = layout->labelfont;
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
@@ -1385,7 +1363,7 @@ void labelsize_cb(Fl_Value_Input* i, void *v) {
} else {
int mod = 0;
n = int(i->value());
- if (n <= 0) n = Fl_Widget_Type::default_size;
+ if (n <= 0) n = layout->labelsize;
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
@@ -1842,6 +1820,7 @@ void textfont_cb(Fl_Choice* i, void* v) {
} else {
int mod = 0;
n = (Fl_Font)i->value();
+ if (n <= 0) n = layout->textfont;
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
@@ -1862,7 +1841,7 @@ void textsize_cb(Fl_Value_Input* i, void* v) {
} else {
int mod = 0;
s = int(i->value());
- if (s <= 0) s = Fl_Widget_Type::default_size;
+ if (s <= 0) s = layout->textsize;
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
@@ -2635,11 +2614,33 @@ static void load_panel() {
the_panel->hide();
}
+extern Fl_Window *widgetbin_panel;
+
// This is called when user double-clicks an item, open or update the panel:
void Fl_Widget_Type::open() {
- if (!the_panel) the_panel = make_widget_panel();
+ bool adjust_position = false;
+ if (!the_panel) {
+ the_panel = make_widget_panel();
+ adjust_position = true;
+ }
load_panel();
- if (numselected) the_panel->show();
+ if (numselected) {
+ the_panel->show();
+ if (adjust_position) {
+ if (widgetbin_panel && widgetbin_panel->visible()) {
+ if ( (the_panel->x()+the_panel->w() > widgetbin_panel->x())
+ && (the_panel->x() < widgetbin_panel->x()+widgetbin_panel->w())
+ && (the_panel->y()+the_panel->h() > widgetbin_panel->y())
+ && (the_panel->y() < widgetbin_panel->y()+widgetbin_panel->h()) )
+ {
+ if (widgetbin_panel->y()+widgetbin_panel->h()+the_panel->h() > Fl::h())
+ the_panel->position(the_panel->x(), widgetbin_panel->y()-the_panel->h()-30);
+ else
+ the_panel->position(the_panel->x(), widgetbin_panel->y()+widgetbin_panel->h()+30);
+ }
+ }
+ }
+ }
}
extern void redraw_overlays();
diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h
index a7bc0f798..b41ba0e53 100644
--- a/fluid/Fl_Widget_Type.h
+++ b/fluid/Fl_Widget_Type.h
@@ -61,8 +61,6 @@ protected:
Fl_Widget *live_widget;
public:
- static int default_size;
-
const char *xclass; // junk string, used for shortcut
Fl_Widget *o;
int public_;
@@ -111,7 +109,6 @@ public:
void copy_properties() FL_OVERRIDE;
virtual void ideal_size(int &w, int &h);
- virtual void ideal_spacing(int &x, int &y);
~Fl_Widget_Type();
void redraw();
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index 78c66cbde..570af58e2 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -1,11 +1,11 @@
//
-// Window type code for the Fast Light Tool Kit (FLTK).
+// Window type code file for the Fast Light Tool Kit (FLTK).
//
// The widget describing an Fl_Window. This is also all the code
// for interacting with the overlay, which allows the user to
// select, move, and resize the children widgets.
//
-// Copyright 1998-2018 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -29,6 +29,7 @@
#include "code.h"
#include "widget_panel.h"
#include "factory.h"
+#include "Fd_Snap_Action.h"
#include <FL/Fl.H>
#include <FL/Fl_Overlay_Window.H>
@@ -46,8 +47,6 @@
extern Fl_Preferences fluid_prefs;
-inline int fl_min(int a, int b) { return (a < b ? a : b); }
-
// Update the XYWH values in the widget panel...
static void update_xywh() {
if (current_widget && current_widget->is_widget()) {
@@ -63,58 +62,6 @@ static void update_xywh() {
}
}
-void guides_cb(Fl_Check_Button *i, long) {
- show_guides = i->value();
- fluid_prefs.set("show_guides", show_guides);
-
- for (Fl_Type *p = Fl_Type::first; p; p = p->next) {
- if (p->is_window()) {
- Fl_Window_Type *w = (Fl_Window_Type *)p;
- ((Fl_Overlay_Window *)(w->o))->redraw_overlay();
- }
- }
-}
-
-void grid_cb(Fl_Int_Input *i, long v) {
- int n = atoi(i->value());
- if (n < 0) n = 0;
- switch (v) {
- case 1:
- gridx = n;
- fluid_prefs.set("gridx", n);
- break;
- case 2:
- gridy = n;
- fluid_prefs.set("gridy", n);
- break;
- case 3:
- snap = n;
- fluid_prefs.set("snap", n);
- break;
- }
-
- // Next go through all of the windows in the project and set the
- // stepping for resizes...
- Fl_Type *p;
- Fl_Window_Type *w;
-
- for (p = Fl_Type::first; p; p = p->next) {
- if (p->is_window()) {
- w = (Fl_Window_Type *)p;
- ((Fl_Window *)(w->o))->size_range(gridx, gridy, Fl::w(), Fl::h());
- }
- }
-}
-
-// Set default widget sizes...
-void default_widget_size_cb(Fl_Round_Button *b, long size) {
- // Update the "normal" text size of new widgets...
- b->setonly();
- Fl_Widget_Type::default_size = (int)size;
- fluid_prefs.set("widget_size", Fl_Widget_Type::default_size);
-}
-
-
void i18n_type_cb(Fl_Choice *c, void *) {
undo_checkpoint();
@@ -236,18 +183,6 @@ void show_project_cb(Fl_Widget *, void *) {
}
void show_grid_cb(Fl_Widget *, void *) {
- char buf[128];
- sprintf(buf,"%d",gridx); horizontal_input->value(buf);
- sprintf(buf,"%d",gridy); vertical_input->value(buf);
- sprintf(buf,"%d",snap); snap_input->value(buf);
- guides_toggle->value(show_guides);
- int s = Fl_Widget_Type::default_size;
- if (s<=8) def_widget_size[0]->setonly();
- else if (s<=11) def_widget_size[1]->setonly();
- else if (s<=14) def_widget_size[2]->setonly();
- else if (s<=18) def_widget_size[3]->setonly();
- else if (s<=24) def_widget_size[4]->setonly();
- else if (s<=32) def_widget_size[5]->setonly();
grid_window->hotspot(grid_window);
grid_window->show();
}
@@ -262,6 +197,7 @@ void header_input_cb(Fl_Input* i, void*) {
set_modflag(1);
g_project.header_file_name = i->value();
}
+
void code_input_cb(Fl_Input* i, void*) {
if (strcmp(g_project.code_file_name.c_str(), i->value()))
set_modflag(1);
@@ -370,6 +306,7 @@ uchar *Overlay_Window::read_image(int &ww, int &hh) {
void Overlay_Window::draw_overlay() {
window->draw_overlay();
}
+
int Overlay_Window::handle(int e) {
int ret = window->handle(e);
if (ret==0) {
@@ -383,7 +320,7 @@ int Overlay_Window::handle(int e) {
}
/**
- Make and add a new WIndow node.
+ Make and add a new Window node.
\param[in] strategy is kAddAsLastChild or kAddAfterCurrent
\return new node
*/
@@ -399,9 +336,6 @@ Fl_Type *Fl_Window_Type::make(Strategy strategy) {
this->o = new Fl_Window(100,100);
Fl_Group::current(0);
}
- // Set the size ranges for this window; in order to avoid opening the
- // X display we use an arbitrary maximum size...
- ((Fl_Window *)(this->o))->size_range(gridx, gridy, 6144, 4096);
myo->factory = this;
myo->drag = 0;
myo->numselected = 0;
@@ -451,9 +385,7 @@ void Fl_Window_Type::open() {
w->show();
w->resizable(p);
}
-
w->image(Fl::scheme_bg_);
- w->size_range(gridx, gridy, Fl::w(), Fl::h());
}
// Read an image of the window
@@ -564,42 +496,33 @@ void Overlay_Window::resize(int X,int Y,int W,int H) {
// nearest multiple of gridsize, and snap to original position
void Fl_Window_Type::newdx() {
int mydx, mydy;
- if (Fl::event_state(FL_ALT) || !snap) {
- mydx = mx-x1;
- mydy = my-y1;
+ mydx = mx-x1;
+ mydy = my-y1;
- if (abs(mydx) < 2 && abs(mydy) < 2) mydx = mydy = 0;
- } else {
- int dx0 = mx-x1;
- int ix = (drag&RIGHT) ? br : bx;
- mydx = gridx ? ((ix+dx0+gridx/2)/gridx)*gridx - ix : dx0;
- if (dx0 > snap) {
- if (mydx < 0) mydx = 0;
- } else if (dx0 < -snap) {
- if (mydx > 0) mydx = 0;
- } else
- mydx = 0;
- int dy0 = my-y1;
- int iy = (drag&BOTTOM) ? by : bt;
- mydy = gridy ? ((iy+dy0+gridy/2)/gridy)*gridy - iy : dy0;
- if (dy0 > snap) {
- if (mydy < 0) mydy = 0;
- } else if (dy0 < -snap) {
- if (mydy > 0) mydy = 0;
- } else
- mydy = 0;
- }
-
- if (!(drag & (DRAG | BOX | LEFT | RIGHT))) {
+ if (!(drag & (FD_DRAG | FD_BOX | FD_LEFT | FD_RIGHT))) {
mydx = 0;
dx = 0;
}
- if (!(drag & (DRAG | BOX | TOP | BOTTOM))) {
+ if (!(drag & (FD_DRAG | FD_BOX | FD_TOP | FD_BOTTOM))) {
mydy = 0;
dy = 0;
}
+ if (show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) {
+ Fl_Type *selection = 0L; // special power for the first selected widget
+ for (Fl_Type *q=next; q && q->level>level; q = q->next) {
+ if (q->selected && q->is_widget() && !q->is_menu_item()) {
+ selection = q;
+ break;
+ }
+ }
+ Fd_Snap_Data data = { mydx, mydy, bx, by, br, bt, drag, 4, 4, mydx, mydy, (Fl_Widget_Type*)selection, this };
+ Fd_Snap_Action::check_all(data);
+ if (data.x_dist < 4) mydx = data.dx_out;
+ if (data.y_dist < 4) mydy = data.dy_out;
+ }
+
if (dx != mydx || dy != mydy) {
dx = mydx; dy = mydy;
((Overlay_Window *)o)->redraw_overlay();
@@ -613,34 +536,34 @@ void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T
R = X+myo->o->w();
T = Y+myo->o->h();
if (!drag) return;
- if (drag&DRAG) {
+ if (drag&FD_DRAG) {
X += dx;
Y += dy;
R += dx;
T += dy;
} else {
- if (drag&LEFT) {
+ if (drag&FD_LEFT) {
if (X==bx) {
X += dx;
} else {
if (X<bx+dx) X = bx+dx;
}
}
- if (drag&TOP) {
+ if (drag&FD_TOP) {
if (Y==by) {
Y += dy;
} else {
if (Y<by+dy) Y = by+dy;
}
}
- if (drag&RIGHT) {
+ if (drag&FD_RIGHT) {
if (R==br) {
R += dx;
} else {
if (R>br+dx) R = br+dx;
}
}
- if (drag&BOTTOM) {
+ if (drag&FD_BOTTOM) {
if (T==bt) {
T += dy;
} else {
@@ -652,118 +575,6 @@ void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T
if (T<Y) {int n = Y; Y = T; T = n;}
}
-// draw a vertical arrow pointing toward y2
-static void draw_v_arrow(int x, int y1, int y2) {
- int dy = (y1>y2) ? -1 : 1 ;
- fl_yxline(x, y1, y2);
- fl_xyline(x-4, y2, x+4);
- fl_line(x-2, y2-dy*5, x, y2-dy);
- fl_line(x+2, y2-dy*5, x, y2-dy);
-}
-
-static void draw_h_arrow(int x1, int y, int x2) {
- int dx = (x1>x2) ? -1 : 1 ;
- fl_xyline(x1, y, x2);
- fl_yxline(x2, y-4, y+4);
- fl_line(x2-dx*5, y-2, x2-dx, y);
- fl_line(x2-dx*5, y+2, x2-dx, y);
-}
-
-static void draw_top_brace(const Fl_Widget *w) {
- fl_yxline(w->x(), w->y()-2, w->y()+6);
- fl_yxline(w->x()+w->w()-1, w->y()-2, w->y()+6);
- fl_xyline(w->x()-2, w->y(), w->x()+w->w()+1);
-}
-
-static void draw_left_brace(const Fl_Widget *w) {
- fl_xyline(w->x()-2, w->y(), w->x()+6);
- fl_xyline(w->x()-2, w->y()+w->h()-1, w->x()+6);
- fl_yxline(w->x(), w->y()-2, w->y()+w->h()+1);
-}
-
-static void draw_right_brace(const Fl_Widget *w) {
- int xx = w->x() + w->w() - 1;
- fl_xyline(xx-6, w->y(), xx+2);
- fl_xyline(xx-6, w->y()+w->h()-1, xx+2);
- fl_yxline(xx, w->y()-2, w->y()+w->h()+1);
-}
-
-static void draw_bottom_brace(const Fl_Widget *w) {
- int yy = w->y() + w->h() - 1;
- fl_yxline(w->x(), yy-6, yy+2);
- fl_yxline(w->x()+w->w()-1, yy-6, yy+2);
- fl_xyline(w->x()-2, yy, w->x()+w->w()+1);
-}
-
-static void draw_height(int x, int y, int b, Fl_Align a) {
- char buf[16];
- int h = b - y;
- sprintf(buf, "%d", h);
- fl_font(FL_HELVETICA, 9);
- int lw = (int)fl_width(buf);
- int lx;
-
- b --;
- if (h < 30) {
- // Move height to the side...
- if (a == FL_ALIGN_LEFT) lx = x - lw - 2;
- else lx = x + 2;
-
- fl_yxline(x, y, b);
- } else {
- // Put height inside the arrows...
- lx = x - lw / 2;
-
- fl_yxline(x, y, y + (h - 11) / 2);
- fl_yxline(x, y + (h + 11) / 2, b);
- }
-
- // Draw the height...
- fl_draw(buf, lx, y + (h + 9) / 2);
-
- // Draw the arrowheads...
- fl_line(x-2, y+5, x, y+1, x+2, y+5);
- fl_line(x-2, b-5, x, b-1, x+2, b-5);
-
- // Draw the end lines...
- fl_xyline(x - 4, y, x + 4);
- fl_xyline(x - 4, b, x + 4);
-}
-
-static void draw_width(int x, int y, int r, Fl_Align a) {
- char buf[16];
- int w = r-x;
- sprintf(buf, "%d", w);
- fl_font(FL_HELVETICA, 9);
- int lw = (int)fl_width(buf);
- int ly = y + 4;
-
- r --;
-
- if (lw > (w - 20)) {
- // Move width above/below the arrows...
- if (a == FL_ALIGN_TOP) ly -= 10;
- else ly += 10;
-
- fl_xyline(x, y, r);
- } else {
- // Put width inside the arrows...
- fl_xyline(x, y, x + (w - lw - 2) / 2);
- fl_xyline(x + (w + lw + 2) / 2, y, r);
- }
-
- // Draw the width...
- fl_draw(buf, x + (w - lw) / 2, ly);
-
- // Draw the arrowheads...
- fl_line(x+5, y-2, x+1, y, x+5, y+2);
- fl_line(r-5, y-2, r-1, y, r-5, y+2);
-
- // Draw the end lines...
- fl_yxline(x, y - 4, y + 4);
- fl_yxline(r, y - 4, y + 4);
-}
-
void Fl_Window_Type::draw_overlay() {
if (recalc) {
bx = o->w(); by = o->h(); br = 0; bt = 0;
@@ -781,7 +592,7 @@ void Fl_Window_Type::draw_overlay() {
sx = bx; sy = by; sr = br; st = bt;
}
fl_color(FL_RED);
- if (drag==BOX && (x1 != mx || y1 != my)) {
+ if (drag==FD_BOX && (x1 != mx || y1 != my)) {
int x = x1; int r = mx; if (x > r) {x = mx; r = x1;}
int y = y1; int b = my; if (y > b) {y = my; b = y1;}
fl_rect(x,y,r-x,b-y);
@@ -792,10 +603,10 @@ void Fl_Window_Type::draw_overlay() {
int mybx,myby,mybr,mybt;
int mysx,mysy,mysr,myst;
mybx = mysx = o->w(); myby = mysy = o->h(); mybr = mysr = 0; mybt = myst = 0;
- Fl_Type *selection = 0L; // used to store the one selected widget (if n==1)
+ Fl_Type *selection = 0L; // special power for the first selected widget
for (Fl_Type *q=next; q && q->level>level; q = q->next)
if (q->selected && q->is_widget() && !q->is_menu_item()) {
- selection = q;
+ if (!selection) selection = q;
Fl_Widget_Type* myo = (Fl_Widget_Type*)q;
int x,y,r,t;
newposition(myo,x,y,r,t);
@@ -843,293 +654,6 @@ void Fl_Window_Type::draw_overlay() {
}
if (selected) return;
- if (show_guides && drag) {
- // draw overlays for UI Guideline distances
- // - check for distance to the window edge
- // * FLTK suggests 10 pixels from the edge
- int d;
- int xsp, ysp;
- int mybx_bak = mybx, myby_bak = myby, mybr_bak = mybr, mybt_bak = mybt;
- Fl_Widget_Type *mysel = (Fl_Widget_Type *)selection;
-
-
- ideal_spacing(xsp, ysp);
-
- if (drag) {
- // Check top spacing...
- if (abs(d = myby - ysp) < 3) {
- dy -= d;
- if (drag & DRAG) mybt -= d;
- myby -= d;
- draw_v_arrow(mybx+5, myby, 0);
- }
-
- // Check bottom spacing...
- if (abs(d = o->h() - mybt - ysp) < 3) {
- dy += d;
- if (drag & DRAG) myby += d;
- mybt += d;
- draw_v_arrow(mybx+5, mybt, o->h());
- }
-
- // Check left spacing...
- if (abs(d = mybx - xsp) < 3) {
- dx -= d;
- if (drag & DRAG) mybr -= d;
- mybx -= d;
- draw_h_arrow(mybx, myby+5, 0);
- }
-
- // Check right spacing...
- if (abs(d = o->w() - mybr - xsp) < 3) {
- dx += d;
- if (drag & DRAG) mybx += d;
- mybr += d;
- draw_h_arrow(mybr, myby+5, o->w());
- }
- }
-
- if (numselected==1 && selection && !(drag & DRAG)) {
- // Check ideal sizes
- int x,y,r,t;
- newposition(mysel,x,y,r,t);
- int w = r-x;
- int h = t-y;
- int iw = w, ih = h;
-
- mysel->ideal_size(iw, ih);
-
- if (drag & (TOP | BOTTOM)) {
- // Check height
- if (abs(d = ih - h) < 5) {
- // Resize height
- if (drag & TOP) {
- myby -= d;
- y -= d;
- dy -= d;
- } else {
- mybt += d;
- t += d;
- dy += d;
- }
- }
-
- // Draw height guide
- draw_height(x < 50 ? x+10 : x-10, y, t,
- x < 50 ? FL_ALIGN_RIGHT : FL_ALIGN_LEFT);
- }
-
- if (drag & (LEFT | RIGHT)) {
- // Check width
- if (abs(d = iw - w) < 5) {
- // Resize width
- if (drag & LEFT) {
- mybx -= d;
- x -= d;
- dx -= d;
- } else {
- mybr += d;
- r += d;
- dx += d;
- }
- }
-
- // Draw width guide
- draw_width(x, y < 50 ? y+10 : y-10, r,
- y < 50 ? FL_ALIGN_BOTTOM : FL_ALIGN_TOP);
- }
- }
-
- // Check spacing and alignment between individual widgets
- if (drag && selection && selection->is_widget()) {
- for (Fl_Type *q=next; q && q->level>level; q = q->next)
- if (q != selection && q->is_widget()) {
- Fl_Widget_Type *qw = (Fl_Widget_Type*)q;
- // Only check visible widgets...
- if (!qw->o->visible_r()) continue;
-
- // Get bounding box of widget...
- int qx = qw->o->x();
- int qr = qw->o->x() + qw->o->w();
- int qy = qw->o->y();
- int qt = qw->o->y() + qw->o->h();
-
- if (!(qw->o->align() & FL_ALIGN_INSIDE)) {
- // Adjust top/bottom for top/bottom labels...
- int ww, hh;
- ww = qw->o->w();
- hh = qw->o->labelsize();
- qw->o->measure_label(ww, hh);
- if (qw->o->align() & FL_ALIGN_TOP) qy -= hh;
- if (qw->o->align() & FL_ALIGN_BOTTOM) qt += hh;
- }
-
- // Do horizontal alignment when the widget is within 25
- // pixels vertically...
- if (fl_min(abs(qy - mysel->o->y() - mysel->o->h()),
- abs(mysel->o->y() - qt)) < 25) {
- // Align to left of other widget...
- if ((drag & (LEFT | DRAG)) && abs(d = mybx - qx) < 3) {
- dx += d;
- mybx += d;
- if (drag & DRAG) mybr += d;
-
- draw_left_brace(qw->o);
- }
-
- // Align to right of other widget...
- if ((drag & (RIGHT | DRAG)) &&
- abs(d = qr - mybr) < 3) {
- dx += d;
- if (drag & DRAG) mybx += d;
- mybr += d;
-
- draw_right_brace(qw->o);
- }
- }
-
- // Align to top of other widget...
- if ((drag & (TOP | DRAG)) && abs(d = myby - qy) < 3) {
- dy += d;
- myby += d;
- if (drag & DRAG) mybt += d;
-
- draw_top_brace(qw->o);
- }
-
- // Align to bottom of other widget...
- if ((drag & (BOTTOM | DRAG)) && abs(d = qt - mybt) < 3) {
- dy += d;
- if (drag & DRAG) myby += d;
- mybt += d;
-
- draw_bottom_brace(qw->o);
- }
-
- // Check spacing between widgets
- if (mysel->is_group()) mysel->ideal_spacing(xsp, ysp);
- else qw->ideal_spacing(xsp, ysp);
-
- if ((qt)>=myby && qy<=mybt) {
- if (drag & (LEFT | DRAG)) {
- // Compare left of selected to left of current
- if (abs(d = qx - mybx - xsp) >= 3)
- d = qx - mybx + xsp;
-
- if (abs(d) < 3) {
- dx += d;
- mybx += d;
- if (drag & DRAG) mybr += d;
-
- // Draw left arrow
- draw_h_arrow(mybx, (myby+mybt)/2, qx);
- }
-
- // Compare left of selected to right of current
- if (abs(d = qr - mybx - xsp) >= 3)
- d = qr - mybx + xsp;
-
- if (abs(d) < 3) {
- dx += d;
- mybx += d;
- if (drag & DRAG) mybr += d;
-
- // Draw left arrow
- draw_h_arrow(mybx, (myby+mybt)/2, qr);
- }
- }
-
- if (drag & (RIGHT | DRAG)) {
- // Compare right of selected to left of current
- if (abs(d = qx - mybr - xsp) >= 3)
- d = qx - mybr + xsp;
-
- if (abs(d) < 3) {
- dx += d;
- if (drag & DRAG) mybx += d;
- mybr += d;
-
- // Draw right arrow
- draw_h_arrow(mybr, (myby+mybt)/2, qx);
- }
-
- // Compare right of selected to right of current
- if (abs(d = qr - mybr + xsp) >= 3)
- d = qr - mybr - xsp;
-
- if (abs(d) < 3) {
- dx += d;
- if (drag & DRAG) mybx += d;
- mybr += d;
-
- // Draw right arrow
- draw_h_arrow(mybr, (myby+mybt)/2, qr);
- }
- }
- }
-
- if (qr>=mybx && qx<=mybr) {
- // Compare top of selected to top of current
- if (drag & (TOP | DRAG)) {
- if (abs(d = qy - myby - ysp) >= 3)
- d = qy - myby + ysp;
-
- if (abs(d) < 3) {
- dy += d;
- myby += d;
- if (drag & DRAG) mybt += d;
-
- // Draw up arrow...
- draw_v_arrow((mybx+mybr)/2, myby, qy);
- }
-
- // Compare top of selected to bottom of current
- if (abs(d = qt - myby - ysp) >= 3)
- d = qt - myby + ysp;
-
- if (abs(d) < 3) {
- dy += d;
- myby += d;
- if (drag & DRAG) mybt += d;
-
- // Draw up arrow...
- draw_v_arrow((mybx+mybr)/2, myby, qt);
- }
- }
-
- // Compare bottom of selected to top of current
- if (drag & (BOTTOM | DRAG)) {
- if (abs(d = qy - mybt - ysp) >= 3)
- d = qy - mybt + ysp;
-
- if (abs(d) < 3) {
- dy += d;
- if (drag & DRAG) myby += d;
- mybt += d;
-
- // Draw down arrow...
- draw_v_arrow((mybx+mybr)/2, mybt, qy);
- }
-
- // Compare bottom of selected to bottom of current
- if (abs(d = qt - mybt - ysp) >= 3)
- d = qt - mybt + ysp;
-
- if (abs(d) < 3) {
- dy += d;
- if (drag & DRAG) myby += d;
- mybt += d;
-
- // Draw down arrow...
- draw_v_arrow((mybx+mybr)/2, mybt, qt);
- }
- }
- }
- }
- }
- mysx += mybx-mybx_bak; mysr += mybr-mybr_bak;
- mysy += myby-myby_bak; myst += mybt-mybt_bak;
- }
// align the snapping selection box with the box we draw.
sx = mysx; sy = mysy; sr = mysr; st = myst;
@@ -1144,6 +668,11 @@ void Fl_Window_Type::draw_overlay() {
fl_rectf(mysr-5,mysy,5,5);
fl_rectf(mysr-5,myst-5,5,5);
fl_rectf(mysx,myst-5,5,5);
+
+ if (show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) {
+ Fd_Snap_Data data = { dx, dy, sx, sy, sr, st, drag, 4, 4, dx, dy, (Fl_Widget_Type*)selection, this};
+ Fd_Snap_Action::draw_all(data);
+ }
}
extern Fl_Menu_Item Main_Menu[];
@@ -1151,6 +680,7 @@ extern Fl_Menu_Item Main_Menu[];
// Calculate new bounding box of selected widgets:
void Fl_Window_Type::fix_overlay() {
overlay_item->label("Hide O&verlays");
+ if (overlay_button) overlay_button->label("Hide &Overlays");
overlays_invisible = 0;
recalc = 1;
((Overlay_Window *)(this->o))->redraw_overlay();
@@ -1181,10 +711,13 @@ void redraw_overlays() {
void toggle_overlays(Fl_Widget *,void *) {
overlays_invisible = !overlays_invisible;
- if (overlays_invisible)
+ if (overlays_invisible) {
overlay_item->label("Show O&verlays");
- else
+ if (overlay_button) overlay_button->label("Show &Overlays");
+ } else {
overlay_item->label("Hide O&verlays");
+ if (overlay_button) overlay_button->label("Hide &Overlays");
+ }
for (Fl_Type *o=Fl_Type::first; o; o=o->next)
if (o->is_window()) {
@@ -1193,6 +726,30 @@ void toggle_overlays(Fl_Widget *,void *) {
}
}
+void toggle_guides(Fl_Widget *,void *) {
+ show_guides = !show_guides;
+ fluid_prefs.set("show_guides", show_guides);
+
+ if (show_guides) {
+ guides_item->label("Hide Guides");
+ if (guides_button) guides_button->label("Hide &Guides");
+ } else {
+ guides_item->label("Show Guides");
+ if (guides_button) guides_button->label("Show &Guides");
+ }
+
+ for (Fl_Type *o=Fl_Type::first; o; o=o->next) {
+ if (o->is_window()) {
+ Fl_Widget_Type* w = (Fl_Widget_Type*)o;
+ ((Overlay_Window*)(w->o))->redraw_overlay();
+ }
+ }
+}
+
+void guides_cb(Fl_Button *o, void *v) {
+ toggle_guides(NULL, NULL);
+}
+
extern void select(Fl_Type *,int);
extern void select_only(Fl_Type *);
extern void deselect();
@@ -1402,15 +959,12 @@ int Fl_Window_Type::handle(int event) {
}}
// see if user grabs edges of selected region:
if (numselected && !(Fl::event_state(FL_SHIFT)) &&
- mx<=br+snap && mx>=bx-snap && my<=bt+snap && my>=by-snap) {
- int snap1 = snap>5 ? snap : 5;
- int w1 = (br-bx)/4; if (w1 > snap1) w1 = snap1;
- if (mx>=br-w1) drag |= RIGHT;
- else if (mx<bx+w1) drag |= LEFT;
- w1 = (bt-by)/4; if (w1 > snap1) w1 = snap1;
- if (my<=by+w1) drag |= TOP;
- else if (my>bt-w1) drag |= BOTTOM;
- if (!drag) drag = DRAG;
+ mx<=br+2 && mx>=bx-2 && my<=bt+2 && my>=by-2) {
+ if (mx >= br-5) drag |= FD_RIGHT;
+ else if (mx <= bx+5) drag |= FD_LEFT;
+ if (my >= bt-5) drag |= FD_BOTTOM;
+ else if (my <= by+5) drag |= FD_TOP;
+ if (!drag) drag = FD_DRAG;
}
// do object-specific selection of other objects:
{Fl_Type* t = selection->click_test(mx, my);
@@ -1427,7 +981,7 @@ int Fl_Window_Type::handle(int event) {
selection = t;
drag = 0;
} else {
- if (!drag) drag = BOX; // if all else fails, start a new selection region
+ if (!drag) drag = FD_BOX; // if all else fails, start a new selection region
}}
return 1;
@@ -1442,7 +996,7 @@ int Fl_Window_Type::handle(int event) {
if (!drag) return 0;
mx = Fl::event_x();
my = Fl::event_y();
- if (drag != BOX && (dx || dy || !Fl::event_is_click())) {
+ if (drag != FD_BOX && (dx || dy || !Fl::event_is_click())) {
if (dx || dy) moveallchildren();
} else if ((Fl::event_clicks() || Fl::event_state(FL_CTRL))) {
Fl_Widget_Type::open();
@@ -1510,8 +1064,16 @@ int Fl_Window_Type::handle(int event) {
case FL_Up: dx = 0; dy = -1; goto ARROW;
case FL_Down: dx = 0; dy = +1; goto ARROW;
ARROW:
- drag = (Fl::event_state(FL_SHIFT)) ? (RIGHT|BOTTOM) : DRAG;
- if (Fl::event_state(FL_COMMAND)) {dx *= gridx; dy *= gridy;}
+ drag = (Fl::event_state(FL_SHIFT)) ? (FD_RIGHT|FD_BOTTOM) : FD_DRAG;
+ if (Fl::event_state(FL_COMMAND)) {
+ int x_step, y_step;
+ if (drag & (FD_RIGHT|FD_BOTTOM))
+ Fd_Snap_Action::get_resize_stepsize(x_step, y_step);
+ else
+ Fd_Snap_Action::get_move_stepsize(x_step, y_step);
+ dx *= x_step;
+ dy *= y_step;
+ }
moveallchildren();
drag = 0;
return 1;
@@ -1642,9 +1204,6 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
this->o = new Fl_Window(100,100);
Fl_Group::current(0);
}
- // Set the size ranges for this window; in order to avoid opening the
- // X display we use an arbitrary maximum size...
- ((Fl_Window *)(this->o))->size_range(gridx, gridy, 6144, 4096);
myo->factory = this;
myo->drag = 0;
myo->numselected = 0;
diff --git a/fluid/Fl_Window_Type.h b/fluid/Fl_Window_Type.h
index 519af347b..8b6693245 100644
--- a/fluid/Fl_Window_Type.h
+++ b/fluid/Fl_Window_Type.h
@@ -5,7 +5,7 @@
// This should have the widget pointer in it, but it is still in the
// Fl_Type base class.
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -28,10 +28,20 @@ class Fl_Widget_Class_Type;
extern Fl_Menu_Item window_type_menu[];
extern Fl_Widget_Class_Type *current_widget_class;
void toggle_overlays(Fl_Widget *,void *);
+void toggle_guides(Fl_Widget *,void *);
void show_project_cb(Fl_Widget *, void *);
void show_grid_cb(Fl_Widget *, void *);
void show_settings_cb(Fl_Widget *, void *);
+enum {
+ FD_LEFT = 1, // user drags the left side of the selection box
+ FD_RIGHT = 2,
+ FD_BOTTOM = 4,
+ FD_TOP = 8,
+ FD_DRAG = 16, // user drags the entire selection
+ FD_BOX = 32 // user creates a new selection box
+};
+
class Fl_Window_Type : public Fl_Widget_Type {
protected:
@@ -45,7 +55,6 @@ protected:
int dx,dy;
int drag; // which parts of bbox are being moved
int numselected; // number of children selected
- enum {LEFT=1,RIGHT=2,BOTTOM=4,TOP=8,DRAG=16,BOX=32};
void draw_overlay();
void newdx();
void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h);
diff --git a/fluid/Makefile b/fluid/Makefile
index 3511b683e..a5569b70f 100644
--- a/fluid/Makefile
+++ b/fluid/Makefile
@@ -19,6 +19,7 @@ include ../makeinclude
CPPFILES = \
CodeEditor.cxx \
StyleParse.cxx \
+ Fd_Snap_Action.cxx \
Fl_Function_Type.cxx \
Fl_Group_Type.cxx \
Fl_Menu_Type.cxx \
diff --git a/fluid/align_widget.cxx b/fluid/align_widget.cxx
index d66a0cc70..20a85a394 100644
--- a/fluid/align_widget.cxx
+++ b/fluid/align_widget.cxx
@@ -477,31 +477,3 @@ void align_widget_cb(Fl_Widget*, long how)
if (changed)
set_modflag(1);
}
-
-
-// Set sizes of selected widgets...
-void widget_size_cb(Fl_Widget *, long size) {
- // Update any selected widgets...
- int changed = 0;
- for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
- if (o->selected && o->is_widget()) {
- if (!changed) {
- changed = 1;
- undo_checkpoint();
- }
-
- Fl_Widget *w = ((Fl_Widget_Type *)o)->o;
- w->labelsize((Fl_Font)size);
- Fl_Font f;
- int s = (int)size;
- Fl_Color c;
- ((Fl_Widget_Type *)o)->textstuff(2, f, s, c);
-
- w->redraw();
- // since this may be a major change, the whole window should be redrawn
- if (w->window()) w->window()->redraw();
- }
- }
- if (changed)
- set_modflag(1);
-}
diff --git a/fluid/align_widget.h b/fluid/align_widget.h
index 541894e94..f04372215 100644
--- a/fluid/align_widget.h
+++ b/fluid/align_widget.h
@@ -20,6 +20,5 @@
class Fl_Widget;
void align_widget_cb(Fl_Widget *, long);
-void widget_size_cb(Fl_Widget *, long);
#endif // _FLUID_ALIGN_WIDGET_H
diff --git a/fluid/alignment_panel.cxx b/fluid/alignment_panel.cxx
index c264dd035..edc2c3cc2 100644
--- a/fluid/alignment_panel.cxx
+++ b/fluid/alignment_panel.cxx
@@ -1,7 +1,7 @@
//
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -497,124 +497,681 @@ ings");
} // Fl_Double_Window* shell_run_window
return shell_run_window;
}
+Fl_Menu_Item *w_layout_menu_storage[4];
Fl_Double_Window *grid_window=(Fl_Double_Window *)0;
-Fl_Int_Input *horizontal_input=(Fl_Int_Input *)0;
+static void cb_grid_window(Fl_Double_Window* o, void* v) {
+ propagate_load(o, v);
+}
+
+Fl_Choice *layout_choice=(Fl_Choice *)0;
+
+static void cb_layout_choice(Fl_Choice* o, void* v) {
+ if (v == LOAD) {
+ o->value(g_layout_list.current_suite());
+ } else {
+ int index = o->value();
+ g_layout_list.current_suite(index);
+ g_layout_list.update_dialogs();
+ }
+}
+
+Fl_Menu_Item menu_layout_choice[] = {
+ {"FLTK", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"Grid", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {0,0,0,0,0,0,0,0,0}
+};
+
+static void cb_(Fl_Button*, void* v) {
+ // Clone the current layout suite
+
+ if (v == LOAD) return;
+
+ Fl_String old_name = "Copy of ";
+ old_name.append(g_layout_list[g_layout_list.current_suite()].name_);
+ const char *new_name = fl_input("Enter a name for the new layout:", old_name.c_str());
+ if (new_name == NULL)
+ return;
+
+ g_layout_list.add(new_name);
+ g_layout_list.update_dialogs();
+}
+
+Fl_Menu_Button *w_layout_menu=(Fl_Menu_Button *)0;
+
+static void cb_w_layout_menu(Fl_Menu_Button*, void* v) {
+ if (v == LOAD) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ if (suite.storage_ == FD_STORE_INTERNAL) {
+ w_layout_menu_rename->deactivate();
+ for (int i=1; i<4; i++) w_layout_menu_storage[i]->deactivate();
+ w_layout_menu_delete->deactivate();
+ } else {
+ w_layout_menu_rename->activate();
+ for (int i=1; i<4; i++) w_layout_menu_storage[i]->activate();
+ w_layout_menu_delete->activate();
+ }
+ w_layout_menu_storage[suite.storage_]->setonly();
+ }
+}
+
+static void cb_w_layout_menu_rename(Fl_Menu_*, void*) {
+ // Rename the current layout suite
+
+ Fl_String old_name = g_layout_list[g_layout_list.current_suite()].name_;
+ const char *new_name = fl_input("Enter a new name for the layout:", old_name.c_str());
+ if (new_name == NULL)
+ return;
+
+ g_layout_list.rename(new_name);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_storage(Fl_Menu_*, void*) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ suite.storage(FD_STORE_INTERNAL);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_storage1(Fl_Menu_*, void*) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ suite.storage(FD_STORE_USER);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_storage2(Fl_Menu_*, void*) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ suite.storage(FD_STORE_PROJECT);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_storage3(Fl_Menu_*, void*) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ suite.storage(FD_STORE_FILE);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_load(Fl_Menu_*, void*) {
+ // Give the user a file chooser and load that file
+ Fl_Native_File_Chooser fnfc;
+ fnfc.title("Load Layout Settings:");
+ fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
+ fnfc.options(Fl_Native_File_Chooser::USE_FILTER_EXT);
+ fnfc.filter("FLUID Layouts\t*.fll\n");
+ if (fnfc.show() != 0) return;
+ const char *new_filename = fnfc.filename();
+ if (!new_filename) return;
+ g_layout_list.load(new_filename);
+ //g_layout_list.current_suite(n);
+ g_layout_list.update_dialogs();
+}
+
+static void cb_w_layout_menu_save(Fl_Menu_*, void*) {
+ // Give the user a file chooser with a suggested name
+ Fl_Native_File_Chooser fnfc;
+ fnfc.title("Save Layout Settings:");
+ fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+ fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT);
+ fnfc.filter("FLUID Layouts\t*.fll\n");
+ if (g_layout_list.filename_) {
+ char *fn = fl_strdup(g_layout_list.filename_);
+ char *name = (char*)fl_filename_name(g_layout_list.filename_);
+ if (name > fn) {
+ name[-1] = 0;
+ fnfc.directory(fn);
+ fnfc.preset_file(name);
+ ::free(fn);
+ } else if (name) {
+ fnfc.preset_file(name);
+ ::free(fn);
+ }
+ }
+ if (fnfc.show() != 0) return;
+ const char *new_filename = fnfc.filename();
+ if (!new_filename) return;
+ if (g_layout_list.filename_)
+ ::free(g_layout_list.filename_);
+ g_layout_list.filename_ = fl_strdup(new_filename);
+ g_layout_list.save(new_filename);
+}
+
+static void cb_w_layout_menu_delete(Fl_Menu_*, void*) {
+ // remove the current suite
+
+ g_layout_list.remove(g_layout_list.current_suite());
+ g_layout_list.update_dialogs();
+}
+
+Fl_Menu_Item menu_w_layout_menu[] = {
+ {"Rename...", 0, (Fl_Callback*)cb_w_layout_menu_rename, 0, 128, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"@fd_beaker FLUID Built-In", 0, (Fl_Callback*)cb_w_layout_menu_storage, 0, 9, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"@fd_user User Preference", 0, (Fl_Callback*)cb_w_layout_menu_storage1, 0, 8, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"@fd_project Store in .fl Project File", 0, (Fl_Callback*)cb_w_layout_menu_storage2, 0, 8, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"@fd_file Store in External File", 0, (Fl_Callback*)cb_w_layout_menu_storage3, 0, 136, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"Load...", 0, (Fl_Callback*)cb_w_layout_menu_load, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"Save...", 0, (Fl_Callback*)cb_w_layout_menu_save, 0, 128, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {"Delete", 0, (Fl_Callback*)cb_w_layout_menu_delete, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0},
+ {0,0,0,0,0,0,0,0,0}
+};
+
+Fl_Button *preset_choice[3]={(Fl_Button *)0};
+
+static void cb_Left(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->left_window_margin);
+ } else {
+ layout->left_window_margin = (int)o->value();
+ }
+}
+
+static void cb_Top(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->top_window_margin);
+ } else {
+ layout->top_window_margin = (int)o->value();
+ }
+}
+
+static void cb_Right(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->right_window_margin);
+ } else {
+ layout->right_window_margin = (int)o->value();
+ }
+}
+
+static void cb_Bottom(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->bottom_window_margin);
+ } else {
+ layout->bottom_window_margin = (int)o->value();
+ }
+}
+
+static void cb_Horizontal(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->window_grid_x);
+ } else {
+ layout->window_grid_x = (int)o->value();
+ }
+}
+
+static void cb_Vertical(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->window_grid_y);
+ } else {
+ layout->window_grid_y = (int)o->value();
+ }
+}
+
+static void cb_Left1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->left_group_margin);
+ } else {
+ layout->left_group_margin = (int)o->value();
+ }
+}
-Fl_Int_Input *vertical_input=(Fl_Int_Input *)0;
+static void cb_Top1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->top_group_margin);
+ } else {
+ layout->top_group_margin = (int)o->value();
+ }
+}
-Fl_Int_Input *snap_input=(Fl_Int_Input *)0;
+static void cb_Right1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->right_group_margin);
+ } else {
+ layout->right_group_margin = (int)o->value();
+ }
+}
+
+static void cb_Bottom1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->bottom_group_margin);
+ } else {
+ layout->bottom_group_margin = (int)o->value();
+ }
+}
-Fl_Check_Button *guides_toggle=(Fl_Check_Button *)0;
+static void cb_Horizontal1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->group_grid_x);
+ } else {
+ layout->group_grid_x = (int)o->value();
+ }
+}
-static void cb_Close2(Fl_Button*, void*) {
- grid_window->hide();
+static void cb_Vertical1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->group_grid_y);
+ } else {
+ layout->group_grid_y = (int)o->value();
+ }
}
-Fl_Round_Button *def_widget_size[6]={(Fl_Round_Button *)0};
+static void cb_Top2(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->top_tabs_margin);
+ } else {
+ layout->top_tabs_margin = (int)o->value();
+ }
+}
+
+static void cb_Bottom2(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->bottom_tabs_margin);
+ } else {
+ layout->bottom_tabs_margin = (int)o->value();
+ }
+}
+
+static void cb_Minimum(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_min_w);
+ } else {
+ layout->widget_min_w = (int)o->value();
+ }
+}
+
+static void cb_Increment(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_inc_w);
+ } else {
+ layout->widget_inc_w = (int)o->value();
+ }
+}
+
+static void cb_Gap(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_gap_x);
+ } else {
+ layout->widget_gap_x = (int)o->value();
+ }
+}
+
+static void cb_1(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_min_h);
+ } else {
+ layout->widget_min_h = (int)o->value();
+ }
+}
+
+static void cb_2(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_inc_h);
+ } else {
+ layout->widget_inc_h = (int)o->value();
+ }
+}
+
+static void cb_3(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value((double)layout->widget_gap_y);
+ } else {
+ layout->widget_gap_y = (int)o->value();
+ }
+}
+
+static void cb_4(Fl_Choice* o, void* v) {
+ if (v == LOAD) {
+ o->value(layout->labelfont);
+ } else {
+ layout->labelfont = (int)o->value();
+ }
+}
+
+static void cb_5(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value(layout->labelsize);
+ } else {
+ layout->labelsize = (int)o->value();
+ }
+}
+
+static void cb_6(Fl_Choice* o, void* v) {
+ if (v == LOAD) {
+ o->value(layout->textfont);
+ } else {
+ layout->textfont = (int)o->value();
+ }
+}
+
+static void cb_7(Fl_Value_Input* o, void* v) {
+ if (v == LOAD) {
+ o->value(layout->textsize);
+ } else {
+ layout->textsize = (int)o->value();
+ }
+}
+
+static void cb_Close2(Fl_Button*, void* v) {
+ if (v != LOAD) grid_window->hide();
+}
Fl_Double_Window* make_layout_window() {
- { grid_window = new Fl_Double_Window(310, 245, "Layout Settings");
- { Fl_Int_Input* o = horizontal_input = new Fl_Int_Input(116, 10, 50, 25, "x");
- horizontal_input->tooltip("Horizontal grid spacing.");
- horizontal_input->type(2);
- horizontal_input->box(FL_THIN_DOWN_BOX);
- horizontal_input->callback((Fl_Callback*)grid_cb, (void*)(1));
- horizontal_input->align(Fl_Align(FL_ALIGN_RIGHT));
- o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
- } // Fl_Int_Input* horizontal_input
- { Fl_Int_Input* o = vertical_input = new Fl_Int_Input(179, 10, 50, 25, "pixels");
- vertical_input->tooltip("Vertical grid spacing.");
- vertical_input->type(2);
- vertical_input->box(FL_THIN_DOWN_BOX);
- vertical_input->callback((Fl_Callback*)grid_cb, (void*)(2));
- vertical_input->align(Fl_Align(FL_ALIGN_RIGHT));
- o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
- } // Fl_Int_Input* vertical_input
- { Fl_Int_Input* o = snap_input = new Fl_Int_Input(116, 45, 50, 25, "pixel snap");
- snap_input->tooltip("Snap to grid within this many pixels.");
- snap_input->type(2);
- snap_input->box(FL_THIN_DOWN_BOX);
- snap_input->callback((Fl_Callback*)grid_cb, (void*)(3));
- snap_input->align(Fl_Align(FL_ALIGN_RIGHT));
- o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);
- } // Fl_Int_Input* snap_input
- { guides_toggle = new Fl_Check_Button(116, 80, 110, 25, "Show Guides");
- guides_toggle->tooltip("Show distance and alignment guides in overlay");
- guides_toggle->down_box(FL_DOWN_BOX);
- guides_toggle->callback((Fl_Callback*)guides_cb, (void*)(4));
- } // Fl_Check_Button* guides_toggle
- { Fl_Button* o = new Fl_Button(240, 210, 60, 25, "Close");
- o->tooltip("Close this dialog.");
- o->callback((Fl_Callback*)cb_Close2);
+ { grid_window = new Fl_Double_Window(320, 491, "Layout Settings");
+ grid_window->callback((Fl_Callback*)cb_grid_window);
+ { Fl_Box* o = new Fl_Box(10, 10, 60, 24, "Layout:");
+ o->labelfont(1);
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { layout_choice = new Fl_Choice(70, 10, 187, 24);
+ layout_choice->down_box(FL_BORDER_BOX);
+ layout_choice->callback((Fl_Callback*)cb_layout_choice);
+ layout_choice->menu(menu_layout_choice);
+ } // Fl_Choice* layout_choice
+ { Fl_Button* o = new Fl_Button(257, 10, 24, 24, "+");
+ o->callback((Fl_Callback*)cb_);
} // Fl_Button* o
- { Fl_Box* o = new Fl_Box(47, 10, 70, 25, "Grid:");
+ { w_layout_menu = new Fl_Menu_Button(281, 10, 24, 24);
+ w_layout_menu->callback((Fl_Callback*)cb_w_layout_menu);
+ w_layout_menu_storage[0] = &menu_w_layout_menu[1];
+ w_layout_menu_storage[1] = &menu_w_layout_menu[2];
+ w_layout_menu_storage[2] = &menu_w_layout_menu[3];
+ w_layout_menu_storage[3] = &menu_w_layout_menu[4];
+ w_layout_menu->menu(menu_w_layout_menu);
+ } // Fl_Menu_Button* w_layout_menu
+ { Fl_Box* o = new Fl_Box(10, 39, 60, 20, "Preset:");
o->labelfont(1);
+ o->labelsize(11);
o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
} // Fl_Box* o
- { Fl_Box* o = new Fl_Box(10, 115, 107, 25, "Widget Size:");
+ { Fl_Group* o = new Fl_Group(70, 39, 235, 20);
+ o->labelsize(11);
+ o->callback((Fl_Callback*)propagate_load);
+ { preset_choice[0] = new Fl_Button(70, 39, 78, 20, "Application");
+ preset_choice[0]->type(102);
+ preset_choice[0]->value(1);
+ preset_choice[0]->selection_color(FL_DARK2);
+ preset_choice[0]->labelsize(11);
+ preset_choice[0]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(0));
+ } // Fl_Button* preset_choice[0]
+ { preset_choice[1] = new Fl_Button(148, 39, 79, 20, "Dialog");
+ preset_choice[1]->type(102);
+ preset_choice[1]->selection_color(FL_DARK2);
+ preset_choice[1]->labelsize(11);
+ preset_choice[1]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(1));
+ } // Fl_Button* preset_choice[1]
+ { preset_choice[2] = new Fl_Button(227, 39, 78, 20, "Toolbox");
+ preset_choice[2]->type(102);
+ preset_choice[2]->selection_color(FL_DARK2);
+ preset_choice[2]->labelsize(11);
+ preset_choice[2]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(2));
+ } // Fl_Button* preset_choice[2]
+ o->end();
+ } // Fl_Group* o
+ { Fl_Box* o = new Fl_Box(70, 64, 235, 20, "---- Window ----");
o->labelfont(1);
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Box* o = new Fl_Box(10, 99, 60, 20, "Margin:");
+ o->labelsize(11);
o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
} // Fl_Box* o
- { Fl_Group* o = new Fl_Group(105, 115, 192, 75);
- { def_widget_size[0] = new Fl_Round_Button(115, 115, 70, 25);
- def_widget_size[0]->type(102);
- def_widget_size[0]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[0]->callback((Fl_Callback*)default_widget_size_cb, (void*)(8));
- } // Fl_Round_Button* def_widget_size[0]
- { Fl_Box* o = new Fl_Box(130, 115, 50, 25, "tiny");
- o->labelsize(8);
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
- { def_widget_size[1] = new Fl_Round_Button(202, 115, 70, 25);
- def_widget_size[1]->type(102);
- def_widget_size[1]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[1]->callback((Fl_Callback*)default_widget_size_cb, (void*)(11));
- } // Fl_Round_Button* def_widget_size[1]
- { Fl_Box* o = new Fl_Box(218, 115, 50, 25, "small");
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 99, 55, 20, "Left:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Left);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 99, 55, 20, "Top:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Top);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(190, 99, 55, 20, "Right:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Right);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(250, 99, 55, 20, "Bottom:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Bottom);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(17, 133, 53, 20, "Grid:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 133, 55, 20, "Horizontal:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Horizontal);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 133, 55, 20, "Vertical:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Vertical);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(70, 158, 235, 20, "---- Group ----");
+ o->labelfont(1);
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Box* o = new Fl_Box(10, 193, 60, 20, "Margin:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 193, 55, 20, "Left:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Left1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 193, 55, 20, "Top:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Top1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(190, 193, 55, 20, "Right:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Right1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(250, 193, 55, 20, "Bottom:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Bottom1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(17, 227, 53, 20, "Grid:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 227, 55, 20, "Horizontal:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Horizontal1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 227, 55, 20, "Vertical:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Vertical1);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(70, 252, 235, 20, "---- Tabs ----");
+ o->labelfont(1);
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Box* o = new Fl_Box(10, 287, 60, 20, "Margin:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 287, 55, 20, "Top:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Top2);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 287, 55, 20, "Bottom:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Bottom2);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(70, 312, 235, 20, "---- Widget ----");
+ o->labelfont(1);
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Box* o = new Fl_Box(10, 347, 60, 20, "Horizontal:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 346, 55, 20, "Minimum:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Minimum);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 346, 55, 20, "Increment:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Increment);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(190, 346, 55, 20, "Gap:");
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_Gap);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Box* o = new Fl_Box(17, 372, 53, 20, "Vertical:");
+ o->labelsize(11);
+ o->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ { Fl_Value_Input* o = new Fl_Value_Input(70, 372, 55, 20);
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_1);
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(130, 372, 55, 20);
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_2);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Value_Input* o = new Fl_Value_Input(190, 372, 55, 20);
+ o->labelsize(11);
+ o->maximum(32767);
+ o->step(1);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_3);
+ o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
+ } // Fl_Value_Input* o
+ { Fl_Group* o = new Fl_Group(70, 397, 200, 20, "Label Font:");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)propagate_load);
+ o->align(Fl_Align(FL_ALIGN_LEFT));
+ { Fl_Choice* o = new Fl_Choice(70, 397, 152, 20);
+ o->tooltip("The style of the label text.");
+ o->box(FL_THIN_UP_BOX);
+ o->down_box(FL_BORDER_BOX);
+ o->labelfont(1);
o->labelsize(11);
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
- { def_widget_size[2] = new Fl_Round_Button(115, 140, 70, 25);
- def_widget_size[2]->type(102);
- def_widget_size[2]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[2]->callback((Fl_Callback*)default_widget_size_cb, (void*)(14));
- } // Fl_Round_Button* def_widget_size[2]
- { Fl_Box* o = new Fl_Box(130, 140, 50, 25, "normal");
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
- { def_widget_size[3] = new Fl_Round_Button(202, 140, 90, 25);
- def_widget_size[3]->type(102);
- def_widget_size[3]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[3]->callback((Fl_Callback*)default_widget_size_cb, (void*)(18));
- } // Fl_Round_Button* def_widget_size[3]
- { Fl_Box* o = new Fl_Box(218, 140, 68, 25, "medium");
- o->labelsize(18);
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
- { def_widget_size[4] = new Fl_Round_Button(115, 165, 75, 25);
- def_widget_size[4]->type(102);
- def_widget_size[4]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[4]->callback((Fl_Callback*)default_widget_size_cb, (void*)(24));
- } // Fl_Round_Button* def_widget_size[4]
- { Fl_Box* o = new Fl_Box(130, 165, 64, 25, "large");
- o->labelsize(24);
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
- { def_widget_size[5] = new Fl_Round_Button(202, 165, 95, 25);
- def_widget_size[5]->type(102);
- def_widget_size[5]->down_box(FL_ROUND_DOWN_BOX);
- def_widget_size[5]->callback((Fl_Callback*)default_widget_size_cb, (void*)(32));
- } // Fl_Round_Button* def_widget_size[5]
- { Fl_Box* o = new Fl_Box(218, 165, 76, 25, "huge");
- o->labelsize(32);
- o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
- } // Fl_Box* o
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_4);
+ Fl_Group::current()->resizable(o);
+ o->menu(fontmenu);
+ } // Fl_Choice* o
+ { Fl_Value_Input* o = new Fl_Value_Input(221, 397, 49, 20);
+ o->tooltip("The size of the label text.");
+ o->labelsize(11);
+ o->maximum(100);
+ o->step(1);
+ o->value(14);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_5);
+ } // Fl_Value_Input* o
+ o->end();
+ } // Fl_Group* o
+ { Fl_Group* o = new Fl_Group(70, 422, 200, 20, "Text Font:");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)propagate_load);
+ o->align(Fl_Align(FL_ALIGN_LEFT));
+ { Fl_Choice* o = new Fl_Choice(70, 422, 152, 20);
+ o->tooltip("The value text style.");
+ o->box(FL_DOWN_BOX);
+ o->down_box(FL_BORDER_BOX);
+ o->labelfont(1);
+ o->labelsize(11);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_6);
+ Fl_Group::current()->resizable(o);
+ o->menu(fontmenu);
+ } // Fl_Choice* o
+ { Fl_Value_Input* o = new Fl_Value_Input(221, 422, 49, 20);
+ o->tooltip("The value text size.");
+ o->labelsize(11);
+ o->maximum(100);
+ o->step(1);
+ o->value(14);
+ o->textsize(11);
+ o->callback((Fl_Callback*)cb_7);
+ } // Fl_Value_Input* o
o->end();
} // Fl_Group* o
+ { Fl_Button* o = new Fl_Button(245, 456, 60, 25, "Close");
+ o->tooltip("Close this dialog.");
+ o->callback((Fl_Callback*)cb_Close2);
+ } // Fl_Button* o
grid_window->set_non_modal();
grid_window->end();
} // Fl_Double_Window* grid_window
+ grid_window->do_callback(grid_window, LOAD);
return grid_window;
}
diff --git a/fluid/alignment_panel.fl b/fluid/alignment_panel.fl
index c1f0305da..3f3abb04d 100644
--- a/fluid/alignment_panel.fl
+++ b/fluid/alignment_panel.fl
@@ -2,10 +2,39 @@
version 1.0400
header_name {.h}
code_name {.cxx}
+snap {
+ ver 1
+ current_suite {FLUID (based on FLTK)}
+ current_preset 1
+ suite {
+ name {FLUID (based on FLTK)}
+ preset { 1
+ 15 15 15 15 0 0
+ 10 10 10 10 0 0
+ 25 25
+ 20 10 4 20 4 8
+ 0 14 0 14
+ }
+ preset { 1
+ 10 10 10 10 0 0
+ 10 10 10 10 0 0
+ 20 20
+ 20 10 5 20 5 5
+ 0 11 0 11
+ }
+ preset { 1
+ 10 10 10 10 0 0
+ 10 10 10 10 0 0
+ 18 18
+ 16 8 2 16 4 2
+ 0 10 0 10
+ }
+ }
+}
comment {//
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -26,18 +55,24 @@ decl {\#include "fluid.h"} {public global
decl {\#include "widget_browser.h"} {public global
}
+decl {\#include "Fd_Snap_Action.h"} {public global
+}
+
decl {\#include "shell_command.h"} {public global
}
decl {\#include <FL/Fl_Text_Buffer.H>} {public local
}
-decl {\#include <FL/Fl_Text_Display.H>} {public local
+decl {\#include <FL/Fl_Text_Display.H>} {selected public local
}
decl {\#include <FL/filename.H>} {public local
}
+decl {\#include <FL/fl_string_functions.h>} {public local
+}
+
decl {\#include <FL/Fl_Scheme_Choice.H>} {public local
}
@@ -60,8 +95,8 @@ decl {extern struct Fl_Menu_Item *dbmanager_item;} {public local
Function {make_project_window()} {open
} {
Fl_Window project_window {
- label {Project Settings}
- xywh {472 246 399 298} type Double
+ label {Project Settings} open
+ xywh {739 251 399 298} type Double
code0 {\#include <FL/Fl_Preferences.H>}
code1 {\#include <FL/Fl_Tooltip.H>} modal visible
} {
@@ -126,15 +161,15 @@ set_modflag(-1, -1);}
} {
MenuItem {} {
label None
- xywh {0 0 100 20}
+ xywh {0 0 100 20} labelsize 14
}
MenuItem {} {
label {GNU gettext}
- xywh {0 0 100 20}
+ xywh {0 0 100 20} labelsize 14
}
MenuItem {} {
label {POSIX catgets}
- xywh {0 0 100 20}
+ xywh {0 0 100 20} labelsize 14
}
}
Fl_Input i18n_include_input {
@@ -182,7 +217,7 @@ Function {make_settings_window()} {open
} {
Fl_Window settings_window {
label {GUI Settings} open
- xywh {701 666 360 355} type Double resizable
+ xywh {722 580 360 355} type Double resizable
code0 {o->size_range(o->w(), o->h());} non_modal visible
} {
Fl_Choice scheme_choice {
@@ -293,7 +328,7 @@ Function {make_shell_window()} {open
} {
Fl_Window shell_window {
label {Shell Command} open
- xywh {502 196 375 208} type Double resizable modal size_range {375 208 1024 208} visible
+ xywh {390 202 375 208} type Double resizable modal size_range {375 208 1024 208} visible
} {
Fl_Group {} {open
xywh {0 0 375 165} resizable
@@ -323,7 +358,7 @@ if (g_shell_use_fl_settings) {
} else {
shell_prefs_get();
}
-update_shell_window();} selected
+update_shell_window();}
tooltip {check to read and write shell command from and to .fl files} xywh {82 110 180 19} down_box DOWN_BOX labelsize 12
}
Fl_Box {} {
@@ -390,109 +425,469 @@ shell_run_window->hide();}
}
}
+decl {Fl_Menu_Item *w_layout_menu_storage[4];} {private global
+}
+
Function {make_layout_window()} {open
} {
Fl_Window grid_window {
label {Layout Settings}
- xywh {745 303 310 245} type Double non_modal visible
+ callback {propagate_load(o, v);} open
+ xywh {392 444 320 491} type Double non_modal visible
} {
- Fl_Input horizontal_input {
- label x
- user_data 1 user_data_type long
- callback grid_cb
- tooltip {Horizontal grid spacing.} xywh {116 10 50 25} type Int box THIN_DOWN_BOX align 8
- code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
- }
- Fl_Input vertical_input {
- label pixels
- user_data 2 user_data_type long
- callback grid_cb
- tooltip {Vertical grid spacing.} xywh {179 10 50 25} type Int box THIN_DOWN_BOX align 8
- code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
- }
- Fl_Input snap_input {
- label {pixel snap}
- user_data 3 user_data_type long
- callback grid_cb
- tooltip {Snap to grid within this many pixels.} xywh {116 45 50 25} type Int box THIN_DOWN_BOX align 8
- code0 {o->when(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY);}
- }
- Fl_Check_Button guides_toggle {
- label {Show Guides}
- user_data 4 user_data_type long
- callback guides_cb
- tooltip {Show distance and alignment guides in overlay} xywh {116 80 110 25} down_box DOWN_BOX
+ Fl_Box {} {
+ label {Layout:}
+ xywh {10 10 60 24} labelfont 1 labelsize 11 align 24
+ }
+ Fl_Choice layout_choice {
+ callback {if (v == LOAD) {
+ o->value(g_layout_list.current_suite());
+ } else {
+ int index = o->value();
+ g_layout_list.current_suite(index);
+ g_layout_list.update_dialogs();
+ }}
+ xywh {70 10 187 24} down_box BORDER_BOX
+ } {
+ MenuItem {} {
+ label FLTK
+ xywh {0 0 31 20} labelsize 14
+ }
+ MenuItem {} {
+ label Grid
+ xywh {0 0 31 20} labelsize 14
+ }
}
Fl_Button {} {
- label Close
- callback {grid_window->hide();}
- tooltip {Close this dialog.} xywh {240 210 60 25}
+ label {+}
+ callback {// Clone the current layout suite
+
+if (v == LOAD) return;
+
+Fl_String old_name = "Copy of ";
+old_name.append(g_layout_list[g_layout_list.current_suite()].name_);
+const char *new_name = fl_input("Enter a name for the new layout:", old_name.c_str());
+if (new_name == NULL)
+ return;
+
+g_layout_list.add(new_name);
+g_layout_list.update_dialogs();}
+ xywh {257 10 24 24}
+ }
+ Fl_Menu_Button w_layout_menu {
+ callback {if (v == LOAD) {
+ Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+ if (suite.storage_ == FD_STORE_INTERNAL) {
+ w_layout_menu_rename->deactivate();
+ for (int i=1; i<4; i++) w_layout_menu_storage[i]->deactivate();
+ w_layout_menu_delete->deactivate();
+ } else {
+ w_layout_menu_rename->activate();
+ for (int i=1; i<4; i++) w_layout_menu_storage[i]->activate();
+ w_layout_menu_delete->activate();
+ }
+ w_layout_menu_storage[suite.storage_]->setonly();
+}}
+ xywh {281 10 24 24}
+ } {
+ MenuItem w_layout_menu_rename {
+ label {Rename...}
+ callback {// Rename the current layout suite
+
+Fl_String old_name = g_layout_list[g_layout_list.current_suite()].name_;
+const char *new_name = fl_input("Enter a new name for the layout:", old_name.c_str());
+if (new_name == NULL)
+ return;
+
+g_layout_list.rename(new_name);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} labelsize 14 divider
+ }
+ MenuItem {w_layout_menu_storage[0]} {
+ label {@fd_beaker FLUID Built-In}
+ callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+suite.storage(FD_STORE_INTERNAL);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} type Radio labelsize 14 deactivate
+ }
+ MenuItem {w_layout_menu_storage[1]} {
+ label {@fd_user User Preference}
+ callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+suite.storage(FD_STORE_USER);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} type Radio labelsize 14
+ }
+ MenuItem {w_layout_menu_storage[2]} {
+ label {@fd_project Store in .fl Project File}
+ callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+suite.storage(FD_STORE_PROJECT);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} type Radio labelsize 14
+ }
+ MenuItem {w_layout_menu_storage[3]} {
+ label {@fd_file Store in External File}
+ callback {Fd_Layout_Suite &suite = g_layout_list[g_layout_list.current_suite()];
+suite.storage(FD_STORE_FILE);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} type Radio labelsize 14 divider
+ }
+ MenuItem w_layout_menu_load {
+ label {Load...}
+ callback {// Give the user a file chooser and load that file
+Fl_Native_File_Chooser fnfc;
+fnfc.title("Load Layout Settings:");
+fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
+fnfc.options(Fl_Native_File_Chooser::USE_FILTER_EXT);
+fnfc.filter("FLUID Layouts\\t*.fll\\n");
+if (fnfc.show() != 0) return;
+const char *new_filename = fnfc.filename();
+if (!new_filename) return;
+g_layout_list.load(new_filename);
+//g_layout_list.current_suite(n);
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} labelsize 14
+ }
+ MenuItem w_layout_menu_save {
+ label {Save...}
+ callback {// Give the user a file chooser with a suggested name
+ Fl_Native_File_Chooser fnfc;
+ fnfc.title("Save Layout Settings:");
+ fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+ fnfc.options(Fl_Native_File_Chooser::SAVEAS_CONFIRM | Fl_Native_File_Chooser::USE_FILTER_EXT);
+ fnfc.filter("FLUID Layouts\\t*.fll\\n");
+ if (g_layout_list.filename_) {
+ char *fn = fl_strdup(g_layout_list.filename_);
+ char *name = (char*)fl_filename_name(g_layout_list.filename_);
+ if (name > fn) {
+ name[-1] = 0;
+ fnfc.directory(fn);
+ fnfc.preset_file(name);
+ ::free(fn);
+ } else if (name) {
+ fnfc.preset_file(name);
+ ::free(fn);
+ }
+ }
+ if (fnfc.show() != 0) return;
+ const char *new_filename = fnfc.filename();
+ if (!new_filename) return;
+ if (g_layout_list.filename_)
+ ::free(g_layout_list.filename_);
+ g_layout_list.filename_ = fl_strdup(new_filename);
+ g_layout_list.save(new_filename);}
+ xywh {0 0 31 20} labelsize 14 divider
+ code0 {\#include <FL/Fl_Native_File_Chooser.H>}
+ }
+ MenuItem w_layout_menu_delete {
+ label Delete
+ callback {// remove the current suite
+
+g_layout_list.remove(g_layout_list.current_suite());
+g_layout_list.update_dialogs();}
+ xywh {0 0 31 20} labelsize 14
+ }
+ }
+ Fl_Box {} {
+ label {Preset:}
+ xywh {10 39 60 20} labelfont 1 labelsize 11 align 24
+ }
+ Fl_Group {} {
+ callback propagate_load open
+ xywh {70 39 235 20} labelsize 11
+ } {
+ Fl_Button {preset_choice[0]} {
+ label Application
+ user_data 0 user_data_type long
+ callback edit_layout_preset_cb
+ xywh {70 39 78 20} type Radio value 1 selection_color 45 labelsize 11
+ }
+ Fl_Button {preset_choice[1]} {
+ label Dialog
+ user_data 1 user_data_type long
+ callback edit_layout_preset_cb
+ xywh {148 39 79 20} type Radio selection_color 45 labelsize 11
+ }
+ Fl_Button {preset_choice[2]} {
+ label Toolbox
+ user_data 2 user_data_type long
+ callback edit_layout_preset_cb
+ xywh {227 39 78 20} type Radio selection_color 45 labelsize 11
+ }
+ }
+ Fl_Box {} {
+ label {---- Window ----}
+ xywh {70 64 235 20} labelfont 1 labelsize 11 align 20
+ }
+ Fl_Box {} {
+ label {Margin:}
+ xywh {10 99 60 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Left:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->left_window_margin);
+} else {
+ layout->left_window_margin = (int)o->value();
+}}
+ xywh {70 99 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Top:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->top_window_margin);
+} else {
+ layout->top_window_margin = (int)o->value();
+}}
+ xywh {130 99 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Right:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->right_window_margin);
+} else {
+ layout->right_window_margin = (int)o->value();
+}}
+ xywh {190 99 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Bottom:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->bottom_window_margin);
+} else {
+ layout->bottom_window_margin = (int)o->value();
+}}
+ xywh {250 99 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
}
Fl_Box {} {
label {Grid:}
- xywh {47 10 70 25} labelfont 1 align 24
+ xywh {17 133 53 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Horizontal:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->window_grid_x);
+} else {
+ layout->window_grid_x = (int)o->value();
+}}
+ xywh {70 133 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Vertical:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->window_grid_y);
+} else {
+ layout->window_grid_y = (int)o->value();
+}}
+ xywh {130 133 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
}
Fl_Box {} {
- label {Widget Size:}
- xywh {10 115 107 25} labelfont 1 align 24
+ label {---- Group ----}
+ xywh {70 158 235 20} labelfont 1 labelsize 11 align 20
}
- Fl_Group {} {open
- xywh {105 115 192 75}
+ Fl_Box {} {
+ label {Margin:}
+ xywh {10 193 60 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Left:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->left_group_margin);
+} else {
+ layout->left_group_margin = (int)o->value();
+}}
+ xywh {70 193 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Top:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->top_group_margin);
+} else {
+ layout->top_group_margin = (int)o->value();
+}}
+ xywh {130 193 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Right:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->right_group_margin);
+} else {
+ layout->right_group_margin = (int)o->value();
+}}
+ xywh {190 193 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Bottom:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->bottom_group_margin);
+} else {
+ layout->bottom_group_margin = (int)o->value();
+}}
+ xywh {250 193 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Box {} {
+ label {Grid:}
+ xywh {17 227 53 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Horizontal:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->group_grid_x);
+} else {
+ layout->group_grid_x = (int)o->value();
+}}
+ xywh {70 227 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Vertical:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->group_grid_y);
+} else {
+ layout->group_grid_y = (int)o->value();
+}}
+ xywh {130 227 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Box {} {
+ label {---- Tabs ----}
+ xywh {70 252 235 20} labelfont 1 labelsize 11 align 20
+ }
+ Fl_Box {} {
+ label {Margin:}
+ xywh {10 287 60 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Top:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->top_tabs_margin);
+} else {
+ layout->top_tabs_margin = (int)o->value();
+}}
+ xywh {70 287 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Bottom:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->bottom_tabs_margin);
+} else {
+ layout->bottom_tabs_margin = (int)o->value();
+}}
+ xywh {130 287 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Box {} {
+ label {---- Widget ----}
+ xywh {70 312 235 20} labelfont 1 labelsize 11 align 20
+ }
+ Fl_Box {} {
+ label {Horizontal:}
+ xywh {10 347 60 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ label {Minimum:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_min_w);
+} else {
+ layout->widget_min_w = (int)o->value();
+}}
+ xywh {70 346 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Increment:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_inc_w);
+} else {
+ layout->widget_inc_w = (int)o->value();
+}}
+ xywh {130 346 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ label {Gap:}
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_gap_x);
+} else {
+ layout->widget_gap_x = (int)o->value();
+}}
+ xywh {190 346 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Box {} {
+ label {Vertical:}
+ xywh {17 372 53 20} labelsize 11 align 24
+ }
+ Fl_Value_Input {} {
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_min_h);
+} else {
+ layout->widget_min_h = (int)o->value();
+}}
+ xywh {70 372 55 20} labelsize 11 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_inc_h);
+} else {
+ layout->widget_inc_h = (int)o->value();
+}}
+ xywh {130 372 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Value_Input {} {
+ callback {if (v == LOAD) {
+ o->value((double)layout->widget_gap_y);
+} else {
+ layout->widget_gap_y = (int)o->value();
+}}
+ xywh {190 372 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11
+ }
+ Fl_Group {} {
+ label {Label Font:}
+ callback propagate_load open
+ xywh {70 397 200 20} labelsize 11 align 4
} {
- Fl_Round_Button {def_widget_size[0]} {
- user_data 8 user_data_type long
- callback default_widget_size_cb
- xywh {115 115 70 25} type Radio down_box ROUND_DOWN_BOX
- }
- Fl_Box {} {
- label tiny
- xywh {130 115 50 25} labelsize 8 align 20
- }
- Fl_Round_Button {def_widget_size[1]} {
- user_data 11 user_data_type long
- callback default_widget_size_cb
- xywh {202 115 70 25} type Radio down_box ROUND_DOWN_BOX
- }
- Fl_Box {} {
- label small
- xywh {218 115 50 25} labelsize 11 align 20
- }
- Fl_Round_Button {def_widget_size[2]} {
- user_data 14 user_data_type long
- callback default_widget_size_cb
- xywh {115 140 70 25} type Radio down_box ROUND_DOWN_BOX
- }
- Fl_Box {} {
- label normal
- xywh {130 140 50 25} align 20
- }
- Fl_Round_Button {def_widget_size[3]} {
- user_data 18 user_data_type long
- callback default_widget_size_cb
- xywh {202 140 90 25} type Radio down_box ROUND_DOWN_BOX
- }
- Fl_Box {} {
- label medium
- xywh {218 140 68 25} labelsize 18 align 20
- }
- Fl_Round_Button {def_widget_size[4]} {
- user_data 24 user_data_type long
- callback default_widget_size_cb
- xywh {115 165 75 25} type Radio down_box ROUND_DOWN_BOX
- }
- Fl_Box {} {
- label large
- xywh {130 165 64 25} labelsize 24 align 20
- }
- Fl_Round_Button {def_widget_size[5]} {
- user_data 32 user_data_type long
- callback default_widget_size_cb
- xywh {202 165 95 25} type Radio down_box ROUND_DOWN_BOX
+ Fl_Choice {} {
+ callback {if (v == LOAD) {
+ o->value(layout->labelfont);
+} else {
+ layout->labelfont = (int)o->value();
+}} open
+ tooltip {The style of the label text.} xywh {70 397 152 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable
+ code0 {extern Fl_Menu_Item fontmenu[];}
+ code1 {o->menu(fontmenu);}
+ } {}
+ Fl_Value_Input {} {
+ callback {if (v == LOAD) {
+ o->value(layout->labelsize);
+} else {
+ layout->labelsize = (int)o->value();
+}}
+ tooltip {The size of the label text.} xywh {221 397 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11
}
- Fl_Box {} {
- label huge
- xywh {218 165 76 25} labelsize 32 align 20
+ }
+ Fl_Group {} {
+ label {Text Font:}
+ callback propagate_load open
+ xywh {70 422 200 20} labelsize 11 align 4
+ } {
+ Fl_Choice {} {
+ callback {if (v == LOAD) {
+ o->value(layout->textfont);
+} else {
+ layout->textfont = (int)o->value();
+}} open
+ tooltip {The value text style.} xywh {70 422 152 20} box DOWN_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable
+ code0 {extern Fl_Menu_Item fontmenu[];}
+ code1 {o->menu(fontmenu);}
+ } {}
+ Fl_Value_Input {} {
+ callback {if (v == LOAD) {
+ o->value(layout->textsize);
+} else {
+ layout->textsize = (int)o->value();
+}}
+ tooltip {The value text size.} xywh {221 422 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11
}
}
+ Fl_Button {} {
+ label Close
+ callback {if (v != LOAD) grid_window->hide();}
+ tooltip {Close this dialog.} xywh {245 456 60 25}
+ }
}
+ code {grid_window->do_callback(grid_window, LOAD);} {}
}
diff --git a/fluid/alignment_panel.h b/fluid/alignment_panel.h
index 577648a94..b0e7b3ffc 100644
--- a/fluid/alignment_panel.h
+++ b/fluid/alignment_panel.h
@@ -1,7 +1,7 @@
//
// Setting and shell dialogs for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -21,10 +21,12 @@
#include <FL/Fl.H>
#include "fluid.h"
#include "widget_browser.h"
+#include "Fd_Snap_Action.h"
#include "shell_command.h"
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Text_Display.H>
#include <FL/filename.H>
+#include <FL/fl_string_functions.h>
#include <FL/Fl_Scheme_Choice.H>
/**
// initialize the scheme from preferences
@@ -95,14 +97,21 @@ extern Fl_Simple_Terminal *shell_run_terminal;
extern Fl_Return_Button *shell_run_button;
Fl_Double_Window* make_shell_window();
extern Fl_Double_Window *grid_window;
-extern void grid_cb(Fl_Int_Input*, long);
-extern Fl_Int_Input *horizontal_input;
-extern Fl_Int_Input *vertical_input;
-extern Fl_Int_Input *snap_input;
-extern void guides_cb(Fl_Check_Button*, long);
-extern Fl_Check_Button *guides_toggle;
-#include <FL/Fl_Round_Button.H>
-extern void default_widget_size_cb(Fl_Round_Button*, long);
-extern Fl_Round_Button *def_widget_size[6];
+extern Fl_Choice *layout_choice;
+#include <FL/Fl_Menu_Button.H>
+extern Fl_Menu_Button *w_layout_menu;
+#include <FL/Fl_Native_File_Chooser.H>
+extern void propagate_load(Fl_Group*, void*);
+extern void edit_layout_preset_cb(Fl_Button*, long);
+extern Fl_Button *preset_choice[3];
+#include <FL/Fl_Value_Input.H>
+extern Fl_Menu_Item fontmenu[];
Fl_Double_Window* make_layout_window();
+extern Fl_Menu_Item menu_layout_choice[];
+extern Fl_Menu_Item menu_w_layout_menu[];
+#define w_layout_menu_rename (menu_w_layout_menu+0)
+extern Fl_Menu_Item *w_layout_menu_storage[4];
+#define w_layout_menu_load (menu_w_layout_menu+5)
+#define w_layout_menu_save (menu_w_layout_menu+6)
+#define w_layout_menu_delete (menu_w_layout_menu+7)
#endif
diff --git a/fluid/factory.cxx b/fluid/factory.cxx
index 551d2b11e..a58648261 100644
--- a/fluid/factory.cxx
+++ b/fluid/factory.cxx
@@ -27,6 +27,7 @@
#include "fluid.h"
#include "Fl_Window_Type.h"
#include "Fl_Group_Type.h"
+#include "Fd_Snap_Action.h"
#include "pixmaps.h"
#include "undo.h"
@@ -1064,12 +1065,14 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) {
Fl_Widget_Type *wt = (Fl_Widget_Type *)t;
// Set font sizes...
- wt->o->labelsize(Fl_Widget_Type::default_size);
+ wt->o->labelsize(layout->labelsize);
+ wt->o->labelfont(layout->labelfont);
- Fl_Font f;
- int s = Fl_Widget_Type::default_size;
+ Fl_Font f = layout->textfont;
+ int s = layout->textsize;
Fl_Color c;
+ wt->textstuff(1, f, s, c);
wt->textstuff(2, f, s, c);
// Resize and/or reposition new widget...
diff --git a/fluid/file.cxx b/fluid/file.cxx
index db59a2733..2da570f3a 100644
--- a/fluid/file.cxx
+++ b/fluid/file.cxx
@@ -159,6 +159,10 @@ int Fd_Project_Reader::close_read() {
return 1;
}
+const char *Fd_Project_Reader::filename_name() {
+ return fl_filename_name(fname);
+}
+
/**
Convert an ASCII sequence form the \.fl file that starts with a \\ into a single character.
Conversion includes the common C style \\ characters like \\n, \\x## hex
@@ -309,7 +313,12 @@ void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy,
goto CONTINUE;
}
- if (!strcmp(c, "snap") || !strcmp(c, "gridx") || !strcmp(c, "gridy")) {
+ if (!strcmp(c, "snap")) {
+ g_layout_list.read(this);
+ goto CONTINUE;
+ }
+
+ if (!strcmp(c, "gridx") || !strcmp(c, "gridy")) {
// grid settings are now global
read_word();
goto CONTINUE;
@@ -523,6 +532,15 @@ const char *Fd_Project_Reader::read_word(int wantbrace) {
}
}
+int Fd_Project_Reader::read_int() {
+ const char *word = read_word();
+ if (word) {
+ return atoi(word);
+ } else {
+ return 0;
+ }
+}
+
int Fd_Project_Reader::read_fdesign_line(const char*& name, const char*& value) {
int length = 0;
int x;
@@ -791,7 +809,7 @@ int Fd_Project_Writer::write_project(const char *filename, int selected_only) {
if (!selected_only) {
write_string("\nheader_name"); write_word(g_project.header_file_name.c_str());
write_string("\ncode_name"); write_word(g_project.code_file_name.c_str());
-
+ g_layout_list.write(this);
#if 0
// https://github.com/fltk/fltk/issues/328
// Project wide settings require a redesign.
diff --git a/fluid/file.h b/fluid/file.h
index 457d14e49..e45bd4256 100644
--- a/fluid/file.h
+++ b/fluid/file.h
@@ -46,11 +46,13 @@ public:
~Fd_Project_Reader();
int open_read(const char *s);
int close_read();
+ const char *filename_name();
int read_quoted();
void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options=0);
int read_project(const char *, int merge, Strategy strategy=kAddAsLastChild);
void read_error(const char *format, ...);
const char *read_word(int wantbrace = 0);
+ int read_int();
int read_fdesign_line(const char*& name, const char*& value);
void read_fdesign();
};
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
index 7512e7bc8..bb98006bc 100644
--- a/fluid/fluid.cxx
+++ b/fluid/fluid.cxx
@@ -1,7 +1,7 @@
//
// FLUID main entry for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2022 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -72,16 +72,7 @@ Fl_Menu_Bar *main_menubar = NULL;
Fl_Window *main_window;
/// Fluid application preferences, allways accessible, will be flushed when app closes.
-Fl_Preferences fluid_prefs(Fl_Preferences::USER_L, "fltk.org", "fluid");
-
-/// Align widget position and size when designing, saved in app preferences and project file.
-int gridx = 5;
-
-/// Align widget position and size when designing, saved in app preferences and project file.
-int gridy = 5;
-
-/// Activate snapping to grid, saved in app preferences and project file.
-int snap = 1;
+Fl_Preferences fluid_prefs(Fl_Preferences::USER_L, "fltk.org", "fluid");
/// Show guides in the design window when positioning widgets, saved in app preferences.
int show_guides = 1;
@@ -132,6 +123,9 @@ Fl_Menu_Item *sourceview_item = NULL;
/// Menuitem to show or hide the editing overlay, label will change if overlay visibility changes.
Fl_Menu_Item *overlay_item = NULL;
+/// Menuitem to show or hide the editing guides, label will change if overlay visibility changes.
+Fl_Menu_Item *guides_item = NULL;
+
////////////////////////////////////////////////////////////////
/// Filename of the current .fl design file
@@ -285,7 +279,6 @@ void Fluid_Project::reset() {
code_file_set = 0;
header_file_name = ".h";
code_file_name = ".cxx";
-
}
// ---- Sourceview definition
@@ -693,6 +686,8 @@ void exit_cb(Fl_Widget *,void *) {
if (help_dialog)
delete help_dialog;
+ g_layout_list.write(fluid_prefs, FD_STORE_USER);
+
undo_clear();
// Destroy tree
@@ -1144,10 +1139,6 @@ void delete_cb(Fl_Widget *, void *) {
void paste_cb(Fl_Widget*, void*) {
//if (ipasteoffset) force_parent = 1;
pasteoffset = ipasteoffset;
- // TODO: make the paste offset more predictable, if any at all.
- // TODO: Don't use the grid if the user switched it off.
- if (gridx>1) pasteoffset = ((pasteoffset-1)/gridx+1)*gridx;
- if (gridy>1) pasteoffset = ((pasteoffset-1)/gridy+1)*gridy;
undo_checkpoint();
undo_suspend();
Strategy strategy = kAddAfterCurrent;
@@ -1370,6 +1361,9 @@ void print_menu_cb(Fl_Widget *, void *) {
// ---- Main menu bar
+extern void select_layout_preset_cb(Fl_Widget *, void *user_data);
+extern void layout_suite_marker(Fl_Widget *, void *user_data);
+
/**
This is the main Fluid menu.
@@ -1428,6 +1422,7 @@ Fl_Menu_Item Main_Menu[] = {
{"&Group", FL_F+7, group_cb},
{"Ung&roup", FL_F+8, ungroup_cb,0, FL_MENU_DIVIDER},
{"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays},
+ {"Hide Guides",FL_COMMAND+FL_SHIFT+'g',toggle_guides},
{"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb},
{"Show Source Code...",FL_ALT+FL_SHIFT+'s', (Fl_Callback*)toggle_sourceview_cb, 0, FL_MENU_DIVIDER},
{"Pro&ject Settings...",FL_ALT+'p',show_project_cb},
@@ -1452,19 +1447,15 @@ Fl_Menu_Item Main_Menu[] = {
{"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31},
{"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32},
{0},
- {"&Center In Group",0,0,0,FL_SUBMENU},
+ {"&Center In Group",0,0,0,FL_SUBMENU|FL_MENU_DIVIDER},
{"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40},
{"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41},
{0},
- {"Set &Widget Size",0,0,0,FL_SUBMENU|FL_MENU_DIVIDER},
- {"&Tiny",FL_ALT+'1',(Fl_Callback *)widget_size_cb,(void*)8,0,FL_NORMAL_LABEL,FL_HELVETICA,8},
- {"&Small",FL_ALT+'2',(Fl_Callback *)widget_size_cb,(void*)11,0,FL_NORMAL_LABEL,FL_HELVETICA,11},
- {"&Normal",FL_ALT+'3',(Fl_Callback *)widget_size_cb,(void*)14,0,FL_NORMAL_LABEL,FL_HELVETICA,14},
- {"&Medium",FL_ALT+'4',(Fl_Callback *)widget_size_cb,(void*)18,0,FL_NORMAL_LABEL,FL_HELVETICA,18},
- {"&Large",FL_ALT+'5',(Fl_Callback *)widget_size_cb,(void*)24,0,FL_NORMAL_LABEL,FL_HELVETICA,24},
- {"&Huge",FL_ALT+'6',(Fl_Callback *)widget_size_cb,(void*)32,0,FL_NORMAL_LABEL,FL_HELVETICA,32},
- {0},
- {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb},
+ {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb, NULL, FL_MENU_DIVIDER},
+ {"Presets", 0, layout_suite_marker, (void*)g_layout_list.main_menu_, FL_SUBMENU_POINTER },
+ {"Application", 0, select_layout_preset_cb, (void*)0, FL_MENU_RADIO|FL_MENU_VALUE },
+ {"Dialog", 0, select_layout_preset_cb, (void*)1, FL_MENU_RADIO },
+ {"Toolbox", 0, select_layout_preset_cb, (void*)2, FL_MENU_RADIO },
{0},
{"&Shell",0,0,0,FL_SUBMENU},
{"Execute &Command...",FL_ALT+'x',(Fl_Callback *)show_shell_window},
@@ -1618,11 +1609,7 @@ void toggle_sourceview_b_cb(Fl_Button*, void *) {
*/
void make_main_window() {
if (!batch_mode) {
- fluid_prefs.get("snap", snap, 1);
- fluid_prefs.get("gridx", gridx, 5);
- fluid_prefs.get("gridy", gridy, 5);
fluid_prefs.get("show_guides", show_guides, 0);
- fluid_prefs.get("widget_size", Fl_Widget_Type::default_size, 14);
fluid_prefs.get("show_comments", show_comments, 1);
shell_prefs_get();
make_layout_window();
@@ -1646,6 +1633,7 @@ void make_main_window() {
widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb);
sourceview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_sourceview_cb);
overlay_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_overlays);
+ guides_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_guides);
main_menubar->global();
fill_in_New_Menu();
main_window->end();
@@ -2091,6 +2079,7 @@ int main(int argc,char **argv) {
main_window->show(argc,argv);
toggle_widgetbin_cb(0,0);
toggle_sourceview_cb(0,0);
+ g_layout_list.read(fluid_prefs, FD_STORE_USER);
if (!c && openlast_button->value() && absolute_history[0][0]) {
// Open previous file when no file specified...
open_history_cb(0, absolute_history[0]);
@@ -2137,13 +2126,10 @@ int main(int argc,char **argv) {
// Set (but do not start) timer callback for external editor updates
ExternalCodeEditor::set_update_timer_callback(external_editor_timer);
- grid_cb(horizontal_input, 0); // Makes sure that windows get snap params...
-
#ifdef _WIN32
Fl::run();
#else
while (!quit_flag) Fl::wait();
-
if (quit_flag) exit_cb(0,0);
#endif // _WIN32
diff --git a/fluid/fluid.h b/fluid/fluid.h
index 7d2a3ade2..c952558df 100644
--- a/fluid/fluid.h
+++ b/fluid/fluid.h
@@ -1,7 +1,7 @@
//
// FLUID main entry for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2021 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -42,9 +42,6 @@ extern Fl_Menu_Item Main_Menu[];
extern Fl_Menu_Bar *main_menubar;
extern Fl_Window *main_window;
-extern int gridx;
-extern int gridy;
-extern int snap;
extern int show_guides;
extern int show_comments;
@@ -65,6 +62,9 @@ extern Fl_Menu_Item *history_item;
extern Fl_Menu_Item *widgetbin_item;
extern Fl_Menu_Item *sourceview_item;
extern Fl_Menu_Item *overlay_item;
+extern Fl_Button *overlay_button;
+extern Fl_Menu_Item *guides_item;
+extern Fl_Button *guides_button;
extern int modflag;
@@ -77,6 +77,7 @@ extern int compile_strings; // fluic -cs
extern int batch_mode;
extern int pasteoffset;
+extern int pasteoffset;
// ---- project settings
@@ -133,7 +134,9 @@ extern void new_from_template_cb(Fl_Widget *w, void *v);
extern int write_code_files();
extern void write_strings_cb(Fl_Widget *, void *);
extern void align_widget_cb(Fl_Widget *, long);
-extern void widget_size_cb(Fl_Widget *, long);
extern void toggle_widgetbin_cb(Fl_Widget *, void *);
+inline int fd_min(int a, int b) { return (a < b ? a : b); }
+inline int fd_min(int a, int b, int c) { return fd_min(a, fd_min(b, c)); }
+
#endif // _FLUID_FLUID_H
diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx
index 089184511..8354df0b9 100644
--- a/fluid/widget_browser.cxx
+++ b/fluid/widget_browser.cxx
@@ -1,7 +1,7 @@
//
// Widget Browser code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2021 by Bill Spitzak and others.
+// Copyright 1998-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx
index adbff5671..a88028237 100644
--- a/fluid/widget_panel.cxx
+++ b/fluid/widget_panel.cxx
@@ -113,6 +113,10 @@ Fl_Box *w_when_box=(Fl_Box *)0;
Fl_Button *wLiveMode=(Fl_Button *)0;
+Fl_Button *overlay_button=(Fl_Button *)0;
+
+Fl_Button *guides_button=(Fl_Button *)0;
+
/**
Create a panel that can be used with all known widgets
*/
@@ -969,7 +973,7 @@ access the Widget pointer and \'v\' to access the user value.");
} // Fl_Menu_Button* o
o->end();
} // Fl_Group* o
- { Fl_Group* o = new Fl_Group(95, 335, 310, 20, "Type:");
+ { Fl_Group* o = new Fl_Group(95, 332, 310, 26, "Type:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)propagate_load);
@@ -999,26 +1003,30 @@ access the Widget pointer and \'v\' to access the user value.");
} // Fl_Tabs* o
{ Fl_Group* o = new Fl_Group(10, 370, 400, 20);
o->labelsize(11);
- { // Hidden resizable box
- Fl_Box* o = new Fl_Box(10, 370, 75, 20);
- o->labelsize(11);
- o->hide();
- Fl_Group::current()->resizable(o);
- } // Fl_Box* o
- { wLiveMode = new Fl_Button(155, 370, 80, 20, "Live &Resize");
+ { wLiveMode = new Fl_Button(10, 370, 80, 20, "Live &Resize");
wLiveMode->tooltip("Create a live duplicate of the selected widgets to test resizing and menu beh\
avior.");
wLiveMode->type(1);
wLiveMode->labelsize(11);
wLiveMode->callback((Fl_Callback*)live_mode_cb);
} // Fl_Button* wLiveMode
- { Fl_Button* o = new Fl_Button(240, 370, 100, 20, "Hide &Overlays");
- o->tooltip("Hide the widget overlay box.");
+ { overlay_button = new Fl_Button(94, 370, 80, 20, "Hide &Overlays");
+ overlay_button->tooltip("Hide the widget overlay box.");
+ overlay_button->labelsize(11);
+ overlay_button->callback((Fl_Callback*)overlay_cb);
+ } // Fl_Button* overlay_button
+ { guides_button = new Fl_Button(178, 370, 80, 20, "Hide &Guides");
+ guides_button->tooltip("Hide alignment guides.");
+ guides_button->labelsize(11);
+ guides_button->callback((Fl_Callback*)guides_cb);
+ } // Fl_Button* guides_button
+ { // Hidden resizable box
+ Fl_Box* o = new Fl_Box(258, 370, 72, 20);
o->labelsize(11);
- o->labelcolor((Fl_Color)1);
- o->callback((Fl_Callback*)overlay_cb);
- } // Fl_Button* o
- { Fl_Return_Button* o = new Fl_Return_Button(345, 370, 65, 20, "Close");
+ o->hide();
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ { Fl_Return_Button* o = new Fl_Return_Button(330, 370, 80, 20, "Close");
o->labelsize(11);
o->callback((Fl_Callback*)ok_cb);
} // Fl_Return_Button* o
diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl
index ea4c1ad24..afed58034 100644
--- a/fluid/widget_panel.fl
+++ b/fluid/widget_panel.fl
@@ -30,7 +30,7 @@ Function {make_widget_panel()} {
comment {Create a panel that can be used with all known widgets} open
} {
Fl_Window {} {
- comment {Use a Double Window to avoid flickering.} open
+ comment {Use a Double Window to avoid flickering.} open selected
xywh {566 244 420 400} type Double labelsize 11 align 80 resizable hotspot
code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0} visible
} {
@@ -40,7 +40,7 @@ Function {make_widget_panel()} {
} {
Fl_Group {} {
label GUI
- callback propagate_load open selected
+ callback propagate_load open
xywh {10 30 400 330} labelsize 11 when 0 resizable
} {
Fl_Group {} {
@@ -784,7 +784,7 @@ wCallback->do_callback(wCallback, v);} open
Fl_Group {} {
label {Type:}
callback propagate_load open
- xywh {95 335 310 20} labelfont 1 labelsize 11 align 4
+ xywh {95 332 310 26} labelfont 1 labelsize 11 align 4
} {
Fl_Input_Choice {} {
callback user_data_type_cb open
@@ -809,24 +809,29 @@ wCallback->do_callback(wCallback, v);} open
Fl_Group {} {open
xywh {10 370 400 20} labelsize 11
} {
- Fl_Box {} {
- comment {Hidden resizable box}
- xywh {10 370 75 20} labelsize 11 hide resizable
- }
Fl_Button wLiveMode {
label {Live &Resize}
callback live_mode_cb
- tooltip {Create a live duplicate of the selected widgets to test resizing and menu behavior.} xywh {155 370 80 20} type Toggle labelsize 11
+ tooltip {Create a live duplicate of the selected widgets to test resizing and menu behavior.} xywh {10 370 80 20} type Toggle labelsize 11
}
- Fl_Button {} {
+ Fl_Button overlay_button {
label {Hide &Overlays}
callback overlay_cb
- tooltip {Hide the widget overlay box.} xywh {240 370 100 20} labelsize 11 labelcolor 1
+ tooltip {Hide the widget overlay box.} xywh {94 370 80 20} labelsize 11
+ }
+ Fl_Button guides_button {
+ label {Hide &Guides}
+ callback guides_cb
+ tooltip {Hide alignment guides.} xywh {178 370 80 20} labelsize 11
+ }
+ Fl_Box {} {
+ comment {Hidden resizable box}
+ xywh {258 370 72 20} labelsize 11 hide resizable
}
Fl_Return_Button {} {
label Close
callback ok_cb
- xywh {345 370 65 20} labelsize 11
+ xywh {330 370 80 20} labelsize 11
}
}
}
diff --git a/fluid/widget_panel.h b/fluid/widget_panel.h
index ddeed0b79..261656317 100644
--- a/fluid/widget_panel.h
+++ b/fluid/widget_panel.h
@@ -135,6 +135,9 @@ extern Fl_Box *w_when_box;
extern void live_mode_cb(Fl_Button*, void*);
extern Fl_Button *wLiveMode;
extern void overlay_cb(Fl_Button*, void*);
+extern Fl_Button *overlay_button;
+extern void guides_cb(Fl_Button*, void*);
+extern Fl_Button *guides_button;
#include <FL/Fl_Return_Button.H>
extern void ok_cb(Fl_Return_Button*, void*);
Fl_Double_Window* make_widget_panel();
diff --git a/src/Fl_Menu_.cxx b/src/Fl_Menu_.cxx
index 60712a9ef..28a476e02 100644
--- a/src/Fl_Menu_.cxx
+++ b/src/Fl_Menu_.cxx
@@ -359,10 +359,11 @@ void Fl_Menu_::setonly(Fl_Menu_Item* item) {
}
/** Turns the radio item "on" for the menu item and turns "off" adjacent radio items set.
- \deprecated This method is dangerous if radio items are first in the menu.
- Use Fl_Menu_::setonly(Fl_Menu_Item*) instead.
+ \note This method is dangerous if radio items are first in the menu.
+ Make sure that \p first is set ciorrectly or use Fl_Menu_::setonly(Fl_Menu_Item*) instead.
+ \param[in] first start of menu array or NULL (default) if the radio group is not the first item
*/
-void Fl_Menu_Item::setonly() {
+void Fl_Menu_Item::setonly(Fl_Menu_Item const* first) {
flags |= FL_MENU_RADIO | FL_MENU_VALUE;
Fl_Menu_Item* j;
for (j = this; ; ) { // go down
@@ -371,9 +372,10 @@ void Fl_Menu_Item::setonly() {
if (!j->text || !j->radio()) break; // stop after group
j->clear();
}
- for (j = this-1; ; j--) { // go up
+ if (this != first) for (j = this-1; ; j--) { // go up
if (!j->text || (j->flags&FL_MENU_DIVIDER) || !j->radio()) break;
j->clear();
+ if (j == first) break;
}
}
diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx
index 04ebbc6e0..5073d4ee4 100644
--- a/src/fl_draw.cxx
+++ b/src/fl_draw.cxx
@@ -43,15 +43,17 @@ static char* underline_at;
*/
static const char* expand_text_(const char* from, char*& buf, int maxbuf, double maxw, int& n,
double &width, int wrap, int draw_symbols) {
- char* e = buf+(maxbuf-4);
underline_at = 0;
double w = 0;
static int l_local_buff = 500;
static char *local_buf = (char*)malloc(l_local_buff); // initial buffer allocation
+ char* e;
if (maxbuf == 0) {
buf = local_buf;
e = buf + l_local_buff - 4;
- }
+ } else {
+ e = buf+(maxbuf-4);
+ }
char* o = buf;
char* word_end = o;
const char* word_start = from;
diff --git a/src/fl_symbols.cxx b/src/fl_symbols.cxx
index e6ebb4199..2cb586ccb 100644
--- a/src/fl_symbols.cxx
+++ b/src/fl_symbols.cxx
@@ -655,6 +655,43 @@ static void draw_redo(Fl_Color c) {
fl_scale(-1.0, 1.0);
}
+static void draw_open_box(Fl_Color col) {
+ fl_color(col);
+ BCP;
+ vv(-1.0, -1.0); vv(-0.4, -1.0); vv(-0.4, -0.75); vv(-0.75, -0.75);
+ vv(-0.75, 0.75); vv(0.75, 0.75); vv(0.75, 0.4); vv(1.0, 0.4); vv(1.0, 1.0);
+ vv(-1.0, 1.0);
+ ECP;
+ set_outline_color(col);
+ BC;
+ vv(-1.0, -1.0); vv(-0.4, -1.0); vv(-0.4, -0.75); vv(-0.75, -0.75);
+ vv(-0.75, 0.75); vv(0.75, 0.75); vv(0.75, 0.4); vv(1.0, 0.4); vv(1.0, 1.0);
+ vv(-1.0, 1.0);
+ EC;
+}
+
+static void draw_import(Fl_Color col)
+{
+ fl_push_matrix();
+ fl_scale(-1.0, 1.0);
+ draw_open_box(col);
+ fl_scale(-1.0, 1.0);
+ fl_translate(-0.8, -0.3);
+ fl_rotate(45.0+90);
+ draw_round_arrow(col, 3);
+ fl_pop_matrix();
+}
+
+static void draw_export(Fl_Color col)
+{
+ draw_open_box(col);
+ fl_push_matrix();
+ fl_translate(0.7, 0.1);
+ fl_rotate(225.0);
+ draw_round_arrow(col, 3);
+ fl_pop_matrix();
+}
+
static void fl_init_symbols(void) {
static char beenhere;
if (beenhere) return;
@@ -702,5 +739,8 @@ static void fl_init_symbols(void) {
fl_add_symbol("undo", draw_undo, 1);
fl_add_symbol("redo", draw_redo, 1);
+ fl_add_symbol("import", draw_import, 1);
+ fl_add_symbol("export", draw_export, 1);
+
// fl_add_symbol("file", draw_file, 1);
}
diff --git a/test/symbols.cxx b/test/symbols.cxx
index d97dfa834..9c51e0fb4 100644
--- a/test/symbols.cxx
+++ b/test/symbols.cxx
@@ -28,7 +28,7 @@ int N = 0;
#define W 70
#define H 70
#define ROWS 6
-#define COLS 6
+#define COLS 7
Fl_Double_Window *window;
Fl_Value_Slider *orientation;
@@ -119,6 +119,8 @@ bt("@refresh");
bt("@reload");
bt("@undo");
bt("@redo");
+bt("@import");
+bt("@export");
orientation = new Fl_Value_Slider(
(int)(window->w()*.05+.5), window->h()-40,