From 51a55bc73660f64e8f4b32b8b4d3858f2a786f7b Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Sun, 16 Mar 2025 17:16:12 -0400 Subject: [PATCH] Fluid: restructuring and rejuvenation of the source code. * Add classes for application and project * Removed all globals from Fluid.h * Extracting args and project history into their own classes * Moving globals into Application class * Initialize values inside headers for some classes. * Undo functionality wrapped in a class inside Project. * File reader and writer are now linked to a project. * Avoid global project access * Nodes (former Types) will be managed by a new Tree class. * Removed static members (hidden globals) form Node/Fl_Type. * Adding Tree iterator. * Use nullptr instead of 0, NULL, or 0L * Renamed Fl_..._Type to ..._Node, FL_OVERRIDE -> override * Renaming ..._type to ...::prototype * Splitting Widget Panel into multiple files. * Moved callback code into widget panel file. * Cleaning up Fluid_Image -> Image_asset * Moving Fd_Snap_Action into new namespace fld::app::Snap_Action etc. * Moved mergeback into proj folder. * `enum ID` is now `enum class Type`. --- fluid/CMakeLists.txt | 91 +- fluid/Fluid.cxx | 1392 ++++++ fluid/Fluid.h | 219 + fluid/Project.cxx | 335 ++ fluid/{app/project.h => Project.h} | 154 +- fluid/README_fl.txt | 22 +- fluid/app/Fluid_Image.cxx | 413 -- fluid/app/Image_Asset.cxx | 532 +++ fluid/app/{Fluid_Image.h => Image_Asset.h} | 57 +- fluid/app/Menu.cxx | 190 + fluid/app/Menu.h | 29 + .../{Fd_Snap_Action.cxx => Snap_Action.cxx} | 458 +- fluid/app/{Fd_Snap_Action.h => Snap_Action.h} | 92 +- fluid/app/args.cxx | 136 + fluid/app/args.h | 55 + fluid/app/fluid.cxx | 2169 --------- fluid/app/fluid.h | 134 - fluid/app/history.cxx | 115 + fluid/app/history.h | 45 + fluid/app/project.cxx | 192 - fluid/app/shell_command.cxx | 197 +- fluid/app/shell_command.h | 46 +- fluid/app/templates.cxx | 143 + fluid/app/templates.h | 29 + fluid/app/undo.h | 37 - fluid/io/Code_Writer.cxx | 430 +- fluid/io/Code_Writer.h | 53 +- fluid/io/Project_Reader.cxx | 197 +- fluid/io/Project_Reader.h | 32 +- fluid/io/Project_Writer.cxx | 82 +- fluid/io/Project_Writer.h | 22 +- fluid/io/String_Writer.cxx | 142 + fluid/io/String_Writer.h | 33 + fluid/main.cxx | 4 +- fluid/nodes/Button_Node.cxx | 166 + fluid/nodes/Button_Node.h | 149 + fluid/nodes/Fl_Button_Type.cxx | 227 - fluid/nodes/Fl_Button_Type.h | 46 - fluid/nodes/Fl_Function_Type.h | 259 -- fluid/nodes/Fl_Grid_Type.h | 82 - fluid/nodes/Fl_Group_Type.h | 242 - fluid/nodes/Fl_Menu_Type.h | 287 -- fluid/nodes/Fl_Widget_Type.cxx | 3939 ----------------- fluid/nodes/Fl_Window_Type.h | 157 - ...Fl_Function_Type.cxx => Function_Node.cxx} | 489 +- fluid/nodes/Function_Node.h | 277 ++ .../nodes/{Fl_Grid_Type.cxx => Grid_Node.cxx} | 333 +- fluid/nodes/Grid_Node.h | 82 + .../{Fl_Group_Type.cxx => Group_Node.cxx} | 332 +- fluid/nodes/Group_Node.h | 261 ++ .../nodes/{Fl_Menu_Type.cxx => Menu_Node.cxx} | 382 +- fluid/nodes/Menu_Node.h | 310 ++ fluid/nodes/{Fl_Type.cxx => Node.cxx} | 596 ++- fluid/nodes/{Fl_Type.h => Node.h} | 156 +- fluid/nodes/Tree.cxx | 128 + fluid/nodes/Tree.h | 106 + fluid/nodes/Widget_Node.cxx | 2438 ++++++++++ .../nodes/{Fl_Widget_Type.h => Widget_Node.h} | 85 +- .../{Fl_Window_Type.cxx => Window_Node.cxx} | 575 ++- fluid/nodes/Window_Node.h | 163 + fluid/nodes/callbacks.cxx | 18 + fluid/nodes/callbacks.h | 23 + fluid/nodes/factory.cxx | 1286 +++--- fluid/nodes/factory.h | 18 +- fluid/panels/about_panel.cxx | 5 +- fluid/panels/about_panel.fl | 6 +- fluid/panels/about_panel.h | 2 +- fluid/panels/codeview_panel.cxx | 115 +- fluid/panels/codeview_panel.fl | 117 +- fluid/panels/function_panel.cxx | 128 +- fluid/panels/function_panel.fl | 126 +- fluid/panels/print_panel.cxx | 586 --- fluid/panels/print_panel.fl | 358 -- fluid/panels/print_panel.h | 56 - fluid/panels/settings_panel.cxx | 434 +- fluid/panels/settings_panel.fl | 426 +- fluid/panels/settings_panel.h | 9 +- fluid/panels/template_panel.cxx | 16 +- fluid/panels/template_panel.fl | 16 +- fluid/panels/widget_panel.cxx | 2856 +++++++----- fluid/panels/widget_panel.fl | 2311 ++++++---- fluid/panels/widget_panel.h | 115 +- fluid/panels/widget_panel/Grid_Child_Tab.cxx | 538 +++ fluid/panels/widget_panel/Grid_Child_Tab.fl | 397 ++ fluid/panels/widget_panel/Grid_Child_Tab.h | 79 + fluid/panels/widget_panel/Grid_Tab.cxx | 778 ++++ fluid/panels/widget_panel/Grid_Tab.fl | 515 +++ fluid/panels/widget_panel/Grid_Tab.h | 90 + fluid/{app => proj}/align_widget.cxx | 194 +- fluid/{app => proj}/align_widget.h | 2 +- fluid/{app => proj}/mergeback.cxx | 80 +- fluid/{app => proj}/mergeback.h | 4 +- fluid/{app => proj}/undo.cxx | 192 +- fluid/proj/undo.h | 93 + fluid/rsrcs/pixmaps.cxx | 122 +- fluid/rsrcs/pixmaps.h | 4 +- fluid/tools/ExternalCodeEditor_UNIX.cxx | 76 +- fluid/tools/ExternalCodeEditor_UNIX.h | 4 +- fluid/tools/ExternalCodeEditor_WIN32.cxx | 92 +- fluid/tools/ExternalCodeEditor_WIN32.h | 2 +- fluid/tools/autodoc.cxx | 64 +- fluid/tools/autodoc.h | 2 +- fluid/tools/filename.cxx | 32 +- fluid/tools/filename.h | 5 +- fluid/widgets/Bin_Button.cxx | 20 +- fluid/widgets/Code_Editor.cxx | 7 +- fluid/widgets/Code_Editor.h | 5 +- fluid/widgets/Code_Viewer.cxx | 5 +- fluid/widgets/Code_Viewer.h | 5 +- fluid/widgets/Formula_Input.cxx | 4 +- fluid/widgets/Formula_Input.h | 4 +- fluid/widgets/Node_Browser.cxx | 96 +- fluid/widgets/Node_Browser.h | 18 +- fluid/widgets/Text_Viewer.cxx | 5 +- fluid/widgets/Text_Viewer.h | 3 +- src/Fl_Tabs.cxx | 2 +- test/preferences.fl | 5 +- 117 files changed, 17426 insertions(+), 15689 deletions(-) create mode 100644 fluid/Fluid.cxx create mode 100644 fluid/Fluid.h create mode 100644 fluid/Project.cxx rename fluid/{app/project.h => Project.h} (55%) delete mode 100644 fluid/app/Fluid_Image.cxx create mode 100644 fluid/app/Image_Asset.cxx rename fluid/app/{Fluid_Image.h => Image_Asset.h} (56%) create mode 100644 fluid/app/Menu.cxx create mode 100644 fluid/app/Menu.h rename fluid/app/{Fd_Snap_Action.cxx => Snap_Action.cxx} (79%) rename fluid/app/{Fd_Snap_Action.h => Snap_Action.h} (73%) create mode 100644 fluid/app/args.cxx create mode 100644 fluid/app/args.h delete mode 100644 fluid/app/fluid.cxx delete mode 100644 fluid/app/fluid.h create mode 100644 fluid/app/history.cxx create mode 100644 fluid/app/history.h delete mode 100644 fluid/app/project.cxx create mode 100644 fluid/app/templates.cxx create mode 100644 fluid/app/templates.h delete mode 100644 fluid/app/undo.h create mode 100644 fluid/io/String_Writer.cxx create mode 100644 fluid/io/String_Writer.h create mode 100644 fluid/nodes/Button_Node.cxx create mode 100644 fluid/nodes/Button_Node.h delete mode 100644 fluid/nodes/Fl_Button_Type.cxx delete mode 100644 fluid/nodes/Fl_Button_Type.h delete mode 100644 fluid/nodes/Fl_Function_Type.h delete mode 100644 fluid/nodes/Fl_Grid_Type.h delete mode 100644 fluid/nodes/Fl_Group_Type.h delete mode 100644 fluid/nodes/Fl_Menu_Type.h delete mode 100644 fluid/nodes/Fl_Widget_Type.cxx delete mode 100644 fluid/nodes/Fl_Window_Type.h rename fluid/nodes/{Fl_Function_Type.cxx => Function_Node.cxx} (83%) create mode 100644 fluid/nodes/Function_Node.h rename fluid/nodes/{Fl_Grid_Type.cxx => Grid_Node.cxx} (70%) create mode 100644 fluid/nodes/Grid_Node.h rename fluid/nodes/{Fl_Group_Type.cxx => Group_Node.cxx} (69%) create mode 100644 fluid/nodes/Group_Node.h rename fluid/nodes/{Fl_Menu_Type.cxx => Menu_Node.cxx} (69%) create mode 100644 fluid/nodes/Menu_Node.h rename fluid/nodes/{Fl_Type.cxx => Node.cxx} (68%) rename fluid/nodes/{Fl_Type.h => Node.h} (70%) create mode 100644 fluid/nodes/Tree.cxx create mode 100644 fluid/nodes/Tree.h create mode 100644 fluid/nodes/Widget_Node.cxx rename fluid/nodes/{Fl_Widget_Type.h => Widget_Node.h} (58%) rename fluid/nodes/{Fl_Window_Type.cxx => Window_Node.cxx} (73%) create mode 100644 fluid/nodes/Window_Node.h create mode 100644 fluid/nodes/callbacks.cxx create mode 100644 fluid/nodes/callbacks.h delete mode 100644 fluid/panels/print_panel.cxx delete mode 100644 fluid/panels/print_panel.fl delete mode 100644 fluid/panels/print_panel.h create mode 100644 fluid/panels/widget_panel/Grid_Child_Tab.cxx create mode 100644 fluid/panels/widget_panel/Grid_Child_Tab.fl create mode 100644 fluid/panels/widget_panel/Grid_Child_Tab.h create mode 100644 fluid/panels/widget_panel/Grid_Tab.cxx create mode 100644 fluid/panels/widget_panel/Grid_Tab.fl create mode 100644 fluid/panels/widget_panel/Grid_Tab.h rename fluid/{app => proj}/align_widget.cxx (63%) rename fluid/{app => proj}/align_widget.h (91%) rename fluid/{app => proj}/mergeback.cxx (88%) rename fluid/{app => proj}/mergeback.h (95%) rename fluid/{app => proj}/undo.cxx (54%) create mode 100644 fluid/proj/undo.h diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index 40f6e3589..bb28c2b9a 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -23,32 +23,41 @@ set(TARGETS fluid) # program fluid properly set(CPPFILES - app/align_widget.cxx - app/Fd_Snap_Action.cxx - app/fluid.cxx - app/Fluid_Image.cxx - app/mergeback.cxx - app/project.cxx + Fluid.cxx + Project.cxx + app/args.cxx + app/Snap_Action.cxx + app/Image_Asset.cxx + app/history.cxx + app/Menu.cxx app/shell_command.cxx - app/undo.cxx + app/templates.cxx io/Code_Writer.cxx io/Project_Writer.cxx io/Project_Reader.cxx + io/String_Writer.cxx + nodes/Tree.cxx + nodes/Button_Node.cxx + nodes/Function_Node.cxx + nodes/Grid_Node.cxx + nodes/Group_Node.cxx + nodes/Menu_Node.cxx + nodes/Node.cxx + nodes/Widget_Node.cxx + nodes/Window_Node.cxx + nodes/callbacks.cxx nodes/factory.cxx - nodes/Fl_Button_Type.cxx - nodes/Fl_Function_Type.cxx - nodes/Fl_Grid_Type.cxx - nodes/Fl_Group_Type.cxx - nodes/Fl_Menu_Type.cxx - nodes/Fl_Type.cxx - nodes/Fl_Widget_Type.cxx - nodes/Fl_Window_Type.cxx panels/about_panel.cxx panels/codeview_panel.cxx panels/function_panel.cxx panels/settings_panel.cxx panels/template_panel.cxx panels/widget_panel.cxx + panels/widget_panel/Grid_Tab.cxx + panels/widget_panel/Grid_Child_Tab.cxx + proj/align_widget.cxx + proj/mergeback.cxx + proj/undo.cxx rsrcs/pixmaps.cxx tools/autodoc.cxx tools/filename.cxx @@ -64,32 +73,41 @@ set(CPPFILES # List header files in Apple's Xcode IDE set(HEADERFILES - app/align_widget.h - app/Fd_Snap_Action.h - app/fluid.h - app/Fluid_Image.h - app/project.h - app/mergeback.h + Fluid.h + Project.h + app/args.h + app/Snap_Action.h + app/Image_Asset.h + app/history.h + app/Menu.h app/shell_command.h - app/undo.h + app/templates.h io/Code_Writer.h io/Project_Writer.h io/Project_Reader.h + io/String_Writer.h + nodes/Tree.h + nodes/Button_Node.h + nodes/Function_Node.h + nodes/Grid_Node.h + nodes/Group_Node.h + nodes/Menu_Node.h + nodes/Node.h + nodes/Widget_Node.h + nodes/Window_Node.h + nodes/callbacks.h nodes/factory.h - nodes/Fl_Button_Type.h - nodes/Fl_Function_Type.h - nodes/Fl_Grid_Type.h - nodes/Fl_Group_Type.h - nodes/Fl_Menu_Type.h - nodes/Fl_Type.h - nodes/Fl_Widget_Type.h - nodes/Fl_Window_Type.h panels/about_panel.h panels/codeview_panel.h panels/function_panel.h panels/settings_panel.h panels/template_panel.h panels/widget_panel.h + panels/widget_panel/Grid_Tab.h + panels/widget_panel/Grid_Child_Tab.h + proj/align_widget.h + proj/mergeback.h + proj/undo.h rsrcs/comments.h rsrcs/pixmaps.h tools/autodoc.h @@ -237,3 +255,16 @@ if(UNIX) ) endforeach() endif(UNIX) + +# Additional warnings during development + +if(APPLE) + if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + target_compile_options(fluid-lib PRIVATE + -Wall -Wextra -Wpedantic -Werror + -Wno-zero-as-null-pointer-constant + -Wno-missing-field-initializers + -Wno-unused-parameter + ) + endif() +endif(APPLE) diff --git a/fluid/Fluid.cxx b/fluid/Fluid.cxx new file mode 100644 index 000000000..48dd7dcfb --- /dev/null +++ b/fluid/Fluid.cxx @@ -0,0 +1,1392 @@ +// +// Fluid Application code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "Fluid.h" + +#include "Project.h" +#include "proj/mergeback.h" +#include "app/Menu.h" +#include "app/shell_command.h" +#include "proj/undo.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" +#include "nodes/Node.h" +#include "nodes/Function_Node.h" +#include "nodes/Group_Node.h" +#include "nodes/Window_Node.h" +#include "nodes/factory.h" +#include "panels/settings_panel.h" +#include "panels/function_panel.h" +#include "panels/codeview_panel.h" +#include "panels/template_panel.h" +#include "panels/about_panel.h" +#include "rsrcs/pixmaps.h" +#include "tools/autodoc.h" +#include "widgets/Node_Browser.h" + +#include +#include +#ifdef __APPLE__ +#include // for fl_open_callback +#endif +#include +#include +#include +#include +#include +#include + +#include // setlocale().. +#include "../src/flstring.h" + + +fld::Application Fluid; + +using namespace fld; + + +/** + Timer to watch for external editor modifications. + + If one or more external editors open, check if their files were modified. + If so: reload to ram, update size/mtime records, and change fluid's + 'modified' state. + */ +static void external_editor_timer(void*) { + int editors_open = ExternalCodeEditor::editors_open(); + if ( Fluid.debug_external_editor ) printf("--- TIMER --- External editors open=%d\n", editors_open); + if ( editors_open > 0 ) { + // Walk tree looking for files modified by external editors. + int modified = 0; + for (Node *p: Fluid.proj.tree.all_nodes()) { + if ( p->is_a(Type::Code) ) { + Code_Node *code = static_cast(p); + // Code changed by external editor? + if ( code->handle_editor_changes() ) { // updates ram, file size/mtime + modified++; + } + if ( code->is_editing() ) { // editor open? + code->reap_editor(); // Try to reap; maybe it recently closed + } + } + } + if ( modified ) Fluid.proj.set_modflag(1); + } + // Repeat timeout if editors still open + // The ExternalCodeEditor class handles start/stopping timer, we just + // repeat_timeout() if it's already on. NOTE: above code may have reaped + // only open editor, which would disable further timeouts. So *recheck* + // if editors still open, to ensure we don't accidentally re-enable them. + // + if ( ExternalCodeEditor::editors_open() ) { + Fl::repeat_timeout(2.0, external_editor_timer); + } +} + + +/** + Create the Fluid application. + This creates the basic app with an empty project and reads the Fluid + preferences database. + */ +Application::Application() +: preferences( Fl_Preferences::USER_L, "fltk.org", "fluid" ) +{ } + + +/** + Start Fluid. + + Fluid can run in interactive mode with a full user interface to design new + user interfaces and write the C++ files to manage them, + + Fluid can run form the command line in batch mode to convert .fl design files + into C++ source and header files. In batch mode, no display is needed, + particularly no X11 connection will be attempted on Linux/Unix. + + \param[in] argc number of arguments in the list + \param[in] argv pointer to an array of arguments + \return in batch mode, an error code will be returned via \c exit() . This + function return 1, if there was an error in the parameters list. + \todo On Windows, Fluid can under certain conditions open a dialog box, even + in batch mode. Is that intentional? Does it circumvent issues with Windows' + stderr and stdout? + */ +int Application::run(int argc,char **argv) { + setlocale(LC_ALL, ""); // enable multi-language errors in file chooser + setlocale(LC_NUMERIC, "C"); // make sure numeric values are written correctly + launch_path_ = end_with_slash(fl_getcwd_str()); // store the current path at launch + + int i = 1; + if ((i = args.load(argc, argv)) == -1) + return 1; + + if (args.show_version) { + printf("fluid v%d.%d.%d\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION); + ::exit(0); + } + + const char *c = nullptr; + if (args.autodoc_path.empty()) + c = argv[i]; + + fl_register_images(); + + make_main_window(); + + if (c) proj.set_filename(c); + if (!batch_mode) { +#ifdef __APPLE__ + fl_open_callback(apple_open_cb); +#endif // __APPLE__ + Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); + Fl_File_Icon::load_system_icons(); + main_window->callback(exit_cb); + position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); + if (g_shell_config) { + g_shell_config->read(preferences, fld::Tool_Store::USER); + g_shell_config->update_settings_dialog(); + g_shell_config->rebuild_shell_menu(); + } + Fluid.layout_list.read(preferences, fld::Tool_Store::USER); + main_window->show(argc,argv); + toggle_widget_bin(); + toggle_codeview_cb(nullptr,nullptr); + if (!c && openlast_button->value() && history.abspath[0][0] && args.autodoc_path.empty()) { + // Open previous file when no file specified... + open_project_file(history.abspath[0]); + } + } + proj.undo.suspend(); + if (c && !fld::io::read_file(proj, c,0)) { + if (batch_mode) { + fprintf(stderr,"%s : %s\n", c, strerror(errno)); + exit(1); + } + fl_message("Can't read %s: %s", c, strerror(errno)); + } + proj.undo.resume(); + + // command line args override code and header filenames from the project file + // in batch mode only + if (batch_mode) { + if (!args.code_filename.empty()) { + proj.code_file_set = 1; + proj.code_file_name = args.code_filename; + } + if (!args.header_filename.empty()) { + proj.header_file_set = 1; + proj.header_file_name = args.header_filename; + } + } + + if (args.update_file) { // fluid -u + fld::io::write_file(proj, c, 0); + if (!args.compile_file) + exit(0); + } + + if (args.compile_file) { // fluid -c[s] + if (args.compile_strings) + proj.write_strings(); + write_code_files(); + exit(0); + } + + // don't lock up if inconsistent command line arguments were given + if (batch_mode) + exit(0); + + proj.set_modflag(0); + proj.undo.clear(); + + // Set (but do not start) timer callback for external editor updates + ExternalCodeEditor::set_update_timer_callback(external_editor_timer); + +#ifndef NDEBUG + // check if the user wants FLUID to generate image for the user documentation + if (!args.autodoc_path.empty()) { + run_autodoc(args.autodoc_path); + proj.set_modflag(0, 0); + quit(); + return 0; + } +#endif + + Fl::run(); + + proj.undo.clear(); + return 0; +} + + +/** + Exit Fluid; we hope you had a nice experience. + If the design was modified, a dialog will ask for confirmation. + */ +void Application::quit() { + if (shell_command_running()) { + int choice = fl_choice("Previous shell command still running!", + "Cancel", + "Exit", + nullptr); + if (choice == 0) { // user chose to cancel the exit operation + return; + } + } + + flush_text_widgets(); + + // verify user intention + if (confirm_project_clear() == false) + return; + + // Stop any external editor update timers + ExternalCodeEditor::stop_update_timer(); + + save_position(main_window,"main_window_pos"); + + if (widgetbin_panel) { + save_position(widgetbin_panel,"widgetbin_pos"); + delete widgetbin_panel; + } + if (codeview_panel) { + Fl_Preferences svp(preferences, "codeview"); + svp.set("autorefresh", cv_autorefresh->value()); + svp.set("autoposition", cv_autoposition->value()); + svp.set("tab", cv_tab->find(cv_tab->value())); + svp.set("code_choice", cv_code_choice); + save_position(codeview_panel,"codeview_pos"); + delete codeview_panel; + codeview_panel = nullptr; + } + if (shell_run_window) { + save_position(shell_run_window,"shell_run_Window_pos"); + } + + if (about_panel) + delete about_panel; + if (help_dialog) + delete help_dialog; + + if (g_shell_config) + g_shell_config->write(preferences, fld::Tool_Store::USER); + Fluid.layout_list.write(preferences, fld::Tool_Store::USER); + + proj.undo.clear(); + + // Destroy tree + // Doing so causes dtors to automatically close all external editors + // and cleans up editor tmp files. Then remove fluid tmpdir /last/. + proj.reset(); + ExternalCodeEditor::tmpdir_clear(); + delete_tmpdir(); + + exit(0); +} + + +/** + Return the working directory path at application launch. + \return a reference to the '/' terminated path. + */ +const std::string &Application::launch_path() const { + return launch_path_; +} + + +/** + Generate a path to a directory for temporary data storage. + \see delete_tmpdir(), get_tmpdir() + \todo remove duplicate API or reuse ExternalCodeEditor::create_tmpdir()! + */ +void Application::create_tmpdir() { + if (tmpdir_create_called) + return; + tmpdir_create_called = true; + + char buf[128]; +#if _WIN32 + // The usual temp file locations on Windows are + // %system%\Windows\Temp + // %userprofiles%\AppData\Local + // usually resolving into + // C:/Windows/Temp/ + // C:\Users\\AppData\Local\Temp + fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); + std::string name = buf; + wchar_t tempdirW[FL_PATH_MAX+1]; + char tempdir[FL_PATH_MAX+1]; + unsigned len = GetTempPathW(FL_PATH_MAX, tempdirW); + if (len == 0) { + strcpy(tempdir, "c:/windows/temp/"); + } else { + unsigned wn = fl_utf8fromwc(tempdir, FL_PATH_MAX, tempdirW, len); + tempdir[wn] = 0; + } + std::string path = tempdir; + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; +#else + fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", getpid()); + std::string name = buf; + auto path_temp = fl_getenv("TMPDIR"); + std::string path = path_temp ? path_temp : ""; + if (!path.empty()) { + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } + if (tmpdir_path.empty()) { + path = std::string("/tmp/") + name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } +#endif + if (tmpdir_path.empty()) { + char pbuf[FL_PATH_MAX+1]; + preferences.get_userdata_path(pbuf, FL_PATH_MAX); + path = std::string(pbuf); + end_with_slash(path); + path += name; + fl_make_path(path.c_str()); + if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; + } + if (tmpdir_path.empty()) { + if (batch_mode) { + fprintf(stderr, "ERROR: Can't create directory for temporary data storage.\n"); + } else { + fl_alert("Can't create directory for temporary data storage."); + } + } +} + + +/** + Delete the temporary directory and all its contents. + \see create_tmpdir(), get_tmpdir() + */ +void Application::delete_tmpdir() { + // was a temporary directory created + if (!tmpdir_create_called) + return; + if (tmpdir_path.empty()) + return; + + // first delete all files that may still be left in the temp directory + struct dirent **de; + int n_de = fl_filename_list(tmpdir_path.c_str(), &de); + if (n_de >= 0) { + for (int i=0; id_name; + fl_unlink(path.c_str()); + } + fl_filename_free_list(&de, n_de); + } + + // then delete the directory itself + if (fl_rmdir(tmpdir_path.c_str()) < 0) { + if (batch_mode) { + fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); + } else { + fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); + } + } +} + + +/** + Return the path to a temporary directory for this instance of Fluid. + Fluid will do its best to clear and delete this directory when exiting. + \return the path to the temporary directory, ending in a '/', or and empty + string if no directory could be created. + */ +const std::string &Application::get_tmpdir() { + if (!tmpdir_create_called) + create_tmpdir(); + return tmpdir_path; +} + + +/** + Return the path and filename of a temporary file for cut or duplicated data. + \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer + \return a pointer to a string in a static buffer + */ +const char *Application::cutfname(int which) { + static char name[2][FL_PATH_MAX]; + static char beenhere = 0; + + if (!beenhere) { + beenhere = 1; + preferences.getUserdataPath(name[0], sizeof(name[0])); + strlcat(name[0], "cut_buffer", sizeof(name[0])); + preferences.getUserdataPath(name[1], sizeof(name[1])); + strlcat(name[1], "dup_buffer", sizeof(name[1])); + } + + return name[which]; +} + + +/** + Clear the current project and create a new, empty one. + + If the current project was modified, FLUID will give the user the opportunity + to save the old project first. + + \param[in] user_must_confirm if set, a confimation dialog is presented to the + user before resetting the project. Default is `true`. + \return false if the operation was canceled + */ +bool Application::new_project(bool user_must_confirm) { + // verify user intention + if ((user_must_confirm) && (confirm_project_clear() == false)) + return false; + + // clear the current project + proj.reset(); + proj.set_filename(nullptr); + proj.set_modflag(0, 0); + widget_browser->rebuild(); + proj.update_settings_dialog(); + + // all is clear to continue + return true; +} + + +/** + Open a file chooser and load an exiting project file. + + If the current project was modified, FLUID will give the user the opportunity + to save the old project first. + + If no filename is given, FLUID will open a file chooser dialog. + + \param[in] filename_arg load from this file, or show file chooser if empty + \return false if the operation was canceled or failed otherwise + */ +bool Application::open_project_file(const std::string &filename_arg) { + // verify user intention + if (confirm_project_clear() == false) + return false; + + // ask for a filename if none was given + std::string new_filename = filename_arg; + if (new_filename.empty()) { + new_filename = open_project_filechooser("Open Project File"); + if (new_filename.empty()) { + return false; + } + } + + // clear the project and merge a file by the given name + new_project(false); + return merge_project_file(new_filename); +} + + +/** + Load a project from the give file name and path. + + The project file is inserted at the currently selected type. + + If no filename is given, FLUID will open a file chooser dialog. + + \param[in] filename_arg path and name of the new project file + \return false if the operation failed + */ +bool Application::merge_project_file(const std::string &filename_arg) { + bool is_a_merge = (!proj.tree.empty()); + std::string title = is_a_merge ? "Merge Project File" : "Open Project File"; + + // ask for a filename if none was given + std::string new_filename = filename_arg; + if (new_filename.empty()) { + new_filename = open_project_filechooser(title); + if (new_filename.empty()) { + return false; + } + } + + const char *c = new_filename.c_str(); + const char *oldfilename = proj.proj_filename; + proj.proj_filename = nullptr; + proj.set_filename(c); + if (is_a_merge) proj.undo.checkpoint(); + proj.undo.suspend(); + if (!fld::io::read_file(proj, c, is_a_merge)) { + proj.undo.resume(); + widget_browser->rebuild(); + proj.update_settings_dialog(); + fl_message("Can't read %s: %s", c, strerror(errno)); + free((void *)proj.proj_filename); + proj.proj_filename = oldfilename; + if (main_window) proj.set_modflag(proj.modflag); + return false; + } + proj.undo.resume(); + widget_browser->rebuild(); + if (is_a_merge) { + // Inserting a file; restore the original filename... + proj.set_filename(oldfilename); + proj.set_modflag(1); + } else { + // Loaded a file; free the old filename... + proj.set_modflag(0, 0); + proj.undo.clear(); + } + if (oldfilename) free((void *)oldfilename); + return true; +} + + +/** + Save the current design to the file given by \c filename. + If automatic, this overwrites an existing file. If interactive, if will + verify with the user. + \param[in] v if v is not nullptr, or no filename is set, open a filechooser. + */ +void Application::save_project_file(void *v) { + flush_text_widgets(); + Fl_Native_File_Chooser fnfc; + const char *c = proj.proj_filename; + if (v || !c || !*c) { + fnfc.title("Save To:"); + fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + fnfc.filter("FLUID Files\t*.f[ld]"); + if (fnfc.show() != 0) return; + c = fnfc.filename(); + if (!fl_access(c, 0)) { + std::string basename = fl_filename_name_str(std::string(c)); + if (fl_choice("The file \"%s\" already exists.\n" + "Do you want to replace it?", "Cancel", + "Replace", nullptr, basename.c_str()) == 0) return; + } + + if (v != (void *)2) proj.set_filename(c); + } + if (!fld::io::write_file(proj, c)) { + fl_alert("Error writing %s: %s", c, strerror(errno)); + return; + } + + if (v != (void *)2) { + proj.set_modflag(0, 1); + proj.undo.save_ = proj.undo.current_; + } +} + + +/** + Reload the file set by \c filename, replacing the current design. + If the design was modified, a dialog will ask for confirmation. + */ +void Application::revert_project() { + if ( proj.modflag) { + if (!fl_choice("This user interface has been changed. Really revert?", + "Cancel", "Revert", nullptr)) return; + } + proj.undo.suspend(); + if (!fld::io::read_file(proj, proj.proj_filename, 0)) { + proj.undo.resume(); + widget_browser->rebuild(); + proj.update_settings_dialog(); + fl_message("Can't read %s: %s", proj.proj_filename, strerror(errno)); + return; + } + widget_browser->rebuild(); + proj.undo.resume(); + proj.set_modflag(0, 0); + proj.undo.clear(); + proj.update_settings_dialog(); +} + + +/** + Open the template browser and load a new file from templates. + + If the current project was modified, FLUID will give the user the opportunity + to save the old project first. + + \return false if the operation was canceled or failed otherwise + */ +bool Application::new_project_from_template() { + // clear the current project first + if (new_project() == false) + return false; + + // Setup the template panel... + if (!template_panel) make_template_panel(); + + template_clear(); + template_browser->add("Blank"); + template_load(); + + template_name->hide(); + template_name->value(""); + + template_instance->show(); + template_instance->deactivate(); + template_instance->value(""); + + template_delete->show(); + + template_submit->label("New"); + template_submit->deactivate(); + + template_panel->label("New"); + + //if ( template_browser->size() == 1 ) { // only one item? + template_browser->value(1); // select it + template_browser->do_callback(); + //} + + // Show the panel and wait for the user to do something... + template_panel->show(); + while (template_panel->shown()) Fl::wait(); + + // See if the user chose anything... + int item = template_browser->value(); + if (item < 1) return false; + + // Load the template, if any... + const char *tname = (const char *)template_browser->data(item); + + if (tname) { + // Grab the instance name... + const char *iname = template_instance->value(); + + if (iname && *iname) { + // Copy the template to a temp file, then read it in... + char line[1024], *ptr, *next; + FILE *infile, *outfile; + + if ((infile = fl_fopen(tname, "rb")) == nullptr) { + fl_alert("Error reading template file \"%s\":\n%s", tname, + strerror(errno)); + proj.set_modflag(0); + proj.undo.clear(); + return false; + } + + if ((outfile = fl_fopen(cutfname(1), "wb")) == nullptr) { + fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), + strerror(errno)); + fclose(infile); + proj.set_modflag(0); + proj.undo.clear(); + return false; + } + + while (fgets(line, sizeof(line), infile)) { + // Replace @INSTANCE@ with the instance name... + for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != nullptr; ptr = next + 10) { + fwrite(ptr, next - ptr, 1, outfile); + fputs(iname, outfile); + } + + fputs(ptr, outfile); + } + + fclose(infile); + fclose(outfile); + + proj.undo.suspend(); + fld::io::read_file(proj, cutfname(1), 0); + fl_unlink(cutfname(1)); + proj.undo.resume(); + } else { + // No instance name, so read the template without replacements... + proj.undo.suspend(); + fld::io::read_file(proj, tname, 0); + proj.undo.resume(); + } + } + + widget_browser->rebuild(); + proj.update_settings_dialog(); + proj.set_modflag(0); + proj.undo.clear(); + + return true; +} + + +/** + Open the dialog to allow the user to print the current window. + */ +void Application::print_snapshots() { + int w, h, ww, hh; + int frompage, topage; + int num_windows = 0; // Number of windows + Window_Node *windows[1000]; // Windows to print + int winpage; // Current window page + Fl_Window *win; + + for (auto w: proj.tree.all_widgets()) { + if (w->is_a(Type::Window)) { + Window_Node *win_t = static_cast(w); + windows[num_windows] = win_t; + Fl_Window *win = static_cast(win_t->o); + if (!win->shown()) continue; + num_windows ++; + } + } + + Fl_Printer printjob; + if ( printjob.start_job(num_windows, &frompage, &topage) ) return; + int pagecount = 0; + for (winpage = 0; winpage < num_windows; winpage++) { + float scale = 1, scale_x = 1, scale_y = 1; + if (winpage+1 < frompage || winpage+1 > topage) continue; + printjob.start_page(); + printjob.printable_rect(&w, &h); + + // Get the time and date... + time_t curtime = time(nullptr); + struct tm *curdate = localtime(&curtime); + char date[1024]; + strftime(date, sizeof(date), "%c", curdate); + fl_font(FL_HELVETICA, 12); + fl_color(FL_BLACK); + fl_draw(date, (w - (int)fl_width(date))/2, fl_height()); + sprintf(date, "%d/%d", ++pagecount, topage-frompage+1); + fl_draw(date, w - (int)fl_width(date), fl_height()); + + // Get the base filename... + std::string basename = fl_filename_name_str(std::string(proj.proj_filename)); + fl_draw(basename.c_str(), 0, fl_height()); + + // print centered and scaled to fit in the page + win = (Fl_Window*)windows[winpage]->o; + ww = win->decorated_w(); + if(ww > w) scale_x = float(w)/ww; + hh = win->decorated_h(); + if(hh > h) scale_y = float(h)/hh; + if (scale_x < scale) scale = scale_x; + if (scale_y < scale) scale = scale_y; + if (scale < 1) { + printjob.scale(scale); + printjob.printable_rect(&w, &h); + } + printjob.origin(w/2, h/2); + printjob.print_window(win, -ww/2, -hh/2); + printjob.end_page(); + } + printjob.end_job(); +} + + +/** + Generate the C++ source and header filenames and write those files. + + This function creates the source filename by setting the file + extension to \c code_file_name and a header filename + with the extension \c header_file_name which are both + settable by the user. + + If the code filename has not been set yet, a "save file as" dialog will be + presented to the user. + + In batch_mode, the function will either be silent, or, if opening or writing + the files fails, write an error message to \c stderr and exit with exit code 1. + + In interactive mode, it will pop up an error message, or, if the user + hasn't disabled that, pop up a confirmation message. + + \param[in] dont_show_completion_dialog don't show the completion dialog + \return 1 if the operation failed, 0 if it succeeded + */ +int Application::write_code_files(bool dont_show_completion_dialog) +{ + // -- handle user interface issues + flush_text_widgets(); + if (!proj.proj_filename) { + save_project_file(nullptr); + if (!proj.proj_filename) return 1; + } + + // -- generate the file names with absolute paths + fld::io::Code_Writer f(proj); + std::string code_filename = proj.codefile_path() + proj.codefile_name(); + std::string header_filename = proj.headerfile_path() + proj.headerfile_name(); + + // -- write the code and header files + if (!batch_mode) proj.enter_project_dir(); + int x = f.write_code(code_filename.c_str(), header_filename.c_str()); + std::string code_filename_rel = fl_filename_relative_str(code_filename); + std::string header_filename_rel = fl_filename_relative_str(header_filename); + if (!batch_mode) proj.leave_project_dir(); + + // -- print error message in batch mode or pop up an error or confirmation dialog box + if (batch_mode) { + if (!x) { + fprintf(stderr, "%s and %s: %s\n", + code_filename_rel.c_str(), + header_filename_rel.c_str(), + strerror(errno)); + exit(1); + } + } else { + if (!x) { + fl_message("Can't write %s or %s: %s", + code_filename_rel.c_str(), + header_filename_rel.c_str(), + strerror(errno)); + } else { + proj.set_modflag(-1, 0); + if (dont_show_completion_dialog==false && completion_button->value()) { + fl_message("Wrote %s and %s", + code_filename_rel.c_str(), + header_filename_rel.c_str()); + } + } + } + return 0; +} + + +/** + User chose to cut the currently selected widgets. + */ +void Application::cut_selected() { + if (!proj.tree.current) { + fl_beep(); + return; + } + flush_text_widgets(); + if (!fld::io::write_file(proj, cutfname(),1)) { + fl_message("Can't write %s: %s", cutfname(), strerror(errno)); + return; + } + proj.undo.checkpoint(); + proj.set_modflag(1); + ipasteoffset = 0; + Node *p = proj.tree.current->parent; + while (p && p->selected) p = p->parent; + delete_all(1); + if (p) select_only(p); + widget_browser->rebuild(); +} + + +/** + User chose to copy the currently selected widgets. + */ +void Application::copy_selected() { + flush_text_widgets(); + if (!proj.tree.current) { + fl_beep(); + return; + } + flush_text_widgets(); + ipasteoffset = 10; + if (!fld::io::write_file(proj, cutfname(),1)) { + fl_message("Can't write %s: %s", cutfname(), strerror(errno)); + return; + } +} + + +/** + User chose to paste the widgets from the cut buffer. + + This function will paste the widgets in the cut buffer after the currently + selected widget. If the currently selected widget is a group widget and + it is not folded, the new widgets will be added inside the group. + */ +void Application::paste_from_clipboard() { + pasteoffset = ipasteoffset; + proj.undo.checkpoint(); + proj.undo.suspend(); + Strategy strategy = Strategy::FROM_FILE_AFTER_CURRENT; + if (proj.tree.current && proj.tree.current->can_have_children()) { + if (proj.tree.current->folded_ == 0) { + // If the current widget is a group widget and it is not folded, + // add the new widgets inside the group. + strategy = Strategy::FROM_FILE_AS_LAST_CHILD; + // The following alternative also works quite nicely + //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD; + } + } + if (!fld::io::read_file(proj, cutfname(), 1, strategy)) { + widget_browser->rebuild(); + fl_message("Can't read %s: %s", cutfname(), strerror(errno)); + } + proj.undo.resume(); + widget_browser->display(proj.tree.current); + widget_browser->rebuild(); + pasteoffset = 0; + ipasteoffset += 10; +} + + +/** + Duplicate the selected widgets. + + This code is a bit complex because it needs to find the last selected + widget with the lowest level, so that the new widgets are inserted after + this one. + */ +void Application::duplicate_selected() { + if (!proj.tree.current) { + fl_beep(); + return; + } + + // flush the text widgets to make sure the user's changes are saved: + flush_text_widgets(); + + // find the last selected node with the lowest level: + int lowest_level = 9999; + Node *new_insert = nullptr; + if (proj.tree.current->selected) { + for (auto t: proj.tree.all_selected_nodes()) { + if (t->level <= lowest_level) { + lowest_level = t->level; + new_insert = t; + } + } + } + if (new_insert) + proj.tree.current = new_insert; + + // write the selected widgets to a file: + if (!fld::io::write_file(proj, cutfname(1),1)) { + fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); + return; + } + + // read the file and add the widgets after the current one: + pasteoffset = 0; + proj.undo.checkpoint(); + proj.undo.suspend(); + if (!fld::io::read_file(proj, cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { + fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); + } + fl_unlink(cutfname(1)); + widget_browser->display(proj.tree.current); + widget_browser->rebuild(); + proj.undo.resume(); +} + + +/** + User chose to delete the currently selected widgets. + */ +void Application::delete_selected() { + if (!proj.tree.current) { + fl_beep(); + return; + } + proj.undo.checkpoint(); + proj.set_modflag(1); + ipasteoffset = 0; + Node *p = proj.tree.current->parent; + while (p && p->selected) p = p->parent; + delete_all(1); + if (p) select_only(p); + widget_browser->rebuild(); +} + + +/** + Show the editor for the \c current Node. + */ +void Application::edit_selected() { + if (!proj.tree.current) { + fl_message("Please select a widget"); + return; + } + proj.tree.current->open(); +} + + +/** + User wants to sort selected widgets by y coordinate. + */ +void Application::sort_selected() { + proj.undo.checkpoint(); + sort((Node*)nullptr); + widget_browser->rebuild(); + proj.set_modflag(1); +} + + +/** + Show or hide the widget bin. + The state is stored in the app preferences. + */ +void Application::toggle_widget_bin() { + if (!widgetbin_panel) { + make_widgetbin(); + if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; + } + + if (widgetbin_panel->visible()) { + widgetbin_panel->hide(); + widgetbin_item->label("Show Widget &Bin..."); + } else { + widgetbin_panel->show(); + widgetbin_item->label("Hide Widget &Bin"); + } +} + + +/** + Open a dialog to show the HTML help page form the FLTK documentation folder. + \param[in] name name of the HTML help file. + */ +void Application::show_help(const char *name) { + const char *docdir; + char helpname[FL_PATH_MAX]; + + if (!help_dialog) help_dialog = new Fl_Help_Dialog(); + + if ((docdir = fl_getenv("FLTK_DOCDIR")) == nullptr) { + docdir = FLTK_DOCDIR; + } + snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); + + // make sure that we can read the file + FILE *f = fopen(helpname, "rb"); + if (f) { + fclose(f); + help_dialog->load(helpname); + } else { + // if we can not read the file, we display the canned version instead + // or ask the native browser to open the page on www.fltk.org + if (strcmp(name, "fluid.html")==0) { + if (!Fl_Shared_Image::find("embedded:/fluid_flow_chart_800.png")) + new Fl_PNG_Image("embedded:/fluid_flow_chart_800.png", fluid_flow_chart_800_png, sizeof(fluid_flow_chart_800_png)); + help_dialog->value + ( + "\n" + "FLTK: Programming with FLUID\n" + "

What is FLUID?

\n" + "The Fast Light User Interface Designer, or FLUID, is a graphical editor " + "that is used to produce FLTK source code. FLUID edits and saves its state " + "in .fl files. These files are text, and you can (with care) " + "edit them in a text editor, perhaps to get some special effects.

\n" + "FLUID can \"compile\" the .fl file into a .cxx " + "and a .h file. The .cxx file defines all the " + "objects from the .fl file and the .h file " + "declares all the global ones. FLUID also supports localization " + "(Internationalization) of label strings using message files and the GNU " + "gettext or POSIX catgets interfaces.

\n" + "A simple program can be made by putting all your code (including a " + "main() function) into the .fl file and thus making the " + ".cxx file a single source file to compile. Most programs are " + "more complex than this, so you write other .cxx files that " + "call the FLUID functions. These .cxx files must " + "#include the .h file or they can #include " + "the .cxx file so it still appears to be a single source file.

" + "

" + "

More information is available online at https://www.fltk.org/" + "" + ); + } else if (strcmp(name, "license.html")==0) { + fl_open_uri("https://www.fltk.org/doc-1.5/license.html"); + return; + } else if (strcmp(name, "index.html")==0) { + fl_open_uri("https://www.fltk.org/doc-1.5/index.html"); + return; + } else { + snprintf(helpname, sizeof(helpname), "https://www.fltk.org/%s", name); + fl_open_uri(helpname); + return; + } + } + help_dialog->show(); +} + + +/** + Open the "About" dialog. + */ +void Application::about() { +#if 1 + if (!about_panel) make_about_panel(); + about_panel->show(); +#else + for (auto &n: proj.tree.all_nodes()) { + puts(n.name()); + } +#endif +} + + +/** + Build the main app window and create a few other dialogs. + */ +void Application::make_main_window() { + if (!batch_mode) { + preferences.get("show_guides", show_guides, 1); + preferences.get("show_restricted", show_restricted, 1); + preferences.get("show_ghosted_outline", show_ghosted_outline, 0); + preferences.get("show_comments", show_comments, 1); + make_shell_window(); + } + + if (!main_window) { + Fl_Widget *o; + loadPixmaps(); + main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); + main_window->box(FL_NO_BOX); + o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); + o->box(FL_FLAT_BOX); + o->tooltip("Double-click to view or change an item."); + main_window->resizable(o); + main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); + main_menubar->menu(main_menu); + // quick access to all dynamic menu items + save_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_save_cb); + history_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_open_history_cb); + widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb); + codeview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_codeview_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); + restricted_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_restricted); + main_menubar->global(); + fill_in_New_Menu(); + main_window->end(); + } + + if (!batch_mode) { + history.load(); + g_shell_config = new Fd_Shell_Command_List; + widget_browser->load_prefs(); + make_settings_window(); + } +} + + +/** + Open a native file chooser to allow choosing a project file for reading. + + Path and filename are preset with the current project filename, if there + is one. + + \param title a text describing the action after selecting a file (load, merge, ...) + \return the file path and name, or an empty string if the operation was canceled + */ +std::string Application::open_project_filechooser(const std::string &title) { + Fl_Native_File_Chooser dialog; + dialog.title(title.c_str()); + dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); + dialog.filter("FLUID Files\t*.f[ld]\n"); + if (proj.proj_filename) { + std::string current_project_file = proj.proj_filename; + dialog.directory(fl_filename_path_str(current_project_file).c_str()); + dialog.preset_file(fl_filename_name_str(current_project_file).c_str()); + } + if (dialog.show() != 0) + return std::string(); + return std::string(dialog.filename()); +} + + +/** + Give the user the opportunity to save a project before clearing it. + + If the project has unsaved changes, this function pops up a dialog, that + allows the user to save the project, continue without saving the project, + or to cancel the operation. + + If the user chooses to save, and no filename was set, a file dialog allows + the user to pick a name and location, or to cancel the operation. + + \return false if the user aborted the operation and the calling function + should abort as well + */ +bool Application::confirm_project_clear() { + if (proj.modflag == 0) return true; + switch (fl_choice("This project has unsaved changes. Do you want to save\n" + "the project file before proceeding?", + "Cancel", "Save", "Don't Save")) + { + case 0 : /* Cancel */ + return false; + case 1 : /* Save */ + save_project_file(nullptr); + if (proj.modflag) return false; // user canceled the "Save As" dialog + } + return true; +} + + +/** + Ensure that text widgets in the widget panel propagates apply current changes. + By temporarily clearing the text focus, all text widgets with changed text + will unfocus and call their respective callbacks, propagating those changes to + their data set. + */ +void Application::flush_text_widgets() { + if (Fl::focus() && (Fl::focus()->top_window() == the_panel)) { + Fl_Widget *old_focus = Fl::focus(); + Fl::focus(nullptr); // trigger callback of the widget that is losing focus + Fl::focus(old_focus); + } +} + + +/** + Position the given window window based on entries in the app preferences. + Customisable by user; feature can be switched off. + The window is not shown or hidden by this function, but a value is returned + to indicate the state to the caller. + \param[in] w position this window + \param[in] prefsName name of the preferences item that stores the window settings + \param[in] Visible default value if window is hidden or shown + \param[in] X, Y, W, H default size and position if nothing is specified in the preferences + \return 1 if the caller should make the window visible, 0 if hidden. + */ +char Application::position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) { + Fl_Preferences pos(preferences, prefsName); + if (prevpos_button->value()) { + pos.get("x", X, X); + pos.get("y", Y, Y); + if ( W!=0 ) { + pos.get("w", W, W); + pos.get("h", H, H); + w->resize( X, Y, W, H ); + } + else + w->position( X, Y ); + } + pos.get("visible", Visible, Visible); + return Visible; +} + + +/** + Save the position and visibility state of a window to the app preferences. + \param[in] w save this window data + \param[in] prefsName name of the preferences item that stores the window settings + */ +void Application::save_position(Fl_Window *w, const char *prefsName) { + Fl_Preferences pos(preferences, prefsName); + pos.set("x", w->x()); + pos.set("y", w->y()); + pos.set("w", w->w()); + pos.set("h", w->h()); + pos.set("visible", (int)(w->shown() && w->visible())); +} + + +/** + Change the app's and hence preview the design's scheme. + + The scheme setting is stored in the app preferences + - in key \p 'scheme_name' since 1.4.0 + - in key \p 'scheme' (index: 0 - 4) in 1.3.x + + This callback is triggered by changing the scheme in the + Fl_Scheme_Choice widget (\p Edit/GUI Settings). + + \param[in] choice the calling widget + + \see init_scheme() for choice values and backwards compatibility + */ +void Application::set_scheme(const char *new_scheme) { + if (batch_mode) + return; + + // set the new scheme only if the scheme was changed + if (Fl::is_scheme(new_scheme)) + return; + + Fl::scheme(new_scheme); + preferences.set("scheme_name", new_scheme); + + // Backwards compatibility: store 1.3 scheme index (1-4). + // We assume that index 0-3 (base, plastic, gtk+, gleam) are in the + // same order as in 1.3.x (index 1-4), higher values are ignored + + int scheme_index = scheme_choice->value(); + if (scheme_index <= 3) // max. index for 1.3.x (Gleam) + preferences.set("scheme", scheme_index + 1); // compensate for different indexing +} + + +/** + Read Fluid's scheme preferences and set the app's scheme. + + Since FLTK 1.4.0 the scheme \b name is stored as a character string + with key "scheme_name" in the preference database. + + In FLTK 1.3.x the scheme preference was stored as an integer index + with key "scheme" in the database. The known schemes were hardcoded in + Fluid's sources (here for reference): + + | Index | 1.3 Scheme Name | Choice | 1.4 Scheme Name | + |-------|-----------------|-------|-----------------| + | 0 | Default (same as None) | n/a | n/a | + | 1 | None (same as Default) | 0 | base | + | 2 | Plastic | 1 | plastic | + | 3 | GTK+ | 2 | gtk+ | + | 4 | Gleam | 3 | gleam | + | n/a | n/a | 4 | oxy | + + The new Fluid tries to keep backwards compatibility and reads both + keys (\p scheme and \p scheme_name). If the latter is defined, it is used. + If not the old \p scheme (index) is used - but we need to subtract one to + get the new Fl_Scheme_Choice index (column "Choice" above). + */ +void Application::init_scheme() { + int scheme_index = 0; // scheme index for backwards compatibility (1.3.x) + char *scheme_name = nullptr; // scheme name since 1.4.0 + preferences.get("scheme_name", scheme_name, "XXX"); // XXX means: not set => fallback 1.3.x + if (!strcmp(scheme_name, "XXX")) { + preferences.get("scheme", scheme_index, 0); + if (scheme_index > 0) { + scheme_index--; + scheme_choice->value(scheme_index); // set the choice value + } + if (scheme_index < 0) + scheme_index = 0; + else if (scheme_index > scheme_choice->size() - 1) + scheme_index = 0; + scheme_name = const_cast(scheme_choice->text(scheme_index)); + preferences.set("scheme_name", scheme_name); + } + // Set the new scheme only if it was not overridden by the -scheme + // command line option + if (Fl::scheme() == nullptr) { + Fl::scheme(scheme_name); + } + free(scheme_name); +} + + +#ifdef __APPLE__ +/** + Handle app launch with an associated filename (macOS only). + Should there be a modified design already, Fluid asks for user confirmation. + \param[in] c the filename of the new design + */ +void Application::apple_open_cb(const char *c) { + Fluid.open_project_file(std::string(c)); +} +#endif // __APPLE__ + diff --git a/fluid/Fluid.h b/fluid/Fluid.h new file mode 100644 index 000000000..1857518ee --- /dev/null +++ b/fluid/Fluid.h @@ -0,0 +1,219 @@ +// +// Fluid Application header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_FLUID_H +#define FLUID_FLUID_H + +#include "Project.h" +#include "app/args.h" +#include "app/history.h" +#include "app/Snap_Action.h" +#include "tools/filename.h" + +#include +#include +#include + +#include + +constexpr int BROWSERWIDTH = 300; +constexpr int BROWSERHEIGHT = 500; +constexpr int WINWIDTH = 300; +constexpr int MENUHEIGHT = 25; +constexpr int WINHEIGHT = (BROWSERHEIGHT+MENUHEIGHT); + +// ---- types + +class Fl_Double_Window; +class Fl_Window; +class Fl_Menu_Bar; +class Node; +class Fl_Choice; +class Fl_Button; +class Fl_Check_Button; +class Fl_Help_Dialog; + +namespace fld { +namespace app { +class Layout_List; +} + +/** + Indicate the storage location for tools like layout suites and shell macros. + \see class Fd_Shell_Command, class Layout_Suite + */ +enum class Tool_Store { + INTERNAL, ///< stored inside FLUID app + USER, ///< suite is stored in the user wide FLUID settings + PROJECT, ///< suite is stored within the current .fl project file + FILE ///< store suite in external file +}; + + +class Project; + +class Application { + /// Currently selected project. + Project *current_project_ = new Project(); + /// Working directory at application launch. + std::string launch_path_; + /// Path to store temporary files during app run. + std::string tmpdir_path; + /// True if the temporary file path was already created. + bool tmpdir_create_called = false; + // Generate a path to a directory for temporary data storage. + void create_tmpdir(); + // Delete the temporary directory and all its contents. + void delete_tmpdir(); + +public: // Member Variables + /// Application wide preferences + Fl_Preferences preferences; + /// Project history. + app::History history; + /// Command line arguments + app::Args args; + /// List of available layouts + app::Layout_List layout_list; + /// Set, if Fluid runs in batch mode, and no user interface is activated. + int batch_mode { 0 }; // fluid + any code generators (-u, -c, -cs) + + // TODO: make this into a class: app::Settings + /// Show guides in the design window when positioning widgets, saved in app preferences. + int show_guides { 1 }; + /// Show areas of restricted use in overlay plane. + /// Restricted areas are widget that overlap each other, widgets that are outside + /// of their parent's bounds (except children of Scroll groups), and areas + /// within an Fl_Tile that are not covered by children. + int show_restricted { 1 }; + /// Show a ghosted outline for groups that have very little contrast. + /// This makes groups with NO_BOX or FLAT_BOX better editable. + int show_ghosted_outline { 1 }; + /// Show widget comments in the browser, saved in app preferences. + int show_comments { 1 }; + + // TODO: make this into a class: app::External_Editor + /// Use external editor for editing Code_Node, saved in app preferences. + int use_external_editor { 0 }; + /// Debugging help for external Code_Node editor. + int debug_external_editor { 0 }; + /// Run this command to load an Code_Node into an external editor, save in app preferences. + // TODO: make this into a std::string + char external_editor_command[512] { }; + + // TODO: make this into a class: app::GUI + Fl_Window *main_window { nullptr }; + static Fl_Menu_Item main_menu[]; + Fl_Menu_Bar *main_menubar { nullptr }; + Fl_Menu_Item *save_item { nullptr }; + Fl_Menu_Item *history_item { nullptr }; + Fl_Menu_Item *widgetbin_item { nullptr }; + Fl_Menu_Item *codeview_item { nullptr }; + Fl_Menu_Item *overlay_item { nullptr }; + Fl_Button *overlay_button { nullptr }; + Fl_Menu_Item *guides_item { nullptr }; + Fl_Menu_Item *restricted_item { nullptr }; + /// Offset in pixels when adding widgets from an .fl file. + int pasteoffset { 0 }; + int ipasteoffset { 0 }; + /// FLUID-wide help dialog. + Fl_Help_Dialog *help_dialog { nullptr }; + +public: // Methods + // Create the Fluid application. + Application(); + /// Destructor. + ~Application() = default; + // Launch the application. + int run(int argc,char **argv); + // Quit the application and clean up. + void quit(); + /// Quick access to the current project. Make sure it stays synched to current_project_. + Project &proj { *current_project_ }; + // Return the working directory path at application launch. + const std::string &launch_path() const; + // Return the path to a temporary directory for this instance of Fluid. + const std::string &get_tmpdir(); + // Return the path and filename of a temporary file for cut or duplicated data. + const char *cutfname(int which = 0); + + // Clear the current project and create a new, empty one. + bool new_project(bool user_must_confirm = true); + // Open a file chooser and load an exiting project file. + bool open_project_file(const std::string &filename_arg); + // Load a project from the give file name and path. + bool merge_project_file(const std::string &filename_arg); + // Save the current design to the file given by \c filename. + void save_project_file(void *arg); + // Reload the file set by \c filename, replacing the current design. + void revert_project(); + // Open the template browser and load a new file from templates. + bool new_project_from_template(); + // Open the dialog to allow the user to print the current window. + void print_snapshots(); + // Generate the C++ source and header filenames and write those files. + int write_code_files(bool dont_show_completion_dialog=false); + + // User chose to cut the currently selected widgets. + void cut_selected(); + // User chose to copy the currently selected widgets. + void copy_selected(); + // User chose to paste the widgets from the cut buffer. + void paste_from_clipboard(); + // Duplicate the selected widgets. + void duplicate_selected(); + // User chose to delete the currently selected widgets. + void delete_selected(); + // Show the editor for the \c current Node. + void edit_selected(); + // User wants to sort selected widgets by y coordinate. + void sort_selected(); + // Show or hide the widget bin. + void toggle_widget_bin(); + // Open a dialog to show the HTML help page form the FLTK documentation folder. + void show_help(const char *name); + // Open the "About" dialog. + void about(); + + // Build the main app window and create a few other dialogs. + void make_main_window(); + // Open a native file chooser to allow choosing a project file for reading. + std::string open_project_filechooser(const std::string &title); + // Give the user the opportunity to save a project before clearing it. + bool confirm_project_clear(); + // Ensure that text widgets in the widget panel propagates apply current changes. + void flush_text_widgets(); + // Position the given window window based on entries in the app preferences. + char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0); + // Save the position and visibility state of a window to the app preferences. + void save_position(Fl_Window *w, const char *prefsName); + // Change the app's and hence preview the design's scheme. + void set_scheme(const char *new_scheme); + // Read Fluid's scheme preferences and set the app's scheme. + void init_scheme(); + +#ifdef __APPLE__ + static void apple_open_cb(const char *c); +#endif // __APPLE__ +}; + +} // namespace fld + +extern fld::Application Fluid; + + +#endif // FLUID_FLUID_H + diff --git a/fluid/Project.cxx b/fluid/Project.cxx new file mode 100644 index 000000000..9eb555299 --- /dev/null +++ b/fluid/Project.cxx @@ -0,0 +1,335 @@ +// +// Fluid Project code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "Project.h" + +#include "io/String_Writer.h" +#include "nodes/Node.h" +#include "panels/settings_panel.h" +#include "panels/codeview_panel.h" + +using namespace fld; + +// ---- project settings + +/** + Initialize a new project. + */ +Project::Project() { +} + +/** + Clear all project resources. + Not implemented. + */ +Project::~Project() { +} + +/** + Reset all project setting to create a new empty project. + */ +void Project::reset() { + ::delete_all(); + i18n_type = fld::I18n_Type::NONE; + + i18n_gnu_include = ""; + i18n_gnu_conditional = ""; + i18n_gnu_function = "gettext"; + i18n_gnu_static_function = "gettext_noop"; + + i18n_pos_include = ""; + i18n_pos_conditional = ""; + i18n_pos_file = ""; + i18n_pos_set = "1"; + + include_H_from_C = 1; + use_FL_COMMAND = 0; + utf8_in_src = 0; + avoid_early_includes = 0; + header_file_set = 0; + code_file_set = 0; + header_file_name = ".h"; + code_file_name = ".cxx"; + write_mergeback_data = 0; +} + +/** + Tell the project and i18n tab of the settings dialog to refresh themselves. + */ +void Project::update_settings_dialog() { + if (settings_window) { + w_settings_project_tab->do_callback(w_settings_project_tab, LOAD); + w_settings_i18n_tab->do_callback(w_settings_i18n_tab, LOAD); + } +} + +/** + Get the absolute path of the project file, for example `/Users/matt/dev/`. + \return the path ending in '/' + */ +std::string Project::projectfile_path() const { + return end_with_slash(fl_filename_absolute_str(fl_filename_path_str(proj_filename), Fluid.launch_path())); +} + +/** + Get the project file name including extension, for example `test.fl`. + \return the file name without path + */ +std::string Project::projectfile_name() const { + return fl_filename_name(proj_filename); +} + +/** + Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' + */ +std::string Project::codefile_path() const { + std::string path = fl_filename_path_str(code_file_name); + if (Fluid.batch_mode) + return end_with_slash(fl_filename_absolute_str(path, Fluid.launch_path())); + else + return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); +} + +/** + Get the generated C++ code file name including extension, for example `test.cxx`. + \return the file name without path + */ +std::string Project::codefile_name() const { + std::string name = fl_filename_name_str(code_file_name); + if (name.empty()) { + return fl_filename_setext_str(fl_filename_name(proj_filename), ".cxx"); + } else if (name[0] == '.') { + return fl_filename_setext_str(fl_filename_name(proj_filename), code_file_name); + } else { + return name; + } +} + +/** + Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. + \return the path ending in '/' + */ +std::string Project::headerfile_path() const { + std::string path = fl_filename_path_str(header_file_name); + if (Fluid.batch_mode) + return end_with_slash(fl_filename_absolute_str(path, Fluid.launch_path())); + else + return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); +} + +/** + Get the generated C++ header file name including extension, for example `test.cxx`. + \return the file name without path + */ +std::string Project::headerfile_name() const { + std::string name = fl_filename_name_str(header_file_name); + if (name.empty()) { + return fl_filename_setext_str(fl_filename_name_str(proj_filename), ".h"); + } else if (name[0] == '.') { + return fl_filename_setext_str(fl_filename_name_str(proj_filename), header_file_name); + } else { + return name; + } +} + +/** + Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. + Although it may be more useful to put the text file into the same directory + with the source and header file, historically, the text is always saved with + the project file in interactive mode, and in the FLUID launch directory in + batch mode. + \return the path ending in '/' + */ +std::string Project::stringsfile_path() const { + if (Fluid.batch_mode) + return Fluid.launch_path(); + else + return projectfile_path(); +} + +/** + Get the generated i18n text file name including extension, for example `test.po`. + \return the file name without path + */ +std::string Project::stringsfile_name() const { + switch (i18n_type) { + default: return fl_filename_setext_str(fl_filename_name(proj_filename), ".txt"); + case fld::I18n_Type::GNU: return fl_filename_setext_str(fl_filename_name(proj_filename), ".po"); + case fld::I18n_Type::POSIX: return fl_filename_setext_str(fl_filename_name(proj_filename), ".msg"); + } +} + +/** + Get the name of the project file without the filename extension. + \return the file name without path or extension + */ +std::string Project::basename() const { + return fl_filename_setext_str(fl_filename_name(proj_filename), ""); +} + + +/** + Change the current working directory to the .fl project directory. + + Every call to enter_project_dir() must have a corresponding leave_project_dir() + call. Enter and leave calls can be nested. + + The first call to enter_project_dir() remembers the original directory, usually + the launch directory of the application. Nested calls will increment a nesting + counter. When the nesting counter is back to 0, leave_project_dir() will return + to the original directory. + + The global variable 'filename' must be set to the current project file with + absolute or relative path information. + + \see leave_project_dir(), pwd, in_project_dir + */ +void Project::enter_project_dir() { + if (in_project_dir<0) { + fprintf(stderr, "** Fluid internal error: enter_project_dir() calls unmatched\n"); + return; + } + in_project_dir++; + // check if we are already in the project dir and do nothing if so + if (in_project_dir>1) return; + // check if there is an active project, and do nothing if there is none + if (!proj_filename || !*proj_filename) { + fprintf(stderr, "** Fluid internal error: enter_project_dir() no filename set\n"); + return; + } + // store the current working directory for later + app_work_dir = fl_getcwd_str(); + // set the current directory to the path of our .fl file + std::string project_path = fl_filename_path_str(fl_filename_absolute_str(proj_filename)); + if (fl_chdir(project_path.c_str()) == -1) { + fprintf(stderr, "** Fluid internal error: enter_project_dir() can't chdir to %s: %s\n", + project_path.c_str(), strerror(errno)); + return; + } + //fprintf(stderr, "chdir from %s to %s\n", app_work_dir.c_str(), fl_getcwd().c_str()); +} + +/** + Change the current working directory to the previous directory. + \see enter_project_dir(), pwd, in_project_dir + */ +void Project::leave_project_dir() { + if (in_project_dir == 0) { + fprintf(stderr, "** Fluid internal error: leave_project_dir() calls unmatched\n"); + return; + } + in_project_dir--; + // still nested, stay in the project directory + if (in_project_dir > 0) return; + // no longer nested, return to the original, usually the application working directory + if (fl_chdir(app_work_dir.c_str()) < 0) { + fprintf(stderr, "** Fluid internal error: leave_project_dir() can't chdir back to %s : %s\n", + app_work_dir.c_str(), strerror(errno)); + } +} + +/** + Set the filename of the current .fl design. + \param[in] c the new absolute filename and path + */ +void Project::set_filename(const char *c) { + if (proj_filename) free((void *)proj_filename); + proj_filename = c ? fl_strdup(c) : nullptr; + + if (proj_filename && !Fluid.batch_mode) + Fluid.history.update(proj_filename); + + set_modflag(modflag); +} + +/** + Write the strings that are used in i18n. + */ +void Project::write_strings() { + Fluid.flush_text_widgets(); + if (!proj_filename) { + Fluid.save_project_file(nullptr); + if (!proj_filename) return; + } + std::string filename = stringsfile_path() + stringsfile_name(); + int x = fld::io::write_strings(*this, filename); + if (Fluid.batch_mode) { + if (x) { + fprintf(stderr, "%s : %s\n", filename.c_str(), strerror(errno)); + exit(1); + } + } else { + if (x) { + fl_message("Can't write %s: %s", filename.c_str(), strerror(errno)); + } else if (completion_button->value()) { + fl_message("Wrote %s", stringsfile_name().c_str()); + } + } +} + + +/** + Set the "modified" flag and update the title of the main window. + + The first argument sets the modification state of the current design against + the corresponding .fl design file. Any change to the widget tree will mark + the design 'modified'. Saving the design will mark it clean. + + The second argument is optional and set the modification state of the current + design against the source code and header file. Any change to the tree, + including saving the tree, will mark the code 'outdated'. Generating source + code and header files will clear this flag until the next modification. + + \param[in] mf 0 to clear the modflag, 1 to mark the design "modified", -1 to + ignore this parameter + \param[in] mfc default -1 to let \c mf control \c modflag_c, 0 to mark the + code files current, 1 to mark it out of date. -2 to ignore changes to mf. + */ +void Project::set_modflag(int mf, int mfc) { + const char *code_ext = nullptr; + char new_title[FL_PATH_MAX]; + + // Update the modflag_c to the worst possible condition. We could be a bit + // more graceful and compare modification times of the files, but C++ has + // no API for that until C++17. + if (mf!=-1) { + modflag = mf; + if (mfc==-1 && mf==1) + mfc = mf; + } + if (mfc>=0) { + modflag_c = mfc; + } + + if (Fluid.main_window) { + std::string basename; + if (!proj_filename) basename = "Untitled.fl"; + else basename = fl_filename_name_str(std::string(proj_filename)); + code_ext = fl_filename_ext(code_file_name.c_str()); + char mod_star = modflag ? '*' : ' '; + char mod_c_star = modflag_c ? '*' : ' '; + snprintf(new_title, sizeof(new_title), "%s%c %s%c", + basename.c_str(), mod_star, code_ext, mod_c_star); + const char *old_title = Fluid.main_window->label(); + // only update the title if it actually changed + if (!old_title || strcmp(old_title, new_title)) + Fluid.main_window->copy_label(new_title); + } + // if the UI was modified in any way, update the Code View panel + if (codeview_panel && codeview_panel->visible() && cv_autorefresh->value()) + codeview_defer_update(); +} diff --git a/fluid/app/project.h b/fluid/Project.h similarity index 55% rename from fluid/app/project.h rename to fluid/Project.h index 058ce1764..e60f7bc26 100644 --- a/fluid/app/project.h +++ b/fluid/Project.h @@ -1,5 +1,5 @@ // -// FLUID main entry for the Fast Light Tool Kit (FLTK). +// Fluid Project header for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -15,29 +15,107 @@ // -#ifndef FLUID_APP_PROJECT_H -#define FLUID_APP_PROJECT_H +#ifndef FLUID_PROJECT_H +#define FLUID_PROJECT_H + +#include "proj/undo.h" +#include "nodes/Tree.h" #include // ---- project class declaration + +namespace fld { + +namespace app { + class Layout_Preset; + extern Layout_Preset *default_layout_preset; +} // namespace app + /** Enumeration of available internationalization types. */ -typedef enum { - FD_I18N_NONE = 0, ///< No i18n, all strings are litearals - FD_I18N_GNU, ///< GNU gettext internationalization - FD_I18N_POSIX ///< Posix catgets internationalization -} Fd_I18n_Type; +enum class I18n_Type { + NONE = 0, ///< No i18n, all strings are litearals + GNU, ///< GNU gettext internationalization + POSIX ///< Posix catgets internationalization +}; + /** Data and settings for a FLUID project file. */ -class Fluid_Project { -public: - Fluid_Project(); - ~Fluid_Project(); +class Project +{ +public: // Member Variables + // Undo actions for this Project. + proj::Undo undo { *this }; + + // Manage the node tree of the project. + node::Tree tree { *this }; + + /// One of the available internationalization types. + fld::I18n_Type i18n_type = I18n_Type::NONE; + /// Include file for GNU i18n, writes an #include statement into the source + /// file. This is usually `` or `"gettext.h"` for GNU gettext. + std::string i18n_gnu_include = ""; + // Optional name of a macro for conditional i18n compilation. + std::string i18n_gnu_conditional = ""; + /// For the gettext/intl.h options, this is the function that translates text + /// at runtime. This is usually "gettext" or "_". + std::string i18n_gnu_function = "gettext"; + /// For the gettext/intl.h options, this is the function that marks the translation + /// of text at initialisation time. This is usually "gettext_noop" or "N_". + std::string i18n_gnu_static_function = "gettext_noop"; + + /// Include file for Posix i18n, write a #include statement into the source + /// file. This is usually `` for Posix catgets. + std::string i18n_pos_include = ""; + // Optional name of a macro for conditional i18n compilation. + std::string i18n_pos_conditional = ""; + /// Name of the nl_catd database + std::string i18n_pos_file = ""; + /// Message set ID for the catalog. + std::string i18n_pos_set = "1"; + + /// If set, generate code to include the header file form the c++ file + int include_H_from_C = 1; + /// If set, handle keyboard shortcut Ctrl on macOS using Cmd instead + int use_FL_COMMAND = 0; + /// Clear if UTF-8 characters in statics texts are written as escape sequences + int utf8_in_src = 0; + /// If set, will not be included from the header code before anything else + int avoid_early_includes = 0; + /// If set, command line overrides header file name in .fl file. + int header_file_set = 0; + /// If set, command line overrides source code file name in .fl file. + int code_file_set = 0; + /// later + int write_mergeback_data = 0; + /// Filename of the current .fl project file + const char *proj_filename { nullptr }; + /// Hold the default extension for header files, or the entire filename if set via command line. + std::string header_file_name = ".h"; + /// Hold the default extension for source code files, or the entire filename if set via command line. + std::string code_file_name = ".cxx"; + + /// Used as a counter to set the .fl project dir as the current directory. + int in_project_dir { 0 }; + /// Application work directory, stored here when temporarily changing to the source code directory. + std::string app_work_dir = ""; + + /// Set if the current design has been modified compared to the associated .fl design file. + int modflag { 0 }; + /// Set if the code files are older than the current design. + int modflag_c { 0 }; + + /// Currently used layout preset. + app::Layout_Preset *layout { app::default_layout_preset }; + +public: // Methods + Project(); + ~Project(); void reset(); void update_settings_dialog(); @@ -51,53 +129,17 @@ public: std::string stringsfile_name() const; std::string basename() const; - /// One of the available internationalization types. - Fd_I18n_Type i18n_type; - /// Include file for GNU i18n, writes an #include statement into the source - /// file. This is usually `` or `"gettext.h"` for GNU gettext. - std::string i18n_gnu_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_gnu_conditional; - /// For the gettext/intl.h options, this is the function that translates text - /// at runtime. This is usually "gettext" or "_". - std::string i18n_gnu_function; - /// For the gettext/intl.h options, this is the function that marks the translation - /// of text at initialisation time. This is usually "gettext_noop" or "N_". - std::string i18n_gnu_static_function; + void enter_project_dir(); + void leave_project_dir(); + + void set_filename(const char *c); + void write_strings(); - /// Include file for Posix i18n, write a #include statement into the source - /// file. This is usually `` for Posix catgets. - std::string i18n_pos_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_pos_conditional; - /// Name of the nl_catd database - std::string i18n_pos_file; - /// Message set ID for the catalog. - std::string i18n_pos_set; - - /// If set, generate code to include the header file form the c++ file - int include_H_from_C; - /// If set, handle keyboard shortcut Ctrl on macOS using Cmd instead - int use_FL_COMMAND; - /// Clear if UTF-8 characters in statics texts are written as escape sequences - int utf8_in_src; - /// If set, will not be included from the header code before anything else - int avoid_early_includes; - /// If set, command line overrides header file name in .fl file. - int header_file_set; - /// If set, command line overrides source code file name in .fl file. - int code_file_set; - int write_mergeback_data; - /// Filename of the current .fl project file - const char *proj_filename { nullptr }; - /// Hold the default extension for header files, or the entire filename if set via command line. - std::string header_file_name; - /// Hold the default extension for source code files, or the entire filename if set via command line. - std::string code_file_name; + void set_modflag(int mf, int mfc = -1); }; -extern Fluid_Project g_project; +} // namespace fld -#endif // FLUID_APP_PROJECT_H +#endif // FLUID_PROJECT_H diff --git a/fluid/README_fl.txt b/fluid/README_fl.txt index 2e69d4cfa..21486d664 100644 --- a/fluid/README_fl.txt +++ b/fluid/README_fl.txt @@ -293,7 +293,7 @@ Note: the hierarchical dependency is implemented twice and somewhat conflicting The list of known Types and their inheritance is: - Fl_Type (note: can't be written) + Node (note: can't be written) +-- Function +-- code +-- codeblock @@ -315,7 +315,7 @@ The list of known Types and their inheritance is: | | +-- Fl_Tile | | +-- Fl_Wizard | | +-- Fl_Grid - | +-- Fl_Menu_Type (note: can't be written) + | +-- Menu_Node (note: can't be written) | | +-- Fl_Menu_Button | | +-- Fl_Choice | | +-- Fl_Input_Choice @@ -373,7 +373,7 @@ are stored as "parent_properties { ...list... }". If a node encounters this property tag, it must ask its parent to interpret the contents of that list. See Fl_Grid for an example. -Type Fl_Type +Type Node "uid" <4-digit-hex> : since Oct 2023, optional, a unique id for this node within the project file @@ -392,12 +392,12 @@ Type "Function" : function signature “C” : if set, function is extern “C” “return_type” : C or C++ type descriptor, can start with “virtual” and/or “static” to further define the function. - ... : inherits more from Fl_Type + ... : inherits more from Node Type codeblock : C++ code, for example "if (test())" "after" : C++ code or comment following the closing '}' - ... : inherits more from Fl_Type + ... : inherits more from Node Type "decl" : C++ code to declare a variable or class member @@ -405,7 +405,7 @@ Type "decl" : C++ code to declare a variable or class member defaults to "private" none or "local" or "global": for declaration in the code body defaults to "global" - ... : inherits more from Fl_Type + ... : inherits more from Node Type "data" : C++ variable name @@ -418,21 +418,21 @@ Type "declblock" : C++ code none or "public" or "protected" : defaults to private (obsolete) "map" : integer value, default is 2 (CODE_IN_SOURCE), - see Fl_DeclBlock_Type::write_map_ + see DeclBlock_Node::write_map_ "after" : C++ code or comment following the block - ... : inherits more from Fl_Type + ... : inherits more from Node Type "comment" : comment text "in_source" or "not_in_source": default to in_source "in_header" or "not_in_header": default to in_header - ... : inherits more from Fl_Type + ... : inherits more from Node Type "class" : prefix, class name none or "private" or "protected" : defaults to public ":" : name of super class - ... : inherits more from Fl_Type + ... : inherits more from Node Type "Fl_Widget" : C++ variable name @@ -487,7 +487,7 @@ Type "Fl_Widget" : C++ variable name "shortcut" : integer "code0" or "code1" or "code2" or "code3" : C++ extra code lines "extra_code" : C++ extra code lines - ... : inherits more from Fl_Type + ... : inherits more from Node Type "Fl_Button" : C++ variable name diff --git a/fluid/app/Fluid_Image.cxx b/fluid/app/Fluid_Image.cxx deleted file mode 100644 index a79ac6c35..000000000 --- a/fluid/app/Fluid_Image.cxx +++ /dev/null @@ -1,413 +0,0 @@ -// -// Pixmap (and other images) label support for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2022 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 "app/Fluid_Image.h" - -#include "app/fluid.h" -#include "io/Project_Reader.h" -#include "io/Project_Writer.h" -#include "io/Code_Writer.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Window_Type.h" -#include "tools/filename.h" - -#include -#include -#include -#include -#include // fl_fopen() -#include -#include -#include -#include "../src/flstring.h" - -#include -#include -#include -#include - -void Fluid_Image::image(Fl_Widget *o) { - if (o->window() != o) o->image(img); -} - -void Fluid_Image::deimage(Fl_Widget *o) { - if (o->window() != o) o->deimage(img); -} - -/** Write the contents of the name() file as binary source code. - \param fmt short name of file contents for error message - \return 0 if the file could not be opened or read */ -size_t Fluid_Image::write_static_binary(fld::io::Code_Writer& f, const char* fmt) { - size_t nData = 0; - enter_project_dir(); - FILE *in = fl_fopen(name(), "rb"); - leave_project_dir(); - if (!in) { - write_file_error(f, fmt); - return 0; - } else { - fseek(in, 0, SEEK_END); - nData = ftell(in); - fseek(in, 0, SEEK_SET); - if (nData) { - char *data = (char*)calloc(nData, 1); - if (fread(data, nData, 1, in)==0) { /* ignore */ } - f.write_cdata(data, (int)nData); - free(data); - } - fclose(in); - } - return nData; -} - -/** Write the contents of the name() file as textual source code. - \param fmt short name of file contents for error message - \return 0 if the file could not be opened or read */ -size_t Fluid_Image::write_static_text(fld::io::Code_Writer& f, const char* fmt) { - size_t nData = 0; - enter_project_dir(); - FILE *in = fl_fopen(name(), "rb"); - leave_project_dir(); - if (!in) { - write_file_error(f, fmt); - return 0; - } else { - fseek(in, 0, SEEK_END); - nData = ftell(in); - fseek(in, 0, SEEK_SET); - if (nData) { - char *data = (char*)calloc(nData+1, 1); - if (fread(data, nData, 1, in)==0) { /* ignore */ } - f.write_cstring(data, (int)nData); - free(data); - } - fclose(in); - } - return nData; -} - -void Fluid_Image::write_static_rgb(fld::io::Code_Writer& f, const char* idata_name) { - // Write image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - const int extra_data = img->ld() ? (img->ld()-img->w()*img->d()) : 0; - f.write_cdata(img->data()[0], (img->w() * img->d() + extra_data) * img->h()); - f.write_c(";\n"); - write_initializer(f, "Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, img->w(), img->h(), img->d(), img->ld()); -} - -/** - Write the static image data into the soutrce file. - - If \p compressed is set, write the original image format, which requires - linking the matching image reader at runtime, or if we want to store the raw - uncompressed pixels, which makes images fast, needs no reader, but takes a - lot of memory (current default for PNG) - - \param compressed write data in the original compressed file format - */ -void Fluid_Image::write_static(fld::io::Code_Writer& f, int compressed) { - if (!img) return; - const char *idata_name = f.unique_id(this, "idata", fl_filename_name(name()), 0); - function_name_ = f.unique_id(this, "image", fl_filename_name(name()), 0); - - if (is_animated_gif_) { - // Write animated gif image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "AnimGIF"); - f.write_c(";\n"); - write_initializer(f, "Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); - } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".gif")==0) { - // Write gif image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "GIF"); - f.write_c(";\n"); - write_initializer(f, "Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); - } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".bmp")==0) { - // Write bmp image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "BMP"); - f.write_c(";\n"); - write_initializer(f, "Fl_BMP_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); - } else if (img->count() > 1) { - // Write Pixmap data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const char *%s[] = {\n", idata_name); - f.write_cstring(img->data()[0], (int)strlen(img->data()[0])); - - int i; - int ncolors, chars_per_color; - sscanf(img->data()[0], "%*d%*d%d%d", &ncolors, &chars_per_color); - - if (ncolors < 0) { - f.write_c(",\n"); - f.write_cstring(img->data()[1], ncolors * -4); - i = 2; - } else { - for (i = 1; i <= ncolors; i ++) { - f.write_c(",\n"); - f.write_cstring(img->data()[i], (int)strlen(img->data()[i])); - } - } - for (; i < img->count(); i ++) { - f.write_c(",\n"); - f.write_cstring(img->data()[i], img->w() * chars_per_color); - } - f.write_c("\n};\n"); - write_initializer(f, "Fl_Pixmap", "%s", idata_name); - } else if (img->d() == 0) { - // Write Bitmap data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - f.write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h()); - f.write_c(";\n"); - write_initializer(f, "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h()); - } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".jpg")==0) { - // Write jpeg image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "JPEG"); - f.write_c(";\n"); - write_initializer(f, "Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); - } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".png")==0) { - // Write png image data... - f.write_c("\n"); - f.write_c_once("#include \n"); - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "PNG"); - f.write_c(";\n"); - write_initializer(f, "Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData); - } -#ifdef FLTK_USE_SVG - else if (fl_ascii_strcasecmp(fl_filename_ext(name()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(name()), ".svgz")==0) { - bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0); - // Write svg image data... - if (compressed) { - f.write_c("\n"); - f.write_c_once("#include \n"); - if (gzipped) { - f.write_c("static const unsigned char %s[] =\n", idata_name); - size_t nData = write_static_binary(f, "SVGZ"); - f.write_c(";\n"); - write_initializer(f, "Fl_SVG_Image", "\"%s\", %s, %ld", fl_filename_name(name()), idata_name, nData); - } else { - f.write_c("static const char %s[] =\n", idata_name); - write_static_text(f, "SVG"); - f.write_c(";\n"); - write_initializer(f, "Fl_SVG_Image", "\"%s\", %s", fl_filename_name(name()), idata_name); - } - } else { - // if FLUID runs from the command line, make sure that the image is not - // only loaded but also rasterized, so we can write the RGB image data - Fl_RGB_Image* rgb_image = NULL; - Fl_SVG_Image* svg_image = NULL; - if (img->d()>0) - rgb_image = (Fl_RGB_Image*)img->image(); - if (rgb_image) - svg_image = rgb_image->as_svg_image(); - if (svg_image) { - svg_image->resize(svg_image->w(), svg_image->h()); - write_static_rgb(f, idata_name); - } else { - write_file_error(f, "RGB_from_SVG"); - } - } - } -#endif // FLTK_USE_SVG - else { - write_static_rgb(f, idata_name); - } -} - -void Fluid_Image::write_file_error(fld::io::Code_Writer& f, const char *fmt) { - f.write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, name(), strerror(errno)); - enter_project_dir(); - f.write_c("// Searching in path \"%s\"\n", fl_getcwd(0, FL_PATH_MAX)); - leave_project_dir(); -} - -void Fluid_Image::write_initializer(fld::io::Code_Writer& f, const char *type_name, const char *format, ...) { - /* Outputs code that returns (and initializes if needed) an Fl_Image as follows: - static Fl_Image *'function_name_'() { - static Fl_Image *image = NULL; - if (!image) - image = new 'type_name'('product of format and remaining args'); - return image; - } */ - va_list ap; - va_start(ap, format); - f.write_c("static Fl_Image *%s() {\n", function_name_); - if (is_animated_gif_) - f.write_c("%sFl_GIF_Image::animate = true;\n", f.indent(1)); - f.write_c("%sstatic Fl_Image *image = NULL;\n", f.indent(1)); - f.write_c("%sif (!image)\n", f.indent(1)); - f.write_c("%simage = new %s(", f.indent(2), type_name); - f.vwrite_c(format, ap); - f.write_c(");\n"); - f.write_c("%sreturn image;\n", f.indent(1)); - f.write_c("}\n"); - va_end(ap); -} - -void Fluid_Image::write_code(fld::io::Code_Writer& f, int bind, const char *var, int inactive) { - /* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item. - This code calls a function output before by Fluid_Image::write_initializer() */ - if (img) { - f.write_c("%s%s->%s%s( %s() );\n", f.indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_); - if (is_animated_gif_) - f.write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", f.indent(), function_name_, var); - } -} - -void Fluid_Image::write_inline(fld::io::Code_Writer& f, int inactive) { - if (img) - f.write_c("%s()", function_name_); -} - - -//////////////////////////////////////////////////////////////// - -static Fluid_Image** images = 0; // sorted list -static int numimages = 0; -static int tablesize = 0; - -Fluid_Image* Fluid_Image::find(const char *iname) { - if (!iname || !*iname) return 0; - - // first search to see if it exists already: - int a = 0; - int b = numimages; - while (a < b) { - int c = (a+b)/2; - int i = strcmp(iname,images[c]->name_); - if (i < 0) b = c; - else if (i > 0) a = c+1; - else return images[c]; - } - - // no, so now see if the file exists: - - enter_project_dir(); - FILE *f = fl_fopen(iname,"rb"); - if (!f) { - if (batch_mode) - fprintf(stderr, "Can't open image file:\n%s\n%s",iname,strerror(errno)); - else - fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno)); - leave_project_dir(); - return 0; - } - fclose(f); - - Fluid_Image *ret = new Fluid_Image(iname); - - if (!ret->img || !ret->img->w() || !ret->img->h()) { - delete ret; - ret = 0; - if (batch_mode) - fprintf(stderr, "Can't read image file:\n%s\nunrecognized image format",iname); - else - fl_message("Can't read image file:\n%s\nunrecognized image format",iname); - } - leave_project_dir(); - if (!ret) return 0; - - // make a new entry in the table: - numimages++; - if (numimages > tablesize) { - tablesize = tablesize ? 2*tablesize : 16; - if (images) images = (Fluid_Image**)realloc(images, tablesize*sizeof(Fluid_Image*)); - else images = (Fluid_Image**)malloc(tablesize*sizeof(Fluid_Image*)); - } - for (b = numimages-1; b > a; b--) images[b] = images[b-1]; - images[a] = ret; - - return ret; -} - -Fluid_Image::Fluid_Image(const char *iname) - : is_animated_gif_(false) -{ - name_ = fl_strdup(iname); - written = 0; - refcount = 0; - img = Fl_Shared_Image::get(iname); - if (img && iname) { - const char *ext = fl_filename_ext(iname); - if (fl_ascii_strcasecmp(ext, ".gif")==0) { - int fc = Fl_Anim_GIF_Image::frame_count(iname); - if (fc > 0) is_animated_gif_ = true; - } - } - function_name_ = NULL; -} - -void Fluid_Image::increment() { - ++refcount; -} - -void Fluid_Image::decrement() { - --refcount; - if (refcount > 0) return; - delete this; -} - -Fluid_Image::~Fluid_Image() { - int a; - if (images) { - for (a = 0; arelease(); - free((void*)name_); -} - -//////////////////////////////////////////////////////////////// - -const char *ui_find_image_name; -Fluid_Image *ui_find_image(const char *oldname) { - enter_project_dir(); - fl_file_chooser_ok_label("Use Image"); - const char *name = fl_file_chooser("Image?", - "Image Files (*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm,svg" -#ifdef HAVE_LIBZ - ",svgz" -#endif - "})", - oldname,1); - fl_file_chooser_ok_label(NULL); - ui_find_image_name = name; - Fluid_Image *ret = (name && *name) ? Fluid_Image::find(name) : 0; - leave_project_dir(); - return ret; -} diff --git a/fluid/app/Image_Asset.cxx b/fluid/app/Image_Asset.cxx new file mode 100644 index 000000000..a001f2291 --- /dev/null +++ b/fluid/app/Image_Asset.cxx @@ -0,0 +1,532 @@ +// +// Image Helper code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "app/Image_Asset.h" + +#include "Fluid.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" +#include "nodes/Group_Node.h" +#include "nodes/Window_Node.h" +#include "tools/filename.h" + +#include +#include +#include +#include +#include // fl_fopen() +#include +#include +#include +#include "../src/flstring.h" + +#include +#include +#include +#include +#include +#include + + +/** + \brief A map of all image assets. + \todo This is a global variable, but should be associated + with a project instead. + */ +static std::map image_asset_map; + + +/** + \brief Write the contents of the image file as binary source code. + + Write the contents of the image file as C++ code, so the image is available in + the target app in the original binary format, for example: + ``` + { 1, 2, 3, ...} + ``` + \param f Write code to this C++ source code file + \param fmt short name of file contents for error message + \return 0 if the file could not be opened or read + */ +size_t Image_Asset::write_static_binary(fld::io::Code_Writer& f, const char* fmt) { + size_t nData = 0; + Fluid.proj.enter_project_dir(); + FILE *in = fl_fopen(filename(), "rb"); + Fluid.proj.leave_project_dir(); + if (!in) { + write_file_error(f, fmt); + return 0; + } else { + fseek(in, 0, SEEK_END); + nData = ftell(in); + fseek(in, 0, SEEK_SET); + if (nData) { + char *data = (char*)calloc(nData, 1); + if (fread(data, nData, 1, in)==0) { /* ignore */ } + f.write_cdata(data, (int)nData); + free(data); + } + fclose(in); + } + return nData; +} + + +/** + \brief Write the contents of the image file as text with escaped special characters. + + This function is only useful for writing out image formats that are ASCII text + based, like svg and pixmaps. Other formats should use write_static_binary(). + + \param f Write code to this C++ source code file + \param fmt short name of file contents for error message + \return 0 if the file could not be opened or read + */ +size_t Image_Asset::write_static_text(fld::io::Code_Writer& f, const char* fmt) { + size_t nData = 0; + Fluid.proj.enter_project_dir(); + FILE *in = fl_fopen(filename(), "rb"); + Fluid.proj.leave_project_dir(); + if (!in) { + write_file_error(f, fmt); + return 0; + } else { + fseek(in, 0, SEEK_END); + nData = ftell(in); + fseek(in, 0, SEEK_SET); + if (nData) { + char *data = (char*)calloc(nData+1, 1); + if (fread(data, nData, 1, in)==0) { /* ignore */ } + f.write_cstring(data, (int)nData); + free(data); + } + fclose(in); + } + return nData; +} + + +/** + \brief Write the contents of the image file as uncompressed RGB. + + Write source code that generates the uncompressed RGB image data at compile + time, and an initializer that creates the image at run time. + + \todo If the ld() value is not 0 and not d()*w(), the image data is not + written correctly. There is no check if the data is actually in RGB format. + + \param f Write code to this C++ source code file + \param fmt short name of file contents for error message + \return 0 if the file could not be opened or read + */ +void Image_Asset::write_static_rgb(fld::io::Code_Writer& f, const char* idata_name) { + // Write image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + const int extra_data = image_->ld() ? (image_->ld()-image_->w()*image_->d()) : 0; + f.write_cdata(image_->data()[0], (image_->w() * image_->d() + extra_data) * image_->h()); + f.write_c(";\n"); + write_initializer(f, "Fl_RGB_Image", "%s, %d, %d, %d, %d", idata_name, image_->w(), image_->h(), image_->d(), image_->ld()); +} + + +/** + \brief Write the static image data into the source file. + + Write source code that generates the image data at compile time, and an + initializer that creates the image at run time. + + If \p compressed is set, write the original image format, which requires + linking the matching image reader at runtime, or if we want to store the raw + uncompressed pixels, which makes images fast, needs no reader, but takes a + lot of memory (current default for PNG) + + \param f Write code to this C++ source code file + \param compressed write data in the original compressed file format + */ +void Image_Asset::write_static(fld::io::Code_Writer& f, int compressed) { + if (!image_) return; + const char *idata_name = f.unique_id(this, "idata", fl_filename_name(filename()), nullptr); + initializer_function_ = f.unique_id(this, "image", fl_filename_name(filename()), nullptr); + + if (is_animated_gif_) { + // Write animated gif image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "AnimGIF"); + f.write_c(";\n"); + write_initializer(f, "Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(filename()), idata_name, nData); + } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(filename()), ".gif")==0) { + // Write gif image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "GIF"); + f.write_c(";\n"); + write_initializer(f, "Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(filename()), idata_name, nData); + } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(filename()), ".bmp")==0) { + // Write bmp image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "BMP"); + f.write_c(";\n"); + write_initializer(f, "Fl_BMP_Image", "\"%s\", %s, %d", fl_filename_name(filename()), idata_name, nData); + } else if (image_->count() > 1) { + // Write Pixmap data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const char *%s[] = {\n", idata_name); + f.write_cstring(image_->data()[0], (int)strlen(image_->data()[0])); + + int i; + int ncolors, chars_per_color; + sscanf(image_->data()[0], "%*d%*d%d%d", &ncolors, &chars_per_color); + + if (ncolors < 0) { + f.write_c(",\n"); + f.write_cstring(image_->data()[1], ncolors * -4); + i = 2; + } else { + for (i = 1; i <= ncolors; i ++) { + f.write_c(",\n"); + f.write_cstring(image_->data()[i], (int)strlen(image_->data()[i])); + } + } + for (; i < image_->count(); i ++) { + f.write_c(",\n"); + f.write_cstring(image_->data()[i], image_->w() * chars_per_color); + } + f.write_c("\n};\n"); + write_initializer(f, "Fl_Pixmap", "%s", idata_name); + } else if (image_->d() == 0) { + // Write Bitmap data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + f.write_cdata(image_->data()[0], ((image_->w() + 7) / 8) * image_->h()); + f.write_c(";\n"); + write_initializer(f, "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((image_->w() + 7) / 8) * image_->h(), image_->w(), image_->h()); + } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(filename()), ".jpg")==0) { + // Write jpeg image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "JPEG"); + f.write_c(";\n"); + write_initializer(f, "Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(filename()), idata_name, nData); + } else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(filename()), ".png")==0) { + // Write png image data... + f.write_c("\n"); + f.write_c_once("#include \n"); + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "PNG"); + f.write_c(";\n"); + write_initializer(f, "Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(filename()), idata_name, nData); + } +#ifdef FLTK_USE_SVG + else if (fl_ascii_strcasecmp(fl_filename_ext(filename()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(filename()), ".svgz")==0) { + bool gzipped = (strcmp(fl_filename_ext(filename()), ".svgz") == 0); + // Write svg image data... + if (compressed) { + f.write_c("\n"); + f.write_c_once("#include \n"); + if (gzipped) { + f.write_c("static const unsigned char %s[] =\n", idata_name); + size_t nData = write_static_binary(f, "SVGZ"); + f.write_c(";\n"); + write_initializer(f, "Fl_SVG_Image", "\"%s\", %s, %ld", fl_filename_name(filename()), idata_name, nData); + } else { + f.write_c("static const char %s[] =\n", idata_name); + write_static_text(f, "SVG"); + f.write_c(";\n"); + write_initializer(f, "Fl_SVG_Image", "\"%s\", %s", fl_filename_name(filename()), idata_name); + } + } else { + // if FLUID runs from the command line, make sure that the image is not + // only loaded but also rasterized, so we can write the RGB image data + Fl_RGB_Image* rgb_image = nullptr; + Fl_SVG_Image* svg_image = nullptr; + if (image_->d()>0) + rgb_image = (Fl_RGB_Image*)image_->image(); + if (rgb_image) + svg_image = rgb_image->as_svg_image(); + if (svg_image) { + svg_image->resize(svg_image->w(), svg_image->h()); + write_static_rgb(f, idata_name); + } else { + write_file_error(f, "RGB_from_SVG"); + } + } + } +#endif // FLTK_USE_SVG + else { + write_static_rgb(f, idata_name); + } +} + + +/** + \brief Write a warning message to the generated code file that the image asset + can't be read. + + This writes a #warning directive to the generated code file which contains the + filename of the image asset and the error message as returned by strerror(errno). + The current working directory is also printed for debugging purposes. + \param f The C++ source code file to write the warning message to. + \param fmt The format string for the image file type. + */ +void Image_Asset::write_file_error(fld::io::Code_Writer& f, const char *fmt) { + f.write_c("#warning Cannot read %s file \"%s\": %s\n", fmt, filename(), strerror(errno)); + Fluid.proj.enter_project_dir(); + f.write_c("// Searching in path \"%s\"\n", fl_getcwd(nullptr, FL_PATH_MAX)); + Fluid.proj.leave_project_dir(); +} + + +/** + \brief Outputs code that loads and returns an Fl_Image. + + The generated code loads the image if it hasn't been loaded yet, and then + returns a pointer to the image. + + \code + static Fl_Image *'initializer_function_'() { + static Fl_Image *image = 0L; + if (!image) + image = new 'type_name'('product of format and remaining args'); + return image; + } + \endcode + + \param f Write the C++ code to this file. + \param image_class Name of the Fl_Image class, for example Fl_GIF_Image. + \param format Format string for additional parameters for the constructor. + */ +void Image_Asset::write_initializer(fld::io::Code_Writer& f, const char *image_class, const char *format, ...) { + va_list ap; + va_start(ap, format); + f.write_c("static Fl_Image *%s() {\n", initializer_function_.c_str()); + if (is_animated_gif_) + f.write_c("%sFl_GIF_Image::animate = true;\n", f.indent(1)); + f.write_c("%sstatic Fl_Image *image = 0L;\n", f.indent(1)); + f.write_c("%sif (!image)\n", f.indent(1)); + f.write_c("%simage = new %s(", f.indent(2), image_class); + f.vwrite_c(format, ap); + f.write_c(");\n"); + f.write_c("%sreturn image;\n", f.indent(1)); + f.write_c("}\n"); + va_end(ap); +} + + +/** + \brief Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item. + + The generated code will call the image initializer function and assign + the resulting image to the widget. + + \param f Write the C++ code to this file. + \param bind If true, use bind_image() instead of image(). + \param var Name of the Fl_Widget or Fl_Menu_Item to attach the image to. + \param inactive If true, use deimage() instead of image(). + */ +void Image_Asset::write_code(fld::io::Code_Writer& f, int bind, const char *var, int inactive) { + if (image_) { + f.write_c("%s%s->%s%s( %s() );\n", + f.indent(), + var, + bind ? "bind_" : "", + inactive ? "deimage" : "image", + initializer_function_.c_str()); + if (is_animated_gif_) + f.write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", + f.indent(), + initializer_function_.c_str(), + var); + } +} + + +/** + \brief Outputs code that calls the image initializer function. + + The generated code calls the image initializer function, loading an image and + assigning it to a Fl_Menu_Item. + + \param f Write the C++ code to this file. + \param inactive Unused. + */ +void Image_Asset::write_inline(fld::io::Code_Writer& f, int inactive) { + (void)inactive; + if (image_) { + f.write_c("%s()", initializer_function_.c_str()); + } +} + + +/** + \brief Finds an image asset by filename. + + If the image asset has already been loaded, it is returned from the cache. + If the image asset has not been loaded, it is loaded from the file system. + If the image asset cannot be loaded, nullptr is returned. + + \param iname The filename of the image asset to find. + \returns The image asset, or nullptr if it cannot be loaded. + */ +Image_Asset* Image_Asset::find(const char *iname) { + if (!iname || !*iname) return nullptr; + + // First search to see if it exists already. If it does, return it. + auto result = image_asset_map.find(iname); + if (result != image_asset_map.end()) + return result->second; + + // Check if a file by that name exists. + Fluid.proj.enter_project_dir(); + FILE *f = fl_fopen(iname,"rb"); + if (!f) { + if (Fluid.batch_mode) + fprintf(stderr, "Can't open image file:\n%s\n%s",iname,strerror(errno)); + else + fl_message("Can't open image file:\n%s\n%s",iname,strerror(errno)); + Fluid.proj.leave_project_dir(); + return nullptr; + } + fclose(f); + + // We found the file. Create the asset. + Image_Asset *asset = new Image_Asset(iname); + if (!asset->image_ || !asset->image_->w() || !asset->image_->h()) { + delete asset; + if (Fluid.batch_mode) + fprintf(stderr, "Can't read image file:\n%s\nunrecognized image format",iname); + else + fl_message("Can't read image file:\n%s\nunrecognized image format",iname); + Fluid.proj.leave_project_dir(); + return nullptr; + } + + // Add the new asset to our image asset map and return it to the caller. + image_asset_map[iname] = asset; + return asset; +} + +/** + \brief Construct an image asset from a file in the project directory. + + This constructor creates an image asset from a file in the project + directory. The image file is loaded and stored in the map of image + assets. The image asset is given a reference count of 1, which means + that it will be destroyed when all references to it have been released. + The constructor also sets the flag to indicate if the image is an + animated GIF. This information is used when generating code for the + image asset. + + \param iname The name of the image file in the project directory. +*/ +Image_Asset::Image_Asset(const char *iname) +{ + filename_ = iname; + image_ = Fl_Shared_Image::get(iname); + if (image_ && iname) { + const char *ext = fl_filename_ext(iname); + if (fl_ascii_strcasecmp(ext, ".gif")==0) { + int fc = Fl_Anim_GIF_Image::frame_count(iname); + if (fc > 0) is_animated_gif_ = true; + } + } +} + +/** + \brief Increments the reference count of the image asset. + + This method increments the reference count of the image asset. The + reference count is used to keep track of how many times the image asset + is referenced in the user interface. When the reference count reaches zero, + the image asset is destroyed. +*/ +void Image_Asset::inc_ref() { + ++refcount_; +} + +/** + \brief Decrements the reference count of the image asset. + + This method decrements the reference count of the image asset. The + reference count is used to keep track of how many times the image asset + is referenced in the user interface. If the reference count reaches zero, + the image asset is destroyed. +*/ +void Image_Asset::dec_ref() { + --refcount_; + if (refcount_ > 0) return; + delete this; +} + +/** + \brief Destructor for the Image_Asset class. + + This destructor removes the image asset from the global image asset map + and releases the associated shared image if it exists. It ensures that + any resources associated with the Image_Asset are properly cleaned up + when the object is destroyed. +*/ +Image_Asset::~Image_Asset() { + image_asset_map.erase(filename_); + if (image_) image_->release(); +} + +//////////////////////////////////////////////////////////////// + +/** + \brief Displays a file chooser for the user to select an image file. + + This function displays a file chooser dialog with the title "Image?" and + the current working directory set to the project directory. The file + chooser displays files with the extensions .bm, .bmp, .gif, .jpg, .pbm, + .pgm, .png, .ppm, .xbm, .xpm, and .svg (and .svgz if zlib support is + enabled). The function returns a pointer to an Image_Asset object that + references the selected image. If the user cancels the file chooser or + selects a file that does not exist, the function returns nullptr. + + \param oldname The default filename to display in the file chooser. + + \return A pointer to an Image_Asset object that references the selected + image, or nullptr if the user cancels the file chooser or selects a file + that does not exist. The asset is automaticly added to the global image + asset map. +*/ +Image_Asset *ui_find_image(const char *oldname) { + Fluid.proj.enter_project_dir(); + fl_file_chooser_ok_label("Use Image"); + const char *name = fl_file_chooser("Image?", + "Image Files (*.{bm,bmp,gif,jpg,pbm,pgm,png,ppm,xbm,xpm,svg" +#ifdef HAVE_LIBZ + ",svgz" +#endif + "})", + oldname,1); + fl_file_chooser_ok_label(nullptr); + Image_Asset *ret = (name && *name) ? Image_Asset::find(name) : nullptr; + Fluid.proj.leave_project_dir(); + return ret; +} + diff --git a/fluid/app/Fluid_Image.h b/fluid/app/Image_Asset.h similarity index 56% rename from fluid/app/Fluid_Image.h rename to fluid/app/Image_Asset.h index f095e83ce..f5376beaa 100644 --- a/fluid/app/Fluid_Image.h +++ b/fluid/app/Image_Asset.h @@ -1,11 +1,7 @@ // -// Image header file for the Fast Light Tool Kit (FLTK). +// Image Helper header file for the Fast Light Tool Kit (FLTK). // -// This class stores the image labels for widgets in fluid. This is -// not a class in FLTK itself, and will produce different types of -// code depending on what the image type is. -// -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -18,43 +14,50 @@ // https://www.fltk.org/bugs.php // -#ifndef FLUID_IMAGE_H -#define FLUID_IMAGE_H +// This class stores the image labels for widgets in fluid. This is +// not a class in FLTK itself, and will produce different types of +// code depending on what the image type is. + + +#ifndef APP_IMAGE_ASSET_H +#define APP_IMAGE_ASSET_H #include "io/Code_Writer.h" #include -class Fluid_Image { - bool is_animated_gif_; - const char *name_; - int refcount; - Fl_Shared_Image *img; - const char *function_name_; -protected: - Fluid_Image(const char *name); // no public constructor - ~Fluid_Image(); // no public destructor +class Image_Asset { + +private: // member variables + bool is_animated_gif_ = false; ///< It's an animated gif. + std::string filename_ { }; ///< Relative path to the image file + int refcount_ = 0; ///< Reference count + Fl_Shared_Image *image_ = nullptr; ///< The actual image as managed by FLTK + std::string initializer_function_ { }; ///< The name of the initializer function + +private: // methods + Image_Asset(const char *name); // no public constructor + ~Image_Asset(); // no public destructor size_t write_static_binary(fld::io::Code_Writer& f, const char* fmt); size_t write_static_text(fld::io::Code_Writer& f, const char* fmt); void write_static_rgb(fld::io::Code_Writer& f, const char* idata_name); -public: - int written; - static Fluid_Image* find(const char *); - void decrement(); // reference counting & automatic free - void increment(); - void image(Fl_Widget *); // set the image of this widget - void deimage(Fl_Widget *); // set the deimage of this widget + +public: // methods + static Image_Asset* find(const char *); + void dec_ref(); // reference counting & automatic free + void inc_ref(); + Fl_Shared_Image *image() const { return image_; } void write_static(fld::io::Code_Writer& f, int compressed); void write_initializer(fld::io::Code_Writer& f, const char *type_name, const char *format, ...); void write_code(fld::io::Code_Writer& f, int bind, const char *var, int inactive = 0); void write_inline(fld::io::Code_Writer& f, int inactive = 0); void write_file_error(fld::io::Code_Writer& f, const char *fmt); - const char *name() const {return name_;} + const char *filename() const { return filename_.c_str(); } }; // pop up file chooser and return a legal image selected by user, // or zero for any errors: -Fluid_Image *ui_find_image(const char *); +Image_Asset *ui_find_image(const char *); extern const char *ui_find_image_name; -#endif +#endif // APP_IMAGE_ASSET_H diff --git a/fluid/app/Menu.cxx b/fluid/app/Menu.cxx new file mode 100644 index 000000000..044cc29a7 --- /dev/null +++ b/fluid/app/Menu.cxx @@ -0,0 +1,190 @@ +// +// Application Main Menu code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "app/Menu.h" + +#include "Fluid.h" + +#include "proj/undo.h" +#include "app/templates.h" +#include "nodes/Node.h" +#include "nodes/Group_Node.h" +#include "nodes/Window_Node.h" +#include "nodes/factory.h" +#include "panels/codeview_panel.h" +#include "app/shell_command.h" + +#include + +// In Snap_Action.h +extern void layout_suite_marker(Fl_Widget *, void *user_data); +extern void select_layout_preset_cb(Fl_Widget *, void *user_data); +extern Fl_Menu_Item main_layout_submenu_[]; + +using namespace fld; + + +void write_cb(Fl_Widget *, void *) { + Fluid.write_code_files(); +} +void openwidget_cb(Fl_Widget *, void *) { Fluid.edit_selected(); } +void copy_cb(Fl_Widget*, void*) { Fluid.copy_selected(); } +void cut_cb(Fl_Widget *, void *) { Fluid.cut_selected(); } +void delete_cb(Fl_Widget *, void *) { Fluid.delete_selected(); } +void paste_cb(Fl_Widget*, void*) { Fluid.paste_from_clipboard(); } +void duplicate_cb(Fl_Widget*, void*) { Fluid.duplicate_selected(); } +static void sort_cb(Fl_Widget *,void *) { Fluid.sort_selected(); } +void about_cb(Fl_Widget *, void *) { Fluid.about(); } +void help_cb(Fl_Widget *, void *) { + Fluid.show_help("fluid.html"); +} +static void save_template_cb(Fl_Widget *, void *) { fld::app::save_template(); } + +void manual_cb(Fl_Widget *, void *) { + Fluid.show_help("index.html"); +} + +static void menu_file_new_cb(Fl_Widget *, void *) { Fluid.new_project(); } +static void menu_file_new_from_template_cb(Fl_Widget *, void *) { Fluid.new_project_from_template(); } +static void menu_file_open_cb(Fl_Widget *, void *) { Fluid.open_project_file(""); } +static void menu_file_insert_cb(Fl_Widget *, void *) { Fluid.merge_project_file(""); } +void menu_file_save_cb(Fl_Widget *, void *arg) { Fluid.save_project_file(arg); } +static void menu_file_print_cb(Fl_Widget *, void *arg) { Fluid.print_snapshots(); } +void menu_file_open_history_cb(Fl_Widget *, void *v) { Fluid.open_project_file(std::string((const char*)v)); } +static void menu_layout_sync_resize_cb(Fl_Menu_ *m, void*) { + if (m->mvalue()->value()) Fluid.proj.tree.allow_layout = 1; else Fluid.proj.tree.allow_layout = 0; +} +static void menu_file_revert_cb(Fl_Widget *, void *) { Fluid.revert_project(); } +void exit_cb(Fl_Widget *,void *) { Fluid.quit(); } +static void write_strings_cb(Fl_Widget *, void *) { Fluid.proj.write_strings(); } +void toggle_widgetbin_cb(Fl_Widget *, void *) { Fluid.toggle_widget_bin(); } +/** + This is the main Fluid menu. + + Design history is manipulated right inside this menu structure. + Some menu items change or deactivate correctly, but most items just trigger + various callbacks. + + \c New_Menu creates new widgets and is explained in detail in another location. + + \see New_Menu + \todo This menu needs some major modernization. Menus are too long and their + sorting is not always obvious. + \todo Shortcuts are all over the place (Alt, Ctrl, Command, Shift-Ctrl, + function keys), and there should be a help page listing all shortcuts. + */ +Fl_Menu_Item Application::main_menu[] = { + {"&File",0,nullptr,nullptr,FL_SUBMENU}, + {"&New", FL_COMMAND+'n', menu_file_new_cb}, + {"&Open...", FL_COMMAND+'o', menu_file_open_cb}, + {"&Insert...", FL_COMMAND+'i', menu_file_insert_cb, nullptr, FL_MENU_DIVIDER}, + {"&Save", FL_COMMAND+'s', menu_file_save_cb, nullptr}, + {"Save &As...", FL_COMMAND+FL_SHIFT+'s', menu_file_save_cb, (void*)1}, + {"Sa&ve A Copy...", 0, menu_file_save_cb, (void*)2}, + {"&Revert...", 0, menu_file_revert_cb, nullptr, FL_MENU_DIVIDER}, + {"New &From Template...", FL_COMMAND+'N', menu_file_new_from_template_cb, nullptr}, + {"Save As &Template...", 0, save_template_cb, nullptr, FL_MENU_DIVIDER}, + {"&Print...", FL_COMMAND+'p', menu_file_print_cb}, + {"Write &Code", FL_COMMAND+FL_SHIFT+'c', write_cb, nullptr}, +// Matt: disabled {"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0}, + {"&Write Strings", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, nullptr, FL_MENU_DIVIDER}, + {Fluid.history.relpath[0], FL_COMMAND+'1', menu_file_open_history_cb, Fluid.history.abspath[0]}, + {Fluid.history.relpath[1], FL_COMMAND+'2', menu_file_open_history_cb, Fluid.history.abspath[1]}, + {Fluid.history.relpath[2], FL_COMMAND+'3', menu_file_open_history_cb, Fluid.history.abspath[2]}, + {Fluid.history.relpath[3], FL_COMMAND+'4', menu_file_open_history_cb, Fluid.history.abspath[3]}, + {Fluid.history.relpath[4], FL_COMMAND+'5', menu_file_open_history_cb, Fluid.history.abspath[4]}, + {Fluid.history.relpath[5], FL_COMMAND+'6', menu_file_open_history_cb, Fluid.history.abspath[5]}, + {Fluid.history.relpath[6], FL_COMMAND+'7', menu_file_open_history_cb, Fluid.history.abspath[6]}, + {Fluid.history.relpath[7], FL_COMMAND+'8', menu_file_open_history_cb, Fluid.history.abspath[7]}, + {Fluid.history.relpath[8], FL_COMMAND+'9', menu_file_open_history_cb, Fluid.history.abspath[8]}, + {Fluid.history.relpath[9], 0, menu_file_open_history_cb, Fluid.history.abspath[9], FL_MENU_DIVIDER}, + {"&Quit", FL_COMMAND+'q', exit_cb}, + {nullptr}, + {"&Edit",0,nullptr,nullptr,FL_SUBMENU}, + {"&Undo", FL_COMMAND+'z', fld::proj::Undo::undo_cb}, + {"&Redo", FL_COMMAND+FL_SHIFT+'z', fld::proj::Undo::redo_cb, nullptr, FL_MENU_DIVIDER}, + {"C&ut", FL_COMMAND+'x', cut_cb}, + {"&Copy", FL_COMMAND+'c', copy_cb}, + {"&Paste", FL_COMMAND+'v', paste_cb}, + {"Dup&licate", FL_COMMAND+'u', duplicate_cb}, + {"&Delete", FL_Delete, delete_cb, nullptr, FL_MENU_DIVIDER}, + {"Select &All", FL_COMMAND+'a', select_all_cb}, + {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, nullptr, FL_MENU_DIVIDER}, + {"Pr&operties...", FL_F+1, openwidget_cb}, + {"&Sort",0,sort_cb}, + {"&Earlier", FL_F+2, earlier_cb}, + {"&Later", FL_F+3, later_cb}, + {"&Group", FL_F+7, group_cb}, + {"Ung&roup", FL_F+8, ungroup_cb,nullptr, FL_MENU_DIVIDER}, + {"Hide O&verlays",FL_COMMAND+FL_SHIFT+'o',toggle_overlays}, + {"Hide Guides",FL_COMMAND+FL_SHIFT+'g',toggle_guides}, + {"Hide Restricted",FL_COMMAND+FL_SHIFT+'r',toggle_restricted}, + {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, + {"Show Code View",FL_ALT+'c', (Fl_Callback*)toggle_codeview_cb, nullptr, FL_MENU_DIVIDER}, + {"Settings...",FL_ALT+'p',show_settings_cb}, + {nullptr}, + {"&New", 0, nullptr, (void *)New_Menu, FL_SUBMENU_POINTER}, + {"&Layout",0,nullptr,nullptr,FL_SUBMENU}, + {"&Align",0,nullptr,nullptr,FL_SUBMENU}, + {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, + {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, + {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, + {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, + {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, + {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, + {nullptr}, + {"&Space Evenly",0,nullptr,nullptr,FL_SUBMENU}, + {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, + {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, + {nullptr}, + {"&Make Same Size",0,nullptr,nullptr,FL_SUBMENU}, + {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, + {"&Height",0,(Fl_Callback *)align_widget_cb,(void*)31}, + {"&Both",0,(Fl_Callback *)align_widget_cb,(void*)32}, + {nullptr}, + {"&Center In Group",0,nullptr,nullptr,FL_SUBMENU}, + {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, + {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, + {nullptr}, + {"Synchronized Resize", 0, (Fl_Callback*)menu_layout_sync_resize_cb, nullptr, FL_MENU_TOGGLE|FL_MENU_DIVIDER }, + {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb, nullptr, FL_MENU_DIVIDER}, + {"Presets", 0, layout_suite_marker, (void*)main_layout_submenu_, FL_SUBMENU_POINTER }, + {"Application", 0, select_layout_preset_cb, (void*)nullptr, 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 }, + {nullptr}, +{"&Shell", 0, Fd_Shell_Command_List::menu_marker, (void*)Fd_Shell_Command_List::default_menu, FL_SUBMENU_POINTER}, + {"&Help",0,nullptr,nullptr,FL_SUBMENU}, + {"&Rapid development with FLUID...",0,help_cb}, + {"&FLTK Programmers Manual...",0,manual_cb, nullptr, FL_MENU_DIVIDER}, + {"&About FLUID...",0,about_cb}, + {nullptr}, +{nullptr}}; + +/** +Show or hide the code preview window. +*/ +void toggle_codeview_cb(Fl_Double_Window *, void *) { + codeview_toggle_visibility(); +} + +/** +Show or hide the code preview window, button callback. +*/ +void toggle_codeview_b_cb(Fl_Button*, void *) { + codeview_toggle_visibility(); +} + diff --git a/fluid/app/Menu.h b/fluid/app/Menu.h new file mode 100644 index 000000000..43f5d7e6f --- /dev/null +++ b/fluid/app/Menu.h @@ -0,0 +1,29 @@ +// +// Application Main Menu header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_APP_MENU_H +#define FLUID_APP_MENU_H + +#include + +extern void exit_cb(class Fl_Widget *,void *); // TODO: remove this +extern void toggle_widgetbin_cb(Fl_Widget *, void *); +extern void menu_file_save_cb(Fl_Widget *, void *arg); +extern void menu_file_open_history_cb(Fl_Widget *, void *v); +extern void align_widget_cb(Fl_Widget *, long); + +#endif // FLUID_APP_MENU_H + diff --git a/fluid/app/Fd_Snap_Action.cxx b/fluid/app/Snap_Action.cxx similarity index 79% rename from fluid/app/Fd_Snap_Action.cxx rename to fluid/app/Snap_Action.cxx index 0a407ac8d..f33054eca 100644 --- a/fluid/app/Fd_Snap_Action.cxx +++ b/fluid/app/Snap_Action.cxx @@ -1,7 +1,7 @@ // // Snap action code file for the Fast Light Tool Kit (FLTK). // -// Copyright 2023 by Bill Spitzak and others. +// Copyright 2023-2025 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 @@ -14,19 +14,28 @@ // https://www.fltk.org/bugs.php // -#include "app/Fd_Snap_Action.h" +#include "app/Snap_Action.h" +#include "Fluid.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" -#include "nodes/Fl_Group_Type.h" +#include "nodes/Group_Node.h" +#include "nodes/Window_Node.h" #include "panels/settings_panel.h" #include #include #include + #include #include #include +#undef min +#undef max +#include + +using namespace fld; +using namespace fld::app; // 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?) @@ -34,10 +43,10 @@ void select_layout_suite_cb(Fl_Widget *, void *user_data); -int Fd_Snap_Action::eex = 0; -int Fd_Snap_Action::eey = 0; +int Snap_Action::eex = 0; +int Snap_Action::eey = 0; -static Fd_Layout_Preset fltk_app = { +static 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 @@ -45,7 +54,7 @@ static Fd_Layout_Preset fltk_app = { 20, 4, 8, // widget_y: min, inc, gap 0, 14, -1, 14 // labelfont/size, textfont/size }; -static Fd_Layout_Preset fltk_dlg = { +static 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 @@ -53,7 +62,7 @@ static Fd_Layout_Preset fltk_dlg = { 20, 5, 5, // widget_y: min, inc, gap 0, 11, -1, 11 // labelfont/size, textfont/size }; -static Fd_Layout_Preset fltk_tool = { +static 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 @@ -62,7 +71,7 @@ static Fd_Layout_Preset fltk_tool = { 0, 10, -1, 10 // labelfont/size, textfont/size }; -static Fd_Layout_Preset grid_app = { +static 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 @@ -71,7 +80,7 @@ static Fd_Layout_Preset grid_app = { 0, 14, -1, 14 // labelfont/size, textfont/size }; -static Fd_Layout_Preset grid_dlg = { +static 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 @@ -80,7 +89,7 @@ static Fd_Layout_Preset grid_dlg = { 0, 12, -1, 12 // labelfont/size, textfont/size }; -static Fd_Layout_Preset grid_tool = { +static 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 @@ -89,25 +98,25 @@ static Fd_Layout_Preset grid_tool = { 0, 10, -1, 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 } +Layout_Preset *fld::app::default_layout_preset = &fltk_app; + +static Layout_Suite static_suite_list[] = { + { (char*)"FLTK", (char*)"@fd_beaker FLTK", { &fltk_app, &fltk_dlg, &fltk_tool }, fld::Tool_Store::INTERNAL }, + { (char*)"Grid", (char*)"@fd_beaker Grid", { &grid_app, &grid_dlg, &grid_tool }, fld::Tool_Store::INTERNAL } }; Fl_Menu_Item main_layout_submenu_[] = { { 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 } + { nullptr } }; static Fl_Menu_Item static_choice_menu[] = { { static_suite_list[0].menu_label }, { static_suite_list[1].menu_label }, - { NULL } + { nullptr } }; -Fd_Layout_Preset *layout = &fltk_app; -Fd_Layout_List g_layout_list; // ---- Callbacks ------------------------------------------------------ MARK: - @@ -118,17 +127,17 @@ void layout_suite_marker(Fl_Widget *, void *) { 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(); + assert(index < Fluid.layout_list.list_size_); + Fluid.layout_list.current_suite(index); + Fluid.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(); + Fluid.layout_list.current_preset(index); + Fluid.layout_list.update_dialogs(); } void edit_layout_preset_cb(Fl_Button *w, long user_data) { @@ -136,19 +145,19 @@ void edit_layout_preset_cb(Fl_Button *w, long user_data) { assert(index >= 0); assert(index < 3); if (user_data == (long)(fl_intptr_t)LOAD) { - w->value(g_layout_list.current_preset() == index); + w->value(Fluid.layout_list.current_preset() == index); } else { - g_layout_list.current_preset(index); - g_layout_list.update_dialogs(); + Fluid.layout_list.current_preset(index); + Fluid.layout_list.update_dialogs(); } } -// ---- Fd_Layout_Suite ------------------------------------------------ MARK: - +// ---- Layout_Suite ------------------------------------------------ MARK: - /** Write presets to a Preferences database. */ -void Fd_Layout_Preset::write(Fl_Preferences &prefs) { +void Layout_Preset::write(Fl_Preferences &prefs) { assert(this); Fl_Preferences p_win(prefs, "Window"); p_win.set("left_margin", left_window_margin); @@ -188,7 +197,7 @@ void Fd_Layout_Preset::write(Fl_Preferences &prefs) { /** Read presets from a Preferences database. */ -void Fd_Layout_Preset::read(Fl_Preferences &prefs) { +void Layout_Preset::read(Fl_Preferences &prefs) { assert(this); Fl_Preferences p_win(prefs, "Window"); p_win.get("left_margin", left_window_margin, 15); @@ -228,7 +237,7 @@ void Fd_Layout_Preset::read(Fl_Preferences &prefs) { /** Write presets to an .fl project file. */ -void Fd_Layout_Preset::write(fld::io::Project_Writer *out) { +void Layout_Preset::write(fld::io::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, @@ -250,7 +259,7 @@ void Fd_Layout_Preset::write(fld::io::Project_Writer *out) { /** Read presets from an .fl project file. */ -void Fd_Layout_Preset::read(fld::io::Project_Reader *in) { +void Layout_Preset::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { @@ -306,7 +315,7 @@ void Fd_Layout_Preset::read(fld::io::Project_Reader *in) { /** Return the preferred text size, but make sure it's not 0. */ -int Fd_Layout_Preset::textsize_not_null() { +int Layout_Preset::textsize_not_null() { // try the user selected text size if (textsize > 0) return textsize; // if the user did not set one, try the label size @@ -316,12 +325,12 @@ int Fd_Layout_Preset::textsize_not_null() { } -// ---- Fd_Layout_Suite ------------------------------------------------ MARK: - +// ---- Layout_Suite ------------------------------------------------ MARK: - /** Write a presets suite to a Preferences database. */ -void Fd_Layout_Suite::write(Fl_Preferences &prefs) { +void Layout_Suite::write(Fl_Preferences &prefs) { assert(this); assert(name_); prefs.set("name", name_); @@ -335,7 +344,7 @@ void Fd_Layout_Suite::write(Fl_Preferences &prefs) { /** Read a presets suite from a Preferences database. */ -void Fd_Layout_Suite::read(Fl_Preferences &prefs) { +void Layout_Suite::read(Fl_Preferences &prefs) { assert(this); for (int i = 0; i < 3; ++i) { Fl_Preferences prefs_preset(prefs, Fl_Preferences::Name(i)); @@ -347,7 +356,7 @@ void Fd_Layout_Suite::read(Fl_Preferences &prefs) { /** Write a presets suite to an .fl project file. */ -void Fd_Layout_Suite::write(fld::io::Project_Writer *out) { +void Layout_Suite::write(fld::io::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) { @@ -359,7 +368,7 @@ void Fd_Layout_Suite::write(fld::io::Project_Writer *out) { /** Read a presets suite from an .fl project file. */ -void Fd_Layout_Suite::read(fld::io::Project_Reader *in) { +void Layout_Suite::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { @@ -387,57 +396,57 @@ void Fd_Layout_Suite::read(fld::io::Project_Reader *in) { \brief Update the menu_label to show a symbol representing the storage location. Also updates the FLUID user interface. */ -void Fd_Layout_Suite::update_label() { +void Layout_Suite::update_label() { std::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; + case fld::Tool_Store::INTERNAL: sym.assign("@fd_beaker "); break; + case fld::Tool_Store::USER: sym.assign("@fd_user "); break; + case fld::Tool_Store::PROJECT: sym.assign("@fd_project "); break; + case fld::Tool_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(); + Fluid.layout_list.update_menu_labels(); } /** \brief Update the Suite name and the Suite menu_label. Also updates the FLUID user interface. */ -void Fd_Layout_Suite::name(const char *n) { +void Layout_Suite::name(const char *n) { if (name_) ::free(name_); if (n) name_ = fl_strdup(n); else - name_ = NULL; + name_ = nullptr; update_label(); } /** Initialize the class for first use. */ -void Fd_Layout_Suite::init() { - name_ = NULL; - menu_label = NULL; - layout[0] = layout[1] = layout[2] = NULL; - storage_ = FD_STORE_INTERNAL; +void Layout_Suite::init() { + name_ = nullptr; + menu_label = nullptr; + layout[0] = layout[1] = layout[2] = nullptr; + storage_ = fld::Tool_Store::INTERNAL; } /** Free all allocated resources. */ -Fd_Layout_Suite::~Fd_Layout_Suite() { - if (storage_ == FD_STORE_INTERNAL) return; +Layout_Suite::~Layout_Suite() { + if (storage_ == fld::Tool_Store::INTERNAL) return; if (name_) ::free(name_); for (int i = 0; i < 3; ++i) { delete layout[i]; } } -// ---- Fd_Layout_List ------------------------------------------------- MARK: - +// ---- Layout_List ------------------------------------------------- MARK: - /** Draw a little FLUID beaker symbol. @@ -580,7 +589,7 @@ void fd_file(Fl_Color c) { /** Instantiate the class that holds a list of all layouts and manages the UI. */ -Fd_Layout_List::Fd_Layout_List() +Layout_List::Layout_List() : main_menu_(main_layout_submenu_), choice_menu_(static_choice_menu), list_(static_suite_list), @@ -599,15 +608,15 @@ Fd_Layout_List::Fd_Layout_List() /** Release allocated resources. */ -Fd_Layout_List::~Fd_Layout_List() { +Layout_List::~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(); + Layout_Suite &suite = list_[i]; + if (suite.storage_ != fld::Tool_Store::INTERNAL) + suite.~Layout_Suite(); } ::free(list_); } @@ -616,10 +625,10 @@ Fd_Layout_List::~Fd_Layout_List() { /** Update the Setting dialog and menus to reflect the current Layout selection state. */ -void Fd_Layout_List::update_dialogs() { - static Fl_Menu_Item *preset_menu = NULL; +void Layout_List::update_dialogs() { + static Fl_Menu_Item *preset_menu = nullptr; if (!preset_menu) { - preset_menu = (Fl_Menu_Item*)main_menubar->find_item(select_layout_preset_cb); + preset_menu = (Fl_Menu_Item*)Fluid.main_menubar->find_item(select_layout_preset_cb); assert(preset_menu); } assert(this); @@ -627,8 +636,8 @@ void Fd_Layout_List::update_dialogs() { assert(current_suite_ < list_size_); assert(current_preset_ >= 0 ); assert(current_preset_ < 3); - layout = list_[current_suite_].layout[current_preset_]; - assert(layout); + Fluid.proj.layout = list_[current_suite_].layout[current_preset_]; + assert(Fluid.proj.layout); if (w_settings_layout_tab) { w_settings_layout_tab->do_callback(w_settings_layout_tab, LOAD); layout_choice->redraw(); @@ -640,7 +649,7 @@ void Fd_Layout_List::update_dialogs() { /** Refresh the label pointers for both pulldown menus. */ -void Fd_Layout_List::update_menu_labels() { +void Layout_List::update_menu_labels() { for (int i=0; iwrite_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; iwrite_string("}"); @@ -737,7 +746,7 @@ void Fd_Layout_List::write(fld::io::Project_Writer *out) { /** Read Suite and Layout selection and project layout data from an .fl project file. */ -void Fd_Layout_List::read(fld::io::Project_Reader *in) { +void Layout_List::read(fld::io::Project_Reader *in) { const char *key; key = in->read_word(1); if (key && !strcmp(key, "{")) { @@ -755,7 +764,7 @@ void Fd_Layout_List::read(fld::io::Project_Reader *in) { } else if (!strcmp(key, "suite")) { int n = add(in->filename_name()); list_[n].read(in); - list_[n].storage(FD_STORE_PROJECT); + list_[n].storage(fld::Tool_Store::PROJECT); } else if (!strcmp(key, "}")) { break; } else { @@ -774,11 +783,11 @@ void Fd_Layout_List::read(fld::io::Project_Reader *in) { Set the current Suite. \param[in] ix index into list of suites */ -void Fd_Layout_List::current_suite(int ix) { +void Layout_List::current_suite(int ix) { assert(ix >= 0); assert(ix < list_size_); current_suite_ = ix; - layout = list_[current_suite_].layout[current_preset_]; + Fluid.proj.layout = list_[current_suite_].layout[current_preset_]; } /** @@ -786,10 +795,10 @@ void Fd_Layout_List::current_suite(int ix) { \param[in] arg_name name of the selected suite \return if no name is given or the name is not found, keep the current suite selected */ -void Fd_Layout_List::current_suite(std::string arg_name) { +void Layout_List::current_suite(std::string arg_name) { if (arg_name.empty()) return; for (int i = 0; i < list_size_; ++i) { - Fd_Layout_Suite &suite = list_[i]; + Layout_Suite &suite = list_[i]; if (suite.name_ && (strcmp(suite.name_, arg_name.c_str()) == 0)) { current_suite(i); break; @@ -801,25 +810,25 @@ void Fd_Layout_List::current_suite(std::string arg_name) { Select a Preset within the current Suite. \param[in] ix 0 = application, 1 = dialog, 2 = toolbox */ -void Fd_Layout_List::current_preset(int ix) { +void Layout_List::current_preset(int ix) { assert(ix >= 0); assert(ix < 3); current_preset_ = ix; - layout = list_[current_suite_].layout[current_preset_]; + Fluid.proj.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; +void Layout_List::capacity(int n) { + static Fl_Menu_Item *suite_menu = nullptr; if (!suite_menu) - suite_menu = (Fl_Menu_Item*)main_menubar->find_item(layout_suite_marker); + suite_menu = (Fl_Menu_Item*)Fluid.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)); + Layout_Suite *new_list = (Layout_Suite*)::calloc(n, sizeof(Layout_Suite)); for (i = 0; i < old_n; i++) new_list[i] = list_[i]; if (!list_is_static_) ::free(list_); @@ -847,22 +856,22 @@ void Fd_Layout_List::capacity(int n) { \brief Clone the currently selected suite and append it to the list. Selects the new layout and updates the UI. */ -int Fd_Layout_List::add(const char *name) { +int 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]; + Layout_Suite &old_suite = list_[current_suite_]; + 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)); + new_suite.layout[i] = new Layout_Preset; + ::memcpy(new_suite.layout[i], old_suite.layout[i], sizeof(Layout_Preset)); } - Fd_Tool_Store new_storage = old_suite.storage_; - if (new_storage == FD_STORE_INTERNAL) - new_storage = FD_STORE_USER; + fld::Tool_Store new_storage = old_suite.storage_; + if (new_storage == fld::Tool_Store::INTERNAL) + new_storage = fld::Tool_Store::USER; new_suite.storage(new_storage); main_menu_[n].label(new_suite.menu_label); main_menu_[n].callback(main_menu_[0].callback()); @@ -877,7 +886,7 @@ int Fd_Layout_List::add(const char *name) { /** Rename the current Suite. */ -void Fd_Layout_List::rename(const char *name) { +void Layout_List::rename(const char *name) { int n = current_suite(); list_[n].name(name); main_menu_[n].label(list_[n].menu_label); @@ -888,7 +897,7 @@ void Fd_Layout_List::rename(const char *name) { Remove the given suite. \param[in] ix index into list of suites */ -void Fd_Layout_List::remove(int ix) { +void Layout_List::remove(int ix) { int tail = list_size_-ix-1; if (tail) { for (int i = ix; i < list_size_-1; i++) @@ -903,9 +912,9 @@ void Fd_Layout_List::remove(int ix) { /** Remove all Suites that use the given storage attribute. - \param[in] storage storage attribute, see FD_STORE_INTERNAL, etc. + \param[in] storage storage attribute, see fld::Tool_Store::INTERNAL, etc. */ -void Fd_Layout_List::remove_all(Fd_Tool_Store storage) { +void Layout_List::remove_all(fld::Tool_Store storage) { for (int i=list_size_-1; i>=0; --i) { if (list_[i].storage_ == storage) remove(i); @@ -931,25 +940,25 @@ static int nearest(int x, int left, int grid, int right=0x7fff) { return grid_x; } -static bool in_window(Fd_Snap_Data &d) { +static bool in_window(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_a(ID_Group) && d.wgt->parent != d.win); +static bool in_group(Snap_Data &d) { + return (d.wgt && d.wgt->parent && d.wgt->parent->is_a(Type::Group) && d.wgt->parent != d.win); } -static bool in_tabs(Fd_Snap_Data &d) { - return (d.wgt && d.wgt->parent && d.wgt->parent->is_a(ID_Tabs)); +static bool in_tabs(Snap_Data &d) { + return (d.wgt && d.wgt->parent && d.wgt->parent->is_a(Type::Tabs)); } -static Fl_Group *parent(Fd_Snap_Data &d) { +static Fl_Group *parent(Snap_Data &d) { return (d.wgt->o->parent()); } -// ---- Fd_Snap_Action ------------------------------------------------- MARK: - +// ---- Snap_Action ------------------------------------------------- MARK: - -/** \class Fd_Snap_Action +/** \class Snap_Action When a user drags one or more widgets, snap actions can be defined that provide hints if a preferred widget position or size is nearby. The user's motion is @@ -974,7 +983,7 @@ static Fl_Group *parent(Fd_Snap_Data &d) { \return -1 if this point is closer than any previous check, and this is the new distance to beat. */ -int Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) { +int Snap_Action::check_x_(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; @@ -987,9 +996,9 @@ int Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) { /** \brief Check if a snap action has reached a preferred y position. - \see Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) + \see Snap_Action::check_x_(Snap_Data &d, int x_ref, int x_snap) */ -int Fd_Snap_Action::check_y_(Fd_Snap_Data &d, int y_ref, int y_snap) { +int Snap_Action::check_y_(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; @@ -1002,9 +1011,9 @@ int Fd_Snap_Action::check_y_(Fd_Snap_Data &d, int y_ref, int y_snap) { /** \brief Check if a snap action has reached a preferred x and y position. - \see Fd_Snap_Action::check_x_(Fd_Snap_Data &d, int x_ref, int x_snap) + \see Snap_Action::check_x_(Snap_Data &d, int x_ref, int x_snap) */ -void Fd_Snap_Action::check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_ref, int y_snap) { +void Snap_Action::check_x_y_(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; @@ -1025,7 +1034,7 @@ void Fd_Snap_Action::check_x_y_(Fd_Snap_Data &d, int x_ref, int x_snap, int y_re should be drawn. \param[inout] d current event data */ -bool Fd_Snap_Action::matches(Fd_Snap_Data &d) { +bool Snap_Action::matches(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); @@ -1038,7 +1047,7 @@ bool Fd_Snap_Action::matches(Fd_Snap_Data &d) { \brief Run through all possible snap actions and store the winning coordinates in eex and eey. \param[inout] d current event data */ -void Fd_Snap_Action::check_all(Fd_Snap_Data &data) { +void Snap_Action::check_all(Snap_Data &data) { for (int i=0; list[i]; i++) { if (list[i]->mask & data.drag) list[i]->check(data); @@ -1054,7 +1063,7 @@ void Fd_Snap_Action::check_all(Fd_Snap_Data &data) { coordinate, all of them will be drawn. \param[inout] d current event data */ -void Fd_Snap_Action::draw_all(Fd_Snap_Data &data) { +void Snap_Action::draw_all(Snap_Data &data) { for (int i=0; list[i]; i++) { if (list[i]->matches(data)) list[i]->draw(data); @@ -1062,7 +1071,8 @@ void Fd_Snap_Action::draw_all(Fd_Snap_Data &data) { } /** Return a sensible step size for resizing a widget. */ -void Fd_Snap_Action::get_resize_stepsize(int &x_step, int &y_step) { +void Snap_Action::get_resize_stepsize(int &x_step, int &y_step) { + auto layout = Fluid.proj.layout; if ((layout->widget_inc_w > 1) && (layout->widget_inc_h > 1)) { x_step = layout->widget_inc_w; y_step = layout->widget_inc_h; @@ -1076,7 +1086,8 @@ void Fd_Snap_Action::get_resize_stepsize(int &x_step, int &y_step) { } /** Return a sensible step size for moving a widget. */ -void Fd_Snap_Action::get_move_stepsize(int &x_step, int &y_step) { +void Snap_Action::get_move_stepsize(int &x_step, int &y_step) { + auto layout = Fluid.proj.layout; if ((layout->group_grid_x > 1) && (layout->group_grid_y > 1)) { x_step = layout->group_grid_x; y_step = layout->group_grid_y; @@ -1090,7 +1101,8 @@ void Fd_Snap_Action::get_move_stepsize(int &x_step, int &y_step) { } /** Fix the given size to the same or next bigger snap position. */ -void Fd_Snap_Action::better_size(int &w, int &h) { +void Snap_Action::better_size(int &w, int &h) { + auto layout = Fluid.proj.layout; int x_min = 1, y_min = 1, x_inc = 1, y_inc = 1; get_resize_stepsize(x_inc, y_inc); if (x_inc < 1) x_inc = 1; @@ -1105,8 +1117,8 @@ void Fd_Snap_Action::better_size(int &w, int &h) { x_min = x_inc; y_min = y_inc; } - int ww = fd_max(w - x_min, 0); w = (w - ww + x_inc - 1) / x_inc; w = w * x_inc; w = w + ww; - int hh = fd_max(h - y_min, 0); h = (h - hh + y_inc - 1) / y_inc; h = h * y_inc; h = h + hh; + int ww = std::max(w - x_min, 0); w = (w - ww + x_inc - 1) / x_inc; w = w * x_inc; w = w + ww; + int hh = std::max(h - y_min, 0); h = (h - hh + y_inc - 1) / y_inc; h = h * y_inc; h = h + hh; } @@ -1115,7 +1127,7 @@ void Fd_Snap_Action::better_size(int &w, int &h) { /** Base class for all actions that drag the left side or the entire widget. */ -class Fd_Snap_Left : public Fd_Snap_Action { +class Fd_Snap_Left : public Snap_Action { public: Fd_Snap_Left() { type = 1; mask = FD_LEFT|FD_DRAG; } }; @@ -1123,7 +1135,7 @@ public: /** Base class for all actions that drag the right side or the entire widget. */ -class Fd_Snap_Right : public Fd_Snap_Action { +class Fd_Snap_Right : public Snap_Action { public: Fd_Snap_Right() { type = 1; mask = FD_RIGHT|FD_DRAG; } }; @@ -1131,7 +1143,7 @@ public: /** Base class for all actions that drag the top side or the entire widget. */ -class Fd_Snap_Top : public Fd_Snap_Action { +class Fd_Snap_Top : public Snap_Action { public: Fd_Snap_Top() { type = 2; mask = FD_TOP|FD_DRAG; } }; @@ -1139,7 +1151,7 @@ public: /** Base class for all actions that drag the bottom side or the entire widget. */ -class Fd_Snap_Bottom : public Fd_Snap_Action { +class Fd_Snap_Bottom : public Snap_Action { public: Fd_Snap_Bottom() { type = 2; mask = FD_BOTTOM|FD_DRAG; } }; @@ -1151,8 +1163,8 @@ public: */ 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); }; + void check(Snap_Data &d) override { clr(); check_x_(d, d.bx, 0); } + void draw(Snap_Data &d) override { draw_left_brace(d.win->o); }; }; Fd_Snap_Left_Window_Edge snap_left_window_edge; @@ -1161,8 +1173,8 @@ 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); }; + void check(Snap_Data &d) override { clr(); check_x_(d, d.br, d.win->o->w()); } + void draw(Snap_Data &d) override { draw_right_brace(d.win->o); }; }; Fd_Snap_Right_Window_Edge snap_right_window_edge; @@ -1171,8 +1183,8 @@ 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); }; + void check(Snap_Data &d) override { clr(); check_y_(d, d.by, 0); } + void draw(Snap_Data &d) override { draw_top_brace(d.win->o); }; }; Fd_Snap_Top_Window_Edge snap_top_window_edge; @@ -1181,8 +1193,8 @@ 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); }; + void check(Snap_Data &d) override { clr(); check_y_(d, d.bt, d.win->o->h()); } + void draw(Snap_Data &d) override { draw_bottom_brace(d.win->o); }; }; Fd_Snap_Bottom_Window_Edge snap_bottom_window_edge; @@ -1191,11 +1203,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_window(d)) check_x_(d, d.bx, layout->left_window_margin); + if (in_window(d)) check_x_(d, d.bx, Fluid.proj.layout->left_window_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_h_arrow(d.bx, (d.by+d.bt)/2, 0); }; }; @@ -1203,11 +1215,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_window(d)) check_x_(d, d.br, d.win->o->w()-layout->right_window_margin); + if (in_window(d)) check_x_(d, d.br, d.win->o->w()-Fluid.proj.layout->right_window_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_h_arrow(d.br, (d.by+d.bt)/2, d.win->o->w()-1); }; }; @@ -1215,11 +1227,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_window(d)) check_y_(d, d.by, layout->top_window_margin); + if (in_window(d)) check_y_(d, d.by, Fluid.proj.layout->top_window_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_v_arrow((d.bx+d.br)/2, d.by, 0); }; }; @@ -1227,11 +1239,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_window(d)) check_y_(d, d.bt, d.win->o->h()-layout->bottom_window_margin); + if (in_window(d)) check_y_(d, d.bt, d.win->o->h()-Fluid.proj.layout->bottom_window_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_v_arrow((d.bx+d.br)/2, d.bt, d.win->o->h()-1); }; }; @@ -1244,11 +1256,11 @@ Fd_Snap_Bottom_Window_Margin snap_bottom_window_margin; */ class Fd_Snap_Left_Group_Edge : public Fd_Snap_Left { public: - void check(Fd_Snap_Data &d) FL_OVERRIDE { + void check(Snap_Data &d) override { clr(); if (in_group(d)) check_x_(d, d.bx, parent(d)->x()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_left_brace(parent(d)); }; }; @@ -1256,11 +1268,11 @@ 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 { + void check(Snap_Data &d) 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 { + void draw(Snap_Data &d) override { draw_right_brace(parent(d)); }; }; @@ -1268,11 +1280,11 @@ 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 { + void check(Snap_Data &d) override { clr(); if (in_group(d)) check_y_(d, d.by, parent(d)->y()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_top_brace(parent(d)); }; }; @@ -1280,11 +1292,11 @@ 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 { + void check(Snap_Data &d) 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 { + void draw(Snap_Data &d) override { draw_bottom_brace(parent(d)); }; }; @@ -1296,11 +1308,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_group(d)) check_x_(d, d.bx, parent(d)->x() + layout->left_group_margin); + if (in_group(d)) check_x_(d, d.bx, parent(d)->x() + Fluid.proj.layout->left_group_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_left_brace(parent(d)); draw_h_arrow(d.bx, (d.by+d.bt)/2, parent(d)->x()); }; @@ -1309,11 +1321,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_group(d)) check_x_(d, d.br, parent(d)->x()+parent(d)->w()-layout->right_group_margin); + if (in_group(d)) check_x_(d, d.br, parent(d)->x()+parent(d)->w()-Fluid.proj.layout->right_group_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_right_brace(parent(d)); draw_h_arrow(d.br, (d.by+d.bt)/2, parent(d)->x()+parent(d)->w()-1); }; @@ -1322,11 +1334,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_group(d) && !in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_group_margin); + if (in_group(d) && !in_tabs(d)) check_y_(d, d.by, parent(d)->y()+Fluid.proj.layout->top_group_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_top_brace(parent(d)); draw_v_arrow((d.bx+d.br)/2, d.by, parent(d)->y()); }; @@ -1335,11 +1347,11 @@ 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 { + void check(Snap_Data &d) override { clr(); - if (in_group(d) && !in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_group_margin); + if (in_group(d) && !in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-Fluid.proj.layout->bottom_group_margin); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_bottom_brace(parent(d)); draw_v_arrow((d.bx+d.br)/2, d.bt, parent(d)->y()+parent(d)->h()-1); }; @@ -1353,18 +1365,18 @@ Fd_Snap_Bottom_Group_Margin snap_bottom_group_margin; */ class Fd_Snap_Top_Tabs_Margin : public Fd_Snap_Top_Group_Margin { public: - void check(Fd_Snap_Data &d) FL_OVERRIDE { + void check(Snap_Data &d) override { clr(); - if (in_tabs(d)) check_y_(d, d.by, parent(d)->y()+layout->top_tabs_margin); + if (in_tabs(d)) check_y_(d, d.by, parent(d)->y()+Fluid.proj.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 { + void check(Snap_Data &d) override { clr(); - if (in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-layout->bottom_tabs_margin); + if (in_tabs(d)) check_y_(d, d.bt, parent(d)->y()+parent(d)->h()-Fluid.proj.layout->bottom_tabs_margin); } }; Fd_Snap_Bottom_Tabs_Margin snap_bottom_tabs_margin; @@ -1374,12 +1386,12 @@ Fd_Snap_Bottom_Tabs_Margin snap_bottom_tabs_margin; /** Base class for grid based snapping. */ -class Fd_Snap_Grid : public Fd_Snap_Action { +class Fd_Snap_Grid : public 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) { + void check_grid(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); @@ -1392,7 +1404,7 @@ public: else check_x_y_(d, d.bx, nearest_x, d.by, nearest_y); } - bool matches(Fd_Snap_Data &d) FL_OVERRIDE { + bool matches(Snap_Data &d) 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); @@ -1404,12 +1416,14 @@ public: */ class Fd_Snap_Window_Grid : public Fd_Snap_Grid { public: - void check(Fd_Snap_Data &d) FL_OVERRIDE { + void check(Snap_Data &d) override { + auto layout = Fluid.proj.layout; 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 { + void draw(Snap_Data &d) override { + auto layout = Fluid.proj.layout; draw_grid(nearest_x, nearest_y, layout->window_grid_x, layout->window_grid_y); }; }; @@ -1420,15 +1434,17 @@ 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 { + void check(Snap_Data &d) override { if (in_group(d)) { + auto layout = Fluid.proj.layout; 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 { + void draw(Snap_Data &d) override { + auto layout = Fluid.proj.layout; draw_grid(nearest_x, nearest_y, layout->group_grid_x, layout->group_grid_y); }; }; @@ -1439,19 +1455,19 @@ Fd_Snap_Group_Grid snap_group_grid; /** Base class the check distance to other widgets in the same group. */ -class Fd_Snap_Sibling : public Fd_Snap_Action { +class Fd_Snap_Sibling : public 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 { + Fd_Snap_Sibling() : best_match(nullptr) { } + virtual int sibling_check(Snap_Data &d, Fl_Widget *s) = 0; + void check(Snap_Data &d) override { clr(); - best_match = NULL; + best_match = nullptr; if (!d.wgt) return; - if (!d.wgt->parent->is_a(ID_Group)) return; + if (!d.wgt->parent->is_a(Type::Group)) return; int dsib_min = 1024; - Fl_Group_Type *gt = (Fl_Group_Type*)d.wgt->parent; + Group_Node *gt = (Group_Node*)d.wgt->parent; Fl_Group *g = (Fl_Group*)gt->o; Fl_Widget *w = d.wgt->o; for (int i=0; ichildren(); i++) { @@ -1479,10 +1495,10 @@ public: 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 { + int sibling_check(Snap_Data &d, Fl_Widget *s) override { return check_x_(d, d.bx, s->x()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_left_brace(best_match); }; }; @@ -1494,11 +1510,11 @@ 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) ); + int sibling_check(Snap_Data &d, Fl_Widget *s) override { + return std::min(check_x_(d, d.bx, s->x()+s->w()), + check_x_(d, d.bx, s->x()+s->w()+Fluid.proj.layout->widget_gap_x) ); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_right_brace(best_match); }; }; @@ -1507,10 +1523,10 @@ 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 { + int sibling_check(Snap_Data &d, Fl_Widget *s) override { return check_x_(d, d.br, s->x()+s->w()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_right_brace(best_match); }; }; @@ -1519,11 +1535,11 @@ 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)); + int sibling_check(Snap_Data &d, Fl_Widget *s) override { + return std::min(check_x_(d, d.br, s->x()), + check_x_(d, d.br, s->x()-Fluid.proj.layout->widget_gap_x)); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_left_brace(best_match); }; }; @@ -1532,10 +1548,10 @@ 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 { + int sibling_check(Snap_Data &d, Fl_Widget *s) override { return check_y_(d, d.by, s->y()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_top_brace(best_match); }; }; @@ -1544,11 +1560,11 @@ 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)); + int sibling_check(Snap_Data &d, Fl_Widget *s) override { + return std::min(check_y_(d, d.by, s->y()+s->h()), + check_y_(d, d.by, s->y()+s->h()+Fluid.proj.layout->widget_gap_y)); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_bottom_brace(best_match); }; }; @@ -1557,10 +1573,10 @@ 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 { + int sibling_check(Snap_Data &d, Fl_Widget *s) override { return check_y_(d, d.bt, s->y()+s->h()); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_bottom_brace(best_match); }; }; @@ -1569,11 +1585,11 @@ 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)); + int sibling_check(Snap_Data &d, Fl_Widget *s) override { + return std::min(check_y_(d, d.bt, s->y()), + check_y_(d, d.bt, s->y()-Fluid.proj.layout->widget_gap_y)); } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { if (best_match) draw_top_brace(best_match); }; }; @@ -1585,10 +1601,11 @@ Fd_Snap_Siblings_Bottom snap_siblings_bottom; /** Snap horizontal resizing to min_w or min_w and a multiple of inc_w. */ -class Fd_Snap_Widget_Ideal_Width : public Fd_Snap_Action { +class Fd_Snap_Widget_Ideal_Width : public Snap_Action { public: Fd_Snap_Widget_Ideal_Width() { type = 1; mask = FD_LEFT|FD_RIGHT; } - void check(Fd_Snap_Data &d) FL_OVERRIDE { + void check(Snap_Data &d) override { + auto layout = Fluid.proj.layout; clr(); if (!d.wgt) return; int iw = 15, ih = 15; @@ -1605,16 +1622,17 @@ public: check_x_(d, d.bx, d.br-iw); } } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) 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 { +class Fd_Snap_Widget_Ideal_Height : public Snap_Action { public: Fd_Snap_Widget_Ideal_Height() { type = 2; mask = FD_TOP|FD_BOTTOM; } - void check(Fd_Snap_Data &d) FL_OVERRIDE { + void check(Snap_Data &d) override { + auto layout = Fluid.proj.layout; clr(); if (!d.wgt) return; int iw, ih; @@ -1631,7 +1649,7 @@ public: check_y_(d, d.by, d.bt-ih); } } - void draw(Fd_Snap_Data &d) FL_OVERRIDE { + void draw(Snap_Data &d) override { draw_height(d.br+7, d.by, d.bt, 0); }; }; @@ -1646,7 +1664,7 @@ Fd_Snap_Widget_Ideal_Height snap_widget_ideal_height; action in the list wins. All snap actions with the same distance and same winning coordinates are drawn in the overlay plane. */ -Fd_Snap_Action *Fd_Snap_Action::list[] = { +Snap_Action *Snap_Action::list[] = { &snap_left_window_edge, &snap_right_window_edge, &snap_top_window_edge, @@ -1681,7 +1699,7 @@ Fd_Snap_Action *Fd_Snap_Action::list[] = { &snap_widget_ideal_width, &snap_widget_ideal_height, - NULL + nullptr }; // ---- draw alignment marks ------------------------------------------- MARK: - diff --git a/fluid/app/Fd_Snap_Action.h b/fluid/app/Snap_Action.h similarity index 73% rename from fluid/app/Fd_Snap_Action.h rename to fluid/app/Snap_Action.h index 0c98b56b8..e555f9a44 100644 --- a/fluid/app/Fd_Snap_Action.h +++ b/fluid/app/Snap_Action.h @@ -1,7 +1,7 @@ // // Snap action header file for the Fast Light Tool Kit (FLTK). // -// Copyright 2023 by Bill Spitzak and others. +// Copyright 2023-2025 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 @@ -17,15 +17,26 @@ #ifndef _FLUID_FD_SNAP_ACTION_H #define _FLUID_FD_SNAP_ACTION_H -#include "app/fluid.h" -#include "nodes/Fl_Window_Type.h" - #include +class Window_Node; +class Widget_Node; struct Fl_Menu_Item; +class Fl_Preferences; extern Fl_Menu_Item main_layout_submenu_[]; +namespace fld { +enum class Tool_Store; // fld:: +namespace io { +class Project_Reader; // fld::io:: +class Project_Writer; // fld::io:: +} // namespace io +} // namespace fld + +namespace fld { +namespace app { + /** \brief Collection of layout settings. @@ -34,7 +45,7 @@ extern Fl_Menu_Item main_layout_submenu_[]; There are three Presets available in one Suite, marked "application", "dialog", and "toolbox". */ -class Fd_Layout_Preset { +class Layout_Preset { public: int left_window_margin; ///< gap between the window border and the widget int right_window_margin; @@ -73,7 +84,7 @@ public: int textsize_not_null(); }; -extern Fd_Layout_Preset *layout; +extern Layout_Preset *default_layout_preset; /** \brief A collection of layout presets. @@ -83,25 +94,26 @@ extern Fd_Layout_Preset *layout; There are three Presets available in one Suite, marked "application", "dialog", and "toolbox". */ -class Fd_Layout_Suite { +class Layout_Suite { public: char *name_; ///< name of the suite char *menu_label; ///< label text used in pulldown menu - Fd_Layout_Preset *layout[3]; ///< presets for application, dialog, and toolbox windows - Fd_Tool_Store storage_; ///< storage location (see FD_STORE_INTERNAL, etc.) + Layout_Preset *layout[3]; ///< presets for application, dialog, and toolbox windows + fld::Tool_Store storage_; ///< storage location (see fld::Tool_Store::INTERNAL, etc.) void write(Fl_Preferences &prefs); void read(Fl_Preferences &prefs); void write(fld::io::Project_Writer*); void read(fld::io::Project_Reader*); void update_label(); - void storage(Fd_Tool_Store s) { storage_ = s; update_label(); } + void storage(fld::Tool_Store s) { storage_ = s; update_label(); } void name(const char *n); void init(); - ~Fd_Layout_Suite(); + ~Layout_Suite(); public: }; + /** \brief Manage all layout suites that are available to the user. @@ -109,11 +121,11 @@ public: as a user preference, as part of an .fl project file, or in a separate file for import/export and sharing. */ -class Fd_Layout_List { +class Layout_List { public: Fl_Menu_Item *main_menu_; Fl_Menu_Item *choice_menu_; - Fd_Layout_Suite *list_; + Layout_Suite *list_; int list_size_; int list_capacity_; bool list_is_static_; @@ -121,8 +133,8 @@ public: int current_preset_; std::string filename_; public: - Fd_Layout_List(); - ~Fd_Layout_List(); + Layout_List(); + ~Layout_List(); void update_dialogs(); void update_menu_labels(); int current_suite() const { return current_suite_; } @@ -130,64 +142,66 @@ public: void current_suite(std::string); int current_preset() const { return current_preset_; } void current_preset(int ix); - Fd_Layout_Suite &operator[](int ix) { return list_[ix]; } + Layout_Suite &operator[](int ix) { return list_[ix]; } int add(const char *name); void rename(const char *name); void capacity(int); int load(const std::string &filename); int save(const std::string &filename); - void write(Fl_Preferences &prefs, Fd_Tool_Store storage); - void read(Fl_Preferences &prefs, Fd_Tool_Store storage); + void write(Fl_Preferences &prefs, fld::Tool_Store storage); + void read(Fl_Preferences &prefs, fld::Tool_Store storage); void write(fld::io::Project_Writer*); void read(fld::io::Project_Reader*); - int add(Fd_Layout_Suite*); + int add(Layout_Suite*); void remove(int index); - void remove_all(Fd_Tool_Store storage); - Fd_Layout_Preset *at(int); + void remove_all(fld::Tool_Store storage); + 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 { +typedef struct 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 + Widget_Node *wgt; ///< first selected widget + Window_Node *win; ///< window that handles the drag action int ex_out, ey_out; ///< chosen snap position -} Fd_Snap_Data; +} Snap_Data; /** \brief Find points of interest when moving the bounding box of all selected widgets. */ -class Fd_Snap_Action { +class 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); + int check_x_(Snap_Data &d, int x_ref, int x_snap); + int check_y_(Snap_Data &d, int y_ref, int y_snap); + void check_x_y_(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 ~Fd_Snap_Action() { } - virtual void check(Fd_Snap_Data &d) = 0; - virtual void draw(Fd_Snap_Data &d) { } - virtual bool matches(Fd_Snap_Data &d); + Snap_Action() : ex(0x7fff), ey(0x7fff), dx(128), dy(128), type(0), mask(0) { } + virtual ~Snap_Action() { } + virtual void check(Snap_Data &d) = 0; + virtual void draw(Snap_Data &d) { } + virtual bool matches(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 Snap_Action *list[]; + static void check_all(Snap_Data &d); + static void draw_all(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); static void better_size(int &w, int &h); }; +} // namespace app +} // namespace fld + + #endif // _FLUID_FD_SNAP_ACTION_H diff --git a/fluid/app/args.cxx b/fluid/app/args.cxx new file mode 100644 index 000000000..b9d958e8c --- /dev/null +++ b/fluid/app/args.cxx @@ -0,0 +1,136 @@ +// +// Command Line Arguments Handling code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "app/args.h" + +#include "Fluid.h" + +#include +#include +#include + +using namespace fld; +using namespace fld::app; + +/** + Load args from command line into variables. + + \param[in] argc number of arguments in the list + \param[in] argv pointer to an array of arguments + \return 0 if the args were handled successfully, -1 if there was an error + and the usage message was shown. + */ +int Args::load(int argc,char **argv) { + int i = 1; + Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW + if ( (Fl::args(argc,argv,i,arg_cb) == 0) // unsupported argument found + || (Fluid.batch_mode && (i != argc-1)) // .fl filename missing + || (!Fluid.batch_mode && (i < argc-1)) // more than one filename found + || (argv[i] && (argv[i][0] == '-'))) { // unknown option + static const char *msg = + "usage: %s name.fl\n" + " -u : update .fl file and exit (may be combined with '-c' or '-cs')\n" + " -c : write .cxx and .h and exit\n" + " -cs : write .cxx and .h and strings and exit\n" + " -o : .cxx output filename, or extension if starts with '.'\n" + " -h : .h output filename, or extension if starts with '.'\n" + " --help : brief usage information\n" + " --version, -v : print fluid version number\n" + " -d : enable internal debugging\n"; + const char *app_name = nullptr; + if ( (argc > 0) && argv[0] && argv[0][0] ) + app_name = fl_filename_name(argv[0]); + if ( !app_name || !app_name[0]) + app_name = "fluid"; +#ifdef _MSC_VER + // TODO: if this is fluid-cmd, use stderr and not fl_message + fl_message(msg, app_name); +#else + fprintf(stderr, msg, app_name); +#endif + return -1; + } + return i; +} + + +int Args::arg_cb(int argc, char** argv, int& i) { + return Fluid.args.arg(argc, argv, i); +} + + +/** + Handle command line arguments. + \param[in] argc number of arguments in the list + \param[in] argv pointer to an array of arguments + \param[inout] i current argument index + \return number of arguments used; if 0, the argument is not supported + */ +int Args::arg(int argc, char** argv, int& i) { + if (argv[i][0] != '-') + return 0; + if (argv[i][1] == 'd' && !argv[i][2]) { + Fluid.debug_external_editor=1; + i++; return 1; + } + if (argv[i][1] == 'u' && !argv[i][2]) { + update_file++; + Fluid.batch_mode++; + i++; return 1; + } + if (argv[i][1] == 'c' && !argv[i][2]) { + compile_file++; + Fluid.batch_mode++; + i++; return 1; + } + if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "--version")==0)) { + show_version = 1; + i++; return 1; + } + if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) { + compile_file++; + compile_strings++; + Fluid.batch_mode++; + i++; return 1; + } + if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { + code_filename = argv[i+1]; + Fluid.batch_mode++; + i += 2; return 2; + } +#ifndef NDEBUG + if ((i+1 < argc) && (strcmp(argv[i], "--autodoc") == 0)) { + autodoc_path = argv[i+1]; + i += 2; return 2; + } +#endif + if (strcmp(argv[i], "--help")==0) { + return 0; + } + if (argv[i][1] == 'h' && !argv[i][2]) { + if ( (i+1 < argc) && (argv[i+1][0] != '-') ) { + header_filename = argv[i+1]; + Fluid.batch_mode++; + i += 2; + return 2; + } else { + // a lone "-h" without a filename will output the help string + return 0; + } + } + return 0; +} + diff --git a/fluid/app/args.h b/fluid/app/args.h new file mode 100644 index 000000000..80dfa2290 --- /dev/null +++ b/fluid/app/args.h @@ -0,0 +1,55 @@ +// +// Command Line Arguments Handling header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_APP_ARGS_H +#define FLUID_APP_ARGS_H + +#include + +namespace fld { +namespace app { + +class Args { + // Callback. + static int arg_cb(int argc, char** argv, int& i); + // Handle args individually. + int arg(int argc, char** argv, int& i); +public: + /// Set, if Fluid was started with the command line argument -u + int update_file { 0 }; // fluid -u + /// Set, if Fluid was started with the command line argument -c + int compile_file { 0 }; // fluid -c + /// Set, if Fluid was started with the command line argument -cs + int compile_strings { 0 }; // fluid -cs + /// command line arguments that overrides the generate code file extension or name + std::string code_filename { }; // fluid -o filename + /// command line arguments that overrides the generate header file extension or name + std::string header_filename { }; // fluid -h filename + /// if set, generate images for automatic documentation in this directory + std::string autodoc_path { }; // fluid --autodoc path + /// Set, if Fluid was started with the command line argument -v + int show_version { 0 }; // fluid -v + /// Constructor. + Args() = default; + // Load args from command line into variables. + int load(int argc, char **argv); +}; + +} // namespace app +} // namespace fld + +#endif // FLUID_APP_ARGS_H + diff --git a/fluid/app/fluid.cxx b/fluid/app/fluid.cxx deleted file mode 100644 index 91c28d0e6..000000000 --- a/fluid/app/fluid.cxx +++ /dev/null @@ -1,2169 +0,0 @@ -// -// FLUID main entry for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 "app/fluid.h" - -#include "app/project.h" -#include "app/mergeback.h" -#include "app/undo.h" -#include "io/Project_Reader.h" -#include "io/Project_Writer.h" -#include "io/Code_Writer.h" -#include "nodes/Fl_Type.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/factory.h" -#include "panels/settings_panel.h" -#include "panels/function_panel.h" -#include "panels/codeview_panel.h" -#include "panels/template_panel.h" -#include "panels/about_panel.h" -#include "rsrcs/pixmaps.h" -#include "app/shell_command.h" -#include "tools/autodoc.h" -#include "widgets/Node_Browser.h" - -#include -#ifdef __APPLE__ -#include // for fl_open_callback -#endif -#include -#include -#include -#include -#include -#include -#include // setlocale().. -#include "../src/flstring.h" - -extern "C" -{ -#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) -# include -# ifdef HAVE_PNG_H -# include -# else -# include -# endif // HAVE_PNG_H -#endif // HAVE_LIBPNG && HAVE_LIBZ -} - -/// \defgroup globals Fluid Global Variables, Functions and Callbacks -/// \{ - -// -// Globals.. -// - -/// FLUID-wide help dialog. -static Fl_Help_Dialog *help_dialog = NULL; - -/// Main app window menu bar. -Fl_Menu_Bar *main_menubar = NULL; - -/// Main app window. -Fl_Window *main_window; - -/// Fluid application preferences, always accessible, will be flushed when app closes. -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; - -/// Show areas of restricted use in overlay plane. -/// Restricted areas are widget that overlap each other, widgets that are outside -/// of their parent's bounds (except children of Scroll groups), and areas -/// within an Fl_Tile that are not covered by children. -int show_restricted = 1; - -/// Show a ghosted outline for groups that have very little contrast. -/// This makes groups with NO_BOX or FLAT_BOX better editable. -int show_ghosted_outline = 1; - -/// Show widget comments in the browser, saved in app preferences. -int show_comments = 1; - -/// Use external editor for editing Fl_Code_Type, saved in app preferences. -int G_use_external_editor = 0; - -/// Debugging help for external Fl_Code_Type editor. -int G_debug = 0; - -/// Run this command to load an Fl_Code_Type into an external editor, save in app preferences. -char G_external_editor_command[512]; - - -// File history info... - -/// Stores the absolute filename of the last 10 design files, saved in app preferences. -char absolute_history[10][FL_PATH_MAX]; - -/// This list of filenames is computed from \c absolute_history and displayed in the main menu. -char relative_history[10][FL_PATH_MAX]; - -/// Menuitem to save a .fl design file, will be deactivated if the design is unchanged. -Fl_Menu_Item *save_item = NULL; - -/// First Menuitem that shows the .fl design file history. -Fl_Menu_Item *history_item = NULL; - -/// Menuitem to show or hide the widget bin, label will change if bin is visible. -Fl_Menu_Item *widgetbin_item = NULL; - -/// Menuitem to show or hide the code view, label will change if view is visible. -Fl_Menu_Item *codeview_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; - -/// Menuitem to show or hide the restricted area overlys, label will change if overlay visibility changes. -Fl_Menu_Item *restricted_item = NULL; - -//////////////////////////////////////////////////////////////// - -/// Set if the current design has been modified compared to the associated .fl design file. -int modflag = 0; - -/// Set if the code files are older than the current design. -int modflag_c = 0; - -/// Application work directory, stored here when temporarily changing to the source code directory. -/// \see goto_source_dir() -static std::string app_work_dir; - -/// Used as a counter to set the .fl project dir as the current directory. -/// \see enter_project_dir(), leave_project_dir() -static char in_project_dir = 0; - -/// Set, if Fluid was started with the command line argument -u -int update_file = 0; // fluid -u - -/// Set, if Fluid was started with the command line argument -c -int compile_file = 0; // fluid -c - -/// Set, if Fluid was started with the command line argument -cs -int compile_strings = 0; // fluid -cs - -/// Set, if Fluid was started with the command line argument -v -int show_version = 0; // fluid -v - -/// Set, if Fluid runs in batch mode, and no user interface is activated. -int batch_mode = 0; // if set (-c, -u) don't open display - -/// command line arguments that overrides the generate code file extension or name -std::string g_code_filename_arg; - -/// command line arguments that overrides the generate header file extension or name -std::string g_header_filename_arg; - -/// current directory path at application launch -std::string g_launch_path; - -/// if set, generate images for automatic documentation in this directory -std::string g_autodoc_path; - -/// path to store temporary files during app run -/// \see tmpdir_create_called -std::string tmpdir_path; - -/// true if the temporary file path was already created -/// \see tmpdir_path -bool tmpdir_create_called = false; - - -/// Offset in pixels when adding widgets from an .fl file. -int pasteoffset = 0; - -/// Paste offset incrementing at every paste command. -static int ipasteoffset = 0; - - -/** - Make sure that a path name ends with a forward slash. - \param[in] str directory or path name - \return a new string, ending with a '/' - */ -std::string end_with_slash(const std::string &str) { - char last = str[str.size()-1]; - if (last !='/' && last != '\\') - return str + "/"; - else - return str; -} - -/** - Generate a path to a directory for temporary data storage. - The path is stored in g_tmpdir. - */ -static void create_tmpdir() { - if (tmpdir_create_called) - return; - tmpdir_create_called = true; - - char buf[128]; -#if _WIN32 - // The usual temp file locations on Windows are - // %system%\Windows\Temp - // %userprofiles%\AppData\Local - // usually resolving into - // C:/Windows/Temp/ - // C:\Users\\AppData\Local\Temp - fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); - std::string name = buf; - wchar_t tempdirW[FL_PATH_MAX+1]; - char tempdir[FL_PATH_MAX+1]; - unsigned len = GetTempPathW(FL_PATH_MAX, tempdirW); - if (len == 0) { - strcpy(tempdir, "c:/windows/temp/"); - } else { - unsigned wn = fl_utf8fromwc(tempdir, FL_PATH_MAX, tempdirW, len); - tempdir[wn] = 0; - } - std::string path = tempdir; - end_with_slash(path); - path += name; - fl_make_path(path.c_str()); - if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; -#else - fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", getpid()); - std::string name = buf; - auto path_temp = fl_getenv("TMPDIR"); - std::string path = path_temp ? path_temp : ""; - if (!path.empty()) { - end_with_slash(path); - path += name; - fl_make_path(path.c_str()); - if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; - } - if (tmpdir_path.empty()) { - path = std::string("/tmp/") + name; - fl_make_path(path.c_str()); - if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; - } -#endif - if (tmpdir_path.empty()) { - char pbuf[FL_PATH_MAX+1]; - fluid_prefs.get_userdata_path(pbuf, FL_PATH_MAX); - path = std::string(pbuf); - end_with_slash(path); - path += name; - fl_make_path(path.c_str()); - if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path; - } - if (tmpdir_path.empty()) { - if (batch_mode) { - fprintf(stderr, "ERROR: Can't create directory for temporary data storage.\n"); - } else { - fl_alert("Can't create directory for temporary data storage."); - } - } -} - -/** - Delete the temporary directory that was created in set_tmpdir. - */ -static void delete_tmpdir() { - // was a temporary directory created - if (!tmpdir_create_called) - return; - if (tmpdir_path.empty()) - return; - - // first delete all files that may still be left in the temp directory - struct dirent **de; - int n_de = fl_filename_list(tmpdir_path.c_str(), &de); - if (n_de >= 0) { - for (int i=0; id_name; - fl_unlink(path.c_str()); - } - fl_filename_free_list(&de, n_de); - } - - // then delete the directory itself - if (fl_rmdir(tmpdir_path.c_str()) < 0) { - if (batch_mode) { - fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); - } else { - fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno)); - } - } -} - -/** - Return the path to a temporary directory for this instance of FLUID. - Fluid will do its best to clear and delete this directory when exiting. - \return the path to the temporary directory, ending in a '/', or and empty - string if no directory could be created. - */ -const std::string &get_tmpdir() { - if (!tmpdir_create_called) - create_tmpdir(); - return tmpdir_path; -} - -/** - Give the user the opportunity to save a project before clearing it. - - If the project has unsaved changes, this function pops up a dialog, that - allows the user to save the project, continue without saving the project, - or to cancel the operation. - - If the user chooses to save, and no filename was set, a file dialog allows - the user to pick a name and location, or to cancel the operation. - - \return false if the user aborted the operation and the calling function - should abort as well - */ -bool confirm_project_clear() { - if (modflag == 0) return true; - switch (fl_choice("This project has unsaved changes. Do you want to save\n" - "the project file before proceeding?", - "Cancel", "Save", "Don't Save")) - { - case 0 : /* Cancel */ - return false; - case 1 : /* Save */ - save_cb(NULL, NULL); - if (modflag) return false; // user canceled the "Save As" dialog - } - return true; -} - -// ---- - -extern Fl_Window *the_panel; - -/** - Ensure that text widgets in the widget panel propagates apply current changes. - By temporarily clearing the text focus, all text widgets with changed text - will unfocus and call their respective callbacks, propagating those changes to - their data set. - */ -void flush_text_widgets() { - if (Fl::focus() && (Fl::focus()->top_window() == the_panel)) { - Fl_Widget *old_focus = Fl::focus(); - Fl::focus(NULL); // trigger callback of the widget that is losing focus - Fl::focus(old_focus); - } -} - -// ---- - -/** - Change the current working directory to the .fl project directory. - - Every call to enter_project_dir() must have a corresponding leave_project_dir() - call. Enter and leave calls can be nested. - - The first call to enter_project_dir() remembers the original directory, usually - the launch directory of the application. Nested calls will increment a nesting - counter. When the nesting counter is back to 0, leave_project_dir() will return - to the original directory. - - The global variable 'filename' must be set to the current project file with - absolute or relative path information. - - \see leave_project_dir(), pwd, in_project_dir - */ -void enter_project_dir() { - if (in_project_dir<0) { - fprintf(stderr, "** Fluid internal error: enter_project_dir() calls unmatched\n"); - return; - } - in_project_dir++; - // check if we are already in the project dir and do nothing if so - if (in_project_dir>1) return; - // check if there is an active project, and do nothing if there is none - if (!g_project.proj_filename || !*g_project.proj_filename) { - fprintf(stderr, "** Fluid internal error: enter_project_dir() no filename set\n"); - return; - } - // store the current working directory for later - app_work_dir = fl_getcwd_str(); - // set the current directory to the path of our .fl file - std::string project_path = fl_filename_path_str(fl_filename_absolute_str(g_project.proj_filename)); - if (fl_chdir(project_path.c_str()) == -1) { - fprintf(stderr, "** Fluid internal error: enter_project_dir() can't chdir to %s: %s\n", - project_path.c_str(), strerror(errno)); - return; - } - //fprintf(stderr, "chdir from %s to %s\n", app_work_dir.c_str(), fl_getcwd().c_str()); -} - -/** - Change the current working directory to the previous directory. - \see enter_project_dir(), pwd, in_project_dir - */ -void leave_project_dir() { - if (in_project_dir == 0) { - fprintf(stderr, "** Fluid internal error: leave_project_dir() calls unmatched\n"); - return; - } - in_project_dir--; - // still nested, stay in the project directory - if (in_project_dir > 0) return; - // no longer nested, return to the original, usually the application working directory - if (fl_chdir(app_work_dir.c_str()) < 0) { - fprintf(stderr, "** Fluid internal error: leave_project_dir() can't chdir back to %s : %s\n", - app_work_dir.c_str(), strerror(errno)); - } -} - -/** - Position the given window window based on entries in the app preferences. - Customisable by user; feature can be switched off. - The window is not shown or hidden by this function, but a value is returned - to indicate the state to the caller. - \param[in] w position this window - \param[in] prefsName name of the preferences item that stores the window settings - \param[in] Visible default value if window is hidden or shown - \param[in] X, Y, W, H default size and position if nothing is specified in the preferences - \return 1 if the caller should make the window visible, 0 if hidden. - */ -char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) { - Fl_Preferences pos(fluid_prefs, prefsName); - if (prevpos_button->value()) { - pos.get("x", X, X); - pos.get("y", Y, Y); - if ( W!=0 ) { - pos.get("w", W, W); - pos.get("h", H, H); - w->resize( X, Y, W, H ); - } - else - w->position( X, Y ); - } - pos.get("visible", Visible, Visible); - return Visible; -} - -/** - Save the position and visibility state of a window to the app preferences. - \param[in] w save this window data - \param[in] prefsName name of the preferences item that stores the window settings - */ -void save_position(Fl_Window *w, const char *prefsName) { - Fl_Preferences pos(fluid_prefs, prefsName); - pos.set("x", w->x()); - pos.set("y", w->y()); - pos.set("w", w->w()); - pos.set("h", w->h()); - pos.set("visible", (int)(w->shown() && w->visible())); -} - -/** - Return the path and filename of a temporary file for cut or duplicated data. - \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer - \return a pointer to a string in a static buffer - */ -static char* cutfname(int which = 0) { - static char name[2][FL_PATH_MAX]; - static char beenhere = 0; - - if (!beenhere) { - beenhere = 1; - fluid_prefs.getUserdataPath(name[0], sizeof(name[0])); - strlcat(name[0], "cut_buffer", sizeof(name[0])); - fluid_prefs.getUserdataPath(name[1], sizeof(name[1])); - strlcat(name[1], "dup_buffer", sizeof(name[1])); - } - - return name[which]; -} - -/** - Timer to watch for external editor modifications. - - If one or more external editors open, check if their files were modified. - If so: reload to ram, update size/mtime records, and change fluid's - 'modified' state. - */ -static void external_editor_timer(void*) { - int editors_open = ExternalCodeEditor::editors_open(); - if ( G_debug ) printf("--- TIMER --- External editors open=%d\n", editors_open); - if ( editors_open > 0 ) { - // Walk tree looking for files modified by external editors. - int modified = 0; - for (Fl_Type *p = Fl_Type::first; p; p = p->next) { - if ( p->is_a(ID_Code) ) { - Fl_Code_Type *code = (Fl_Code_Type*)p; - // Code changed by external editor? - if ( code->handle_editor_changes() ) { // updates ram, file size/mtime - modified++; - } - if ( code->is_editing() ) { // editor open? - code->reap_editor(); // Try to reap; maybe it recently closed - } - } - } - if ( modified ) set_modflag(1); - } - // Repeat timeout if editors still open - // The ExternalCodeEditor class handles start/stopping timer, we just - // repeat_timeout() if it's already on. NOTE: above code may have reaped - // only open editor, which would disable further timeouts. So *recheck* - // if editors still open, to ensure we don't accidentally re-enable them. - // - if ( ExternalCodeEditor::editors_open() ) { - Fl::repeat_timeout(2.0, external_editor_timer); - } -} - -/** - Save the current design to the file given by \c filename. - If automatic, this overwrites an existing file. If interactive, if will - verify with the user. - \param[in] v if v is not NULL, or no filename is set, open a filechooser. - */ -void save_cb(Fl_Widget *, void *v) { - flush_text_widgets(); - Fl_Native_File_Chooser fnfc; - const char *c = g_project.proj_filename; - if (v || !c || !*c) { - fnfc.title("Save To:"); - fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); - fnfc.filter("FLUID Files\t*.f[ld]"); - if (fnfc.show() != 0) return; - c = fnfc.filename(); - if (!fl_access(c, 0)) { - std::string basename = fl_filename_name_str(std::string(c)); - if (fl_choice("The file \"%s\" already exists.\n" - "Do you want to replace it?", "Cancel", - "Replace", NULL, basename.c_str()) == 0) return; - } - - if (v != (void *)2) set_filename(c); - } - if (!fld::io::write_file(c)) { - fl_alert("Error writing %s: %s", c, strerror(errno)); - return; - } - - if (v != (void *)2) { - set_modflag(0, 1); - undo_save = undo_current; - } -} - -/** - Save a design template. - \todo We should document the concept of templates. - */ -void save_template_cb(Fl_Widget *, void *) { - // Setup the template panel... - if (!template_panel) make_template_panel(); - - template_clear(); - template_browser->add("New Template"); - template_load(); - - template_name->show(); - template_name->value(""); - - template_instance->hide(); - - template_delete->show(); - template_delete->deactivate(); - - template_submit->label("Save"); - template_submit->deactivate(); - - template_panel->label("Save Template"); - - // Show the panel and wait for the user to do something... - template_panel->show(); - while (template_panel->shown()) Fl::wait(); - - // Get the template name, return if it is empty... - const char *c = template_name->value(); - if (!c || !*c) return; - - // Convert template name to filename_with_underscores - char savename[FL_PATH_MAX], *saveptr; - strlcpy(savename, c, sizeof(savename)); - for (saveptr = savename; *saveptr; saveptr ++) { - if (isspace(*saveptr)) *saveptr = '_'; - } - - // Find the templates directory... - char filename[FL_PATH_MAX]; - fluid_prefs.getUserdataPath(filename, sizeof(filename)); - - strlcat(filename, "templates", sizeof(filename)); - if (fl_access(filename, 0)) fl_make_path(filename); - - strlcat(filename, "/", sizeof(filename)); - strlcat(filename, savename, sizeof(filename)); - - char *ext = filename + strlen(filename); - if (ext >= (filename + sizeof(filename) - 5)) { - fl_alert("The template name \"%s\" is too long!", c); - return; - } - - // Save the .fl file... - strcpy(ext, ".fl"); - - if (!fl_access(filename, 0)) { - if (fl_choice("The template \"%s\" already exists.\n" - "Do you want to replace it?", "Cancel", - "Replace", NULL, c) == 0) return; - } - - if (!fld::io::write_file(filename)) { - fl_alert("Error writing %s: %s", filename, strerror(errno)); - return; - } - -#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) - // Get the screenshot, if any... - Fl_Type *t; - - for (t = Fl_Type::first; t; t = t->next) { - // Find the first window... - if (t->is_a(ID_Window)) break; - } - - if (!t) return; - - // Grab a screenshot... - Fl_Window_Type *wt = (Fl_Window_Type *)t; - uchar *pixels; - int w, h; - - if ((pixels = wt->read_image(w, h)) == NULL) return; - - // Save to a PNG file... - strcpy(ext, ".png"); - - errno = 0; - if (fl_write_png(filename, pixels, w, h, 3) != 0) { - delete[] pixels; - fl_alert("Error writing %s: %s", filename, strerror(errno)); - return; - } - -# if 0 // The original PPM output code... - strcpy(ext, ".ppm"); - fp = fl_fopen(filename, "wb"); - fprintf(fp, "P6\n%d %d 255\n", w, h); - fwrite(pixels, w * h, 3, fp); - fclose(fp); -# endif // 0 - - delete[] pixels; -#endif // HAVE_LIBPNG && HAVE_LIBZ -} - -/** - Reload the file set by \c filename, replacing the current design. - If the design was modified, a dialog will ask for confirmation. - */ -void revert_cb(Fl_Widget *,void *) { - if (modflag) { - if (!fl_choice("This user interface has been changed. Really revert?", - "Cancel", "Revert", NULL)) return; - } - undo_suspend(); - if (!fld::io::read_file(g_project.proj_filename, 0)) { - undo_resume(); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - fl_message("Can't read %s: %s", g_project.proj_filename, strerror(errno)); - return; - } - widget_browser->rebuild(); - undo_resume(); - set_modflag(0, 0); - undo_clear(); - g_project.update_settings_dialog(); -} - -/** - Exit Fluid; we hope you had a nice experience. - If the design was modified, a dialog will ask for confirmation. - */ -void exit_cb(Fl_Widget *,void *) { - if (shell_command_running()) { - int choice = fl_choice("Previous shell command still running!", - "Cancel", - "Exit", - NULL); - if (choice == 0) { // user chose to cancel the exit operation - return; - } - } - - flush_text_widgets(); - - // verify user intention - if (confirm_project_clear() == false) - return; - - // Stop any external editor update timers - ExternalCodeEditor::stop_update_timer(); - - save_position(main_window,"main_window_pos"); - - if (widgetbin_panel) { - save_position(widgetbin_panel,"widgetbin_pos"); - delete widgetbin_panel; - } - if (codeview_panel) { - Fl_Preferences svp(fluid_prefs, "codeview"); - svp.set("autorefresh", cv_autorefresh->value()); - svp.set("autoposition", cv_autoposition->value()); - svp.set("tab", cv_tab->find(cv_tab->value())); - svp.set("code_choice", cv_code_choice); - save_position(codeview_panel,"codeview_pos"); - delete codeview_panel; - codeview_panel = 0; - } - if (shell_run_window) { - save_position(shell_run_window,"shell_run_Window_pos"); - } - - if (about_panel) - delete about_panel; - if (help_dialog) - delete help_dialog; - - if (g_shell_config) - g_shell_config->write(fluid_prefs, FD_STORE_USER); - g_layout_list.write(fluid_prefs, FD_STORE_USER); - - undo_clear(); - - // Destroy tree - // Doing so causes dtors to automatically close all external editors - // and cleans up editor tmp files. Then remove fluid tmpdir /last/. - g_project.reset(); - ExternalCodeEditor::tmpdir_clear(); - delete_tmpdir(); - - exit(0); -} - -/** - Clear the current project and create a new, empty one. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - \param[in] user_must_confirm if set, a confimation dialog is presented to the - user before resetting the project. Default is `true`. - \return false if the operation was canceled - */ -bool new_project(bool user_must_confirm) { - // verify user intention - if ((user_must_confirm) && (confirm_project_clear() == false)) - return false; - - // clear the current project - g_project.reset(); - set_filename(NULL); - set_modflag(0, 0); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - - // all is clear to continue - return true; -} - -/** - Open the template browser and load a new file from templates. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - \return false if the operation was canceled or failed otherwise - */ -bool new_project_from_template() { - // clear the current project first - if (new_project() == false) - return false; - - // Setup the template panel... - if (!template_panel) make_template_panel(); - - template_clear(); - template_browser->add("Blank"); - template_load(); - - template_name->hide(); - template_name->value(""); - - template_instance->show(); - template_instance->deactivate(); - template_instance->value(""); - - template_delete->show(); - - template_submit->label("New"); - template_submit->deactivate(); - - template_panel->label("New"); - - //if ( template_browser->size() == 1 ) { // only one item? - template_browser->value(1); // select it - template_browser->do_callback(); - //} - - // Show the panel and wait for the user to do something... - template_panel->show(); - while (template_panel->shown()) Fl::wait(); - - // See if the user chose anything... - int item = template_browser->value(); - if (item < 1) return false; - - // Load the template, if any... - const char *tname = (const char *)template_browser->data(item); - - if (tname) { - // Grab the instance name... - const char *iname = template_instance->value(); - - if (iname && *iname) { - // Copy the template to a temp file, then read it in... - char line[1024], *ptr, *next; - FILE *infile, *outfile; - - if ((infile = fl_fopen(tname, "rb")) == NULL) { - fl_alert("Error reading template file \"%s\":\n%s", tname, - strerror(errno)); - set_modflag(0); - undo_clear(); - return false; - } - - if ((outfile = fl_fopen(cutfname(1), "wb")) == NULL) { - fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1), - strerror(errno)); - fclose(infile); - set_modflag(0); - undo_clear(); - return false; - } - - while (fgets(line, sizeof(line), infile)) { - // Replace @INSTANCE@ with the instance name... - for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != NULL; ptr = next + 10) { - fwrite(ptr, next - ptr, 1, outfile); - fputs(iname, outfile); - } - - fputs(ptr, outfile); - } - - fclose(infile); - fclose(outfile); - - undo_suspend(); - fld::io::read_file(cutfname(1), 0); - fl_unlink(cutfname(1)); - undo_resume(); - } else { - // No instance name, so read the template without replacements... - undo_suspend(); - fld::io::read_file(tname, 0); - undo_resume(); - } - } - - widget_browser->rebuild(); - g_project.update_settings_dialog(); - set_modflag(0); - undo_clear(); - - return true; -} - -/** - Open a native file chooser to allow choosing a project file for reading. - - Path and filename are preset with the current project filename, if there - is one. - - \param title a text describing the action after selecting a file (load, merge, ...) - \return the file path and name, or an empty string if the operation was canceled - */ -std::string open_project_filechooser(const std::string &title) { - Fl_Native_File_Chooser dialog; - dialog.title(title.c_str()); - dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); - dialog.filter("FLUID Files\t*.f[ld]\n"); - if (g_project.proj_filename) { - std::string current_project_file = g_project.proj_filename; - dialog.directory(fl_filename_path_str(current_project_file).c_str()); - dialog.preset_file(fl_filename_name_str(current_project_file).c_str()); - } - if (dialog.show() != 0) - return std::string(); - return std::string(dialog.filename()); -} - -/** - Load a project from the give file name and path. - - The project file is inserted at the currently selected type. - - If no filename is given, FLUID will open a file chooser dialog. - - \param[in] filename_arg path and name of the new project file - \return false if the operation failed - */ -bool merge_project_file(const std::string &filename_arg) { - bool is_a_merge = (Fl_Type::first != NULL); - std::string title = is_a_merge ? "Merge Project File" : "Open Project File"; - - // ask for a filename if none was given - std::string new_filename = filename_arg; - if (new_filename.empty()) { - new_filename = open_project_filechooser(title); - if (new_filename.empty()) { - return false; - } - } - - const char *c = new_filename.c_str(); - const char *oldfilename = g_project.proj_filename; - g_project.proj_filename = NULL; - set_filename(c); - if (is_a_merge) undo_checkpoint(); - undo_suspend(); - if (!fld::io::read_file(c, is_a_merge)) { - undo_resume(); - widget_browser->rebuild(); - g_project.update_settings_dialog(); - fl_message("Can't read %s: %s", c, strerror(errno)); - free((void *)g_project.proj_filename); - g_project.proj_filename = oldfilename; - if (main_window) set_modflag(modflag); - return false; - } - undo_resume(); - widget_browser->rebuild(); - if (is_a_merge) { - // Inserting a file; restore the original filename... - set_filename(oldfilename); - set_modflag(1); - } else { - // Loaded a file; free the old filename... - set_modflag(0, 0); - undo_clear(); - } - if (oldfilename) free((void *)oldfilename); - return true; -} - -/** - Open a file chooser and load an exiting project file. - - If the current project was modified, FLUID will give the user the opportunity - to save the old project first. - - If no filename is given, FLUID will open a file chooser dialog. - - \param[in] filename_arg load from this file, or show file chooser if empty - \return false if the operation was canceled or failed otherwise - */ -bool open_project_file(const std::string &filename_arg) { - // verify user intention - if (confirm_project_clear() == false) - return false; - - // ask for a filename if none was given - std::string new_filename = filename_arg; - if (new_filename.empty()) { - new_filename = open_project_filechooser("Open Project File"); - if (new_filename.empty()) { - return false; - } - } - - // clear the project and merge a file by the given name - new_project(false); - return merge_project_file(new_filename); -} - -#ifdef __APPLE__ -/** - Handle app launch with an associated filename (macOS only). - Should there be a modified design already, Fluid asks for user confirmation. - \param[in] c the filename of the new design - */ -void apple_open_cb(const char *c) { - open_project_file(std::string(c)); -} -#endif // __APPLE__ - -/** - Generate the C++ source and header filenames and write those files. - - This function creates the source filename by setting the file - extension to \c code_file_name and a header filename - with the extension \c code_file_name which are both - settable by the user. - - If the code filename has not been set yet, a "save file as" dialog will be - presented to the user. - - In batch_mode, the function will either be silent, or, if opening or writing - the files fails, write an error message to \c stderr and exit with exit code 1. - - In interactive mode, it will pop up an error message, or, if the user - hasn't disabled that, pop up a confirmation message. - - \param[in] dont_show_completion_dialog don't show the completion dialog - \return 1 if the operation failed, 0 if it succeeded - */ -int write_code_files(bool dont_show_completion_dialog) -{ - // -- handle user interface issues - flush_text_widgets(); - if (!g_project.proj_filename) { - save_cb(0,0); - if (!g_project.proj_filename) return 1; - } - - // -- generate the file names with absolute paths - fld::io::Code_Writer f; - std::string code_filename = g_project.codefile_path() + g_project.codefile_name(); - std::string header_filename = g_project.headerfile_path() + g_project.headerfile_name(); - - // -- write the code and header files - if (!batch_mode) enter_project_dir(); - int x = f.write_code(code_filename.c_str(), header_filename.c_str()); - std::string code_filename_rel = fl_filename_relative_str(code_filename); - std::string header_filename_rel = fl_filename_relative_str(header_filename); - if (!batch_mode) leave_project_dir(); - - // -- print error message in batch mode or pop up an error or confirmation dialog box - if (batch_mode) { - if (!x) { - fprintf(stderr, "%s and %s: %s\n", - code_filename_rel.c_str(), - header_filename_rel.c_str(), - strerror(errno)); - exit(1); - } - } else { - if (!x) { - fl_message("Can't write %s or %s: %s", - code_filename_rel.c_str(), - header_filename_rel.c_str(), - strerror(errno)); - } else { - set_modflag(-1, 0); - if (dont_show_completion_dialog==false && completion_button->value()) { - fl_message("Wrote %s and %s", - code_filename_rel.c_str(), - header_filename_rel.c_str()); - } - } - } - return 0; -} - -/** - Callback to write C++ code and header files. - */ -void write_cb(Fl_Widget *, void *) { - write_code_files(); -} - -#if 0 -// Matt: disabled -/** - Merge the possibly modified content of code files back into the project. - */ -int mergeback_code_files() -{ - flush_text_widgets(); - if (!filename) return 1; - if (!g_project.write_mergeback_data) { - fl_message("MergeBack is not enabled for this project.\n" - "Please enable MergeBack in the project settings\n" - "dialog and re-save the project file and the code."); - return 0; - } - - std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); - std::string code_filename; -#if 1 - if (!batch_mode) { - Fl_Preferences build_records(Fl_Preferences::USER_L, "fltk.org", "fluid-build"); - Fl_Preferences path(build_records, proj_filename.c_str()); - int i, n = proj_filename.size(); - for (i=0; ivalue()) { - fl_message("Wrote %s", g_project.stringsfile_name().c_str()); - } - } -} - -/** - Show the editor for the \c current Fl_Type. - */ -void openwidget_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_message("Please select a widget"); - return; - } - Fl_Type::current->open(); -} - -/** - User chose to copy the currently selected widgets. - */ -void copy_cb(Fl_Widget*, void*) { - flush_text_widgets(); - if (!Fl_Type::current) { - fl_beep(); - return; - } - flush_text_widgets(); - ipasteoffset = 10; - if (!fld::io::write_file(cutfname(),1)) { - fl_message("Can't write %s: %s", cutfname(), strerror(errno)); - return; - } -} - -/** - User chose to cut the currently selected widgets. - */ -void cut_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - flush_text_widgets(); - if (!fld::io::write_file(cutfname(),1)) { - fl_message("Can't write %s: %s", cutfname(), strerror(errno)); - return; - } - undo_checkpoint(); - set_modflag(1); - ipasteoffset = 0; - Fl_Type *p = Fl_Type::current->parent; - while (p && p->selected) p = p->parent; - delete_all(1); - if (p) select_only(p); - widget_browser->rebuild(); -} - -/** - User chose to delete the currently selected widgets. - */ -void delete_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - undo_checkpoint(); - set_modflag(1); - ipasteoffset = 0; - Fl_Type *p = Fl_Type::current->parent; - while (p && p->selected) p = p->parent; - delete_all(1); - if (p) select_only(p); - widget_browser->rebuild(); -} - -/** - User chose to paste the widgets from the cut buffer. - - This function will paste the widgets in the cut buffer after the currently - selected widget. If the currently selected widget is a group widget and - it is not folded, the new widgets will be added inside the group. - */ -void paste_cb(Fl_Widget*, void*) { - pasteoffset = ipasteoffset; - undo_checkpoint(); - undo_suspend(); - Strategy strategy = Strategy::FROM_FILE_AFTER_CURRENT; - if (Fl_Type::current && Fl_Type::current->can_have_children()) { - if (Fl_Type::current->folded_ == 0) { - // If the current widget is a group widget and it is not folded, - // add the new widgets inside the group. - strategy = Strategy::FROM_FILE_AS_LAST_CHILD; - // The following alternative also works quite nicely - //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD; - } - } - if (!fld::io::read_file(cutfname(), 1, strategy)) { - widget_browser->rebuild(); - fl_message("Can't read %s: %s", cutfname(), strerror(errno)); - } - undo_resume(); - widget_browser->display(Fl_Type::current); - widget_browser->rebuild(); - pasteoffset = 0; - ipasteoffset += 10; -} - -/** - Duplicate the selected widgets. - - This code is a bit complex because it needs to find the last selected - widget with the lowest level, so that the new widgets are inserted after - this one. - */ -void duplicate_cb(Fl_Widget*, void*) { - if (!Fl_Type::current) { - fl_beep(); - return; - } - - // flush the text widgets to make sure the user's changes are saved: - flush_text_widgets(); - - // find the last selected node with the lowest level: - int lowest_level = 9999; - Fl_Type *new_insert = NULL; - if (Fl_Type::current->selected) { - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { - if (t->selected && (t->level <= lowest_level)) { - lowest_level = t->level; - new_insert = t; - } - } - } - if (new_insert) - Fl_Type::current = new_insert; - - // write the selected widgets to a file: - if (!fld::io::write_file(cutfname(1),1)) { - fl_message("Can't write %s: %s", cutfname(1), strerror(errno)); - return; - } - - // read the file and add the widgets after the current one: - pasteoffset = 0; - undo_checkpoint(); - undo_suspend(); - if (!fld::io::read_file(cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) { - fl_message("Can't read %s: %s", cutfname(1), strerror(errno)); - } - fl_unlink(cutfname(1)); - widget_browser->display(Fl_Type::current); - widget_browser->rebuild(); - undo_resume(); -} - -/** - User wants to sort selected widgets by y coordinate. - */ -static void sort_cb(Fl_Widget *,void *) { - undo_checkpoint(); - sort((Fl_Type*)NULL); - widget_browser->rebuild(); - set_modflag(1); -} - -/** - Open the "About" dialog. - */ -void about_cb(Fl_Widget *, void *) { - if (!about_panel) make_about_panel(); - about_panel->show(); -} - -/** - Open a dialog to show the HTML help page form the FLTK documentation folder. - \param[in] name name of the HTML help file. - */ -void show_help(const char *name) { - const char *docdir; - char helpname[FL_PATH_MAX]; - - if (!help_dialog) help_dialog = new Fl_Help_Dialog(); - - if ((docdir = fl_getenv("FLTK_DOCDIR")) == NULL) { - docdir = FLTK_DOCDIR; - } - snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name); - - // make sure that we can read the file - FILE *f = fopen(helpname, "rb"); - if (f) { - fclose(f); - help_dialog->load(helpname); - } else { - // if we can not read the file, we display the canned version instead - // or ask the native browser to open the page on www.fltk.org - if (strcmp(name, "fluid.html")==0) { - if (!Fl_Shared_Image::find("embedded:/fluid_flow_chart_800.png")) - new Fl_PNG_Image("embedded:/fluid_flow_chart_800.png", fluid_flow_chart_800_png, sizeof(fluid_flow_chart_800_png)); - help_dialog->value - ( - "\n" - "FLTK: Programming with FLUID\n" - "

What is FLUID?

\n" - "The Fast Light User Interface Designer, or FLUID, is a graphical editor " - "that is used to produce FLTK source code. FLUID edits and saves its state " - "in .fl files. These files are text, and you can (with care) " - "edit them in a text editor, perhaps to get some special effects.

\n" - "FLUID can \"compile\" the .fl file into a .cxx " - "and a .h file. The .cxx file defines all the " - "objects from the .fl file and the .h file " - "declares all the global ones. FLUID also supports localization " - "(Internationalization) of label strings using message files and the GNU " - "gettext or POSIX catgets interfaces.

\n" - "A simple program can be made by putting all your code (including a " - "main() function) into the .fl file and thus making the " - ".cxx file a single source file to compile. Most programs are " - "more complex than this, so you write other .cxx files that " - "call the FLUID functions. These .cxx files must " - "#include the .h file or they can #include " - "the .cxx file so it still appears to be a single source file.

" - "

" - "

More information is available online at https://www.fltk.org/" - "" - ); - } else if (strcmp(name, "license.html")==0) { - fl_open_uri("https://www.fltk.org/doc-1.5/license.html"); - return; - } else if (strcmp(name, "index.html")==0) { - fl_open_uri("https://www.fltk.org/doc-1.5/index.html"); - return; - } else { - snprintf(helpname, sizeof(helpname), "https://www.fltk.org/%s", name); - fl_open_uri(helpname); - return; - } - } - help_dialog->show(); -} - -/** - User wants help on Fluid. - */ -void help_cb(Fl_Widget *, void *) { - show_help("fluid.html"); -} - -/** - User wants to see the Fluid manual. - */ -void manual_cb(Fl_Widget *, void *) { - show_help("index.html"); -} - -// ---- Printing - -/** - Open the dialog to allow the user to print the current window. - */ -void print_menu_cb(Fl_Widget *, void *) { - int w, h, ww, hh; - int frompage, topage; - Fl_Type *t; // Current widget - int num_windows; // Number of windows - Fl_Window_Type *windows[1000]; // Windows to print - int winpage; // Current window page - Fl_Window *win; - - for (t = Fl_Type::first, num_windows = 0; t; t = t->next) { - if (t->is_a(ID_Window)) { - windows[num_windows] = (Fl_Window_Type *)t; - if (!((Fl_Window*)(windows[num_windows]->o))->shown()) continue; - num_windows ++; - } - } - - Fl_Printer printjob; - if ( printjob.start_job(num_windows, &frompage, &topage) ) return; - int pagecount = 0; - for (winpage = 0; winpage < num_windows; winpage++) { - float scale = 1, scale_x = 1, scale_y = 1; - if (winpage+1 < frompage || winpage+1 > topage) continue; - printjob.start_page(); - printjob.printable_rect(&w, &h); - - // Get the time and date... - time_t curtime = time(NULL); - struct tm *curdate = localtime(&curtime); - char date[1024]; - strftime(date, sizeof(date), "%c", curdate); - fl_font(FL_HELVETICA, 12); - fl_color(FL_BLACK); - fl_draw(date, (w - (int)fl_width(date))/2, fl_height()); - sprintf(date, "%d/%d", ++pagecount, topage-frompage+1); - fl_draw(date, w - (int)fl_width(date), fl_height()); - - // Get the base filename... - std::string basename = fl_filename_name_str(std::string(g_project.proj_filename)); - fl_draw(basename.c_str(), 0, fl_height()); - - // print centered and scaled to fit in the page - win = (Fl_Window*)windows[winpage]->o; - ww = win->decorated_w(); - if(ww > w) scale_x = float(w)/ww; - hh = win->decorated_h(); - if(hh > h) scale_y = float(h)/hh; - if (scale_x < scale) scale = scale_x; - if (scale_y < scale) scale = scale_y; - if (scale < 1) { - printjob.scale(scale); - printjob.printable_rect(&w, &h); - } - printjob.origin(w/2, h/2); - printjob.print_window(win, -ww/2, -hh/2); - printjob.end_page(); - } - printjob.end_job(); -} - -// ---- Main menu bar - -extern void select_layout_preset_cb(Fl_Widget *, void *user_data); -extern void layout_suite_marker(Fl_Widget *, void *user_data); - -static void menu_file_new_cb(Fl_Widget *, void *) { new_project(); } -static void menu_file_new_from_template_cb(Fl_Widget *, void *) { new_project_from_template(); } -static void menu_file_open_cb(Fl_Widget *, void *) { open_project_file(""); } -static void menu_file_insert_cb(Fl_Widget *, void *) { merge_project_file(""); } -static void menu_file_open_history_cb(Fl_Widget *, void *v) { open_project_file(std::string((const char*)v)); } -static void menu_layout_sync_resize_cb(Fl_Menu_ *m, void*) { - if (m->mvalue()->value()) Fl_Type::allow_layout = 1; else Fl_Type::allow_layout = 0; } -/** - This is the main Fluid menu. - - Design history is manipulated right inside this menu structure. - Some menu items change or deactivate correctly, but most items just trigger - various callbacks. - - \c New_Menu creates new widgets and is explained in detail in another location. - - \see New_Menu - \todo This menu needs some major modernization. Menus are too long and their - sorting is not always obvious. - \todo Shortcuts are all over the place (Alt, Ctrl, Command, Shift-Ctrl, - function keys), and there should be a help page listing all shortcuts. - */ -Fl_Menu_Item Main_Menu[] = { -{"&File",0,0,0,FL_SUBMENU}, - {"&New", FL_COMMAND+'n', menu_file_new_cb}, - {"&Open...", FL_COMMAND+'o', menu_file_open_cb}, - {"&Insert...", FL_COMMAND+'i', menu_file_insert_cb, 0, FL_MENU_DIVIDER}, - {"&Save", FL_COMMAND+'s', save_cb, 0}, - {"Save &As...", FL_COMMAND+FL_SHIFT+'s', save_cb, (void*)1}, - {"Sa&ve A Copy...", 0, save_cb, (void*)2}, - {"&Revert...", 0, revert_cb, 0, FL_MENU_DIVIDER}, - {"New &From Template...", FL_COMMAND+'N', menu_file_new_from_template_cb, 0}, - {"Save As &Template...", 0, save_template_cb, 0, FL_MENU_DIVIDER}, - {"&Print...", FL_COMMAND+'p', print_menu_cb}, - {"Write &Code", FL_COMMAND+FL_SHIFT+'c', write_cb, 0}, -// Matt: disabled {"MergeBack Code", FL_COMMAND+FL_SHIFT+'m', mergeback_cb, 0}, - {"&Write Strings", FL_COMMAND+FL_SHIFT+'w', write_strings_cb, 0, FL_MENU_DIVIDER}, - {relative_history[0], FL_COMMAND+'1', menu_file_open_history_cb, absolute_history[0]}, - {relative_history[1], FL_COMMAND+'2', menu_file_open_history_cb, absolute_history[1]}, - {relative_history[2], FL_COMMAND+'3', menu_file_open_history_cb, absolute_history[2]}, - {relative_history[3], FL_COMMAND+'4', menu_file_open_history_cb, absolute_history[3]}, - {relative_history[4], FL_COMMAND+'5', menu_file_open_history_cb, absolute_history[4]}, - {relative_history[5], FL_COMMAND+'6', menu_file_open_history_cb, absolute_history[5]}, - {relative_history[6], FL_COMMAND+'7', menu_file_open_history_cb, absolute_history[6]}, - {relative_history[7], FL_COMMAND+'8', menu_file_open_history_cb, absolute_history[7]}, - {relative_history[8], FL_COMMAND+'9', menu_file_open_history_cb, absolute_history[8]}, - {relative_history[9], 0, menu_file_open_history_cb, absolute_history[9], FL_MENU_DIVIDER}, - {"&Quit", FL_COMMAND+'q', exit_cb}, - {0}, -{"&Edit",0,0,0,FL_SUBMENU}, - {"&Undo", FL_COMMAND+'z', undo_cb}, - {"&Redo", FL_COMMAND+FL_SHIFT+'z', redo_cb, 0, FL_MENU_DIVIDER}, - {"C&ut", FL_COMMAND+'x', cut_cb}, - {"&Copy", FL_COMMAND+'c', copy_cb}, - {"&Paste", FL_COMMAND+'v', paste_cb}, - {"Dup&licate", FL_COMMAND+'u', duplicate_cb}, - {"&Delete", FL_Delete, delete_cb, 0, FL_MENU_DIVIDER}, - {"Select &All", FL_COMMAND+'a', select_all_cb}, - {"Select &None", FL_COMMAND+FL_SHIFT+'a', select_none_cb, 0, FL_MENU_DIVIDER}, - {"Pr&operties...", FL_F+1, openwidget_cb}, - {"&Sort",0,sort_cb}, - {"&Earlier", FL_F+2, earlier_cb}, - {"&Later", FL_F+3, later_cb}, - {"&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}, - {"Hide Restricted",FL_COMMAND+FL_SHIFT+'r',toggle_restricted}, - {"Show Widget &Bin...",FL_ALT+'b',toggle_widgetbin_cb}, - {"Show Code View",FL_ALT+'c', (Fl_Callback*)toggle_codeview_cb, 0, FL_MENU_DIVIDER}, - {"Settings...",FL_ALT+'p',show_settings_cb}, - {0}, -{"&New", 0, 0, (void *)New_Menu, FL_SUBMENU_POINTER}, -{"&Layout",0,0,0,FL_SUBMENU}, - {"&Align",0,0,0,FL_SUBMENU}, - {"&Left",0,(Fl_Callback *)align_widget_cb,(void*)10}, - {"&Center",0,(Fl_Callback *)align_widget_cb,(void*)11}, - {"&Right",0,(Fl_Callback *)align_widget_cb,(void*)12}, - {"&Top",0,(Fl_Callback *)align_widget_cb,(void*)13}, - {"&Middle",0,(Fl_Callback *)align_widget_cb,(void*)14}, - {"&Bottom",0,(Fl_Callback *)align_widget_cb,(void*)15}, - {0}, - {"&Space Evenly",0,0,0,FL_SUBMENU}, - {"&Across",0,(Fl_Callback *)align_widget_cb,(void*)20}, - {"&Down",0,(Fl_Callback *)align_widget_cb,(void*)21}, - {0}, - {"&Make Same Size",0,0,0,FL_SUBMENU}, - {"&Width",0,(Fl_Callback *)align_widget_cb,(void*)30}, - {"&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}, - {"&Horizontal",0,(Fl_Callback *)align_widget_cb,(void*)40}, - {"&Vertical",0,(Fl_Callback *)align_widget_cb,(void*)41}, - {0}, - {"Synchronized Resize", 0, (Fl_Callback*)menu_layout_sync_resize_cb, NULL, FL_MENU_TOGGLE|FL_MENU_DIVIDER }, - {"&Grid and Size Settings...",FL_COMMAND+'g',show_grid_cb, NULL, FL_MENU_DIVIDER}, - {"Presets", 0, layout_suite_marker, (void*)main_layout_submenu_, 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, Fd_Shell_Command_List::menu_marker, (void*)Fd_Shell_Command_List::default_menu, FL_SUBMENU_POINTER}, -{"&Help",0,0,0,FL_SUBMENU}, - {"&Rapid development with FLUID...",0,help_cb}, - {"&FLTK Programmers Manual...",0,manual_cb, 0, FL_MENU_DIVIDER}, - {"&About FLUID...",0,about_cb}, - {0}, -{0}}; - -/** - Change the app's and hence preview the design's scheme. - - The scheme setting is stored in the app preferences - - in key \p 'scheme_name' since 1.4.0 - - in key \p 'scheme' (index: 0 - 4) in 1.3.x - - This callback is triggered by changing the scheme in the - Fl_Scheme_Choice widget (\p Edit/GUI Settings). - - \param[in] choice the calling widget - - \see init_scheme() for choice values and backwards compatibility - */ -void scheme_cb(Fl_Scheme_Choice *choice, void *) { - if (batch_mode) - return; - - // set the new scheme only if the scheme was changed - const char *new_scheme = choice->text(choice->value()); - - if (Fl::is_scheme(new_scheme)) - return; - - Fl::scheme(new_scheme); - fluid_prefs.set("scheme_name", new_scheme); - - // Backwards compatibility: store 1.3 scheme index (1-4). - // We assume that index 0-3 (base, plastic, gtk+, gleam) are in the - // same order as in 1.3.x (index 1-4), higher values are ignored - - int scheme_index = scheme_choice->value(); - if (scheme_index <= 3) // max. index for 1.3.x (Gleam) - fluid_prefs.set("scheme", scheme_index + 1); // compensate for different indexing -} - -/** - Read Fluid's scheme preferences and set the app's scheme. - - Since FLTK 1.4.0 the scheme \b name is stored as a character string - with key "scheme_name" in the preference database. - - In FLTK 1.3.x the scheme preference was stored as an integer index - with key "scheme" in the database. The known schemes were hardcoded in - Fluid's sources (here for reference): - - | Index | 1.3 Scheme Name | Choice | 1.4 Scheme Name | - |-------|-----------------|-------|-----------------| - | 0 | Default (same as None) | n/a | n/a | - | 1 | None (same as Default) | 0 | base | - | 2 | Plastic | 1 | plastic | - | 3 | GTK+ | 2 | gtk+ | - | 4 | Gleam | 3 | gleam | - | n/a | n/a | 4 | oxy | - - The new Fluid tries to keep backwards compatibility and reads both - keys (\p scheme and \p scheme_name). If the latter is defined, it is used. - If not the old \p scheme (index) is used - but we need to subtract one to - get the new Fl_Scheme_Choice index (column "Choice" above). -*/ -void init_scheme() { - int scheme_index = 0; // scheme index for backwards compatibility (1.3.x) - char *scheme_name = 0; // scheme name since 1.4.0 - fluid_prefs.get("scheme_name", scheme_name, "XXX"); // XXX means: not set => fallback 1.3.x - if (!strcmp(scheme_name, "XXX")) { - fluid_prefs.get("scheme", scheme_index, 0); - if (scheme_index > 0) { - scheme_index--; - scheme_choice->value(scheme_index); // set the choice value - } - if (scheme_index < 0) - scheme_index = 0; - else if (scheme_index > scheme_choice->size() - 1) - scheme_index = 0; - scheme_name = const_cast(scheme_choice->text(scheme_index)); - fluid_prefs.set("scheme_name", scheme_name); - } - // Set the new scheme only if it was not overridden by the -scheme - // command line option - if (Fl::scheme() == NULL) { - Fl::scheme(scheme_name); - } - free(scheme_name); -} - -/** - Show or hide the widget bin. - The state is stored in the app preferences. - */ -void toggle_widgetbin_cb(Fl_Widget *, void *) { - if (!widgetbin_panel) { - make_widgetbin(); - if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return; - } - - if (widgetbin_panel->visible()) { - widgetbin_panel->hide(); - widgetbin_item->label("Show Widget &Bin..."); - } else { - widgetbin_panel->show(); - widgetbin_item->label("Hide Widget &Bin"); - } -} - -/** - Show or hide the code preview window. - */ -void toggle_codeview_cb(Fl_Double_Window *, void *) { - codeview_toggle_visibility(); -} - -/** - Show or hide the code preview window, button callback. - */ -void toggle_codeview_b_cb(Fl_Button*, void *) { - codeview_toggle_visibility(); -} - -/** - Build the main app window and create a few other dialogs. - */ -void make_main_window() { - if (!batch_mode) { - fluid_prefs.get("show_guides", show_guides, 1); - fluid_prefs.get("show_restricted", show_restricted, 1); - fluid_prefs.get("show_ghosted_outline", show_ghosted_outline, 0); - fluid_prefs.get("show_comments", show_comments, 1); - make_shell_window(); - } - - if (!main_window) { - Fl_Widget *o; - loadPixmaps(); - main_window = new Fl_Double_Window(WINWIDTH,WINHEIGHT,"fluid"); - main_window->box(FL_NO_BOX); - o = make_widget_browser(0,MENUHEIGHT,BROWSERWIDTH,BROWSERHEIGHT); - o->box(FL_FLAT_BOX); - o->tooltip("Double-click to view or change an item."); - main_window->resizable(o); - main_menubar = new Fl_Menu_Bar(0,0,BROWSERWIDTH,MENUHEIGHT); - main_menubar->menu(Main_Menu); - // quick access to all dynamic menu items - save_item = (Fl_Menu_Item*)main_menubar->find_item(save_cb); - history_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_open_history_cb); - widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb); - codeview_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_codeview_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); - restricted_item = (Fl_Menu_Item*)main_menubar->find_item((Fl_Callback*)toggle_restricted); - main_menubar->global(); - fill_in_New_Menu(); - main_window->end(); - } - - if (!batch_mode) { - load_history(); - g_shell_config = new Fd_Shell_Command_List; - widget_browser->load_prefs(); - make_settings_window(); - } -} - -/** - Load file history from preferences. - - This loads the absolute filepaths of the last 10 used design files. - It also computes and stores the relative filepaths for display in - the main menu. - */ -void load_history() { - int i; // Looping var - int max_files; - - fluid_prefs.get("recent_files", max_files, 5); - if (max_files > 10) max_files = 10; - - for (i = 0; i < max_files; i ++) { - fluid_prefs.get( Fl_Preferences::Name("file%d", i), absolute_history[i], "", sizeof(absolute_history[i])); - if (absolute_history[i][0]) { - // Make a shortened version of the filename for the menu... - std::string fn = fl_filename_shortened(absolute_history[i], 48); - strncpy(relative_history[i], fn.c_str(), sizeof(relative_history[i]) - 1); - if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; - else history_item[i].flags = 0; - } else break; - } - - for (; i < 10; i ++) { - if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; - history_item[i].hide(); - } -} - -/** - Update file history from preferences. - - Add this new filepath to the history and update the main menu. - Writes the new file history to the app preferences. - - \param[in] flname path or filename of .fl file, will be converted into an - absolute file path based on the current working directory. - */ -void update_history(const char *flname) { - int i; // Looping var - char absolute[FL_PATH_MAX]; - int max_files; - - - fluid_prefs.get("recent_files", max_files, 5); - if (max_files > 10) max_files = 10; - - fl_filename_absolute(absolute, sizeof(absolute), flname); -#ifdef _WIN32 - // Make path canonical. - for (char *s = absolute; *s; s++) { - if (*s == '\\') - *s = '/'; - } -#endif - - - for (i = 0; i < max_files; i ++) -#if defined(_WIN32) || defined(__APPLE__) - if (!strcasecmp(absolute, absolute_history[i])) break; -#else - if (!strcmp(absolute, absolute_history[i])) break; -#endif // _WIN32 || __APPLE__ - - if (i == 0) return; - - if (i >= max_files) i = max_files - 1; - - // Move the other flnames down in the list... - memmove(absolute_history + 1, absolute_history, - i * sizeof(absolute_history[0])); - memmove(relative_history + 1, relative_history, - i * sizeof(relative_history[0])); - - // Put the new file at the top... - strlcpy(absolute_history[0], absolute, sizeof(absolute_history[0])); - std::string fn = fl_filename_shortened(absolute_history[0], 48); - strncpy(relative_history[0], fn.c_str(), sizeof(relative_history[0]) - 1); - - // Update the menu items as needed... - for (i = 0; i < max_files; i ++) { - fluid_prefs.set( Fl_Preferences::Name("file%d", i), absolute_history[i]); - if (absolute_history[i][0]) { - if (i == 9) history_item[i].flags = FL_MENU_DIVIDER; - else history_item[i].flags = 0; - } else break; - } - - for (; i < 10; i ++) { - fluid_prefs.set( Fl_Preferences::Name("file%d", i), ""); - if (i) history_item[i-1].flags |= FL_MENU_DIVIDER; - history_item[i].hide(); - } - fluid_prefs.flush(); -} - -/** - Set the filename of the current .fl design. - \param[in] c the new absolute filename and path - */ -void set_filename(const char *c) { - if (g_project.proj_filename) free((void *)g_project.proj_filename); - g_project.proj_filename = c ? fl_strdup(c) : NULL; - - if (g_project.proj_filename && !batch_mode) - update_history(g_project.proj_filename); - - set_modflag(modflag); -} - - -/** - Set the "modified" flag and update the title of the main window. - - The first argument sets the modification state of the current design against - the corresponding .fl design file. Any change to the widget tree will mark - the design 'modified'. Saving the design will mark it clean. - - The second argument is optional and set the modification state of the current - design against the source code and header file. Any change to the tree, - including saving the tree, will mark the code 'outdated'. Generating source - code and header files will clear this flag until the next modification. - - \param[in] mf 0 to clear the modflag, 1 to mark the design "modified", -1 to - ignore this parameter - \param[in] mfc default -1 to let \c mf control \c modflag_c, 0 to mark the - code files current, 1 to mark it out of date. -2 to ignore changes to mf. - */ -void set_modflag(int mf, int mfc) { - const char *code_ext = NULL; - char new_title[FL_PATH_MAX]; - - // Update the modflag_c to the worst possible condition. We could be a bit - // more graceful and compare modification times of the files, but C++ has - // no API for that until C++17. - if (mf!=-1) { - modflag = mf; - if (mfc==-1 && mf==1) - mfc = mf; - } - if (mfc>=0) { - modflag_c = mfc; - } - - if (main_window) { - std::string basename; - if (!g_project.proj_filename) basename = "Untitled.fl"; - else basename = fl_filename_name_str(std::string(g_project.proj_filename)); - code_ext = fl_filename_ext(g_project.code_file_name.c_str()); - char mod_star = modflag ? '*' : ' '; - char mod_c_star = modflag_c ? '*' : ' '; - snprintf(new_title, sizeof(new_title), "%s%c %s%c", - basename.c_str(), mod_star, code_ext, mod_c_star); - const char *old_title = main_window->label(); - // only update the title if it actually changed - if (!old_title || strcmp(old_title, new_title)) - main_window->copy_label(new_title); - } - // if the UI was modified in any way, update the Code View panel - if (codeview_panel && codeview_panel->visible() && cv_autorefresh->value()) - codeview_defer_update(); -} - -// ---- Main program entry point - -/** - Handle command line arguments. - \param[in] argc number of arguments in the list - \param[in] argv pointer to an array of arguments - \param[inout] i current argument index - \return number of arguments used; if 0, the argument is not supported - */ -static int arg(int argc, char** argv, int& i) { - if (argv[i][0] != '-') - return 0; - if (argv[i][1] == 'd' && !argv[i][2]) { - G_debug=1; - i++; return 1; - } - if (argv[i][1] == 'u' && !argv[i][2]) { - update_file++; - batch_mode++; - i++; return 1; - } - if (argv[i][1] == 'c' && !argv[i][2]) { - compile_file++; - batch_mode++; - i++; return 1; - } - if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "--version")==0)) { - show_version = 1; - i++; return 1; - } - if (argv[i][1] == 'c' && argv[i][2] == 's' && !argv[i][3]) { - compile_file++; - compile_strings++; - batch_mode++; - i++; return 1; - } - if (argv[i][1] == 'o' && !argv[i][2] && i+1 < argc) { - g_code_filename_arg = argv[i+1]; - batch_mode++; - i += 2; return 2; - } -#ifndef NDEBUG - if ((i+1 < argc) && (strcmp(argv[i], "--autodoc") == 0)) { - g_autodoc_path = argv[i+1]; - i += 2; return 2; - } -#endif - if (strcmp(argv[i], "--help")==0) { - return 0; - } - if (argv[i][1] == 'h' && !argv[i][2]) { - if ( (i+1 < argc) && (argv[i+1][0] != '-') ) { - g_header_filename_arg = argv[i+1]; - batch_mode++; - i += 2; - return 2; - } else { - // a lone "-h" without a filename will output the help string - return 0; - } - } - return 0; -} - -#if ! (defined(_WIN32) && !defined (__CYGWIN__)) - -int quit_flag = 0; -#include -#ifdef _sigargs -#define SIGARG _sigargs -#else -#ifdef __sigargs -#define SIGARG __sigargs -#else -#define SIGARG int // you may need to fix this for older systems -#endif -#endif - -extern "C" { -static void sigint(SIGARG) { - signal(SIGINT,sigint); - quit_flag = 1; -} -} - -#endif - -/** - Start Fluid. - - Fluid can run in interactive mode with a full user interface to design new - user interfaces and write the C++ files to manage them, - - Fluid can run form the command line in batch mode to convert .fl design files - into C++ source and header files. In batch mode, no display is needed, - particularly no X11 connection will be attempted on Linux/Unix. - - \param[in] argc number of arguments in the list - \param[in] argv pointer to an array of arguments - \return in batch mode, an error code will be returned via \c exit() . This - function return 1, if there was an error in the parameters list. - \todo On Windows, Fluid can under certain conditions open a dialog box, even - in batch mode. Is that intentional? Does it circumvent issues with Windows' - stderr and stdout? - */ -int fluid_main(int argc,char **argv) { - int i = 1; - - setlocale(LC_ALL, ""); // enable multi-language errors in file chooser - setlocale(LC_NUMERIC, "C"); // make sure numeric values are written correctly - g_launch_path = end_with_slash(fl_getcwd_str()); // store the current path at launch - - Fl::args_to_utf8(argc, argv); // for MSYS2/MinGW - if ( (Fl::args(argc,argv,i,arg) == 0) // unsupported argument found - || (batch_mode && (i != argc-1)) // .fl filename missing - || (!batch_mode && (i < argc-1)) // more than one filename found - || (argv[i] && (argv[i][0] == '-'))) { // unknown option - static const char *msg = - "usage: %s name.fl\n" - " -u : update .fl file and exit (may be combined with '-c' or '-cs')\n" - " -c : write .cxx and .h and exit\n" - " -cs : write .cxx and .h and strings and exit\n" - " -o : .cxx output filename, or extension if starts with '.'\n" - " -h : .h output filename, or extension if starts with '.'\n" - " --help : brief usage information\n" - " --version, -v : print fluid version number\n" - " -d : enable internal debugging\n"; - const char *app_name = NULL; - if ( (argc > 0) && argv[0] && argv[0][0] ) - app_name = fl_filename_name(argv[0]); - if ( !app_name || !app_name[0]) - app_name = "fluid"; -#ifdef _MSC_VER - // TODO: if this is fluid-cmd, use stderr and not fl_message - fl_message(msg, app_name); -#else - fprintf(stderr, msg, app_name); -#endif - return 1; - } - if (show_version) { - printf("fluid v%d.%d.%d\n", FL_MAJOR_VERSION, FL_MINOR_VERSION, FL_PATCH_VERSION); - ::exit(0); - } - - const char *c = NULL; - if (g_autodoc_path.empty()) - c = argv[i]; - - fl_register_images(); - - make_main_window(); - - if (c) set_filename(c); - if (!batch_mode) { -#ifdef __APPLE__ - fl_open_callback(apple_open_cb); -#endif // __APPLE__ - Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX)); - Fl_File_Icon::load_system_icons(); - main_window->callback(exit_cb); - position_window(main_window,"main_window_pos", 1, 10, 30, WINWIDTH, WINHEIGHT ); - if (g_shell_config) { - g_shell_config->read(fluid_prefs, FD_STORE_USER); - g_shell_config->update_settings_dialog(); - g_shell_config->rebuild_shell_menu(); - } - g_layout_list.read(fluid_prefs, FD_STORE_USER); - main_window->show(argc,argv); - toggle_widgetbin_cb(0,0); - toggle_codeview_cb(0,0); - if (!c && openlast_button->value() && absolute_history[0][0] && g_autodoc_path.empty()) { - // Open previous file when no file specified... - open_project_file(absolute_history[0]); - } - } - undo_suspend(); - if (c && !fld::io::read_file(c,0)) { - if (batch_mode) { - fprintf(stderr,"%s : %s\n", c, strerror(errno)); - exit(1); - } - fl_message("Can't read %s: %s", c, strerror(errno)); - } - undo_resume(); - - // command line args override code and header filenames from the project file - // in batch mode only - if (batch_mode) { - if (!g_code_filename_arg.empty()) { - g_project.code_file_set = 1; - g_project.code_file_name = g_code_filename_arg; - } - if (!g_header_filename_arg.empty()) { - g_project.header_file_set = 1; - g_project.header_file_name = g_header_filename_arg; - } - } - - if (update_file) { // fluid -u - fld::io::write_file(c,0); - if (!compile_file) - exit(0); - } - - if (compile_file) { // fluid -c[s] - if (compile_strings) - write_strings_cb(0,0); - write_cb(0,0); - exit(0); - } - - // don't lock up if inconsistent command line arguments were given - if (batch_mode) - exit(0); - - set_modflag(0); - undo_clear(); -#ifndef _WIN32 - signal(SIGINT,sigint); -#endif - - // Set (but do not start) timer callback for external editor updates - ExternalCodeEditor::set_update_timer_callback(external_editor_timer); - -#ifndef NDEBUG - // check if the user wants FLUID to generate image for the user documentation - if (!g_autodoc_path.empty()) { - run_autodoc(g_autodoc_path); - set_modflag(0, 0); - exit_cb(0,0); - return 0; - } -#endif - -#ifdef _WIN32 - Fl::run(); -#else - while (!quit_flag) Fl::wait(); - if (quit_flag) exit_cb(0,0); -#endif // _WIN32 - - undo_clear(); - return (0); -} - -/// \} - diff --git a/fluid/app/fluid.h b/fluid/app/fluid.h deleted file mode 100644 index 686047a72..000000000 --- a/fluid/app/fluid.h +++ /dev/null @@ -1,134 +0,0 @@ -// -// FLUID main entry for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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_APP_FLUID_H -#define FLUID_APP_FLUID_H - -#include "tools/filename.h" - -#include -#include -#include - -#include - -#define BROWSERWIDTH 300 -#define BROWSERHEIGHT 500 -#define WINWIDTH 300 -#define MENUHEIGHT 25 -#define WINHEIGHT (BROWSERHEIGHT+MENUHEIGHT) - -// ---- types - -class Fl_Double_Window; -class Fl_Window; -class Fl_Menu_Bar; -class Fl_Type; -class Fl_Choice; -class Fl_Button; -class Fl_Check_Button; - -/** - Indicate the storage location for tools like layout suites and shell macros. - \see class Fd_Shell_Command, class Fd_Layout_Suite - */ -typedef enum { - FD_STORE_INTERNAL, ///< stored inside FLUID app - FD_STORE_USER, ///< suite is stored in the user wide FLUID settings - FD_STORE_PROJECT, ///< suite is stored within the current .fl project file - FD_STORE_FILE ///< store suite in external file -} Fd_Tool_Store; - -// ---- global variables - -extern Fl_Preferences fluid_prefs; -extern Fl_Menu_Item Main_Menu[]; -extern Fl_Menu_Bar *main_menubar; -extern Fl_Window *main_window; - -extern int show_guides; -extern int show_restricted; -extern int show_ghosted_outline; -extern int show_comments; - -extern int G_use_external_editor; -extern int G_debug; -extern char G_external_editor_command[512]; - -// File history info... -extern char absolute_history[10][FL_PATH_MAX]; -extern char relative_history[10][FL_PATH_MAX]; -extern void load_history(); -extern void update_history(const char *); - -extern Fl_Menu_Item *save_item; -extern Fl_Menu_Item *history_item; -extern Fl_Menu_Item *widgetbin_item; -extern Fl_Menu_Item *codeview_item; -extern Fl_Menu_Item *overlay_item; -extern Fl_Button *overlay_button; -extern Fl_Menu_Item *guides_item; -extern Fl_Menu_Item *restricted_item; -extern Fl_Check_Button *guides_button; - -extern int modflag; - -extern int update_file; // fluid -u -extern int compile_file; // fluid -c -extern int compile_strings; // fluic -cs -extern int batch_mode; - -extern int pasteoffset; - -extern std::string g_code_filename_arg; -extern std::string g_header_filename_arg; -extern std::string g_launch_path; - -extern std::string g_autodoc_path; - -// ---- public functions - -extern int fluid_main(int argc,char **argv); - -extern bool new_project(bool user_must_confirm = true); -extern void enter_project_dir(); -extern void leave_project_dir(); -extern void set_filename(const char *c); -extern void set_modflag(int mf, int mfc=-1); - -extern const std::string &get_tmpdir(); -extern std::string end_with_slash(const std::string &str); - -// ---- public callback functions - -extern void save_cb(Fl_Widget *, void *v); -extern void save_template_cb(Fl_Widget *, void *); -extern void revert_cb(Fl_Widget *,void *); -extern void exit_cb(Fl_Widget *,void *); - -extern int write_code_files(bool dont_show_completion_dialog=false); -extern void write_strings_cb(Fl_Widget *, void *); -extern void align_widget_cb(Fl_Widget *, long); -extern void toggle_widgetbin_cb(Fl_Widget *, void *); - -extern char position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W=0, int H=0); - -inline int fd_min(int a, int b) { return (a < b ? a : b); } -inline int fd_max(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_APP_FLUID_H - diff --git a/fluid/app/history.cxx b/fluid/app/history.cxx new file mode 100644 index 000000000..7eadb5469 --- /dev/null +++ b/fluid/app/history.cxx @@ -0,0 +1,115 @@ +// +// Fluid Project File History code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "app/history.h" + +#include "Fluid.h" + +#include "../src/flstring.h" + +using namespace fld; +using namespace fld::app; + + +/** + Load file history from preferences. + + This loads the absolute filepaths of the last 10 used design files. + It also computes and stores the relative filepaths for display in + the main menu. + */ +void History::load() { + int i; // Looping var + int max_files; + + Fluid.preferences.get("recent_files", max_files, 5); + if (max_files > 10) max_files = 10; + + for (i = 0; i < max_files; i ++) { + Fluid.preferences.get( Fl_Preferences::Name("file%d", i), abspath[i], "", sizeof(abspath[i])); + if (abspath[i][0]) { + // Make a shortened version of the filename for the menu... + std::string fn = fl_filename_shortened(abspath[i], 48); + strncpy(relpath[i], fn.c_str(), sizeof(relpath[i]) - 1); + if (i == 9) Fluid.history_item[i].flags = FL_MENU_DIVIDER; + else Fluid.history_item[i].flags = 0; + } else break; + } + + for (; i < 10; i ++) { + if (i) Fluid.history_item[i-1].flags |= FL_MENU_DIVIDER; + Fluid.history_item[i].hide(); + } +} + +/** + Update file history from preferences. + + Add this new filepath to the history and update the main menu. + Writes the new file history to the app preferences. + + \param[in] project_file path and filename of .fl project file, will be + converted into an absolute file path based on the current working directory. + */ +void History::update(std::string project_file) { + int i; // Looping var + int max_files; + + Fluid.preferences.get("recent_files", max_files, 5); + if (max_files > 10) max_files = 10; + + std::string absolute = fld::fix_separators(fl_filename_absolute_str(project_file)); + for (i = 0; i < max_files; i ++) +#if defined(_WIN32) || defined(__APPLE__) + if (!strcasecmp(absolute.c_str(), abspath[i])) break; +#else + if (!strcmp(absolute.c_str(), abspath[i])) break; +#endif // _WIN32 || __APPLE__ + + // Does the first entry match? + if (i == 0) + return; + + // Was there no match? + if (i >= max_files) + i = max_files - 1; + + // Move the other filenames down in the list... + memmove(abspath + 1, abspath, i * sizeof(abspath[0])); + memmove(relpath + 1, relpath, i * sizeof(relpath[0])); + + // Put the new file at the top... + strlcpy(abspath[0], absolute.c_str(), sizeof(abspath[0])); + std::string fn = fl_filename_shortened(absolute, 48); + strncpy(relpath[0], fn.c_str(), sizeof(relpath[0]) - 1); + + // Update the menu items as needed... + for (i = 0; i < max_files; i ++) { + Fluid.preferences.set( Fl_Preferences::Name("file%d", i), abspath[i]); + if (abspath[i][0]) { + if (i == 9) Fluid.history_item[i].flags = FL_MENU_DIVIDER; + else Fluid.history_item[i].flags = 0; + } else break; + } + + for (; i < 10; i ++) { + Fluid.preferences.set( Fl_Preferences::Name("file%d", i), ""); + if (i) Fluid.history_item[i-1].flags |= FL_MENU_DIVIDER; + Fluid.history_item[i].hide(); + } + Fluid.preferences.flush(); +} + diff --git a/fluid/app/history.h b/fluid/app/history.h new file mode 100644 index 000000000..e32723b4b --- /dev/null +++ b/fluid/app/history.h @@ -0,0 +1,45 @@ +// +// Fluid Project File History header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_APP_HISTORY_H +#define FLUID_APP_HISTORY_H + +#include + +#include + +namespace fld { +namespace app { + +class History { +public: + /// Stores the absolute filename of the last 10 project files, saved in app preferences. + char abspath[10][FL_PATH_MAX] { }; + /// The list of filenames as displayed in the main menu. + char relpath[10][FL_PATH_MAX] { }; + // Create the project file history. + History() = default; + // Load the project history from the preferences database. + void load(); + // Add a new file to the project history using absolute paths. + void update(std::string project_file); +}; + +} // namespace app +} // namespace fld + +#endif // FLUID_APP_HISTORY_H + diff --git a/fluid/app/project.cxx b/fluid/app/project.cxx deleted file mode 100644 index f369680e5..000000000 --- a/fluid/app/project.cxx +++ /dev/null @@ -1,192 +0,0 @@ -// -// FLUID main entry for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 "app/project.h" - -#include "nodes/Fl_Type.h" -#include "panels/settings_panel.h" - -// ---- project settings - -/// The current project, possibly a new, empty roject -Fluid_Project g_project; - -/** - Initialize a new project. - */ -Fluid_Project::Fluid_Project() : -i18n_type(FD_I18N_NONE), -include_H_from_C(1), -use_FL_COMMAND(0), -utf8_in_src(0), -avoid_early_includes(0), -header_file_set(0), -code_file_set(0), -write_mergeback_data(0), -header_file_name(".h"), -code_file_name(".cxx") -{ } - -/** - Clear all project resources. - Not implemented. - */ -Fluid_Project::~Fluid_Project() { -} - -/** - Reset all project setting to create a new empty project. - */ -void Fluid_Project::reset() { - ::delete_all(); - i18n_type = FD_I18N_NONE; - - i18n_gnu_include = ""; - i18n_gnu_conditional = ""; - i18n_gnu_function = "gettext"; - i18n_gnu_static_function = "gettext_noop"; - - i18n_pos_include = ""; - i18n_pos_conditional = ""; - i18n_pos_file = ""; - i18n_pos_set = "1"; - - include_H_from_C = 1; - use_FL_COMMAND = 0; - utf8_in_src = 0; - avoid_early_includes = 0; - header_file_set = 0; - code_file_set = 0; - header_file_name = ".h"; - code_file_name = ".cxx"; - write_mergeback_data = 0; -} - -/** - Tell the project and i18n tab of the settings dialog to refresh themselves. - */ -void Fluid_Project::update_settings_dialog() { - if (settings_window) { - w_settings_project_tab->do_callback(w_settings_project_tab, LOAD); - w_settings_i18n_tab->do_callback(w_settings_i18n_tab, LOAD); - } -} - -/** - Get the absolute path of the project file, for example `/Users/matt/dev/`. - \return the path ending in '/' - */ -std::string Fluid_Project::projectfile_path() const { - return end_with_slash(fl_filename_absolute_str(fl_filename_path_str(proj_filename), g_launch_path)); -} - -/** - Get the project file name including extension, for example `test.fl`. - \return the file name without path - */ -std::string Fluid_Project::projectfile_name() const { - return fl_filename_name(proj_filename); -} - -/** - Get the absolute path of the generated C++ code file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::codefile_path() const { - std::string path = fl_filename_path_str(code_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ code file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::codefile_name() const { - std::string name = fl_filename_name_str(code_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name(proj_filename), ".cxx"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name(proj_filename), code_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated C++ header file, for example `/Users/matt/dev/src/`. - \return the path ending in '/' - */ -std::string Fluid_Project::headerfile_path() const { - std::string path = fl_filename_path_str(header_file_name); - if (batch_mode) - return end_with_slash(fl_filename_absolute_str(path, g_launch_path)); - else - return end_with_slash(fl_filename_absolute_str(path, projectfile_path())); -} - -/** - Get the generated C++ header file name including extension, for example `test.cxx`. - \return the file name without path - */ -std::string Fluid_Project::headerfile_name() const { - std::string name = fl_filename_name_str(header_file_name); - if (name.empty()) { - return fl_filename_setext_str(fl_filename_name_str(proj_filename), ".h"); - } else if (name[0] == '.') { - return fl_filename_setext_str(fl_filename_name_str(proj_filename), header_file_name); - } else { - return name; - } -} - -/** - Get the absolute path of the generated i18n strings file, for example `/Users/matt/dev/`. - Although it may be more useful to put the text file into the same directory - with the source and header file, historically, the text is always saved with - the project file in interactive mode, and in the FLUID launch directory in - batch mode. - \return the path ending in '/' - */ -std::string Fluid_Project::stringsfile_path() const { - if (batch_mode) - return g_launch_path; - else - return projectfile_path(); -} - -/** - Get the generated i18n text file name including extension, for example `test.po`. - \return the file name without path - */ -std::string Fluid_Project::stringsfile_name() const { - switch (i18n_type) { - default: return fl_filename_setext_str(fl_filename_name(proj_filename), ".txt"); - case FD_I18N_GNU: return fl_filename_setext_str(fl_filename_name(proj_filename), ".po"); - case FD_I18N_POSIX: return fl_filename_setext_str(fl_filename_name(proj_filename), ".msg"); - } -} - -/** - Get the name of the project file without the filename extension. - \return the file name without path or extension - */ -std::string Fluid_Project::basename() const { - return fl_filename_setext_str(fl_filename_name(proj_filename), ""); -} - diff --git a/fluid/app/shell_command.cxx b/fluid/app/shell_command.cxx index 7012de8e6..3bb252cae 100644 --- a/fluid/app/shell_command.cxx +++ b/fluid/app/shell_command.cxx @@ -1,7 +1,7 @@ // -// FLUID main entry for the Fast Light Tool Kit (FLTK). +// Shell Command database coe for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -62,7 +62,7 @@ // TODO: make the settings dialog resizable // TODO: make g_shell_config static, not a pointer, but don't load anything in batch mode -// FEATURE: Fd_Tool_Store icons are currently redundant with @file and @save and could be improved +// FEATURE: fld::Tool_Store icons are currently redundant with @file and @save and could be improved // FEATURE: hostname, username, getenv support? // FEATURE: add the files ./fluid.prefs and ./fluid.user.prefs as tool locations // FEATURE: interpret compiler output, for example: clang, and highlight errors and warnings @@ -97,8 +97,8 @@ #include "app/shell_command.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "panels/settings_panel.h" @@ -110,6 +110,8 @@ #include +using namespace fld; + static std::string fltk_config_cmd; static Fl_Process s_proc; @@ -120,40 +122,6 @@ bool shell_command_running() { return s_proc.desc() ? true : false; } -/** - Reads an entry from the group. A default value must be - supplied. The return value indicates if the value was available - (non-zero) or the default was used (0). - - \param[in] prefs preference group - \param[in] key name of entry - \param[out] value returned from preferences or default value if none was set - \param[in] defaultValue default value to be used if no preference was set - \return 0 if the default value was used - */ -char preferences_get(Fl_Preferences &prefs, const char *key, std::string &value, const std::string &defaultValue) { - char *v = NULL; - char ret = prefs.get(key, v, defaultValue.c_str()); - value = v; - ::free(v); - return ret; -} - -/** - Sets an entry (name/value pair). The return value indicates if there - was a problem storing the data in memory. However it does not - reflect if the value was actually stored in the preference file. - - \param[in] prefs preference group - \param[in] entry name of entry - \param[in] value set this entry to value (stops at the first nul character). - \return 0 if setting the value failed - */ -char preferences_set(Fl_Preferences &prefs, const char *key, const std::string &value) { - return prefs.set(key, value.c_str()); -} - - /** \class Fl_Process Launch an external shell command. */ @@ -162,7 +130,6 @@ char preferences_set(Fl_Preferences &prefs, const char *key, const std::string & Create a process manager */ Fl_Process::Fl_Process() { - _fpt= NULL; } /** @@ -183,13 +150,13 @@ Fl_Process::~Fl_Process() { FILE * Fl_Process::popen(const char *cmd, const char *mode) { #if defined(_WIN32) && !defined(__CYGWIN__) // PRECONDITIONS - if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL; + if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return nullptr; if (_fpt) close(); // close first before reuse ptmode = *mode; pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE; // stderr to stdout wanted ? - int fusion = (strstr(cmd,"2>&1") !=NULL); + int fusion = (strstr(cmd,"2>&1") !=nullptr); // Create windows pipes if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) ) @@ -203,8 +170,8 @@ FILE * Fl_Process::popen(const char *cmd, const char *mode) { si.hStdOutput = pout[1]; si.hStdError = fusion ? pout[1] : perr [1]; - if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE, - DETACHED_PROCESS,NULL,NULL, &si, &pi)) { + if ( CreateProcess(nullptr, (LPTSTR) cmd,nullptr,nullptr,TRUE, + DETACHED_PROCESS,nullptr,nullptr, &si, &pi)) { // don't need theses handles inherited by child process: clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]); HANDLE & h = *mode == 'r' ? pout[0] : pin[1]; @@ -231,13 +198,13 @@ int Fl_Process::close() { clean_close(perr[0]); clean_close(pin[1]); clean_close(pout[0]); - _fpt = NULL; + _fpt = nullptr; return 0; } return -1; #else int ret = ::pclose(_fpt); - _fpt=NULL; + _fpt=nullptr; return ret; #endif } @@ -256,10 +223,10 @@ FILE *Fl_Process::desc() const { \param[out] line buffer to receive the line \param[in] s size of the provided buffer - \return NULL if an error occurred, otherwise a pointer to the string + \return nullptr if an error occurred, otherwise a pointer to the string */ char *Fl_Process::get_line(char * line, size_t s) const { - return _fpt ? fgets(line, (int)s, _fpt) : NULL; + return _fpt ? fgets(line, (int)s, _fpt) : nullptr; } // returns fileno(FILE*): @@ -279,7 +246,7 @@ int Fl_Process::get_fileno() const { bool Fl_Process::createPipe(HANDLE * h, BOOL bInheritHnd) { SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; + sa.lpSecurityDescriptor = nullptr; sa.bInheritHandle = bInheritHnd; return CreatePipe (&h[0],&h[1],&sa,0) ? true : false; } @@ -288,7 +255,7 @@ FILE *Fl_Process::freeHandles() { clean_close(pin[0]); clean_close(pin[1]); clean_close(pout[0]); clean_close(pout[1]); clean_close(perr[0]); clean_close(perr[1]); - return NULL; // convenient for error management + return nullptr; // convenient for error management } void Fl_Process::clean_close(HANDLE& h) { @@ -312,13 +279,13 @@ static bool prepare_shell_command(int flags) { return false; } if (flags & Fd_Shell_Command::SAVE_PROJECT) { - save_cb(0, 0); + Fluid.save_project_file(nullptr); } if (flags & Fd_Shell_Command::SAVE_SOURCECODE) { - write_code_files(true); + Fluid.write_code_files(true); } if (flags & Fd_Shell_Command::SAVE_STRINGS) { - write_strings_cb(0, 0); + Fluid.proj.write_strings(); } return true; } @@ -345,7 +312,7 @@ void shell_timer_cb(void*) { void shell_pipe_cb(FL_SOCKET, void*) { char line[1024]=""; // Line from command output... - if (s_proc.get_line(line, sizeof(line)) != NULL) { + if (s_proc.get_line(line, sizeof(line)) != nullptr) { // Add the line to the output list... shell_run_terminal->append(line); } else { @@ -373,29 +340,29 @@ static void expand_macro(std::string &cmd, const std::string ¯o, const std:: } static void expand_macros(std::string &cmd) { - expand_macro(cmd, "@BASENAME@", g_project.basename()); - expand_macro(cmd, "@PROJECTFILE_PATH@", g_project.projectfile_path()); - expand_macro(cmd, "@PROJECTFILE_NAME@", g_project.projectfile_name()); - expand_macro(cmd, "@CODEFILE_PATH@", g_project.codefile_path()); - expand_macro(cmd, "@CODEFILE_NAME@", g_project.codefile_name()); - expand_macro(cmd, "@HEADERFILE_PATH@", g_project.headerfile_path()); - expand_macro(cmd, "@HEADERFILE_NAME@", g_project.headerfile_name()); - expand_macro(cmd, "@TEXTFILE_PATH@", g_project.stringsfile_path()); - expand_macro(cmd, "@TEXTFILE_NAME@", g_project.stringsfile_name()); + expand_macro(cmd, "@BASENAME@", Fluid.proj.basename()); + expand_macro(cmd, "@PROJECTFILE_PATH@", Fluid.proj.projectfile_path()); + expand_macro(cmd, "@PROJECTFILE_NAME@", Fluid.proj.projectfile_name()); + expand_macro(cmd, "@CODEFILE_PATH@", Fluid.proj.codefile_path()); + expand_macro(cmd, "@CODEFILE_NAME@", Fluid.proj.codefile_name()); + expand_macro(cmd, "@HEADERFILE_PATH@", Fluid.proj.headerfile_path()); + expand_macro(cmd, "@HEADERFILE_NAME@", Fluid.proj.headerfile_name()); + expand_macro(cmd, "@TEXTFILE_PATH@", Fluid.proj.stringsfile_path()); + expand_macro(cmd, "@TEXTFILE_NAME@", Fluid.proj.stringsfile_name()); // TODO: implement finding the script `fltk-config` for all platforms // if (cmd.find("@FLTK_CONFIG@") != std::string::npos) { // find_fltk_config(); // expand_macro(cmd, "@FLTK_CONFIG@", fltk_config_cmd.c_str()); // } if (cmd.find("@TMPDIR@") != std::string::npos) - expand_macro(cmd, "@TMPDIR@", get_tmpdir()); + expand_macro(cmd, "@TMPDIR@", Fluid.get_tmpdir()); } /** Show the terminal window where it was last positioned. */ void show_terminal_window() { - Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); + Fl_Preferences pos(Fluid.preferences, "shell_run_Window_pos"); int x, y, w, h; pos.get("x", x, -1); pos.get("y", y, 0); @@ -439,7 +406,7 @@ void run_shell_command(const std::string &cmd, int flags) { shell_run_terminal->printf("\033[0;32m%s\033[0m\n", expanded_cmd.c_str()); shell_run_window->label(expanded_cmd.c_str()); - if (s_proc.popen((char *)expanded_cmd.c_str()) == NULL) { + if (s_proc.popen((char *)expanded_cmd.c_str()) == nullptr) { shell_run_terminal->printf("\033[1;31mUnable to run shell command: %s\033[0m\n", strerror(errno)); shell_run_window->label("FLUID Shell"); @@ -459,10 +426,10 @@ void run_shell_command(const std::string &cmd, int flags) { */ Fd_Shell_Command::Fd_Shell_Command() : shortcut(0), - storage(FD_STORE_USER), + storage(fld::Tool_Store::USER), condition(0), flags(0), - shell_menu_item_(NULL) + shell_menu_item_(nullptr) { } @@ -480,7 +447,7 @@ Fd_Shell_Command::Fd_Shell_Command(const Fd_Shell_Command *rhs) condition_data(rhs->condition_data), command(rhs->command), flags(rhs->flags), - shell_menu_item_(NULL) + shell_menu_item_(nullptr) { } @@ -493,11 +460,11 @@ Fd_Shell_Command::Fd_Shell_Command(const std::string &in_name) : name(in_name), label(in_name), shortcut(0), - storage(FD_STORE_USER), + storage(fld::Tool_Store::USER), condition(Fd_Shell_Command::ALWAYS), command("echo \"Hello, FLUID!\""), flags(Fd_Shell_Command::SAVE_PROJECT|Fd_Shell_Command::SAVE_SOURCECODE), - shell_menu_item_(NULL) + shell_menu_item_(nullptr) { } @@ -516,7 +483,7 @@ Fd_Shell_Command::Fd_Shell_Command(const std::string &in_name) Fd_Shell_Command::Fd_Shell_Command(const std::string &in_name, const std::string &in_label, Fl_Shortcut in_shortcut, - Fd_Tool_Store in_storage, + fld::Tool_Store in_storage, int in_condition, const std::string &in_condition_data, const std::string &in_command, @@ -529,7 +496,7 @@ Fd_Shell_Command::Fd_Shell_Command(const std::string &in_name, condition_data(in_condition_data), command(in_command), flags(in_flags), - shell_menu_item_(NULL) + shell_menu_item_(nullptr) { } @@ -549,8 +516,8 @@ void Fd_Shell_Command::run() { */ void Fd_Shell_Command::update_shell_menu() { if (shell_menu_item_) { - const char *old_label = shell_menu_item_->label(); // can be NULL - const char *new_label = label.c_str(); // never NULL + const char *old_label = shell_menu_item_->label(); // can be nullptr + const char *new_label = label.c_str(); // never nullptr if (!old_label || (old_label && strcmp(old_label, new_label))) { if (old_label) ::free((void*)old_label); shell_menu_item_->label(fl_strdup(new_label)); @@ -597,33 +564,33 @@ bool Fd_Shell_Command::is_active() { void Fd_Shell_Command::read(Fl_Preferences &prefs) { int tmp; - preferences_get(prefs, "name", name, ""); - preferences_get(prefs, "label", label, ""); + prefs.get("name", name, ""); + prefs.get("label", label, ""); prefs.get("shortcut", tmp, 0); shortcut = (Fl_Shortcut)tmp; prefs.get("storage", tmp, -1); - if (tmp != -1) storage = (Fd_Tool_Store)tmp; + if (tmp != -1) storage = (fld::Tool_Store)tmp; prefs.get("condition", condition, ALWAYS); - preferences_get(prefs, "condition_data", condition_data, ""); - preferences_get(prefs, "command", command, ""); + prefs.get("condition_data", condition_data, ""); + prefs.get("command", command, ""); prefs.get("flags", flags, 0); } void Fd_Shell_Command::write(Fl_Preferences &prefs, bool save_location) { - preferences_set(prefs, "name", name); - preferences_set(prefs, "label", label); + prefs.set("name", name); + prefs.set("label", label); if (shortcut != 0) prefs.set("shortcut", (int)shortcut); if (save_location) prefs.set("storage", (int)storage); if (condition != ALWAYS) prefs.set("condition", condition); - if (!condition_data.empty()) preferences_set(prefs, "condition_data", condition_data); - if (!command.empty()) preferences_set(prefs, "command", command); + if (!condition_data.empty()) prefs.set("condition_data", condition_data); + if (!command.empty()) prefs.set("command", command); if (flags != 0) prefs.set("flags", flags); } void Fd_Shell_Command::read(class fld::io::Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group - storage = FD_STORE_PROJECT; + storage = fld::Tool_Store::PROJECT; for (;;) { c = in->read_word(1); if (strcmp(c, "}")==0) break; // end of command list @@ -667,10 +634,6 @@ void Fd_Shell_Command::write(class fld::io::Project_Writer *out) { Manage a list of shell commands and their parameters. */ Fd_Shell_Command_List::Fd_Shell_Command_List() -: list(NULL), - list_size(0), - list_capacity(0), - shell_menu_(NULL) { } @@ -702,14 +665,14 @@ void Fd_Shell_Command_List::clear() { ::free(list); list_size = 0; list_capacity = 0; - list = 0; + list = nullptr; } } /** remove all shell commands of the given storage location from the list. */ -void Fd_Shell_Command_List::clear(Fd_Tool_Store storage) { +void Fd_Shell_Command_List::clear(fld::Tool_Store storage) { for (int i=list_size-1; i>=0; i--) { if (list[i]->storage == storage) { remove(i); @@ -720,22 +683,22 @@ void Fd_Shell_Command_List::clear(Fd_Tool_Store storage) { /** Read shell configuration from a preferences group. */ -void Fd_Shell_Command_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { +void Fd_Shell_Command_List::read(Fl_Preferences &prefs, fld::Tool_Store storage) { // import the old shell commands from previous user settings - if (&fluid_prefs == &prefs) { + if (&Fluid.preferences == &prefs) { int version; prefs.get("shell_commands_version", version, 0); if (version == 0) { int save_fl, save_code, save_strings; Fd_Shell_Command *cmd = new Fd_Shell_Command(); - cmd->storage = FD_STORE_USER; + cmd->storage = fld::Tool_Store::USER; cmd->name = "Sample Shell Command"; cmd->label = "Sample Shell Command"; cmd->shortcut = FL_ALT+'g'; - preferences_get(fluid_prefs, "shell_command", cmd->command, "echo \"Sample Shell Command\""); - fluid_prefs.get("shell_savefl", save_fl, 1); - fluid_prefs.get("shell_writecode", save_code, 1); - fluid_prefs.get("shell_writemsgs", save_strings, 0); + Fluid.preferences.get("shell_command", cmd->command, "echo \"Sample Shell Command\""); + Fluid.preferences.get("shell_savefl", save_fl, 1); + Fluid.preferences.get("shell_writecode", save_code, 1); + Fluid.preferences.get("shell_writemsgs", save_strings, 0); if (save_fl) cmd->flags |= Fd_Shell_Command::SAVE_PROJECT; if (save_code) cmd->flags |= Fd_Shell_Command::SAVE_SOURCECODE; if (save_strings) cmd->flags |= Fd_Shell_Command::SAVE_STRINGS; @@ -749,7 +712,7 @@ void Fd_Shell_Command_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { for (int i=0; istorage = FD_STORE_USER; + cmd->storage = fld::Tool_Store::USER; cmd->read(cmd_prefs); add(cmd); } @@ -758,12 +721,12 @@ void Fd_Shell_Command_List::read(Fl_Preferences &prefs, Fd_Tool_Store storage) { /** Write shell configuration to a preferences group. */ -void Fd_Shell_Command_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) { +void Fd_Shell_Command_List::write(Fl_Preferences &prefs, fld::Tool_Store storage) { Fl_Preferences shell_commands(prefs, "shell_commands"); shell_commands.delete_all_groups(); int index = 0; for (int i=0; istorage == FD_STORE_USER) { + if (list[i]->storage == fld::Tool_Store::USER) { Fl_Preferences cmd(shell_commands, Fl_Preferences::Name(index++)); list[i]->write(cmd); } @@ -776,7 +739,7 @@ void Fd_Shell_Command_List::write(Fl_Preferences &prefs, Fd_Tool_Store storage) void Fd_Shell_Command_List::read(fld::io::Project_Reader *in) { const char *c = in->read_word(1); if (strcmp(c, "{")!=0) return; // expecting start of group - clear(FD_STORE_PROJECT); + clear(fld::Tool_Store::PROJECT); for (;;) { c = in->read_word(1); if (strcmp(c, "}")==0) break; // end of command list @@ -796,13 +759,13 @@ void Fd_Shell_Command_List::read(fld::io::Project_Reader *in) { void Fd_Shell_Command_List::write(fld::io::Project_Writer *out) { int n_in_project_file = 0; for (int i=0; istorage == FD_STORE_PROJECT) + if (list[i]->storage == fld::Tool_Store::PROJECT) n_in_project_file++; } if (n_in_project_file > 0) { out->write_string("\nshell_commands {"); for (int i=0; istorage == FD_STORE_PROJECT) + if (list[i]->storage == fld::Tool_Store::PROJECT) list[i]->write(out); } out->write_string("\n}"); @@ -872,9 +835,9 @@ void menu_shell_customize_cb(Fl_Widget*, void*) { Rebuild the entire shell submenu from scratch and replace the old menu. */ void Fd_Shell_Command_List::rebuild_shell_menu() { - static Fl_Menu_Item *shell_submenu = NULL; + static Fl_Menu_Item *shell_submenu = nullptr; if (!shell_submenu) - shell_submenu = (Fl_Menu_Item*)main_menubar->find_item(menu_marker); + shell_submenu = (Fl_Menu_Item*)Fluid.main_menubar->find_item(menu_marker); int i, j, num_active_items = 0; // count the active commands @@ -926,7 +889,7 @@ void Fd_Shell_Command_List::update_settings_dialog() { */ Fl_Menu_Item Fd_Shell_Command_List::default_menu[] = { { "Customize...", FL_ALT+'x', menu_shell_customize_cb }, - { NULL } + { nullptr } }; /** @@ -939,7 +902,7 @@ void Fd_Shell_Command_List::menu_marker(Fl_Widget*, void*) { /** Export all selected shell commands to an external file. - Verify that g_shell_config and w_settings_shell_list are not NULL. Open a + Verify that g_shell_config and w_settings_shell_list are not nullptr. Open a file chooser and export all items that are selected in w_settings_shell_list into an external file. */ @@ -951,11 +914,11 @@ void Fd_Shell_Command_List::export_selected() { dialog.title("Export selected shell commands:"); dialog.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); dialog.filter("FLUID Files\t*.flcmd\n"); - dialog.directory(g_project.projectfile_path().c_str()); - dialog.preset_file((g_project.basename() + ".flcmd").c_str()); + dialog.directory(Fluid.proj.projectfile_path().c_str()); + dialog.preset_file((Fluid.proj.basename() + ".flcmd").c_str()); if (dialog.show() != 0) return; - Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); + Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", nullptr, (Fl_Preferences::Root)(Fl_Preferences::C_LOCALE|Fl_Preferences::CLEAR)); Fl_Preferences shell_commands(file, "shell_commands"); int i, index = 0, n = w_settings_shell_list->size(); for (i = 0; i < n; i++) { @@ -969,7 +932,7 @@ void Fd_Shell_Command_List::export_selected() { /** Import shell commands from an external file and add them to the list. - Verify that g_shell_config and w_settings_shell_list are not NULL. Open a + Verify that g_shell_config and w_settings_shell_list are not nullptr. Open a file chooser and import all items. */ void Fd_Shell_Command_List::import_from_file() { @@ -980,17 +943,17 @@ void Fd_Shell_Command_List::import_from_file() { dialog.title("Import shell commands:"); dialog.type(Fl_Native_File_Chooser::BROWSE_FILE); dialog.filter("FLUID Files\t*.flcmd\n"); - dialog.directory(g_project.projectfile_path().c_str()); - dialog.preset_file((g_project.basename() + ".flcmd").c_str()); + dialog.directory(Fluid.proj.projectfile_path().c_str()); + dialog.preset_file((Fluid.proj.basename() + ".flcmd").c_str()); if (dialog.show() != 0) return; - Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", NULL, Fl_Preferences::C_LOCALE); + Fl_Preferences file(dialog.filename(), "flcmd.fluid.fltk.org", nullptr, Fl_Preferences::C_LOCALE); Fl_Preferences shell_commands(file, "shell_commands"); int i, n = shell_commands.groups(); for (i = 0; i < n; i++) { Fl_Preferences cmd_prefs(shell_commands, Fl_Preferences::Name(i)); Fd_Shell_Command *cmd = new Fd_Shell_Command(); - cmd->storage = FD_STORE_USER; + cmd->storage = fld::Tool_Store::USER; cmd->read(cmd_prefs); g_shell_config->add(cmd); } @@ -1003,5 +966,5 @@ void Fd_Shell_Command_List::import_from_file() { /** A pointer to the list of shell commands if we are not in batch mode. */ -Fd_Shell_Command_List *g_shell_config = NULL; +Fd_Shell_Command_List *g_shell_config = nullptr; diff --git a/fluid/app/shell_command.h b/fluid/app/shell_command.h index 3f5508493..bc7a18c3e 100644 --- a/fluid/app/shell_command.h +++ b/fluid/app/shell_command.h @@ -1,7 +1,7 @@ // -// FLUID main entry for the Fast Light Tool Kit (FLTK). +// Shell Command database header for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -17,7 +17,7 @@ #ifndef _FLUID_SHELL_COMMAND_H #define _FLUID_SHELL_COMMAND_H -#include "app/fluid.h" +#include "Fluid.h" #include @@ -48,13 +48,11 @@ struct Fl_Menu_Item; class Fl_Widget; class Fl_Preferences; -char preferences_get(Fl_Preferences &prefs, const char *key, std::string &value, const std::string &defaultValue); -char preferences_set(Fl_Preferences &prefs, const char *key, const std::string &value); - void show_terminal_window(); void run_shell_command(const std::string &cmd, int flags); bool shell_command_running(void); + class Fl_Process { public: Fl_Process(); @@ -83,9 +81,10 @@ private: #endif protected: - FILE * _fpt; + FILE * _fpt = nullptr; }; + class Fd_Shell_Command { public: enum { ALWAYS, NEVER, MAC_ONLY, UX_ONLY, WIN_ONLY, MAC_AND_UX_ONLY, USER_ONLY, HOST_ONLY, ENV_ONLY }; // conditions @@ -97,19 +96,19 @@ public: Fd_Shell_Command(const std::string &in_name, const std::string &in_label, Fl_Shortcut in_shortcut, - Fd_Tool_Store in_storage, + fld::Tool_Store in_storage, int in_condition, const std::string &in_condition_data, const std::string &in_command, int in_flags); - std::string name; - std::string label; - Fl_Shortcut shortcut; - Fd_Tool_Store storage; - int condition; // always, hide, windows only, linux only, mac only, user, machine - std::string condition_data; // user name, machine name - std::string command; - int flags; // save_project, save_code, save_string, ... + std::string name { }; + std::string label { }; + Fl_Shortcut shortcut = 0; + fld::Tool_Store storage = fld::Tool_Store::USER; + int condition = ALWAYS; // always, hide, windows only, linux only, mac only, user, machine + std::string condition_data { }; // user name, machine name + std::string command { }; + int flags = 0; // save_project, save_code, save_string, ... Fl_Menu_Item *shell_menu_item_; void run(); void read(Fl_Preferences &prefs); @@ -120,12 +119,13 @@ public: bool is_active(); }; + class Fd_Shell_Command_List { public: - Fd_Shell_Command **list; - int list_size; - int list_capacity; - Fl_Menu_Item *shell_menu_; + Fd_Shell_Command **list = nullptr; + int list_size = 0; + int list_capacity = 0; + Fl_Menu_Item *shell_menu_ = nullptr; public: Fd_Shell_Command_List(); ~Fd_Shell_Command_List(); @@ -134,13 +134,13 @@ public: void insert(int index, Fd_Shell_Command *cmd); void remove(int index); void clear(); - void clear(Fd_Tool_Store store); + void clear(fld::Tool_Store store); // void move_up(); // void move_down(); // int load(const std::string &filename); // int save(const std::string &filename); - void read(Fl_Preferences &prefs, Fd_Tool_Store storage); - void write(Fl_Preferences &prefs, Fd_Tool_Store storage); + void read(Fl_Preferences &prefs, fld::Tool_Store storage); + void write(Fl_Preferences &prefs, fld::Tool_Store storage); void read(class fld::io::Project_Reader*); void write(class fld::io::Project_Writer*); void rebuild_shell_menu(); diff --git a/fluid/app/templates.cxx b/fluid/app/templates.cxx new file mode 100644 index 000000000..802357ed2 --- /dev/null +++ b/fluid/app/templates.cxx @@ -0,0 +1,143 @@ +// +// Fluid Project Templates code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "app/templates.h" + +#include "Fluid.h" +#include "io/Project_Writer.h" +#include "nodes/factory.h" +#include "nodes/Tree.h" +#include "nodes/Window_Node.h" +#include "panels/template_panel.h" + +#include +#include +#include +#include "../src/flstring.h" + +using namespace fld; +using namespace fld::app; + +/** + Save a design template. + \todo We should document the concept of templates. + */ +void fld::app::save_template() { + // Setup the template panel... + if (!template_panel) make_template_panel(); + + template_clear(); + template_browser->add("New Template"); + template_load(); + + template_name->show(); + template_name->value(""); + + template_instance->hide(); + + template_delete->show(); + template_delete->deactivate(); + + template_submit->label("Save"); + template_submit->deactivate(); + + template_panel->label("Save Template"); + + // Show the panel and wait for the user to do something... + template_panel->show(); + while (template_panel->shown()) Fl::wait(); + + // Get the template name, return if it is empty... + const char *c = template_name->value(); + if (!c || !*c) return; + + // Convert template name to filename_with_underscores + char savename[FL_PATH_MAX], *saveptr; + strlcpy(savename, c, sizeof(savename)); + for (saveptr = savename; *saveptr; saveptr ++) { + if (isspace(*saveptr)) *saveptr = '_'; + } + + // Find the templates directory... + char filename[FL_PATH_MAX]; + Fluid.preferences.getUserdataPath(filename, sizeof(filename)); + + strlcat(filename, "templates", sizeof(filename)); + if (fl_access(filename, 0)) fl_make_path(filename); + + strlcat(filename, "/", sizeof(filename)); + strlcat(filename, savename, sizeof(filename)); + + char *ext = filename + strlen(filename); + if (ext >= (filename + sizeof(filename) - 5)) { + fl_alert("The template name \"%s\" is too long!", c); + return; + } + + // Save the .fl file... + strcpy(ext, ".fl"); + + if (!fl_access(filename, 0)) { + if (fl_choice("The template \"%s\" already exists.\n" + "Do you want to replace it?", "Cancel", + "Replace", nullptr, c) == 0) return; + } + + if (!fld::io::write_file(Fluid.proj, filename)) { + fl_alert("Error writing %s: %s", filename, strerror(errno)); + return; + } + +#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ) + // Get the screenshot, if any... + Node *t; + + for (t = Fluid.proj.tree.first; t; t = t->next) { + // Find the first window... + if (t->is_a(Type::Window)) break; + } + + if (!t) return; + + // Grab a screenshot... + Window_Node *wt = (Window_Node *)t; + uchar *pixels; + int w, h; + + if ((pixels = wt->read_image(w, h)) == nullptr) return; + + // Save to a PNG file... + strcpy(ext, ".png"); + + errno = 0; + if (fl_write_png(filename, pixels, w, h, 3) != 0) { + delete[] pixels; + fl_alert("Error writing %s: %s", filename, strerror(errno)); + return; + } + +# if 0 // The original PPM output code... + strcpy(ext, ".ppm"); + fp = fl_fopen(filename, "wb"); + fprintf(fp, "P6\n%d %d 255\n", w, h); + fwrite(pixels, w * h, 3, fp); + fclose(fp); +# endif // 0 + + delete[] pixels; +#endif // HAVE_LIBPNG && HAVE_LIBZ +} + diff --git a/fluid/app/templates.h b/fluid/app/templates.h new file mode 100644 index 000000000..cedec9f76 --- /dev/null +++ b/fluid/app/templates.h @@ -0,0 +1,29 @@ +// +// Fluid Project Templates header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_APP_TEMPLATES_H +#define FLUID_APP_TEMPLATES_H + +namespace fld { +namespace app { + +void save_template(); + +} // namespace app +} // namespace fld + +#endif // FLUID_APP_TEMPLATES_H + diff --git a/fluid/app/undo.h b/fluid/app/undo.h deleted file mode 100644 index e8ffab891..000000000 --- a/fluid/app/undo.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// FLUID undo definitions for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 undo_h -#define undo_h - -class Fl_Widget; - -#define kUndoWindowResize 1 - -extern int undo_current; // Current undo level in buffer -extern int undo_last; // Last undo level in buffer -extern int undo_save; // Last undo level that was saved -extern int undo_once_type; // Suspend further undos of the same type - -void redo_cb(Fl_Widget *, void *); // Redo menu callback -void undo_cb(Fl_Widget *, void *); // Undo menu callback -void undo_checkpoint(); // Save current file to undo buffer -int undo_checkpoint_once(int type); // Save undo buffer once until a different checkpoint type is called -void undo_clear(); // Clear undo buffer -void undo_resume(); // Resume undo checkpoints -void undo_suspend(); // Suspend undo checkpoints - -#endif // !undo_h diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx index c88ebc147..c9e638c93 100644 --- a/fluid/io/Code_Writer.cxx +++ b/fluid/io/Code_Writer.cxx @@ -1,5 +1,5 @@ // -// Code output routines for the Fast Light Tool Kit (FLTK). +// Fluid C++ Code Writer code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -16,18 +16,16 @@ #include "io/Code_Writer.h" -#include "app/project.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/Fl_Function_Type.h" +#include "Fluid.h" +#include "Project.h" +#include "nodes/Window_Node.h" +#include "nodes/Function_Node.h" #include #include "../src/flstring.h" #include -/// \defgroup cfile C Code File Operations -/// \{ - using namespace fld; using namespace fld::io; @@ -41,146 +39,6 @@ int is_id(char c) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; } -/** - Write a string to a file, replacing all non-ASCII characters with octal codes. - \param[in] out output file - \param[in] text write this NUL terminated utf-8 string - \return EOF if any of the file access calls failed, 0 if OK - */ -int write_escaped_strings(FILE *out, const char *text) { - int ret = 0; - const unsigned char *utf8_text = (const unsigned char *)text; - for (const unsigned char *s = utf8_text; *s; ++s) { - unsigned char c = *s; - // escape control characters, delete, all utf-8, and the double quotes - // note: we should have an option in the project settings to allow utf-8 - // characters in the output text and not escape them - if (c < 32 || c > 126 || c == '\"') { - if (c == '\r') { - ret = fputs("\\r", out); - } else if (c == '\n') { - ret = fputs("\\n", out); - } else { - ret = fprintf(out, "\\%03o", c); - } - } else { - ret = putc((int)c, out); - } - } - return ret; -} - -/** - Write a file that contains all label and tooltip strings for internationalization. - The user is responsible to set the right file name extension. The file format - is determined by `g_project.i18n_type`. - \param[in] filename file path and name to a file that will hold the strings - \return 1 if the file could not be opened for writing, or the result of `fclose`. - */ -int write_strings(const std::string &filename) { - Fl_Type *p; - Fl_Widget_Type *w; - int i; - - FILE *fp = fl_fopen(filename.c_str(), "wb"); - if (!fp) return 1; - - switch (g_project.i18n_type) { - case FD_I18N_NONE : /* None, just put static text out */ - fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", - FL_VERSION); - for (p = Fl_Type::first; p; p = p->next) { - if (p->is_widget()) { - w = (Fl_Widget_Type *)p; - - if (w->label()) { - write_escaped_strings(fp, w->label()); - putc('\n', fp); - } - - if (w->tooltip()) { - write_escaped_strings(fp, w->tooltip()); - putc('\n', fp); - } - } - } - break; - case FD_I18N_GNU : /* GNU gettext, put a .po file out */ - fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", - FL_VERSION); - for (p = Fl_Type::first; p; p = p->next) { - if (p->is_widget()) { - w = (Fl_Widget_Type *)p; - - if (w->label()) { - fputs("msgid \"", fp); - write_escaped_strings(fp, w->label()); - fputs("\"\n", fp); - - fputs("msgstr \"", fp); - write_escaped_strings(fp, w->label()); - fputs("\"\n", fp); - } - - if (w->tooltip()) { - fputs("msgid \"", fp); - write_escaped_strings(fp, w->tooltip()); - fputs("\"\n", fp); - - fputs("msgstr \"", fp); - write_escaped_strings(fp, w->tooltip()); - fputs("\"\n", fp); - } - } - } - break; - case FD_I18N_POSIX : /* POSIX catgets, put a .msg file out */ - fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", - FL_VERSION); - fprintf(fp, "$set %s\n", g_project.i18n_pos_set.c_str()); - fputs("$quote \"\n", fp); - - for (i = 1, p = Fl_Type::first; p; p = p->next) { - if (p->is_widget()) { - w = (Fl_Widget_Type *)p; - - if (w->label()) { - fprintf(fp, "%d \"", i ++); - write_escaped_strings(fp, w->label()); - fputs("\"\n", fp); - } - - if (w->tooltip()) { - fprintf(fp, "%d \"", i ++); - write_escaped_strings(fp, w->tooltip()); - fputs("\"\n", fp); - } - } - } - break; - } - - return fclose(fp); -} - -//////////////////////////////////////////////////////////////// -// Generate unique but human-readable identifiers: - -/** A binary searchable tree storing identifiers for quick retrieval. */ -struct Fd_Identifier_Tree { - char* text; - void* object; - Fd_Identifier_Tree *left, *right; - Fd_Identifier_Tree (const char* t, void* o) : text(fl_strdup(t)), object(o) {left = right = 0;} - ~Fd_Identifier_Tree(); -}; - -Fd_Identifier_Tree::~Fd_Identifier_Tree() { - delete left; - free((void *)text); - delete right; -} - /** \brief Return a unique name for the given object. This function combines the name and label into an identifier. It then checks @@ -209,22 +67,21 @@ const char* Code_Writer::unique_id(void* o, const char* type, const char* name, } *q = 0; // okay, search the tree and see if the name was already used: - Fd_Identifier_Tree** p = &id_root; int which = 0; - while (*p) { - int i = strcmp(buffer, (*p)->text); - if (!i) { - if ((*p)->object == o) return (*p)->text; - // already used, we need to pick a new name: - sprintf(q,"%x",++which); - p = &id_root; - continue; + for (;;) { + auto it = unique_id_list.find(buffer); + // If the id does not exist, add it to the map + if (it == unique_id_list.end()) { + it = unique_id_list.insert(std::make_pair(buffer, o)).first; + return it->first.c_str(); } - else if (i < 0) p = &((*p)->left); - else p = &((*p)->right); + // If it does exist, and the pointers are the same, just return it. + if (it->second == o) { + return it->first.c_str(); + } + // Else repeat until we have a new id, + sprintf(q,"%x",++which); } - *p = new Fd_Identifier_Tree(buffer, o); - return (*p)->text; } //////////////////////////////////////////////////////////////// @@ -272,45 +129,6 @@ const char *Code_Writer::indent_plus(int offset) { } -//////////////////////////////////////////////////////////////// -// declarations/include files: -// Each string generated by write_h_once is written only once to -// the header file. This is done by keeping a binary tree of all -// the calls so far and not printing it if it is in the tree. - -/** A binary searchable tree storing text for quick retrieval. */ -struct Fd_Text_Tree { - char *text; - Fd_Text_Tree *left, *right; - Fd_Text_Tree(const char *t) { - text = fl_strdup(t); - left = right = 0; - } - ~Fd_Text_Tree(); -}; - -Fd_Text_Tree::~Fd_Text_Tree() { - delete left; - free((void *)text); - delete right; -} - -/** A binary searchable tree storing pointers for quick retrieval. */ -struct Fd_Pointer_Tree { - void *ptr; - Fd_Pointer_Tree *left, *right; - Fd_Pointer_Tree(void *p) { - ptr = p; - left = right = 0; - } - ~Fd_Pointer_Tree(); -}; - -Fd_Pointer_Tree::~Fd_Pointer_Tree() { - delete left; - delete right; -} - /** Print a formatted line to the header file, unless the same line was produced before in this header file. \note Resulting line is cropped at 1023 bytes. @@ -323,15 +141,11 @@ int Code_Writer::write_h_once(const char *format, ...) { va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); - Fd_Text_Tree **p = &text_in_header; - while (*p) { - int i = strcmp(buf,(*p)->text); - if (!i) return 0; - else if (i < 0) p = &((*p)->left); - else p = &((*p)->right); + if (text_in_header.find(buf) != text_in_header.end()) { + return 0; } - fprintf(header_file,"%s\n",buf); - *p = new Fd_Text_Tree(buf); + fprintf(header_file, "%s\n", buf); + text_in_header.insert(buf); return 1; } @@ -347,22 +161,16 @@ int Code_Writer::write_c_once(const char *format, ...) { va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); - Fd_Text_Tree **p = &text_in_header; - while (*p) { - int i = strcmp(buf,(*p)->text); - if (!i) return 0; - else if (i < 0) p = &((*p)->left); - else p = &((*p)->right); + // Return if the text was already printed to the header file. + if (text_in_header.find(buf) != text_in_header.end()) { + return 0; } - p = &text_in_code; - while (*p) { - int i = strcmp(buf,(*p)->text); - if (!i) return 0; - else if (i < 0) p = &((*p)->left); - else p = &((*p)->right); + // Return if the text was already printed to the source file. + if (text_in_code.find(buf) != text_in_code.end()) { + return 0; } crc_printf("%s\n", buf); - *p = new Fd_Text_Tree(buf); + text_in_code.insert(buf); return 1; } @@ -373,13 +181,10 @@ int Code_Writer::write_c_once(const char *format, ...) { \return true if found in the tree, false if added to the tree */ bool Code_Writer::c_contains(void *pp) { - Fd_Pointer_Tree **p = &ptr_in_code; - while (*p) { - if ((*p)->ptr == pp) return true; - else if ((*p)->ptr < pp) p = &((*p)->left); - else p = &((*p)->right); + if (ptr_in_code.find(pp) != ptr_in_code.end()) { + return true; } - *p = new Fd_Pointer_Tree(pp); + ptr_in_code.insert(pp); return false; } @@ -408,14 +213,14 @@ void Code_Writer::write_cstring(const char *s, int length) { } // if we are rendering to the source code preview window, and the text is // longer than four lines, we only render a placeholder. - if (write_codeview && ((s==NULL) || (length>300))) { + if (write_codeview && ((s==nullptr) || (length>300))) { if (length>=0) crc_printf("\" ... %d bytes of text... \"", length); else crc_puts("\" ... text... \""); return; } - if (length==-1 || s==0L) { + if (length==-1 || s==nullptr) { crc_puts("\n#error string not found\n"); crc_puts("\" ... undefined size text... \""); return; @@ -454,7 +259,7 @@ void Code_Writer::write_cstring(const char *s, int length) { break; } // if the UTF-8 option is checked, write unicode characters verbatim - if (g_project.utf8_in_src && (c&0x80)) { + if (proj_.utf8_in_src && (c&0x80)) { if ((c&0x40)) { // This is the first character in a utf-8 sequence (0b11......). // A line break would be ok here. Do not put linebreak in front of @@ -644,13 +449,13 @@ void Code_Writer::write_c_indented(const char *textlines, int inIndent, char inT constructor whereas functions, declarations, and inline data are seen as members of the class itself. */ -bool is_class_member(Fl_Type *t) { - return t->is_a(ID_Function) - || t->is_a(ID_Decl) - || t->is_a(ID_Data); -// || t->is_a(ID_Class) // FLUID can't handle a class inside a class -// || t->is_a(ID_Widget_Class) -// || t->is_a(ID_DeclBlock) // Declaration blocks are generally not handled well +bool is_class_member(Node *t) { + return t->is_a(Type::Function) + || t->is_a(Type::Decl) + || t->is_a(Type::Data); +// || t->is_a(Type::Class) // FLUID can't handle a class inside a class +// || t->is_a(Type::Widget_Class) +// || t->is_a(Type::DeclBlock) // Declaration blocks are generally not handled well } /** @@ -661,11 +466,11 @@ bool is_class_member(Fl_Type *t) { \param[in] q should be a comment type \return true if this comment is followed by a class member \return false if it is followed by a widget or code - \see is_class_member(Fl_Type *t) + \see is_class_member(Node *t) */ -bool is_comment_before_class_member(Fl_Type *q) { - if (q->is_a(ID_Comment) && q->next && q->next->level==q->level) { - if (q->next->is_a(ID_Comment)) +bool is_comment_before_class_member(Node *q) { + if (q->is_a(Type::Comment) && q->next && q->next->level==q->level) { + if (q->next->is_a(Type::Comment)) return is_comment_before_class_member(q->next); if (is_class_member(q->next)) return true; @@ -678,14 +483,14 @@ bool is_comment_before_class_member(Fl_Type *q) { \param[in] p write this type and all its children \return pointer to the next sibling */ -Fl_Type* Code_Writer::write_static(Fl_Type* p) { +Node* Code_Writer::write_static(Node* p) { if (write_codeview) p->header_static_start = (int)ftell(header_file); if (write_codeview) p->code_static_start = (int)ftell(code_file); p->write_static(*this); if (write_codeview) p->code_static_end = (int)ftell(code_file); if (write_codeview) p->header_static_end = (int)ftell(header_file); - Fl_Type* q; + Node* q; for (q = p->next; q && q->level > p->level;) { q = write_static(q); } @@ -697,13 +502,13 @@ Fl_Type* Code_Writer::write_static(Fl_Type* p) { /** Recursively write code, putting children between the two parts of the parent code. - \param[in] p write this type and all its children + \param[in] p write this node and all its children \return pointer to the next sibling */ -Fl_Type* Code_Writer::write_code(Fl_Type* p) { +Node* Code_Writer::write_code(Node* p) { // write all code that comes before the children code // (but don't write the last comment until the very end) - if (!(p==Fl_Type::last && p->is_a(ID_Comment))) { + if (!(p==Fluid.proj.tree.last && p->is_a(Type::Comment))) { if (write_codeview) p->code1_start = (int)ftell(code_file); if (write_codeview) p->header1_start = (int)ftell(header_file); p->write_code1(*this); @@ -711,7 +516,7 @@ Fl_Type* Code_Writer::write_code(Fl_Type* p) { if (write_codeview) p->header1_end = (int)ftell(header_file); } // recursively write the code of all children - Fl_Type* q; + Node* q; if (p->is_widget() && p->is_class()) { // Handle widget classes specially for (q = p->next; q && q->level > p->level;) { @@ -745,7 +550,7 @@ Fl_Type* Code_Writer::write_code(Fl_Type* p) { } write_h("};\n"); - current_widget_class = 0L; + current_widget_class = nullptr; } else { for (q = p->next; q && q->level > p->level;) q = write_code(q); // write all code that come after the children @@ -771,10 +576,10 @@ Fl_Type* Code_Writer::write_code(Fl_Type* p) { */ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { write_codeview = to_codeview; - delete id_root; id_root = 0; + unique_id_list.clear(); indentation = 0; - current_class = 0L; - current_widget_class = 0L; + current_class = nullptr; + current_widget_class = nullptr; if (!s) code_file = stdout; else { FILE *f = fl_fopen(s, "wb"); @@ -788,29 +593,29 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { header_file = f; } // Remember the last code file location for MergeBack - if (s && g_project.write_mergeback_data && !to_codeview) { - std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); - int i, n = (int)proj_filename.size(); - for (i=0; iis_a(ID_Comment)) { + Node* first_node = Fluid.proj.tree.first; + if (first_node && first_node->is_a(Type::Comment)) { if (write_codeview) { - first_type->code1_start = first_type->code2_start = (int)ftell(code_file); - first_type->header1_start = first_type->header2_start = (int)ftell(header_file); + first_node->code1_start = first_node->code2_start = (int)ftell(code_file); + first_node->header1_start = first_node->header2_start = (int)ftell(header_file); } // it is ok to write non-recursive code here, because comments have no children or code2 blocks - first_type->write_code1(*this); + first_node->write_code1(*this); if (write_codeview) { - first_type->code1_end = first_type->code2_end = (int)ftell(code_file); - first_type->header1_end = first_type->header2_end = (int)ftell(header_file); + first_node->code1_end = first_node->code2_end = (int)ftell(code_file); + first_node->header1_end = first_node->header2_end = (int)ftell(header_file); } - first_type = first_type->next; + first_node = first_node->next; } const char *hdr = "\ @@ -828,27 +633,27 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { fprintf(header_file, "#define %s\n", define_name); } - if (g_project.avoid_early_includes==0) { + if (proj_.avoid_early_includes==0) { write_h_once("#include "); } - if (t && g_project.include_H_from_C) { + if (t && proj_.include_H_from_C) { if (to_codeview) { write_c("#include \"CodeView.h\"\n"); - } else if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name.c_str(), '/') == NULL) { + } else if (proj_.header_file_name[0] == '.' && strchr(proj_.header_file_name.c_str(), '/') == nullptr) { write_c("#include \"%s\"\n", fl_filename_name(t)); } else { - write_c("#include \"%s\"\n", g_project.header_file_name.c_str()); + write_c("#include \"%s\"\n", proj_.header_file_name.c_str()); } } std::string loc_include, loc_conditional; - if (g_project.i18n_type==FD_I18N_GNU) { - loc_include = g_project.i18n_gnu_include; - loc_conditional = g_project.i18n_gnu_conditional; + if (proj_.i18n_type==fld::I18n_Type::GNU) { + loc_include = proj_.i18n_gnu_include; + loc_conditional = proj_.i18n_gnu_conditional; } else { - loc_include = g_project.i18n_pos_include; - loc_conditional = g_project.i18n_pos_conditional; + loc_include = proj_.i18n_pos_include; + loc_conditional = proj_.i18n_pos_conditional; } - if (g_project.i18n_type && !loc_include.empty()) { + if ((proj_.i18n_type != fld::I18n_Type::NONE) && !loc_include.empty()) { int conditional = !loc_conditional.empty(); if (conditional) { write_c("#ifdef %s\n", loc_conditional.c_str()); @@ -858,26 +663,26 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { write_c("#%sinclude \"%s\"\n", indent(), loc_include.c_str()); else write_c("#%sinclude %s\n", indent(), loc_include.c_str()); - if (g_project.i18n_type == FD_I18N_POSIX) { - if (!g_project.i18n_pos_file.empty()) { - write_c("extern nl_catd %s;\n", g_project.i18n_pos_file.c_str()); + if (proj_.i18n_type == fld::I18n_Type::POSIX) { + if (!proj_.i18n_pos_file.empty()) { + write_c("extern nl_catd %s;\n", proj_.i18n_pos_file.c_str()); } else { write_c("// Initialize I18N stuff now for menus...\n"); write_c("#%sinclude \n", indent()); write_c("static char *_locale = setlocale(LC_MESSAGES, \"\");\n"); - write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", g_project.basename().c_str()); + write_c("static nl_catd _catalog = catopen(\"%s\", 0);\n", proj_.basename().c_str()); } } if (conditional) { write_c("#else\n"); - if (g_project.i18n_type == FD_I18N_GNU) { - if (!g_project.i18n_gnu_function.empty()) { - write_c("#%sifndef %s\n", indent(), g_project.i18n_gnu_function.c_str()); - write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_function.c_str()); + if (proj_.i18n_type == fld::I18n_Type::GNU) { + if (!proj_.i18n_gnu_function.empty()) { + write_c("#%sifndef %s\n", indent(), proj_.i18n_gnu_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n_gnu_function.c_str()); write_c("#%sendif\n", indent()); } } - if (g_project.i18n_type == FD_I18N_POSIX) { + if (proj_.i18n_type == fld::I18n_Type::POSIX) { write_c("#%sifndef catgets\n", indent()); write_c("#%sdefine catgets(catalog, set, msgid, text) text\n", indent_plus(1)); write_c("#%sendif\n", indent()); @@ -885,13 +690,13 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { indentation--; write_c("#endif\n"); } - if (g_project.i18n_type == FD_I18N_GNU && g_project.i18n_gnu_static_function[0]) { - write_c("#ifndef %s\n", g_project.i18n_gnu_static_function.c_str()); - write_c("#%sdefine %s(text) text\n", indent_plus(1), g_project.i18n_gnu_static_function.c_str()); + if (proj_.i18n_type == fld::I18n_Type::GNU && proj_.i18n_gnu_static_function[0]) { + write_c("#ifndef %s\n", proj_.i18n_gnu_static_function.c_str()); + write_c("#%sdefine %s(text) text\n", indent_plus(1), proj_.i18n_gnu_static_function.c_str()); write_c("#endif\n"); } } - for (Fl_Type* p = first_type; p;) { + for (Node* p = first_node; p;) { // write all static data for this & all children first write_static(p); // then write the nested code: @@ -902,26 +707,26 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { fprintf(header_file, "#endif\n"); - Fl_Type* last_type = Fl_Type::last; - if (last_type && (last_type != Fl_Type::first) && last_type->is_a(ID_Comment)) { + Node* last_node = Fluid.proj.tree.last; + if (last_node && (last_node != Fluid.proj.tree.first) && last_node->is_a(Type::Comment)) { if (write_codeview) { - last_type->code1_start = last_type->code2_start = (int)ftell(code_file); - last_type->header1_start = last_type->header2_start = (int)ftell(header_file); + last_node->code1_start = last_node->code2_start = (int)ftell(code_file); + last_node->header1_start = last_node->header2_start = (int)ftell(header_file); } - last_type->write_code1(*this); + last_node->write_code1(*this); if (write_codeview) { - last_type->code1_end = last_type->code2_end = (int)ftell(code_file); - last_type->header1_end = last_type->header2_end = (int)ftell(header_file); + last_node->code1_end = last_node->code2_end = (int)ftell(code_file); + last_node->header1_end = last_node->header2_end = (int)ftell(header_file); } } int x = 0, y = 0; if (code_file != stdout) x = fclose(code_file); - code_file = 0; + code_file = nullptr; if (header_file != stdout) y = fclose(header_file); - header_file = 0; + header_file = nullptr; return x >= 0 && y >= 0; } @@ -947,23 +752,10 @@ void Code_Writer::write_public(int state) { /** Create and initialize a new C++ source code writer. */ -Code_Writer::Code_Writer() -: code_file(NULL), - header_file(NULL), - id_root(NULL), - text_in_header(NULL), - text_in_code(NULL), - ptr_in_code(NULL), - block_crc_(0), - block_line_start_(true), - block_buffer_(NULL), - block_buffer_size_(0), - indentation(0), - write_codeview(false), - varused_test(0), - varused(0) +Code_Writer::Code_Writer(Project &proj) +: proj_ { proj } { - block_crc_ = crc32(0, NULL, 0); + block_crc_ = crc32(0, nullptr, 0); } /** @@ -971,10 +763,6 @@ Code_Writer::Code_Writer() */ Code_Writer::~Code_Writer() { - delete id_root; - delete ptr_in_code; - delete text_in_code; - delete text_in_header; if (block_buffer_) ::free(block_buffer_); } @@ -987,9 +775,9 @@ Code_Writer::~Code_Writer() \param[in] uid the unique id of the current type */ void Code_Writer::tag(int type, unsigned short uid) { - if (g_project.write_mergeback_data) + if (proj_.write_mergeback_data) fprintf(code_file, "//~fl~%d~%04x~%08x~~\n", type, (int)uid, (unsigned int)block_crc_); - block_crc_ = crc32(0, NULL, 0); + block_crc_ = crc32(0, nullptr, 0); } /** @@ -1054,7 +842,7 @@ int Code_Writer::crc_printf(const char *format, ...) { \return see fprintf(FILE *, *const char*, ...) */ int Code_Writer::crc_vprintf(const char *format, va_list args) { - if (g_project.write_mergeback_data) { + if (proj_.write_mergeback_data) { int n = vsnprintf(block_buffer_, block_buffer_size_, format, args); if (n > block_buffer_size_) { block_buffer_size_ = n + 128; @@ -1075,7 +863,7 @@ int Code_Writer::crc_vprintf(const char *format, va_list args) { \return see fputs(const char*, FILE*) */ int Code_Writer::crc_puts(const char *text) { - if (g_project.write_mergeback_data) { + if (proj_.write_mergeback_data) { crc_add(text); } return fputs(text, code_file); @@ -1088,12 +876,10 @@ int Code_Writer::crc_puts(const char *text) { \return see fputc(int, FILE*) */ int Code_Writer::crc_putc(int c) { - if (g_project.write_mergeback_data) { + if (proj_.write_mergeback_data) { uchar uc = (uchar)c; crc_add(&uc, 1); } return fputc(c, code_file); } -/// \} - diff --git a/fluid/io/Code_Writer.h b/fluid/io/Code_Writer.h index b4a6518b4..ca23ca0a2 100644 --- a/fluid/io/Code_Writer.h +++ b/fluid/io/Code_Writer.h @@ -1,7 +1,7 @@ // -// Code output routines for the Fast Light Tool Kit (FLTK). +// Fluid C++ Code Writer header for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2021 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -22,43 +22,50 @@ #include #include #include +#include +#include -class Fl_Type; +class Node; struct Fd_Identifier_Tree; struct Fd_Text_Tree; struct Fd_Pointer_Tree; int is_id(char c); -int write_strings(const std::string &filename); namespace fld { + +class Project; + namespace io { class Code_Writer { -protected: +private: + /// Link Code_Writer class to the project. + Project &proj_; + /// file pointer for the C++ code file - FILE *code_file; + FILE *code_file = nullptr; /// file pointer for the C++ header file - FILE *header_file; + FILE *header_file = nullptr; /// tree of unique but human-readable identifiers - Fd_Identifier_Tree* id_root; + std::map unique_id_list { }; /// searchable text tree for text that is only written once to the header file - Fd_Text_Tree *text_in_header; + std::set text_in_header { }; /// searchable text tree for text that is only written once to the code file - Fd_Text_Tree *text_in_code; + std::set text_in_code { }; /// searchable tree for pointers that are only written once to the code file - Fd_Pointer_Tree *ptr_in_code; + std::set ptr_in_code { }; /// crc32 for blocks of text written to the code file - unsigned long block_crc_; + unsigned long block_crc_ = 0; /// if set, we are at the start of a line and can ignore leading spaces in crc - bool block_line_start_; + bool block_line_start_ = true; /// expanding buffer for vsnprintf - char *block_buffer_; + char *block_buffer_ = nullptr; /// size of expanding buffer for vsnprintf - int block_buffer_size_; + int block_buffer_size_ = 0; void crc_add(const void *data, int n=-1); int crc_printf(const char *format, ...); @@ -68,19 +75,19 @@ protected: public: /// current level of source code indentation - int indentation; + int indentation = 0; /// set if we write abbreviated file for the source code previewer /// (disables binary data blocks, for example) - bool write_codeview; + bool write_codeview = false; /// silly thing to prevent declaring unused variables: /// When this symbol is on, all attempts to write code don't write /// anything, but set a variable if it looks like the variable "o" is used: - int varused_test; + int varused_test = 0; /// set to 1 if varused_test found that a variable is actually used - int varused; + int varused = 0; public: - Code_Writer(); + Code_Writer(Project &proj); ~Code_Writer(); const char* unique_id(void* o, const char*, const char*, const char*); /// Increment source code indentation level. @@ -102,14 +109,14 @@ public: void write_h(const char*, ...) __fl_attr((__format__ (__printf__, 2, 3))); void write_hc(const char *, int, const char*, const char*); void write_c_indented(const char *textlines, int inIndent, char inTrailwWith); - Fl_Type* write_static(Fl_Type* p); - Fl_Type* write_code(Fl_Type* p); + Node* write_static(Node* p); + Node* write_code(Node* p); int write_code(const char *cfile, const char *hfile, bool to_codeview=false); void write_public(int state); // writes pubic:/private: as needed void tag(int type, unsigned short uid); - static unsigned long block_crc(const void *data, int n=-1, unsigned long in_crc=0, bool *inout_line_start=NULL); + static unsigned long block_crc(const void *data, int n=-1, unsigned long in_crc=0, bool *inout_line_start=nullptr); }; } // namespace io diff --git a/fluid/io/Project_Reader.cxx b/fluid/io/Project_Reader.cxx index ff88238ba..4ef0c6523 100644 --- a/fluid/io/Project_Reader.cxx +++ b/fluid/io/Project_Reader.cxx @@ -1,12 +1,7 @@ // -// Fluid file routines for the Fast Light Tool Kit (FLTK). +// Fluid Project File Reader code for the Fast Light Tool Kit (FLTK). // -// You may find the basic read_* and write_* routines to -// be useful for other programs. I have used them many times. -// They are somewhat similar to tcl, using matching { and } -// to quote strings. -// -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -19,18 +14,23 @@ // https://www.fltk.org/bugs.php // +// You may find the basic read_* and write_* routines to +// be useful for other programs. I have used them many times. +// They are somewhat similar to tcl, using matching { and } +// to quote strings. + #include "io/Project_Reader.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include "app/shell_command.h" -#include "app/undo.h" -#include "app/Fd_Snap_Action.h" +#include "proj/undo.h" +#include "app/Snap_Action.h" #include "nodes/factory.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Widget_Type.h" -#include "nodes/Fl_Grid_Type.h" -#include "nodes/Fl_Window_Type.h" +#include "nodes/Function_Node.h" +#include "nodes/Widget_Node.h" +#include "nodes/Grid_Node.h" +#include "nodes/Window_Node.h" #include "widgets/Node_Browser.h" #include @@ -53,12 +53,12 @@ int fld::io::fdesign_flip = 0; \param[in] filename read this file \param[in] merge if this is set, merge the file into an existing project - at Fl_Type::current + at Fluid.proj.tree.current \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ -int fld::io::read_file(const char *filename, int merge, Strategy strategy) { - Project_Reader f; +int fld::io::read_file(Project &proj, const char *filename, int merge, Strategy strategy) { + Project_Reader f(proj); strategy.source(Strategy::FROM_FILE); return f.read_project(filename, merge, strategy); } @@ -97,13 +97,8 @@ void Project_Reader::expand_buffer(int length) { } /** \brief Construct local project reader. */ -Project_Reader::Project_Reader() -: fin(NULL), - lineno(0), - fname(NULL), - buffer(NULL), - buflen(0), - read_version(0.0) +Project_Reader::Project_Reader(Project &proj) +: proj_(proj) { } @@ -117,7 +112,7 @@ Project_Reader::~Project_Reader() /** Open an .fl file for reading. - \param[in] s filename, if NULL, read from stdin instead + \param[in] s filename, if nullptr, read from stdin instead \return 0 if the operation failed, 1 if it succeeded */ int Project_Reader::open_read(const char *s) { @@ -142,7 +137,7 @@ int Project_Reader::open_read(const char *s) { int Project_Reader::close_read() { if (fin != stdin) { int x = fclose(fin); - fin = 0; + fin = nullptr; return x >= 0; } return 1; @@ -200,17 +195,17 @@ int Project_Reader::read_quoted() { // read whatever character is after a \ If this is the first call, also read the global settings for this design. - \param[in] p parent node or NULL + \param[in] p parent node or nullptr \param[in] merge if set, merge into existing design, else replace design \param[in] strategy add nodes after current or as last child \param[in] skip_options this is set if the options were already found in a previous call, and there is no need to waste time searching for them. - \return the last type that was created + \return the last node that was created */ -Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) { - Fl_Type::current = p; - Fl_Type *last_child_read = NULL; - Fl_Type *t = NULL; +Node *Project_Reader::read_children(Node *p, int merge, Strategy strategy, char skip_options) { + Fluid.proj.tree.current = p; + Node *last_child_read = nullptr; + Node *t = nullptr; for (;;) { const char *c = read_word(); REUSE_C: @@ -230,12 +225,12 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, // this is the first word in a .fd file: if (!strcmp(c,"Magic:")) { read_fdesign(); - return NULL; + return nullptr; } if (!strcmp(c,"version")) { c = read_word(); - read_version = strtod(c,0); + read_version = strtod(c,nullptr); if (read_version<=0 || read_version>double(FL_VERSION+0.00001)) read_error("unknown version '%s'",c); continue; @@ -243,77 +238,77 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, // back compatibility with Vincent Penne's original class code: if (!p && !strcmp(c,"define_in_struct")) { - Fl_Type *t = add_new_widget_from_file("class", Strategy::FROM_FILE_AS_LAST_CHILD); + Node *t = add_new_widget_from_file("class", Strategy::FROM_FILE_AS_LAST_CHILD); t->name(read_word()); - Fl_Type::current = p = t; + Fluid.proj.tree.current = p = t; merge = 1; // stops "missing }" error continue; } if (!strcmp(c,"do_not_include_H_from_C")) { - g_project.include_H_from_C=0; + proj_.include_H_from_C=0; goto CONTINUE; } if (!strcmp(c,"use_FL_COMMAND")) { - g_project.use_FL_COMMAND=1; + proj_.use_FL_COMMAND=1; goto CONTINUE; } if (!strcmp(c,"utf8_in_src")) { - g_project.utf8_in_src=1; + proj_.utf8_in_src=1; goto CONTINUE; } if (!strcmp(c,"avoid_early_includes")) { - g_project.avoid_early_includes=1; + proj_.avoid_early_includes=1; goto CONTINUE; } if (!strcmp(c,"i18n_type")) { - g_project.i18n_type = static_cast(atoi(read_word())); + proj_.i18n_type = static_cast(atoi(read_word())); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_function")) { - g_project.i18n_gnu_function = read_word(); + proj_.i18n_gnu_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_gnu_static_function")) { - g_project.i18n_gnu_static_function = read_word(); + proj_.i18n_gnu_static_function = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_file")) { - g_project.i18n_pos_file = read_word(); + proj_.i18n_pos_file = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_pos_set")) { - g_project.i18n_pos_set = read_word(); + proj_.i18n_pos_set = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_include")) { - if (g_project.i18n_type == FD_I18N_GNU) - g_project.i18n_gnu_include = read_word(); - else if (g_project.i18n_type == FD_I18N_POSIX) - g_project.i18n_pos_include = read_word(); + if (proj_.i18n_type == fld::I18n_Type::GNU) + proj_.i18n_gnu_include = read_word(); + else if (proj_.i18n_type == fld::I18n_Type::POSIX) + proj_.i18n_pos_include = read_word(); goto CONTINUE; } if (!strcmp(c,"i18n_conditional")) { - if (g_project.i18n_type == FD_I18N_GNU) - g_project.i18n_gnu_conditional = read_word(); - else if (g_project.i18n_type == FD_I18N_POSIX) - g_project.i18n_pos_conditional = read_word(); + if (proj_.i18n_type == fld::I18n_Type::GNU) + proj_.i18n_gnu_conditional = read_word(); + else if (proj_.i18n_type == fld::I18n_Type::POSIX) + proj_.i18n_pos_conditional = read_word(); goto CONTINUE; } if (!strcmp(c,"header_name")) { - if (!g_project.header_file_set) g_project.header_file_name = read_word(); + if (!proj_.header_file_set) proj_.header_file_name = read_word(); else read_word(); goto CONTINUE; } if (!strcmp(c,"code_name")) { - if (!g_project.code_file_set) g_project.code_file_name = read_word(); + if (!proj_.code_file_set) proj_.code_file_name = read_word(); else read_word(); goto CONTINUE; } if (!strcmp(c, "snap")) { - g_layout_list.read(this); + Fluid.layout_list.read(this); goto CONTINUE; } @@ -333,7 +328,7 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, } if (!strcmp(c, "mergeback")) { - g_project.write_mergeback_data = read_int(); + proj_.write_mergeback_data = read_int(); goto CONTINUE; } } @@ -350,7 +345,7 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, c = read_word(1); if (strcmp(c,"{") && t->is_class()) { // - ((Fl_Class_Type*)t)->prefix(t->name()); + ((Class_Node*)t)->prefix(t->name()); t->name(c); c = read_word(1); } @@ -378,11 +373,11 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, // FIXME: this has no business in the file reader! // TODO: this is called whenever something is pasted from the top level into a grid // It makes sense to make this more universal for other widget types too. - if (merge && t && t->parent && t->parent->is_a(ID_Grid)) { - if (Fl_Window_Type::popupx != 0x7FFFFFFF) { - ((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); + if (merge && t && t->parent && t->parent->is_a(Type::Grid)) { + if (Window_Node::popupx != 0x7FFFFFFF) { + ((Grid_Node*)t->parent)->insert_child_at(((Widget_Node*)t)->o, Window_Node::popupx, Window_Node::popupy); } else { - ((Fl_Grid_Type*)t->parent)->insert_child_at_next_free_cell(((Fl_Widget_Type*)t)->o); + ((Grid_Node*)t->parent)->insert_child_at_next_free_cell(((Widget_Node*)t)->o); } } @@ -393,9 +388,9 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, strategy.placement(Strategy::AFTER_CURRENT); } if (strategy.placement() == Strategy::AFTER_CURRENT) { - Fl_Type::current = t; + Fluid.proj.tree.current = t; } else { - Fl_Type::current = p; + Fluid.proj.tree.current = p; } CONTINUE:; @@ -410,46 +405,46 @@ Fl_Type *Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, /** \brief Read a .fl project file. \param[in] filename read this file \param[in] merge if this is set, merge the file into an existing project - at Fl_Type::current + at Fluid.proj.tree.current \param[in] strategy add new nodes after current or as last child \return 0 if the operation failed, 1 if it succeeded */ int Project_Reader::read_project(const char *filename, int merge, Strategy strategy) { - Fl_Type *o; - undo_suspend(); + Node *o; + proj_.undo.suspend(); read_version = 0.0; if (!open_read(filename)) { - undo_resume(); + proj_.undo.resume(); return 0; } if (merge) deselect(); else - g_project.reset(); - read_children(Fl_Type::current, merge, strategy); + proj_.reset(); + read_children(Fluid.proj.tree.current, merge, strategy); // clear this - Fl_Type::current = 0; + Fluid.proj.tree.current = nullptr; // Force menu items to be rebuilt... - for (o = Fl_Type::first; o; o = o->next) { - if (o->is_a(ID_Menu_Manager_)) { - o->add_child(0,0); + for (o = Fluid.proj.tree.first; o; o = o->next) { + if (o->is_a(Type::Menu_Manager_)) { + o->add_child(nullptr,nullptr); } } - for (o = Fl_Type::first; o; o = o->next) { + for (o = Fluid.proj.tree.first; o; o = o->next) { if (o->selected) { - Fl_Type::current = o; + Fluid.proj.tree.current = o; break; } } - selection_changed(Fl_Type::current); + selection_changed(Fluid.proj.tree.current); if (g_shell_config) { g_shell_config->rebuild_shell_menu(); g_shell_config->update_settings_dialog(); } - g_layout_list.update_dialogs(); - g_project.update_settings_dialog(); + Fluid.layout_list.update_dialogs(); + proj_.update_settings_dialog(); int ret = close_read(); - undo_resume(); + proj_.undo.resume(); return ret; } @@ -457,8 +452,8 @@ int Project_Reader::read_project(const char *filename, int merge, Strategy strat Display an error while reading the file. If the .fl file isn't opened for reading, pop up an FLTK dialog, otherwise print to stdout. - \note Matt: I am not sure why it is done this way. Shouldn't this depend on \c batch_mode? - \todo Not happy about this function. Output channel should depend on `batch_mode` + \note Matt: I am not sure why it is done this way. Shouldn't this depend on \c Fluid.batch_mode? + \todo Not happy about this function. Output channel should depend on `Fluid.batch_mode` as the note above already states. I want to make all file readers and writers depend on an error handling base class that outputs a useful analysis of file operations. @@ -480,7 +475,7 @@ void Project_Reader::read_error(const char *format, ...) { } /** - Return a word read from the .fl file, or NULL at the EOF. + Return a word read from the .fl file, or nullptr at the EOF. This will skip all comments (# to end of line), and evaluate all \\xxx sequences and use \\ at the end of line to remove the newline. @@ -504,7 +499,7 @@ const char *Project_Reader::read_word(int wantbrace) { for (;;) { x = nextchar(); if (x < 0 && feof(fin)) { // eof - return 0; + return nullptr; } else if (x == '#') { // comment do x = nextchar(); while (x >= 0 && x != '\n'); lineno++; @@ -650,7 +645,7 @@ static const char *class_matcher[] = { "2", "FL_BOX", // was FL_TEXT "62","FL_TIMER", "24","Fl_Value_Slider", - 0}; + nullptr}; /** @@ -712,13 +707,13 @@ static void forms_end(Fl_Group *g, int flip) { void Project_Reader::read_fdesign() { int fdesign_magic = atoi(read_word()); fdesign_flip = (fdesign_magic < 13000); - Fl_Widget_Type *window = 0; - Fl_Widget_Type *group = 0; - Fl_Widget_Type *widget = 0; - if (!Fl_Type::current) { - Fl_Type *t = add_new_widget_from_file("Function", Strategy::FROM_FILE_AS_LAST_CHILD); + Widget_Node *window = nullptr; + Widget_Node *group = nullptr; + Widget_Node *widget = nullptr; + if (!Fluid.proj.tree.current) { + Node *t = add_new_widget_from_file("Function", Strategy::FROM_FILE_AS_LAST_CHILD); t->name("create_the_forms()"); - Fl_Type::current = t; + Fluid.proj.tree.current = t; } for (;;) { const char *name; @@ -727,33 +722,33 @@ void Project_Reader::read_fdesign() { if (!strcmp(name,"Name")) { - window = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Window", Strategy::FROM_FILE_AS_LAST_CHILD); + window = (Widget_Node*)add_new_widget_from_file("Fl_Window", Strategy::FROM_FILE_AS_LAST_CHILD); window->name(value); window->label(value); - Fl_Type::current = widget = window; + Fluid.proj.tree.current = widget = window; } else if (!strcmp(name,"class")) { if (!strcmp(value,"FL_BEGIN_GROUP")) { - group = widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Group", Strategy::FROM_FILE_AS_LAST_CHILD); - Fl_Type::current = group; + group = widget = (Widget_Node*)add_new_widget_from_file("Fl_Group", Strategy::FROM_FILE_AS_LAST_CHILD); + Fluid.proj.tree.current = group; } else if (!strcmp(value,"FL_END_GROUP")) { if (group) { Fl_Group* g = (Fl_Group*)(group->o); g->begin(); forms_end(g, fdesign_flip); - Fl_Group::current(0); + Fl_Group::current(nullptr); } - group = widget = 0; - Fl_Type::current = window; + group = widget = nullptr; + Fluid.proj.tree.current = window; } else { for (int i = 0; class_matcher[i]; i += 2) if (!strcmp(value,class_matcher[i])) { value = class_matcher[i+1]; break;} - widget = (Fl_Widget_Type*)add_new_widget_from_file(value, Strategy::FROM_FILE_AS_LAST_CHILD); + widget = (Widget_Node*)add_new_widget_from_file(value, Strategy::FROM_FILE_AS_LAST_CHILD); if (!widget) { printf("class %s not found, using Fl_Button\n", value); - widget = (Fl_Widget_Type*)add_new_widget_from_file("Fl_Button", Strategy::FROM_FILE_AS_LAST_CHILD); + widget = (Widget_Node*)add_new_widget_from_file("Fl_Button", Strategy::FROM_FILE_AS_LAST_CHILD); } } diff --git a/fluid/io/Project_Reader.h b/fluid/io/Project_Reader.h index 20928d25f..b25b04ead 100644 --- a/fluid/io/Project_Reader.h +++ b/fluid/io/Project_Reader.h @@ -1,7 +1,7 @@ // -// Fluid file routines for the Fast Light Tool Kit (FLTK). +// Fluid Project File Reader header for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -17,35 +17,41 @@ #ifndef FLUID_IO_PROJECT_READER_H #define FLUID_IO_PROJECT_READER_H -#include "nodes/Fl_Type.h" +#include "nodes/Node.h" #include #include -class Fl_Type; +class Node; namespace fld { + +class Project; + namespace io { extern int fdesign_flip; -int read_file(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); +int read_file(Project &proj, const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); class Project_Reader { protected: + /// Link Project_Reader class to the project. + Project &proj_; + /// Project input file - FILE *fin; + FILE *fin = nullptr; /// Number of most recently read line - int lineno; + int lineno = 0; /// Pointer to the file path and name (not copied!) - const char *fname; + const char *fname = nullptr; /// Expanding buffer to store the most recently read word - char *buffer; + char *buffer = nullptr; /// Exact size of the expanding buffer in bytes - int buflen; + int buflen = 0; void expand_buffer(int length); @@ -53,16 +59,16 @@ protected: public: /// Holds the file version number after reading the "version" tag - double read_version; + double read_version = 0.0; public: - Project_Reader(); + Project_Reader(Project &proj); ~Project_Reader(); int open_read(const char *s); int close_read(); const char *filename_name(); int read_quoted(); - Fl_Type *read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options=0); + Node *read_children(Node *p, int merge, Strategy strategy, char skip_options=0); int read_project(const char *, int merge, Strategy strategy=Strategy::FROM_FILE_AS_LAST_CHILD); void read_error(const char *format, ...); const char *read_word(int wantbrace = 0); diff --git a/fluid/io/Project_Writer.cxx b/fluid/io/Project_Writer.cxx index 26af62f37..bfe6e0566 100644 --- a/fluid/io/Project_Writer.cxx +++ b/fluid/io/Project_Writer.cxx @@ -1,12 +1,12 @@ // -// Fluid file routines for the Fast Light Tool Kit (FLTK). +// Fluid Project File Writer code for the Fast Light Tool Kit (FLTK). // // You may find the basic read_* and write_* routines to // be useful for other programs. I have used them many times. // They are somewhat similar to tcl, using matching { and } // to quote strings. // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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,11 +21,11 @@ #include "io/Project_Writer.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include "app/shell_command.h" -#include "app/undo.h" -#include "app/Fd_Snap_Action.h" +#include "proj/undo.h" +#include "app/Snap_Action.h" /// \defgroup flfile .fl Project File Operations /// \{ @@ -42,18 +42,16 @@ using namespace fld::io; is used to implement copy and paste. \return 0 if the operation failed, 1 if it succeeded */ -int fld::io::write_file(const char *filename, int selected_only, bool to_codeview) { - Project_Writer out; +int fld::io::write_file(Project &proj, const char *filename, int selected_only, bool to_codeview) { + Project_Writer out(proj); return out.write_project(filename, selected_only, to_codeview); } // ---- Project_Writer ---------------------------------------------- MARK: - /** \brief Construct local project writer. */ -Project_Writer::Project_Writer() -: fout(NULL), - needspace(0), - write_codeview_(false) +Project_Writer::Project_Writer(Project &proj) +: proj_(proj) { } @@ -64,8 +62,8 @@ Project_Writer::~Project_Writer() /** Open the .fl design file for writing. - If the filename is NULL, associate stdout instead. - \param[in] s the filename or NULL for stdout + If the filename is nullptr, associate stdout instead. + \param[in] s the filename or nullptr for stdout \return 1 if successful. 0 if the operation failed */ int Project_Writer::open_write(const char *s) { @@ -102,55 +100,55 @@ int Project_Writer::close_write() { */ int Project_Writer::write_project(const char *filename, int selected_only, bool sv) { write_codeview_ = sv; - undo_suspend(); + proj_.undo.suspend(); if (!open_write(filename)) { - undo_resume(); + proj_.undo.resume(); return 0; } write_string("# data file for the Fltk User Interface Designer (fluid)\n" "version %.4f",FL_VERSION); - if(!g_project.include_H_from_C) + if(!proj_.include_H_from_C) write_string("\ndo_not_include_H_from_C"); - if(g_project.use_FL_COMMAND) + if(proj_.use_FL_COMMAND) write_string("\nuse_FL_COMMAND"); - if (g_project.utf8_in_src) + if (proj_.utf8_in_src) write_string("\nutf8_in_src"); - if (g_project.avoid_early_includes) + if (proj_.avoid_early_includes) write_string("\navoid_early_includes"); - if (g_project.i18n_type) { - write_string("\ni18n_type %d", g_project.i18n_type); - switch (g_project.i18n_type) { - case FD_I18N_NONE: + if ((proj_.i18n_type != fld::I18n_Type::NONE)) { + write_string("\ni18n_type %d", static_cast(proj_.i18n_type)); + switch (proj_.i18n_type) { + case fld::I18n_Type::NONE: break; - case FD_I18N_GNU : /* GNU gettext */ - write_string("\ni18n_include"); write_word(g_project.i18n_gnu_include.c_str()); - write_string("\ni18n_conditional"); write_word(g_project.i18n_gnu_conditional.c_str()); - write_string("\ni18n_gnu_function"); write_word(g_project.i18n_gnu_function.c_str()); - write_string("\ni18n_gnu_static_function"); write_word(g_project.i18n_gnu_static_function.c_str()); + case fld::I18n_Type::GNU : /* GNU gettext */ + write_string("\ni18n_include"); write_word(proj_.i18n_gnu_include.c_str()); + write_string("\ni18n_conditional"); write_word(proj_.i18n_gnu_conditional.c_str()); + write_string("\ni18n_gnu_function"); write_word(proj_.i18n_gnu_function.c_str()); + write_string("\ni18n_gnu_static_function"); write_word(proj_.i18n_gnu_static_function.c_str()); break; - case FD_I18N_POSIX : /* POSIX catgets */ - write_string("\ni18n_include"); write_word(g_project.i18n_pos_include.c_str()); - write_string("\ni18n_conditional"); write_word(g_project.i18n_pos_conditional.c_str()); - if (!g_project.i18n_pos_file.empty()) { + case fld::I18n_Type::POSIX : /* POSIX catgets */ + write_string("\ni18n_include"); write_word(proj_.i18n_pos_include.c_str()); + write_string("\ni18n_conditional"); write_word(proj_.i18n_pos_conditional.c_str()); + if (!proj_.i18n_pos_file.empty()) { write_string("\ni18n_pos_file"); - write_word(g_project.i18n_pos_file.c_str()); + write_word(proj_.i18n_pos_file.c_str()); } - write_string("\ni18n_pos_set"); write_word(g_project.i18n_pos_set.c_str()); + write_string("\ni18n_pos_set"); write_word(proj_.i18n_pos_set.c_str()); break; } } 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); + write_string("\nheader_name"); write_word(proj_.header_file_name.c_str()); + write_string("\ncode_name"); write_word(proj_.code_file_name.c_str()); + Fluid.layout_list.write(this); if (g_shell_config) g_shell_config->write(this); - if (g_project.write_mergeback_data) - write_string("\nmergeback %d", g_project.write_mergeback_data); + if (proj_.write_mergeback_data) + write_string("\nmergeback %d", proj_.write_mergeback_data); } - for (Fl_Type *p = Fl_Type::first; p;) { + for (Node *p = proj_.tree.first; p;) { if (!selected_only || p->selected) { p->write(*this); write_string("\n"); @@ -161,7 +159,7 @@ int Project_Writer::write_project(const char *filename, int selected_only, bool } } int ret = close_write(); - undo_resume(); + proj_.undo.resume(); return ret; } diff --git a/fluid/io/Project_Writer.h b/fluid/io/Project_Writer.h index c6e50ca7c..67aebb46e 100644 --- a/fluid/io/Project_Writer.h +++ b/fluid/io/Project_Writer.h @@ -1,7 +1,7 @@ // -// Fluid file routines for the Fast Light Tool Kit (FLTK). +// Fluid Project File Writer header for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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,25 +21,31 @@ #include -class Fl_Type; +class Node; namespace fld { + +class Project; + namespace io { -int write_file(const char *, int selected_only = 0, bool to_codeview = false); +int write_file(Project &proj, const char *, int selected_only = 0, bool to_codeview = false); class Project_Writer { protected: + /// Link Project_Writer class to the project. + Project &proj_; + // Project output file, always opened in "wb" mode - FILE *fout; + FILE *fout = nullptr; /// If set, one space is written before text unless the format starts with a newline character - int needspace; + int needspace = 0; /// Set if this file will be used in the codeview dialog - bool write_codeview_; + bool write_codeview_ = false; public: - Project_Writer(); + Project_Writer(Project &proj); ~Project_Writer(); int open_write(const char *s); int close_write(); diff --git a/fluid/io/String_Writer.cxx b/fluid/io/String_Writer.cxx new file mode 100644 index 000000000..6b70ec1f3 --- /dev/null +++ b/fluid/io/String_Writer.cxx @@ -0,0 +1,142 @@ +// +// String File Writer code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "io/String_Writer.h" + +#include "Fluid.h" +#include "Project.h" +#include "nodes/Window_Node.h" +#include "nodes/Function_Node.h" + +using namespace fld; +using namespace fld::io; + +/** + Write a string to a file, replacing all non-ASCII characters with octal codes. + \param[in] out output file + \param[in] text write this NUL terminated utf-8 string + \return EOF if any of the file access calls failed, 0 if OK + */ +static int write_escaped_strings(FILE *out, const char *text) { + int ret = 0; + const unsigned char *utf8_text = (const unsigned char *)text; + for (const unsigned char *s = utf8_text; *s; ++s) { + unsigned char c = *s; + // escape control characters, delete, all utf-8, and the double quotes + // note: we should have an option in the project settings to allow utf-8 + // characters in the output text and not escape them + if (c < 32 || c > 126 || c == '\"') { + if (c == '\r') { + ret = fputs("\\r", out); + } else if (c == '\n') { + ret = fputs("\\n", out); + } else { + ret = fprintf(out, "\\%03o", c); + } + } else { + ret = putc((int)c, out); + } + } + return ret; +} + +/** + Write a file that contains all label and tooltip strings for internationalization. + The user is responsible to set the right file name extension. The file format + is determined by `proj_.i18n_type`. + \param[in] filename file path and name to a file that will hold the strings + \return 1 if the file could not be opened for writing, or the result of `fclose`. + */ +int fld::io::write_strings(Project &proj, const std::string &filename) { + Node *p; + Widget_Node *w; + int i; + + FILE *fp = fl_fopen(filename.c_str(), "wb"); + if (!fp) return 1; + + switch (proj.i18n_type) { + case fld::I18n_Type::NONE : /* None, just put static text out */ + fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + for (auto w: proj.tree.all_widgets()) { + if (w->label()) { + write_escaped_strings(fp, w->label()); + putc('\n', fp); + } + if (w->tooltip()) { + write_escaped_strings(fp, w->tooltip()); + putc('\n', fp); + } + } + break; + case fld::I18n_Type::GNU : /* GNU gettext, put a .po file out */ + fprintf(fp, "# generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + for (p = proj.tree.first; p; p = p->next) { + if (p->is_widget()) { + w = (Widget_Node *)p; + + if (w->label()) { + fputs("msgid \"", fp); + write_escaped_strings(fp, w->label()); + fputs("\"\n", fp); + + fputs("msgstr \"", fp); + write_escaped_strings(fp, w->label()); + fputs("\"\n", fp); + } + + if (w->tooltip()) { + fputs("msgid \"", fp); + write_escaped_strings(fp, w->tooltip()); + fputs("\"\n", fp); + + fputs("msgstr \"", fp); + write_escaped_strings(fp, w->tooltip()); + fputs("\"\n", fp); + } + } + } + break; + case fld::I18n_Type::POSIX : /* POSIX catgets, put a .msg file out */ + fprintf(fp, "$ generated by Fast Light User Interface Designer (fluid) version %.4f\n", + FL_VERSION); + fprintf(fp, "$set %s\n", proj.i18n_pos_set.c_str()); + fputs("$quote \"\n", fp); + + for (i = 1, p = proj.tree.first; p; p = p->next) { + if (p->is_widget()) { + w = (Widget_Node *)p; + + if (w->label()) { + fprintf(fp, "%d \"", i ++); + write_escaped_strings(fp, w->label()); + fputs("\"\n", fp); + } + + if (w->tooltip()) { + fprintf(fp, "%d \"", i ++); + write_escaped_strings(fp, w->tooltip()); + fputs("\"\n", fp); + } + } + } + break; + } + + return fclose(fp); +} diff --git a/fluid/io/String_Writer.h b/fluid/io/String_Writer.h new file mode 100644 index 000000000..0109a32a3 --- /dev/null +++ b/fluid/io/String_Writer.h @@ -0,0 +1,33 @@ +// +// String File Writer header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_IO_STRING_WRITER_H +#define FLUID_IO_STRING_WRITER_H + +#include + +namespace fld { + +class Project; + +namespace io { + +int write_strings(Project &proj, const std::string &filename); + +} // namespace io +} // namespace fld + +#endif // FLUID_IO_STRING_WRITER_H diff --git a/fluid/main.cxx b/fluid/main.cxx index d05732d2b..cc30114df 100644 --- a/fluid/main.cxx +++ b/fluid/main.cxx @@ -15,9 +15,9 @@ // #include "main.h" -#include "app/fluid.h" +#include "Fluid.h" int main(int argc,char **argv) { - return fluid_main(argc, argv); + return Fluid.run(argc, argv); } diff --git a/fluid/nodes/Button_Node.cxx b/fluid/nodes/Button_Node.cxx new file mode 100644 index 000000000..c1ac26e95 --- /dev/null +++ b/fluid/nodes/Button_Node.cxx @@ -0,0 +1,166 @@ +// +// Button Node code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 +// + +/** + \file Bottun_Node.cxx + + Node prototypes for Fl_Button based classes. Those are used by the Node + Factory to generate the scene from project files or user input. + */ + +#include "nodes/Button_Node.h" + +#include "Fluid.h" +#include "app/Snap_Action.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +// ---- Button Nodes --------------------------------------------------- MARK: - + + +// ---- Button ---- + +Button_Node Button_Node::prototype; + +static Fl_Menu_Item buttontype_menu[] = { + {"Normal", 0, nullptr, (void*)nullptr}, + {"Toggle", 0, nullptr, (void*)FL_TOGGLE_BUTTON}, + {"Radio", 0, nullptr, (void*)FL_RADIO_BUTTON}, + {nullptr} +}; + +Fl_Menu_Item *Button_Node::subtypes() { + return buttontype_menu; +} + +void Button_Node::ideal_size(int &w, int &h) { + auto layout = Fluid.proj.layout; + h = layout->labelsize + 8; + w = layout->labelsize * 4 + 8; + fld::app::Snap_Action::better_size(w, h); +} + +Fl_Widget *Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Button(x, y, w, h, "Button"); +} + +void Button_Node::write_properties(fld::io::Project_Writer &f) { + Widget_Node::write_properties(f); + Fl_Button *btn = (Fl_Button*)o; + if (btn->compact()) { + f.write_string("compact"); + f.write_string("%d", btn->compact()); + } +} + +void Button_Node::read_property(fld::io::Project_Reader &f, const char *c) { + Fl_Button *btn = (Fl_Button*)o; + if (!strcmp(c, "compact")) { + btn->compact((uchar)atol(f.read_word())); + } else { + Widget_Node::read_property(f, c); + } +} + +void Button_Node::copy_properties() { + Widget_Node::copy_properties(); + Fl_Button *s = (Fl_Button*)o, *d = (Fl_Button*)live_widget; + d->compact(s->compact()); +} + + +// ---- Return Button ---- + +void Return_Button_Node::ideal_size(int &w, int &h) { + auto layout = Fluid.proj.layout; + h = layout->labelsize + 8; + w = layout->labelsize * 4 + 8 + h; // make room for the symbol + fld::app::Snap_Action::better_size(w, h); +} + +Fl_Widget *Return_Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Return_Button(x, y, w, h, "Button"); +} + +Return_Button_Node Return_Button_Node::prototype; + + +// ---- Repeat Button ---- + +Fl_Widget *Repeat_Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Repeat_Button(x, y, w, h, "Button"); +} + +Repeat_Button_Node Repeat_Button_Node::prototype; + + +// ---- Light Button ---- + +void Light_Button_Node::ideal_size(int &w, int &h) { + auto layout = Fluid.proj.layout; + h = layout->labelsize + 8; + w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the light + fld::app::Snap_Action::better_size(w, h); +} + +Fl_Widget *Light_Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Light_Button(x, y, w, h, "Button"); +} + +Light_Button_Node Light_Button_Node::prototype; + + +// ---- Check Button ---- + +void Check_Button_Node::ideal_size(int &w, int &h) { + auto layout = Fluid.proj.layout; + h = layout->labelsize + 8; + w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol + fld::app::Snap_Action::better_size(w, h); +} + +Fl_Widget *Check_Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Check_Button(x, y, w, h, "Button"); +} + +Check_Button_Node Check_Button_Node::prototype; + + +// ---- Round Button ---- + +void Round_Button_Node::ideal_size(int &w, int &h) { + auto layout = Fluid.proj.layout; + h = layout->labelsize + 8; + w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol + fld::app::Snap_Action::better_size(w, h); +} + +Fl_Widget *Round_Button_Node::widget(int x, int y, int w, int h) { + return new Fl_Round_Button(x, y, w, h, "Button"); +} + +Round_Button_Node Round_Button_Node::prototype; + diff --git a/fluid/nodes/Button_Node.h b/fluid/nodes/Button_Node.h new file mode 100644 index 000000000..ecdc8cc24 --- /dev/null +++ b/fluid/nodes/Button_Node.h @@ -0,0 +1,149 @@ +// +// Button Node header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_NODES_BUTTON_NODE_H +#define FLUID_NODES_BUTTON_NODE_H + +#include "nodes/Widget_Node.h" + +/** + \brief A handler for the simple push button and a base class for all other buttons. + */ +class Button_Node : public Widget_Node +{ +public: + typedef Widget_Node super; + static Button_Node prototype; +private: + Fl_Menu_Item *subtypes() override; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Button"; } + const char *alt_type_name() override { return "fltk::Button"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Button_Node(); } + int is_button() const override { return 1; } + Type type() const override { return Type::Button; } + bool is_a(Type inType) const override { return (inType==Type::Button) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + void copy_properties() override; +}; + +// ---- Return Button ---- + +/** + \brief The Return Button is simply a Button with the return key as a hotkey. + */ +class Return_Button_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Return_Button_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Return_Button"; } + const char *alt_type_name() override { return "fltk::ReturnButton"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Return_Button_Node(); } + Type type() const override { return Type::Return_Button; } + bool is_a(Type inType) const override { return (inType==Type::Return_Button) ? true : super::is_a(inType); } +}; + +// ---- Repeat Button ---- + +/** + \brief Handler for Fl_Repeat_Button. + \note Even though Fl_Repeat_Button is somewhat limited compared to Fl_Button, + and some settings may not make much sense, it is still derived from it, + so the wrapper should be as well. + */ +class Repeat_Button_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Repeat_Button_Node prototype; +public: + const char *type_name() override { return "Fl_Repeat_Button"; } + const char *alt_type_name() override { return "fltk::RepeatButton"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Repeat_Button_Node(); } + Type type() const override { return Type::Repeat_Button; } + bool is_a(Type inType) const override { return (inType==Type::Repeat_Button) ? true : super::is_a(inType); } +}; + +// ---- Light Button ---- + +/** + \brief A handler for a toggle button with an indicator light. + */ +class Light_Button_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Light_Button_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Light_Button"; } + const char *alt_type_name() override { return "fltk::LightButton"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Light_Button_Node(); } + Type type() const override { return Type::Light_Button; } + bool is_a(Type inType) const override { return (inType==Type::Light_Button) ? true : super::is_a(inType); } +}; + +// ---- Check Button ---- + +/** + \brief Manage buttons with a check mark on its left. + */ +class Check_Button_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Check_Button_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Check_Button"; } + const char *alt_type_name() override { return "fltk::CheckButton"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Check_Button_Node(); } + Type type() const override { return Type::Check_Button; } + bool is_a(Type inType) const override { return (inType==Type::Check_Button) ? true : super::is_a(inType); } +}; + +// ---- Round Button ---- + +/** + \brief Manage buttons with a round indicator on its left. + */ +class Round_Button_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Round_Button_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Round_Button"; } + const char *alt_type_name() override { return "fltk::RadioButton"; } + Fl_Widget *widget(int x, int y, int w, int h) override; + Widget_Node *_make() override { return new Round_Button_Node(); } + Type type() const override { return Type::Round_Button; } + bool is_a(Type inType) const override { return (inType==Type::Round_Button) ? true : super::is_a(inType); } +}; + + +#endif // FLUID_NODES_BUTTON_NODE_H diff --git a/fluid/nodes/Fl_Button_Type.cxx b/fluid/nodes/Fl_Button_Type.cxx deleted file mode 100644 index 2d3b7f31f..000000000 --- a/fluid/nodes/Fl_Button_Type.cxx +++ /dev/null @@ -1,227 +0,0 @@ -// -// Button type factory code for the Fast Light Tool Kit (FLTK). -// -// Type classes for most of the fltk widgets. Most of the work -// is done by code in Fl_Widget_Type.C. Also a factory instance -// of each of these type classes. -// -// This file also contains the "new" menu, which has a pointer -// to a factory instance for every class (both the ones defined -// here and ones in other files) -// -// 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 -// 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 "nodes/Fl_Button_Type.h" - -#include "app/Fd_Snap_Action.h" -#include "io/Project_Reader.h" -#include "io/Project_Writer.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - - - -// ---- Button Types --------------------------------------------------- MARK: - - - -// ---- Button ---- - -static Fl_Menu_Item buttontype_menu[] = { - {"Normal", 0, 0, (void*)0}, - {"Toggle", 0, 0, (void*)FL_TOGGLE_BUTTON}, - {"Radio", 0, 0, (void*)FL_RADIO_BUTTON}, - {0} -}; - -Fl_Menu_Item *Fl_Button_Type::subtypes() { - return buttontype_menu; -} - -void Fl_Button_Type::ideal_size(int &w, int &h) { - h = layout->labelsize + 8; - w = layout->labelsize * 4 + 8; - Fd_Snap_Action::better_size(w, h); -} - -Fl_Widget *Fl_Button_Type::widget(int x, int y, int w, int h) { - return new Fl_Button(x, y, w, h, "Button"); -} - -void Fl_Button_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Widget_Type::write_properties(f); - Fl_Button *btn = (Fl_Button*)o; - if (btn->compact()) { - f.write_string("compact"); - f.write_string("%d", btn->compact()); - } -} - -void Fl_Button_Type::read_property(fld::io::Project_Reader &f, const char *c) { - Fl_Button *btn = (Fl_Button*)o; - if (!strcmp(c, "compact")) { - btn->compact((uchar)atol(f.read_word())); - } else { - Fl_Widget_Type::read_property(f, c); - } -} - -void Fl_Button_Type::copy_properties() { - Fl_Widget_Type::copy_properties(); - Fl_Button *s = (Fl_Button*)o, *d = (Fl_Button*)live_widget; - d->compact(s->compact()); -} - -Fl_Button_Type Fl_Button_type; - - -// ---- Return Button ---- - -/** - \brief The Return Button is simply a Button with the return key as a hotkey. - */ -class Fl_Return_Button_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - h = layout->labelsize + 8; - w = layout->labelsize * 4 + 8 + h; // make room for the symbol - Fd_Snap_Action::better_size(w, h); - } - const char *type_name() FL_OVERRIDE { return "Fl_Return_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::ReturnButton"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - return new Fl_Return_Button(x, y, w, h, "Button"); - } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Return_Button_Type(); } - ID id() const FL_OVERRIDE { return ID_Return_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Return_Button) ? true : super::is_a(inID); } -}; - -Fl_Return_Button_Type Fl_Return_Button_type; - - -// ---- Repeat Button ---- - -/** - \brief Handler for Fl_Repeat_Button. - \note Even though Fl_Repeat_Button is somewhat limited compared to Fl_Button, - and some settings may not make much sense, it is still derived from it, - so the wrapper should be as well. - */ -class Fl_Repeat_Button_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - const char *type_name() FL_OVERRIDE { return "Fl_Repeat_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::RepeatButton"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - return new Fl_Repeat_Button(x, y, w, h, "Button"); - } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Repeat_Button_Type(); } - ID id() const FL_OVERRIDE { return ID_Repeat_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Repeat_Button) ? true : super::is_a(inID); } -}; - -Fl_Repeat_Button_Type Fl_Repeat_Button_type; - - -// ---- Light Button ---- - -/** - \brief A handler for a toggle button with an indicator light. - */ -class Fl_Light_Button_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - h = layout->labelsize + 8; - w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the light - Fd_Snap_Action::better_size(w, h); - } - const char *type_name() FL_OVERRIDE { return "Fl_Light_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::LightButton"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - return new Fl_Light_Button(x, y, w, h, "Button"); - } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Light_Button_Type(); } - ID id() const FL_OVERRIDE { return ID_Light_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Light_Button) ? true : super::is_a(inID); } -}; - -Fl_Light_Button_Type Fl_Light_Button_type; - - -// ---- Check Button ---- - -/** - \brief Manage buttons with a check mark on its left. - */ -class Fl_Check_Button_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - h = layout->labelsize + 8; - w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol - Fd_Snap_Action::better_size(w, h); - } - const char *type_name() FL_OVERRIDE { return "Fl_Check_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::CheckButton"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - return new Fl_Check_Button(x, y, w, h, "Button"); - } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Check_Button_Type(); } - ID id() const FL_OVERRIDE { return ID_Check_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Check_Button) ? true : super::is_a(inID); } -}; - -Fl_Check_Button_Type Fl_Check_Button_type; - - -// ---- Round Button ---- - -/** - \brief Manage buttons with a round indicator on its left. - */ -class Fl_Round_Button_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - h = layout->labelsize + 8; - w = layout->labelsize * 4 + 8 + layout->labelsize; // make room for the symbol - Fd_Snap_Action::better_size(w, h); - } - const char *type_name() FL_OVERRIDE { return "Fl_Round_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::RadioButton"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - return new Fl_Round_Button(x, y, w, h, "Button"); - } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Round_Button_Type(); } - ID id() const FL_OVERRIDE { return ID_Round_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Round_Button) ? true : super::is_a(inID); } -}; - -Fl_Round_Button_Type Fl_Round_Button_type; - diff --git a/fluid/nodes/Fl_Button_Type.h b/fluid/nodes/Fl_Button_Type.h deleted file mode 100644 index 4229ac82d..000000000 --- a/fluid/nodes/Fl_Button_Type.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Button type header file for the Fast Light Tool Kit (FLTK). -// -// 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 -// 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 _FL_BUTTON_TYPE_H -#define _FL_BUTTON_TYPE_H - -#include "nodes/Fl_Widget_Type.h" - -/** - \brief A handler for the simple push button and a base class for all other buttons. - */ -class Fl_Button_Type : public Fl_Widget_Type -{ - typedef Fl_Widget_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE; - const char *type_name() FL_OVERRIDE { return "Fl_Button"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Button"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE; - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Button_Type(); } - int is_button() const FL_OVERRIDE { return 1; } - ID id() const FL_OVERRIDE { return ID_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Button) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; -}; - -extern Fl_Button_Type Fl_Button_type; - - -#endif // _FL_BUTTON_TYPE_H diff --git a/fluid/nodes/Fl_Function_Type.h b/fluid/nodes/Fl_Function_Type.h deleted file mode 100644 index 4c2319aee..000000000 --- a/fluid/nodes/Fl_Function_Type.h +++ /dev/null @@ -1,259 +0,0 @@ -// -// C function type header file for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2021 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_FL_FUNCTION_TYPE_H -#define _FLUID_FL_FUNCTION_TYPE_H - -#include "nodes/Fl_Type.h" - -#include "app/Fluid_Image.h" -#ifdef _WIN32 -#include "tools/ExternalCodeEditor_WIN32.h" -#else -#include "tools/ExternalCodeEditor_UNIX.h" -#endif - -#include -#include -#include -#include - -#include -#include - -extern class Fl_Class_Type *current_class; - -int has_toplevel_function(const char *rtype, const char *sig); - -const char *c_check(const char *c, int type = 0); - -// ---- Fl_Function_Type declaration - -class Fl_Function_Type : public Fl_Type -{ - typedef Fl_Type super; - const char* return_type; - char public_, cdecl_, constructor, havewidgets; - -public: - Fl_Function_Type(); - ~Fl_Function_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void open() FL_OVERRIDE; - int ismain() {return name_ == 0;} - const char *type_name() FL_OVERRIDE {return "Function";} - const char *title() FL_OVERRIDE { - return name() ? name() : "main()"; - } - int can_have_children() const FL_OVERRIDE {return 1;} - int is_code_block() const FL_OVERRIDE {return 1;} - int is_public() const FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Function; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Function) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int has_signature(const char *, const char*) const; -}; - -// ---- Fl_Code_Type declaration - -class Fl_Code_Type : public Fl_Type -{ - typedef Fl_Type super; - ExternalCodeEditor editor_; - int cursor_position_; - int code_input_scroll_row; - int code_input_scroll_col; - -public: - Fl_Code_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write(fld::io::Project_Writer &f) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "code";} - int is_code_block() const FL_OVERRIDE {return 0;} - ID id() const FL_OVERRIDE { return ID_Code; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Code) ? true : super::is_a(inID); } - int is_public() const FL_OVERRIDE { return -1; } - int is_editing(); - int reap_editor(); - int handle_editor_changes(); -}; - -// ---- Fl_CodeBlock_Type declaration - -class Fl_CodeBlock_Type : public Fl_Type -{ - typedef Fl_Type super; - const char* after; - -public: - Fl_CodeBlock_Type(); - ~Fl_CodeBlock_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "codeblock";} - int is_code_block() const FL_OVERRIDE {return 1;} - int can_have_children() const FL_OVERRIDE {return 1;} - int is_public() const FL_OVERRIDE { return -1; } - ID id() const FL_OVERRIDE { return ID_CodeBlock; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_CodeBlock) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; -}; - -// ---- Fl_Decl_Type declaration - -class Fl_Decl_Type : public Fl_Type -{ - typedef Fl_Type super; - -protected: - char public_; - char static_; - -public: - Fl_Decl_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "decl";} - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int is_public() const FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Decl; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Decl) ? true : super::is_a(inID); } -}; - -// ---- Fl_Data_Type declaration - -class Fl_Data_Type : public Fl_Decl_Type -{ - typedef Fl_Decl_Type super; - const char *filename_; - int text_mode_; - -public: - Fl_Data_Type(); - ~Fl_Data_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE {} - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "data";} - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Data; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Data) ? true : super::is_a(inID); } -}; - -// ---- Fl_DeclBlock_Type declaration - -class Fl_DeclBlock_Type : public Fl_Type -{ - typedef Fl_Type super; - enum { - CODE_IN_HEADER = 1, - CODE_IN_SOURCE = 2, - STATIC_IN_HEADER = 4, - STATIC_IN_SOURCE = 8 - }; - const char* after; ///< code after all children of this block - int write_map_; ///< see enum above - -public: - Fl_DeclBlock_Type(); - ~Fl_DeclBlock_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_static_after(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "declblock";} - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int can_have_children() const FL_OVERRIDE {return 1;} - int is_decl_block() const FL_OVERRIDE {return 1;} - int is_public() const FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_DeclBlock; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_DeclBlock) ? true : super::is_a(inID); } -}; - -// ---- Fl_Comment_Type declaration - -class Fl_Comment_Type : public Fl_Type -{ - typedef Fl_Type super; - char in_c_, in_h_, style_; - -public: - Fl_Comment_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE { } - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "comment";} - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int is_public() const FL_OVERRIDE { return 1; } - ID id() const FL_OVERRIDE { return ID_Comment; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Comment) ? true : super::is_a(inID); } -}; - -// ---- Fl_Class_Type declaration - -class Fl_Class_Type : public Fl_Type -{ - typedef Fl_Type super; - const char* subclass_of; - char public_; - const char* class_prefix; - -public: - Fl_Class_Type(); - ~Fl_Class_Type(); - // state variables for output: - char write_public_state; // true when public: has been printed - Fl_Class_Type* parent_class; // save class if nested -// - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void open() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "class";} - int can_have_children() const FL_OVERRIDE {return 1;} - int is_decl_block() const FL_OVERRIDE {return 1;} - int is_class() const FL_OVERRIDE {return 1;} - int is_public() const FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Class; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Class) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - - // class prefix attribute access - void prefix(const char* p); - const char* prefix() const {return class_prefix;} -}; - -#endif // _FLUID_FL_FUNCTION_TYPE_H diff --git a/fluid/nodes/Fl_Grid_Type.h b/fluid/nodes/Fl_Grid_Type.h deleted file mode 100644 index 1ce5321c8..000000000 --- a/fluid/nodes/Fl_Grid_Type.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// Fl_Grid type 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_FL_GRID_TYPE_H -#define _FLUID_FL_GRID_TYPE_H - -#include "nodes/Fl_Group_Type.h" -#include - -// ---- Fl_Grid_Type --------------------------------------------------- MARK: - - -extern const char grid_type_name[]; - -class Fl_Grid_Proxy : public Fl_Grid { -protected: - typedef struct { Fl_Widget *widget; Cell *cell; } Cell_Widget_Pair; - Cell_Widget_Pair *transient_; - int num_transient_; - int cap_transient_; - void transient_make_room_(int n); - void transient_remove_(Fl_Widget *w); -public: - Fl_Grid_Proxy(int X,int Y,int W,int H); - ~Fl_Grid_Proxy(); - void resize(int,int,int,int) FL_OVERRIDE; - void draw() FL_OVERRIDE; - void draw_overlay(); - void move_cell(Fl_Widget *child, int to_row, int to_col, int how = 0); - Cell* any_cell(Fl_Widget *widget) const; - Cell* transient_cell(Fl_Widget *widget) const; - Cell* transient_widget(Fl_Widget *wi, int row, int col, int row_span, int col_span, Fl_Grid_Align align = FL_GRID_FILL); - Cell* widget(Fl_Widget *wi, int row, int col, Fl_Grid_Align align = FL_GRID_FILL); - Cell* widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align = FL_GRID_FILL); -}; - -class Fl_Grid_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; -public: - Fl_Grid_Type(); - const char *type_name() FL_OVERRIDE {return grid_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::GridGroup";} - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Grid_Type(); } - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Grid; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Grid) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - void write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) FL_OVERRIDE; - void read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) FL_OVERRIDE; - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void leave_live_mode() FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; - void copy_properties_for_children() FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; - void layout_widget() FL_OVERRIDE; - void child_resized(Fl_Widget_Type *child); - void insert_child_at(Fl_Widget *child, int x, int y); - void insert_child_at_next_free_cell(Fl_Widget *child); - void keyboard_move_child(Fl_Widget_Type*, int key); - - static class Fl_Grid *selected(); -}; - -#endif // _FLUID_FL_GRID_TYPE_H diff --git a/fluid/nodes/Fl_Group_Type.h b/fluid/nodes/Fl_Group_Type.h deleted file mode 100644 index 30fab1d20..000000000 --- a/fluid/nodes/Fl_Group_Type.h +++ /dev/null @@ -1,242 +0,0 @@ -// -// Group type header file for the Fast Light Tool Kit (FLTK). -// -// 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 -// 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_FL_GROUP_TYPE_H -#define _FLUID_FL_GROUP_TYPE_H - -#include "nodes/Fl_Widget_Type.h" - -#include -#include -#include -#include - -void group_cb(Fl_Widget *, void *); -void ungroup_cb(Fl_Widget *, void *); - -// ---- Fl_Group_Type -------------------------------------------------- MARK: - - -/** - Proxy group to use in place of Fl_Group in the interactive window. - - In an interactive environment, groups should not automatically resize their - children. This proxy disables the layout of children by default. Children - layout propagation may be enable temporarily by incrementing `allow_layout` - before resizing and decrementing it again afterwards. - */ -class Fl_Group_Proxy : public Fl_Group { -public: - Fl_Group_Proxy(int X,int Y,int W,int H) : Fl_Group(X, Y, W, H) { Fl_Group::current(0); } - void resize(int x, int y, int w, int h) FL_OVERRIDE; - void draw() FL_OVERRIDE; -}; - -class Fl_Group_Type : public Fl_Widget_Type -{ - typedef Fl_Widget_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "Fl_Group";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::Group";} - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Group_Proxy *g = new Fl_Group_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Group_Type();} - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; - int can_have_children() const FL_OVERRIDE {return 1;} - ID id() const FL_OVERRIDE { return ID_Group; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Group) ? true : super::is_a(inID); } - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void leave_live_mode() FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; -}; - -// ---- Fl_Pack_Type --------------------------------------------------- MARK: - - -extern const char pack_type_name[]; -extern Fl_Menu_Item pack_type_menu[]; - -class Fl_Pack_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE {return pack_type_menu;} -public: - const char *type_name() FL_OVERRIDE {return pack_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::PackedGroup";} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Pack_Type();} - ID id() const FL_OVERRIDE { return ID_Pack; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Pack) ? true : super::is_a(inID); } - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; -}; - -// ---- Fl_Flex_Type --------------------------------------------------- MARK: - - -extern const char flex_type_name[]; -extern Fl_Menu_Item flex_type_menu[]; - -class Fl_Flex_Proxy : public Fl_Flex { -public: - Fl_Flex_Proxy(int X,int Y,int W,int H) : Fl_Flex(X, Y, W, H) { Fl_Group::current(0); } - void resize(int x, int y, int w, int h) FL_OVERRIDE; - void draw() FL_OVERRIDE; -}; - -class Fl_Flex_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE {return flex_type_menu;} - int fixedSizeTupleSize; /* number of pairs in array */ - int *fixedSizeTuple; /* [ index, size, index2, size2, ... ] */ - int suspend_auto_layout; -public: - Fl_Flex_Type() : fixedSizeTupleSize(0), fixedSizeTuple(NULL), suspend_auto_layout(0) { } - const char *type_name() FL_OVERRIDE {return flex_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::FlexGroup";} - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Flex_Type(); } - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Flex *g = new Fl_Flex_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} - ID id() const FL_OVERRIDE { return ID_Flex; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Flex) ? true : super::is_a(inID); } - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; - void copy_properties_for_children() FL_OVERRIDE; - void postprocess_read() FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; -// void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; -// void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; - void layout_widget() FL_OVERRIDE; - void change_subtype_to(int n); - void insert_child_at(Fl_Widget *child, int x, int y); - void keyboard_move_child(Fl_Widget_Type*, int key); - static int parent_is_flex(Fl_Type*); - static int size(Fl_Type*, char fixed_only=0); - static int is_fixed(Fl_Type*); -}; - -// ---- Fl_Table_Type -------------------------------------------------- MARK: - - -class Fl_Table_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE; - const char *type_name() FL_OVERRIDE { return "Fl_Table"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::TableGroup"; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Table_Type(); } - Fl_Widget *widget(int X, int Y, int W, int H) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Table; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Table) ? true : super::is_a(inID); } - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; -}; - -// ---- Fl_Tabs_Type --------------------------------------------------- MARK: - - -extern const char tabs_type_name[]; - -class Fl_Tabs_Proxy : public Fl_Tabs { -public: - Fl_Tabs_Proxy(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {} - void resize(int,int,int,int) FL_OVERRIDE; - void draw() FL_OVERRIDE; -}; - -class Fl_Tabs_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; -public: - 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 { - Fl_Tabs_Proxy *g = new Fl_Tabs_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Tabs_Type();} - Fl_Type* click_test(int,int) FL_OVERRIDE; - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Tabs; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tabs) ? true : super::is_a(inID); } - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; -}; - -// ---- Fl_Scroll_Type ------------------------------------------------- MARK: - - -extern const char scroll_type_name[]; -extern Fl_Menu_Item scroll_type_menu[]; - -class Fl_Scroll_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE {return scroll_type_menu;} -public: - const char *type_name() FL_OVERRIDE {return scroll_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::ScrollGroup";} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Scroll_Type();} - ID id() const FL_OVERRIDE { return ID_Scroll; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Scroll) ? true : super::is_a(inID); } - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; -}; - -// ---- Fl_Tile_Type --------------------------------------------------- MARK: - - -extern const char tile_type_name[]; - -class Fl_Tile_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; -public: - const char *type_name() FL_OVERRIDE {return tile_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::TileGroup";} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Tile_Type();} - ID id() const FL_OVERRIDE { return ID_Tile; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tile) ? true : super::is_a(inID); } - void copy_properties() FL_OVERRIDE; -}; - -// ---- Fl_Wizard_Type ------------------------------------------------- MARK: - - -class Fl_Wizard_Proxy : public Fl_Wizard { -public: - Fl_Wizard_Proxy(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {} - void resize(int,int,int,int) FL_OVERRIDE; - void draw() FL_OVERRIDE; -}; - -extern const char wizard_type_name[]; - -class Fl_Wizard_Type : public Fl_Group_Type -{ - typedef Fl_Group_Type super; -public: - const char *type_name() FL_OVERRIDE {return wizard_type_name;} - const char *alt_type_name() FL_OVERRIDE {return "fltk::WizardGroup";} - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Wizard_Proxy *g = new Fl_Wizard_Proxy(X,Y,W,H); Fl_Group::current(0); return g;} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Wizard_Type();} - ID id() const FL_OVERRIDE { return ID_Wizard; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Wizard) ? true : super::is_a(inID); } -}; - -#endif // _FLUID_FL_GROUP_TYPE_H diff --git a/fluid/nodes/Fl_Menu_Type.h b/fluid/nodes/Fl_Menu_Type.h deleted file mode 100644 index 136a1c289..000000000 --- a/fluid/nodes/Fl_Menu_Type.h +++ /dev/null @@ -1,287 +0,0 @@ -// -// Menu type header file for the Fast Light Tool Kit (FLTK). -// -// Type for creating all subclasses of Fl_Widget -// This should have the widget pointer in it, but it is still in the -// Fl_Type base class. -// -// 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 -// 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_FL_MENU_TYPE_H -#define _FLUID_FL_MENU_TYPE_H - -#include "nodes/Fl_Button_Type.h" - -#include "app/Fd_Snap_Action.h" - -#include -#include -#include -#include -#include -#include - -extern Fl_Menu_Item dummymenu[]; -extern Fl_Menu_Item button_type_menu[]; -extern Fl_Menu_Item menu_item_type_menu[]; -extern Fl_Menu_Item menu_bar_type_menu[]; - -/** - \brief Manage all types on menu items. - Deriving Fl_Menu_Item_Type from Fl_Button_Type is intentional. For the purpose - of editing, a Menu Item is implemented with `o` pointing to an Fl_Button for - holding all properties. - */ -class Fl_Menu_Item_Type : public Fl_Button_Type -{ - typedef Fl_Button_Type super; -public: - Fl_Menu_Item* subtypes() FL_OVERRIDE {return menu_item_type_menu;} - const char* type_name() FL_OVERRIDE {return "MenuItem";} - const char* alt_type_name() FL_OVERRIDE {return "fltk::Item";} - Fl_Type* make(Strategy strategy) FL_OVERRIDE; - Fl_Type* make(int flags, Strategy strategy); - int is_button() const FL_OVERRIDE {return 1;} // this gets shortcut to work - Fl_Widget* widget(int,int,int,int) FL_OVERRIDE {return 0;} - Fl_Widget_Type* _make() FL_OVERRIDE {return 0;} - virtual const char* menu_name(fld::io::Code_Writer& f, int& i); - int flags(); - void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_item(fld::io::Code_Writer& f); - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - int is_true_widget() const FL_OVERRIDE { return 0; } - ID id() const FL_OVERRIDE { return ID_Menu_Item; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Item) ? true : super::is_a(inID); } -}; - -/** - \brief Manage Radio style Menu Items. - */ -class Fl_Radio_Menu_Item_Type : public Fl_Menu_Item_Type -{ - typedef Fl_Menu_Item_Type super; -public: - const char* type_name() FL_OVERRIDE {return "RadioMenuItem";} - Fl_Type* make(Strategy strategy) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Radio_Menu_Item; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Radio_Menu_Item) ? true : super::is_a(inID); } -}; - -/** - \brief Manage Checkbox style Menu Items. - */ -class Fl_Checkbox_Menu_Item_Type : public Fl_Menu_Item_Type -{ - typedef Fl_Menu_Item_Type super; -public: - const char* type_name() FL_OVERRIDE {return "CheckMenuItem";} - Fl_Type* make(Strategy strategy) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Checkbox_Menu_Item; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Checkbox_Menu_Item) ? true : super::is_a(inID); } -}; - -/** - \brief Manage Submenu style Menu Items. - Submenu Items are simply buttons just like all other menu items, but they - can also hold a pointer to a list of submenus, or have a flag set that - allows submenus to follow in the current array. As buttons, they can - be clicked by the user, and they will call their callback, if one is set. - */ -class Fl_Submenu_Type : public Fl_Menu_Item_Type -{ - typedef Fl_Menu_Item_Type super; -public: - Fl_Menu_Item* subtypes() FL_OVERRIDE {return 0;} - const char* type_name() FL_OVERRIDE {return "Submenu";} - const char* alt_type_name() FL_OVERRIDE {return "fltk::ItemGroup";} - int can_have_children() const FL_OVERRIDE {return 1;} - int is_button() const FL_OVERRIDE {return 0;} // disable shortcut - Fl_Type* make(Strategy strategy) FL_OVERRIDE; - // changes to submenu must propagate up so build_menu is called - // on the parent Fl_Menu_Type: - void add_child(Fl_Type*a, Fl_Type*b) FL_OVERRIDE {parent->add_child(a,b);} - void move_child(Fl_Type*a, Fl_Type*b) FL_OVERRIDE {parent->move_child(a,b);} - void remove_child(Fl_Type*a) FL_OVERRIDE {parent->remove_child(a);} - ID id() const FL_OVERRIDE { return ID_Submenu; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Submenu) ? true : super::is_a(inID); } -}; - -// ----------------------------------------------------------------------------- - -/** - \brief Base class for all widgets that can have a pulldown menu attached. - Widgets with this type can be derived from Fl_Menu_ or from - Fl_Group (Fl_Input_Choice). - */ -class Fl_Menu_Manager_Type : public Fl_Widget_Type -{ - typedef Fl_Widget_Type super; -public: - void ideal_size(int &w, int &h) FL_OVERRIDE { - h = layout->textsize_not_null() + 8; - w = layout->textsize_not_null() * 6 + 8; - Fd_Snap_Action::better_size(w, h); - } - int can_have_children() const FL_OVERRIDE {return 1;} - int menusize; - virtual void build_menu() = 0; - Fl_Menu_Manager_Type() : Fl_Widget_Type() {menusize = 0;} - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE { build_menu(); } - void remove_child(Fl_Type*) FL_OVERRIDE { build_menu();} - Fl_Type* click_test(int x, int y) FL_OVERRIDE = 0; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE = 0; - ID id() const FL_OVERRIDE { return ID_Menu_Manager_; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Manager_) ? true : super::is_a(inID); } -}; - -/** - \brief Manage the composite widget Input Choice. - \note Input Choice is a composite window, so `o` will be pointing to a widget - derived from Fl_Group. All menu related methods from Fl_Menu_Trait_Type must - be virtual and must be reimplemented here (click_test, build_menu, textstuff). - */ -class Fl_Input_Choice_Type : public Fl_Menu_Manager_Type -{ - typedef Fl_Menu_Manager_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); - switch (w) { - case 4: - case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; - case 1: myo->textfont(f); break; - case 2: myo->textsize(s); break; - case 3: myo->textcolor(c); break; - } - return 1; - } -public: - ~Fl_Input_Choice_Type() { - if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Input_Choice*)o)->menu()); - } - const char *type_name() FL_OVERRIDE {return "Fl_Input_Choice";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::ComboBox";} - Fl_Type* click_test(int,int) FL_OVERRIDE; - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); - myo->menu(dummymenu); - myo->value("input"); - return myo; - } - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Input_Choice_Type();} - void build_menu() FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Input_Choice; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Input_Choice) ? true : super::is_a(inID); } - void copy_properties() FL_OVERRIDE; -}; - -/** - \brief Base class to handle widgets that are derived from Fl_Menu_. - */ -class Fl_Menu_Base_Type : public Fl_Menu_Manager_Type -{ - typedef Fl_Menu_Manager_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Fl_Widget_Type*)this->factory)->o : this->o); - switch (w) { - case 4: - case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; - case 1: myo->textfont(f); break; - case 2: myo->textsize(s); break; - case 3: myo->textcolor(c); break; - } - return 1; - } -public: - int can_have_children() const FL_OVERRIDE {return 1;} - void build_menu() FL_OVERRIDE; - ~Fl_Menu_Base_Type() { - if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); - } - Fl_Type* click_test(int x, int y) FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Menu_; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_) ? true : super::is_a(inID); } -}; - -extern Fl_Menu_Item button_type_menu[]; - -/** - \brief Make Menu Button widgets. - */ -class Fl_Menu_Button_Type : public Fl_Menu_Base_Type -{ - typedef Fl_Menu_Base_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE {return button_type_menu;} -public: - const char *type_name() FL_OVERRIDE {return "Fl_Menu_Button";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuButton";} - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - return new Fl_Menu_Button(X,Y,W,H,"menu");} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Button_Type();} - ID id() const FL_OVERRIDE { return ID_Menu_Button; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Button) ? true : super::is_a(inID); } -}; - - -/** - \brief Manage Choice type menu widgets. - */ -class Fl_Choice_Type : public Fl_Menu_Base_Type -{ - typedef Fl_Menu_Base_Type super; -public: - const char *type_name() FL_OVERRIDE {return "Fl_Choice";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::Choice";} - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE { - Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:"); - myo->menu(dummymenu); - return myo; - } - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Choice_Type();} - ID id() const FL_OVERRIDE { return ID_Choice; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Choice) ? true : super::is_a(inID); } -}; - - -/** - \brief Manage Menubar widgets. - */ -class Fl_Menu_Bar_Type : public Fl_Menu_Base_Type -{ - typedef Fl_Menu_Base_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE {return menu_bar_type_menu;} -public: - Fl_Menu_Bar_Type(); - ~Fl_Menu_Bar_Type() FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "Fl_Menu_Bar";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::MenuBar";} - Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {return new Fl_Menu_Bar(X,Y,W,H);} - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Menu_Bar_Type();} - void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; -// void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - ID id() const FL_OVERRIDE { return ID_Menu_Bar; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Menu_Bar) ? true : super::is_a(inID); } - bool is_sys_menu_bar(); - const char *sys_menubar_name(); - const char *sys_menubar_proxy_name(); -protected: - char *_proxy_name; -}; - - -#endif // _FLUID_FL_MENU_TYPE_H diff --git a/fluid/nodes/Fl_Widget_Type.cxx b/fluid/nodes/Fl_Widget_Type.cxx deleted file mode 100644 index 2cde4d531..000000000 --- a/fluid/nodes/Fl_Widget_Type.cxx +++ /dev/null @@ -1,3939 +0,0 @@ -// -// Widget type code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2025 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 "nodes/Fl_Widget_Type.h" - -#include "app/fluid.h" -#include "app/project.h" -#include "app/Fluid_Image.h" -#include "app/mergeback.h" -#include "app/undo.h" -#include "io/Project_Reader.h" -#include "io/Project_Writer.h" -#include "io/Code_Writer.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Menu_Type.h" -#include "nodes/Fl_Function_Type.h" -#include "panels/settings_panel.h" -#include "panels/widget_panel.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../src/flstring.h" - -#include -#include - -// Make an Fl_Widget_Type subclass instance. -// It figures out the automatic size and parent of the new widget, -// creates the Fl_Widget (by calling the virtual function _make), -// adds it to the Fl_Widget hierarchy, creates a new Fl_Type -// instance, sets the widget pointers, and makes all the display -// update correctly... - -int Fl_Widget_Type::is_widget() const {return 1;} -int Fl_Widget_Type::is_public() const {return public_;} - -const char* subclassname(Fl_Type* l) { - if (l->is_a(ID_Menu_Bar)) { - Fl_Menu_Bar_Type *mb = static_cast(l); - if (mb->is_sys_menu_bar()) - return mb->sys_menubar_name(); - } - if (l->is_widget()) { - Fl_Widget_Type* p = (Fl_Widget_Type*)l; - const char* c = p->subclass(); - if (c) return c; - if (l->is_class()) return "Fl_Group"; - if (p->o->type() == FL_DOUBLE_WINDOW) return "Fl_Double_Window"; - if (p->id() == ID_Input) { - if (p->o->type() == FL_FLOAT_INPUT) return "Fl_Float_Input"; - if (p->o->type() == FL_INT_INPUT) return "Fl_Int_Input"; - } - } - return l->type_name(); -} - -// Return the ideal widget size... -void -Fl_Widget_Type::ideal_size(int &w, int &h) { - w = 120; - h = 100; - Fd_Snap_Action::better_size(w, h); -} - -/** - Make a new Widget node. - \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT - \return new node - */ -Fl_Type *Fl_Widget_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *pp = anchor; - if (pp && (strategy.placement() == Strategy::AFTER_CURRENT)) - pp = pp->parent; - while (pp && !pp->is_a(ID_Group)) { - anchor = pp; - strategy.placement(Strategy::AFTER_CURRENT); - pp = pp->parent; - } - if (!pp || !pp->is_true_widget() || !anchor->is_true_widget()) { - fl_message("Please select a group widget or window"); - return 0; - } - - Fl_Widget_Type* p = (Fl_Widget_Type*)pp; - Fl_Widget_Type* q = (Fl_Widget_Type*)anchor; - - // Figure out a border between widget and window: - int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25; - - int ULX,ULY; // parent's origin in window - if (!p->is_a(ID_Window)) { // if it is a group, add corner - ULX = p->o->x(); ULY = p->o->y(); - } else { - ULX = ULY = 0; - } - - // Figure out a position and size for the widget - int X,Y,W,H; - if (is_a(ID_Group)) { // fill the parent with the widget - X = ULX+B; - W = p->o->w()-B; - Y = ULY+B; - H = p->o->h()-B; - } else if (q != p) { // copy position and size of current widget - W = q->o->w(); - H = q->o->h(); - X = q->o->x()+W; - Y = q->o->y(); - if (X+W > ULX+p->o->w()) { - X = q->o->x(); - Y = q->o->y()+H; - if (Y+H > ULY+p->o->h()) Y = ULY+B; - } - } else { // just make it small and square... - X = ULX+B; - Y = ULY+B; - W = H = B; - } - - // Construct the Fl_Type: - Fl_Widget_Type *t = _make(); - if (!o) o = widget(0,0,100,100); // create template widget - t->factory = this; - // Construct the Fl_Widget: - t->o = widget(X,Y,W,H); - if (strategy.source() == Strategy::FROM_FILE) - t->o->label(0); - else if (t->o->label()) t->label(t->o->label()); // allow editing - t->o->user_data((void*)t); - // Put it in the parent: - // ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add()) - // add to browser: - t->add(anchor, strategy); - t->redraw(); - return t; -} - -void Fl_Widget_Type::setimage(Fluid_Image *i) { - if (i == image || is_a(ID_Window)) return; - if (image) image->decrement(); - if (i) i->increment(); - image = i; - if (i) { - i->image(o); - if (o->image() && (scale_image_w_ || scale_image_h_)) { - int iw = scale_image_w_>0 ? scale_image_w_ : o->image()->data_w(); - int ih = scale_image_h_>0 ? scale_image_h_ : o->image()->data_h(); - o->image()->scale(iw, ih, 0, 1); - } - } else { - o->image(0); - //scale_image_w_ = scale_image_h_ = 0; - } - redraw(); -} - -void Fl_Widget_Type::setinactive(Fluid_Image *i) { - if (i == inactive || is_a(ID_Window)) return; - if (inactive) inactive->decrement(); - if (i) i->increment(); - inactive = i; - if (i) { - i->deimage(o); - if (o->deimage()) { - int iw = scale_deimage_w_>0 ? scale_deimage_w_ : o->deimage()->data_w(); - int ih = scale_deimage_h_>0 ? scale_deimage_h_ : o->deimage()->data_h(); - o->deimage()->scale(iw, ih, 0, 1); - } - } else { - o->deimage(0); - //scale_deimage_w_ = scale_deimage_h_ = 0; - } - redraw(); -} - -void Fl_Widget_Type::setlabel(const char *n) { - o->label(n); - redraw(); -} - -Fl_Widget_Type::Fl_Widget_Type() -: override_visible_(0) -{ - for (int n=0; nwindow(); - delete o; - if (win) - win->redraw(); - } - if (subclass_) free((void*)subclass_); - if (tooltip_) free((void*)tooltip_); - if (image_name_) { - free((void*)image_name_); - if (image) image->decrement(); - } - if (inactive_name_) { - free((void*)inactive_name_); - if (inactive) inactive->decrement(); - } - for (int n=0; ntooltip(n); -} - -void Fl_Widget_Type::image_name(const char *n) { - setimage(Fluid_Image::find(n)); - storestring(n,image_name_); -} - -void Fl_Widget_Type::inactive_name(const char *n) { - setinactive(Fluid_Image::find(n)); - storestring(n,inactive_name_); -} - -void Fl_Widget_Type::redraw() { - Fl_Type *t = this; - if (is_a(ID_Menu_Item)) { - // find the menu button that parents this menu: - do t = t->parent; while (t && t->is_a(ID_Menu_Item)); - // kludge to cause build_menu to be called again: - if (t) - t->add_child(0, 0); - } else { - while (t->parent && t->parent->is_widget()) t = t->parent; - ((Fl_Widget_Type*)t)->o->redraw(); - } -} - -// the recursive part sorts all children, returns pointer to next: -Fl_Type *sort(Fl_Type *parent) { - Fl_Type *f,*n=0; - for (f = parent ? parent->next : Fl_Type::first; ; f = n) { - if (!f || (parent && f->level <= parent->level)) break; - n = sort(f); - if (!f->selected || !f->is_true_widget()) continue; - Fl_Widget* fw = ((Fl_Widget_Type*)f)->o; - Fl_Type *g; // we will insert before this - for (g = parent ? parent->next : Fl_Type::first; g != f; g = g->next) { - if (!g->selected || g->level > f->level) continue; - Fl_Widget* gw = ((Fl_Widget_Type*)g)->o; - if (gw->y() > fw->y()) break; - if (gw->y() == fw->y() && gw->x() > fw->x()) break; - } - if (g != f) f->move_before(g); - } - if (parent) - parent->layout_widget(); - return f; -} - -//////////////////////////////////////////////////////////////// -// The control panels! - -Fl_Window *the_panel; - -// All the callbacks use the argument to indicate whether to load or store. -// This avoids the need for pointers to all the widgets, and keeps the -// code localized in the callbacks. -// A value of LOAD means to load. The hope is that this will not collide -// with any actual useful values for the argument. I also use this to -// initialized parts of the widget that are nyi by fluid. - -Fl_Widget_Type *current_widget; // one of the selected ones -void* const LOAD = (void *)"LOAD"; // "magic" pointer to indicate that we need to load values into the dialog -static int numselected; // number selected -static int haderror; - -void name_cb(Fl_Input* o, void *v) { - if (v == LOAD) { - static char buf[1024]; - if (numselected != 1) { - snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected); - o->hide(); - } else { - o->value(current_widget->name()); - o->show(); - snprintf(buf, sizeof(buf), "%s Properties", current_widget->title()); - } - - the_panel->label(buf); - } else { - if (numselected == 1) { - current_widget->name(o->value()); - // I don't update window title, as it probably is being closed - // and wm2 (a window manager) barfs if you retitle and then - // hide a window: - // ((Fl_Window*)(o->parent()->parent()->parent()))->label(current_widget->title()); - } - } -} - -void name_public_member_cb(Fl_Choice* i, void* v) { - if (v == LOAD) { - i->value(current_widget->public_); - if (current_widget->is_in_class()) i->show(); else i->hide(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - Fl_Widget_Type *w = ((Fl_Widget_Type*)o); - if (w->is_in_class()) { - w->public_ = i->value(); - } else { - // if this is not in a class, it can be only private or public - w->public_ = (i->value()>0); - } - mod = 1; - } - } - if (mod) { - set_modflag(1); - redraw_browser(); - } - } -} - -void name_public_cb(Fl_Choice* i, void* v) { - if (v == LOAD) { - i->value(current_widget->public_>0); - if (current_widget->is_in_class()) i->hide(); else i->show(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->public_ = i->value(); - mod = 1; - } - } - if (mod) { - set_modflag(1); - redraw_browser(); - } - } -} - -/* Treating UNDO for text widget. - - Goal: we want to continuously update the UI while the user is typing text - (changing the label, in this case). Code View does deferred updates, and - the widget browser and widget panel update on every keystroke. At the same - time, we want to limit undo actions to few and logical units. - - Caveats: - - 1: the text widget has its own undo handling for the text field, but we may want to do a global undo - 2: every o->label() call will create an undo entry, but we want only one single event for all selected widgets - 3: we want a single undo for the entire editing phase, but still propagate changes as they happen - - The edit process has these main states: - - 1: starting to edit [first_change==1 && !unfocus]; we must create a single undo checkpoint before anything changes - 2: continue editing [first_change==0 && !unfocus]; we must suspend any undo checkpoints - 3: done editing, unfocus [first_change==0 && unfocus]; we must make sure that undo checkpoints are enabled again - 4: losing focus without editing [first_change==1 && unfocus]; don't create and checkpoints - - We must also check: - 1: changing focus without changing text (works) - 2: copy and paste, drag and drop operations (works) - 3: save operation without unfocus event (works) - */ -void label_cb(Fl_Input* i, void *v) { - static int first_change = 1; - if (v == LOAD) { - i->value(current_widget->label()); - first_change = 1; - } else { - if (i->changed()) { - undo_suspend(); - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - if (!mod) { - if (first_change) { - undo_resume(); - undo_checkpoint(); - undo_suspend(); - first_change = 0; - } - mod = 1; - } - o->label(i->value()); - } - } - undo_resume(); - if (mod) set_modflag(1); - } - int r = (int)Fl::callback_reason(); - if ( (r == FL_REASON_LOST_FOCUS) || (r == FL_REASON_ENTER_KEY) ) - first_change = 1; - } -} - -static Fl_Input *image_input; - -void image_cb(Fl_Input* i, void *v) { - if (v == LOAD) { - image_input = i; - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->image_name()); - } else i->deactivate(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->image_name(i->value()); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void image_browse_cb(Fl_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) - b->activate(); - else - b->deactivate(); - } else { - int mod = 0; - if (ui_find_image(image_input->value())) { - image_input->value(ui_find_image_name); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->image_name(ui_find_image_name); - mod = 1; - } - } - if (mod) set_modflag(1); - } - } -} - -void bind_image_cb(Fl_Check_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - b->activate(); - b->value(current_widget->bind_image_); - } else { - b->deactivate(); - } - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->bind_image_ = b->value(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void compress_image_cb(Fl_Check_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - b->activate(); - b->value(!current_widget->compress_image_); - } else { - b->deactivate(); - } - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->compress_image_ = !b->value(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -static Fl_Input *inactive_input; - -void inactive_cb(Fl_Input* i, void *v) { - if (v == LOAD) { - inactive_input = i; - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->inactive_name()); - } else i->deactivate(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->inactive_name(i->value()); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void inactive_browse_cb(Fl_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) - b->activate(); - else - b->deactivate(); - } else { - int mod = 0; - if (ui_find_image(inactive_input->value())) { - inactive_input->value(ui_find_image_name); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->inactive_name(ui_find_image_name); - mod = 1; - } - } - if (mod) set_modflag(1); - } - } -} - -void bind_deimage_cb(Fl_Check_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - b->activate(); - b->value(current_widget->bind_deimage_); - } else { - b->deactivate(); - } - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->bind_deimage_ = b->value(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void compress_deimage_cb(Fl_Check_Button* b, void *v) { - if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { - b->activate(); - b->value(!current_widget->compress_deimage_); - } else { - b->deactivate(); - } - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->compress_deimage_ = !b->value(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void tooltip_cb(Fl_Input* i, void *v) { - if (v == LOAD) { - if (current_widget->is_widget()) { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->tooltip()); - } else i->deactivate(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - ((Fl_Widget_Type*)o)->tooltip(i->value()); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -fld::widget::Formula_Input *x_input, *y_input, *w_input, *h_input; - -static int widget_i = 0; - -static int vars_i_cb(const fld::widget::Formula_Input*, void *v) { - return widget_i; -} - -static int vars_x_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = (Fl_Type*)v; - if (t->is_widget()) - return ((Fl_Widget_Type*)t)->o->x(); - return 0; -} - -static int vars_y_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = (Fl_Type*)v; - if (t->is_widget()) - return ((Fl_Widget_Type*)t)->o->y(); - return 0; -} - -static int vars_w_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = (Fl_Type*)v; - if (t->is_widget()) - return ((Fl_Widget_Type*)t)->o->w(); - return 0; -} - -static int vars_h_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = (Fl_Type*)v; - if (t->is_widget()) - return ((Fl_Widget_Type*)t)->o->h(); - return 0; -} - -static int vars_px_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->parent; - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->x(); - return 0; -} - -static int vars_py_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->parent; - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->y(); - return 0; -} - -static int vars_pw_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->parent; - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->w(); - return 0; -} - -static int vars_ph_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->parent; - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->h(); - return 0; -} - -static int vars_sx_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->x(); - return 0; -} - -static int vars_sy_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->y(); - return 0; -} - -static int vars_sw_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->w(); - return 0; -} - -static int vars_sh_cb(const fld::widget::Formula_Input*, void *v) { - Fl_Type *t = ((Fl_Type*)v)->prev_sibling(); - if (t && t->is_widget()) - return ((Fl_Widget_Type*)t)->o->h(); - return 0; -} - -static int bbox_x, bbox_y, bbox_r, bbox_b; -static int bbox_min(int a, int b) { return (ab) ? a : b; } - -static void calculate_bbox(Fl_Type *p) { - char first = 1; - bbox_x = bbox_y = bbox_r = bbox_b = 0; - for (p=p->first_child(); p; p=p->next_sibling()) { - if (p->is_widget()) { - Fl_Widget *o = ((Fl_Widget_Type*)p)->o; - if (first) { - bbox_x = o->x(); bbox_y = o->y(); - bbox_r = o->x() + o->w(); bbox_b = o->y() + o->h(); - first = 0; - } else { - bbox_x = bbox_min(bbox_x, o->x()); - bbox_y = bbox_min(bbox_y, o->y()); - bbox_r = bbox_max(bbox_r, o->x() + o->w()); - bbox_b = bbox_max(bbox_b, o->y() + o->h()); - } - } - } -} - -static int vars_cx_cb(const fld::widget::Formula_Input*, void *v) { - calculate_bbox((Fl_Type*)v); - return bbox_x; -} - -static int vars_cy_cb(const fld::widget::Formula_Input*, void *v) { - calculate_bbox((Fl_Type*)v); - return bbox_y; -} - -static int vars_cw_cb(const fld::widget::Formula_Input*, void *v) { - calculate_bbox((Fl_Type*)v); - return bbox_r - bbox_x; -} - -static int vars_ch_cb(const fld::widget::Formula_Input*, void *v) { - calculate_bbox((Fl_Type*)v); - return bbox_b - bbox_y; -} - -fld::widget::Formula_Input_Vars widget_vars[] = { - { "i", vars_i_cb }, // zero based counter of selected widgets - { "x", vars_x_cb }, // position and size of current widget - { "y", vars_y_cb }, - { "w", vars_w_cb }, - { "h", vars_h_cb }, - { "px", vars_px_cb }, // position and size of parent widget - { "py", vars_py_cb }, - { "pw", vars_pw_cb }, - { "ph", vars_ph_cb }, - { "sx", vars_sx_cb }, // position and size of previous sibling - { "sy", vars_sy_cb }, - { "sw", vars_sw_cb }, - { "sh", vars_sh_cb }, - { "cx", vars_cx_cb }, // position and size of bounding box of all children - { "cy", vars_cy_cb }, - { "cw", vars_cw_cb }, - { "ch", vars_ch_cb }, - { 0 } -}; - -void x_cb(fld::widget::Formula_Input *i, void *v) { - if (v == LOAD) { - x_input = i; - if (current_widget->is_true_widget()) { - i->value(((Fl_Widget_Type *)current_widget)->o->x()); - x_input->activate(); - } else x_input->deactivate(); - } else { - undo_checkpoint(); - widget_i = 0; - int mod = 0; - int v = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - i->variables(widget_vars, o); - v = i->value(); - w->resize(v, w->y(), w->w(), w->h()); - if (w->window()) w->window()->redraw(); - widget_i++; - mod = 1; - } - } - if (mod) { - set_modflag(1); - i->value(v); // change the displayed value to the result of the last - // calculation. Keep the formula if it was not used. - } - } -} - -void y_cb(fld::widget::Formula_Input *i, void *v) { - if (v == LOAD) { - y_input = i; - if (current_widget->is_true_widget()) { - i->value(((Fl_Widget_Type *)current_widget)->o->y()); - y_input->activate(); - } else y_input->deactivate(); - } else { - undo_checkpoint(); - widget_i = 0; - int mod = 0; - int v = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - i->variables(widget_vars, o); - v = i->value(); - w->resize(w->x(), v, w->w(), w->h()); - if (w->window()) w->window()->redraw(); - widget_i++; - mod = 1; - } - } - if (mod) { - set_modflag(1); - i->value(v); - } - } -} - -void w_cb(fld::widget::Formula_Input *i, void *v) { - if (v == LOAD) { - w_input = i; - if (current_widget->is_true_widget()) { - i->value(((Fl_Widget_Type *)current_widget)->o->w()); - w_input->activate(); - } else w_input->deactivate(); - } else { - undo_checkpoint(); - widget_i = 0; - int mod = 0; - int v = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - i->variables(widget_vars, o); - v = i->value(); - w->resize(w->x(), w->y(), v, w->h()); - if (w->window()) w->window()->redraw(); - widget_i++; - mod = 1; - } - } - if (mod) { - set_modflag(1); - i->value(v); - } - } -} - -void h_cb(fld::widget::Formula_Input *i, void *v) { - if (v == LOAD) { - h_input = i; - if (current_widget->is_true_widget()) { - i->value(((Fl_Widget_Type *)current_widget)->o->h()); - h_input->activate(); - } else h_input->deactivate(); - } else { - undo_checkpoint(); - widget_i = 0; - int mod = 0; - int v = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - i->variables(widget_vars, o); - v = i->value(); - w->resize(w->x(), w->y(), w->w(), v); - if (w->window()) w->window()->redraw(); - widget_i++; - mod = 1; - } - } - if (mod) { - set_modflag(1); - i->value(v); - } - } -} - -void wc_relative_cb(Fl_Choice *i, void *v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Widget_Class)) { - i->show(); - i->value(((Fl_Widget_Class_Type *)current_widget)->wc_relative); - } else { - i->hide(); - } - } else { - int mod = 0; - undo_checkpoint(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && current_widget->is_a(ID_Widget_Class)) { - Fl_Widget_Class_Type *t = (Fl_Widget_Class_Type *)o; - t->wc_relative = i->value(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -// turn number to string or string to number for saving to file: -// does not work for hierarchical menus! - -const char *item_name(Fl_Menu_Item* m, int i) { - if (m) { - while (m->label()) { - if (m->argument() == i) return m->label(); - m++; - } - } - static char buffer[20]; - sprintf(buffer, "%d", i); - return buffer; -} -int item_number(Fl_Menu_Item* m, const char* i) { - if (!i) - return 0; - if (m && i) { - if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; - while (m->label()) { - if (!strcmp(m->label(), i)) return int(m->argument()); - m++; - } - } - return atoi(i); -} - -#define ZERO_ENTRY 1000 - -Fl_Menu_Item boxmenu[] = { -{"NO_BOX",0,0,(void *)ZERO_ENTRY}, -{"boxes",0,0,0,FL_SUBMENU}, -{"UP_BOX",0,0,(void *)FL_UP_BOX}, -{"DOWN_BOX",0,0,(void *)FL_DOWN_BOX}, -{"FLAT_BOX",0,0,(void *)FL_FLAT_BOX}, -{"BORDER_BOX",0,0,(void *)FL_BORDER_BOX}, -{"THIN_UP_BOX",0,0,(void *)FL_THIN_UP_BOX}, -{"THIN_DOWN_BOX",0,0,(void *)FL_THIN_DOWN_BOX}, -{"ENGRAVED_BOX",0,0,(void *)FL_ENGRAVED_BOX}, -{"EMBOSSED_BOX",0,0,(void *)FL_EMBOSSED_BOX}, -{"ROUND_UP_BOX",0,0,(void *)FL_ROUND_UP_BOX}, -{"ROUND_DOWN_BOX",0,0,(void *)FL_ROUND_DOWN_BOX}, -{"DIAMOND_UP_BOX",0,0,(void *)FL_DIAMOND_UP_BOX}, -{"DIAMOND_DOWN_BOX",0,0,(void *)FL_DIAMOND_DOWN_BOX}, -{"SHADOW_BOX",0,0,(void *)FL_SHADOW_BOX}, -{"ROUNDED_BOX",0,0,(void *)FL_ROUNDED_BOX}, -{"RSHADOW_BOX",0,0,(void *)FL_RSHADOW_BOX}, -{"RFLAT_BOX",0,0,(void *)FL_RFLAT_BOX}, -{"OVAL_BOX",0,0,(void *)FL_OVAL_BOX}, -{"OSHADOW_BOX",0,0,(void *)FL_OSHADOW_BOX}, -{"OFLAT_BOX",0,0,(void *)FL_OFLAT_BOX}, -{"PLASTIC_UP_BOX",0,0,(void *)FL_PLASTIC_UP_BOX}, -{"PLASTIC_DOWN_BOX",0,0,(void *)FL_PLASTIC_DOWN_BOX}, -{"PLASTIC_THIN_UP_BOX",0,0,(void *)FL_PLASTIC_THIN_UP_BOX}, -{"PLASTIC_THIN_DOWN_BOX",0,0,(void *)FL_PLASTIC_THIN_DOWN_BOX}, -{"PLASTIC_ROUND_UP_BOX",0,0,(void *)FL_PLASTIC_ROUND_UP_BOX}, -{"PLASTIC_ROUND_DOWN_BOX",0,0,(void *)FL_PLASTIC_ROUND_DOWN_BOX}, -{"GTK_UP_BOX",0,0,(void *)FL_GTK_UP_BOX}, -{"GTK_DOWN_BOX",0,0,(void *)FL_GTK_DOWN_BOX}, -{"GTK_THIN_UP_BOX",0,0,(void *)FL_GTK_THIN_UP_BOX}, -{"GTK_THIN_DOWN_BOX",0,0,(void *)FL_GTK_THIN_DOWN_BOX}, -{"GTK_ROUND_UP_BOX",0,0,(void *)FL_GTK_ROUND_UP_BOX}, -{"GTK_ROUND_DOWN_BOX",0,0,(void *)FL_GTK_ROUND_DOWN_BOX}, -{"GLEAM_UP_BOX",0,0,(void *)FL_GLEAM_UP_BOX}, -{"GLEAM_DOWN_BOX",0,0,(void *)FL_GLEAM_DOWN_BOX}, -{"GLEAM_THIN_UP_BOX",0,0,(void *)FL_GLEAM_THIN_UP_BOX}, -{"GLEAM_THIN_DOWN_BOX",0,0,(void *)FL_GLEAM_THIN_DOWN_BOX}, -{"GLEAM_ROUND_UP_BOX",0,0,(void *)FL_GLEAM_ROUND_UP_BOX}, -{"GLEAM_ROUND_DOWN_BOX",0,0,(void *)FL_GLEAM_ROUND_DOWN_BOX}, -{"OXY_UP_BOX",0,0,(void *)FL_OXY_UP_BOX}, -{"OXY_DOWN_BOX",0,0,(void *)FL_OXY_DOWN_BOX}, -{"OXY_THIN_UP_BOX",0,0,(void *)FL_OXY_THIN_UP_BOX}, -{"OXY_THIN_DOWN_BOX",0,0,(void *)FL_OXY_THIN_DOWN_BOX}, -{"OXY_ROUND_UP_BOX",0,0,(void *)FL_OXY_ROUND_UP_BOX}, -{"OXY_ROUND_DOWN_BOX",0,0,(void *)FL_OXY_ROUND_DOWN_BOX}, -{"OXY_BUTTON_UP_BOX",0,0,(void *)FL_OXY_BUTTON_UP_BOX}, -{"OXY_BUTTON_DOWN_BOX",0,0,(void *)FL_OXY_BUTTON_DOWN_BOX}, -{0}, -{"frames",0,0,0,FL_SUBMENU}, -{"UP_FRAME",0,0,(void *)FL_UP_FRAME}, -{"DOWN_FRAME",0,0,(void *)FL_DOWN_FRAME}, -{"THIN_UP_FRAME",0,0,(void *)FL_THIN_UP_FRAME}, -{"THIN_DOWN_FRAME",0,0,(void *)FL_THIN_DOWN_FRAME}, -{"ENGRAVED_FRAME",0,0,(void *)FL_ENGRAVED_FRAME}, -{"EMBOSSED_FRAME",0,0,(void *)FL_EMBOSSED_FRAME}, -{"BORDER_FRAME",0,0,(void *)FL_BORDER_FRAME}, -{"SHADOW_FRAME",0,0,(void *)FL_SHADOW_FRAME}, -{"ROUNDED_FRAME",0,0,(void *)FL_ROUNDED_FRAME}, -{"OVAL_FRAME",0,0,(void *)FL_OVAL_FRAME}, -{"PLASTIC_UP_FRAME",0,0,(void *)FL_PLASTIC_UP_FRAME}, -{"PLASTIC_DOWN_FRAME",0,0,(void *)FL_PLASTIC_DOWN_FRAME}, -{"GTK_UP_FRAME",0,0,(void *)FL_GTK_UP_FRAME}, -{"GTK_DOWN_FRAME",0,0,(void *)FL_GTK_DOWN_FRAME}, -{"GTK_THIN_UP_FRAME",0,0,(void *)FL_GTK_THIN_UP_FRAME}, -{"GTK_THIN_DOWN_FRAME",0,0,(void *)FL_GTK_THIN_DOWN_FRAME}, -{"GLEAM_UP_FRAME",0,0,(void *)FL_GLEAM_UP_FRAME}, -{"GLEAM_DOWN_FRAME",0,0,(void *)FL_GLEAM_DOWN_FRAME}, -{"OXY_UP_FRAME",0,0,(void *)FL_OXY_UP_FRAME}, -{"OXY_DOWN_FRAME",0,0,(void *)FL_OXY_DOWN_FRAME}, -{"OXY_THIN_UP_FRAME",0,0,(void *)FL_OXY_THIN_UP_FRAME}, -{"OXY_THIN_DOWN_FRAME",0,0,(void *)FL_OXY_THIN_DOWN_FRAME}, -{0}, -{0}}; - -const char *boxname(int i) { - if (!i) i = ZERO_ENTRY; - for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) - if (boxmenu[j].argument() == i) return boxmenu[j].label(); - return 0; -} - -int boxnumber(const char *i) { - if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; - for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) - if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) { - return int(boxmenu[j].argument()); - } - return 0; -} - -void box_cb(Fl_Choice* i, void *v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - int n = current_widget->o->box(); if (!n) n = ZERO_ENTRY; - for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) - if (boxmenu[j].argument() == n) {i->value(j); break;} - } else { - int mod = 0; - int m = i->value(); - int n = int(boxmenu[m].argument()); - if (!n) return; // should not happen - if (n == ZERO_ENTRY) n = 0; - 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; - q->o->box((Fl_Boxtype)n); - q->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void down_box_cb(Fl_Choice* i, void *v) { - if (v == LOAD) { - int n; - if (current_widget->is_a(ID_Button)) - n = ((Fl_Button*)(current_widget->o))->down_box(); - else if (current_widget->is_a(ID_Input_Choice)) - n = ((Fl_Input_Choice*)(current_widget->o))->down_box(); - else if (current_widget->is_a(ID_Menu_Manager_)) - n = ((Fl_Menu_*)(current_widget->o))->down_box(); - else { - i->deactivate(); return; - } - i->activate(); - if (!n) n = ZERO_ENTRY; - for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) - if (boxmenu[j].argument() == n) {i->value(j); break;} - } else { - int mod = 0; - int m = i->value(); - int n = int(boxmenu[m].argument()); - if (!n) return; // should not happen - if (n == ZERO_ENTRY) n = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - if (o->is_a(ID_Button)) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); - if (((Fl_Button*)(q->o))->value()) q->redraw(); - } else if (o->is_a(ID_Input_Choice)) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - ((Fl_Input_Choice*)(q->o))->down_box((Fl_Boxtype)n); - } else if (o->is_a(ID_Menu_Manager_)) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); - } - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void compact_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - uchar n; - if (current_widget->is_a(ID_Button) && !current_widget->is_a(ID_Menu_Item)) { - n = ((Fl_Button*)(current_widget->o))->compact(); - i->value(n); - i->show(); - } else { - i->hide(); - } - } else { - int mod = 0; - uchar n = (uchar)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Button) && !o->is_a(ID_Menu_Item)) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - uchar v = ((Fl_Button*)(q->o))->compact(); - if (n != v) { - if (!mod) { - mod = 1; - undo_checkpoint(); - } - ((Fl_Button*)(q->o))->compact(n); - q->redraw(); - } - } - } - if (mod) set_modflag(1); - } -} - - - -//////////////////////////////////////////////////////////////// - -Fl_Menu_Item whenmenu[] = { - // set individual bits - {"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED, FL_MENU_TOGGLE}, - {"FL_WHEN_NOT_CHANGED",0,0,(void*)FL_WHEN_NOT_CHANGED, FL_MENU_TOGGLE}, - {"FL_WHEN_RELEASE",0,0,(void*)FL_WHEN_RELEASE, FL_MENU_TOGGLE}, - {"FL_WHEN_ENTER_KEY",0,0,(void*)FL_WHEN_ENTER_KEY, FL_MENU_TOGGLE}, - {"FL_WHEN_CLOSED",0,0,(void*)FL_WHEN_CLOSED, FL_MENU_TOGGLE|FL_MENU_DIVIDER}, - // set bit combinations - {"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER}, - {"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)FL_WHEN_RELEASE_ALWAYS}, - {"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, - {"FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)FL_WHEN_ENTER_KEY_CHANGED}, - {0}}; - - -static Fl_Menu_Item whensymbolmenu[] = { - /* 0 */ {"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER}, - /* 1 */ {"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED}, - /* 2 */ {"FL_WHEN_NOT_CHANGED",0,0,(void*)FL_WHEN_NOT_CHANGED}, - /* 3 */ {"FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED)}, - /* 4 */ {"FL_WHEN_RELEASE",0,0,(void*)FL_WHEN_RELEASE}, - /* 5 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE)}, - /* 6 */ {"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)FL_WHEN_RELEASE_ALWAYS}, - /* 7 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE_ALWAYS)}, - /* 8 */ {"FL_WHEN_ENTER_KEY",0,0,(void*)FL_WHEN_ENTER_KEY}, - /* 9 */ {"FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, - /* 10 */ {"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, - /* 11 */ {"FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)FL_WHEN_ENTER_KEY_CHANGED}, - /* 12 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY)}, - /* 13 */ {"FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, - /* 14 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_ALWAYS)}, - /* 15 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_CHANGED)}, - {0} -}; - -// Return a text string representing the Fl_When value n -const char* when_symbol_name(int n) { - static char sym[128]; - if (n == FL_WHEN_CLOSED) { - strcpy(sym, "FL_WHEN_CLOSED"); - } else { - strcpy(sym, whensymbolmenu[n&15].label()); - if (n & FL_WHEN_CLOSED) - strcat(sym, " | FL_WHEN_CLOSED"); - } - return sym; -} - -// Set the check marks in the "when()" menu according to the Fl_When value n -void set_whenmenu(int n) { - if (n&FL_WHEN_CHANGED) whenmenu[0].set(); else whenmenu[0].clear(); - if (n&FL_WHEN_NOT_CHANGED) whenmenu[1].set(); else whenmenu[1].clear(); - if (n&FL_WHEN_RELEASE) whenmenu[2].set(); else whenmenu[2].clear(); - if (n&FL_WHEN_ENTER_KEY) whenmenu[3].set(); else whenmenu[3].clear(); - if (n&FL_WHEN_CLOSED) whenmenu[4].set(); else whenmenu[4].clear(); -} - -void when_cb(Fl_Menu_Button* i, void *v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - int n = current_widget->o->when(); - set_whenmenu(n); - w_when_box->copy_label(when_symbol_name(n)); - } else { - int mod = 0; - int n = 0; - if (i->mvalue() && ((i->mvalue()->flags & FL_MENU_TOGGLE) == 0) ) { - n = (int)i->mvalue()->argument(); - set_whenmenu(n); - } else { - if (whenmenu[0].value()) n |= FL_WHEN_CHANGED; - if (whenmenu[1].value()) n |= FL_WHEN_NOT_CHANGED; - if (whenmenu[2].value()) n |= FL_WHEN_RELEASE; - if (whenmenu[3].value()) n |= FL_WHEN_ENTER_KEY; - if (whenmenu[4].value()) n |= FL_WHEN_CLOSED; - } - w_when_box->copy_label(when_symbol_name(n)); - 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; - q->o->when(n); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -uchar Fl_Widget_Type::resizable() const { - if (is_a(ID_Window)) return ((Fl_Window*)o)->resizable() != 0; - Fl_Group* p = (Fl_Group*)o->parent(); - if (p) return p->resizable() == o; - else return 0; -} - -void Fl_Widget_Type::resizable(uchar v) { - if (v) { - if (resizable()) return; - if (is_a(ID_Window)) ((Fl_Window*)o)->resizable(o); - else { - Fl_Group* p = (Fl_Group*)o->parent(); - if (p) p->resizable(o); - } - } else { - if (!resizable()) return; - if (is_a(ID_Window)) { - ((Fl_Window*)o)->resizable(0); - } else { - Fl_Group* p = (Fl_Group*)o->parent(); - if (p) p->resizable(0); - } - } -} - -void resizable_cb(Fl_Light_Button* i,void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} - if (numselected > 1) {i->deactivate(); return;} - i->activate(); - i->value(current_widget->resizable()); - } else { - undo_checkpoint(); - current_widget->resizable(i->value()); - set_modflag(1); - } -} - -void hotspot_cb(Fl_Light_Button* i,void* v) { - if (v == LOAD) { - if (numselected > 1) {i->deactivate(); return;} - if (current_widget->is_a(ID_Menu_Item)) i->label("divider"); - else i->label("hotspot"); - i->activate(); - i->value(current_widget->hotspot()); - } else { - undo_checkpoint(); - current_widget->hotspot(i->value()); - if (current_widget->is_a(ID_Menu_Item)) { - current_widget->redraw(); - return; - } - if (i->value()) { - Fl_Type *p = current_widget->parent; - if (!p || !p->is_widget()) return; - while (!p->is_a(ID_Window)) p = p->parent; - for (Fl_Type *o = p->next; o && o->level > p->level; o = o->next) { - if (o->is_widget() && o != current_widget) - ((Fl_Widget_Type*)o)->hotspot(0); - } - } - set_modflag(1); - } -} - -void visible_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - i->value(current_widget->o->visible()); - if (current_widget->is_a(ID_Window)) i->deactivate(); - else i->activate(); - } else { - int mod = 0; - int n = i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - if (!mod) { - mod = 1; - undo_checkpoint(); - } - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - n ? q->o->show() : q->o->hide(); - q->redraw(); - if (n && q->parent && q->parent->type_name()) { - if (q->parent->is_a(ID_Tabs)) { - ((Fl_Tabs *)q->o->parent())->value(q->o); - } else if (q->parent->is_a(ID_Wizard)) { - ((Fl_Wizard *)q->o->parent())->value(q->o); - } - } - } - } - if (mod) { - set_modflag(1); - redraw_browser(); - } - } -} - -void active_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - i->value(current_widget->o->active()); - if (current_widget->is_a(ID_Window)) i->deactivate(); - else i->activate(); - } else { - int mod = 0; - int n = i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - if (!mod) { - mod = 1; - undo_checkpoint(); - } - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - n ? q->o->activate() : q->o->deactivate(); - q->redraw(); - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -Fl_Menu_Item fontmenu[] = { - {"Helvetica"}, - {"Helvetica bold"}, - {"Helvetica italic"}, - {"Helvetica bold italic"}, - {"Courier"}, - {"Courier bold"}, - {"Courier italic"}, - {"Courier bold italic"}, - {"Times"}, - {"Times bold"}, - {"Times italic"}, - {"Times bold italic"}, - {"Symbol"}, - {"Terminal"}, - {"Terminal Bold"}, - {"Zapf Dingbats"}, - {NULL} -}; - -Fl_Menu_Item fontmenu_w_default[] = { - {"", 0, NULL, NULL, FL_MENU_DIVIDER}, - {"Helvetica"}, - {"Helvetica bold"}, - {"Helvetica italic"}, - {"Helvetica bold italic"}, - {"Courier"}, - {"Courier bold"}, - {"Courier italic"}, - {"Courier bold italic"}, - {"Times"}, - {"Times bold"}, - {"Times italic"}, - {"Times bold italic"}, - {"Symbol"}, - {"Terminal"}, - {"Terminal Bold"}, - {"Zapf Dingbats"}, - {NULL} -}; - -void labelfont_cb(Fl_Choice* i, void *v) { - if (v == LOAD) { - int n = current_widget->o->labelfont(); - if (n > 15) n = 0; - i->value(n); - } else { - int mod = 0; - int n = i->value(); - if (n <= 0) n = layout->labelfont; - if (n <= 0) n = FL_HELVETICA; - 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; - q->o->labelfont(n); - q->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void labelsize_cb(Fl_Value_Input* i, void *v) { - int n; - if (v == LOAD) { - n = current_widget->o->labelsize(); - } else { - int mod = 0; - n = int(i->value()); - 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; - q->o->labelsize(n); - q->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } - i->value(n); -} - -extern const char *ui_find_image_name; - -Fl_Menu_Item labeltypemenu[] = { - {"NORMAL_LABEL",0,0,(void*)0}, - {"SHADOW_LABEL",0,0,(void*)FL_SHADOW_LABEL}, - {"ENGRAVED_LABEL",0,0,(void*)FL_ENGRAVED_LABEL}, - {"EMBOSSED_LABEL",0,0,(void*)FL_EMBOSSED_LABEL}, - {"NO_LABEL",0,0,(void*)(FL_NO_LABEL)}, -{0}}; - -void labeltype_cb(Fl_Choice* i, void *v) { - if (v == LOAD) { - int n; - n = current_widget->o->labeltype(); - i->when(FL_WHEN_RELEASE); - for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++) - if (labeltypemenu[j].argument() == n) {i->value(j); break;} - } else { - int mod = 0; - int m = i->value(); - int n = int(labeltypemenu[m].argument()); - if (n<0) return; // should not happen - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - Fl_Widget_Type* p = (Fl_Widget_Type*)o; - p->o->labeltype((Fl_Labeltype)n); - p->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -Fl_Menu_Item colormenu[] = { - { "Foreground Color", 0, 0, (void*)(fl_intptr_t)FL_FOREGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, - { "Background Color", 0, 0, (void*)(fl_intptr_t)FL_BACKGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, - { "Background Color 2", 0, 0, (void*)(fl_intptr_t)FL_BACKGROUND2_COLOR, 0, 0, FL_HELVETICA, 11}, - { "Selection Color", 0, 0, (void*)(fl_intptr_t)FL_SELECTION_COLOR, 0, 0, FL_HELVETICA, 11}, - { "Inactive Color", 0, 0, (void*)(fl_intptr_t)FL_INACTIVE_COLOR, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, - { "Black", 0, 0, (void*)(fl_intptr_t)FL_BLACK, 0, 0, FL_HELVETICA, 11}, - { "White", 0, 0, (void*)(fl_intptr_t)FL_WHITE, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, - { "Gray 0", 0, 0, (void*)(fl_intptr_t)FL_GRAY0, 0, 0, FL_HELVETICA, 11}, - { "Dark 3", 0, 0, (void*)(fl_intptr_t)FL_DARK3, 0, 0, FL_HELVETICA, 11}, - { "Dark 2", 0, 0, (void*)(fl_intptr_t)FL_DARK2, 0, 0, FL_HELVETICA, 11}, - { "Dark 1", 0, 0, (void*)(fl_intptr_t)FL_DARK1, 0, 0, FL_HELVETICA, 11}, - { "Light 1", 0, 0, (void*)(fl_intptr_t)FL_LIGHT1, 0, 0, FL_HELVETICA, 11}, - { "Light 2", 0, 0, (void*)(fl_intptr_t)FL_LIGHT2, 0, 0, FL_HELVETICA, 11}, - { "Light 3", 0, 0, (void*)(fl_intptr_t)FL_LIGHT3, 0, 0, FL_HELVETICA, 11}, - { 0 } -}; - -void color_common(Fl_Color c) { - int mod = 0; - 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; - q->o->color(c); q->o->redraw(); - if (q->parent && q->parent->is_a(ID_Tabs)) { - if (q->o->parent()) q->o->parent()->redraw(); - } - mod = 1; - } - } - if (mod) set_modflag(1); -} - -void color_cb(Fl_Button* i, void *v) { - Fl_Color c = current_widget->o->color(); - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - } else { - Fl_Color d = fl_show_colormap(c); - if (d == c) return; - c = d; - color_common(c); - } - i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); -} - -void color_menu_cb(Fl_Menu_Button* i, void *v) { - Fl_Color c = current_widget->o->color(); - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - } else { - Fl_Color d = (Fl_Color)(i->mvalue()->argument()); - if (d == c) return; - c = d; - color_common(c); - w_color->color(c); w_color->labelcolor(fl_contrast(FL_BLACK,c)); w_color->redraw(); - } -} - -void color2_common(Fl_Color c) { - int mod = 0; - 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; - q->o->selection_color(c); q->o->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); -} - -void color2_cb(Fl_Button* i, void *v) { - Fl_Color c = current_widget->o->selection_color(); - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - } else { - Fl_Color d = fl_show_colormap(c); - if (d == c) return; - c = d; - color2_common(c); - } - i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); -} - -void color2_menu_cb(Fl_Menu_Button* i, void *v) { - Fl_Color c = current_widget->o->selection_color(); - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - } else { - Fl_Color d = (Fl_Color)(i->mvalue()->argument()); - if (d == c) return; - c = d; - color2_common(c); - w_selectcolor->color(c); w_selectcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_selectcolor->redraw(); - } -} - -void labelcolor_common(Fl_Color c) { - int mod = 0; - 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; - q->o->labelcolor(c); q->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); -} - -void labelcolor_cb(Fl_Button* i, void *v) { - Fl_Color c = current_widget->o->labelcolor(); - if (v != LOAD) { - Fl_Color d = fl_show_colormap(c); - if (d == c) return; - c = d; - labelcolor_common(c); - } - i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); -} - -void labelcolor_menu_cb(Fl_Menu_Button* i, void *v) { - Fl_Color c = current_widget->o->labelcolor(); - if (v != LOAD) { - Fl_Color d = (Fl_Color)(i->mvalue()->argument()); - if (d == c) return; - c = d; - labelcolor_common(c); - w_labelcolor->color(c); w_labelcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_labelcolor->redraw(); - } -} - -static Fl_Button* relative(Fl_Widget* o, int i) { - Fl_Group* g = (Fl_Group*)(o->parent()); - return (Fl_Button*)(g->child(g->find(*o)+i)); -} - -static Fl_Menu_Item alignmenu[] = { - {"FL_ALIGN_CENTER",0,0,(void*)(fl_intptr_t)(FL_ALIGN_CENTER)}, - {"FL_ALIGN_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP)}, - {"FL_ALIGN_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM)}, - {"FL_ALIGN_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT)}, - {"FL_ALIGN_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT)}, - {"FL_ALIGN_INSIDE",0,0,(void*)(fl_intptr_t)(FL_ALIGN_INSIDE)}, - {"FL_ALIGN_CLIP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_CLIP)}, - {"FL_ALIGN_WRAP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_WRAP)}, - {"FL_ALIGN_TEXT_OVER_IMAGE",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TEXT_OVER_IMAGE)}, - {"FL_ALIGN_TOP_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP_LEFT)}, - {"FL_ALIGN_TOP_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_TOP_RIGHT)}, - {"FL_ALIGN_BOTTOM_LEFT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_LEFT)}, - {"FL_ALIGN_BOTTOM_RIGHT",0,0,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_RIGHT)}, - {"FL_ALIGN_LEFT_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_TOP)}, - {"FL_ALIGN_RIGHT_TOP",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_TOP)}, - {"FL_ALIGN_LEFT_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_BOTTOM)}, - {"FL_ALIGN_RIGHT_BOTTOM",0,0,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_BOTTOM)}, -{0}}; - -void align_cb(Fl_Button* i, void *v) { - Fl_Align b = Fl_Align(fl_uintptr_t(i->user_data())); - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - i->value(current_widget->o->align() & b); - } else { - int mod = 0; - undo_checkpoint(); - 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; - Fl_Align x = q->o->align(); - Fl_Align y; - if (i->value()) { - y = x | b; - if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) { - Fl_Button *b1 = relative(i,+1); - b1->clear(); - y = y & ~(b1->argument()); - } - if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) { - Fl_Button *b1 = relative(i,-1); - b1->clear(); - y = y & ~(b1->argument()); - } - } else { - y = x & ~b; - } - if (x != y) { - q->o->align(y); - q->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void align_position_cb(Fl_Choice *i, void *v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); - Fl_Align b = current_widget->o->align() & FL_ALIGN_POSITION_MASK; - for (;mi->text;mi++) { - if ((Fl_Align)(mi->argument())==b) - i->value(mi); - } - } else { - const Fl_Menu_Item *mi = i->menu() + i->value(); - Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); - int mod = 0; - undo_checkpoint(); - 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; - Fl_Align x = q->o->align(); - Fl_Align y = (x & ~FL_ALIGN_POSITION_MASK) | b; - if (x != y) { - q->o->align(y); - q->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void align_text_image_cb(Fl_Choice *i, void *v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); - Fl_Align b = current_widget->o->align() & FL_ALIGN_IMAGE_MASK; - for (;mi->text;mi++) { - if ((Fl_Align)(mi->argument())==b) - i->value(mi); - } - } else { - const Fl_Menu_Item *mi = i->menu() + i->value(); - Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); - int mod = 0; - undo_checkpoint(); - 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; - Fl_Align x = q->o->align(); - Fl_Align y = (x & ~FL_ALIGN_IMAGE_MASK) | b; - if (x != y) { - q->o->align(y); - q->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -void callback_cb(fld::widget::Code_Editor* i, void *v) { - if (v == LOAD) { - const char *cbtext = current_widget->callback(); - i->buffer()->text( cbtext ? cbtext : "" ); - } else { - int mod = 0; - char *c = i->buffer()->text(); - const char *d = c_check(c); - if (d) { - fl_message("Error in callback: %s",d); - if (i->window()) i->window()->make_current(); - haderror = 1; - } - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - o->callback(c); - mod = 1; - } - } - if (mod) set_modflag(1); - free(c); - } -} - -void comment_cb(Fl_Text_Editor* i, void *v) { - if (v == LOAD) { - const char *cmttext = current_widget->comment(); - i->buffer()->text( cmttext ? cmttext : "" ); - } else { - int mod = 0; - char *c = i->buffer()->text(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - o->comment(c); - mod = 1; - } - } - if (mod) set_modflag(1); - free(c); - } -} - -void user_data_cb(Fl_Input *i, void *v) { - if (v == LOAD) { - i->value(current_widget->user_data()); - } else { - int mod = 0; - const char *c = i->value(); - const char *d = c_check(c); - if (d) {fl_message("Error in user_data: %s",d); haderror = 1; return;} - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - o->user_data(c); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void user_data_type_cb(Fl_Input_Choice *i, void *v) { - static const char *dflt = "void*"; - if (v == LOAD) { - const char *c = current_widget->user_data_type(); - if (!c) c = dflt; - i->value(c); - } else { - int mod = 0; - const char *c = i->value(); - const char *d = c_check(c); - if (!*c) i->value(dflt); - else if (!strcmp(c,dflt)) c = 0; - if (!d) { - if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) - d = "must be pointer or long"; - } - if (d) {fl_message("Error in type: %s",d); haderror = 1; return;} - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected) { - o->user_data_type(c); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -// "v_attributes" let user type in random code for attribute settings: - -void v_input_cb(Fl_Input* i, void* v) { - int n = fl_int(i->user_data()); - if (v == LOAD) { - i->value(current_widget->extra_code(n)); - } else { - int mod = 0; - const char *c = i->value(); - const char *d = c_check(c&&c[0]=='#' ? c+1 : c); - if (d) {fl_message("Error in %s: %s",i->label(),d); haderror = 1; return;} - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - Fl_Widget_Type *t = (Fl_Widget_Type*)o; - t->extra_code(n,c); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void subclass_cb(Fl_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Menu_Item)) {i->deactivate(); return;} else i->activate(); - i->value(current_widget->subclass()); - } else { - int mod = 0; - const char *c = i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget()) { - Fl_Widget_Type *t = (Fl_Widget_Type*)o; - t->subclass(c); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -// textstuff: set textfont, textsize, textcolor attributes: - -// default widget returns 0 to indicate not-implemented: -// The first parameter specifies the operation: -// 0: get all values -// 1: set the text font -// 2: set the text size -// 3: set the text color -// 4: get all default values for this type -int Fl_Widget_Type::textstuff(int, Fl_Font&, int&, Fl_Color&) { - return 0; -} - -void textfont_cb(Fl_Choice* i, void* v) { - Fl_Font n; int s; Fl_Color c; - if (v == LOAD) { - if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} - i->activate(); - if (n > 15) n = FL_HELVETICA; - i->value(n); - } 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; - q->textstuff(1,n,s,c); - q->o->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void textsize_cb(Fl_Value_Input* i, void* v) { - Fl_Font n; int s; Fl_Color c; - if (v == LOAD) { - if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} - i->activate(); - } else { - int mod = 0; - s = int(i->value()); - if (s <= 0) s = layout->textsize; - if (s <= 0) s = 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; - q->textstuff(2,n,s,c); - q->o->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); - } - i->value(s); -} - -void textcolor_common(Fl_Color c) { - Fl_Font n; int s; - int mod = 0; - 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; - q->textstuff(3,n,s,c); q->o->redraw(); - mod = 1; - } - } - if (mod) set_modflag(1); -} - -void textcolor_cb(Fl_Button* i, void* v) { - Fl_Font n; int s; Fl_Color c; - if (v == LOAD) { - if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} - i->activate(); - } else { - c = i->color(); - Fl_Color d = fl_show_colormap(c); - if (d == c) return; - c = d; - textcolor_common(c); - } - i->color(c); i->labelcolor(fl_contrast(FL_BLACK,c)); i->redraw(); -} - -void textcolor_menu_cb(Fl_Menu_Button* i, void* v) { - Fl_Font n; int s; Fl_Color c; - if (v == LOAD) { - if (!current_widget->textstuff(0,n,s,c)) {i->deactivate(); return;} - i->activate(); - } else { - c = i->color(); - Fl_Color d = (Fl_Color)(i->mvalue()->argument()); - if (d == c) return; - c = d; - textcolor_common(c); - w_textcolor->color(c); w_textcolor->labelcolor(fl_contrast(FL_BLACK,c)); w_textcolor->redraw(); - } -} - -void image_spacing_cb(Fl_Value_Input* i, void* v) { - int s; - if (v == LOAD) { - if (!current_widget->is_true_widget()) { - i->deactivate(); - i->value(0); - } else { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->o->label_image_spacing()); - } - } else { - int mod = 0; - s = int(i->value()); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - if (q->o->label_image_spacing() != s) { - q->o->label_image_spacing(s); - if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) - q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void h_label_margin_cb(Fl_Value_Input* i, void* v) { - int s; - if (v == LOAD) { - if (!current_widget->is_true_widget()) { - i->deactivate(); - i->value(0); - } else { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->o->horizontal_label_margin()); - } - } else { - int mod = 0; - s = int(i->value()); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - if (q->o->horizontal_label_margin() != s) { - q->o->horizontal_label_margin(s); - if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) - q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void v_label_margin_cb(Fl_Value_Input* i, void* v) { - int s; - if (v == LOAD) { - if (!current_widget->is_true_widget()) { - i->deactivate(); - i->value(0); - } else { - i->activate(); - i->value(((Fl_Widget_Type*)current_widget)->o->vertical_label_margin()); - } - } else { - int mod = 0; - s = int(i->value()); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_true_widget()) { - Fl_Widget_Type* q = (Fl_Widget_Type*)o; - if (q->o->vertical_label_margin() != s) { - q->o->vertical_label_margin(s); - if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) - q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// -// Kludges to the panel for subclasses: - -void min_w_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) return; - i->value(((Fl_Window_Type*)current_widget)->sr_min_w); - } else { - int mod = 0; - undo_checkpoint(); - int n = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - ((Fl_Window_Type*)current_widget)->sr_min_w = n; - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void min_h_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) return; - i->value(((Fl_Window_Type*)current_widget)->sr_min_h); - } else { - int mod = 0; - undo_checkpoint(); - int n = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - ((Fl_Window_Type*)current_widget)->sr_min_h = n; - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void max_w_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) return; - i->value(((Fl_Window_Type*)current_widget)->sr_max_w); - } else { - int mod = 0; - undo_checkpoint(); - int n = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - ((Fl_Window_Type*)current_widget)->sr_max_w = n; - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void max_h_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) return; - i->value(((Fl_Window_Type*)current_widget)->sr_max_h); - } else { - int mod = 0; - undo_checkpoint(); - int n = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - ((Fl_Window_Type*)current_widget)->sr_max_h = n; - mod = 1; - } - } - if (mod) set_modflag(1); - } -} - -void set_min_size_cb(Fl_Button*, void* v) { - if (v == LOAD) { - } else { - int mod = 0; - undo_checkpoint(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - Fl_Window_Type *win = (Fl_Window_Type*)current_widget; - win->sr_min_w = win->o->w(); - win->sr_min_h = win->o->h(); - mod = 1; - } - } - propagate_load(the_panel, LOAD); - if (mod) set_modflag(1); - } -} - -void set_max_size_cb(Fl_Button*, void* v) { - if (v == LOAD) { - } else { - int mod = 0; - undo_checkpoint(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - Fl_Window_Type *win = (Fl_Window_Type*)current_widget; - win->sr_max_w = win->o->w(); - win->sr_max_h = win->o->h(); - mod = 1; - } - } - propagate_load(the_panel, LOAD); - if (mod) set_modflag(1); - } -} - -void slider_size_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Slider)) {i->deactivate(); return;} - i->activate(); - i->value(((Fl_Slider*)(current_widget->o))->slider_size()); - } else { - int mod = 0; - undo_checkpoint(); - double n = i->value(); - 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; - if (q->is_a(ID_Slider)) { - ((Fl_Slider*)(q->o))->slider_size(n); - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void min_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Valuator_)) { - i->activate(); - i->value(((Fl_Valuator*)(current_widget->o))->minimum()); - } else if (current_widget->is_a(ID_Spinner)) { - i->activate(); - i->value(((Fl_Spinner*)(current_widget->o))->minimum()); - } else { - i->deactivate(); - return; - } - } else { - int mod = 0; - undo_checkpoint(); - double n = i->value(); - 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; - if (q->is_a(ID_Valuator_)) { - ((Fl_Valuator*)(q->o))->minimum(n); - q->o->redraw(); - mod = 1; - } else if (q->is_a(ID_Spinner)) { - ((Fl_Spinner*)(q->o))->minimum(n); - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void max_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Valuator_)) { - i->activate(); - i->value(((Fl_Valuator*)(current_widget->o))->maximum()); - } else if (current_widget->is_a(ID_Spinner)) { - i->activate(); - i->value(((Fl_Spinner*)(current_widget->o))->maximum()); - } else { - i->deactivate(); - return; - } - } else { - int mod = 0; - undo_checkpoint(); - double n = i->value(); - 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; - if (q->is_a(ID_Valuator_)) { - ((Fl_Valuator*)(q->o))->maximum(n); - q->o->redraw(); - mod = 1; - } else if (q->is_a(ID_Spinner)) { - ((Fl_Spinner*)(q->o))->maximum(n); - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void step_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Valuator_)) { - i->activate(); - i->value(((Fl_Valuator*)(current_widget->o))->step()); - } else if (current_widget->is_a(ID_Spinner)) { - i->activate(); - i->value(((Fl_Spinner*)(current_widget->o))->step()); - } else { - i->deactivate(); - return; - } - } else { - int mod = 0; - undo_checkpoint(); - double n = i->value(); - 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; - if (q->is_a(ID_Valuator_)) { - ((Fl_Valuator*)(q->o))->step(n); - q->o->redraw(); - mod = 1; - } else if (q->is_a(ID_Spinner)) { - ((Fl_Spinner*)(q->o))->step(n); - q->o->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -void value_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Valuator_)) { - i->activate(); - i->value(((Fl_Valuator*)(current_widget->o))->value()); - } else if (current_widget->is_button()) { - i->activate(); - i->value(((Fl_Button*)(current_widget->o))->value()); - } else if (current_widget->is_a(ID_Spinner)) { - i->activate(); - i->value(((Fl_Spinner*)(current_widget->o))->value()); - } else - i->deactivate(); - } else { - int mod = 0; - undo_checkpoint(); - double n = i->value(); - 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; - if (q->is_a(ID_Valuator_)) { - ((Fl_Valuator*)(q->o))->value(n); - mod = 1; - } else if (q->is_button()) { - ((Fl_Button*)(q->o))->value(n != 0); - if (q->is_a(ID_Menu_Item)) q->redraw(); - mod = 1; - } else if (q->is_a(ID_Spinner)) { - ((Fl_Spinner*)(q->o))->value(n); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -// The following three callbacks cooperate, showing only one of the groups of -// widgets that use the same space in the dialog. - -void values_group_cb(Fl_Group* g, void* v) { - if (v == LOAD) { - if ( current_widget->is_a(ID_Flex) - || current_widget->is_a(ID_Grid) - || current_widget->is_a(ID_Window)) - { - g->hide(); - } else { - g->show(); - } - propagate_load(g, v); - } -} - -void flex_margin_group_cb(Fl_Group* g, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Flex)) { - g->show(); - } else { - g->hide(); - } - propagate_load(g, v); - } -} - -void size_range_group_cb(Fl_Group* g, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Window)) { - g->show(); - } else { - g->hide(); - } - propagate_load(g, v); - } -} - - -static void flex_margin_cb(Fl_Value_Input* i, void* v, - void (*load_margin)(Fl_Flex*,Fl_Value_Input*), - int (*update_margin)(Fl_Flex*,int)) { - if (v == LOAD) { - if (current_widget->is_a(ID_Flex)) { - load_margin((Fl_Flex*)current_widget->o, i); - } - } else { - int mod = 0; - int new_value = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Flex)) { - Fl_Flex_Type* q = (Fl_Flex_Type*)o; - Fl_Flex* w = (Fl_Flex*)q->o; - if (update_margin(w, new_value)) { - w->layout(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -static void load_left_margin(Fl_Flex *w, Fl_Value_Input* i) -{ - int v; - w->margin(&v, NULL, NULL, NULL); - i->value((double)v); -} - -static int update_left_margin(Fl_Flex *w, int new_value) -{ - int l, t, r, b; - w->margin(&l, &t, &r, &b); - if (new_value!=l) { - w->margin(new_value, t, r, b); - return 1; - } else { - return 0; - } -} - -void flex_margin_left_cb(Fl_Value_Input* i, void* v) { - flex_margin_cb(i, v, load_left_margin, update_left_margin); -} - -static void load_top_margin(Fl_Flex *w, Fl_Value_Input* i) -{ - int v; - w->margin(NULL, &v, NULL, NULL); - i->value((double)v); -} - -static int update_top_margin(Fl_Flex *w, int new_value) -{ - int l, t, r, b; - w->margin(&l, &t, &r, &b); - if (new_value!=t) { - w->margin(l, new_value, r, b); - return 1; - } else { - return 0; - } -} - -void flex_margin_top_cb(Fl_Value_Input* i, void* v) { - flex_margin_cb(i, v, load_top_margin, update_top_margin); -} - -static void load_right_margin(Fl_Flex *w, Fl_Value_Input* i) -{ - int v; - w->margin(NULL, NULL, &v, NULL); - i->value((double)v); -} - -static int update_right_margin(Fl_Flex *w, int new_value) -{ - int l, t, r, b; - w->margin(&l, &t, &r, &b); - if (new_value!=r) { - w->margin(l, t, new_value, b); - return 1; - } else { - return 0; - } -} - -void flex_margin_right_cb(Fl_Value_Input* i, void* v) { - flex_margin_cb(i, v, load_right_margin, update_right_margin); -} - -static void load_bottom_margin(Fl_Flex *w, Fl_Value_Input* i) -{ - int v; - w->margin(NULL, NULL, NULL, &v); - i->value((double)v); -} - -static int update_bottom_margin(Fl_Flex *w, int new_value) -{ - int l, t, r, b; - w->margin(&l, &t, &r, &b); - if (new_value!=b) { - w->margin(l, t, r, new_value); - return 1; - } else { - return 0; - } -} - -void flex_margin_bottom_cb(Fl_Value_Input* i, void* v) { - flex_margin_cb(i, v, load_bottom_margin, update_bottom_margin); -} - -static void load_gap(Fl_Flex *w, Fl_Value_Input* i) -{ - int v = w->gap(); - i->value((double)v); -} - -static int update_gap(Fl_Flex *w, int new_value) -{ - int g = w->gap(); - if (new_value!=g) { - w->gap(new_value); - return 1; - } else { - return 0; - } -} - -void flex_margin_gap_cb(Fl_Value_Input* i, void* v) { - flex_margin_cb(i, v, load_gap, update_gap); -} - -void position_group_cb(Fl_Group* g, void* v) { - if (v == LOAD) { - if (Fl_Flex_Type::parent_is_flex(current_widget)) { - g->hide(); - } else { - g->show(); - } - } - propagate_load(g, v); -} - -void flex_size_group_cb(Fl_Group* g, void* v) { - if (v == LOAD) { - if (Fl_Flex_Type::parent_is_flex(current_widget)) { - g->show(); - } else { - g->hide(); - } - } - propagate_load(g, v); -} - -void flex_size_cb(Fl_Value_Input* i, void* v) { - if (v == LOAD) { - if (Fl_Flex_Type::parent_is_flex(current_widget)) { - i->value(Fl_Flex_Type::size(current_widget)); - } - } else { - int mod = 0; - int new_size = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) { - Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o; - Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o; - int was_fixed = f->fixed(w); - if (new_size==0) { - if (was_fixed) { - f->fixed(w, 0); - f->layout(); - widget_flex_fixed->value(0); - mod = 1; - } - } else { - int old_size = Fl_Flex_Type::size(o); - if (old_size!=new_size || !was_fixed) { - f->fixed(w, new_size); - f->layout(); - widget_flex_fixed->value(1); - mod = 1; - } - } - } - } - if (mod) set_modflag(1); - } -} - -void flex_fixed_cb(Fl_Check_Button* i, void* v) { - if (v == LOAD) { - if (Fl_Flex_Type::parent_is_flex(current_widget)) { - i->value(Fl_Flex_Type::is_fixed(current_widget)); - } - } else { - int mod = 0; - int new_fixed = (int)i->value(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) { - Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o; - Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o; - int was_fixed = f->fixed(w); - if (new_fixed==0) { - if (was_fixed) { - f->fixed(w, 0); - f->layout(); - mod = 1; - } - } else { - if (!was_fixed) { - f->fixed(w, Fl_Flex_Type::size(o)); - f->layout(); - mod = 1; - } - } - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -// subtypes: - -Fl_Menu_Item *Fl_Widget_Type::subtypes() {return 0;} - -void subtype_cb(Fl_Choice* i, void* v) { - static Fl_Menu_Item empty_type_menu[] = { - {"Normal",0,0,(void*)0}, - {0}}; - - if (v == LOAD) { - Fl_Menu_Item* m = current_widget->subtypes(); - if (!m) { - i->menu(empty_type_menu); - i->value(0); - i->deactivate(); - } else { - i->menu(m); - int j; - for (j = 0;; j++) { - if (!m[j].text) {j = 0; break;} - if (current_widget->is_a(ID_Spinner)) { - if (m[j].argument() == ((Fl_Spinner*)current_widget->o)->type()) break; - } else { - if (m[j].argument() == current_widget->o->type()) break; - } - } - i->value(j); - i->activate(); - } - i->redraw(); - } else { - int mod = 0; - int n = int(i->mvalue()->argument()); - Fl_Menu_Item* m = current_widget->subtypes(); - 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; - if (q->subtypes()==m) { - if (q->is_a(ID_Spinner)) - ((Fl_Spinner*)q->o)->type(n); - else if (q->is_a(ID_Flex)) - ((Fl_Flex_Type*)q)->change_subtype_to(n); - else - q->o->type(n); - q->redraw(); - mod = 1; - } - } - } - if (mod) set_modflag(1); - } -} - -//////////////////////////////////////////////////////////////// - -void propagate_load(Fl_Group* g, void* v) { - if (v == LOAD) { - Fl_Widget*const* a = g->array(); - for (int i=g->children(); i--;) { - Fl_Widget* o = *a++; - o->do_callback(o, LOAD, FL_REASON_USER); - } - } -} - -void set_cb(Fl_Button*, void*) { - haderror = 0; - Fl_Widget*const* a = the_panel->array(); - for (int i=the_panel->children(); i--;) { - Fl_Widget* o = *a++; - if (o->changed()) { - o->do_callback(); - if (haderror) return; - o->clear_changed(); - } - } -} - -void ok_cb(Fl_Return_Button* o, void* v) { - set_cb(o,v); - if (!haderror) the_panel->hide(); -} - -void toggle_overlays(Fl_Widget *,void *); // in Fl_Window_Type.cxx -void overlay_cb(Fl_Button*o,void *v) { - toggle_overlays(o,v); -} - -void leave_live_mode_cb(Fl_Widget*, void*); - -void live_mode_cb(Fl_Button*o,void *) { - /// \todo live mode should end gracefully when the application quits - /// or when the user closes the live widget - static Fl_Type *live_type = 0L; - static Fl_Widget *live_widget = 0L; - static Fl_Window *live_window = 0L; - // if 'o' is 0, we must quit live mode - if (!o) { - o = wLiveMode; - o->value(0); - } - if (o->value()) { - if (numselected == 1) { - Fl_Group::current(0L); - live_widget = current_widget->enter_live_mode(1); - if (live_widget) { - live_type = current_widget; - Fl_Group::current(0); - int w = live_widget->w(); - int h = live_widget->h(); - live_window = new Fl_Double_Window(w+20, h+55, "Fluid Live Resize"); - live_window->box(FL_FLAT_BOX); - live_window->color(FL_GREEN); - Fl_Group *rsz = new Fl_Group(0, h+20, 130, 35); - rsz->box(FL_NO_BOX); - Fl_Box *rsz_dummy = new Fl_Box(110, h+20, 1, 25); - rsz_dummy->box(FL_NO_BOX); - rsz->resizable(rsz_dummy); - Fl_Button *btn = new Fl_Button(10, h+20, 100, 25, "Exit Live Resize"); - btn->labelsize(12); - btn->callback(leave_live_mode_cb); - rsz->end(); - live_window->add(live_widget); - live_widget->position(10, 10); - live_window->resizable(live_widget); - live_window->set_modal(); // block all other UI - live_window->callback(leave_live_mode_cb); - if (current_widget->is_a(ID_Window)) { - Fl_Window_Type *w = (Fl_Window_Type*)current_widget; - int mw = w->sr_min_w; if (mw>0) mw += 20; - int mh = w->sr_min_h; if (mh>0) mh += 55; - int MW = w->sr_max_w; if (MW>0) MW += 20; - int MH = w->sr_max_h; if (MH>2) MH += 55; - if (mw || mh || MW || MH) - live_window->size_range(mw, mh, MW, MH); - } - live_window->show(); - live_widget->show(); - } else o->value(0); - } else o->value(0); - } else { - if (live_type) - live_type->leave_live_mode(); - if (live_window) { - live_window->hide(); - Fl::delete_widget(live_window); - } - live_type = 0L; - live_widget = 0L; - live_window = 0L; - } -} - -// update the panel according to current widget set: -void load_panel() { - if (!the_panel) return; - - // find all the Fl_Widget subclasses currently selected: - numselected = 0; - current_widget = 0; - if (Fl_Type::current) { - if (Fl_Type::current->is_widget()) - current_widget=(Fl_Widget_Type*)Fl_Type::current; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->is_widget() && o->selected) { - numselected++; - if (!current_widget) current_widget = (Fl_Widget_Type*)o; - } - } - } - if (current_widget && current_widget->is_a(ID_Grid)) { - if (widget_tab_grid->parent()!=widget_tabs) - widget_tabs->add(widget_tab_grid); - } else { - if (widget_tab_grid->parent()==widget_tabs) { - widget_tabs_repo->add(widget_tab_grid); - } - } - if (current_widget && current_widget->parent && current_widget->parent->is_a(ID_Grid)) { - if (widget_tab_grid_child->parent()!=widget_tabs) - widget_tabs->add(widget_tab_grid_child); - } else { - if (widget_tab_grid_child->parent()==widget_tabs) { - widget_tabs_repo->add(widget_tab_grid_child); - } - } - if (numselected) - propagate_load(the_panel, LOAD); - else - 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() { - bool adjust_position = false; - if (!the_panel) { - the_panel = make_widget_panel(); - adjust_position = true; - } - load_panel(); - 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(); -extern void check_redraw_corresponding_parent(Fl_Type*); -extern void redraw_browser(); -extern void update_codeview_position(); - -// Called when ui changes what objects are selected: -// p is selected object, null for all deletions (we must throw away -// old panel in that case, as the object may no longer exist) -void selection_changed(Fl_Type *p) { - // store all changes to the current selected objects: - if (p && the_panel && the_panel->visible()) { - set_cb(0,0); - // if there was an error, we try to leave the selected set unchanged: - if (haderror) { - Fl_Type *q = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - o->new_selected = o->selected; - if (!q && o->selected) q = o; - } - if (!p || !p->selected) p = q; - Fl_Type::current = p; - redraw_browser(); - return; - } - } - // update the selected flags to new set: - Fl_Type *q = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - o->selected = o->new_selected; - if (!q && o->selected) q = o; - } - if (!p || !p->selected) p = q; - Fl_Type::current = p; - check_redraw_corresponding_parent(p); - redraw_overlays(); - // load the panel with the new settings: - load_panel(); - // update the code viewer to show the code for the selected object - update_codeview_position(); -} - -//////////////////////////////////////////////////////////////// -// Writing the C code: - -// test to see if user named a function, or typed in code: -int is_name(const char *c) { - for (; *c; c++) - if ((ispunct(*c)||*c=='\n') && *c!='_' && *c!=':') return 0; - return 1; -} - -// Test to see if name() is an array entry. If so, and this is the -// highest number, return name[num+1]. Return null if not the highest -// number or a field or function. Return name() if not an array entry. -const char *array_name(Fl_Widget_Type *o) { - const char *c = o->name(); - if (!c) return 0; - const char *d; - for (d = c; *d != '['; d++) { - if (!*d) return c; - if (ispunct(*d) && *d!='_') return 0; - } - int num = atoi(d+1); - int sawthis = 0; - Fl_Type *t = o->prev; - Fl_Type *tp = o; - const char *cn = o->class_name(1); - for (; t && t->class_name(1) == cn; tp = t, t = t->prev) {/*empty*/} - for (t = tp; t && t->class_name(1) == cn; t = t->next) { - if (t == o) {sawthis=1; continue;} - const char *e = t->name(); - if (!e) continue; - if (strncmp(c,e,d-c)) continue; - int n1 = atoi(e+(d-c)+1); - if (n1 > num || (n1==num && sawthis)) return 0; - } - static char buffer[128]; - // MRS: we want strncpy() here... - strncpy(buffer,c,d-c+1); - snprintf(buffer+(d-c+1),sizeof(buffer) - (d-c+1), "%d]",num+1); - return buffer; -} - -// Test to see if extra code is a declaration: -int isdeclare(const char *c) { - while (isspace(*c)) c++; - if (*c == '#') return 1; - if (!strncmp(c,"extern",6)) return 1; - if (!strncmp(c,"typedef",7)) return 1; - if (!strncmp(c,"using",5)) return 1; - return 0; -} - -void Fl_Widget_Type::write_static(fld::io::Code_Writer& f) { - const char* t = subclassname(this); - if (!subclass() || (is_class() && !strncmp(t, "Fl_", 3))) { - f.write_h_once("#include "); - f.write_h_once("#include ", t); - } - for (int n=0; n < NUM_EXTRA_CODE; n++) { - if (extra_code(n) && isdeclare(extra_code(n))) - f.write_h_once("%s", extra_code(n)); - } - if (callback() && is_name(callback())) { - int write_extern_declaration = 1; - char buf[1024]; snprintf(buf, 1023, "%s(*)", callback()); - if (is_in_class()) { - if (has_function("static void", buf)) - write_extern_declaration = 0; - } else { - if (has_toplevel_function(0L, buf)) - write_extern_declaration = 0; - } - if (write_extern_declaration) - f.write_h_once("extern void %s(%s*, %s);", callback(), t, - user_data_type() ? user_data_type() : "void*"); - } - const char* k = class_name(1); - const char* c = array_name(this); - if (c && !k && !is_class()) { - f.write_c("\n"); - if (!public_) f.write_c("static "); - else f.write_h("extern %s *%s;\n", t, c); - if (strchr(c, '[') == NULL) f.write_c("%s *%s=(%s *)0;\n", t, c, t); - else f.write_c("%s *%s={(%s *)0};\n", t, c, t); - } - if (callback() && !is_name(callback())) { - // see if 'o' or 'v' used, to prevent unused argument warnings: - int use_o = 0; - int use_v = 0; - const char *d; - for (d = callback(); *d;) { - if (*d == 'o' && !is_id(d[1])) use_o = 1; - if (*d == 'v' && !is_id(d[1])) use_v = 1; - do d++; while (is_id(*d)); - while (*d && !is_id(*d)) d++; - } - const char* cn = callback_name(f); - if (k) { - f.write_c("\nvoid %s::%s_i(%s*", k, cn, t); - } else { - f.write_c("\nstatic void %s(%s*", cn, t); - } - if (use_o) f.write_c(" o"); - const char* ut = user_data_type() ? user_data_type() : "void*"; - f.write_c(", %s", ut); - if (use_v) f.write_c(" v"); - f.write_c(") {\n"); - // Matt: disabled f.tag(FD_TAG_GENERIC, 0); - f.write_c_indented(callback(), 1, 0); - if (*(d-1) != ';' && *(d-1) != '}') { - const char *p = strrchr(callback(), '\n'); - if (p) p ++; - else p = callback(); - // Only add trailing semicolon if the last line is not a preprocessor - // statement... - if (*p != '#' && *p) f.write_c(";"); - } - f.write_c("\n"); - // Matt: disabled f.tag(FD_TAG_WIDGET_CALLBACK, get_uid()); - f.write_c("}\n"); - if (k) { - f.write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut); - f.write_c("%s((%s*)(o", f.indent(1), k); - Fl_Type *q = 0; - for (Fl_Type* p = parent; p && p->is_widget(); q = p, p = p->parent) - f.write_c("->parent()"); - if (!q || !q->is_a(ID_Widget_Class)) - f.write_c("->user_data()"); - f.write_c("))->%s_i(o,v);\n}\n", cn); - } - } - if (image) { - if (!f.c_contains(image)) - image->write_static(f, compress_image_); - } - if (inactive) { - if (!f.c_contains(inactive)) - inactive->write_static(f, compress_deimage_); - } -} - -void Fl_Widget_Type::write_code1(fld::io::Code_Writer& f) { - const char* t = subclassname(this); - const char *c = array_name(this); - if (c) { - if (class_name(1)) { - f.write_public(public_); - f.write_h("%s%s *%s;\n", f.indent(1), t, c); - } - } - if (class_name(1) && callback() && !is_name(callback())) { - const char* cn = callback_name(f); - const char* ut = user_data_type() ? user_data_type() : "void*"; - f.write_public(0); - f.write_h("%sinline void %s_i(%s*, %s);\n", f.indent(1), cn, t, ut); - f.write_h("%sstatic void %s(%s*, %s);\n", f.indent(1), cn, t, ut); - } - // figure out if local variable will be used (prevent compiler warnings): - int wused = !name() && is_a(ID_Window); - const char *ptr; - - f.varused = wused; - - if (!name() && !f.varused) { - f.varused |= can_have_children(); - - if (!f.varused) { - f.varused_test = 1; - write_widget_code(f); - f.varused_test = 0; - } - } - - if (!f.varused) { - for (int n=0; n < NUM_EXTRA_CODE; n++) - if (extra_code(n) && !isdeclare(extra_code(n))) - { - int instring = 0; - int inname = 0; - int incomment = 0; - int incppcomment = 0; - for (ptr = extra_code(n); *ptr; ptr ++) { - if (instring) { - if (*ptr == '\\') ptr++; - else if (*ptr == '\"') instring = 0; - } else if (inname && !isalnum(*ptr & 255)) { - inname = 0; - } else if (*ptr == '/' && ptr[1]=='*') { - incomment = 1; ptr++; - } else if (incomment) { - if (*ptr == '*' && ptr[1]=='/') { - incomment = 0; ptr++; - } - } else if (*ptr == '/' && ptr[1]=='/') { - incppcomment = 1; ptr++; - } else if (incppcomment) { - if (*ptr == '\n') - incppcomment = 0; - } else if (*ptr == '\"') { - instring = 1; - } else if (isalnum(*ptr & 255) || *ptr == '_') { - size_t len = strspn(ptr, "0123456789_" - "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - if (!strncmp(ptr, "o", len)) { - f.varused = 1; - break; - } else { - ptr += len - 1; - } - } - } - } - } - - f.write_c("%s{ ", f.indent()); - write_comment_inline_c(f); - if (f.varused) f.write_c("%s* o = ", t); - if (name()) f.write_c("%s = ", name()); - if (is_a(ID_Window)) { - // Handle special case where user is faking a Fl_Group type as a window, - // there is no 2-argument constructor in that case: - if (!strstr(t, "Window")) - f.write_c("new %s(0, 0, %d, %d", t, o->w(), o->h()); - else - f.write_c("new %s(%d, %d", t, o->w(), o->h()); - } else if (is_a(ID_Menu_Bar) - && ((Fl_Menu_Bar_Type*)this)->is_sys_menu_bar() - && is_in_class()) { - f.write_c("(%s*)new %s(%d, %d, %d, %d", - t, ((Fl_Menu_Bar_Type*)this)->sys_menubar_proxy_name(), - o->x(), o->y(), o->w(), o->h()); - } else { - f.write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h()); - } - if (label() && *label()) { - f.write_c(", "); - switch (g_project.i18n_type) { - case FD_I18N_NONE : /* None */ - f.write_cstring(label()); - break; - case FD_I18N_GNU : /* GNU gettext */ - f.write_c("%s(", g_project.i18n_gnu_function.c_str()); - f.write_cstring(label()); - f.write_c(")"); - break; - case FD_I18N_POSIX : /* POSIX catgets */ - f.write_c("catgets(%s,%s,%d,", - g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), - g_project.i18n_pos_set.c_str(), msgnum()); - f.write_cstring(label()); - f.write_c(")"); - break; - } - } - f.write_c(");\n"); - - f.indentation++; - - // Avoid compiler warning for unused variable. - // Also avoid quality control warnings about incorrect allocation error handling. - if (wused) f.write_c("%sw = o; (void)w;\n", f.indent()); - - write_widget_code(f); -} - -void Fl_Widget_Type::write_color(fld::io::Code_Writer& f, const char* field, Fl_Color color) { - const char* color_name = 0; - switch (color) { - case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break; - case FL_BACKGROUND2_COLOR: color_name = "FL_BACKGROUND2_COLOR"; break; - case FL_INACTIVE_COLOR: color_name = "FL_INACTIVE_COLOR"; break; - case FL_SELECTION_COLOR: color_name = "FL_SELECTION_COLOR"; break; - case FL_GRAY0: color_name = "FL_GRAY0"; break; - case FL_DARK3: color_name = "FL_DARK3"; break; - case FL_DARK2: color_name = "FL_DARK2"; break; - case FL_DARK1: color_name = "FL_DARK1"; break; - case FL_BACKGROUND_COLOR: color_name = "FL_BACKGROUND_COLOR"; break; - case FL_LIGHT1: color_name = "FL_LIGHT1"; break; - case FL_LIGHT2: color_name = "FL_LIGHT2"; break; - case FL_LIGHT3: color_name = "FL_LIGHT3"; break; - case FL_BLACK: color_name = "FL_BLACK"; break; - case FL_RED: color_name = "FL_RED"; break; - case FL_GREEN: color_name = "FL_GREEN"; break; - case FL_YELLOW: color_name = "FL_YELLOW"; break; - case FL_BLUE: color_name = "FL_BLUE"; break; - case FL_MAGENTA: color_name = "FL_MAGENTA"; break; - case FL_CYAN: color_name = "FL_CYAN"; break; - case FL_DARK_RED: color_name = "FL_DARK_RED"; break; - case FL_DARK_GREEN: color_name = "FL_DARK_GREEN"; break; - case FL_DARK_YELLOW: color_name = "FL_DARK_YELLOW"; break; - case FL_DARK_BLUE: color_name = "FL_DARK_BLUE"; break; - case FL_DARK_MAGENTA: color_name = "FL_DARK_MAGENTA"; break; - case FL_DARK_CYAN: color_name = "FL_DARK_CYAN"; break; - case FL_WHITE: color_name = "FL_WHITE"; break; - } - const char *var = is_class() ? "this" : name() ? name() : "o"; - if (color_name) { - f.write_c("%s%s->%s(%s);\n", f.indent(), var, field, color_name); - } else { - f.write_c("%s%s->%s((Fl_Color)%d);\n", f.indent(), var, field, color); - } -} - -// this is split from write_code1(fld::io::Code_Writer& f) for Fl_Window_Type: -void Fl_Widget_Type::write_widget_code(fld::io::Code_Writer& f) { - Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; - const char *var = is_class() ? "this" : name() ? name() : "o"; - - if (tooltip() && *tooltip()) { - f.write_c("%s%s->tooltip(",f.indent(), var); - switch (g_project.i18n_type) { - case FD_I18N_NONE : /* None */ - f.write_cstring(tooltip()); - break; - case FD_I18N_GNU : /* GNU gettext */ - f.write_c("%s(", g_project.i18n_gnu_function.c_str()); - f.write_cstring(tooltip()); - f.write_c(")"); - break; - case FD_I18N_POSIX : /* POSIX catgets */ - f.write_c("catgets(%s,%s,%d,", - g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), - g_project.i18n_pos_set.c_str(), - msgnum() + 1); - f.write_cstring(tooltip()); - f.write_c(")"); - break; - } - f.write_c(");\n"); - } - - if (is_a(ID_Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) - f.write_c("%s%s->type(%d);\n", f.indent(), var, ((Fl_Spinner*)o)->type()); - else if (o->type() != tplate->type() && !is_a(ID_Window)) - f.write_c("%s%s->type(%d);\n", f.indent(), var, o->type()); - if (o->box() != tplate->box() || subclass()) - f.write_c("%s%s->box(FL_%s);\n", f.indent(), var, boxname(o->box())); - - // write shortcut command if needed - int shortcut = 0; - if (is_button()) shortcut = ((Fl_Button*)o)->shortcut(); - else if (is_a(ID_Input)) shortcut = ((Fl_Input_*)o)->shortcut(); - else if (is_a(ID_Value_Input)) shortcut = ((Fl_Value_Input*)o)->shortcut(); - else if (is_a(ID_Text_Display)) shortcut = ((Fl_Text_Display*)o)->shortcut(); - if (shortcut) { - int s = shortcut; - f.write_c("%s%s->shortcut(", f.indent(), var); - if (g_project.use_FL_COMMAND) { - if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } - if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } - } else { - if (s & FL_CTRL) { f.write_c("FL_CTRL|"); s &= ~FL_CTRL; } - if (s & FL_META) { f.write_c("FL_META|"); s &= ~FL_META; } - } - if (s & FL_SHIFT) { f.write_c("FL_SHIFT|"); s &= ~FL_SHIFT; } - if (s & FL_ALT) { f.write_c("FL_ALT|"); s &= ~FL_ALT; } - if ((s < 127) && isprint(s)) - f.write_c("'%c');\n", s); - else - f.write_c("0x%x);\n", s); - } - - if (is_a(ID_Button)) { - Fl_Button* b = (Fl_Button*)o; - if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, - boxname(b->down_box())); - if (b->value()) f.write_c("%s%s->value(1);\n", f.indent(), var); - if (b->compact()) f.write_c("%s%s->compact(%d);\n", f.indent(), var, b->compact()); - } else if (is_a(ID_Input_Choice)) { - Fl_Input_Choice* b = (Fl_Input_Choice*)o; - if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, - boxname(b->down_box())); - } else if (is_a(ID_Menu_Manager_)) { - Fl_Menu_* b = (Fl_Menu_*)o; - if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, - boxname(b->down_box())); - } - if (o->color() != tplate->color() || subclass()) - write_color(f, "color", o->color()); - if (o->selection_color() != tplate->selection_color() || subclass()) - write_color(f, "selection_color", o->selection_color()); - if (image) { - image->write_code(f, bind_image_, var); - if (scale_image_w_ || scale_image_h_) { - f.write_c("%s%s->image()->scale(", f.indent(), var); - if (scale_image_w_>0) - f.write_c("%d, ", scale_image_w_); - else - f.write_c("%s->image()->data_w(), ", var); - if (scale_image_h_>0) - f.write_c("%d, 0, 1);\n", scale_image_h_); - else - f.write_c("%s->image()->data_h(), 0, 1);\n", var); - } - } - if (inactive) { - inactive->write_code(f, bind_deimage_, var, 1); - if (scale_deimage_w_ || scale_deimage_h_) { - f.write_c("%s%s->deimage()->scale(", f.indent(), var); - if (scale_deimage_w_>0) - f.write_c("%d, ", scale_deimage_w_); - else - f.write_c("%s->deimage()->data_w(), ", var); - if (scale_deimage_h_>0) - f.write_c("%d, 0, 1);\n", scale_deimage_h_); - else - f.write_c("%s->deimage()->data_h(), 0, 1);\n", var); - } - } - if (o->labeltype() != tplate->labeltype() || subclass()) - f.write_c("%s%s->labeltype(FL_%s);\n", f.indent(), var, - item_name(labeltypemenu, o->labeltype())); - if (o->labelfont() != tplate->labelfont() || subclass()) - f.write_c("%s%s->labelfont(%d);\n", f.indent(), var, o->labelfont()); - if (o->labelsize() != tplate->labelsize() || subclass()) - f.write_c("%s%s->labelsize(%d);\n", f.indent(), var, o->labelsize()); - if (o->labelcolor() != tplate->labelcolor() || subclass()) - write_color(f, "labelcolor", o->labelcolor()); - if (o->horizontal_label_margin() != tplate->horizontal_label_margin()) - f.write_c("%s%s->horizontal_label_margin(%d);\n", f.indent(), var, o->horizontal_label_margin()); - if (o->vertical_label_margin() != tplate->vertical_label_margin()) - f.write_c("%s%s->vertical_label_margin(%d);\n", f.indent(), var, o->vertical_label_margin()); - if (o->label_image_spacing() != tplate->label_image_spacing()) - f.write_c("%s%s->label_image_spacing(%d);\n", f.indent(), var, o->label_image_spacing()); - if (is_a(ID_Valuator_)) { - Fl_Valuator* v = (Fl_Valuator*)o; - Fl_Valuator* t = (Fl_Valuator*)(tplate); - if (v->minimum()!=t->minimum()) - f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); - if (v->maximum()!=t->maximum()) - f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); - if (v->step()!=t->step()) - f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); - if (v->value()) { - if (is_a(ID_Scrollbar)) { // Fl_Scrollbar::value(double) is not available - f.write_c("%s%s->Fl_Slider::value(%g);\n", f.indent(), var, v->value()); - } else { - f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); - } - } - if (is_a(ID_Slider)) { - double x = ((Fl_Slider*)v)->slider_size(); - double y = ((Fl_Slider*)t)->slider_size(); - if (x != y) f.write_c("%s%s->slider_size(%g);\n", f.indent(), var, x); - } - } - if (is_a(ID_Spinner)) { - Fl_Spinner* v = (Fl_Spinner*)o; - Fl_Spinner* t = (Fl_Spinner*)(tplate); - if (v->minimum()!=t->minimum()) - f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); - if (v->maximum()!=t->maximum()) - f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); - if (v->step()!=t->step()) - f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); - if (v->value()!=1.0f) - f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); - } - - {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { - Fl_Font g; int s; Fl_Color c; textstuff(0,g,s,c); - if (g != ff) f.write_c("%s%s->textfont(%d);\n", f.indent(), var, g); - if (s != fs) f.write_c("%s%s->textsize(%d);\n", f.indent(), var, s); - if (c != fc) write_color(f, "textcolor", c); - }} - const char* ud = user_data(); - if (class_name(1) && !parent->is_widget()) ud = "this"; - if (callback()) { - f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f)); - if (ud) - f.write_c(", (void*)(%s));\n", ud); - else - f.write_c(");\n"); - } else if (ud) { - f.write_c("%s%s->user_data((void*)(%s));\n", f.indent(), var, ud); - } - if (o->align() != tplate->align() || subclass()) { - int i = o->align(); - f.write_c("%s%s->align(Fl_Align(%s", f.indent(), var, - item_name(alignmenu, i & ~FL_ALIGN_INSIDE)); - if (i & FL_ALIGN_INSIDE) f.write_c("|FL_ALIGN_INSIDE"); - f.write_c("));\n"); - } - Fl_When ww = o->when(); - if (ww != tplate->when() || subclass()) - f.write_c("%s%s->when(%s);\n", f.indent(), var, when_symbol_name(ww)); - if (!o->visible() && o->parent()) - f.write_c("%s%s->hide();\n", f.indent(), var); - if (!o->active()) - f.write_c("%s%s->deactivate();\n", f.indent(), var); - if (!is_a(ID_Group) && resizable()) - f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var); - if (hotspot()) { - if (is_class()) - f.write_c("%shotspot(%s);\n", f.indent(), var); - else if (is_a(ID_Window)) - f.write_c("%s%s->hotspot(%s);\n", f.indent(), var, var); - else - f.write_c("%s%s->window()->hotspot(%s);\n", f.indent(), var, var); - } -} - -void Fl_Widget_Type::write_extra_code(fld::io::Code_Writer& f) { - for (int n=0; n < NUM_EXTRA_CODE; n++) - if (extra_code(n) && !isdeclare(extra_code(n))) - f.write_c("%s%s\n", f.indent(), extra_code(n)); -} - -void Fl_Widget_Type::write_block_close(fld::io::Code_Writer& f) { - f.indentation--; - f.write_c("%s} // %s* %s\n", f.indent(), subclassname(this), - name() ? name() : "o"); -} - -void Fl_Widget_Type::write_code2(fld::io::Code_Writer& f) { - write_extra_code(f); - write_block_close(f); -} - -//////////////////////////////////////////////////////////////// - -void Fl_Widget_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); - f.write_indent(level+1); - switch (public_) { - case 0: f.write_string("private"); break; - case 1: break; - case 2: f.write_string("protected"); break; - } - if (tooltip() && *tooltip()) { - f.write_string("tooltip"); - f.write_word(tooltip()); - } - if (image_name() && *image_name()) { - if (scale_image_w_ || scale_image_h_) - f.write_string("scale_image {%d %d}", scale_image_w_, scale_image_h_); - f.write_string("image"); - f.write_word(image_name()); - f.write_string("compress_image %d", compress_image_); - } - if (bind_image_) f.write_string("bind_image 1"); - if (inactive_name() && *inactive_name()) { - if (scale_deimage_w_ || scale_deimage_h_) - f.write_string("scale_deimage {%d %d}", scale_deimage_w_, scale_deimage_h_); - f.write_string("deimage"); - f.write_word(inactive_name()); - f.write_string("compress_deimage %d", compress_deimage_); - } - if (bind_deimage_) f.write_string("bind_deimage 1"); - f.write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h()); - Fl_Widget* tplate = ((Fl_Widget_Type*)factory)->o; - if (is_a(ID_Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) { - f.write_string("type"); - f.write_word(item_name(subtypes(), ((Fl_Spinner*)o)->type())); - } else if (subtypes() && (o->type() != tplate->type() || is_a(ID_Window))) { - f.write_string("type"); - f.write_word(item_name(subtypes(), o->type())); - } - if (o->box() != tplate->box()) { - f.write_string("box"); f.write_word(boxname(o->box()));} - if (is_a(ID_Input)) { - Fl_Input_* b = (Fl_Input_*)o; - if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); - } - if (is_a(ID_Value_Input)) { - Fl_Value_Input* b = (Fl_Value_Input*)o; - if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); - } - if (is_a(ID_Text_Display)) { - Fl_Text_Display* b = (Fl_Text_Display*)o; - if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); - } - if (is_a(ID_Button)) { - Fl_Button* b = (Fl_Button*)o; - if (b->down_box()) { - f.write_string("down_box"); f.write_word(boxname(b->down_box()));} - if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); - if (b->value()) f.write_string("value 1"); - } else if (is_a(ID_Input_Choice)) { - Fl_Input_Choice* b = (Fl_Input_Choice*)o; - if (b->down_box()) { - f.write_string("down_box"); f.write_word(boxname(b->down_box()));} - } else if (is_a(ID_Menu_)) { - Fl_Menu_* b = (Fl_Menu_*)o; - if (b->down_box()) { - f.write_string("down_box"); f.write_word(boxname(b->down_box()));} - } - if (o->color()!=tplate->color()) - f.write_string("color %d", o->color()); - if (o->selection_color()!=tplate->selection_color()) - f.write_string("selection_color %d", o->selection_color()); - if (o->labeltype()!=tplate->labeltype()) { - f.write_string("labeltype"); - f.write_word(item_name(labeltypemenu, o->labeltype())); - } - if (o->labelfont()!=tplate->labelfont()) - f.write_string("labelfont %d", o->labelfont()); - if (o->labelsize()!=tplate->labelsize()) - f.write_string("labelsize %d", o->labelsize()); - if (o->labelcolor()!=tplate->labelcolor()) - f.write_string("labelcolor %d", o->labelcolor()); - if (o->align()!=tplate->align()) - f.write_string("align %d", o->align()); - if (o->horizontal_label_margin()!=tplate->horizontal_label_margin()) - f.write_string("h_label_margin %d", o->horizontal_label_margin()); - if (o->vertical_label_margin()!=tplate->vertical_label_margin()) - f.write_string("v_label_margin %d", o->vertical_label_margin()); - if (o->label_image_spacing()!=tplate->label_image_spacing()) - f.write_string("image_spacing %d", o->label_image_spacing()); - if (o->when() != tplate->when()) - f.write_string("when %d", o->when()); - if (is_a(ID_Valuator_)) { - Fl_Valuator* v = (Fl_Valuator*)o; - Fl_Valuator* t = (Fl_Valuator*)(tplate); - if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); - if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); - if (v->step()!=t->step()) f.write_string("step %g",v->step()); - if (v->value()!=0.0) f.write_string("value %g",v->value()); - if (is_a(ID_Slider)) { - double x = ((Fl_Slider*)v)->slider_size(); - double y = ((Fl_Slider*)t)->slider_size(); - if (x != y) f.write_string("slider_size %g", x); - } - } - if (is_a(ID_Spinner)) { - Fl_Spinner* v = (Fl_Spinner*)o; - Fl_Spinner* t = (Fl_Spinner*)(tplate); - if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); - if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); - if (v->step()!=t->step()) f.write_string("step %g",v->step()); - if (v->value()!=1.0) f.write_string("value %g",v->value()); - } - {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { - Fl_Font ft; int s; Fl_Color c; textstuff(0,ft,s,c); - if (ft != ff) f.write_string("textfont %d", ft); - if (s != fs) f.write_string("textsize %d", s); - if (c != fc) f.write_string("textcolor %d", c); - }} - if (!o->visible() && !override_visible_) f.write_string("hide"); - if (!o->active()) f.write_string("deactivate"); - if (resizable()) f.write_string("resizable"); - if (hotspot()) f.write_string(is_a(ID_Menu_Item) ? "divider" : "hotspot"); - for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) { - f.write_indent(level+1); - f.write_string("code%d",n); - f.write_word(extra_code(n)); - } - if (subclass()) { - f.write_indent(level+1); - f.write_string("class"); - f.write_word(subclass()); - } -} - -void Fl_Widget_Type::read_property(fld::io::Project_Reader &f, const char *c) { - int x,y,w,h; Fl_Font ft; int s; Fl_Color cc; - if (!strcmp(c,"private")) { - public_ = 0; - } else if (!strcmp(c,"protected")) { - public_ = 2; - } else if (!strcmp(c,"xywh")) { - if (sscanf(f.read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) { - x += pasteoffset; - y += pasteoffset; - // FIXME temporary change! - if (f.read_version>=2.0 && o->parent() && o->parent()!=o->window()) { - x += o->parent()->x(); - y += o->parent()->y(); - } - o->resize(x,y,w,h); - } - } else if (!strcmp(c,"tooltip")) { - tooltip(f.read_word()); - } else if (!strcmp(c,"scale_image")) { - if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { - scale_image_w_ = w; - scale_image_h_ = h; - } - } else if (!strcmp(c,"image")) { - image_name(f.read_word()); - // starting in 2023, `image` is always followed by `compress_image` - // the code below is for compatibility with older .fl files - const char *ext = fl_filename_ext(image_name_); - if ( strcmp(ext, ".jpg") - && strcmp(ext, ".png") - && strcmp(ext, ".svg") - && strcmp(ext, ".svgz")) - compress_image_ = 0; // if it is neither of those, default to uncompressed - } else if (!strcmp(c,"bind_image")) { - bind_image_ = (int)atol(f.read_word()); - } else if (!strcmp(c,"compress_image")) { - compress_image_ = (int)atol(f.read_word()); - } else if (!strcmp(c,"scale_deimage")) { - if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { - scale_deimage_w_ = w; - scale_deimage_h_ = h; - } - } else if (!strcmp(c,"deimage")) { - inactive_name(f.read_word()); - // starting in 2023, `deimage` is always followed by `compress_deimage` - // the code below is for compatibility with older .fl files - const char *ext = fl_filename_ext(inactive_name_); - if ( strcmp(ext, ".jpg") - && strcmp(ext, ".png") - && strcmp(ext, ".svg") - && strcmp(ext, ".svgz")) - compress_deimage_ = 0; // if it is neither of those, default to uncompressed - } else if (!strcmp(c,"bind_deimage")) { - bind_deimage_ = (int)atol(f.read_word()); - } else if (!strcmp(c,"compress_deimage")) { - compress_deimage_ = (int)atol(f.read_word()); - } else if (!strcmp(c,"type")) { - if (is_a(ID_Spinner)) - ((Fl_Spinner*)o)->type(item_number(subtypes(), f.read_word())); - else - o->type(item_number(subtypes(), f.read_word())); - } else if (!strcmp(c,"box")) { - const char* value = f.read_word(); - if ((x = boxnumber(value))) { - if (x == ZERO_ENTRY) x = 0; - o->box((Fl_Boxtype)x); - } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x); - } else if (is_a(ID_Button) && !strcmp(c,"down_box")) { - const char* value = f.read_word(); - if ((x = boxnumber(value))) { - if (x == ZERO_ENTRY) x = 0; - ((Fl_Button*)o)->down_box((Fl_Boxtype)x); - } - } else if (is_a(ID_Input_Choice) && !strcmp(c,"down_box")) { - const char* value = f.read_word(); - if ((x = boxnumber(value))) { - if (x == ZERO_ENTRY) x = 0; - ((Fl_Input_Choice*)o)->down_box((Fl_Boxtype)x); - } - } else if (is_a(ID_Menu_) && !strcmp(c,"down_box")) { - const char* value = f.read_word(); - if ((x = boxnumber(value))) { - if (x == ZERO_ENTRY) x = 0; - ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x); - } - } else if (is_button() && !strcmp(c,"value")) { - const char* value = f.read_word(); - ((Fl_Button*)o)->value(atoi(value)); - } else if (!strcmp(c,"color")) { - const char *cw = f.read_word(); - if (cw[0]=='0' && cw[1]=='x') { - sscanf(cw,"0x%x",&x); - o->color(x); - } else { - int n = sscanf(cw,"%d %d",&x,&y); - if (n == 2) { // back compatibility... - if (x != 47) o->color(x); - o->selection_color(y); - } else { - o->color(x); - } - } - } else if (!strcmp(c,"selection_color")) { - if (sscanf(f.read_word(),"%d",&x)) o->selection_color(x); - } else if (!strcmp(c,"labeltype")) { - c = f.read_word(); - if (!strcmp(c,"image")) { - Fluid_Image *i = Fluid_Image::find(label()); - if (!i) f.read_error("Image file '%s' not found", label()); - else setimage(i); - image_name(label()); - label(""); - } else { - o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c)); - } - } else if (!strcmp(c,"labelfont")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->labelfont(x); - } else if (!strcmp(c,"labelsize")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->labelsize(x); - } else if (!strcmp(c,"labelcolor")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->labelcolor(x); - } else if (!strcmp(c,"align")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->align(x); - } else if (!strcmp(c,"h_label_margin")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->horizontal_label_margin(x); - } else if (!strcmp(c,"v_label_margin")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->vertical_label_margin(x); - } else if (!strcmp(c,"image_spacing")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->label_image_spacing(x); - } else if (!strcmp(c,"when")) { - if (sscanf(f.read_word(),"%d",&x) == 1) o->when(x); - } else if (!strcmp(c,"minimum")) { - if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->minimum(strtod(f.read_word(),0)); - if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->minimum(strtod(f.read_word(),0)); - } else if (!strcmp(c,"maximum")) { - if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->maximum(strtod(f.read_word(),0)); - if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->maximum(strtod(f.read_word(),0)); - } else if (!strcmp(c,"step")) { - if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->step(strtod(f.read_word(),0)); - if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->step(strtod(f.read_word(),0)); - } else if (!strcmp(c,"value")) { - if (is_a(ID_Valuator_)) ((Fl_Valuator*)o)->value(strtod(f.read_word(),0)); - if (is_a(ID_Spinner)) ((Fl_Spinner*)o)->value(strtod(f.read_word(),0)); - } else if ( (!strcmp(c,"slider_size") || !strcmp(c,"size")) && is_a(ID_Slider)) { - ((Fl_Slider*)o)->slider_size(strtod(f.read_word(),0)); - } else if (!strcmp(c,"textfont")) { - if (sscanf(f.read_word(),"%d",&x) == 1) {ft=(Fl_Font)x; textstuff(1,ft,s,cc);} - } else if (!strcmp(c,"textsize")) { - if (sscanf(f.read_word(),"%d",&x) == 1) {s=x; textstuff(2,ft,s,cc);} - } else if (!strcmp(c,"textcolor")) { - if (sscanf(f.read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,ft,s,cc);} - } else if (!strcmp(c,"hide")) { - o->hide(); - } else if (!strcmp(c,"deactivate")) { - o->deactivate(); - } else if (!strcmp(c,"resizable")) { - resizable(1); - } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) { - hotspot(1); - } else if (!strcmp(c,"class")) { - subclass(f.read_word()); - } else if (!strcmp(c,"shortcut")) { - int shortcut = (int)strtol(f.read_word(),0,0); - if (is_button()) ((Fl_Button*)o)->shortcut(shortcut); - else if (is_a(ID_Input)) ((Fl_Input_*)o)->shortcut(shortcut); - else if (is_a(ID_Value_Input)) ((Fl_Value_Input*)o)->shortcut(shortcut); - else if (is_a(ID_Text_Display)) ((Fl_Text_Display*)o)->shortcut(shortcut); - } else { - if (!strncmp(c,"code",4)) { - int n = atoi(c+4); - if (n >= 0 && n <= NUM_EXTRA_CODE) { - extra_code(n,f.read_word()); - return; - } - } else if (!strcmp(c,"extra_code")) { - extra_code(0,f.read_word()); - return; - } - Fl_Type::read_property(f, c); - } -} - -Fl_Menu_Item boxmenu1[] = { - // these extra ones are for looking up fdesign saved strings: - {"NO_FRAME", 0,0,(void *)FL_NO_BOX}, - {"ROUNDED3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, - {"ROUNDED3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, - {"OVAL3D_UPBOX", 0,0,(void *)_FL_ROUND_UP_BOX}, - {"OVAL3D_DOWNBOX", 0,0,(void *)_FL_ROUND_DOWN_BOX}, - {"0", 0,0,(void *)ZERO_ENTRY}, - {"1", 0,0,(void *)FL_UP_BOX}, - {"2", 0,0,(void *)FL_DOWN_BOX}, - {"3", 0,0,(void *)FL_FLAT_BOX}, - {"4", 0,0,(void *)FL_BORDER_BOX}, - {"5", 0,0,(void *)FL_SHADOW_BOX}, - {"6", 0,0,(void *)FL_FRAME_BOX}, - {"7", 0,0,(void *)FL_ROUNDED_BOX}, - {"8", 0,0,(void *)FL_RFLAT_BOX}, - {"9", 0,0,(void *)FL_RSHADOW_BOX}, - {"10", 0,0,(void *)FL_UP_FRAME}, - {"11", 0,0,(void *)FL_DOWN_FRAME}, -{0}}; - -int lookup_symbol(const char *, int &, int numberok = 0); - -int Fl_Widget_Type::read_fdesign(const char* propname, const char* value) { - int v; - if (!strcmp(propname,"box")) { - float x,y,w,h; - if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { - if (fld::io::fdesign_flip) { - Fl_Type *p; - for (p = parent; p && !p->is_a(ID_Window); p = p->parent) {/*empty*/} - if (p && p->is_widget()) y = ((Fl_Widget_Type*)p)->o->h()-(y+h); - } - x += pasteoffset; - y += pasteoffset; - o->resize(int(x),int(y),int(w),int(h)); - } - } else if (!strcmp(propname,"label")) { - label(value); - } else if (!strcmp(propname,"name")) { - this->name(value); - } else if (!strcmp(propname,"callback")) { - callback(value); user_data_type("long"); - } else if (!strcmp(propname,"argument")) { - user_data(value); - } else if (!strcmp(propname,"shortcut")) { - if (value[0]) { - char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value); - extra_code(0,buf); - } - } else if (!strcmp(propname,"style")) { - if (!strncmp(value,"FL_NORMAL",9)) return 1; - if (!lookup_symbol(value,v,1)) return 0; - o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8)); - } else if (!strcmp(propname,"size")) { - if (!lookup_symbol(value,v,1)) return 0; - o->labelsize(v); - } else if (!strcmp(propname,"type")) { - if (!strncmp(value,"NORMAL",6)) return 1; - if (lookup_symbol(value,v,1)) {o->type(v); return 1;} - if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE; - if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE; - return 0; - } else if (!strcmp(propname,"lcol")) { - if (!lookup_symbol(value,v,1)) return 0; - o->labelcolor(v); - } else if (!strcmp(propname,"return")) { - if (!lookup_symbol(value,v,0)) return 0; - o->when(v|FL_WHEN_RELEASE); - } else if (!strcmp(propname,"alignment")) { - if (!lookup_symbol(value,v)) { - // convert old numeric values: - int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0; - v = 0; - if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;} - switch (v1) { - case 0: v += FL_ALIGN_TOP; break; - case 1: v += FL_ALIGN_BOTTOM; break; - case 2: v += FL_ALIGN_LEFT; break; - case 3: v += FL_ALIGN_RIGHT; break; - case 4: v += FL_ALIGN_CENTER; break; - default: return 0; - } - } - o->align(v); - } else if (!strcmp(propname,"resizebox")) { - resizable(1); - } else if (!strcmp(propname,"colors")) { - char* p = (char*)value; - while (*p != ' ') {if (!*p) return 0; p++;} - *p = 0; - int v1; - if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) { - *p=' '; return 0;} - o->color(v,v1); - } else if (!strcmp(propname,"resize")) { - return !strcmp(value,"FL_RESIZE_ALL"); - } else if (!strcmp(propname,"gravity")) { - return !strcmp(value,"FL_NoGravity FL_NoGravity"); - } else if (!strcmp(propname,"boxtype")) { - TRY_BOXTYPE: - int x = boxnumber(value); - if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;} - if (x == ZERO_ENTRY) { - x = 0; - if (o->box() != ((Fl_Widget_Type*)factory)->o->box()) return 1; // kludge for frame - } - o->box((Fl_Boxtype)x); - } else { - return 0; - } - return 1; -} - -void leave_live_mode_cb(Fl_Widget*, void*) { - live_mode_cb(0, 0); -} - -Fl_Widget *Fl_Widget_Type::enter_live_mode(int) { - live_widget = widget(o->x(), o->y(), o->w(), o->h()); - if (live_widget) - copy_properties(); - return live_widget; -} - -Fl_Widget* Fl_Widget_Type::propagate_live_mode(Fl_Group* grp) { - live_widget = grp; - copy_properties(); - Fl_Type *n; - for (n = next; n && n->level > level; n = n->next) { - if (n->level == level+1) { - Fl_Widget* proxy_child = n->enter_live_mode(); - if (proxy_child && n->is_widget() && ((Fl_Widget_Type*)n)->resizable()) { - grp->resizable(proxy_child); - } - } - } - grp->end(); - live_widget = grp; - copy_properties_for_children(); - return live_widget; -} - - -void Fl_Widget_Type::leave_live_mode() { -} - -/** - copy all properties from the edit widget to the live widget - */ -void Fl_Widget_Type::copy_properties() { - if (!live_widget) - return; - - Fl_Font ff = 0; - int fs = 0; - Fl_Color fc = 0; - textstuff(0, ff, fs, fc); - - // copy all attributes common to all widget types - Fl_Widget *w = live_widget; - w->label(o->label()); - w->tooltip(tooltip()); - w->type(o->type()); - w->box(o->box()); - w->color(o->color()); - w->selection_color(o->selection_color()); - w->labeltype(o->labeltype()); - w->labelfont(o->labelfont()); - w->labelsize(o->labelsize()); - w->labelcolor(o->labelcolor()); - w->align(o->align()); - w->when(o->when()); - - // copy all attributes specific to widgets derived from Fl_Button - if (is_button()) { - Fl_Button* d = (Fl_Button*)live_widget, *s = (Fl_Button*)o; - d->down_box(s->down_box()); - d->shortcut(s->shortcut()); - d->value(s->value()); - } - - // copy all attributes specific to widgets derived from Fl_Input_ - if (is_a(ID_Input)) { - Fl_Input_* d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; - d->shortcut(s->shortcut()); - d->textfont(ff); - d->textsize(fs); - d->textcolor(fc); - } - - // copy all attributes specific to widgets derived from Fl_Value_Input - if (is_a(ID_Value_Input)) { - Fl_Value_Input* d = (Fl_Value_Input*)live_widget, *s = (Fl_Value_Input*)o; - d->shortcut(s->shortcut()); - d->textfont(ff); - d->textsize(fs); - d->textcolor(fc); - } - - // copy all attributes specific to widgets derived from Fl_Text_Display - if (is_a(ID_Text_Display)) { - Fl_Text_Display* d = (Fl_Text_Display*)live_widget, *s = (Fl_Text_Display*)o; - d->shortcut(s->shortcut()); - d->textfont(ff); - d->textsize(fs); - d->textcolor(fc); - } - - // copy all attributes specific to Fl_Valuator and derived classes - if (is_a(ID_Valuator_)) { - Fl_Valuator* d = (Fl_Valuator*)live_widget, *s = (Fl_Valuator*)o; - d->minimum(s->minimum()); - d->maximum(s->maximum()); - d->step(s->step()); - d->value(s->value()); - if (is_a(ID_Slider)) { - Fl_Slider *d = (Fl_Slider*)live_widget, *s = (Fl_Slider*)o; - d->slider_size(s->slider_size()); - } - } - - // copy all attributes specific to Fl_Spinner and derived classes - if (is_a(ID_Spinner)) { - Fl_Spinner* d = (Fl_Spinner*)live_widget, *s = (Fl_Spinner*)o; - d->minimum(s->minimum()); - d->maximum(s->maximum()); - d->step(s->step()); - d->value(s->value()); - } - - if (!o->visible()) - w->hide(); - if (!o->active()) - w->deactivate(); -} - diff --git a/fluid/nodes/Fl_Window_Type.h b/fluid/nodes/Fl_Window_Type.h deleted file mode 100644 index 0dcb9e96e..000000000 --- a/fluid/nodes/Fl_Window_Type.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// Window type header file for the Fast Light Tool Kit (FLTK). -// -// Type for creating all subclasses of Fl_Widget -// This should have the widget pointer in it, but it is still in the -// Fl_Type base class. -// -// 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 -// 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_FL_WINDOW_TYPE_H -#define _FLUID_FL_WINDOW_TYPE_H - -#include "nodes/Fl_Group_Type.h" - -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 toggle_restricted(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_Group_Type -{ - typedef Fl_Group_Type super; -protected: - - Fl_Menu_Item* subtypes() FL_OVERRIDE {return window_type_menu;} - - friend class Overlay_Window; - int mx,my; // mouse position during dragging - int x1,y1; // initial position of selection box - int bx,by,br,bt; // bounding box of selection before snapping - int sx,sy,sr,st; // bounding box of selection after snapping to guides - int dx,dy; - int drag; // which parts of bbox are being moved - int numselected; // number of children selected - void draw_out_of_bounds(Fl_Widget_Type *group, int x, int y, int w, int h); - void draw_out_of_bounds(); - void draw_overlaps(); - void draw_overlay(); - void newdx(); - void newposition(Fl_Widget_Type *,int &x,int &y,int &w,int &h); - int handle(int); - void setlabel(const char *) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - Fl_Widget_Type *_make() FL_OVERRIDE {return 0;} // we don't call this - Fl_Widget *widget(int,int,int,int) FL_OVERRIDE {return 0;} - int recalc; // set by fix_overlay() - void moveallchildren(int key=0); - ID id() const FL_OVERRIDE { return ID_Window; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Window) ? true : super::is_a(inID); } - void open_(); - -public: - - Fl_Window_Type() : - mx(0), my(0), - x1(0), y1(0), - bx(0), by(0), br(0), bt(0), - sx(0), sy(0), sr(0), st(0), - dx(0), dy(0), - drag(0), - numselected(0), - recalc(0), - modal(0), non_modal(0), - xclass(NULL), - sr_min_w(0), sr_min_h(0), sr_max_w(0), sr_max_h(0) - { } - uchar modal, non_modal; - const char *xclass; // junk string, used for shortcut - - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "Fl_Window";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::Window";} - - void open() FL_OVERRIDE; - void ideal_size(int &w, int &h) FL_OVERRIDE; - - void fix_overlay(); // Update the bounding box, etc - uchar *read_image(int &ww, int &hh); // Read an image of the window - - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int read_fdesign(const char*, const char*) FL_OVERRIDE; - - void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE; - void remove_child(Fl_Type*) FL_OVERRIDE; - - int can_have_children() const FL_OVERRIDE {return 1;} - - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; - void leave_live_mode() FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; - - int sr_min_w, sr_min_h, sr_max_w, sr_max_h; - - static int popupx, popupy; -}; - -class Fl_Widget_Class_Type : private Fl_Window_Type -{ - typedef Fl_Window_Type super; -protected: - Fl_Menu_Item* subtypes() FL_OVERRIDE {return 0;} - -public: - Fl_Widget_Class_Type() { - write_public_state = 0; - wc_relative = 0; - } - // state variables for output: - char write_public_state; // true when public: has been printed - char wc_relative; // if 1, reposition all children, if 2, reposition and resize - - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - const char *type_name() FL_OVERRIDE {return "widget_class";} - ID id() const FL_OVERRIDE { return ID_Widget_Class; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Widget_Class) ? true : super::is_a(inID); } - int can_have_children() const FL_OVERRIDE {return 1;} - int is_code_block() const FL_OVERRIDE {return 1;} - int is_decl_block() const FL_OVERRIDE {return 1;} - int is_class() const FL_OVERRIDE {return 1;} -}; - -#endif // _FLUID_FL_WINDOW_TYPE_H diff --git a/fluid/nodes/Fl_Function_Type.cxx b/fluid/nodes/Function_Node.cxx similarity index 83% rename from fluid/nodes/Fl_Function_Type.cxx rename to fluid/nodes/Function_Node.cxx index 5778324bf..8ffdbef01 100644 --- a/fluid/nodes/Fl_Function_Type.cxx +++ b/fluid/nodes/Function_Node.cxx @@ -1,7 +1,7 @@ // -// C function type code for the Fast Light Tool Kit (FLTK). +// C function Node code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -14,16 +14,16 @@ // https://www.fltk.org/bugs.php // -#include "nodes/Fl_Function_Type.h" +#include "nodes/Function_Node.h" -#include "app/fluid.h" -#include "app/mergeback.h" -#include "app/undo.h" +#include "Fluid.h" +#include "proj/mergeback.h" +#include "proj/undo.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/Fl_Group_Type.h" +#include "nodes/Window_Node.h" +#include "nodes/Group_Node.h" #include "panels/function_panel.h" #include "rsrcs/comments.h" #include "widgets/Node_Browser.h" @@ -37,22 +37,22 @@ /// Set a current class, so that the code of the children is generated correctly. -Fl_Class_Type *current_class = NULL; +Class_Node *current_class = nullptr; /** \brief Return 1 if the list contains a function with the given signature at the top level. - Fl_Widget_Type uses this to check if a callback by a certain signature is - already defined by the user within this file. If not, Fl_Widget_Type will + Widget_Node uses this to check if a callback by a certain signature is + already defined by the user within this file. If not, Widget_Node will generate an `extern $sig$;` statement. - \param[in] rtype return type, can be NULL to avoid checking (not used by Fl_Widget_Type) + \param[in] rtype return type, can be nullptr to avoid checking (not used by Widget_Node) \param[in] sig function signature \return 1 if found. */ int has_toplevel_function(const char *rtype, const char *sig) { - Fl_Type *child; - for (child = Fl_Type::first; child; child = child->next) { - if (!child->is_in_class() && child->is_a(ID_Function)) { - const Fl_Function_Type *fn = (const Fl_Function_Type*)child; + Node *child; + for (child = Fluid.proj.tree.first; child; child = child->next) { + if (!child->is_in_class() && child->is_a(Type::Function)) { + const Function_Node *fn = (const Function_Node*)child; if (fn->has_signature(rtype, sig)) return 1; } @@ -71,7 +71,7 @@ static char buffer[128]; // for error messages This is used to find a matching " or ' in a string. \param[inout] c start searching here, return where we found \c type \param[in] type find this character - \return NULL if the character was found, else a pointer to a static string + \return nullptr if the character was found, else a pointer to a static string with an error message */ const char *_q_check(const char * & c, int type) { @@ -83,7 +83,7 @@ const char *_q_check(const char * & c, int type) { if (*c) c++; break; default: - if (*(c-1) == type) return 0; + if (*(c-1) == type) return nullptr; } } @@ -93,14 +93,14 @@ const char *_q_check(const char * & c, int type) { {, [, ", ', and ( are matched. \param[inout] c start searching here, return the end of the search \param[in] type find this character match - \return NULL if the character was found, else a pointer to a static string + \return nullptr if the character was found, else a pointer to a static string with an error message */ const char *_c_check(const char * & c, int type) { const char *d; for (;;) switch (*c++) { case 0: - if (!type) return 0; + if (!type) return nullptr; sprintf(buffer, "missing '%c'", type); return buffer; case '/': @@ -123,7 +123,8 @@ const char *_c_check(const char * & c, int type) { // while (*c != '\n' && *c) c++; // break; case '{': - if (type==')') goto UNEXPECTED; +// // Matt: C++ does allow {} inside () now +// if (type==')') goto UNEXPECTED; d = _c_check(c,'}'); if (d) return d; break; @@ -146,8 +147,8 @@ const char *_c_check(const char * & c, int type) { case '}': case ')': case ']': - UNEXPECTED: - if (type == *(c-1)) return 0; +// UNEXPECTED: + if (type == *(c-1)) return nullptr; sprintf(buffer, "unexpected '%c'", *(c-1)); return buffer; } @@ -158,7 +159,7 @@ const char *_c_check(const char * & c, int type) { Make sure that {, ", ', and ( are matched. \param[in] c start searching here \param[in] type find this character match (default is 0) - \return NULL if the character was found, else a pointer to a static string + \return nullptr if the character was found, else a pointer to a static string with an error message \note This function checks every conceivable line of code, which is not always wanted. It can't differentiate characters in comments, and the @@ -169,9 +170,9 @@ const char *c_check(const char *c, int type) { return _c_check(c,type); } -// ---- Fl_Function_Type implementation +// ---- Function_Node implementation -/** \class Fl_Function_Type +/** \class Function_Node Manage a C++ function node in the Fluid design. A function can have a signature (name followed by arguments), a return type @@ -180,14 +181,14 @@ const char *c_check(const char *c, int type) { */ /// Prototype for a function to be used by the factory. -Fl_Function_Type Fl_Function_type; +Function_Node Function_Node::prototype; /** Create a new function. */ -Fl_Function_Type::Fl_Function_Type() : - Fl_Type(), - return_type(0L), +Function_Node::Function_Node() : + Node(), + return_type(nullptr), public_(0), cdecl_(0), constructor(0), @@ -197,7 +198,7 @@ Fl_Function_Type::Fl_Function_Type() : /** Destructor. */ -Fl_Function_Type::~Fl_Function_Type() { +Function_Node::~Function_Node() { if (return_type) free((void*)return_type); } @@ -206,8 +207,8 @@ Fl_Function_Type::~Fl_Function_Type() { \param[in] strategy add new function after current or as last child \return the new node */ -Fl_Type *Fl_Function_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Function_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { @@ -215,9 +216,9 @@ Fl_Type *Fl_Function_Type::make(Strategy strategy) { strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Function_Type *o = new Fl_Function_Type(); + Function_Node *o = new Function_Node(); o->name("make_window()"); - o->return_type = 0; + o->return_type = nullptr; o->add(anchor, strategy); o->factory = this; o->public_ = 1; @@ -231,8 +232,8 @@ Fl_Type *Fl_Function_Type::make(Strategy strategy) { - "C" is written if we want a C signature instead of C++ - "return_type" is followed by the return type of the function */ -void Fl_Function_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void Function_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; case 2: f.write_string("protected"); break; @@ -248,7 +249,7 @@ void Fl_Function_Type::write_properties(fld::io::Project_Writer &f) { Read function specific properties fron an .fl file. \param[in] c read from this string */ -void Fl_Function_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Function_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { @@ -258,14 +259,14 @@ void Fl_Function_Type::read_property(fld::io::Project_Reader &f, const char *c) } else if (!strcmp(c,"return_type")) { storestring(f.read_word(),return_type); } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } /** Open the function_panel dialog box to edit this function. */ -void Fl_Function_Type::open() { +void Function_Node::open() { // fill dialog box if (!function_panel) make_function_panel(); f_return_type_input->value(return_type); @@ -285,7 +286,7 @@ void Fl_Function_Type::open() { const char *c = comment(); f_comment_input->buffer()->text(c?c:""); function_panel->show(); - const char* message = 0; + const char* message = nullptr; for (;;) { // repeat as long as there are errors // - message loop until OK or cancel is pressed for (;;) { @@ -311,7 +312,7 @@ void Fl_Function_Type::open() { // - alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", - "Continue Editing", "Ignore Error", NULL, message); + "Continue Editing", "Ignore Error", nullptr, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } @@ -338,14 +339,14 @@ void Fl_Function_Type::open() { } c = f_comment_input->buffer()->text(); if (c && *c) { - if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } + if (!comment() || strcmp(c, comment())) { Fluid.proj.set_modflag(1); redraw_browser(); } comment(c); } else { - if (comment()) { set_modflag(1); redraw_browser(); } - comment(0); + if (comment()) { Fluid.proj.set_modflag(1); redraw_browser(); } + comment(nullptr); } if (c) free((void*)c); - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); break; } BREAK2: @@ -356,7 +357,7 @@ BREAK2: Return 1 if the function is global. \return 1 if public, 0 if local. */ -int Fl_Function_Type::is_public() const { +int Function_Node::is_public() const { return public_; } @@ -410,10 +411,10 @@ static void clean_function_for_implementation(char *out, const char *function_na This writes the code that goes \b before all children of this class. \see write_code2(fld::io::Code_Writer& f) */ -void Fl_Function_Type::write_code1(fld::io::Code_Writer& f) { +void Function_Node::write_code1(fld::io::Code_Writer& f) { constructor=0; havewidgets = 0; - Fl_Type *child; + Node *child; // if the function has no children (hence no body), Fluid will not generate // the function either. This is great if you decide to implement that function // inside another module @@ -438,11 +439,11 @@ void Fl_Function_Type::write_code1(fld::io::Code_Writer& f) { int is_static = 0; int is_virtual = 0; if (rtype) { - if (!strcmp(rtype,"static")) {is_static = 1; rtype = 0;} + if (!strcmp(rtype,"static")) {is_static = 1; rtype = nullptr;} else if (!strncmp(rtype, "static ",7)) {is_static = 1; rtype += 7;} } if (rtype) { - if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = 0;} + if (!strcmp(rtype, "virtual")) {is_virtual = 1; rtype = nullptr;} else if (!strncmp(rtype, "virtual ",8)) {is_virtual = 1; rtype += 8;} } if (!rtype) { @@ -529,13 +530,13 @@ void Fl_Function_Type::write_code1(fld::io::Code_Writer& f) { This writes the code that goes \b after all children of this class. \see write_code1(fld::io::Code_Writer& f) */ -void Fl_Function_Type::write_code2(fld::io::Code_Writer& f) { - Fl_Type *child; +void Function_Node::write_code2(fld::io::Code_Writer& f) { + Node *child; const char *var = "w"; char havechildren = 0; for (child = next; child && child->level > level; child = child->next) { havechildren = 1; - if (child->is_a(ID_Window) && child->name()) var = child->name(); + if (child->is_a(Type::Window) && child->name()) var = child->name(); } if (ismain()) { @@ -552,24 +553,24 @@ void Fl_Function_Type::write_code2(fld::io::Code_Writer& f) { } /** - Check if the return type and signature s match. + Check if the return type and signatures match. \param[in] rtype function return type \param[in] sig function name followed by arguments \return 1 if they match, 0 if not */ -int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const { +int Function_Node::has_signature(const char *rtype, const char *sig) const { if (rtype && !return_type) return 0; if (!name()) return 0; - if ( (rtype==0L || strcmp(return_type, rtype)==0) + if ( (rtype==nullptr || strcmp(return_type, rtype)==0) && fl_filename_match(name(), sig)) { return 1; } return 0; } -// ---- Fl_Code_Type declaration +// ---- Code_Node declaration -/** \class Fl_Code_Type +/** \class Code_Node Manage a block of C++ code in the Fluid design. This node manages an arbitrary block of code inside a function that will @@ -578,12 +579,12 @@ int Fl_Function_Type::has_signature(const char *rtype, const char *sig) const { */ /// Prototype for code to be used by the factory. -Fl_Code_Type Fl_Code_type; +Code_Node Code_Node::prototype; /** Constructor. */ -Fl_Code_Type::Fl_Code_Type() : +Code_Node::Code_Node() : cursor_position_(0), code_input_scroll_row(0), code_input_scroll_col(0) @@ -596,8 +597,8 @@ Fl_Code_Type::Fl_Code_Type() : \param[in] strategy add code after current or as last child \return new Code node */ -Fl_Type *Fl_Code_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Code_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { @@ -607,9 +608,9 @@ Fl_Type *Fl_Code_Type::make(Strategy strategy) { } if (!p) { fl_message("Please select a function"); - return 0; + return nullptr; } - Fl_Code_Type *o = new Fl_Code_Type(); + Code_Node *o = new Code_Node(); o->name("printf(\"Hello, World!\\n\");"); o->add(anchor, strategy); o->factory = this; @@ -619,10 +620,10 @@ Fl_Type *Fl_Code_Type::make(Strategy strategy) { /** Open the code_panel or an external editor to edit this code section. */ -void Fl_Code_Type::open() { +void Code_Node::open() { // Using an external code editor? Open it.. - if ( G_use_external_editor && G_external_editor_command[0] ) { - const char *cmd = G_external_editor_command; + if ( Fluid.use_external_editor && Fluid.external_editor_command[0] ) { + const char *cmd = Fluid.external_editor_command; const char *code = name(); if (!code) code = ""; if ( editor_.open_editor(cmd, code) == 0 ) @@ -635,7 +636,7 @@ void Fl_Code_Type::open() { code_input->insert_position(cursor_position_); code_input->scroll(code_input_scroll_row, code_input_scroll_col); code_panel->show(); - const char* message = 0; + const char* message = nullptr; for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); @@ -647,7 +648,7 @@ void Fl_Code_Type::open() { message = c_check(c); if (message) { int v = fl_choice("Potential syntax error detected: %s", - "Continue Editing", "Ignore Error", NULL, message); + "Continue Editing", "Ignore Error", nullptr, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } @@ -665,21 +666,21 @@ BREAK2: /** Grab changes from an external editor and write this node. */ -void Fl_Code_Type::write(fld::io::Project_Writer &f) { +void Code_Node::write(fld::io::Project_Writer &f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { - main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents + Fluid.main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents } - Fl_Type::write(f); + Node::write(f); } /** Write the code block with the correct indentation. */ -void Fl_Code_Type::write_code1(fld::io::Code_Writer& f) { +void Code_Node::write_code1(fld::io::Code_Writer& f) { // External editor changes? If so, load changes into ram, update mtime/size if ( handle_editor_changes() == 1 ) { - main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents + Fluid.main_window->redraw(); // tell fluid to redraw; edits may affect tree's contents } // Matt: disabled f.tag(FD_TAG_GENERIC, 0); f.write_c_indented(name(), 0, '\n'); @@ -689,7 +690,7 @@ void Fl_Code_Type::write_code1(fld::io::Code_Writer& f) { /** See if external editor is open. */ -int Fl_Code_Type::is_editing() { +int Code_Node::is_editing() { return editor_.is_editing(); } @@ -700,7 +701,7 @@ int Fl_Code_Type::is_editing() { \return 0: process still running \return \>0: process finished + reaped (returns pid) */ -int Fl_Code_Type::reap_editor() { +int Code_Node::reap_editor() { return editor_.reap_editor(); } @@ -713,8 +714,8 @@ int Fl_Code_Type::reap_editor() { \todo Figure out how saving a fluid file can be intercepted to grab current contents of editor file.. */ -int Fl_Code_Type::handle_editor_changes() { - const char *newcode = 0; +int Code_Node::handle_editor_changes() { + const char *newcode = nullptr; switch ( editor_.handle_changes(&newcode) ) { case 1: { // (1)=changed name(newcode); // update value in ram @@ -727,9 +728,9 @@ int Fl_Code_Type::handle_editor_changes() { return 0; } -// ---- Fl_CodeBlock_Type implementation +// ---- CodeBlock_Node implementation -/** \class Fl_CodeBlock_Type +/** \class CodeBlock_Node Manage two blocks of C++ code enclosing its children. This node manages two lines of code that enclose all children @@ -739,20 +740,20 @@ int Fl_Code_Type::handle_editor_changes() { */ /// Prototype for a block of code to be used by the factory. -Fl_CodeBlock_Type Fl_CodeBlock_type; +CodeBlock_Node CodeBlock_Node::prototype; /** Constructor. */ -Fl_CodeBlock_Type::Fl_CodeBlock_Type() : - Fl_Type(), - after(NULL) +CodeBlock_Node::CodeBlock_Node() : + Node(), + after(nullptr) { } /** Destructor. */ -Fl_CodeBlock_Type::~Fl_CodeBlock_Type() { +CodeBlock_Node::~CodeBlock_Node() { if (after) free((void*)after); } @@ -764,8 +765,8 @@ Fl_CodeBlock_Type::~Fl_CodeBlock_Type() { \param[in] strategy add after current or as last child \return new CodeBlock */ -Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *CodeBlock_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { @@ -775,11 +776,11 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { } if (!p) { fl_message("Please select a function"); - return 0; + return nullptr; } - Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); + CodeBlock_Node *o = new CodeBlock_Node(); o->name("if (test())"); - o->after = 0; + o->after = nullptr; o->add(anchor, strategy); o->factory = this; return o; @@ -790,8 +791,8 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) { - "after" is followed by the code that comes after the children The "before" code is stored in the name() field. */ -void Fl_CodeBlock_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void CodeBlock_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); if (after) { f.write_string("after"); f.write_word(after); @@ -801,23 +802,23 @@ void Fl_CodeBlock_Type::write_properties(fld::io::Project_Writer &f) { /** Read the node specific properties. */ -void Fl_CodeBlock_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void CodeBlock_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"after")) { storestring(f.read_word(),after); } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } /** Open the codeblock_panel. */ -void Fl_CodeBlock_Type::open() { +void CodeBlock_Node::open() { if (!codeblock_panel) make_codeblock_panel(); code_before_input->value(name()); code_after_input->value(after); codeblock_panel->show(); - const char* message = 0; + const char* message = nullptr; for (;;) { // repeat as long as there are errors // event loop for (;;) { @@ -834,7 +835,7 @@ void Fl_CodeBlock_Type::open() { // alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", - "Continue Editing", "Ignore Error", NULL, message); + "Continue Editing", "Ignore Error", nullptr, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } @@ -850,7 +851,7 @@ BREAK2: /** Write the "before" code. */ -void Fl_CodeBlock_Type::write_code1(fld::io::Code_Writer& f) { +void CodeBlock_Node::write_code1(fld::io::Code_Writer& f) { const char* c = name(); f.write_c("%s%s {\n", f.indent(), c ? c : ""); f.indentation++; @@ -859,15 +860,15 @@ void Fl_CodeBlock_Type::write_code1(fld::io::Code_Writer& f) { /** Write the "after" code. */ -void Fl_CodeBlock_Type::write_code2(fld::io::Code_Writer& f) { +void CodeBlock_Node::write_code2(fld::io::Code_Writer& f) { f.indentation--; if (after) f.write_c("%s} %s\n", f.indent(), after); else f.write_c("%s}\n", f.indent()); } -// ---- Fl_Decl_Type declaration +// ---- Decl_Node declaration -/** \class Fl_Decl_Type +/** \class Decl_Node Manage the C/C++ declaration of a variable. This node manages a single line of code that can be in the header or the source @@ -877,12 +878,12 @@ void Fl_CodeBlock_Type::write_code2(fld::io::Code_Writer& f) { */ /// Prototype for a declaration to be used by the factory. -Fl_Decl_Type Fl_Decl_type; +Decl_Node Decl_Node::prototype; /** Constructor. */ -Fl_Decl_Type::Fl_Decl_Type() : +Decl_Node::Decl_Node() : public_(0), static_(1) { } @@ -890,9 +891,9 @@ Fl_Decl_Type::Fl_Decl_Type() : /** Return 1 if this declaration and its parents are public. */ -int Fl_Decl_Type::is_public() const +int Decl_Node::is_public() const { - Fl_Type *p = parent; + Node *p = parent; while (p && !p->is_decl_block()) p = p->parent; if(p && p->is_public() && public_) return public_; @@ -906,8 +907,8 @@ int Fl_Decl_Type::is_public() const \param[in] strategy add after current or as last child \return new Declaration node */ -Fl_Type *Fl_Decl_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Decl_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { @@ -915,7 +916,7 @@ Fl_Type *Fl_Decl_Type::make(Strategy strategy) { strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Decl_Type *o = new Fl_Decl_Type(); + Decl_Node *o = new Decl_Node(); o->public_ = 0; o->static_ = 1; o->name("int x;"); @@ -929,8 +930,8 @@ Fl_Type *Fl_Decl_Type::make(Strategy strategy) { - "private"/"public"/"protected" - "local"/"global" if this is static or not */ -void Fl_Decl_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void Decl_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); switch (public_) { case 0: f.write_string("private"); break; case 1: f.write_string("public"); break; @@ -945,7 +946,7 @@ void Fl_Decl_Type::write_properties(fld::io::Project_Writer &f) { /** Read the specific properties. */ -void Fl_Decl_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Decl_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"public")) { public_ = 1; } else if (!strcmp(c,"private")) { @@ -957,14 +958,14 @@ void Fl_Decl_Type::read_property(fld::io::Project_Reader &f, const char *c) { } else if (!strcmp(c,"global")) { static_ = 0; } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } /** Open the decl_panel to edit this node. */ -void Fl_Decl_Type::open() { +void Decl_Node::open() { if (!decl_panel) make_decl_panel(); decl_input->buffer()->text(name()); if (is_in_class()) { @@ -979,7 +980,7 @@ void Fl_Decl_Type::open() { const char *c = comment(); decl_comment_input->buffer()->text(c?c:""); decl_panel->show(); - const char* message = 0; + const char* message = nullptr; for (;;) { // repeat as long as there are errors // event loop for (;;) { @@ -995,7 +996,7 @@ void Fl_Decl_Type::open() { // alert user if (message) { int v = fl_choice("Potential syntax error detected: %s", - "Continue Editing", "Ignore Error", NULL, message); + "Continue Editing", "Ignore Error", nullptr, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } @@ -1003,26 +1004,26 @@ void Fl_Decl_Type::open() { name(c); if (is_in_class()) { if (public_!=decl_class_choice->value()) { - set_modflag(1); + Fluid.proj.set_modflag(1); public_ = decl_class_choice->value(); } } else { if (public_!=(decl_choice->value()&1)) { - set_modflag(1); + Fluid.proj.set_modflag(1); public_ = (decl_choice->value()&1); } if (static_!=((decl_choice->value()>>1)&1)) { - set_modflag(1); + Fluid.proj.set_modflag(1); static_ = ((decl_choice->value()>>1)&1); } } c = decl_comment_input->buffer()->text(); if (c && *c) { - if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } + if (!comment() || strcmp(c, comment())) { Fluid.proj.set_modflag(1); redraw_browser(); } comment(c); } else { - if (comment()) { set_modflag(1); redraw_browser(); } - comment(0); + if (comment()) { Fluid.proj.set_modflag(1); redraw_browser(); } + comment(nullptr); } if (c) free((void*)c); break; @@ -1036,7 +1037,7 @@ BREAK2: \todo There are a lot of side effect in this node depending on the given text and the parent node. They need to be understood and documented. */ -void Fl_Decl_Type::write_code1(fld::io::Code_Writer& f) { +void Decl_Node::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (!c) return; // handle a few keywords differently if inside a class @@ -1100,9 +1101,9 @@ void Fl_Decl_Type::write_code1(fld::io::Code_Writer& f) { } } -// ---- Fl_Data_Type declaration +// ---- Data_Node declaration -/** \class Fl_Data_Type +/** \class Data_Node Manage data from an external arbitrary file. The content of the file will be stored in binary inside the generated @@ -1110,21 +1111,21 @@ void Fl_Decl_Type::write_code1(fld::io::Code_Writer& f) { */ /// Prototype for a data node to be used by the factory. -Fl_Data_Type Fl_Data_type; +Data_Node Data_Node::prototype; /** Constructor. */ -Fl_Data_Type::Fl_Data_Type() : - Fl_Decl_Type(), - filename_(NULL), +Data_Node::Data_Node() : + Decl_Node(), + filename_(nullptr), text_mode_(0) { } /** Destructor. */ -Fl_Data_Type::~Fl_Data_Type() { +Data_Node::~Data_Node() { if (filename_) free((void*)filename_); } @@ -1134,8 +1135,8 @@ Fl_Data_Type::~Fl_Data_Type() { \param[in] strategy add after current or as last child \return new inline data node */ -Fl_Type *Fl_Data_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Data_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { @@ -1143,10 +1144,10 @@ Fl_Type *Fl_Data_Type::make(Strategy strategy) { strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Data_Type *o = new Fl_Data_Type(); + Data_Node *o = new Data_Node(); o->public_ = 1; o->static_ = 1; - o->filename_ = 0; + o->filename_ = nullptr; o->text_mode_ = 0; o->name("myInlineData"); o->add(anchor, strategy); @@ -1159,8 +1160,8 @@ Fl_Type *Fl_Data_Type::make(Strategy strategy) { - "filename" followed by the filename of the file to inline - "textmode" if data is written in ASCII vs. binary */ -void Fl_Data_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Decl_Type::write_properties(f); +void Data_Node::write_properties(fld::io::Project_Writer &f) { + Decl_Node::write_properties(f); if (filename_) { f.write_string("filename"); f.write_word(filename_); @@ -1176,7 +1177,7 @@ void Fl_Data_Type::write_properties(fld::io::Project_Writer &f) { /** Read specific properties. */ -void Fl_Data_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Data_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"filename")) { storestring(f.read_word(), filename_, 1); } else if (!strcmp(c,"textmode")) { @@ -1184,14 +1185,14 @@ void Fl_Data_Type::read_property(fld::io::Project_Reader &f, const char *c) { } else if (!strcmp(c,"compressed")) { text_mode_ = 2; } else { - Fl_Decl_Type::read_property(f, c); + Decl_Node::read_property(f, c); } } /** Open the data_panel to edit this node. */ -void Fl_Data_Type::open() { +void Data_Node::open() { if (!data_panel) make_data_panel(); data_input->value(name()); if (is_in_class()) { @@ -1214,12 +1215,12 @@ void Fl_Data_Type::open() { if (w == data_panel_cancel) goto BREAK2; else if (w == data_panel_ok) break; else if (w == data_filebrowser) { - enter_project_dir(); - const char *fn = fl_file_chooser("Load Inline Data", 0L, data_filename->value(), 1); - leave_project_dir(); + Fluid.proj.enter_project_dir(); + const char *fn = fl_file_chooser("Load Inline Data", nullptr, data_filename->value(), 1); + Fluid.proj.leave_project_dir(); if (fn) { if (strcmp(fn, data_filename->value())) - set_modflag(1); + Fluid.proj.set_modflag(1); data_filename->value(fn); } } @@ -1246,27 +1247,27 @@ void Fl_Data_Type::open() { if (n==q) { OOPS: int v = fl_choice("%s", - "Continue Editing", "Ignore Error", NULL, + "Continue Editing", "Ignore Error", nullptr, "Variable name must be a C identifier"); if (v==0) { free(s); continue; } // Continue Editing //if (v==1) { } // Ignore Error and close dialog } - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); name(n); free(s); // store flags if (is_in_class()) { if (public_!=data_class_choice->value()) { - set_modflag(1); + Fluid.proj.set_modflag(1); public_ = data_class_choice->value(); } } else { if (public_!=(data_choice->value()&1)) { - set_modflag(1); + Fluid.proj.set_modflag(1); public_ = (data_choice->value()&1); } if (static_!=((data_choice->value()>>1)&1)) { - set_modflag(1); + Fluid.proj.set_modflag(1); static_ = ((data_choice->value()>>1)&1); } } @@ -1276,22 +1277,22 @@ void Fl_Data_Type::open() { // store the filename c = data_filename->value(); if (filename_ && strcmp(filename_, data_filename->value())) - set_modflag(1); + Fluid.proj.set_modflag(1); else if (!filename_ && *c) - set_modflag(1); - if (filename_) { free((void*)filename_); filename_ = 0L; } + Fluid.proj.set_modflag(1); + if (filename_) { free((void*)filename_); filename_ = nullptr; } if (c && *c) filename_ = fl_strdup(c); // store the comment c = data_comment_input->buffer()->text(); if (c && *c) { - if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } + if (!comment() || strcmp(c, comment())) { Fluid.proj.set_modflag(1); redraw_browser(); } comment(c); } else { - if (comment()) { set_modflag(1); redraw_browser(); } - comment(0); + if (comment()) { Fluid.proj.set_modflag(1); redraw_browser(); } + comment(nullptr); } if (c) free((void*)c); - set_modflag(1); + Fluid.proj.set_modflag(1); break; } BREAK2: @@ -1301,19 +1302,19 @@ BREAK2: /** Write the content of the external file inline into the source code. */ -void Fl_Data_Type::write_code1(fld::io::Code_Writer& f) { - const char *message = 0; +void Data_Node::write_code1(fld::io::Code_Writer& f) { + const char *message = nullptr; const char *c = name(); if (!c) return; const char *fn = filename_; - char *data = 0; + char *data = nullptr; int nData = -1; int uncompressedDataSize = 0; // path should be set correctly already if (filename_ && !f.write_codeview) { - enter_project_dir(); + Fluid.proj.enter_project_dir(); FILE *f = fl_fopen(filename_, "rb"); - leave_project_dir(); + Fluid.proj.leave_project_dir(); if (!f) { message = "Can't include data from file. Can't open"; } else { @@ -1426,9 +1427,9 @@ void Fl_Data_Type::write_code1(fld::io::Code_Writer& f) { } } // if we are in interactive mode, we pop up a warning dialog - // giving the error: (batch_mode && !write_codeview) ??? + // giving the error: (Fluid.batch_mode && !write_codeview) ??? if (message && !f.write_codeview) { - if (batch_mode) + if (Fluid.batch_mode) fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn); else fl_alert("%s\n%s\n", message, fn); @@ -1436,9 +1437,9 @@ void Fl_Data_Type::write_code1(fld::io::Code_Writer& f) { if (data) free(data); } -// ---- Fl_DeclBlock_Type declaration +// ---- DeclBlock_Node declaration -/** \class Fl_DeclBlock_Type +/** \class DeclBlock_Node Manage a declaration block. Declaration blocks have two text field that are written before and after @@ -1447,21 +1448,21 @@ void Fl_Data_Type::write_code1(fld::io::Code_Writer& f) { */ /// Prototype for a declaration block to be used by the factory. -Fl_DeclBlock_Type Fl_DeclBlock_type; +DeclBlock_Node DeclBlock_Node::prototype; /** Constructor. */ -Fl_DeclBlock_Type::Fl_DeclBlock_Type() : - Fl_Type(), - after(NULL), +DeclBlock_Node::DeclBlock_Node() : + Node(), + after(nullptr), write_map_(CODE_IN_SOURCE) { } /** Destructor. */ -Fl_DeclBlock_Type::~Fl_DeclBlock_Type() { +DeclBlock_Node::~DeclBlock_Node() { if (after) ::free((void*)after); } @@ -1469,7 +1470,7 @@ Fl_DeclBlock_Type::~Fl_DeclBlock_Type() { /** Return 1 if this block is public. */ -int Fl_DeclBlock_Type::is_public() const { +int DeclBlock_Node::is_public() const { return ((write_map_&CODE_IN_HEADER) != 0); } @@ -1478,15 +1479,15 @@ int Fl_DeclBlock_Type::is_public() const { \param[in] strategy add after current or as last child \return new Declaration Block node */ -Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *DeclBlock_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type(); + DeclBlock_Node *o = new DeclBlock_Node(); o->name("#if 1"); o->write_map_ = CODE_IN_SOURCE; o->after = fl_strdup("#endif"); @@ -1500,8 +1501,8 @@ Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) { - "public"/"protected" - "after" followed by the second code block. */ -void Fl_DeclBlock_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void DeclBlock_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); // deprecated if (is_public()) f.write_string("public"); // new way to map declaration block to various parts of the generated code @@ -1514,7 +1515,7 @@ void Fl_DeclBlock_Type::write_properties(fld::io::Project_Writer &f) { /** Read the specific properties. */ -void Fl_DeclBlock_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void DeclBlock_Node::read_property(fld::io::Project_Reader &f, const char *c) { if(!strcmp(c,"public")) { write_map_ |= CODE_IN_HEADER; } else if(!strcmp(c,"protected")) { @@ -1524,14 +1525,14 @@ void Fl_DeclBlock_Type::read_property(fld::io::Project_Reader &f, const char *c) } else if (!strcmp(c,"after")) { storestring(f.read_word(),after); } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } /** Open the declblock_panel to edit this node. */ -void Fl_DeclBlock_Type::open() { +void DeclBlock_Node::open() { // build dialog box if (!declblock_panel) make_declblock_panel(); // preset all values @@ -1545,7 +1546,7 @@ void Fl_DeclBlock_Type::open() { declblock_comment_input->buffer()->text(c?c:""); // show modal dialog and loop until satisfied declblock_panel->show(); - const char* message = 0; + const char* message = nullptr; for (;;) { // repeat as long as there are errors for (;;) { Fl_Widget* w = Fl::readqueue(); @@ -1563,7 +1564,7 @@ void Fl_DeclBlock_Type::open() { message = c_check(b&&b[0]=='#' ? b+1 : b); if (message) { int v = fl_choice("Potential syntax error detected: %s", - "Continue Editing", "Ignore Error", NULL, message); + "Continue Editing", "Ignore Error", nullptr, message); if (v==0) continue; // Continue Editing //if (v==1) { } // Ignore Error and close dialog } @@ -1573,54 +1574,54 @@ void Fl_DeclBlock_Type::open() { if (write_map_ & STATIC_IN_HEADER) { if (declblock_static_header->value()==0) { write_map_ &= ~STATIC_IN_HEADER; - set_modflag(1); + Fluid.proj.set_modflag(1); } } else { if (declblock_static_header->value()) { write_map_ |= STATIC_IN_HEADER; - set_modflag(1); + Fluid.proj.set_modflag(1); } } if (write_map_ & STATIC_IN_SOURCE) { if (declblock_static_source->value()==0) { write_map_ &= ~STATIC_IN_SOURCE; - set_modflag(1); + Fluid.proj.set_modflag(1); } } else { if (declblock_static_source->value()) { write_map_ |= STATIC_IN_SOURCE; - set_modflag(1); + Fluid.proj.set_modflag(1); } } if (write_map_ & CODE_IN_HEADER) { if (declblock_code_header->value()==0) { write_map_ &= ~CODE_IN_HEADER; - set_modflag(1); + Fluid.proj.set_modflag(1); } } else { if (declblock_code_header->value()) { write_map_ |= CODE_IN_HEADER; - set_modflag(1); + Fluid.proj.set_modflag(1); } } if (write_map_ & CODE_IN_SOURCE) { if (declblock_code_source->value()==0) { write_map_ &= ~CODE_IN_SOURCE; - set_modflag(1); + Fluid.proj.set_modflag(1); } } else { if (declblock_code_source->value()) { write_map_ |= CODE_IN_SOURCE; - set_modflag(1); + Fluid.proj.set_modflag(1); } } c = declblock_comment_input->buffer()->text(); if (c && *c) { - if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } + if (!comment() || strcmp(c, comment())) { Fluid.proj.set_modflag(1); redraw_browser(); } comment(c); } else { - if (comment()) { set_modflag(1); redraw_browser(); } - comment(0); + if (comment()) { Fluid.proj.set_modflag(1); redraw_browser(); } + comment(nullptr); } if (c) free((void*)c); break; @@ -1633,7 +1634,7 @@ BREAK2: Write the \b before static code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ -void Fl_DeclBlock_Type::write_static(fld::io::Code_Writer& f) { +void DeclBlock_Node::write_static(fld::io::Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & STATIC_IN_HEADER) @@ -1646,7 +1647,7 @@ void Fl_DeclBlock_Type::write_static(fld::io::Code_Writer& f) { /** Write the \b after static code to the source file, and to the header file if declared public. */ -void Fl_DeclBlock_Type::write_static_after(fld::io::Code_Writer& f) { +void DeclBlock_Node::write_static_after(fld::io::Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & STATIC_IN_HEADER) @@ -1660,7 +1661,7 @@ void Fl_DeclBlock_Type::write_static_after(fld::io::Code_Writer& f) { Write the \b before code to the source file, and to the header file if declared public. The before code is stored in the name() field. */ -void Fl_DeclBlock_Type::write_code1(fld::io::Code_Writer& f) { +void DeclBlock_Node::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (c && *c) { if (write_map_ & CODE_IN_HEADER) @@ -1673,7 +1674,7 @@ void Fl_DeclBlock_Type::write_code1(fld::io::Code_Writer& f) { /** Write the \b after code to the source file, and to the header file if declared public. */ -void Fl_DeclBlock_Type::write_code2(fld::io::Code_Writer& f) { +void DeclBlock_Node::write_code2(fld::io::Code_Writer& f) { const char* c = after; if (c && *c) { if (write_map_ & CODE_IN_HEADER) @@ -1683,9 +1684,9 @@ void Fl_DeclBlock_Type::write_code2(fld::io::Code_Writer& f) { } } -// ---- Fl_Comment_Type declaration +// ---- Comment_Node declaration -/** \class Fl_Comment_Type +/** \class Comment_Node Manage a comment node. The comment field takes one or more lines of ASCII text. If the text starts @@ -1694,12 +1695,12 @@ void Fl_DeclBlock_Type::write_code2(fld::io::Code_Writer& f) { */ /// Prototype for a comment node to be used by the factory. -Fl_Comment_Type Fl_Comment_type; +Comment_Node Comment_Node::prototype; /** Constructor. */ -Fl_Comment_Type::Fl_Comment_Type() : +Comment_Node::Comment_Node() : in_c_(1), in_h_(1), style_(0) @@ -1710,8 +1711,8 @@ Fl_Comment_Type::Fl_Comment_Type() : \param[in] strategy add after current or as last child \return new Comment node */ -Fl_Type *Fl_Comment_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Comment_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_code_block()) { @@ -1719,7 +1720,7 @@ Fl_Type *Fl_Comment_Type::make(Strategy strategy) { strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Comment_Type *o = new Fl_Comment_Type(); + Comment_Node *o = new Comment_Node(); o->in_c_ = 1; o->in_h_ = 1; o->style_ = 0; @@ -1734,8 +1735,8 @@ Fl_Type *Fl_Comment_Type::make(Strategy strategy) { - "in_source"/"not_in_source" if the comment will be written to the source code - "in_header"/"not_in_header" if the comment will be written to the header file */ -void Fl_Comment_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void Comment_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); if (in_c_) f.write_string("in_source"); else f.write_string("not_in_source"); if (in_h_) f.write_string("in_header"); else f.write_string("not_in_header"); } @@ -1743,7 +1744,7 @@ void Fl_Comment_Type::write_properties(fld::io::Project_Writer &f) { /** Read extra properties. */ -void Fl_Comment_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Comment_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"in_source")) { in_c_ = 1; } else if (!strcmp(c,"not_in_source")) { @@ -1753,7 +1754,7 @@ void Fl_Comment_Type::read_property(fld::io::Project_Reader &f, const char *c) { } else if (!strcmp(c,"not_in_header")) { in_h_ = 0; } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } @@ -1782,7 +1783,7 @@ static void load_comments_preset(Fl_Preferences &menu) { /** Open the comment_panel to edit this node. */ -void Fl_Comment_Type::open() { +void Comment_Node::open() { if (!comment_panel) make_comment_panel(); const char *text = name(); { @@ -1838,7 +1839,7 @@ void Fl_Comment_Type::open() { fl_message("Please select an entry from this menu first."); } else if (fl_choice("Are you sure that you want to delete the entry\n" "\"%s\"\nfrom the database?", "Cancel", "Delete", - NULL, itempath)) { + nullptr, itempath)) { Fl_Preferences db(Fl_Preferences::USER_L, "fltk.org", "fluid_comments"); db.deleteEntry(itempath); comment_predefined->remove(last_selected_item); @@ -1869,8 +1870,8 @@ void Fl_Comment_Type::open() { else if (w == comment_load) { // load a comment from disk fl_file_chooser_ok_label("Use File"); - const char *fname = fl_file_chooser("Pick a comment", 0L, 0L); - fl_file_chooser_ok_label(NULL); + const char *fname = fl_file_chooser("Pick a comment", nullptr, nullptr); + fl_file_chooser_ok_label(nullptr); if (fname) { if (comment_input->buffer()->loadfile(fname)) { fl_alert("Error loading file\n%s", fname); @@ -1891,7 +1892,7 @@ void Fl_Comment_Type::open() { in_h_ = comment_in_header->value(); mod = 1; } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); break; } BREAK2: @@ -1901,7 +1902,7 @@ BREAK2: /** Write the comment to the files. */ -void Fl_Comment_Type::write_code1(fld::io::Code_Writer& f) { +void Comment_Node::write_code1(fld::io::Code_Writer& f) { const char* c = name(); if (!c) return; if (!in_c_ && !in_h_) return; @@ -1941,29 +1942,29 @@ void Fl_Comment_Type::write_code1(fld::io::Code_Writer& f) { free(txt); } -// ---- Fl_Class_Type declaration +// ---- Class_Node declaration -/** \class Fl_Class_Type +/** \class Class_Node Manage a class declaration and implementation. */ /// Prototype for a class node to be used by the factory. -Fl_Class_Type Fl_Class_type; +Class_Node Class_Node::prototype; /** Constructor. */ -Fl_Class_Type::Fl_Class_Type() : - Fl_Type(), - subclass_of(NULL), +Class_Node::Class_Node() : + Node(), + subclass_of(nullptr), public_(1), - class_prefix(NULL) + class_prefix(nullptr) { } /** Destructor. */ -Fl_Class_Type::~Fl_Class_Type() { +Class_Node::~Class_Node() { if (subclass_of) free((void*)subclass_of); if (class_prefix) @@ -1973,14 +1974,14 @@ Fl_Class_Type::~Fl_Class_Type() { /** Return 1 if this class is marked public. */ -int Fl_Class_Type::is_public() const { +int Class_Node::is_public() const { return public_; } /** Set the prefixx string. */ -void Fl_Class_Type::prefix(const char*p) { +void Class_Node::prefix(const char*p) { free((void*) class_prefix); class_prefix=fl_strdup(p ? p : "" ); } @@ -1990,8 +1991,8 @@ void Fl_Class_Type::prefix(const char*p) { \param[in] strategy add after current or as last child \return new Class node */ -Fl_Type *Fl_Class_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Class_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && !p->is_decl_block()) { @@ -1999,10 +2000,10 @@ Fl_Type *Fl_Class_Type::make(Strategy strategy) { strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Class_Type *o = new Fl_Class_Type(); + Class_Node *o = new Class_Node(); o->name("UserInterface"); - o->class_prefix = NULL; - o->subclass_of = NULL; + o->class_prefix = nullptr; + o->subclass_of = nullptr; o->public_ = 1; o->add(anchor, strategy); o->factory = this; @@ -2014,8 +2015,8 @@ Fl_Type *Fl_Class_Type::make(Strategy strategy) { - ":" followed by the super class - "private"/"protected" */ -void Fl_Class_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Type::write_properties(f); +void Class_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); if (subclass_of) { f.write_string(":"); f.write_word(subclass_of); @@ -2029,7 +2030,7 @@ void Fl_Class_Type::write_properties(fld::io::Project_Writer &f) { /** Read additional properties. */ -void Fl_Class_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Class_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"private")) { public_ = 0; } else if (!strcmp(c,"protected")) { @@ -2037,14 +2038,14 @@ void Fl_Class_Type::read_property(fld::io::Project_Reader &f, const char *c) { } else if (!strcmp(c,":")) { storestring(f.read_word(), subclass_of); } else { - Fl_Type::read_property(f, c); + Node::read_property(f, c); } } /** Open the class_panel to edit the class name and superclass name. */ -void Fl_Class_Type::open() { +void Class_Node::open() { if (!class_panel) make_class_panel(); char fullname[FL_PATH_MAX]=""; if (prefix() && strlen(prefix())) @@ -2057,9 +2058,9 @@ void Fl_Class_Type::open() { const char *c = comment(); c_comment_input->buffer()->text(c?c:""); class_panel->show(); - const char* message = 0; + const char* message = nullptr; - char *na=0,*pr=0,*p=0; // name and prefix substrings + char *na=nullptr,*pr=nullptr,*p=nullptr; // name and prefix substrings for (;;) { // repeat as long as there are errors // we don;t give the option to ignore this error here because code depends @@ -2099,15 +2100,15 @@ void Fl_Class_Type::open() { storestring(c, subclass_of); if (public_ != c_public_button->value()) { public_ = c_public_button->value(); - set_modflag(1); + Fluid.proj.set_modflag(1); } c = c_comment_input->buffer()->text(); if (c && *c) { - if (!comment() || strcmp(c, comment())) { set_modflag(1); redraw_browser(); } + if (!comment() || strcmp(c, comment())) { Fluid.proj.set_modflag(1); redraw_browser(); } comment(c); } else { - if (comment()) { set_modflag(1); redraw_browser(); } - comment(0); + if (comment()) { Fluid.proj.set_modflag(1); redraw_browser(); } + comment(nullptr); } if (c) free((void*)c); break; @@ -2119,7 +2120,7 @@ BREAK2: /** Write the header code that declares this class. */ -void Fl_Class_Type::write_code1(fld::io::Code_Writer& f) { +void Class_Node::write_code1(fld::io::Code_Writer& f) { parent_class = current_class; current_class = this; write_public_state = 0; @@ -2136,7 +2137,7 @@ void Fl_Class_Type::write_code1(fld::io::Code_Writer& f) { /** Write the header code that ends the declaration of this class. */ -void Fl_Class_Type::write_code2(fld::io::Code_Writer& f) { +void Class_Node::write_code2(fld::io::Code_Writer& f) { f.write_h("};\n"); current_class = parent_class; } @@ -2144,11 +2145,11 @@ void Fl_Class_Type::write_code2(fld::io::Code_Writer& f) { /** Return 1 if this class contains a function with the given signature. */ -int Fl_Type::has_function(const char *rtype, const char *sig) const { - Fl_Type *child; +int Node::has_function(const char *rtype, const char *sig) const { + Node *child; for (child = next; child && child->level > level; child = child->next) { - if (child->level == level+1 && child->is_a(ID_Function)) { - const Fl_Function_Type *fn = (const Fl_Function_Type*)child; + if (child->level == level+1 && child->is_a(Type::Function)) { + const Function_Node *fn = (const Function_Node*)child; if (fn->has_signature(rtype, sig)) return 1; } diff --git a/fluid/nodes/Function_Node.h b/fluid/nodes/Function_Node.h new file mode 100644 index 000000000..ac8bcdcc2 --- /dev/null +++ b/fluid/nodes/Function_Node.h @@ -0,0 +1,277 @@ +// +// C function Node header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_NODES_FUNCTION_NODE_H +#define FLUID_NODES_FUNCTION_NODE_H + +#include "nodes/Node.h" + +#include "app/Image_Asset.h" +#ifdef _WIN32 +#include "tools/ExternalCodeEditor_WIN32.h" +#else +#include "tools/ExternalCodeEditor_UNIX.h" +#endif + +#include +#include +#include +#include + +#include +#include + +extern class Class_Node *current_class; + +int has_toplevel_function(const char *rtype, const char *sig); + +const char *c_check(const char *c, int type = 0); + +// ---- Function_Node declaration + +class Function_Node : public Node +{ +public: + typedef Node super; + static Function_Node prototype; +private: + const char* return_type; + char public_, cdecl_, constructor, havewidgets; +public: + Function_Node(); + ~Function_Node(); + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void open() override; + int ismain() {return name_ == nullptr;} + const char *type_name() override {return "Function";} + const char *title() override { + return name() ? name() : "main()"; + } + int can_have_children() const override {return 1;} + int is_code_block() const override {return 1;} + int is_public() const override; + Type type() const override { return Type::Function; } + bool is_a(Type inType) const override { return (inType==Type::Function) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int has_signature(const char *, const char*) const; +}; + +// ---- Code_Node declaration + +class Code_Node : public Node +{ +public: + typedef Node super; + static Code_Node prototype; +private: + ExternalCodeEditor editor_; + int cursor_position_; + int code_input_scroll_row; + int code_input_scroll_col; +public: + Code_Node(); + Node *make(Strategy strategy) override; + void write(fld::io::Project_Writer &f) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override { } + void open() override; + const char *type_name() override {return "code";} + int is_code_block() const override {return 0;} + Type type() const override { return Type::Code; } + bool is_a(Type inType) const override { return (inType==Type::Code) ? true : super::is_a(inType); } + int is_public() const override { return -1; } + int is_editing(); + int reap_editor(); + int handle_editor_changes(); +}; + +// ---- CodeBlock_Node declaration + +class CodeBlock_Node : public Node +{ +public: + typedef Node super; + static CodeBlock_Node prototype; +private: + const char* after; +public: + CodeBlock_Node(); + ~CodeBlock_Node(); + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void open() override; + const char *type_name() override {return "codeblock";} + int is_code_block() const override {return 1;} + int can_have_children() const override {return 1;} + int is_public() const override { return -1; } + Type type() const override { return Type::CodeBlock; } + bool is_a(Type inType) const override { return (inType==Type::CodeBlock) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; +}; + +// ---- Decl_Node declaration + +class Decl_Node : public Node +{ +public: + typedef Node super; + static Decl_Node prototype; +protected: + char public_; + char static_; + +public: + Decl_Node(); + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override { } + void open() override; + const char *type_name() override {return "decl";} + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int is_public() const override; + Type type() const override { return Type::Decl; } + bool is_a(Type inType) const override { return (inType==Type::Decl) ? true : super::is_a(inType); } +}; + +// ---- Data_Node declaration + +class Data_Node : public Decl_Node +{ +public: + typedef Decl_Node super; + static Data_Node prototype; +private: + const char *filename_; + int text_mode_; + +public: + Data_Node(); + ~Data_Node(); + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override {} + void open() override; + const char *type_name() override {return "data";} + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + Type type() const override { return Type::Data; } + bool is_a(Type inType) const override { return (inType==Type::Data) ? true : super::is_a(inType); } +}; + +// ---- DeclBlock_Node declaration + +class DeclBlock_Node : public Node +{ +public: + typedef Node super; + static DeclBlock_Node prototype; +private: + enum { + CODE_IN_HEADER = 1, + CODE_IN_SOURCE = 2, + STATIC_IN_HEADER = 4, + STATIC_IN_SOURCE = 8 + }; + const char* after; ///< code after all children of this block + int write_map_; ///< see enum above + +public: + DeclBlock_Node(); + ~DeclBlock_Node(); + Node *make(Strategy strategy) override; + void write_static(fld::io::Code_Writer& f) override; + void write_static_after(fld::io::Code_Writer& f) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void open() override; + const char *type_name() override {return "declblock";} + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int can_have_children() const override {return 1;} + int is_decl_block() const override {return 1;} + int is_public() const override; + Type type() const override { return Type::DeclBlock; } + bool is_a(Type inType) const override { return (inType==Type::DeclBlock) ? true : super::is_a(inType); } +}; + +// ---- Comment_Node declaration + +class Comment_Node : public Node +{ +public: + typedef Node super; + static Comment_Node prototype; +private: + char in_c_, in_h_, style_; + +public: + Comment_Node(); + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override { } + void open() override; + const char *type_name() override {return "comment";} + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int is_public() const override { return 1; } + Type type() const override { return Type::Comment; } + bool is_a(Type inType) const override { return (inType==Type::Comment) ? true : super::is_a(inType); } +}; + +// ---- Class_Node declaration + +class Class_Node : public Node +{ +public: + typedef Node super; + static Class_Node prototype; +private: + const char* subclass_of; + char public_; + const char* class_prefix; +public: + Class_Node(); + ~Class_Node(); + // state variables for output: + char write_public_state; // true when public: has been printed + Class_Node* parent_class; // save class if nested +// + Node *make(Strategy strategy) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void open() override; + const char *type_name() override {return "class";} + int can_have_children() const override {return 1;} + int is_decl_block() const override {return 1;} + int is_class() const override {return 1;} + int is_public() const override; + Type type() const override { return Type::Class; } + bool is_a(Type inType) const override { return (inType==Type::Class) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + + // class prefix attribute access + void prefix(const char* p); + const char* prefix() const {return class_prefix;} +}; + +#endif // FLUID_NODES_FUNCTION_NODE_H diff --git a/fluid/nodes/Fl_Grid_Type.cxx b/fluid/nodes/Grid_Node.cxx similarity index 70% rename from fluid/nodes/Fl_Grid_Type.cxx rename to fluid/nodes/Grid_Node.cxx index 03d6620ea..06f6d4166 100644 --- a/fluid/nodes/Fl_Grid_Type.cxx +++ b/fluid/nodes/Grid_Node.cxx @@ -1,7 +1,7 @@ // -// Fl_Grid object code for the Fast Light Tool Kit (FLTK). +// Grid Node code for the Fast Light Tool Kit (FLTK). // -// Copyright 2023 by Bill Spitzak and others. +// Copyright 2023-2025 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 @@ -14,11 +14,11 @@ // https://www.fltk.org/bugs.php // -#include "nodes/Fl_Grid_Type.h" +#include "nodes/Grid_Node.h" -#include "app/fluid.h" -#include "app/Fd_Snap_Action.h" -#include "app/undo.h" +#include "Fluid.h" +#include "app/Snap_Action.h" +#include "proj/undo.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" @@ -35,6 +35,12 @@ #include #include +// TODO: better grid overlay? +// TODO: grid_child_cb should move all selected cells, not just the current_selected. +// TODO: buttons to add and delete rows and columns in the widget dialog +// TODO: ways to resize rows and columns, add and delete them in the project window, pulldown menu? +// TODO: alignment can be FL_GRID_LEFT|FL_GRID_VERTICAL? + // ---- Fl_Grid_Proxy --------------------------------------------------- MARK: - /** @@ -45,7 +51,7 @@ */ Fl_Grid_Proxy::Fl_Grid_Proxy(int X,int Y,int W,int H) : Fl_Grid(X,Y,W,H), - transient_(NULL), + transient_(nullptr), num_transient_(0), cap_transient_(0) { @@ -63,7 +69,7 @@ Fl_Grid_Proxy::~Fl_Grid_Proxy() { // Override group's resize behavior to do nothing to children: void Fl_Grid_Proxy::resize(int X, int Y, int W, int H) { - if (Fl_Type::allow_layout > 0) { + if (Fluid.proj.tree.allow_layout > 0) { Fl_Grid::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); @@ -75,7 +81,7 @@ void Fl_Grid_Proxy::resize(int X, int Y, int W, int H) { Override draw() to make groups with no box or flat box background visible. */ void Fl_Grid_Proxy::draw() { - if (show_ghosted_outline && (box() == FL_NO_BOX)) { + if (Fluid.show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Grid::draw(); @@ -131,27 +137,27 @@ void Fl_Grid_Proxy::move_cell(Fl_Widget *in_child, int to_row, int to_col, int h } if ((to_row < 0) || (to_row+rowspan > rows())) return; if ((to_col < 0) || (to_col+colspan > cols())) return; - Fl_Grid::Cell *new_cell = NULL; + Fl_Grid::Cell *new_cell = nullptr; if (how == 0) { // replace old occupant in cell, making that one homeless new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else if (how == 1) { // don't replace an old occupant, making ourselves homeless // todo: colspan, rowspan? - if (cell(to_row, to_col) == NULL) { + if (cell(to_row, to_col) == nullptr) { new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else { if (old_cell) remove_cell(old_cell->row(), old_cell->col()); } } else if (how == 2) { Cell *current = cell(to_row, to_col); - if (current == NULL) { + if (current == nullptr) { new_cell = widget(in_child, to_row, to_col, rowspan, colspan, align); } else { if (old_cell) remove_cell(old_cell->row(), old_cell->col()); new_cell = transient_widget(in_child, to_row, to_col, rowspan, colspan, align); Fl_Widget *w = current->widget(); - Fl_Type::allow_layout++; + Fluid.proj.tree.allow_layout++; in_child->resize(w->x(), w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; } } if (new_cell) new_cell->minimum_size(w, h); @@ -234,7 +240,7 @@ void Fl_Grid_Proxy::transient_remove_(Fl_Widget *w) { /** Find a cell in the grid or in the transient cell list. \param[in] widget must be a child of the grid. - \return the cell, the transient cell, or NULL if neither was found. + \return the cell, the transient cell, or nullptr if neither was found. */ Fl_Grid_Proxy::Cell *Fl_Grid_Proxy::any_cell(Fl_Widget *widget) const { Cell *c = cell(widget); @@ -245,14 +251,14 @@ Fl_Grid_Proxy::Cell *Fl_Grid_Proxy::any_cell(Fl_Widget *widget) const { /** Find a cell in the transient cell list. \param[in] widget must be a child of the grid. - \return the transient cell, or NULL if it was not found. + \return the transient cell, or nullptr if it was not found. */ Fl_Grid_Proxy::Cell *Fl_Grid_Proxy::transient_cell(Fl_Widget *widget) const { for (int i=0; ilayout(3, 3); - Fl_Group::current(0); + Fl_Group::current(nullptr); return g; } -Fl_Widget *Fl_Grid_Type::enter_live_mode(int top) { +Fl_Widget *Grid_Node::enter_live_mode(int top) { Fl_Grid *grid = new Fl_Grid(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grid); } -void Fl_Grid_Type::leave_live_mode() { +void Grid_Node::leave_live_mode() { } -void Fl_Grid_Type::copy_properties() +void Grid_Node::copy_properties() { super::copy_properties(); Fl_Grid *d = (Fl_Grid*)live_widget, *s =(Fl_Grid*)o; @@ -325,7 +329,7 @@ void Fl_Grid_Type::copy_properties() } } -void Fl_Grid_Type::copy_properties_for_children() { +void Grid_Node::copy_properties_for_children() { Fl_Grid *d = (Fl_Grid*)live_widget, *s =(Fl_Grid*)o; for (int i=0; ichildren(); i++) { Fl_Grid::Cell *cell = s->cell(s->child(i)); @@ -339,7 +343,7 @@ void Fl_Grid_Type::copy_properties_for_children() { d->layout(); } -void Fl_Grid_Type::write_properties(fld::io::Project_Writer &f) +void Grid_Node::write_properties(fld::io::Project_Writer &f) { super::write_properties(f); Fl_Grid* grid = (Fl_Grid*)o; @@ -404,7 +408,7 @@ void Fl_Grid_Type::write_properties(fld::io::Project_Writer &f) } } -void Fl_Grid_Type::read_property(fld::io::Project_Reader &f, const char *c) +void Grid_Node::read_property(fld::io::Project_Reader &f, const char *c) { Fl_Grid* grid = (Fl_Grid*)o; if (!strcmp(c,"dimensions")) { @@ -454,13 +458,13 @@ void Fl_Grid_Type::read_property(fld::io::Project_Reader &f, const char *c) } } -void Fl_Grid_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) { +void Grid_Node::write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate) { Fl_Grid *grid; Fl_Widget *child_widget; Fl_Grid::Cell *cell; if (!child->is_true_widget()) return super::write_parent_properties(f, child, true); grid = (Fl_Grid*)o; - child_widget = ((Fl_Widget_Type*)child)->o; + child_widget = ((Widget_Node*)child)->o; cell = grid->cell(child_widget); if (!cell) return super::write_parent_properties(f, child, true); if (encapsulate) { @@ -501,13 +505,13 @@ void Fl_Grid_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type * // NOTE: we have to do this in a loop just as ::read_property() in case a new // property is added. In the current setup, all the remaining properties // will be skipped -void Fl_Grid_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) { +void Grid_Node::read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property) { if (!child->is_true_widget()) { super::read_parent_property(f, child, property); return; } Fl_Grid *grid = (Fl_Grid*)o; - Fl_Widget *child_widget = ((Fl_Widget_Type*)child)->o; + Fl_Widget *child_widget = ((Widget_Node*)child)->o; if (!strcmp(property, "location")) { int row = -1, col = -1; const char *value = f.read_word(); @@ -540,10 +544,10 @@ void Fl_Grid_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *chi } } -void Fl_Grid_Type::write_code1(fld::io::Code_Writer& f) { +void Grid_Node::write_code1(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; - Fl_Widget_Type::write_code1(f); + Widget_Node::write_code1(f); int i, rows = grid->rows(), cols = grid->cols(); f.write_c("%s%s->layout(%d, %d);\n", f.indent(), var, rows, cols); int lm, tm, rm, bm; @@ -604,7 +608,7 @@ void Fl_Grid_Type::write_code1(fld::io::Code_Writer& f) { } } -void Fl_Grid_Type::write_code2(fld::io::Code_Writer& f) { +void Grid_Node::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Grid* grid = (Fl_Grid*)o; bool first_cell = true; @@ -613,7 +617,7 @@ void Fl_Grid_Type::write_code2(fld::io::Code_Writer& f) { Fl_Grid::Cell *cell = grid->cell(c); if (cell) { if (first_cell) { - f.write_c("%sFl_Grid::Cell *cell = NULL;\n", f.indent()); + f.write_c("%sFl_Grid::Cell *cell = 0L;\n", f.indent()); first_cell = false; } f.write_c("%scell = %s->widget(%s->child(%d), %d, %d, %d, %d, %d);\n", @@ -627,21 +631,21 @@ void Fl_Grid_Type::write_code2(fld::io::Code_Writer& f) { super::write_code2(f); } -void Fl_Grid_Type::add_child(Fl_Type* a, Fl_Type* b) { +void Grid_Node::add_child(Node* a, Node* b) { super::add_child(a, b); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); grid->redraw(); } -void Fl_Grid_Type::move_child(Fl_Type* a, Fl_Type* b) { +void Grid_Node::move_child(Node* a, Node* b) { super::move_child(a, b); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); grid->redraw(); } -void Fl_Grid_Type::remove_child(Fl_Type* a) { +void Grid_Node::remove_child(Node* a) { super::remove_child(a); Fl_Grid* grid = (Fl_Grid*)o; grid->need_layout(1); @@ -653,7 +657,7 @@ void Fl_Grid_Type::remove_child(Fl_Type* a) { FLUID, users will want to resize children. So we need to trick Fl_Grid into taking the new size as the initial size. */ -void Fl_Grid_Type::child_resized(Fl_Widget_Type *child_type) { +void Grid_Node::child_resized(Widget_Node *child_type) { Fl_Grid *grid = (Fl_Grid*)o; Fl_Widget *child = child_type->o; Fl_Grid::Cell *cell = grid->cell(child); @@ -671,10 +675,10 @@ void Fl_Grid_Type::child_resized(Fl_Widget_Type *child_type) { } /** Return the currently selected Grid widget if is a Grid Type. */ -Fl_Grid *Fl_Grid_Type::selected() { - if (current_widget && current_widget->is_a(ID_Grid)) - return ((Fl_Grid*)((Fl_Grid_Type*)current_widget)->o); - return NULL; +Fl_Grid *Grid_Node::selected() { + if (current_widget && current_widget->is_a(Type::Grid)) + return ((Fl_Grid*)((Grid_Node*)current_widget)->o); + return nullptr; } /** @@ -682,10 +686,10 @@ Fl_Grid *Fl_Grid_Type::selected() { /param[in] child /param[in] x, y pixels from the top left of the window */ -void Fl_Grid_Type::insert_child_at(Fl_Widget *child, int x, int y) { +void Grid_Node::insert_child_at(Fl_Widget *child, int x, int y) { Fl_Grid_Proxy *grid = (Fl_Grid_Proxy*)o; int row = -1, col = -1, ml, mt, grg, gcg; - grid->margin(&ml, &mt, NULL, NULL); + grid->margin(&ml, &mt, nullptr, nullptr); grid->gap(&grg, &gcg); int x0 = grid->x() + Fl::box_dx(grid->box()) + ml; int y0 = grid->y() + Fl::box_dy(grid->box()) + mt; @@ -716,7 +720,7 @@ void Fl_Grid_Type::insert_child_at(Fl_Widget *child, int x, int y) { /param[in] child */ -void Fl_Grid_Type::insert_child_at_next_free_cell(Fl_Widget *child) { +void Grid_Node::insert_child_at_next_free_cell(Fl_Widget *child) { Fl_Grid_Proxy *grid = (Fl_Grid_Proxy*)o; if (grid->cell(child)) return; // The code below would insert the new widget after the last selected one, but @@ -748,7 +752,7 @@ void Fl_Grid_Type::insert_child_at_next_free_cell(Fl_Widget *child) { \param[in] child pointer to the child type \param[in] key code of the last keypress when handling a FL_KEYBOARD event. */ -void Fl_Grid_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { +void Grid_Node::keyboard_move_child(Widget_Node *child, int key) { Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)o); Fl_Grid::Cell *cell = grid->any_cell(child->o); if (!cell) return; @@ -763,232 +767,9 @@ void Fl_Grid_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { } } -void Fl_Grid_Type::layout_widget() { - allow_layout++; +void Grid_Node::layout_widget() { + Fluid.proj.tree.allow_layout++; ((Fl_Grid*)o)->layout(); - allow_layout--; -} - - -// ---- Widget Panel Callbacks ---------------------------------------- MARK: - - -// TODO: better grid overlay? -// TODO: grid_child_cb should move all selected cells, not just the current_selected. -// TODO: buttons to add and delete rows and columns in the widget dialog -// TODO: ways to resize rows and columns, add and delete them in the project window, pulldown menu? -// TODO: alignment can be FL_GRID_LEFT|FL_GRID_VERTICAL? - -extern fld::widget::Formula_Input *widget_grid_row_input, *widget_grid_col_input, -*widget_grid_rowspan_input, *widget_grid_colspan_input; -extern Fl_Group *widget_tab_grid_child; - -void grid_child_cb(fld::widget::Formula_Input* i, void* v, int what) { - if ( !current_widget - || !current_widget->parent - || !current_widget->parent->is_a(ID_Grid)) - { - return; - } - Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; - Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); - Fl_Grid::Cell *cell = g->any_cell(child); - if (v == LOAD) { - int v = -1; - if (cell) { - switch (what & 0x00ff) { - case 8: v = cell->row(); break; - case 9: v = cell->col(); break; - case 10: v = cell->rowspan(); break; - case 11: v = cell->colspan(); break; - case 12: cell->minimum_size(&v, NULL); break; - case 13: cell->minimum_size(NULL, &v); break; - } - } - i->value(v); - } else { - undo_checkpoint(); - int v2 = -2, old_v = -2, v = i->value(); - if (i==widget_grid_row_input) v2 = widget_grid_col_input->value(); - if (i==widget_grid_col_input) v2 = widget_grid_row_input->value(); - Fl_Grid::Cell *new_cell = NULL; - if (cell) { - switch (what & 0x00ff) { - case 8: old_v = cell->row(); v2 = cell->col(); break; - case 9: old_v = cell->col(); v2 = cell->row(); break; - case 10: old_v = cell->rowspan(); break; - case 11: old_v = cell->colspan(); break; - case 12: cell->minimum_size(&old_v, &v2); break; - case 13: cell->minimum_size(&v2, &old_v); break; - } - } - switch (what & 0xff00) { - case 0x0100: v--; break; - case 0x0200: v++; break; - } - if (old_v != v) { - switch (what & 0x00ff) { - case 8: - if (v2 == -1 && v >= 0) v2 = 0; - g->move_cell(current_widget->o, v, v2, 2); i->value(v); - break; - case 9: - if (v2 == -1 && v >= 0) v2 = 0; - g->move_cell(current_widget->o, v2, v, 2); i->value(v); - break; - case 10: if (cell && cell->row()+v<=g->rows() && v>0) cell->rowspan(v); - break; - case 11: if (cell && cell->col()+v<=g->cols() && v>0) cell->colspan(v); - break; - case 12: if (cell && v>=0) cell->minimum_size(v, v2); - break; - case 13: if (cell && v>=0) cell->minimum_size(v2, v); - break; - } - if (!cell && new_cell) - new_cell->minimum_size(20, 20); - g->need_layout(true); - set_modflag(1); - } - } -} -void grid_set_row_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 8); - if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); -} -void grid_dec_row_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_row_input, v, 0x0100 + 8); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_inc_row_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_row_input, v, 0x0200 + 8); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_set_col_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 9); - if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); -} -void grid_dec_col_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_col_input, v, 0x0100 + 9); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_inc_col_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_col_input, v, 0x0200 + 9); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_set_rowspan_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 10); - if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); -} -void grid_dec_rowspan_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_rowspan_input, v, 0x0100 + 10); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_inc_rowspan_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_rowspan_input, v, 0x0200 + 10); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_set_colspan_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 11); - if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); -} -void grid_dec_colspan_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_colspan_input, v, 0x0100 + 11); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_inc_colspan_cb(Fl_Button* i, void* v) { - if (v!=LOAD) { - grid_child_cb(widget_grid_colspan_input, v, 0x0200 + 11); - widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); - } -} -void grid_set_min_wdt_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 12); -} -void grid_set_min_hgt_cb(fld::widget::Formula_Input* i, void* v) { - grid_child_cb(i, v, 13); -} - -void grid_align_horizontal_cb(Fl_Choice* i, void* v) { - if ( !current_widget - || !current_widget->parent - || !current_widget->parent->is_a(ID_Grid)) - { - return; - } - int mask = (FL_GRID_LEFT | FL_GRID_RIGHT | FL_GRID_HORIZONTAL); - Fl_Grid *g = ((Fl_Grid*)((Fl_Widget_Type*)current_widget->parent)->o); - if (v == LOAD) { - int a = FL_GRID_FILL & mask; - Fl_Grid::Cell *cell = g->cell(current_widget->o); - if (cell) { - a = cell->align() & mask; - } - const Fl_Menu_Item *mi = i->find_item_with_argument(a); - if (mi) i->value(mi); - } else { - undo_checkpoint(); - int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; - const Fl_Menu_Item *mi = i->mvalue(); - if (mi) v = (int)mi->argument(); - Fl_Grid::Cell *cell = g->cell(current_widget->o); - if (cell) { - old_v = cell->align() & mask; - if (old_v != v) { - cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); - g->need_layout(true); - g->redraw(); - set_modflag(1); - } - } - } -} - -void grid_align_vertical_cb(Fl_Choice* i, void* v) { - if ( !current_widget - || !current_widget->parent - || !current_widget->parent->is_a(ID_Grid)) - { - return; - } - int mask = (FL_GRID_TOP | FL_GRID_BOTTOM | FL_GRID_VERTICAL); - Fl_Grid *g = ((Fl_Grid*)((Fl_Widget_Type*)current_widget->parent)->o); - if (v == LOAD) { - int a = FL_GRID_FILL & mask; - Fl_Grid::Cell *cell = g->cell(current_widget->o); - if (cell) { - a = cell->align() & mask; - } - const Fl_Menu_Item *mi = i->find_item_with_argument(a); - if (mi) i->value(mi); - } else { - undo_checkpoint(); - int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; - const Fl_Menu_Item *mi = i->mvalue(); - if (mi) v = (int)mi->argument(); - Fl_Grid::Cell *cell = g->cell(current_widget->o); - if (cell) { - old_v = cell->align() & mask; - if (old_v != v) { - cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); - g->need_layout(true); - g->redraw(); - set_modflag(1); - } - } - } + Fluid.proj.tree.allow_layout--; } diff --git a/fluid/nodes/Grid_Node.h b/fluid/nodes/Grid_Node.h new file mode 100644 index 000000000..4363164ee --- /dev/null +++ b/fluid/nodes/Grid_Node.h @@ -0,0 +1,82 @@ +// +// Grid Node header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 2023-2025 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_NODES_GRID_NODE_H +#define FLUID_NODES_GRID_NODE_H + +#include "nodes/Group_Node.h" +#include + +// ---- Grid_Node --------------------------------------------------- MARK: - + +class Fl_Grid_Proxy : public Fl_Grid { +protected: + typedef struct { Fl_Widget *widget; Cell *cell; } Cell_Widget_Pair; + Cell_Widget_Pair *transient_; + int num_transient_; + int cap_transient_; + void transient_make_room_(int n); + void transient_remove_(Fl_Widget *w); +public: + Fl_Grid_Proxy(int X,int Y,int W,int H); + ~Fl_Grid_Proxy(); + void resize(int,int,int,int) override; + void draw() override; + void draw_overlay(); + void move_cell(Fl_Widget *child, int to_row, int to_col, int how = 0); + Cell* any_cell(Fl_Widget *widget) const; + Cell* transient_cell(Fl_Widget *widget) const; + Cell* transient_widget(Fl_Widget *wi, int row, int col, int row_span, int col_span, Fl_Grid_Align align = FL_GRID_FILL); + Cell* widget(Fl_Widget *wi, int row, int col, Fl_Grid_Align align = FL_GRID_FILL); + Cell* widget(Fl_Widget *wi, int row, int col, int rowspan, int colspan, Fl_Grid_Align align = FL_GRID_FILL); +}; + +class Grid_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Grid_Node prototype; +public: + Grid_Node(); + const char *type_name() override {return "Fl_Grid";} + const char *alt_type_name() override {return "fltk::GridGroup";} + Widget_Node *_make() override { return new Grid_Node(); } + Fl_Widget *widget(int X,int Y,int W,int H) override; + Type type() const override { return Type::Grid; } + bool is_a(Type inType) const override { return (inType==Type::Grid) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + void write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate) override; + void read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property) override; + Fl_Widget *enter_live_mode(int top=0) override; + void leave_live_mode() override; + void copy_properties() override; + void copy_properties_for_children() override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void add_child(Node*, Node*) override; + void move_child(Node*, Node*) override; + void remove_child(Node*) override; + void layout_widget() override; + void child_resized(Widget_Node *child); + void insert_child_at(Fl_Widget *child, int x, int y); + void insert_child_at_next_free_cell(Fl_Widget *child); + void keyboard_move_child(Widget_Node*, int key); + + static class Fl_Grid *selected(); +}; + +#endif // FLUID_NODES_GRID_NODE_H diff --git a/fluid/nodes/Fl_Group_Type.cxx b/fluid/nodes/Group_Node.cxx similarity index 69% rename from fluid/nodes/Fl_Group_Type.cxx rename to fluid/nodes/Group_Node.cxx index 5d3cba07c..d269b62ab 100644 --- a/fluid/nodes/Fl_Group_Type.cxx +++ b/fluid/nodes/Group_Node.cxx @@ -1,7 +1,7 @@ // -// Fl_Group object code for the Fast Light Tool Kit (FLTK). +// Group Node code for the Fast Light Tool Kit (FLTK). // -// Object describing an Fl_Group and links to Fl_Window_Type.C and +// Object describing an Fl_Group and links to Window_Node.C and // the Fl_Tabs widget, with special stuff to select tab items and // insure that only one is visible. // @@ -18,11 +18,11 @@ // https://www.fltk.org/bugs.php // -#include "nodes/Fl_Group_Type.h" +#include "nodes/Group_Node.h" -#include "app/fluid.h" -#include "app/undo.h" -#include "app/Fd_Snap_Action.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "app/Snap_Action.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" @@ -40,16 +40,16 @@ #include -// ---- Fl_Group_Type -------------------------------------------------- MARK: - +// ---- Group_Node -------------------------------------------------- MARK: - -Fl_Group_Type Fl_Group_type; // the "factory" +Group_Node Group_Node::prototype; /** Override group's resize behavior to do nothing to children by default. \param[in] X, Y, W, H new size */ void Fl_Group_Proxy::resize(int X, int Y, int W, int H) { - if (Fl_Type::allow_layout > 0) { + if (Fluid.proj.tree.allow_layout > 0) { Fl_Group::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); @@ -61,7 +61,7 @@ void Fl_Group_Proxy::resize(int X, int Y, int W, int H) { Override draw() to make groups with no box or flat box background visible. */ void Fl_Group_Proxy::draw() { - if (show_ghosted_outline && (box() == FL_NO_BOX)) { + if (Fluid.show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Group::draw(); @@ -71,16 +71,16 @@ void Fl_Group_Proxy::draw() { /** \brief Enlarge the group size, so all children fit within. */ -void fix_group_size(Fl_Type *tt) { - if (!tt || !tt->is_a(ID_Group)) return; - Fl_Group_Type* t = (Fl_Group_Type*)tt; +void fix_group_size(Node *tt) { + if (!tt || !tt->is_a(Type::Group)) return; + Group_Node* t = (Group_Node*)tt; int X = t->o->x(); int Y = t->o->y(); int R = X+t->o->w(); int B = Y+t->o->h(); - for (Fl_Type *nn = t->next; nn && nn->level > t->level; nn = nn->next) { + for (Node *nn = t->next; nn && nn->level > t->level; nn = nn->next) { if (nn->is_true_widget()) { - Fl_Widget_Type* n = (Fl_Widget_Type*)nn; + Widget_Node* n = (Widget_Node*)nn; int x = n->o->x(); if (x < X) X = x; int y = n->o->y(); if (y < Y) Y = y; int r = x+n->o->w();if (r > R) R = r; @@ -93,84 +93,84 @@ void fix_group_size(Fl_Type *tt) { extern void group_selected_menuitems(); void group_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { + if (!Fluid.proj.tree.current) { fl_message("No widgets selected."); return; } - if (!Fl_Type::current->is_widget()) { + if (!Fluid.proj.tree.current->is_widget()) { fl_message("Only widgets and menu items can be grouped."); return; } - if (Fl_Type::current->is_a(ID_Menu_Item)) { + if (Fluid.proj.tree.current->is_a(Type::Menu_Item)) { group_selected_menuitems(); return; } // The group will be created in the parent group of the current widget - Fl_Type *qq = Fl_Type::current->parent; - Fl_Widget_Type *q = static_cast(Fl_Type::current); - while (qq && !qq->is_a(ID_Group)) { + Node *qq = Fluid.proj.tree.current->parent; + Widget_Node *q = static_cast(Fluid.proj.tree.current); + while (qq && !qq->is_a(Type::Group)) { qq = qq->parent; } if (!qq) { fl_message("Can't create a new group here."); return; } - undo_checkpoint(); - undo_suspend(); - Fl_Type::current = qq; - Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make(Strategy::AS_LAST_CHILD)); + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + Fluid.proj.tree.current = qq; + Group_Node *n = (Group_Node*)(Group_Node::prototype.make(Strategy::AS_LAST_CHILD)); n->move_before(q); n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h()); - for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { + for (Node *t = qq->next; t && (t->level > qq->level);) { if (t->level != n->level || t == n || !t->selected) { t = t->next; continue; } - Fl_Type *nxt = t->remove(); + Node *nxt = t->remove(); t->add(n, Strategy::AS_LAST_CHILD); t = nxt; } fix_group_size(n); - Fl_Type::current = q; + Fluid.proj.tree.current = q; n->layout_widget(); widget_browser->rebuild(); - undo_resume(); - set_modflag(1); + Fluid.proj.undo.resume(); + Fluid.proj.set_modflag(1); } extern void ungroup_selected_menuitems(); void ungroup_cb(Fl_Widget *, void *) { - if (!Fl_Type::current) { + if (!Fluid.proj.tree.current) { fl_message("No widgets selected."); return; } - if (!Fl_Type::current->is_widget()) { + if (!Fluid.proj.tree.current->is_widget()) { fl_message("Only widgets and menu items can be ungrouped."); return; } - if (Fl_Type::current->is_a(ID_Menu_Item)) { + if (Fluid.proj.tree.current->is_a(Type::Menu_Item)) { ungroup_selected_menuitems(); return; } - Fl_Widget_Type *q = static_cast(Fl_Type::current); + Widget_Node *q = static_cast(Fluid.proj.tree.current); int q_level = q->level; - Fl_Type *qq = Fl_Type::current->parent; + Node *qq = Fluid.proj.tree.current->parent; while (qq && !qq->is_true_widget()) qq = qq->parent; - if (!qq || !qq->is_a(ID_Group)) { + if (!qq || !qq->is_a(Type::Group)) { fl_message("Only menu widgets inside a group can be ungrouped."); return; } - undo_checkpoint(); - undo_suspend(); - Fl_Type::current = qq; - for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + Fluid.proj.tree.current = qq; + for (Node *t = qq->next; t && (t->level > qq->level);) { if (t->level != q_level || !t->selected) { t = t->next; continue; } - Fl_Type *nxt = t->remove(); + Node *nxt = t->remove(); t->insert(qq); t = nxt; } @@ -178,29 +178,29 @@ void ungroup_cb(Fl_Widget *, void *) { qq->remove(); delete qq; // qq has no children that need to be delete } - Fl_Type::current = q; + Fluid.proj.tree.current = q; widget_browser->rebuild(); - undo_resume(); - set_modflag(1); + Fluid.proj.undo.resume(); + Fluid.proj.set_modflag(1); } -void Fl_Group_Type::ideal_size(int &w, int &h) { +void Group_Node::ideal_size(int &w, int &h) { if (parent && parent->is_true_widget()) { - Fl_Widget *p = ((Fl_Widget_Type*)parent)->o; + Fl_Widget *p = ((Widget_Node*)parent)->o; w = p->w() / 2; h = p->h() / 2; } else { w = 140; h = 140; } - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } -void Fl_Group_Type::write_code1(fld::io::Code_Writer& f) { - Fl_Widget_Type::write_code1(f); +void Group_Node::write_code1(fld::io::Code_Writer& f) { + Widget_Node::write_code1(f); } -void Fl_Group_Type::write_code2(fld::io::Code_Writer& f) { +void Group_Node::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; write_extra_code(f); f.write_c("%s%s->end();\n", f.indent(), var); @@ -212,79 +212,79 @@ void Fl_Group_Type::write_code2(fld::io::Code_Writer& f) { // This is called when o is created. If it is in the tab group make // sure it is visible: -void Fl_Group_Type::add_child(Fl_Type* cc, Fl_Type* before) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; - Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; +void Group_Node::add_child(Node* cc, Node* before) { + Widget_Node* c = (Widget_Node*)cc; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; ((Fl_Group*)o)->insert(*(c->o), b); o->redraw(); } // This is called when o is deleted. If it is in the tab group make // sure it is not visible: -void Fl_Group_Type::remove_child(Fl_Type* cc) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; +void Group_Node::remove_child(Node* cc) { + Widget_Node* c = (Widget_Node*)cc; ((Fl_Group*)o)->remove(c->o); o->redraw(); } // move, don't change selected value: -void Fl_Group_Type::move_child(Fl_Type* cc, Fl_Type* before) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; - Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; +void Group_Node::move_child(Node* cc, Node* before) { + Widget_Node* c = (Widget_Node*)cc; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; ((Fl_Group*)o)->insert(*(c->o), b); o->redraw(); } // live mode support -Fl_Widget* Fl_Group_Type::enter_live_mode(int) { +Fl_Widget* Group_Node::enter_live_mode(int) { Fl_Group *grp = new Fl_Group(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grp); } -void Fl_Group_Type::leave_live_mode() { +void Group_Node::leave_live_mode() { } /** copy all properties from the edit widget to the live widget */ -void Fl_Group_Type::copy_properties() { - Fl_Widget_Type::copy_properties(); +void Group_Node::copy_properties() { + Widget_Node::copy_properties(); } -// ---- Fl_Pack_Type --------------------------------------------------- MARK: - +// ---- Pack_Node --------------------------------------------------- MARK: - -Fl_Pack_Type Fl_Pack_type; // the "factory" +Pack_Node Pack_Node::prototype; // the "factory" const char pack_type_name[] = "Fl_Pack"; Fl_Menu_Item pack_type_menu[] = { - {"HORIZONTAL", 0, 0, (void*)Fl_Pack::HORIZONTAL}, - {"VERTICAL", 0, 0, (void*)Fl_Pack::VERTICAL}, - {0} + {"HORIZONTAL", 0, nullptr, (void*)Fl_Pack::HORIZONTAL}, + {"VERTICAL", 0, nullptr, (void*)Fl_Pack::VERTICAL}, + {nullptr} }; -Fl_Widget *Fl_Pack_Type::enter_live_mode(int) { +Fl_Widget *Pack_Node::enter_live_mode(int) { Fl_Group *grp = new Fl_Pack(o->x(), o->y(), o->w(), o->h()); return propagate_live_mode(grp); } -void Fl_Pack_Type::copy_properties() +void Pack_Node::copy_properties() { - Fl_Group_Type::copy_properties(); + Group_Node::copy_properties(); Fl_Pack *d = (Fl_Pack*)live_widget, *s =(Fl_Pack*)o; d->spacing(s->spacing()); } -// ---- Fl_Flex_Type --------------------------------------------------- MARK: - +// ---- Flex_Node --------------------------------------------------- MARK: - const char flex_type_name[] = "Fl_Flex"; Fl_Menu_Item flex_type_menu[] = { - {"HORIZONTAL", 0, 0, (void*)Fl_Flex::HORIZONTAL}, - {"VERTICAL", 0, 0, (void*)Fl_Flex::VERTICAL}, - {0}}; + {"HORIZONTAL", 0, nullptr, (void*)Fl_Flex::HORIZONTAL}, + {"VERTICAL", 0, nullptr, (void*)Fl_Flex::VERTICAL}, + {nullptr}}; -Fl_Flex_Type Fl_Flex_type; // the "factory" +Flex_Node Flex_Node::prototype; // the "factory" /** Override flex's resize behavior to do nothing to children by default. @@ -292,7 +292,7 @@ Fl_Flex_Type Fl_Flex_type; // the "factory" \param[in] X, Y, W, H new size */ void Fl_Flex_Proxy::resize(int X, int Y, int W, int H) { - if (Fl_Type::allow_layout > 0) { + if (Fluid.proj.tree.allow_layout > 0) { Fl_Flex::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); @@ -304,13 +304,13 @@ void Fl_Flex_Proxy::resize(int X, int Y, int W, int H) { Override draw() to make groups with no box or flat box background visible. */ void Fl_Flex_Proxy::draw() { - if (show_ghosted_outline && (box() == FL_NO_BOX)) { + if (Fluid.show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Flex::draw(); } -Fl_Widget *Fl_Flex_Type::enter_live_mode(int) { +Fl_Widget *Flex_Node::enter_live_mode(int) { Fl_Flex *grp = new Fl_Flex(o->x(), o->y(), o->w(), o->h()); propagate_live_mode(grp); Fl_Flex *d = grp, *s =(Fl_Flex*)o; @@ -325,9 +325,9 @@ Fl_Widget *Fl_Flex_Type::enter_live_mode(int) { return grp; } -void Fl_Flex_Type::copy_properties() +void Flex_Node::copy_properties() { - Fl_Group_Type::copy_properties(); + Group_Node::copy_properties(); Fl_Flex *d = (Fl_Flex*)live_widget, *s =(Fl_Flex*)o; int lm, tm, rm, bm; s->margin(&lm, &tm, &rm, &bm); @@ -335,7 +335,7 @@ void Fl_Flex_Type::copy_properties() d->gap( s->gap() ); } -void Fl_Flex_Type::copy_properties_for_children() { +void Flex_Node::copy_properties_for_children() { Fl_Flex *d = (Fl_Flex*)live_widget, *s =(Fl_Flex*)o; for (int i=0; ichildren(); i++) { if (s->fixed(s->child(i)) && ichildren()) { @@ -349,9 +349,9 @@ void Fl_Flex_Type::copy_properties_for_children() { d->layout(); } -void Fl_Flex_Type::write_properties(fld::io::Project_Writer &f) +void Flex_Node::write_properties(fld::io::Project_Writer &f) { - Fl_Group_Type::write_properties(f); + Group_Node::write_properties(f); Fl_Flex* flex = (Fl_Flex*)o; int lm, tm, rm, bm; flex->margin(&lm, &tm, &rm, &bm); @@ -374,7 +374,7 @@ void Fl_Flex_Type::write_properties(fld::io::Project_Writer &f) } } -void Fl_Flex_Type::read_property(fld::io::Project_Reader &f, const char *c) +void Flex_Node::read_property(fld::io::Project_Reader &f, const char *c) { Fl_Flex* flex = (Fl_Flex*)o; suspend_auto_layout = 1; @@ -399,11 +399,11 @@ void Fl_Flex_Type::read_property(fld::io::Project_Reader &f, const char *c) } f.read_word(1); // must be '}' } else { - Fl_Group_Type::read_property(f, c); + Group_Node::read_property(f, c); } } -void Fl_Flex_Type::postprocess_read() +void Flex_Node::postprocess_read() { Fl_Flex* flex = (Fl_Flex*)o; if (fixedSizeTupleSize>0) { @@ -417,12 +417,12 @@ void Fl_Flex_Type::postprocess_read() } fixedSizeTupleSize = 0; delete[] fixedSizeTuple; - fixedSizeTuple = NULL; + fixedSizeTuple = nullptr; } suspend_auto_layout = 0; } -void Fl_Flex_Type::write_code2(fld::io::Code_Writer& f) { +void Flex_Node::write_code2(fld::io::Code_Writer& f) { const char *var = name() ? name() : "o"; Fl_Flex* flex = (Fl_Flex*)o; int lm, tm, rm, bm; @@ -437,40 +437,40 @@ void Fl_Flex_Type::write_code2(fld::io::Code_Writer& f) { f.write_c("%s%s->fixed(%s->child(%d), %d);\n", f.indent(), var, var, i, flex->horizontal() ? ci->w() : ci->h()); } - Fl_Group_Type::write_code2(f); + Group_Node::write_code2(f); } -//void Fl_Flex_Type::add_child(Fl_Type* a, Fl_Type* b) { -// Fl_Group_Type::add_child(a, b); +//void Flex_Node::add_child(Node* a, Node* b) { +// Group_Node::add_child(a, b); // if (!suspend_auto_layout) // ((Fl_Flex*)o)->layout(); //} // -//void Fl_Flex_Type::move_child(Fl_Type* a, Fl_Type* b) { -// Fl_Group_Type::move_child(a, b); +//void Flex_Node::move_child(Node* a, Node* b) { +// Group_Node::move_child(a, b); // if (!suspend_auto_layout) // ((Fl_Flex*)o)->layout(); //} -void Fl_Flex_Type::remove_child(Fl_Type* a) { +void Flex_Node::remove_child(Node* a) { if (a->is_widget()) - ((Fl_Flex*)o)->fixed(((Fl_Widget_Type*)a)->o, 0); - Fl_Group_Type::remove_child(a); + ((Fl_Flex*)o)->fixed(((Widget_Node*)a)->o, 0); + Group_Node::remove_child(a); // ((Fl_Flex*)o)->layout(); layout_widget(); } -void Fl_Flex_Type::layout_widget() { - allow_layout++; +void Flex_Node::layout_widget() { + Fluid.proj.tree.allow_layout++; ((Fl_Flex*)o)->layout(); - allow_layout--; + Fluid.proj.tree.allow_layout--; } // Change from HORIZONTAL to VERTICAL or back. // Children in a horizontal Flex have already the full vertical height. If we // just change to vertical, the accumulated hight of all children is too big. // We need to relayout existing children. -void Fl_Flex_Type::change_subtype_to(int n) { +void Flex_Node::change_subtype_to(int n) { Fl_Flex* f = (Fl_Flex*)o; if (f->type()==n) return; @@ -504,10 +504,10 @@ void Fl_Flex_Type::change_subtype_to(int n) { f->layout(); } -int Fl_Flex_Type::parent_is_flex(Fl_Type *t) { +int Flex_Node::parent_is_flex(Node *t) { return (t->is_widget() && t->parent - && t->parent->is_a(ID_Flex)); + && t->parent->is_a(Type::Flex)); } /** @@ -517,7 +517,7 @@ int Fl_Flex_Type::parent_is_flex(Fl_Type *t) { this and will be relocated if so \param[in] x, y pixel coordinates relative to the top left of the window */ -void Fl_Flex_Type::insert_child_at(Fl_Widget *child, int x, int y) { +void Flex_Node::insert_child_at(Fl_Widget *child, int x, int y) { Fl_Flex *flex = (Fl_Flex*)o; // find the insertion point closest to x, y int d = flex->w() + flex->h(), di = -1; @@ -551,7 +551,7 @@ void Fl_Flex_Type::insert_child_at(Fl_Widget *child, int x, int y) { \param[in] child pointer to the child type \param[in] key code of the last keypress when handling a FL_KEYBOARD event. */ -void Fl_Flex_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { +void Flex_Node::keyboard_move_child(Widget_Node *child, int key) { Fl_Flex *flex = ((Fl_Flex*)o); int ix = flex->find(child->o); if (ix == flex->children()) return; @@ -570,36 +570,36 @@ void Fl_Flex_Type::keyboard_move_child(Fl_Widget_Type *child, int key) { } } -int Fl_Flex_Type::size(Fl_Type *t, char fixed_only) { +int Flex_Node::size(Node *t, char fixed_only) { if (!t->is_widget()) return 0; if (!t->parent) return 0; - if (!t->parent->is_a(ID_Flex)) return 0; - Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent; + if (!t->parent->is_a(Type::Flex)) return 0; + Flex_Node* ft = (Flex_Node*)t->parent; Fl_Flex* f = (Fl_Flex*)ft->o; - Fl_Widget *w = ((Fl_Widget_Type*)t)->o; + Fl_Widget *w = ((Widget_Node*)t)->o; if (fixed_only && !f->fixed(w)) return 0; return f->horizontal() ? w->w() : w->h(); } -int Fl_Flex_Type::is_fixed(Fl_Type *t) { +int Flex_Node::is_fixed(Node *t) { if (!t->is_widget()) return 0; if (!t->parent) return 0; - if (!t->parent->is_a(ID_Flex)) return 0; - Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent; + if (!t->parent->is_a(Type::Flex)) return 0; + Flex_Node* ft = (Flex_Node*)t->parent; Fl_Flex* f = (Fl_Flex*)ft->o; - Fl_Widget *w = ((Fl_Widget_Type*)t)->o; + Fl_Widget *w = ((Widget_Node*)t)->o; return f->fixed(w); } -// ---- Fl_Table_Type -------------------------------------------------- MARK: - +// ---- Table_Node -------------------------------------------------- MARK: - -Fl_Table_Type Fl_Table_type; // the "factory" +Table_Node Table_Node::prototype; // the "factory" static const int MAX_ROWS = 14; static const int MAX_COLS = 7; // this is a minimal table widget used as an example when adding tables in Fluid -class Fluid_Table : public Fl_Table { +class Fl_Table_Proxy : public Fl_Table { int data[MAX_ROWS][MAX_COLS]; // data array for cells // Draw the row/col headings @@ -629,7 +629,7 @@ class Fluid_Table : public Fl_Table { // Fl_Table calls this function to draw each visible cell in the table. // It's up to us to use FLTK's drawing functions to draw the cells the way we want. // - void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) FL_OVERRIDE { + void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) override { static char s[40]; switch ( context ) { case CONTEXT_STARTPAGE: // before page is drawn.. @@ -652,7 +652,7 @@ class Fluid_Table : public Fl_Table { } } public: - Fluid_Table(int x, int y, int w, int h, const char *l=0L) + Fl_Table_Proxy(int x, int y, int w, int h, const char *l=nullptr) : Fl_Table(x, y, w, h, l) { end(); for ( int r=0; ro : 0; +void Table_Node::add_child(Node* cc, Node* before) { + Widget_Node* c = (Widget_Node*)cc; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; if (((Fl_Table*)o)->children()==1) { // the FLuid_Table has one extra child fl_message("Inserting child widgets into an Fl_Table is not recommended.\n" "Please refer to the documentation on Fl_Table."); @@ -687,42 +687,42 @@ void Fl_Table_Type::add_child(Fl_Type* cc, Fl_Type* before) { o->redraw(); } -void Fl_Table_Type::remove_child(Fl_Type* cc) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; +void Table_Node::remove_child(Node* cc) { + Widget_Node* c = (Widget_Node*)cc; ((Fl_Table*)o)->remove(*(c->o)); o->redraw(); } -void Fl_Table_Type::move_child(Fl_Type* cc, Fl_Type* before) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; - Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; +void Table_Node::move_child(Node* cc, Node* before) { + Widget_Node* c = (Widget_Node*)cc; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; ((Fl_Table*)o)->insert(*(c->o), b); o->redraw(); } -Fl_Widget *Fl_Table_Type::enter_live_mode(int) { - Fl_Group *grp = new Fluid_Table(o->x(), o->y(), o->w(), o->h()); +Fl_Widget *Table_Node::enter_live_mode(int) { + Fl_Group *grp = new Fl_Table_Proxy(o->x(), o->y(), o->w(), o->h()); live_widget = grp; copy_properties(); grp->end(); return live_widget; } -void Fl_Table_Type::ideal_size(int &w, int &h) { +void Table_Node::ideal_size(int &w, int &h) { w = 160; h = 120; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } -// ---- Fl_Tabs_Type --------------------------------------------------- MARK: - +// ---- Tabs_Node --------------------------------------------------- MARK: - -Fl_Tabs_Type Fl_Tabs_type; // the "factory" +Tabs_Node Tabs_Node::prototype; const char tabs_type_name[] = "Fl_Tabs"; // Override group's resize behavior to do nothing to children: void Fl_Tabs_Proxy::resize(int X, int Y, int W, int H) { - if (Fl_Type::allow_layout > 0) { + if (Fluid.proj.tree.allow_layout > 0) { Fl_Tabs::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); @@ -734,7 +734,7 @@ void Fl_Tabs_Proxy::resize(int X, int Y, int W, int H) { Override draw() to make groups with no box or flat box background visible. */ void Fl_Tabs_Proxy::draw() { - if (show_ghosted_outline && (box() == FL_NO_BOX)) { + if (Fluid.show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Tabs::draw(); @@ -744,10 +744,10 @@ void Fl_Tabs_Proxy::draw() { // if it is a tab title, and adjust visibility and return new selection: // If none, return o unchanged: -Fl_Type* Fl_Tabs_Type::click_test(int x, int y) { +Node* Tabs_Node::click_test(int x, int y) { Fl_Tabs *t = (Fl_Tabs*)o; Fl_Widget *a = t->which(x,y); - if (!a) return 0; // didn't click on tab + if (!a) return nullptr; // didn't click on tab // changing the visible tab has an impact on the generated // source code, so mark this project as changed. int changed = (a!=t->value()); @@ -755,22 +755,22 @@ Fl_Type* Fl_Tabs_Type::click_test(int x, int y) { t->handle(FL_PUSH); Fl::pushed(t); while (Fl::pushed()==t) Fl::wait(); - if (changed) set_modflag(1); - return (Fl_Type*)(t->value()->user_data()); + if (changed) Fluid.proj.set_modflag(1); + return (Node*)(t->value()->user_data()); } -void Fl_Tabs_Type::add_child(Fl_Type* c, Fl_Type* before) { - Fl_Group_Type::add_child(c, before); +void Tabs_Node::add_child(Node* c, Node* before) { + Group_Node::add_child(c, before); } -void Fl_Tabs_Type::remove_child(Fl_Type* cc) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; +void Tabs_Node::remove_child(Node* cc) { + Widget_Node* c = (Widget_Node*)cc; Fl_Tabs *t = (Fl_Tabs*)o; - if (t->value() == c->o) t->value(0); - Fl_Group_Type::remove_child(c); + if (t->value() == c->o) t->value(nullptr); + Group_Node::remove_child(c); } -Fl_Widget *Fl_Tabs_Type::enter_live_mode(int) { +Fl_Widget *Tabs_Node::enter_live_mode(int) { Fl_Tabs *original = static_cast(o); Fl_Tabs *clone = new Fl_Tabs(o->x(), o->y(), o->w(), o->h()); propagate_live_mode(clone); @@ -780,29 +780,29 @@ Fl_Widget *Fl_Tabs_Type::enter_live_mode(int) { return clone; } -// ---- Fl_Scroll_Type ------------------------------------------------- MARK: - +// ---- Scroll_Node ------------------------------------------------- MARK: - -Fl_Scroll_Type Fl_Scroll_type; // the "factory" +Scroll_Node Scroll_Node::prototype; // the "factory" const char scroll_type_name[] = "Fl_Scroll"; Fl_Menu_Item scroll_type_menu[] = { - {"BOTH", 0, 0, 0/*(void*)Fl_Scroll::BOTH*/}, - {"HORIZONTAL", 0, 0, (void*)Fl_Scroll::HORIZONTAL}, - {"VERTICAL", 0, 0, (void*)Fl_Scroll::VERTICAL}, - {"HORIZONTAL_ALWAYS", 0, 0, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, - {"VERTICAL_ALWAYS", 0, 0, (void*)Fl_Scroll::VERTICAL_ALWAYS}, - {"BOTH_ALWAYS", 0, 0, (void*)Fl_Scroll::BOTH_ALWAYS}, - {0}}; + {"BOTH", 0, nullptr, nullptr/*(void*)Fl_Scroll::BOTH*/}, + {"HORIZONTAL", 0, nullptr, (void*)Fl_Scroll::HORIZONTAL}, + {"VERTICAL", 0, nullptr, (void*)Fl_Scroll::VERTICAL}, + {"HORIZONTAL_ALWAYS", 0, nullptr, (void*)Fl_Scroll::HORIZONTAL_ALWAYS}, + {"VERTICAL_ALWAYS", 0, nullptr, (void*)Fl_Scroll::VERTICAL_ALWAYS}, + {"BOTH_ALWAYS", 0, nullptr, (void*)Fl_Scroll::BOTH_ALWAYS}, + {nullptr}}; -Fl_Widget *Fl_Scroll_Type::enter_live_mode(int) { +Fl_Widget *Scroll_Node::enter_live_mode(int) { Fl_Group *grp = new Fl_Scroll(o->x(), o->y(), o->w(), o->h()); grp->show(); return propagate_live_mode(grp); } -void Fl_Scroll_Type::copy_properties() { - Fl_Group_Type::copy_properties(); +void Scroll_Node::copy_properties() { + Group_Node::copy_properties(); Fl_Scroll *s = (Fl_Scroll*)o, *d = (Fl_Scroll*)live_widget; d->scroll_to(s->xposition(), s->yposition()); d->type(s->type()); @@ -810,26 +810,26 @@ void Fl_Scroll_Type::copy_properties() { d->hscrollbar.align(s->hscrollbar.align()); } -// ---- Fl_Tile_Type --------------------------------------------------- MARK: - +// ---- Tile_Node --------------------------------------------------- MARK: - -Fl_Tile_Type Fl_Tile_type; // the "factory" +Tile_Node Tile_Node::prototype; // the "factory" const char tile_type_name[] = "Fl_Tile"; -void Fl_Tile_Type::copy_properties() { - Fl_Group_Type::copy_properties(); +void Tile_Node::copy_properties() { + Group_Node::copy_properties(); // no additional properties } -// ---- Fl_Wizard_Type ------------------------------------------------ MARK: - +// ---- Wizard_Node ------------------------------------------------ MARK: - -Fl_Wizard_Type Fl_Wizard_type; // the "factory" +Wizard_Node Wizard_Node::prototype; // the "factory" const char wizard_type_name[] = "Fl_Wizard"; // Override group's resize behavior to do nothing to children: void Fl_Wizard_Proxy::resize(int X, int Y, int W, int H) { - if (Fl_Type::allow_layout > 0) { + if (Fluid.proj.tree.allow_layout > 0) { Fl_Wizard::resize(X, Y, W, H); } else { Fl_Widget::resize(X, Y, W, H); @@ -841,7 +841,7 @@ void Fl_Wizard_Proxy::resize(int X, int Y, int W, int H) { Override draw() to make groups with no box or flat box background visible. */ void Fl_Wizard_Proxy::draw() { - if (show_ghosted_outline && (box() == FL_NO_BOX)) { + if (Fluid.show_ghosted_outline && (box() == FL_NO_BOX)) { fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f))); } Fl_Wizard::draw(); diff --git a/fluid/nodes/Group_Node.h b/fluid/nodes/Group_Node.h new file mode 100644 index 000000000..6b6fe9fcd --- /dev/null +++ b/fluid/nodes/Group_Node.h @@ -0,0 +1,261 @@ +// +// Group Node header file for the Fast Light Tool Kit (FLTK). +// +// 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 +// 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_NODES_GROUP_NODE_H +#define FLUID_NODES_GROUP_NODE_H + +#include "nodes/Widget_Node.h" + +#include +#include +#include +#include + +void group_cb(Fl_Widget *, void *); +void ungroup_cb(Fl_Widget *, void *); + +// ---- Group_Node -------------------------------------------------- MARK: - + +/** + Proxy group to use in place of Fl_Group in the interactive window. + + In an interactive environment, groups should not automatically resize their + children. This proxy disables the layout of children by default. Children + layout propagation may be enable temporarily by incrementing `allow_layout` + before resizing and decrementing it again afterwards. + */ +class Fl_Group_Proxy : public Fl_Group { +public: + Fl_Group_Proxy(int X,int Y,int W,int H) : Fl_Group(X, Y, W, H) { Fl_Group::current(nullptr); } + void resize(int x, int y, int w, int h) override; + void draw() override; +}; + +class Group_Node : public Widget_Node +{ +public: + typedef Widget_Node super; + static Group_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override {return "Fl_Group";} + const char *alt_type_name() override {return "fltk::Group";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Group_Proxy *g = new Fl_Group_Proxy(X,Y,W,H); Fl_Group::current(nullptr); return g;} + Widget_Node *_make() override {return new Group_Node();} + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + void add_child(Node*, Node*) override; + void move_child(Node*, Node*) override; + void remove_child(Node*) override; + int can_have_children() const override {return 1;} + Type type() const override { return Type::Group; } + bool is_a(Type inType) const override { return (inType==Type::Group) ? true : super::is_a(inType); } + Fl_Widget *enter_live_mode(int top=0) override; + void leave_live_mode() override; + void copy_properties() override; +}; + +// ---- Pack_Node --------------------------------------------------- MARK: - + +extern const char pack_type_name[]; +extern Fl_Menu_Item pack_type_menu[]; + +class Pack_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Pack_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return pack_type_menu;} +public: + const char *type_name() override {return pack_type_name;} + const char *alt_type_name() override {return "fltk::PackedGroup";} + Widget_Node *_make() override {return new Pack_Node();} + Type type() const override { return Type::Pack; } + bool is_a(Type inType) const override { return (inType==Type::Pack) ? true : super::is_a(inType); } + Fl_Widget *enter_live_mode(int top=0) override; + void copy_properties() override; +}; + +// ---- Flex_Node --------------------------------------------------- MARK: - + +extern const char flex_type_name[]; +extern Fl_Menu_Item flex_type_menu[]; + +class Fl_Flex_Proxy : public Fl_Flex { +public: + Fl_Flex_Proxy(int X,int Y,int W,int H) : Fl_Flex(X, Y, W, H) { Fl_Group::current(nullptr); } + void resize(int x, int y, int w, int h) override; + void draw() override; +}; + +class Flex_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Flex_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return flex_type_menu;} + int fixedSizeTupleSize; /* number of pairs in array */ + int *fixedSizeTuple; /* [ index, size, index2, size2, ... ] */ + int suspend_auto_layout; +public: + Flex_Node() : fixedSizeTupleSize(0), fixedSizeTuple(nullptr), suspend_auto_layout(0) { } + const char *type_name() override {return flex_type_name;} + const char *alt_type_name() override {return "fltk::FlexGroup";} + Widget_Node *_make() override { return new Flex_Node(); } + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Flex *g = new Fl_Flex_Proxy(X,Y,W,H); Fl_Group::current(nullptr); return g;} + Type type() const override { return Type::Flex; } + bool is_a(Type inType) const override { return (inType==Type::Flex) ? true : super::is_a(inType); } + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + Fl_Widget *enter_live_mode(int top=0) override; + void copy_properties() override; + void copy_properties_for_children() override; + void postprocess_read() override; + void write_code2(fld::io::Code_Writer& f) override; +// void add_child(Node*, Node*) override; +// void move_child(Node*, Node*) override; + void remove_child(Node*) override; + void layout_widget() override; + void change_subtype_to(int n); + void insert_child_at(Fl_Widget *child, int x, int y); + void keyboard_move_child(Widget_Node*, int key); + static int parent_is_flex(Node*); + static int size(Node*, char fixed_only=0); + static int is_fixed(Node*); +}; + +// ---- Table_Node -------------------------------------------------- MARK: - + +class Table_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Table_Node prototype; +public: + void ideal_size(int &w, int &h) override; + const char *type_name() override { return "Fl_Table"; } + const char *alt_type_name() override { return "fltk::TableGroup"; } + Widget_Node *_make() override { return new Table_Node(); } + Fl_Widget *widget(int X, int Y, int W, int H) override; + Type type() const override { return Type::Table; } + bool is_a(Type inType) const override { return (inType==Type::Table) ? true : super::is_a(inType); } + Fl_Widget *enter_live_mode(int top=0) override; + void add_child(Node*, Node*) override; + void move_child(Node*, Node*) override; + void remove_child(Node*) override; +}; + +// ---- Tabs_Node --------------------------------------------------- MARK: - + +extern const char tabs_type_name[]; + +class Fl_Tabs_Proxy : public Fl_Tabs { +public: + Fl_Tabs_Proxy(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {} + void resize(int,int,int,int) override; + void draw() override; +}; + +class Tabs_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Tabs_Node prototype; +public: + const char *type_name() override {return tabs_type_name;} + const char *alt_type_name() override {return "fltk::TabGroup";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Tabs_Proxy *g = new Fl_Tabs_Proxy(X,Y,W,H); Fl_Group::current(nullptr); return g;} + Widget_Node *_make() override {return new Tabs_Node();} + Node* click_test(int,int) override; + void add_child(Node*, Node*) override; + void remove_child(Node*) override; + Type type() const override { return Type::Tabs; } + bool is_a(Type inType) const override { return (inType==Type::Tabs) ? true : super::is_a(inType); } + Fl_Widget *enter_live_mode(int top=0) override; +}; + +// ---- Scroll_Node ------------------------------------------------- MARK: - + +extern const char scroll_type_name[]; +extern Fl_Menu_Item scroll_type_menu[]; + +class Scroll_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Scroll_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return scroll_type_menu;} +public: + const char *type_name() override {return scroll_type_name;} + const char *alt_type_name() override {return "fltk::ScrollGroup";} + Widget_Node *_make() override {return new Scroll_Node();} + Type type() const override { return Type::Scroll; } + bool is_a(Type inType) const override { return (inType==Type::Scroll) ? true : super::is_a(inType); } + Fl_Widget *enter_live_mode(int top=0) override; + void copy_properties() override; +}; + +// ---- Tile_Node --------------------------------------------------- MARK: - + +extern const char tile_type_name[]; + +class Tile_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Tile_Node prototype; +public: + const char *type_name() override {return tile_type_name;} + const char *alt_type_name() override {return "fltk::TileGroup";} + Widget_Node *_make() override {return new Tile_Node();} + Type type() const override { return Type::Tile; } + bool is_a(Type inType) const override { return (inType==Type::Tile) ? true : super::is_a(inType); } + void copy_properties() override; +}; + +// ---- Wizard_Node ------------------------------------------------- MARK: - + +class Fl_Wizard_Proxy : public Fl_Wizard { +public: + Fl_Wizard_Proxy(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {} + void resize(int,int,int,int) override; + void draw() override; +}; + +extern const char wizard_type_name[]; + +class Wizard_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Wizard_Node prototype; +public: + const char *type_name() override {return wizard_type_name;} + const char *alt_type_name() override {return "fltk::WizardGroup";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Wizard_Proxy *g = new Fl_Wizard_Proxy(X,Y,W,H); Fl_Group::current(nullptr); return g;} + Widget_Node *_make() override {return new Wizard_Node();} + Type type() const override { return Type::Wizard; } + bool is_a(Type inType) const override { return (inType==Type::Wizard) ? true : super::is_a(inType); } +}; + +#endif // FLUID_NODES_GROUP_NODE_H diff --git a/fluid/nodes/Fl_Menu_Type.cxx b/fluid/nodes/Menu_Node.cxx similarity index 69% rename from fluid/nodes/Fl_Menu_Type.cxx rename to fluid/nodes/Menu_Node.cxx index 83435df50..2a76b833a 100644 --- a/fluid/nodes/Fl_Menu_Type.cxx +++ b/fluid/nodes/Menu_Node.cxx @@ -1,13 +1,7 @@ // -// Menu item code for the Fast Light Tool Kit (FLTK). +// Menu Node code for the Fast Light Tool Kit (FLTK). // -// Menu items are kludged by making a phony Fl_Box widget so the normal -// widget panel can be used to control them. -// -// This file also contains code to make Fl_Menu_Button, Fl_Menu_Bar, -// etc widgets. -// -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -20,17 +14,17 @@ // https://www.fltk.org/bugs.php // -#include "nodes/Fl_Menu_Type.h" +#include "nodes/Menu_Node.h" -#include "app/fluid.h" -#include "app/project.h" -#include "app/Fluid_Image.h" -#include "app/mergeback.h" -#include "app/undo.h" +#include "Fluid.h" +#include "Project.h" +#include "app/Image_Asset.h" +#include "proj/mergeback.h" +#include "proj/undo.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" -#include "nodes/Fl_Window_Type.h" +#include "nodes/Window_Node.h" #include "widgets/Formula_Input.h" #include "widgets/Node_Browser.h" @@ -51,17 +45,17 @@ #include Fl_Menu_Item menu_item_type_menu[] = { - {"Normal",0,0,(void*)0}, - {"Toggle",0,0,(void*)FL_MENU_BOX}, - {"Radio",0,0,(void*)FL_MENU_RADIO}, - {0}}; + {"Normal",0,nullptr,(void*)nullptr}, + {"Toggle",0,nullptr,(void*)FL_MENU_BOX}, + {"Radio",0,nullptr,(void*)FL_MENU_RADIO}, + {nullptr}}; static void delete_dependents(Fl_Menu_Item *m) { if (!m) return; int level = 0; for (;;m++) { - if (m->label()==NULL) { + if (m->label()==nullptr) { if (level==0) { break; } else { @@ -82,18 +76,18 @@ static void delete_menu(Fl_Menu_Item *m) { delete[] m; } -void Fl_Input_Choice_Type::build_menu() { +void Input_Choice_Node::build_menu() { Fl_Input_Choice* w = (Fl_Input_Choice*)o; // count how many Fl_Menu_Item structures needed: int n = 0; - Fl_Type* q; + Node* q; for (q = next; q && q->level > level; q = q->next) { if (q->can_have_children()) n++; // space for null at end of submenu n++; } if (!n) { if (menusize) delete_menu((Fl_Menu_Item*)(w->menu())); - w->menu(0); + w->menu(nullptr); menusize = 0; } else { n++; // space for null at end of menu @@ -105,7 +99,7 @@ void Fl_Input_Choice_Type::build_menu() { if (menusize) delete_dependents((Fl_Menu_Item*)(w->menu())); } // Menus are already built during the .fl file reading process, so if the - // end of a menu list is not read yet, the end markers (label==NULL) will + // end of a menu list is not read yet, the end markers (label==nullptr) will // not be set, and deleting dependents will randomly free memory. // Clearing the array should avoid that. memset( (void*)w->menu(), 0, menusize * sizeof(Fl_Menu_Item) ); @@ -113,7 +107,7 @@ void Fl_Input_Choice_Type::build_menu() { Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); int lvl = level+1; for (q = next; q && q->level > level; q = q->next) { - Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; + Menu_Item_Node* i = (Menu_Item_Node*)q; if (i->o->image()) { if (i->o->label() && i->o->label()[0]) { Fl_Multi_Label *ml = new Fl_Multi_Label; @@ -130,7 +124,7 @@ void Fl_Input_Choice_Type::build_menu() { m->labeltype(i->o->labeltype()); } m->shortcut(((Fl_Button*)(i->o))->shortcut()); - m->callback(0,(void*)i); + m->callback(nullptr,(void*)i); m->flags = i->flags(); m->labelfont(i->o->labelfont()); m->labelsize(i->o->labelsize()); @@ -138,8 +132,8 @@ void Fl_Input_Choice_Type::build_menu() { if (q->can_have_children()) {lvl++; m->flags |= FL_SUBMENU;} m++; int l1 = - (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : level; - while (lvl > l1) {m->label(0); m++; lvl--;} + (q->next && q->next->is_a(Type::Menu_Item)) ? q->next->level : level; + while (lvl > l1) {m->label(nullptr); m++; lvl--;} lvl = l1; } } @@ -151,8 +145,8 @@ void Fl_Input_Choice_Type::build_menu() { \param[in] strategy add after current or as last child \return new Menu Item node */ -Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) { - return Fl_Menu_Item_Type::make(0, strategy); +Node *Menu_Item_Node::make(Strategy strategy) { + return Menu_Item_Node::make(0, strategy); } /** @@ -161,29 +155,29 @@ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) { \param[in] strategy add after current or as last child \return new Menu Item node */ -Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) { +Node* Menu_Item_Node::make(int flags, Strategy strategy) { // Find a good insert position based on the current marked node - Fl_Type *anchor = Fl_Type::current, *p = anchor; + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; - while (p && !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) { + while (p && !(p->is_a(Type::Menu_Manager_) || p->is_a(Type::Submenu))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a menu widget or a menu item"); - return 0; + return nullptr; } if (!o) { o = new Fl_Button(0,0,100,20); // create template widget } - Fl_Menu_Item_Type* t = NULL; + Menu_Item_Node* t = nullptr; if (flags==FL_SUBMENU) { - t = new Fl_Submenu_Type(); + t = new Submenu_Node(); } else { - t = new Fl_Menu_Item_Type(); + t = new Menu_Item_Node(); } t->o = new Fl_Button(0,0,100,20); t->o->type(flags); @@ -201,50 +195,50 @@ Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) { void group_selected_menuitems() { // The group will be created in the parent group of the current menuitem - if (!Fl_Type::current->is_a(ID_Menu_Item)) { + if (!Fluid.proj.tree.current->is_a(Type::Menu_Item)) { return; } - Fl_Menu_Item_Type *q = static_cast(Fl_Type::current); - Fl_Type *qq = Fl_Type::current->parent; - if (!qq || !(qq->is_a(ID_Menu_Manager_) || qq->is_a(ID_Submenu))) { + Menu_Item_Node *q = static_cast(Fluid.proj.tree.current); + Node *qq = Fluid.proj.tree.current->parent; + if (!qq || !(qq->is_a(Type::Menu_Manager_) || qq->is_a(Type::Submenu))) { fl_message("Can't create a new submenu here."); return; } - undo_checkpoint(); - undo_suspend(); - Fl_Widget_Type *n = (Fl_Widget_Type*)(q->make(FL_SUBMENU, Strategy::AFTER_CURRENT)); - for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + Widget_Node *n = (Widget_Node*)(q->make(FL_SUBMENU, Strategy::AFTER_CURRENT)); + for (Node *t = qq->next; t && (t->level > qq->level);) { if (t->level != n->level || t == n || !t->selected) { t = t->next; continue; } - Fl_Type *nxt = t->remove(); + Node *nxt = t->remove(); t->add(n, Strategy::AS_LAST_CHILD); t = nxt; } widget_browser->rebuild(); - undo_resume(); - set_modflag(1); + Fluid.proj.undo.resume(); + Fluid.proj.set_modflag(1); } void ungroup_selected_menuitems() { // Find the submenu - Fl_Type *qq = Fl_Type::current->parent; - Fl_Widget_Type *q = static_cast(Fl_Type::current); + Node *qq = Fluid.proj.tree.current->parent; + Widget_Node *q = static_cast(Fluid.proj.tree.current); int q_level = q->level; - if (!qq || !qq->is_a(ID_Submenu)) { + if (!qq || !qq->is_a(Type::Submenu)) { fl_message("Only menu items inside a submenu can be ungrouped."); return; } - undo_checkpoint(); - undo_suspend(); - Fl_Type::current = qq; - for (Fl_Type *t = qq->next; t && (t->level > qq->level);) { + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + Fluid.proj.tree.current = qq; + for (Node *t = qq->next; t && (t->level > qq->level);) { if (t->level != q_level || !t->selected) { t = t->next; continue; } - Fl_Type *nxt = t->remove(); + Node *nxt = t->remove(); t->insert(qq); t = nxt; } @@ -252,10 +246,10 @@ void ungroup_selected_menuitems() { qq->remove(); delete qq; // qq has no children that need to be delete } - Fl_Type::current = q; + Fluid.proj.tree.current = q; widget_browser->rebuild(); - undo_resume(); - set_modflag(1); + Fluid.proj.undo.resume(); + Fluid.proj.set_modflag(1); } @@ -264,8 +258,8 @@ void ungroup_selected_menuitems() { \param[in] strategy add after current or as last child \return new node */ -Fl_Type *Fl_Checkbox_Menu_Item_Type::make(Strategy strategy) { - return Fl_Menu_Item_Type::make(FL_MENU_TOGGLE, strategy); +Node *Checkbox_Menu_Item_Node::make(Strategy strategy) { + return Menu_Item_Node::make(FL_MENU_TOGGLE, strategy); } /** @@ -273,8 +267,8 @@ Fl_Type *Fl_Checkbox_Menu_Item_Type::make(Strategy strategy) { \param[in] strategy add after current or as last child \return new node */ -Fl_Type *Fl_Radio_Menu_Item_Type::make(Strategy strategy) { - return Fl_Menu_Item_Type::make(FL_MENU_RADIO, strategy); +Node *Radio_Menu_Item_Node::make(Strategy strategy) { + return Menu_Item_Node::make(FL_MENU_RADIO, strategy); } /** @@ -282,30 +276,33 @@ Fl_Type *Fl_Radio_Menu_Item_Type::make(Strategy strategy) { \param[in] strategy add after current or as last child \return new node */ -Fl_Type *Fl_Submenu_Type::make(Strategy strategy) { - return Fl_Menu_Item_Type::make(FL_SUBMENU, strategy); +Node *Submenu_Node::make(Strategy strategy) { + return Menu_Item_Node::make(FL_SUBMENU, strategy); } -Fl_Menu_Item_Type Fl_Menu_Item_type; -Fl_Checkbox_Menu_Item_Type Fl_Checkbox_Menu_Item_type; -Fl_Radio_Menu_Item_Type Fl_Radio_Menu_Item_type; -Fl_Submenu_Type Fl_Submenu_type; +Menu_Item_Node Menu_Item_Node::prototype; + +Checkbox_Menu_Item_Node Checkbox_Menu_Item_Node::prototype; + +Radio_Menu_Item_Node Radio_Menu_Item_Node::prototype; + +Submenu_Node Submenu_Node::prototype; //////////////////////////////////////////////////////////////// // Writing the C code: -// test functions in Fl_Widget_Type.C: +// test functions in Widget_Node.C: int is_name(const char *c); -const char *array_name(Fl_Widget_Type *o); +const char *array_name(Widget_Node *o); int isdeclare(const char *c); // Search backwards to find the parent menu button and return it's name. // Also put in i the index into the button's menu item array belonging // to this menu item. -const char* Fl_Menu_Item_Type::menu_name(fld::io::Code_Writer& f, int& i) { +const char* Menu_Item_Node::menu_name(fld::io::Code_Writer& f, int& i) { i = 0; - Fl_Type* t = prev; - while (t && t->is_a(ID_Menu_Item)) { + Node* t = prev; + while (t && t->is_a(Type::Menu_Item)) { // be sure to count the {0} that ends a submenu: if (t->level > t->next->level) i += (t->level - t->next->level); // detect empty submenu: @@ -313,11 +310,11 @@ const char* Fl_Menu_Item_Type::menu_name(fld::io::Code_Writer& f, int& i) { t = t->prev; i++; } - if (!t) return "\n#error Fl_Menu_Item_Type::menu_name, invalid f\n"; + if (!t) return "\n#error Menu_Item_Node::menu_name, invalid f\n"; return f.unique_id(t, "menu", t->name(), t->label()); } -void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { +void Menu_Item_Node::write_static(fld::io::Code_Writer& f) { if (image && label() && label()[0]) { f.write_h_once("#include "); f.write_h_once("#include "); @@ -374,16 +371,16 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { // Implement the callback as a static member function f.write_c("void %s::%s(Fl_Menu_* o, %s v) {\n", k, cn, ut); // Find the Fl_Menu_ container for this menu item - Fl_Type* t = parent; while (t->is_a(ID_Menu_Item)) t = t->parent; + Node* t = parent; while (t->is_a(Type::Menu_Item)) t = t->parent; if (t) { - Fl_Widget_Type *tw = (t->is_widget()) ? static_cast(t) : NULL; - Fl_Type *q = NULL; + Widget_Node *tw = (t->is_widget()) ? static_cast(t) : nullptr; + Node *q = nullptr; // Generate code to call the callback - if (tw->is_a(ID_Menu_Bar) && ((Fl_Menu_Bar_Type*)tw)->is_sys_menu_bar()) { + if (tw->is_a(Type::Menu_Bar) && ((Menu_Bar_Node*)tw)->is_sys_menu_bar()) { // Fl_Sys_Menu_Bar removes itself from any parent on macOS, so we // wrapped it in a class and remeber the parent class in a new // class memeber variable. - Fl_Menu_Bar_Type *tmb = (Fl_Menu_Bar_Type*)tw; + Menu_Bar_Node *tmb = (Menu_Bar_Node*)tw; f.write_c("%s%s* sys_menu_bar = ((%s*)o);\n", f.indent(1), tmb->sys_menubar_proxy_name(), tmb->sys_menubar_proxy_name()); f.write_c("%s%s* parent_class = ((%s*)sys_menu_bar->_parent_class);\n", @@ -393,7 +390,7 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { } else { f.write_c("%s((%s*)(o", f.indent(1), k); // The class pointer is in the user_data field of the top widget - if (t && t->is_a(ID_Input_Choice)) { + if (t && t->is_a(Type::Input_Choice)) { // Go up one more level for Fl_Input_Choice, as these are groups themselves f.write_c("->parent()"); } @@ -401,7 +398,7 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { for (t = t->parent; t && t->is_widget() && !is_class(); q = t, t = t->parent) f.write_c("->parent()"); // user_data is cast into a pointer to the - if (!q || !q->is_a(ID_Widget_Class)) + if (!q || !q->is_a(Type::Widget_Class)) f.write_c("->user_data()"); f.write_c("))->%s_i(o,v);\n}\n", cn); } @@ -414,7 +411,7 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { if (!f.c_contains(image)) image->write_static(f, compress_image_); } - if (next && next->is_a(ID_Menu_Item)) return; + if (next && next->is_a(Type::Menu_Item)) return; // okay, when we hit last item in the menu we have to write the // entire array out: const char* k = class_name(1); @@ -425,27 +422,27 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { int i; f.write_c("\nFl_Menu_Item %s[] = {\n", menu_name(f, i)); } - Fl_Type* t = prev; while (t && t->is_a(ID_Menu_Item)) t = t->prev; - for (Fl_Type* q = t->next; q && q->is_a(ID_Menu_Item); q = q->next) { - ((Fl_Menu_Item_Type*)q)->write_item(f); + Node* t = prev; while (t && t->is_a(Type::Menu_Item)) t = t->prev; + for (Node* q = t->next; q && q->is_a(Type::Menu_Item); q = q->next) { + ((Menu_Item_Node*)q)->write_item(f); int thislevel = q->level; if (q->can_have_children()) thislevel++; int nextlevel = - (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : t->level+1; + (q->next && q->next->is_a(Type::Menu_Item)) ? q->next->level : t->level+1; while (thislevel > nextlevel) {f.write_c(" {0,0,0,0,0,0,0,0,0},\n"); thislevel--;} } f.write_c(" {0,0,0,0,0,0,0,0,0}\n};\n"); if (k) { // Write menu item variables... - t = prev; while (t && t->is_a(ID_Menu_Item)) t = t->prev; - for (Fl_Type* q = t->next; q && q->is_a(ID_Menu_Item); q = q->next) { - Fl_Menu_Item_Type *m = (Fl_Menu_Item_Type*)q; + t = prev; while (t && t->is_a(Type::Menu_Item)) t = t->prev; + for (Node* q = t->next; q && q->is_a(Type::Menu_Item); q = q->next) { + Menu_Item_Node *m = (Menu_Item_Node*)q; const char *c = array_name(m); if (c) { if (c==m->name()) { // assign a menu item address directly to a variable int i; - const char* n = ((Fl_Menu_Item_Type *)q)->menu_name(f, i); + const char* n = ((Menu_Item_Node *)q)->menu_name(f, i); f.write_c("Fl_Menu_Item* %s::%s = %s::%s + %d;\n", k, c, k, n, i); } else { // if the name is an array, only define the array. @@ -457,20 +454,20 @@ void Fl_Menu_Item_Type::write_static(fld::io::Code_Writer& f) { } } -int Fl_Menu_Item_Type::flags() { +int Menu_Item_Node::flags() { int i = o->type(); if (((Fl_Button*)o)->value()) i |= FL_MENU_VALUE; if (!o->active()) i |= FL_MENU_INACTIVE; if (!o->visible()) i |= FL_MENU_INVISIBLE; if (can_have_children()) { - if (user_data() == NULL) i |= FL_SUBMENU; + if (user_data() == nullptr) i |= FL_SUBMENU; else i |= FL_SUBMENU_POINTER; } if (hotspot()) i |= FL_MENU_DIVIDER; return i; } -void Fl_Menu_Item_Type::write_item(fld::io::Code_Writer& f) { +void Menu_Item_Node::write_item(fld::io::Code_Writer& f) { static const char * const labeltypes[] = { "FL_NORMAL_LABEL", "FL_NO_LABEL", @@ -485,14 +482,14 @@ void Fl_Menu_Item_Type::write_item(fld::io::Code_Writer& f) { write_comment_inline_c(f, " "); f.write_c(" {"); if (label() && label()[0]) - switch (g_project.i18n_type) { - case FD_I18N_GNU: + switch (Fluid.proj.i18n_type) { + case fld::I18n_Type::GNU: // we will call i18n when the menu is instantiated for the first time - f.write_c("%s(", g_project.i18n_gnu_static_function.c_str()); + f.write_c("%s(", Fluid.proj.i18n_gnu_static_function.c_str()); f.write_cstring(label()); f.write_c(")"); break; - case FD_I18N_POSIX: + case fld::I18n_Type::POSIX: // fall through: strings can't be translated before a catalog is chosen default: f.write_cstring(label()); @@ -502,7 +499,7 @@ void Fl_Menu_Item_Type::write_item(fld::io::Code_Writer& f) { if (((Fl_Button*)o)->shortcut()) { int s = ((Fl_Button*)o)->shortcut(); f.write_c(", "); - if (g_project.use_FL_COMMAND) { + if (Fluid.proj.use_FL_COMMAND) { if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } } else { @@ -519,7 +516,7 @@ void Fl_Menu_Item_Type::write_item(fld::io::Code_Writer& f) { f.write_c(", 0, "); } if (callback()) { - const char* k = is_name(callback()) ? 0 : class_name(1); + const char* k = is_name(callback()) ? nullptr : class_name(1); if (k) { f.write_c(" (Fl_Callback*)%s::%s,", k, callback_name(f)); } else { @@ -544,10 +541,10 @@ void start_menu_initialiser(fld::io::Code_Writer& f, int &initialized, const cha } } -void Fl_Menu_Item_Type::write_code1(fld::io::Code_Writer& f) { +void Menu_Item_Node::write_code1(fld::io::Code_Writer& f) { int i; const char* mname = menu_name(f, i); - if (!prev->is_a(ID_Menu_Item)) { + if (!prev->is_a(Type::Menu_Item)) { // for first menu item, declare the array if (class_name(1)) { f.write_h("%sstatic Fl_Menu_Item %s[];\n", f.indent(1), mname); @@ -591,16 +588,16 @@ void Fl_Menu_Item_Type::write_code1(fld::io::Code_Writer& f) { f.write_c("%sml->labela = (char*)", f.indent()); image->write_inline(f); f.write_c(";\n"); - if (g_project.i18n_type==FD_I18N_NONE) { + if (Fluid.proj.i18n_type==fld::I18n_Type::NONE) { f.write_c("%sml->labelb = o->label();\n", f.indent()); - } else if (g_project.i18n_type==FD_I18N_GNU) { + } else if (Fluid.proj.i18n_type==fld::I18n_Type::GNU) { f.write_c("%sml->labelb = %s(o->label());\n", - f.indent(), g_project.i18n_gnu_function.c_str()); - } else if (g_project.i18n_type==FD_I18N_POSIX) { + f.indent(), Fluid.proj.i18n_gnu_function.c_str()); + } else if (Fluid.proj.i18n_type==fld::I18n_Type::POSIX) { f.write_c("%sml->labelb = catgets(%s,%s,i+%d,o->label());\n", f.indent(), - g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), - g_project.i18n_pos_set.c_str(), msgnum()); + Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), + Fluid.proj.i18n_pos_set.c_str(), msgnum()); } f.write_c("%sml->typea = FL_IMAGE_LABEL;\n", f.indent()); f.write_c("%sml->typeb = FL_NORMAL_LABEL;\n", f.indent()); @@ -609,21 +606,21 @@ void Fl_Menu_Item_Type::write_code1(fld::io::Code_Writer& f) { image->write_code(f, 0, "o"); } } - if (g_project.i18n_type && label() && label()[0]) { + if ((Fluid.proj.i18n_type != fld::I18n_Type::NONE) && label() && label()[0]) { Fl_Labeltype t = o->labeltype(); if (image) { // label was already copied a few lines up } else if ( t==FL_NORMAL_LABEL || t==FL_SHADOW_LABEL || t==FL_ENGRAVED_LABEL || t==FL_EMBOSSED_LABEL) { start_menu_initialiser(f, menuItemInitialized, mname, i); - if (g_project.i18n_type==FD_I18N_GNU) { + if (Fluid.proj.i18n_type==fld::I18n_Type::GNU) { f.write_c("%so->label(%s(o->label()));\n", - f.indent(), g_project.i18n_gnu_function.c_str()); - } else if (g_project.i18n_type==FD_I18N_POSIX) { + f.indent(), Fluid.proj.i18n_gnu_function.c_str()); + } else if (Fluid.proj.i18n_type==fld::I18n_Type::POSIX) { f.write_c("%so->label(catgets(%s,%s,i+%d,o->label()));\n", f.indent(), - g_project.i18n_pos_file.empty() ? "_catalog" : g_project.i18n_pos_file.c_str(), - g_project.i18n_pos_set.c_str(), msgnum()); + Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), + Fluid.proj.i18n_pos_set.c_str(), msgnum()); } } } @@ -639,7 +636,7 @@ void Fl_Menu_Item_Type::write_code1(fld::io::Code_Writer& f) { } } -void Fl_Menu_Item_Type::write_code2(fld::io::Code_Writer&) {} +void Menu_Item_Node::write_code2(fld::io::Code_Writer&) {} //////////////////////////////////////////////////////////////// // This is the base class for widgets that contain a menu (ie @@ -648,18 +645,18 @@ void Fl_Menu_Item_Type::write_code2(fld::io::Code_Writer&) {} // children. An actual array of Fl_Menu_Items is kept parallel // with the child objects and updated as they change. -void Fl_Menu_Base_Type::build_menu() { +void Menu_Base_Node::build_menu() { Fl_Menu_* w = (Fl_Menu_*)o; // count how many Fl_Menu_Item structures needed: int n = 0; - Fl_Type* q; + Node* q; for (q = next; q && q->level > level; q = q->next) { if (q->can_have_children()) n++; // space for null at end of submenu n++; } if (!n) { if (menusize) delete_menu((Fl_Menu_Item*)(w->menu())); - w->menu(0); + w->menu(nullptr); menusize = 0; } else { n++; // space for null at end of menu @@ -671,7 +668,7 @@ void Fl_Menu_Base_Type::build_menu() { if (menusize) delete_dependents((Fl_Menu_Item*)(w->menu())); } // Menus are already built during the .fl file reading process, so if the - // end of a menu list is not read yet, the end markers (label==NULL) will + // end of a menu list is not read yet, the end markers (label==nullptr) will // not be set, and deleting dependents will randomly free memory. // Clearing the array should avoid that. memset( (void*)w->menu(), 0, menusize * sizeof(Fl_Menu_Item) ); @@ -679,7 +676,7 @@ void Fl_Menu_Base_Type::build_menu() { Fl_Menu_Item* m = (Fl_Menu_Item*)(w->menu()); int lvl = level+1; for (q = next; q && q->level > level; q = q->next) { - Fl_Menu_Item_Type* i = (Fl_Menu_Item_Type*)q; + Menu_Item_Node* i = (Menu_Item_Node*)q; if (i->o->image()) { if (i->o->label() && i->o->label()[0]) { Fl_Multi_Label *ml = new Fl_Multi_Label; @@ -696,7 +693,7 @@ void Fl_Menu_Base_Type::build_menu() { m->labeltype(i->o->labeltype()); } m->shortcut(((Fl_Button*)(i->o))->shortcut()); - m->callback(0,(void*)i); + m->callback(nullptr,(void*)i); m->flags = i->flags() | i->o->type(); m->labelfont(i->o->labelfont()); m->labelsize(i->o->labelsize()); @@ -704,43 +701,43 @@ void Fl_Menu_Base_Type::build_menu() { if (q->can_have_children()) {lvl++; m->flags |= FL_SUBMENU;} m++; int l1 = - (q->next && q->next->is_a(ID_Menu_Item)) ? q->next->level : level; - while (lvl > l1) {m->label(0); m++; lvl--;} + (q->next && q->next->is_a(Type::Menu_Item)) ? q->next->level : level; + while (lvl > l1) {m->label(nullptr); m++; lvl--;} lvl = l1; } } o->redraw(); } -Fl_Type* Fl_Menu_Base_Type::click_test(int, int) { - if (selected) return 0; // let user move the widget +Node* Menu_Base_Node::click_test(int, int) { + if (selected) return nullptr; // let user move the widget Fl_Menu_* w = (Fl_Menu_*)o; - if (!menusize) return 0; + if (!menusize) return nullptr; const Fl_Menu_Item* save = w->mvalue(); - w->value((Fl_Menu_Item*)0); + w->value((Fl_Menu_Item*)nullptr); Fl::pushed(w); w->handle(FL_PUSH); - Fl::focus(NULL); + Fl::focus(nullptr); const Fl_Menu_Item* m = w->mvalue(); if (m) { // restore the settings of toggles & radio items: if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); - return (Fl_Type*)(m->user_data()); + return (Node*)(m->user_data()); } w->value(save); return this; } -void Fl_Menu_Manager_Type::write_code2(fld::io::Code_Writer& f) { - if (next && next->is_a(ID_Menu_Item)) { +void Menu_Manager_Node::write_code2(fld::io::Code_Writer& f) { + if (next && next->is_a(Type::Menu_Item)) { f.write_c("%s%s->menu(%s);\n", f.indent(), name() ? name() : "o", f.unique_id(this, "menu", name(), label())); } - Fl_Widget_Type::write_code2(f); + Widget_Node::write_code2(f); } -void Fl_Menu_Base_Type::copy_properties() { - Fl_Widget_Type::copy_properties(); +void Menu_Base_Node::copy_properties() { + Widget_Node::copy_properties(); Fl_Menu_ *s = (Fl_Menu_*)o, *d = (Fl_Menu_*)live_widget; d->menu(s->menu()); d->down_box(s->down_box()); @@ -752,28 +749,28 @@ void Fl_Menu_Base_Type::copy_properties() { //////////////////////////////////////////////////////////////// Fl_Menu_Item button_type_menu[] = { - {"normal",0,0,(void*)0}, - {"popup1",0,0,(void*)Fl_Menu_Button::POPUP1}, - {"popup2",0,0,(void*)Fl_Menu_Button::POPUP2}, - {"popup3",0,0,(void*)Fl_Menu_Button::POPUP3}, - {"popup12",0,0,(void*)Fl_Menu_Button::POPUP12}, - {"popup23",0,0,(void*)Fl_Menu_Button::POPUP23}, - {"popup13",0,0,(void*)Fl_Menu_Button::POPUP13}, - {"popup123",0,0,(void*)Fl_Menu_Button::POPUP123}, - {0}}; + {"normal",0,nullptr,(void*)nullptr}, + {"popup1",0,nullptr,(void*)Fl_Menu_Button::POPUP1}, + {"popup2",0,nullptr,(void*)Fl_Menu_Button::POPUP2}, + {"popup3",0,nullptr,(void*)Fl_Menu_Button::POPUP3}, + {"popup12",0,nullptr,(void*)Fl_Menu_Button::POPUP12}, + {"popup23",0,nullptr,(void*)Fl_Menu_Button::POPUP23}, + {"popup13",0,nullptr,(void*)Fl_Menu_Button::POPUP13}, + {"popup123",0,nullptr,(void*)Fl_Menu_Button::POPUP123}, + {nullptr}}; -Fl_Menu_Button_Type Fl_Menu_Button_type; +Menu_Button_Node Menu_Button_Node::prototype; //////////////////////////////////////////////////////////////// -Fl_Menu_Item dummymenu[] = {{"CHOICE"},{0}}; +Fl_Menu_Item dummymenu[] = {{"CHOICE"},{nullptr}}; -Fl_Choice_Type Fl_Choice_type; +Choice_Node Choice_Node::prototype; -Fl_Input_Choice_Type Fl_Input_Choice_type; +Input_Choice_Node Input_Choice_Node::prototype; -void Fl_Input_Choice_Type::copy_properties() { - Fl_Widget_Type::copy_properties(); +void Input_Choice_Node::copy_properties() { + Widget_Node::copy_properties(); Fl_Input_Choice *s = (Fl_Input_Choice*)o, *d = (Fl_Input_Choice*)live_widget; d->menu(s->menu()); d->down_box(s->down_box()); @@ -782,20 +779,20 @@ void Fl_Input_Choice_Type::copy_properties() { d->textsize(s->textsize()); } -Fl_Type* Fl_Input_Choice_Type::click_test(int, int) { - if (selected) return 0; // let user move the widget +Node* Input_Choice_Node::click_test(int, int) { + if (selected) return nullptr; // let user move the widget Fl_Menu_* w = ((Fl_Input_Choice*)o)->menubutton(); - if (!menusize) return 0; + if (!menusize) return nullptr; const Fl_Menu_Item* save = w->mvalue(); - w->value((Fl_Menu_Item*)0); + w->value((Fl_Menu_Item*)nullptr); Fl::pushed(w); w->handle(FL_PUSH); - Fl::focus(NULL); + Fl::focus(nullptr); const Fl_Menu_Item* m = w->mvalue(); if (m) { // restore the settings of toggles & radio items: if (m->flags & (FL_MENU_RADIO | FL_MENU_TOGGLE)) build_menu(); - return (Fl_Type*)(m->user_data()); + return (Node*)(m->user_data()); } w->value(save); return this; @@ -803,19 +800,19 @@ Fl_Type* Fl_Input_Choice_Type::click_test(int, int) { //////////////////////////////////////////////////////////////// -Fl_Menu_Bar_Type Fl_Menu_Bar_type; +Menu_Bar_Node Menu_Bar_Node::prototype; Fl_Menu_Item menu_bar_type_menu[] = { - {"Fl_Menu_Bar",0,0,(void*)0}, - {"Fl_Sys_Menu_Bar",0,0,(void*)1}, - {0}}; + {"Fl_Menu_Bar",0,nullptr,(void*)nullptr}, + {"Fl_Sys_Menu_Bar",0,nullptr,(void*)1}, + {nullptr}}; -Fl_Menu_Bar_Type::Fl_Menu_Bar_Type() -: _proxy_name(NULL) +Menu_Bar_Node::Menu_Bar_Node() +: _proxy_name(nullptr) { } -Fl_Menu_Bar_Type::~Fl_Menu_Bar_Type() { +Menu_Bar_Node::~Menu_Bar_Node() { if (_proxy_name) ::free(_proxy_name); } @@ -825,19 +822,19 @@ Fl_Menu_Bar_Type::~Fl_Menu_Bar_Type() { This test fails if subclass() is the name of a class that the user may have derived from Fl_Sys_Menu_Bar. */ -bool Fl_Menu_Bar_Type::is_sys_menu_bar() { +bool Menu_Bar_Node::is_sys_menu_bar() { if (o->type()==1) return true; return ( subclass() && (strcmp(subclass(), "Fl_Sys_Menu_Bar")==0) ); } -const char *Fl_Menu_Bar_Type::sys_menubar_name() { +const char *Menu_Bar_Node::sys_menubar_name() { if (subclass()) return subclass(); else return "Fl_Sys_Menu_Bar"; } -const char *Fl_Menu_Bar_Type::sys_menubar_proxy_name() { +const char *Menu_Bar_Node::sys_menubar_proxy_name() { if (!_proxy_name) _proxy_name = (char*)::malloc(128); ::snprintf(_proxy_name, 63, "%s_Proxy", sys_menubar_name()); @@ -845,7 +842,7 @@ const char *Fl_Menu_Bar_Type::sys_menubar_proxy_name() { } -void Fl_Menu_Bar_Type::write_static(fld::io::Code_Writer& f) { +void Menu_Bar_Node::write_static(fld::io::Code_Writer& f) { super::write_static(f); if (is_sys_menu_bar()) { f.write_h_once("#include "); @@ -854,7 +851,7 @@ void Fl_Menu_Bar_Type::write_static(fld::io::Code_Writer& f) { f.write_c_once( // must be less than 1024 bytes! "\nclass %s: public %s {\n" "public:\n" - " %s(int x, int y, int w, int h, const char *l=NULL)\n" + " %s(int x, int y, int w, int h, const char *l=0L)\n" " : %s(x, y, w, h, l) { }\n" " void *_parent_class;\n" "};\n", @@ -865,7 +862,7 @@ void Fl_Menu_Bar_Type::write_static(fld::io::Code_Writer& f) { } } -void Fl_Menu_Bar_Type::write_code1(fld::io::Code_Writer& f) { +void Menu_Bar_Node::write_code1(fld::io::Code_Writer& f) { super::write_code1(f); if (is_sys_menu_bar() && is_in_class()) { f.write_c("%s((%s*)%s)->_parent_class = (void*)this;\n", @@ -873,52 +870,7 @@ void Fl_Menu_Bar_Type::write_code1(fld::io::Code_Writer& f) { } } -//void Fl_Menu_Bar_Type::write_code2(fld::io::Code_Writer& f) { +//void Menu_Bar_Node::write_code2(fld::io::Code_Writer& f) { // super::write_code2(f); //} -//////////////////////////////////////////////////////////////// -// Shortcut entry item in panel: -void shortcut_in_cb(Fl_Shortcut_Button* i, void* v) { - if (v == LOAD) { - if (current_widget->is_button()) - i->value( ((Fl_Button*)(current_widget->o))->shortcut() ); - else if (current_widget->is_a(ID_Input)) - i->value( ((Fl_Input_*)(current_widget->o))->shortcut() ); - else if (current_widget->is_a(ID_Value_Input)) - i->value( ((Fl_Value_Input*)(current_widget->o))->shortcut() ); - else if (current_widget->is_a(ID_Text_Display)) - i->value( ((Fl_Text_Display*)(current_widget->o))->shortcut() ); - else { - i->hide(); - i->parent()->hide(); - return; - } - //i->default_value( i->value() ); // enable the "undo" capability of the shortcut button - i->show(); - i->parent()->show(); - i->redraw(); - } else { - int mod = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) - if (o->selected && o->is_button()) { - Fl_Button* b = (Fl_Button*)(((Fl_Widget_Type*)o)->o); - if (b->shortcut() != (int)i->value()) mod = 1; - b->shortcut(i->value()); - if (o->is_a(ID_Menu_Item)) ((Fl_Widget_Type*)o)->redraw(); - } else if (o->selected && o->is_a(ID_Input)) { - Fl_Input_* b = (Fl_Input_*)(((Fl_Widget_Type*)o)->o); - if (b->shortcut() != (int)i->value()) mod = 1; - b->shortcut(i->value()); - } else if (o->selected && o->is_a(ID_Value_Input)) { - Fl_Value_Input* b = (Fl_Value_Input*)(((Fl_Widget_Type*)o)->o); - if (b->shortcut() != (int)i->value()) mod = 1; - b->shortcut(i->value()); - } else if (o->selected && o->is_a(ID_Text_Display)) { - Fl_Text_Display* b = (Fl_Text_Display*)(((Fl_Widget_Type*)o)->o); - if (b->shortcut() != (int)i->value()) mod = 1; - b->shortcut(i->value()); - } - if (mod) set_modflag(1); - } -} diff --git a/fluid/nodes/Menu_Node.h b/fluid/nodes/Menu_Node.h new file mode 100644 index 000000000..59d3b06bb --- /dev/null +++ b/fluid/nodes/Menu_Node.h @@ -0,0 +1,310 @@ +// +// Menu Node header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 +// + +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Node base class. +// + + +#ifndef FLUID_NODES_MENU_NODE_H +#define FLUID_NODES_MENU_NODE_H + +#include "nodes/Button_Node.h" + +#include "Fluid.h" +#include "app/Snap_Action.h" + +#include +#include +#include +#include +#include +#include + +extern Fl_Menu_Item dummymenu[]; +extern Fl_Menu_Item button_type_menu[]; +extern Fl_Menu_Item menu_item_type_menu[]; +extern Fl_Menu_Item menu_bar_type_menu[]; + +/** + \brief Manage all types on menu items. + Deriving Menu_Item_Node from Button_Node is intentional. For the purpose + of editing, a Menu Item is implemented with `o` pointing to an Fl_Button for + holding all properties. + */ +class Menu_Item_Node : public Button_Node +{ +public: + typedef Button_Node super; + static Menu_Item_Node prototype; +public: + Fl_Menu_Item* subtypes() override {return menu_item_type_menu;} + const char* type_name() override {return "MenuItem";} + const char* alt_type_name() override {return "fltk::Item";} + Node* make(Strategy strategy) override; + Node* make(int flags, Strategy strategy); + int is_button() const override {return 1;} // this gets shortcut to work + Fl_Widget* widget(int,int,int,int) override {return nullptr;} + Widget_Node* _make() override {return nullptr;} + virtual const char* menu_name(fld::io::Code_Writer& f, int& i); + int flags(); + void write_static(fld::io::Code_Writer& f) override; + void write_item(fld::io::Code_Writer& f); + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + int is_true_widget() const override { return 0; } + Type type() const override { return Type::Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \brief Manage Radio style Menu Items. + */ +class Radio_Menu_Item_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Radio_Menu_Item_Node prototype; +public: + const char* type_name() override {return "RadioMenuItem";} + Node* make(Strategy strategy) override; + Type type() const override { return Type::Radio_Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Radio_Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \brief Manage Checkbox style Menu Items. + */ +class Checkbox_Menu_Item_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Checkbox_Menu_Item_Node prototype; +public: + const char* type_name() override {return "CheckMenuItem";} + Node* make(Strategy strategy) override; + Type type() const override { return Type::Checkbox_Menu_Item; } + bool is_a(Type inType) const override { return (inType==Type::Checkbox_Menu_Item) ? true : super::is_a(inType); } +}; + +/** + \brief Manage Submenu style Menu Items. + Submenu Items are simply buttons just like all other menu items, but they + can also hold a pointer to a list of submenus, or have a flag set that + allows submenus to follow in the current array. As buttons, they can + be clicked by the user, and they will call their callback, if one is set. + */ +class Submenu_Node : public Menu_Item_Node +{ +public: + typedef Menu_Item_Node super; + static Submenu_Node prototype; +public: + Fl_Menu_Item* subtypes() override {return nullptr;} + const char* type_name() override {return "Submenu";} + const char* alt_type_name() override {return "fltk::ItemGroup";} + int can_have_children() const override {return 1;} + int is_button() const override {return 0;} // disable shortcut + Node* make(Strategy strategy) override; + // changes to submenu must propagate up so build_menu is called + // on the parent Menu_Node: + void add_child(Node*a, Node*b) override {parent->add_child(a,b);} + void move_child(Node*a, Node*b) override {parent->move_child(a,b);} + void remove_child(Node*a) override {parent->remove_child(a);} + Type type() const override { return Type::Submenu; } + bool is_a(Type inType) const override { return (inType==Type::Submenu) ? true : super::is_a(inType); } +}; + +// ----------------------------------------------------------------------------- + +/** + \brief Base class for all widgets that can have a pulldown menu attached. + Widgets with this type can be derived from Fl_Menu_ or from + Fl_Group (Fl_Input_Choice). + */ +class Menu_Manager_Node : public Widget_Node +{ + typedef Widget_Node super; +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; + h = layout->textsize_not_null() + 8; + w = layout->textsize_not_null() * 6 + 8; + fld::app::Snap_Action::better_size(w, h); + } + int can_have_children() const override {return 1;} + int menusize; + virtual void build_menu() = 0; + Menu_Manager_Node() : Widget_Node() {menusize = 0;} + void add_child(Node*, Node*) override { build_menu(); } + void move_child(Node*, Node*) override { build_menu(); } + void remove_child(Node*) override { build_menu();} + Node* click_test(int x, int y) override = 0; + void write_code2(fld::io::Code_Writer& f) override; + void copy_properties() override = 0; + Type type() const override { return Type::Menu_Manager_; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Manager_) ? true : super::is_a(inType); } +}; + +/** + \brief Manage the composite widget Input Choice. + \note Input Choice is a composite window, so `o` will be pointing to a widget + derived from Fl_Group. All menu related methods from Fl_Menu_Trait_Type must + be virtual and must be reimplemented here (click_test, build_menu, textstuff). + */ +class Input_Choice_Node : public Menu_Manager_Node +{ +public: + typedef Menu_Manager_Node super; + static Input_Choice_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Input_Choice *myo = (Fl_Input_Choice*)(w==4 ? ((Widget_Node*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; + } +public: + ~Input_Choice_Node() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Input_Choice*)o)->menu()); + } + const char *type_name() override {return "Fl_Input_Choice";} + const char *alt_type_name() override {return "fltk::ComboBox";} + Node* click_test(int,int) override; + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Input_Choice *myo = new Fl_Input_Choice(X,Y,W,H,"input choice:"); + myo->menu(dummymenu); + myo->value("input"); + return myo; + } + Widget_Node *_make() override {return new Input_Choice_Node();} + void build_menu() override; + Type type() const override { return Type::Input_Choice; } + bool is_a(Type inType) const override { return (inType==Type::Input_Choice) ? true : super::is_a(inType); } + void copy_properties() override; +}; + +/** + \brief Base class to handle widgets that are derived from Fl_Menu_. + */ +class Menu_Base_Node : public Menu_Manager_Node +{ + typedef Menu_Manager_Node super; + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Menu_ *myo = (Fl_Menu_*)(w==4 ? ((Widget_Node*)this->factory)->o : this->o); + switch (w) { + case 4: + case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; + case 1: myo->textfont(f); break; + case 2: myo->textsize(s); break; + case 3: myo->textcolor(c); break; + } + return 1; + } +public: + int can_have_children() const override {return 1;} + void build_menu() override; + ~Menu_Base_Node() { + if (menusize) delete[] (Fl_Menu_Item*)(((Fl_Menu_*)o)->menu()); + } + Node* click_test(int x, int y) override; + void copy_properties() override; + Type type() const override { return Type::Menu_; } + bool is_a(Type inType) const override { return (inType==Type::Menu_) ? true : super::is_a(inType); } +}; + +extern Fl_Menu_Item button_type_menu[]; + +/** + \brief Make Menu Button widgets. + */ +class Menu_Button_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Menu_Button_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return button_type_menu;} +public: + const char *type_name() override {return "Fl_Menu_Button";} + const char *alt_type_name() override {return "fltk::MenuButton";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + return new Fl_Menu_Button(X,Y,W,H,"menu");} + Widget_Node *_make() override {return new Menu_Button_Node();} + Type type() const override { return Type::Menu_Button; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Button) ? true : super::is_a(inType); } +}; + + +/** + \brief Manage Choice type menu widgets. + */ +class Choice_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Choice_Node prototype; +public: + const char *type_name() override {return "Fl_Choice";} + const char *alt_type_name() override {return "fltk::Choice";} + Fl_Widget *widget(int X,int Y,int W,int H) override { + Fl_Choice *myo = new Fl_Choice(X,Y,W,H,"choice:"); + myo->menu(dummymenu); + return myo; + } + Widget_Node *_make() override {return new Choice_Node();} + Type type() const override { return Type::Choice; } + bool is_a(Type inType) const override { return (inType==Type::Choice) ? true : super::is_a(inType); } +}; + + +/** + \brief Manage Menubar widgets. + */ +class Menu_Bar_Node : public Menu_Base_Node +{ +public: + typedef Menu_Base_Node super; + static Menu_Bar_Node prototype; +private: + Fl_Menu_Item *subtypes() override {return menu_bar_type_menu;} +public: + Menu_Bar_Node(); + ~Menu_Bar_Node() override; + const char *type_name() override {return "Fl_Menu_Bar";} + const char *alt_type_name() override {return "fltk::MenuBar";} + Fl_Widget *widget(int X,int Y,int W,int H) override {return new Fl_Menu_Bar(X,Y,W,H);} + Widget_Node *_make() override {return new Menu_Bar_Node();} + void write_static(fld::io::Code_Writer& f) override; + void write_code1(fld::io::Code_Writer& f) override; +// void write_code2(fld::io::Code_Writer& f) override; + Type type() const override { return Type::Menu_Bar; } + bool is_a(Type inType) const override { return (inType==Type::Menu_Bar) ? true : super::is_a(inType); } + bool is_sys_menu_bar(); + const char *sys_menubar_name(); + const char *sys_menubar_proxy_name(); +protected: + char *_proxy_name; +}; + + +#endif // FLUID_NODES_MENU_NODE_H diff --git a/fluid/nodes/Fl_Type.cxx b/fluid/nodes/Node.cxx similarity index 68% rename from fluid/nodes/Fl_Type.cxx rename to fluid/nodes/Node.cxx index 8f078e06e..194484a93 100644 --- a/fluid/nodes/Fl_Type.cxx +++ b/fluid/nodes/Node.cxx @@ -1,7 +1,7 @@ // -// Widget type code for the Fast Light Tool Kit (FLTK). +// Node base class code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -17,7 +17,7 @@ /// \defgroup fl_type Basic Node for all Widgets and Functions /// \{ -/** \class Fl_Type +/** \class Node Each object described by Fluid is one of these objects. They are all stored in a double-linked list. @@ -30,84 +30,84 @@ not in the linked list and are not written to files or copied or otherwise examined. - The Fl_Type inheritance is currently: - --+-- Fl_Type - +-- Fl_Function_Type - +-- Fl_Code_Type - +-- Fl_CodeBlock_Type - +-+ Fl_Decl_Type + The Node inheritance is currently: + --+-- Node + +-- Function_Node + +-- Code_Node + +-- CodeBlock_Node + +-+ Decl_Node | +-- Fl_Data - +-- Fl_DeclBlock_Type - +-- Fl_Comment_Type - +-- Fl_Class_Type - +-+ Fl_Widget_Type, 'o' points to a class derived from Fl_Widget - +-+ Fl_Browser_Base_Type, 'o' is Fl_Browser + +-- DeclBlock_Node + +-- Comment_Node + +-- Class_Node + +-+ Widget_Node, 'o' points to a class derived from Fl_Widget + +-+ Browser_Base_Node, 'o' is Fl_Browser | +-+ Fl_Browser | | +-- Fl_File_Browser | +-- Fl_Check_Browser - +-- Fl_Tree_Type - +-- Fl_Help_View_Type - +-+ Fl_Valuator_Type, 'o' is Fl_Valuator_ - | +-- Fl_Counter_Type - | +-- Fl_Adjuster_Type - | +-- Fl_Dial_Type - | +-- Fl_Roller_Type - | +-- Fl_Slider_Type - | +-- Fl_Value_Input_Type - | +-- Fl_Value_Output_Type - +-+ Fl_Input_Type - | +-- Fl_Output_Type - +-+ Fl_Text_Display_Type - | +-- Fl_Text_Editor_Type - +-- Fl_Terminal_Type - +-- Fl_Box_Type - +-- Fl_Clock_Type - +-- Fl_Progress_Type - +-- Fl_Spinner_Type - +-+ Fl_Group_Type - | +-- Fl_Pack_Type - | +-- Fl_Flex_Type - | +-- Fl_Grid_Type - | +-- Fl_Table_Type - | +-- Fl_Tabs_Type - | +-- Fl_Scroll_Type - | +-- Fl_Tile_Type - | +-- Fl_Wizard_Type - | +-+ Fl_Window_Type - | +-- Fl_Widget_Class_Type - +-+ Fl_Menu_Manager_Type, 'o' is based on Fl_Widget - | +-+ Fl_Menu_Base_Type, 'o' is based on Fl_Menu_ - | | +-- Fl_Menu_Button_Type - | | +-- Fl_Choice_Type - | | +-- Fl_Menu_Bar_Type - | +-- Fl_Input_Choice_Type, 'o' is based on Fl_Input_Choice which is Fl_Group - +-+ Fl_Button_Type - +-- Fl_Return_Button_Type - +-- Fl_Repeat_Button_Type - +-- Fl_Light_Button_Type - +-- Fl_Check_Button_Type - +-- Fl_Round_Button_Type - +-+ Fl_Menu_Item_Type, 'o' is derived from Fl_Button in FLUID - +-- Fl_Radio_Menu_Item_Type - +-- Fl_Checkbox_Menu_Item_Type + +-- Tree_Node + +-- Help_View_Node + +-+ Valuator_Node, 'o' is Fl_Valuator_ + | +-- Counter_Node + | +-- Adjuster_Node + | +-- Dial_Node + | +-- Roller_Node + | +-- Slider_Node + | +-- Value_Input_Node + | +-- Value_Output_Node + +-+ Input_Node + | +-- Output_Node + +-+ Text_Display_Node + | +-- Text_Editor_Node + +-- Terminal_Node + +-- Box_Node + +-- Clock_Node + +-- Progress_Node + +-- Spinner_Node + +-+ Group_Node + | +-- Pack_Node + | +-- Flex_Node + | +-- Grid_Node + | +-- Table_Node + | +-- Tabs_Node + | +-- Scroll_Node + | +-- Tile_Node + | +-- Wizard_Node + | +-+ Window_Node + | +-- Widget_Class_Node + +-+ Menu_Manager_Node, 'o' is based on Fl_Widget + | +-+ Menu_Base_Node, 'o' is based on Fl_Menu_ + | | +-- Menu_Button_Node + | | +-- Choice_Node + | | +-- Menu_Bar_Node + | +-- Input_Choice_Node, 'o' is based on Fl_Input_Choice which is Fl_Group + +-+ Button_Node + +-- Return_Button_Node + +-- Repeat_Button_Node + +-- Light_Button_Node + +-- Check_Button_Node + +-- Round_Button_Node + +-+ Menu_Item_Node, 'o' is derived from Fl_Button in FLUID + +-- Radio_Menu_Item_Node + +-- Checkbox_Menu_Item_Node +-- Fl_Submenu_Item_Type */ -#include "nodes/Fl_Type.h" +#include "nodes/Node.h" -#include "app/fluid.h" -#include "app/project.h" -#include "app/Fd_Snap_Action.h" +#include "Fluid.h" +#include "Project.h" +#include "app/Snap_Action.h" #include "app/shell_command.h" -#include "app/undo.h" +#include "proj/undo.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Widget_Type.h" -#include "nodes/Fl_Window_Type.h" -#include "nodes/Fl_Group_Type.h" +#include "nodes/Function_Node.h" +#include "nodes/Widget_Node.h" +#include "nodes/Window_Node.h" +#include "nodes/Group_Node.h" #include "rsrcs/pixmaps.h" #include "widgets/Node_Browser.h" @@ -121,13 +121,7 @@ // ---- global variables -Fl_Type *Fl_Type::first = NULL; -Fl_Type *Fl_Type::last = NULL; -Fl_Type *Fl_Type::current = NULL; -Fl_Type *Fl_Type::current_dnd = NULL; -int Fl_Type::allow_layout = 0; - -Fl_Type *in_this_only; // set if menu popped-up in window +Node *in_this_only; // set if menu popped-up in window // ---- various functions @@ -138,8 +132,8 @@ Fl_Type *in_this_only; // set if menu popped-up in window Print the current project tree to stderr. */ void print_project_tree() { - fprintf(stderr, "---- %s --->\n", g_project.projectfile_name().c_str()); - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + fprintf(stderr, "---- %s --->\n", Fluid.proj.projectfile_name().c_str()); + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { for (int i = t->level; i > 0; i--) fprintf(stderr, ". "); fprintf(stderr, "%s\n", subclassname(t)); @@ -157,20 +151,20 @@ void print_project_tree() { */ bool validate_project_tree() { // Validate `first` and `last` - if (Fl_Type::first == NULL) { - if (Fl_Type::last == NULL) { + if (Fluid.proj.tree.first == nullptr) { + if (Fluid.proj.tree.last == nullptr) { return true; } else { - fprintf(stderr, "ERROR: `first` is NULL, but `last` is not!\n"); + fprintf(stderr, "ERROR: `first` is nullptr, but `last` is not!\n"); return false; } } - if (Fl_Type::last == NULL) { - fprintf(stderr, "ERROR: `last` is NULL, but `first` is not!\n"); + if (Fluid.proj.tree.last == nullptr) { + fprintf(stderr, "ERROR: `last` is nullptr, but `first` is not!\n"); return false; } // Validate the branch linkage, parent links, etc. - return validate_branch(Fl_Type::first); + return validate_branch(Fluid.proj.tree.first); } #endif @@ -183,19 +177,19 @@ bool validate_project_tree() { \param[in] root the first node in a branch \return true if the branch is correctly separated and valid */ -bool validate_independent_branch(class Fl_Type *root) { +bool validate_independent_branch(class Node *root) { // Make sure that `first` and `last` do not point at any node in this branch - if (Fl_Type::first) { - for (Fl_Type *t = root; t; t = t->next) { - if (Fl_Type::first == t) { + if (Fluid.proj.tree.first) { + for (Node *t = root; t; t = t->next) { + if (Fluid.proj.tree.first == t) { fprintf(stderr, "ERROR: Branch is not independent, `first` is pointing to branch member!\n"); return false; } } } - if (Fl_Type::last) { - for (Fl_Type *t = root; t; t = t->next) { - if (Fl_Type::last == t) { + if (Fluid.proj.tree.last) { + for (Node *t = root; t; t = t->next) { + if (Fluid.proj.tree.last == t) { fprintf(stderr, "ERROR: Branch is not independent, `last` is pointing to branch member!\n"); return false; } @@ -215,14 +209,14 @@ bool validate_independent_branch(class Fl_Type *root) { \param[in] root the first node in a branch \return true if the branch is valid */ -bool validate_branch(class Fl_Type *root) { +bool validate_branch(class Node *root) { // Only check real branches if (!root) { fprintf(stderr, "WARNING: Branch is empty!\n"); return false; } // Check relation between this and next node - for (Fl_Type *t = root; t; t = t->next) { + for (Node *t = root; t; t = t->next) { if (t->level < root->level) { fprintf(stderr, "ERROR: Node in tree is above root level!\n"); return false; @@ -247,10 +241,10 @@ bool validate_branch(class Fl_Type *root) { } } // Validate the `parent` entry - for (Fl_Type *p = t->prev; ; p = p->prev) { - if (p == NULL) { - if (t->parent != NULL) { - fprintf(stderr, "ERROR: `parent` pointer should be NULL!\n"); + for (Node *p = t->prev; ; p = p->prev) { + if (p == nullptr) { + if (t->parent != nullptr) { + fprintf(stderr, "ERROR: `parent` pointer should be nullptr!\n"); return false; } break; @@ -270,22 +264,22 @@ bool validate_branch(class Fl_Type *root) { #endif void select_all_cb(Fl_Widget *,void *) { - Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; + Node *p = Fluid.proj.tree.current ? Fluid.proj.tree.current->parent : nullptr; if (in_this_only) { - Fl_Type *t = p; + Node *t = p; for (; t && t != in_this_only; t = t->parent) {/*empty*/} if (t != in_this_only) p = in_this_only; } for (;;) { if (p) { int foundany = 0; - for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { + for (Node *t = p->next; t && t->level>p->level; t = t->next) { if (!t->new_selected) {widget_browser->select(t,1,0); foundany = 1;} } if (foundany) break; p = p->parent; } else { - for (Fl_Type *t = Fl_Type::first; t; t = t->next) + for (Node *t = Fluid.proj.tree.first; t; t = t->next) widget_browser->select(t,1,0); break; } @@ -294,22 +288,22 @@ void select_all_cb(Fl_Widget *,void *) { } void select_none_cb(Fl_Widget *,void *) { - Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0; + Node *p = Fluid.proj.tree.current ? Fluid.proj.tree.current->parent : nullptr; if (in_this_only) { - Fl_Type *t = p; + Node *t = p; for (; t && t != in_this_only; t = t->parent) {/*empty*/} if (t != in_this_only) p = in_this_only; } for (;;) { if (p) { int foundany = 0; - for (Fl_Type *t = p->next; t && t->level>p->level; t = t->next) { + for (Node *t = p->next; t && t->level>p->level; t = t->next) { if (t->new_selected) {widget_browser->select(t,0,0); foundany = 1;} } if (foundany) break; p = p->parent; } else { - for (Fl_Type *t = Fl_Type::first; t; t = t->next) + for (Node *t = Fluid.proj.tree.first; t; t = t->next) widget_browser->select(t,0,0); break; } @@ -321,15 +315,15 @@ void select_none_cb(Fl_Widget *,void *) { Callback to move all selected items before their previous unselected sibling. */ void earlier_cb(Fl_Widget*,void*) { - Fl_Type *f; + Node *f; int mod = 0; - for (f = Fl_Type::first; f; ) { - Fl_Type* nxt = f->next; + for (f = Fluid.proj.tree.first; f; ) { + Node* nxt = f->next; if (f->selected) { - Fl_Type* g; + Node* g; for (g = f->prev; g && g->level > f->level; g = g->prev) {/*empty*/} if (g && g->level == f->level && !g->selected) { - if (!mod) undo_checkpoint(); + if (!mod) Fluid.proj.undo.checkpoint(); f->move_before(g); if (f->parent) f->parent->layout_widget(); mod = 1; @@ -337,8 +331,8 @@ void earlier_cb(Fl_Widget*,void*) { } f = nxt; } - if (mod) set_modflag(1); - widget_browser->display(Fl_Type::current); + if (mod) Fluid.proj.set_modflag(1); + widget_browser->display(Fluid.proj.tree.current); widget_browser->rebuild(); } @@ -346,15 +340,15 @@ void earlier_cb(Fl_Widget*,void*) { Callback to move all selected items after their next unselected sibling. */ void later_cb(Fl_Widget*,void*) { - Fl_Type *f; + Node *f; int mod = 0; - for (f = Fl_Type::last; f; ) { - Fl_Type* prv = f->prev; + for (f = Fluid.proj.tree.last; f; ) { + Node* prv = f->prev; if (f->selected) { - Fl_Type* g; + Node* g; for (g = f->next; g && g->level > f->level; g = g->next) {/*empty*/} if (g && g->level == f->level && !g->selected) { - if (!mod) undo_checkpoint(); + if (!mod) Fluid.proj.undo.checkpoint(); g->move_before(f); if (f->parent) f->parent->layout_widget(); mod = 1; @@ -362,21 +356,21 @@ void later_cb(Fl_Widget*,void*) { } f = prv; } - if (mod) set_modflag(1); - widget_browser->display(Fl_Type::current); + if (mod) Fluid.proj.set_modflag(1); + widget_browser->display(Fluid.proj.tree.current); widget_browser->rebuild(); } /** \brief Delete all children of a Type. */ -static void delete_children(Fl_Type *p) { - Fl_Type *f; +static void delete_children(Node *p) { + Node *f; // find all types following p that are higher in level, effectively finding // the last child of the last child for (f = p; f && f->next && f->next->level > p->level; f = f->next) {/*empty*/} // now loop back up to p, deleting all children on the way for (; f != p; ) { - Fl_Type *g = f->prev; + Node *g = f->prev; delete f; f = g; } @@ -384,7 +378,7 @@ static void delete_children(Fl_Type *p) { /** Delete all nodes in the Types tree and reset project settings, or delete selected nodes. Also calls the browser to refresh. - \note Please refactor this into two separate methods of Fluid_Project. + \note Please refactor this into two separate methods of Project. \param[in] selected_only if set, delete only the selected widgets and don't reset the project. */ @@ -394,10 +388,10 @@ void delete_all(int selected_only) { widget_browser->save_scroll_position(); widget_browser->new_list(); } - for (Fl_Type *f = Fl_Type::first; f;) { + for (Node *f = Fluid.proj.tree.first; f;) { if (f->selected || !selected_only) { delete_children(f); - Fl_Type *g = f->next; + Node *g = f->next; delete f; f = g; } else { @@ -407,7 +401,7 @@ void delete_all(int selected_only) { if(!selected_only) { // reset the setting for the external shell command if (g_shell_config) { - g_shell_config->clear(FD_STORE_PROJECT); + g_shell_config->clear(fld::Tool_Store::PROJECT); g_shell_config->rebuild_shell_menu(); g_shell_config->update_settings_dialog(); } @@ -415,12 +409,12 @@ void delete_all(int selected_only) { widget_browser->hposition(0); widget_browser->vposition(0); } - g_layout_list.remove_all(FD_STORE_PROJECT); - g_layout_list.current_suite(0); - g_layout_list.current_preset(0); - g_layout_list.update_dialogs(); + Fluid.layout_list.remove_all(fld::Tool_Store::PROJECT); + Fluid.layout_list.current_suite(0); + Fluid.layout_list.current_preset(0); + Fluid.layout_list.update_dialogs(); } - selection_changed(0); + selection_changed(nullptr); if (widget_browser) { if (selected_only) widget_browser->restore_scroll_position(); @@ -431,41 +425,41 @@ void delete_all(int selected_only) { /** Update a string. Replace a string pointer with new value, strips leading/trailing blanks. As a side effect, this call also sets the mod flags. - \param[in] n new string, can be NULL + \param[in] n new string, can be nullptr \param[out] p update this pointer, possibly reallocate memory \param[in] nostrip if set, do not strip leading and trailing spaces and tabs \return 1 if the string in p changed */ int storestring(const char *n, const char * & p, int nostrip) { if (n == p) return 0; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); int length = 0; if (n) { // see if blank, strip leading & trailing blanks if (!nostrip) while (isspace((int)(unsigned char)*n)) n++; const char *e = n + strlen(n); if (!nostrip) while (e > n && isspace((int)(unsigned char)*(e-1))) e--; length = int(e-n); - if (!length) n = 0; + if (!length) n = nullptr; } if (n == p) return 0; if (n && p && !strncmp(n,p,length) && !p[length]) return 0; if (p) free((void *)p); if (!n || !*n) { - p = 0; + p = nullptr; } else { char *q = (char *)malloc(length+1); strlcpy(q,n,length+1); p = q; } - set_modflag(1); + Fluid.proj.set_modflag(1); return 1; } /** Update the `visible` flag for `p` and all its descendants. \param[in] p start here and update all descendants */ -void update_visibility_flag(Fl_Type *p) { - Fl_Type *t = p; +void update_visibility_flag(Node *p) { + Node *t = p; for (;;) { if (t->parent) t->visible = t->parent->visible && !t->parent->folded_; else t->visible = 1; @@ -474,49 +468,49 @@ void update_visibility_flag(Fl_Type *p) { } } -// ---- implementation of Fl_Type +// ---- implementation of Node -/** \var Fl_Type *Fl_Type::parent +/** \var Node *Node::parent Link to the parent node in the tree structure. Used for simulating a tree structure via a doubly linked list. */ -/** \var Fl_Type *Fl_Type::level +/** \var Node *Node::level Zero based depth of the node within the tree structure. Level is used to emulate a tree structure: the first node with a lower level in the prev list would be the parent of this node. If the next member has a higher level value, it is this nodes first child. At the same level, it would be the first sibling. */ -/** \var Fl_Type *Fl_Type::next +/** \var Node *Node::next Points to the next node in the doubly linked list. - If this is NULL, we are at the end of the list. + If this is nullptr, we are at the end of the list. Used for simulating a tree structure via a doubly linked list. */ -/** \var Fl_Type *Fl_Type::prev +/** \var Node *Node::prev Link to the next node in the tree structure. - If this is NULL, we are at the beginning of the list. + If this is nullptr, we are at the beginning of the list. Used for simulating a tree structure via a doubly linked list. */ /** Constructor and base for any node in the widget tree. */ -Fl_Type::Fl_Type() : - name_(NULL), - label_(NULL), - callback_(NULL), - user_data_(NULL), - user_data_type_(NULL), - comment_(NULL), +Node::Node() : + name_(nullptr), + label_(nullptr), + callback_(nullptr), + user_data_(nullptr), + user_data_type_(nullptr), + comment_(nullptr), uid_(0), - parent(NULL), + parent(nullptr), new_selected(0), selected(0), folded_(0), visible(0), level(0), - next(NULL), prev(NULL), - factory(NULL), + next(nullptr), prev(nullptr), + factory(nullptr), code_static_start(-1), code_static_end(-1), code1_start(-1), code1_end(-1), code2_start(-1), code2_end(-1), @@ -536,13 +530,13 @@ Fl_Type::Fl_Type() : because the node does not know if it is part of the widget tree, or if it is in a separate tree. We try to take care of that as well as possible. */ -Fl_Type::~Fl_Type() { +Node::~Node() { // warning: destructor only works for widgets that have been add()ed. if (prev) prev->next = next; // else first = next; // don't do that! The Type may not be part of the main list if (next) next->prev = prev; // else last = prev; - if (Fl_Type::last == this) Fl_Type::last = prev; - if (Fl_Type::first == this) Fl_Type::first = next; - if (current == this) current = NULL; + if (Fluid.proj.tree.last == this) Fluid.proj.tree.last = prev; + if (Fluid.proj.tree.first == this) Fluid.proj.tree.first = next; + if (Fluid.proj.tree.current == this) Fluid.proj.tree.current = nullptr; if (parent) parent->remove_child(this); if (name_) free((void*)name_); if (label_) free((void*)label_); @@ -552,34 +546,34 @@ Fl_Type::~Fl_Type() { if (comment_) free((void*)comment_); } -// Return the previous sibling in the tree structure or NULL. -Fl_Type *Fl_Type::prev_sibling() { - Fl_Type *n; +// Return the previous sibling in the tree structure or nullptr. +Node *Node::prev_sibling() { + Node *n; for (n = prev; n && n->level > level; n = n->prev) ; if (n && (n->level == level)) return n; - return 0; + return nullptr; } -// Return the next sibling in the tree structure or NULL. -Fl_Type *Fl_Type::next_sibling() { - Fl_Type *n; +// Return the next sibling in the tree structure or nullptr. +Node *Node::next_sibling() { + Node *n; for (n = next; n && n->level > level; n = n->next) ; if (n && (n->level == level)) return n; - return 0; + return nullptr; } -// Return the first child or NULL -Fl_Type *Fl_Type::first_child() { - Fl_Type *n = next; +// Return the first child or nullptr +Node *Node::first_child() { + Node *n = next; if (n->level > level) return n; - return NULL; + return nullptr; } // Generate a descriptive text for this item, to put in browser & window titles -const char* Fl_Type::title() { +const char* Node::title() { const char* c = name(); if (c) return c; @@ -588,42 +582,42 @@ const char* Fl_Type::title() { /** Return the window that contains this widget. - \return NULL if this is not a widget. + \return nullptr if this is not a widget. */ -Fl_Window_Type *Fl_Type::window() { +Window_Node *Node::window() { if (!is_widget()) - return NULL; - for (Fl_Type *t = this; t; t=t->parent) - if (t->is_a(ID_Window)) - return (Fl_Window_Type*)t; - return NULL; + return nullptr; + for (Node *t = this; t; t=t->parent) + if (t->is_a(Type::Window)) + return (Window_Node*)t; + return nullptr; } /** Return the group that contains this widget. - \return NULL if this is not a widget. + \return nullptr if this is not a widget. */ -Fl_Group_Type *Fl_Type::group() { +Group_Node *Node::group() { if (!is_widget()) - return NULL; - for (Fl_Type *t = this; t; t=t->parent) - if (t->is_a(ID_Group)) - return (Fl_Group_Type*)t; - return NULL; + return nullptr; + for (Node *t = this; t; t=t->parent) + if (t->is_a(Type::Group)) + return (Group_Node*)t; + return nullptr; } /** Add this list/tree of widgets as a new last child of p. \c this must not be part of the widget browser. \c p however must be in the - widget_browser, so \c Fl_Type::first and \c Fl_Type::last are valid for \c p. + widget_browser, so \c Fluid.proj.tree.first and \c Fluid.proj.tree.last are valid for \c p. This methods updates the widget_browser. \param[in] p insert \c this tree as a child of \c p \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT */ -void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { +void Node::add(Node *anchor, Strategy strategy) { #if 0 #ifndef NDEBUG // print_project_tree(); @@ -634,16 +628,16 @@ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { #endif #endif - Fl_Type *target = NULL; // insert self before target node, if NULL, insert last - Fl_Type *target_parent = NULL; // this will be the new parent for branch + Node *target = nullptr; // insert self before target node, if nullptr, insert last + Node *target_parent = nullptr; // this will be the new parent for branch int target_level = 0; // adjust self to this new level // Find the node after our insertion position switch (strategy.placement()) { case Strategy::AS_FIRST_CHILD: default: - if (anchor == NULL) { - target = Fl_Type::first; + if (anchor == nullptr) { + target = Fluid.proj.tree.first; } else { target = anchor->next; target_level = anchor->level + 1; @@ -651,7 +645,7 @@ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { } break; case Strategy::AS_LAST_CHILD: - if (anchor == NULL) { + if (anchor == nullptr) { /* empty */ } else { for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/} @@ -660,8 +654,8 @@ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { } break; case Strategy::AFTER_CURRENT: - if (anchor == NULL) { - target = Fl_Type::first; + if (anchor == nullptr) { + target = Fluid.proj.tree.first; } else { for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/} target_level = anchor->level; @@ -672,54 +666,54 @@ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { // Find the last node of our tree - Fl_Type *end = this; + Node *end = this; while (end->next) end = end->next; // Everything is prepared, now insert ourself in front of the target node - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); // Walk the tree to update parent pointers and levels int source_level = level; - for (Fl_Type *t = this; t; t = t->next) { + for (Node *t = this; t; t = t->next) { t->level += (target_level-source_level); if (t->level == target_level) t->parent = target_parent; } - // Now link ourselves and our children before 'target', or last, if 'target' is NULL + // Now link ourselves and our children before 'target', or last, if 'target' is nullptr if (target) { prev = target->prev; target->prev = end; end->next = target; } else { - prev = Fl_Type::last; - end->next = NULL; - Fl_Type::last = end; + prev = Fluid.proj.tree.last; + end->next = nullptr; + Fluid.proj.tree.last = end; } if (prev) { prev->next = this; } else { - Fl_Type::first = this; + Fluid.proj.tree.first = this; } #if 0 { // make sure that we have no duplicate uid's - Fl_Type *tp = this; + Node *tp = this; do { tp->set_uid(tp->uid_); tp = tp->next; - } while (tp!=end && tp!=NULL); + } while (tp!=end && tp!=nullptr); } #endif // Give the widgets in our tree a chance to update themselves - for (Fl_Type *t = this; t && t!=end->next; t = t->next) { + for (Node *t = this; t && t!=end->next; t = t->next) { if (target_parent && (t->level == target_level)) - target_parent->add_child(t, 0); + target_parent->add_child(t, nullptr); update_visibility_flag(t); } - set_modflag(1); + Fluid.proj.set_modflag(1); widget_browser->redraw(); #if 0 @@ -734,35 +728,35 @@ void Fl_Type::add(Fl_Type *anchor, Strategy strategy) { Add `this` list/tree of widgets as a new sibling before `g`. `This` is not part of the widget browser. `g` must be in the - widget_browser, so `Fl_Type::first` and `Fl_Type::last` are valid for `g . + widget_browser, so `Fluid.proj.tree.first` and `Fluid.proj.tree.last` are valid for `g . This methods updates the widget_browser. \param[in] g pointer to a node within the tree */ -void Fl_Type::insert(Fl_Type *g) { +void Node::insert(Node *g) { // 'this' is not in the Node_Browser, so we must run the linked list to find the last entry - Fl_Type *end = this; + Node *end = this; while (end->next) end = end->next; // 'this' will get the same parent as 'g' parent = g->parent; // run the list again to set the future node levels int newlevel = g->level; visible = g->visible; - for (Fl_Type *t = this->next; t; t = t->next) t->level += newlevel-level; + for (Node *t = this->next; t; t = t->next) t->level += newlevel-level; level = newlevel; // insert this in the list before g prev = g->prev; - if (prev) prev->next = this; else first = this; + if (prev) prev->next = this; else Fluid.proj.tree.first = this; end->next = g; g->prev = end; update_visibility_flag(this); { // make sure that we have no duplicate uid's - Fl_Type *tp = this; + Node *tp = this; do { tp->set_uid(tp->uid_); tp = tp->next; - } while (tp!=end && tp!=NULL); + } while (tp!=end && tp!=nullptr); } // tell parent that it has a new child, so it can update itself if (parent) parent->add_child(this, g); @@ -770,13 +764,13 @@ void Fl_Type::insert(Fl_Type *g) { } // Return message number for I18N... -int Fl_Type::msgnum() { +int Node::msgnum() { int count; - Fl_Type *p; + Node *p; for (count = 0, p = this; p;) { if (p->label()) count ++; - if (p != this && p->is_widget() && ((Fl_Widget_Type *)p)->tooltip()) count ++; + if (p != this && p->is_widget() && ((Widget_Node *)p)->tooltip()) count ++; if (p->prev) p = p->prev; else p = p->parent; @@ -789,14 +783,14 @@ int Fl_Type::msgnum() { Remove this node and all its children from the parent node. This does not delete anything. The resulting list//tree will no longer be in - the widget_browser, so \c Fl_Type::first and \c Fl_Type::last do not apply + the widget_browser, so \c Fluid.proj.tree.first and \c Fluid.proj.tree.last do not apply to it. - \return the node that follows this node after the operation; can be NULL + \return the node that follows this node after the operation; can be nullptr */ -Fl_Type *Fl_Type::remove() { +Node *Node::remove() { // find the last child of this node - Fl_Type *end = this; + Node *end = this; for (;;) { if (!end->next || end->next->level <= level) break; @@ -806,56 +800,56 @@ Fl_Type *Fl_Type::remove() { if (prev) prev->next = end->next; else - first = end->next; + Fluid.proj.tree.first = end->next; // unlink the last child from their next node if (end->next) end->next->prev = prev; else - last = prev; - Fl_Type *r = end->next; - prev = end->next = 0; + Fluid.proj.tree.last = prev; + Node *r = end->next; + prev = end->next = nullptr; // allow the parent to update changes in the UI if (parent) parent->remove_child(this); - parent = 0; + parent = nullptr; // tell the widget_browser that we removed some nodes widget_browser->redraw(); - selection_changed(0); + selection_changed(nullptr); return r; } -void Fl_Type::name(const char *n) { - int nostrip = is_a(ID_Comment); +void Node::name(const char *n) { + int nostrip = is_a(Type::Comment); if (storestring(n,name_,nostrip)) { if (visible) widget_browser->redraw(); } } -void Fl_Type::label(const char *n) { +void Node::label(const char *n) { if (storestring(n,label_,1)) { setlabel(label_); if (visible && !name_) widget_browser->redraw(); } } -void Fl_Type::callback(const char *n) { +void Node::callback(const char *n) { storestring(n,callback_); } -void Fl_Type::user_data(const char *n) { +void Node::user_data(const char *n) { storestring(n,user_data_); } -void Fl_Type::user_data_type(const char *n) { +void Node::user_data_type(const char *n) { storestring(n,user_data_type_); } -void Fl_Type::comment(const char *n) { +void Node::comment(const char *n) { if (storestring(n,comment_,1)) { if (visible) widget_browser->redraw(); } } -void Fl_Type::open() { +void Node::open() { printf("Open of '%s' is not yet implemented\n",type_name()); } @@ -867,20 +861,20 @@ void Fl_Type::open() { The caller must make sure that the widget browser is rebuilt correctly. \param[in] g move \c this tree before \c g */ -void Fl_Type::move_before(Fl_Type* g) { +void Node::move_before(Node* g) { if (level != g->level) printf("move_before levels don't match! %d %d\n", level, g->level); // Find the last child in the list - Fl_Type *n; + Node *n; for (n = next; n && n->level > level; n = n->next) ; if (n == g) return; // now link this tree before g - Fl_Type *l = n ? n->prev : Fl_Type::last; + Node *l = n ? n->prev : Fluid.proj.tree.last; prev->next = n; - if (n) n->prev = prev; else Fl_Type::last = prev; + if (n) n->prev = prev; else Fluid.proj.tree.last = prev; prev = g->prev; l->next = g; - if (prev) prev->next = this; else Fl_Type::first = this; + if (prev) prev->next = this; else Fluid.proj.tree.first = this; g->prev = l; // tell parent that it has a new child, so it can update itself if (parent && is_widget()) parent->move_child(this,g); @@ -888,14 +882,14 @@ void Fl_Type::move_before(Fl_Type* g) { // write a widget and all its children: -void Fl_Type::write(fld::io::Project_Writer &f) { +void Node::write(fld::io::Project_Writer &f) { if (f.write_codeview()) proj1_start = (int)ftell(f.file()) + 1; if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1; f.write_indent(level); f.write_word(type_name()); if (is_class()) { - const char * p = ((Fl_Class_Type*)this)->prefix(); + const char * p = ((Class_Node*)this)->prefix(); if (p && strlen(p)) f.write_word(p); } @@ -912,7 +906,7 @@ void Fl_Type::write(fld::io::Project_Writer &f) { } // now do children: f.write_open(); - Fl_Type *child; + Node *child; for (child = next; child && child->level > level; child = child->next) if (child->level == level+1) child->write(f); if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1; @@ -920,9 +914,9 @@ void Fl_Type::write(fld::io::Project_Writer &f) { if (f.write_codeview()) proj2_end = (int)ftell(f.file()); } -void Fl_Type::write_properties(fld::io::Project_Writer &f) { +void Node::write_properties(fld::io::Project_Writer &f) { // repeat this for each attribute: - if (g_project.write_mergeback_data && uid_) { + if (Fluid.proj.write_mergeback_data && uid_) { f.write_word("uid"); f.write_string("%04x", uid_); } @@ -954,7 +948,7 @@ void Fl_Type::write_properties(fld::io::Project_Writer &f) { if (selected) f.write_word("selected"); } -void Fl_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"uid")) { const char *hex = f.read_word(); int x = 0; @@ -1019,13 +1013,13 @@ void Fl_Type::read_property(fld::io::Project_Reader &f, const char *c) { Lastly, this method should call the super class to give it a chance to append its own properties. - \see Fl_Grid_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) + \see Grid_Node::write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate) \param[in] f the project file writer \param[in] child write properties for this child, make sure it has the correct type \param[in] encapsulate write the `parent_properties {}` block if true before writing any properties */ -void Fl_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) { +void Node::write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate) { (void)f; (void)child; (void)encapsulate; // nothing to do here // put the following code into your implementation of write_parent_properties @@ -1052,26 +1046,26 @@ void Fl_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child method reads back those properties. This function is virtual, so if a Type does not support a property, it will propagate to its super class. - \see Fl_Type::write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate) - \see Fl_Grid_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) + \see Node::write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate) + \see Grid_Node::read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property) \param[in] f the project file writer \param[in] child read properties for this child \param[in] property the name of a property, or "}" when we reach the end of the list */ -void Fl_Type::read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property) { +void Node::read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property) { (void)child; f.read_error("Unknown parent property \"%s\"", property); } -int Fl_Type::read_fdesign(const char*, const char*) {return 0;} +int Node::read_fdesign(const char*, const char*) {return 0;} /** Write a comment into the header file. \param[in] pre indent the comment by this string */ -void Fl_Type::write_comment_h(fld::io::Code_Writer& f, const char *pre) +void Node::write_comment_h(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_h("%s/**\n", pre); @@ -1094,7 +1088,7 @@ void Fl_Type::write_comment_h(fld::io::Code_Writer& f, const char *pre) /** Write a comment into the source file. */ -void Fl_Type::write_comment_c(fld::io::Code_Writer& f, const char *pre) +void Node::write_comment_c(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { f.write_c("%s/**\n", pre); @@ -1119,11 +1113,11 @@ void Fl_Type::write_comment_c(fld::io::Code_Writer& f, const char *pre) /** Write a comment into the source file. */ -void Fl_Type::write_comment_inline_c(fld::io::Code_Writer& f, const char *pre) +void Node::write_comment_inline_c(fld::io::Code_Writer& f, const char *pre) { if (comment() && *comment()) { const char *s = comment(); - if (strchr(s, '\n')==0L) { + if (strchr(s, '\n')==nullptr) { // single line comment if (pre) f.write_c("%s", pre); f.write_c("// %s\n", s); @@ -1165,21 +1159,21 @@ void Fl_Type::write_comment_inline_c(fld::io::Code_Writer& f, const char *pre) \return a widget pointer that the live mode initiator can 'show()' \see leave_live_mode() */ -Fl_Widget *Fl_Type::enter_live_mode(int) { - return 0L; +Fl_Widget *Node::enter_live_mode(int) { + return nullptr; } /** Release all resources created when entering live mode. \see enter_live_mode() */ -void Fl_Type::leave_live_mode() { +void Node::leave_live_mode() { } /** Copy all needed properties for this type into the live object. */ -void Fl_Type::copy_properties() { +void Node::copy_properties() { } /** @@ -1190,16 +1184,16 @@ void Fl_Type::copy_properties() { plain function or a member function within the same class and that the parameter types match. */ -int Fl_Type::user_defined(const char* cbname) const { - for (Fl_Type* p = Fl_Type::first; p ; p = p->next) - if (p->is_a(ID_Function) && p->name() != 0) +int Node::user_defined(const char* cbname) const { + for (Node* p = Fluid.proj.tree.first; p ; p = p->next) + if (p->is_a(Type::Function) && p->name() != nullptr) if (strncmp(p->name(), cbname, strlen(cbname)) == 0) if (p->name()[strlen(cbname)] == '(') return 1; return 0; } -const char *Fl_Type::callback_name(fld::io::Code_Writer& f) { +const char *Node::callback_name(fld::io::Code_Writer& f) { if (is_name(callback())) return callback(); return f.unique_id(this, "cb", name(), label()); } @@ -1215,15 +1209,15 @@ const char *Fl_Type::callback_name(fld::io::Code_Writer& f) { \param need_nest if clear, search up one level to the first enclosing class. If set, recurse all the way up to the top node. \return the name of the enclosing class, or names of the enclosing classes - in a static buffe (don't call free), or NULL if this Type is not inside a class + in a static buffe (don't call free), or nullptr if this Type is not inside a class */ -const char* Fl_Type::class_name(const int need_nest) const { - Fl_Type* p = parent; +const char* Node::class_name(const int need_nest) const { + Node* p = parent; while (p) { if (p->is_class()) { // see if we are nested in another class, we must fully-qualify name: // this is lame but works... - const char* q = 0; + const char* q = nullptr; if(need_nest) q=p->class_name(need_nest); if (q) { static char s[256]; @@ -1236,15 +1230,15 @@ const char* Fl_Type::class_name(const int need_nest) const { } p = p->parent; } - return 0; + return nullptr; } /** - Check if this is inside a Fl_Class_Type or Fl_Widget_Class_Type. - \return true if any of the parents is Fl_Class_Type or Fl_Widget_Class_Type + Check if this is inside a Class_Node or Widget_Class_Node. + \return true if any of the parents is Class_Node or Widget_Class_Node */ -bool Fl_Type::is_in_class() const { - Fl_Type* p = parent; +bool Node::is_in_class() const { + Node* p = parent; while (p) { if (p->is_class()) return true; p = p->parent; @@ -1252,18 +1246,18 @@ bool Fl_Type::is_in_class() const { return false; } -void Fl_Type::write_static(fld::io::Code_Writer&) { +void Node::write_static(fld::io::Code_Writer&) { } -void Fl_Type::write_static_after(fld::io::Code_Writer&) { +void Node::write_static_after(fld::io::Code_Writer&) { } -void Fl_Type::write_code1(fld::io::Code_Writer& f) { +void Node::write_code1(fld::io::Code_Writer& f) { f.write_h("// Header for %s\n", title()); f.write_c("// Code for %s\n", title()); } -void Fl_Type::write_code2(fld::io::Code_Writer&) { +void Node::write_code2(fld::io::Code_Writer&) { } /** Set a uid that is unique within the project. @@ -1275,15 +1269,15 @@ void Fl_Type::write_code2(fld::io::Code_Writer&) { \param[in] suggested_uid the preferred uid for this node \return the actualt uid that was given to the node */ -unsigned short Fl_Type::set_uid(unsigned short suggested_uid) { +unsigned short Node::set_uid(unsigned short suggested_uid) { if (suggested_uid==0) suggested_uid = (unsigned short)rand(); for (;;) { - Fl_Type *tp = Fl_Type::first; + Node *tp = Fluid.proj.tree.first; for ( ; tp; tp = tp->next) if (tp!=this && tp->uid_==suggested_uid) break; - if (tp==NULL) + if (tp==nullptr) break; suggested_uid = (unsigned short)rand(); } @@ -1291,48 +1285,6 @@ unsigned short Fl_Type::set_uid(unsigned short suggested_uid) { return suggested_uid; } -/** Find a node by its unique id. - - Every node in a type tree has an id that is unique for the current project. - Walk the tree and return the node with this uid. - - \param[in] uid any number between 0 and 65535 - \return the node with this uid, or NULL if not found - */ -Fl_Type *Fl_Type::find_by_uid(unsigned short uid) { - for (Fl_Type *tp = Fl_Type::first; tp; tp = tp->next) { - if (tp->uid_ == uid) return tp; - } - return NULL; -} - -/** Find a type node by using the codeview text positions. - - \param[in] text_type 0=source file, 1=header, 2=.fl project file - \param[in] crsr cursor position in text - \return the node we found or NULL - */ -Fl_Type *Fl_Type::find_in_text(int text_type, int crsr) { - for (Fl_Type *node = first; node; node = node->next) { - switch (text_type) { - case 0: - if (crsr >= node->code1_start && crsr < node->code1_end) return node; - if (crsr >= node->code2_start && crsr < node->code2_end) return node; - if (crsr >= node->code_static_start && crsr < node->code_static_end) return node; - break; - case 1: - if (crsr >= node->header1_start && crsr < node->header1_end) return node; - if (crsr >= node->header2_start && crsr < node->header2_end) return node; - if (crsr >= node->header_static_start && crsr < node->header_static_end) return node; - break; - case 2: - if (crsr >= node->proj1_start && crsr < node->proj1_end) return node; - if (crsr >= node->proj2_start && crsr < node->proj2_end) return node; - break; - } - } - return 0; -} /// \} diff --git a/fluid/nodes/Fl_Type.h b/fluid/nodes/Node.h similarity index 70% rename from fluid/nodes/Fl_Type.h rename to fluid/nodes/Node.h index e7dde3b39..5c473a936 100644 --- a/fluid/nodes/Fl_Type.h +++ b/fluid/nodes/Node.h @@ -1,5 +1,5 @@ // -// Widget type header file for the Fast Light Tool Kit (FLTK). +// Node base class header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -14,17 +14,17 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FL_TYPE_H -#define _FLUID_FL_TYPE_H +#ifndef FLUID_NODES_NODE_H +#define FLUID_NODES_NODE_H #include "io/Code_Writer.h" #include #include -class Fl_Type; -class Fl_Group_Type; -class Fl_Window_Type; +class Node; +class Group_Node; +class Window_Node; namespace fld { namespace io { @@ -45,15 +45,15 @@ class Project_Writer; labels. Type created FROM_FILE will start with no label, so the label is set correctly later. - \see Fl_Type *Fl_..._Type::make(Strategy strategy) calls `add()` + \see Node *Fl_..._Type::make(Strategy strategy) calls `add()` Add single Type: - Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open) - Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) - Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy) + Node *add_new_widget_from_user(Node *inPrototype, Strategy strategy, bool and_open) + Node *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) + Node *add_new_widget_from_file(const char *inName, Strategy strategy) Add a hierarchy of Types - void Fl_Type::add(Fl_Type *p, Strategy strategy) + void Node::add(Node *p, Strategy strategy) int read_file(const char *filename, int merge, Strategy strategy) - Fl_Type *fld::io::Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) + Node *fld::io::Project_Reader::read_children(Node *p, int merge, Strategy strategy, char skip_options) int fld::io::Project_Reader::read_project(const char *filename, int merge, Strategy strategy) */ typedef struct Strategy { @@ -77,40 +77,40 @@ typedef struct Strategy { Flags source() { return (Flags)(flags & SOURCE_MASK); } } Strategy; -enum ID { +enum class Type { // administrative - ID_Base_, ID_Widget_, ID_Menu_Manager_, ID_Menu_, ID_Browser_, ID_Valuator_, + Base_, Widget_, Menu_Manager_, Menu_, Browser_, Valuator_, // non-widget - ID_Function, ID_Code, ID_CodeBlock, - ID_Decl, ID_DeclBlock, ID_Class, - ID_Widget_Class, ID_Comment, ID_Data, + Function, Code, CodeBlock, + Decl, DeclBlock, Class, + Widget_Class, Comment, Data, // groups - ID_Window, ID_Group, ID_Pack, - ID_Flex, ID_Tabs, ID_Scroll, - ID_Tile, ID_Wizard, ID_Grid, + Window, Group, Pack, + Flex, Tabs, Scroll, + Tile, Wizard, Grid, // buttons - ID_Button, ID_Return_Button, ID_Light_Button, - ID_Check_Button, ID_Repeat_Button, ID_Round_Button, + Button, Return_Button, Light_Button, + Check_Button, Repeat_Button, Round_Button, // valuators - ID_Slider, ID_Scrollbar, ID_Value_Slider, - ID_Adjuster, ID_Counter, ID_Spinner, - ID_Dial, ID_Roller, ID_Value_Input, ID_Value_Output, + Slider, Scrollbar, Value_Slider, + Adjuster, Counter, Spinner, + Dial, Roller, Value_Input, Value_Output, // text - ID_Input, ID_Output, ID_Text_Editor, - ID_Text_Display, ID_File_Input, ID_Terminal, + Input, Output, Text_Editor, + Text_Display, File_Input, Terminal, // menus - ID_Menu_Bar, ID_Menu_Button, ID_Choice, - ID_Input_Choice, ID_Submenu, ID_Menu_Item, - ID_Checkbox_Menu_Item, ID_Radio_Menu_Item, + Menu_Bar, Menu_Button, Choice, + Input_Choice, Submenu, Menu_Item, + Checkbox_Menu_Item, Radio_Menu_Item, // browsers - ID_Browser, ID_Check_Browser, ID_File_Browser, - ID_Tree, ID_Help_View, ID_Table, + Browser, Check_Browser, File_Browser, + Tree, Help_View, Table, // misc - ID_Box, ID_Clock, ID_Progress, - ID_Max_ + Box, Clock, Progress, + Max_ }; -void update_visibility_flag(Fl_Type *p); +void update_visibility_flag(Node *p); void delete_all(int selected_only=0); int storestring(const char *n, const char * & p, int nostrip=0); @@ -122,8 +122,8 @@ void later_cb(Fl_Widget*,void*); #ifndef NDEBUG void print_project_tree(); bool validate_project_tree(); -bool validate_independent_branch(class Fl_Type *root); -bool validate_branch(class Fl_Type *root); +bool validate_independent_branch(class Node *root); +bool validate_branch(class Node *root); #endif /** @@ -134,8 +134,8 @@ bool validate_branch(class Fl_Type *root); to create a pseudo tree structure. To make walking up the tree faster, Type also holds a pointer to the `parent` Type. - Types can be identified using the builtin ID system that works like RTTI. The - method `id()` returns the exact type, and the method `is_a(ID)` returns true + Types can be identified using the builtin Type system that works like RTTI. The + method `type()` returns the exact type, and the method `is_a(Type)` returns true if this is the exact type or derived from the type, and a dynamic cast will work reliably. @@ -149,20 +149,20 @@ bool validate_branch(class Fl_Type *root); \todo it may make sense to have a readable iterator class instead of relying on pointer manipulation. Or use std in future releases. */ -class Fl_Type { +class Node { /** Copy the label text to Widgets and Windows, does nothing in Type. */ virtual void setlabel(const char *) { } // virtual part of label(char*) protected: - Fl_Type(); + Node(); /** Name of a widget, or code some non-widget Types. */ const char *name_; /** Label text of a widget. */ const char *label_; /** If it is just a word, it's the name of the callback function. Otherwise - it is the full callback C++ code. Can be NULL. */ + it is the full callback C++ code. Can be nullptr. */ const char *callback_; /** Widget user data field as C++ text. */ const char *user_data_; @@ -175,9 +175,9 @@ protected: unsigned short uid_; public: // things that should not be public: - + // TODO: reference back to the tree /** Quick link to the parent Type instead of walking up the linked list. */ - Fl_Type *parent; + Node *parent; /** This type is rendered "selected" in the tree browser. */ char new_selected; // browser highlight /** Backup storage for selection if an error occurred during some operation @@ -187,13 +187,12 @@ public: // things that should not be public: char folded_; // if set, children are not shown in browser char visible; // true if all parents are open int level; // number of parents over this - static Fl_Type *first, *last; - Fl_Type *next, *prev; - Fl_Type *prev_sibling(); - Fl_Type *next_sibling(); - Fl_Type *first_child(); + Node *next, *prev; + Node *prev_sibling(); + Node *next_sibling(); + Node *first_child(); - Fl_Type *factory; + Node *factory; const char *callback_name(fld::io::Code_Writer& f); // text positions of this type in code, header, and project file (see codeview) @@ -211,16 +210,16 @@ protected: public: - virtual ~Fl_Type(); - virtual Fl_Type *make(Strategy strategy) = 0; + virtual ~Node(); + virtual Node *make(Strategy strategy) = 0; - Fl_Window_Type *window(); - Fl_Group_Type *group(); + Window_Node *window(); + Group_Node *group(); - void add(Fl_Type *parent, Strategy strategy); - void insert(Fl_Type *n); // insert into list before n - Fl_Type* remove(); // remove from list - void move_before(Fl_Type*); // move before a sibling + void add(Node *parent, Strategy strategy); + void insert(Node *n); // insert into list before n + Node* remove(); // remove from list + void move_before(Node*); // move before a sibling virtual const char *title(); // string for browser virtual const char *type_name() = 0; // type for code output @@ -239,11 +238,11 @@ public: const char *comment() { return comment_; } void comment(const char *); - virtual Fl_Type* click_test(int,int) { return NULL; } + virtual Node* click_test(int,int) { return nullptr; } - virtual void add_child(Fl_Type*, Fl_Type* beforethis) { } - virtual void move_child(Fl_Type*, Fl_Type* beforethis) { } - virtual void remove_child(Fl_Type*) { } + virtual void add_child(Node*, Node* beforethis) { } + virtual void move_child(Node*, Node* beforethis) { } + virtual void remove_child(Node*) { } /** Give widgets a chance to arrange their children after all children were added. If adding individual children, this is called immediately, but if children @@ -252,17 +251,14 @@ public: */ virtual void layout_widget() { } - static Fl_Type *current; // most recently picked object - static Fl_Type *current_dnd; - virtual void open(); // what happens when you double-click // read and write data to a saved file: virtual void write(fld::io::Project_Writer &f); virtual void write_properties(fld::io::Project_Writer &f); virtual void read_property(fld::io::Project_Reader &f, const char *); - virtual void write_parent_properties(fld::io::Project_Writer &f, Fl_Type *child, bool encapsulate); - virtual void read_parent_property(fld::io::Project_Reader &f, Fl_Type *child, const char *property); + virtual void write_parent_properties(fld::io::Project_Writer &f, Node *child, bool encapsulate); + virtual void read_parent_property(fld::io::Project_Reader &f, Node *child, const char *property); virtual int read_fdesign(const char*, const char*); virtual void postprocess_read() { } @@ -273,7 +269,7 @@ public: virtual void write_code2(fld::io::Code_Writer& f); // code and .h after children void write_comment_h(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the header file void write_comment_c(fld::io::Code_Writer& f, const char *ind=""); // write the commentary text into the source file - void write_comment_inline_c(fld::io::Code_Writer& f, const char *ind=0L); // write the commentary text + void write_comment_inline_c(fld::io::Code_Writer& f, const char *ind=nullptr); // write the commentary text // live mode virtual Fl_Widget *enter_live_mode(int top=0); // build widgets needed for live mode @@ -290,20 +286,20 @@ public: virtual int is_widget() const {return 0;} /** Return 1 if the type is a widget but not a menu item. */ virtual int is_true_widget() const {return 0;} - /** Return 1 if a type behaves like a button (Fl_Button and Fl_Menu_Item and derived, but not Fl_Submenu_Type. */ + /** Return 1 if a type behaves like a button (Fl_Button and Fl_Menu_Item and derived, but not Submenu_Node. */ virtual int is_button() const {return 0;} - /** Return 1 if this is a Fl_Widget_Class_Type, Fl_CodeBlock_Type, or Fl_Function_Type */ + /** Return 1 if this is a Widget_Class_Node, CodeBlock_Node, or Function_Node */ virtual int is_code_block() const {return 0;} - /** Return 1 if this is a Fl_Widget_Class_Type, Fl_Class_Type, or Fl_DeclBlock_Type */ + /** Return 1 if this is a Widget_Class_Node, Class_Node, or DeclBlock_Node */ virtual int is_decl_block() const {return 0;} - /** Return 1 if this is a Fl_Class_Type or Fl_Widget_Class_Type. */ + /** Return 1 if this is a Class_Node or Widget_Class_Node. */ virtual int is_class() const {return 0;} /** Return 1 if the type browser shall draw a padlock over the icon. */ virtual int is_public() const {return 1;} - /** Return the type ID for this Type. */ - virtual ID id() const { return ID_Base_; } - /** Check if this Type is of the give type ID or derived from that type ID. */ - virtual bool is_a(ID inID) const { return (inID==ID_Base_); } + /** Return the type Type for this Type. */ + virtual Type type() const { return Type::Base_; } + /** Check if this Type is of the give type Type or derived from that type Type. */ + virtual bool is_a(Type inType) const { return (inType==Type::Base_); } const char* class_name(const int need_nest) const; bool is_in_class() const; @@ -312,12 +308,6 @@ public: unsigned short set_uid(unsigned short suggested_uid=0); unsigned short get_uid() { return uid_; } - static Fl_Type *find_by_uid(unsigned short uid); - - static Fl_Type *find_in_text(int text_type, int crsr); - - /// If this is greater zero, widgets will be allowed to lay out their children. - static int allow_layout; }; -#endif // _FLUID_FL_TYPE_H +#endif // FLUID_NODES_NODE_H diff --git a/fluid/nodes/Tree.cxx b/fluid/nodes/Tree.cxx new file mode 100644 index 000000000..ca9b3d761 --- /dev/null +++ b/fluid/nodes/Tree.cxx @@ -0,0 +1,128 @@ +// +// Node Tree code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "nodes/Tree.h" + +#include "Project.h" + +using namespace fld; +using namespace fld::node; + + +Tree::Iterator::Iterator(Node *t, bool only_selected) +: type_(t) +, only_selected_(only_selected) +{ + if (t) { + if (only_selected_) { + if (!type_->selected) { + operator++(); + } + } + } +} + +Tree::Iterator &Tree::Iterator::operator++() { + if (only_selected_) { + do { + type_ = type_->next; + } while (type_ && !type_->selected); + } else { + type_ = type_->next; + } + return *this; +} + +Tree::WIterator::WIterator(Node *t, bool only_selected) +: type_(t) +, only_selected_(only_selected) +{ + if (t) { + if (only_selected_) { + if (!type_->selected || !type_->is_widget()) { + operator++(); + } + } else { + if (!type_->is_widget()) { + operator++(); + } + } + } +} + +Tree::WIterator& Tree::WIterator::operator++() { + if (only_selected_) { + do { + type_ = type_->next; + } while (type_ && (!type_->selected || !type_->is_widget())); + } else { + do { + type_ = type_->next; + } while (type_ && !type_->is_widget()); + } + return *this; +} + + +Tree::Tree(Project &proj) +: proj_(proj) +{ (void)proj_; } + + +/** Find a node by its unique id. + + Every node in a type tree has an id that is unique for the current project. + Walk the tree and return the node with this uid. + + \param[in] uid any number between 0 and 65535 + \return the node with this uid, or nullptr if not found + */ +Node *Tree::find_by_uid(unsigned short uid) { + for (auto tp: all_nodes()) { + if (tp->get_uid() == uid) return tp; + } + return nullptr; +} + + +/** Find a type node by using the codeview text positions. + + \param[in] text_type 0=source file, 1=header, 2=.fl project file + \param[in] crsr cursor position in text + \return the node we found or nullptr + */ +Node *Tree::find_in_text(int text_type, int crsr) { + for (auto node: all_nodes()) { + switch (text_type) { + case 0: + if (crsr >= node->code1_start && crsr < node->code1_end) return node; + if (crsr >= node->code2_start && crsr < node->code2_end) return node; + if (crsr >= node->code_static_start && crsr < node->code_static_end) return node; + break; + case 1: + if (crsr >= node->header1_start && crsr < node->header1_end) return node; + if (crsr >= node->header2_start && crsr < node->header2_end) return node; + if (crsr >= node->header_static_start && crsr < node->header_static_end) return node; + break; + case 2: + if (crsr >= node->proj1_start && crsr < node->proj1_end) return node; + if (crsr >= node->proj2_start && crsr < node->proj2_end) return node; + break; + } + } + return nullptr; +} diff --git a/fluid/nodes/Tree.h b/fluid/nodes/Tree.h new file mode 100644 index 000000000..f494af651 --- /dev/null +++ b/fluid/nodes/Tree.h @@ -0,0 +1,106 @@ +// +// Node Tree header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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_NODES_TREE_H +#define FLUID_NODES_TREE_H + +#include "nodes/Widget_Node.h" + +class Node; + +namespace fld { + +class Project; + +namespace node { + +class Tree { + + // A class that can iterate over the entire scene graph. + class Iterator { + Node *type_ = nullptr; + bool only_selected_ = false; + public: + explicit Iterator(Node *t, bool only_selected); + Node* operator*() { return type_; } + Iterator& operator++(); + bool operator!=(const Iterator& other) const { return type_ != other.type_; } + }; + + // A container for a node iterator + class Container { + Tree &tree_; + bool only_selected_ = false; + public: + Container(Tree &tree, bool only_selected) : tree_(tree), only_selected_(only_selected) { } + Iterator begin() { return Iterator(tree_.first, only_selected_); } + Iterator end() { return Iterator(nullptr, only_selected_); } + }; + + // A class that iterate over the scene graph, but returns only nodes of type widget. + class WIterator { + Node *type_ = nullptr; + bool only_selected_ = false; + public: + explicit WIterator(Node *t, bool only_selected); + Widget_Node* operator*() { return static_cast(type_); } + WIterator& operator++(); + bool operator!=(const WIterator& other) const { return type_ != other.type_; } + }; + + // A container for a widget node iterator + class WContainer { + Tree &tree_; + bool only_selected_ = false; + public: + WContainer(Tree &tree, bool only_selected) : tree_(tree), only_selected_(only_selected) { } + WIterator begin() { return WIterator(tree_.first, only_selected_); } + WIterator end() { return WIterator(nullptr, only_selected_); } + }; + + /// Link Tree class to the project. + Project &proj_; + +public: + + Node *first = nullptr; + Node *last = nullptr; + Node *current = nullptr; // most recently picked object + Node *current_dnd = nullptr; + /// If this is greater zero, widgets will be allowed to lay out their children. + int allow_layout = 0; + +public: + + Tree(Project &proj); + + bool empty() { return first == nullptr; } + + // Iterators: `for (auto &n: tree.all_nodes()) { n.print(); } + Container all_nodes() { return Container(*this, false); } + WContainer all_widgets() { return WContainer(*this, false); } + Container all_selected_nodes() { return Container(*this, true); } + WContainer all_selected_widgets() { return WContainer(*this, true); } + + Node *find_by_uid(unsigned short uid); + Node *find_in_text(int text_type, int crsr); +}; + +} // namespace node +} // namespace fld + + +#endif // FLUID_NODES_TREE_H diff --git a/fluid/nodes/Widget_Node.cxx b/fluid/nodes/Widget_Node.cxx new file mode 100644 index 000000000..cba8607f2 --- /dev/null +++ b/fluid/nodes/Widget_Node.cxx @@ -0,0 +1,2438 @@ +// +// Widget Node code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 "nodes/Widget_Node.h" + +#include "Fluid.h" +#include "Project.h" +#include "app/Image_Asset.h" +#include "proj/mergeback.h" +#include "proj/undo.h" +#include "io/Project_Reader.h" +#include "io/Project_Writer.h" +#include "io/Code_Writer.h" +#include "nodes/Menu_Node.h" +#include "nodes/Function_Node.h" +#include "nodes/Window_Node.h" +#include "panels/widget_panel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../src/flstring.h" + +#include +#include +#undef min +#undef max +#include + +// Make an Widget_Node subclass instance. +// It figures out the automatic size and parent of the new widget, +// creates the Fl_Widget (by calling the virtual function _make), +// adds it to the Fl_Widget hierarchy, creates a new Node +// instance, sets the widget pointers, and makes all the display +// update correctly... + +int Widget_Node::is_widget() const {return 1;} +int Widget_Node::is_public() const {return public_;} + +const char* subclassname(Node* l) { + if (l->is_a(Type::Menu_Bar)) { + Menu_Bar_Node *mb = static_cast(l); + if (mb->is_sys_menu_bar()) + return mb->sys_menubar_name(); + } + if (l->is_widget()) { + Widget_Node* p = (Widget_Node*)l; + const char* c = p->subclass(); + if (c) return c; + if (l->is_class()) return "Fl_Group"; + if (p->o->type() == FL_DOUBLE_WINDOW) return "Fl_Double_Window"; + if (p->type() == Type::Input) { + if (p->o->type() == FL_FLOAT_INPUT) return "Fl_Float_Input"; + if (p->o->type() == FL_INT_INPUT) return "Fl_Int_Input"; + } + } + return l->type_name(); +} + +// Return the ideal widget size... +void +Widget_Node::ideal_size(int &w, int &h) { + w = 120; + h = 100; + fld::app::Snap_Action::better_size(w, h); +} + +/** + Make a new Widget node. + \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT + \return new node + */ +Node *Widget_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *pp = anchor; + if (pp && (strategy.placement() == Strategy::AFTER_CURRENT)) + pp = pp->parent; + while (pp && !pp->is_a(Type::Group)) { + anchor = pp; + strategy.placement(Strategy::AFTER_CURRENT); + pp = pp->parent; + } + if (!pp || !pp->is_true_widget() || !anchor->is_true_widget()) { + fl_message("Please select a group widget or window"); + return nullptr; + } + + Widget_Node* p = (Widget_Node*)pp; + Widget_Node* q = (Widget_Node*)anchor; + + // Figure out a border between widget and window: + int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25; + + int ULX,ULY; // parent's origin in window + if (!p->is_a(Type::Window)) { // if it is a group, add corner + ULX = p->o->x(); ULY = p->o->y(); + } else { + ULX = ULY = 0; + } + + // Figure out a position and size for the widget + int X,Y,W,H; + if (is_a(Type::Group)) { // fill the parent with the widget + X = ULX+B; + W = p->o->w()-B; + Y = ULY+B; + H = p->o->h()-B; + } else if (q != p) { // copy position and size of current widget + W = q->o->w(); + H = q->o->h(); + X = q->o->x()+W; + Y = q->o->y(); + if (X+W > ULX+p->o->w()) { + X = q->o->x(); + Y = q->o->y()+H; + if (Y+H > ULY+p->o->h()) Y = ULY+B; + } + } else { // just make it small and square... + X = ULX+B; + Y = ULY+B; + W = H = B; + } + + // Construct the Node: + Widget_Node *t = _make(); + if (!o) o = widget(0,0,100,100); // create template widget + t->factory = this; + // Construct the Fl_Widget: + t->o = widget(X,Y,W,H); + if (strategy.source() == Strategy::FROM_FILE) + t->o->label(nullptr); + else if (t->o->label()) t->label(t->o->label()); // allow editing + t->o->user_data((void*)t); + // Put it in the parent: + // ((Fl_Group *)(p->o))->add(t->o); (done by Node::add()) + // add to browser: + t->add(anchor, strategy); + t->redraw(); + return t; +} + +void Widget_Node::setimage(Image_Asset *i) { + if (i == image || is_a(Type::Window)) return; + if (image) image->dec_ref(); + if (i) i->inc_ref(); + image = i; + if (i) { + o->image(i->image()); + if (o->image() && (scale_image_w_ || scale_image_h_)) { + int iw = scale_image_w_>0 ? scale_image_w_ : o->image()->data_w(); + int ih = scale_image_h_>0 ? scale_image_h_ : o->image()->data_h(); + o->image()->scale(iw, ih, 0, 1); + } + } else { + o->image(nullptr); + //scale_image_w_ = scale_image_h_ = 0; + } + redraw(); +} + +void Widget_Node::setinactive(Image_Asset *i) { + if (i == inactive || is_a(Type::Window)) return; + if (inactive) inactive->dec_ref(); + if (i) i->inc_ref(); + inactive = i; + if (i) { + o->deimage(i->image()); + if (o->deimage()) { + int iw = scale_deimage_w_>0 ? scale_deimage_w_ : o->deimage()->data_w(); + int ih = scale_deimage_h_>0 ? scale_deimage_h_ : o->deimage()->data_h(); + o->deimage()->scale(iw, ih, 0, 1); + } + } else { + o->deimage(nullptr); + //scale_deimage_w_ = scale_deimage_h_ = 0; + } + redraw(); +} + +void Widget_Node::setlabel(const char *n) { + o->label(n); + redraw(); +} + +Widget_Node::Widget_Node() +: override_visible_(0) +{ + for (int n=0; nwindow(); + delete o; + if (win) + win->redraw(); + } + if (subclass_) free((void*)subclass_); + if (tooltip_) free((void*)tooltip_); + if (image_name_) { + free((void*)image_name_); + if (image) image->dec_ref(); + } + if (inactive_name_) { + free((void*)inactive_name_); + if (inactive) inactive->dec_ref(); + } + for (int n=0; ntooltip(n); +} + +void Widget_Node::image_name(const char *n) { + setimage(Image_Asset::find(n)); + storestring(n,image_name_); +} + +void Widget_Node::inactive_name(const char *n) { + setinactive(Image_Asset::find(n)); + storestring(n,inactive_name_); +} + +void Widget_Node::redraw() { + Node *t = this; + if (is_a(Type::Menu_Item)) { + // find the menu button that parents this menu: + do t = t->parent; while (t && t->is_a(Type::Menu_Item)); + // kludge to cause build_menu to be called again: + if (t) + t->add_child(nullptr, nullptr); + } else { + while (t->parent && t->parent->is_widget()) t = t->parent; + ((Widget_Node*)t)->o->redraw(); + } +} + +// the recursive part sorts all children, returns pointer to next: +Node *sort(Node *parent) { + Node *f,*n=nullptr; + for (f = parent ? parent->next : Fluid.proj.tree.first; ; f = n) { + if (!f || (parent && f->level <= parent->level)) break; + n = sort(f); + if (!f->selected || !f->is_true_widget()) continue; + Fl_Widget* fw = ((Widget_Node*)f)->o; + Node *g; // we will insert before this + for (g = parent ? parent->next : Fluid.proj.tree.first; g != f; g = g->next) { + if (!g->selected || g->level > f->level) continue; + Fl_Widget* gw = ((Widget_Node*)g)->o; + if (gw->y() > fw->y()) break; + if (gw->y() == fw->y() && gw->x() > fw->x()) break; + } + if (g != f) f->move_before(g); + } + if (parent) + parent->layout_widget(); + return f; +} + +//////////////////////////////////////////////////////////////// +// The control panels! + +Fl_Window *the_panel; + +// All the callbacks use the argument to indicate whether to load or store. +// This avoids the need for pointers to all the widgets, and keeps the +// code localized in the callbacks. +// A value of LOAD means to load. The hope is that this will not collide +// with any actual useful values for the argument. I also use this to +// initialized parts of the widget that are nyi by fluid. + +Widget_Node *current_widget; // one of the selected ones +void* const LOAD = (void *)"LOAD"; // "magic" pointer to indicate that we need to load values into the dialog +int numselected; // number selected +int haderror; + +void name_public_cb(Fl_Choice* i, void* v) { + if (v == LOAD) { + i->value(current_widget->public_>0); + if (current_widget->is_in_class()) i->hide(); else i->show(); + } else { + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + ((Widget_Node*)o)->public_ = i->value(); + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + redraw_browser(); + } + } +} + +/* Treating UNDO for text widget. + + Goal: we want to continuously update the UI while the user is typing text + (changing the label, in this case). Code View does deferred updates, and + the widget browser and widget panel update on every keystroke. At the same + time, we want to limit undo actions to few and logical units. + + Caveats: + + 1: the text widget has its own undo handling for the text field, but we may want to do a global undo + 2: every o->label() call will create an undo entry, but we want only one single event for all selected widgets + 3: we want a single undo for the entire editing phase, but still propagate changes as they happen + + The edit process has these main states: + + 1: starting to edit [first_change==1 && !unfocus]; we must create a single undo checkpoint before anything changes + 2: continue editing [first_change==0 && !unfocus]; we must suspend any undo checkpoints + 3: done editing, unfocus [first_change==0 && unfocus]; we must make sure that undo checkpoints are enabled again + 4: losing focus without editing [first_change==1 && unfocus]; don't create and checkpoints + + We must also check: + 1: changing focus without changing text (works) + 2: copy and paste, drag and drop operations (works) + 3: save operation without unfocus event (works) + */ +void label_cb(Fl_Input* i, void *v) { + static int first_change = 1; + if (v == LOAD) { + i->value(current_widget->label()); + first_change = 1; + } else { + if (i->changed()) { + Fluid.proj.undo.suspend(); + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + if (!mod) { + if (first_change) { + Fluid.proj.undo.resume(); + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + first_change = 0; + } + mod = 1; + } + o->label(i->value()); + } + } + Fluid.proj.undo.resume(); + if (mod) Fluid.proj.set_modflag(1); + } + int r = (int)Fl::callback_reason(); + if ( (r == FL_REASON_LOST_FOCUS) || (r == FL_REASON_ENTER_KEY) ) + first_change = 1; + } +} + + + + + + +int widget_i = 0; + +static int vars_i_cb(const fld::widget::Formula_Input*, void *v) { + return widget_i; +} + +static int vars_x_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = (Node*)v; + if (t->is_widget()) + return ((Widget_Node*)t)->o->x(); + return 0; +} + +static int vars_y_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = (Node*)v; + if (t->is_widget()) + return ((Widget_Node*)t)->o->y(); + return 0; +} + +static int vars_w_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = (Node*)v; + if (t->is_widget()) + return ((Widget_Node*)t)->o->w(); + return 0; +} + +static int vars_h_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = (Node*)v; + if (t->is_widget()) + return ((Widget_Node*)t)->o->h(); + return 0; +} + +static int vars_px_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->parent; + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->x(); + return 0; +} + +static int vars_py_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->parent; + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->y(); + return 0; +} + +static int vars_pw_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->parent; + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->w(); + return 0; +} + +static int vars_ph_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->parent; + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->h(); + return 0; +} + +static int vars_sx_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->prev_sibling(); + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->x(); + return 0; +} + +static int vars_sy_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->prev_sibling(); + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->y(); + return 0; +} + +static int vars_sw_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->prev_sibling(); + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->w(); + return 0; +} + +static int vars_sh_cb(const fld::widget::Formula_Input*, void *v) { + Node *t = ((Node*)v)->prev_sibling(); + if (t && t->is_widget()) + return ((Widget_Node*)t)->o->h(); + return 0; +} + +static int bbox_x, bbox_y, bbox_r, bbox_b; + +static void calculate_bbox(Node *p) { + char first = 1; + bbox_x = bbox_y = bbox_r = bbox_b = 0; + for (p=p->first_child(); p; p=p->next_sibling()) { + if (p->is_widget()) { + Fl_Widget *o = ((Widget_Node*)p)->o; + if (first) { + bbox_x = o->x(); bbox_y = o->y(); + bbox_r = o->x() + o->w(); bbox_b = o->y() + o->h(); + first = 0; + } else { + bbox_x = std::min(bbox_x, o->x()); + bbox_y = std::min(bbox_y, o->y()); + bbox_r = std::max(bbox_r, o->x() + o->w()); + bbox_b = std::max(bbox_b, o->y() + o->h()); + } + } + } +} + +static int vars_cx_cb(const fld::widget::Formula_Input*, void *v) { + calculate_bbox((Node*)v); + return bbox_x; +} + +static int vars_cy_cb(const fld::widget::Formula_Input*, void *v) { + calculate_bbox((Node*)v); + return bbox_y; +} + +static int vars_cw_cb(const fld::widget::Formula_Input*, void *v) { + calculate_bbox((Node*)v); + return bbox_r - bbox_x; +} + +static int vars_ch_cb(const fld::widget::Formula_Input*, void *v) { + calculate_bbox((Node*)v); + return bbox_b - bbox_y; +} + +fld::widget::Formula_Input_Vars widget_vars[] = { + { "i", vars_i_cb }, // zero based counter of selected widgets + { "x", vars_x_cb }, // position and size of current widget + { "y", vars_y_cb }, + { "w", vars_w_cb }, + { "h", vars_h_cb }, + { "px", vars_px_cb }, // position and size of parent widget + { "py", vars_py_cb }, + { "pw", vars_pw_cb }, + { "ph", vars_ph_cb }, + { "sx", vars_sx_cb }, // position and size of previous sibling + { "sy", vars_sy_cb }, + { "sw", vars_sw_cb }, + { "sh", vars_sh_cb }, + { "cx", vars_cx_cb }, // position and size of bounding box of all children + { "cy", vars_cy_cb }, + { "cw", vars_cw_cb }, + { "ch", vars_ch_cb }, + { nullptr } +}; + + + + + +//////////////////////////////////////////////////////////////// + +// turn number to string or string to number for saving to file: +// does not work for hierarchical menus! + +const char *item_name(Fl_Menu_Item* m, int i) { + if (m) { + while (m->label()) { + if (m->argument() == i) return m->label(); + m++; + } + } + static char buffer[20]; + sprintf(buffer, "%d", i); + return buffer; +} +int item_number(Fl_Menu_Item* m, const char* i) { + if (!i) + return 0; + if (m && i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + while (m->label()) { + if (!strcmp(m->label(), i)) return int(m->argument()); + m++; + } + } + return atoi(i); +} + +#define ZERO_ENTRY 1000 + +Fl_Menu_Item boxmenu[] = { + {"NO_BOX",0,nullptr,(void *)ZERO_ENTRY}, + {"boxes",0,nullptr,nullptr,FL_SUBMENU}, + {"UP_BOX",0,nullptr,(void *)FL_UP_BOX}, + {"DOWN_BOX",0,nullptr,(void *)FL_DOWN_BOX}, + {"FLAT_BOX",0,nullptr,(void *)FL_FLAT_BOX}, + {"BORDER_BOX",0,nullptr,(void *)FL_BORDER_BOX}, + {"THIN_UP_BOX",0,nullptr,(void *)FL_THIN_UP_BOX}, + {"THIN_DOWN_BOX",0,nullptr,(void *)FL_THIN_DOWN_BOX}, + {"ENGRAVED_BOX",0,nullptr,(void *)FL_ENGRAVED_BOX}, + {"EMBOSSED_BOX",0,nullptr,(void *)FL_EMBOSSED_BOX}, + {"ROUND_UP_BOX",0,nullptr,(void *)FL_ROUND_UP_BOX}, + {"ROUND_DOWN_BOX",0,nullptr,(void *)FL_ROUND_DOWN_BOX}, + {"DIAMOND_UP_BOX",0,nullptr,(void *)FL_DIAMOND_UP_BOX}, + {"DIAMOND_DOWN_BOX",0,nullptr,(void *)FL_DIAMOND_DOWN_BOX}, + {"SHADOW_BOX",0,nullptr,(void *)FL_SHADOW_BOX}, + {"ROUNDED_BOX",0,nullptr,(void *)FL_ROUNDED_BOX}, + {"RSHADOW_BOX",0,nullptr,(void *)FL_RSHADOW_BOX}, + {"RFLAT_BOX",0,nullptr,(void *)FL_RFLAT_BOX}, + {"OVAL_BOX",0,nullptr,(void *)FL_OVAL_BOX}, + {"OSHADOW_BOX",0,nullptr,(void *)FL_OSHADOW_BOX}, + {"OFLAT_BOX",0,nullptr,(void *)FL_OFLAT_BOX}, + {"PLASTIC_UP_BOX",0,nullptr,(void *)FL_PLASTIC_UP_BOX}, + {"PLASTIC_DOWN_BOX",0,nullptr,(void *)FL_PLASTIC_DOWN_BOX}, + {"PLASTIC_THIN_UP_BOX",0,nullptr,(void *)FL_PLASTIC_THIN_UP_BOX}, + {"PLASTIC_THIN_DOWN_BOX",0,nullptr,(void *)FL_PLASTIC_THIN_DOWN_BOX}, + {"PLASTIC_ROUND_UP_BOX",0,nullptr,(void *)FL_PLASTIC_ROUND_UP_BOX}, + {"PLASTIC_ROUND_DOWN_BOX",0,nullptr,(void *)FL_PLASTIC_ROUND_DOWN_BOX}, + {"GTK_UP_BOX",0,nullptr,(void *)FL_GTK_UP_BOX}, + {"GTK_DOWN_BOX",0,nullptr,(void *)FL_GTK_DOWN_BOX}, + {"GTK_THIN_UP_BOX",0,nullptr,(void *)FL_GTK_THIN_UP_BOX}, + {"GTK_THIN_DOWN_BOX",0,nullptr,(void *)FL_GTK_THIN_DOWN_BOX}, + {"GTK_ROUND_UP_BOX",0,nullptr,(void *)FL_GTK_ROUND_UP_BOX}, + {"GTK_ROUND_DOWN_BOX",0,nullptr,(void *)FL_GTK_ROUND_DOWN_BOX}, + {"GLEAM_UP_BOX",0,nullptr,(void *)FL_GLEAM_UP_BOX}, + {"GLEAM_DOWN_BOX",0,nullptr,(void *)FL_GLEAM_DOWN_BOX}, + {"GLEAM_THIN_UP_BOX",0,nullptr,(void *)FL_GLEAM_THIN_UP_BOX}, + {"GLEAM_THIN_DOWN_BOX",0,nullptr,(void *)FL_GLEAM_THIN_DOWN_BOX}, + {"GLEAM_ROUND_UP_BOX",0,nullptr,(void *)FL_GLEAM_ROUND_UP_BOX}, + {"GLEAM_ROUND_DOWN_BOX",0,nullptr,(void *)FL_GLEAM_ROUND_DOWN_BOX}, + {"OXY_UP_BOX",0,nullptr,(void *)FL_OXY_UP_BOX}, + {"OXY_DOWN_BOX",0,nullptr,(void *)FL_OXY_DOWN_BOX}, + {"OXY_THIN_UP_BOX",0,nullptr,(void *)FL_OXY_THIN_UP_BOX}, + {"OXY_THIN_DOWN_BOX",0,nullptr,(void *)FL_OXY_THIN_DOWN_BOX}, + {"OXY_ROUND_UP_BOX",0,nullptr,(void *)FL_OXY_ROUND_UP_BOX}, + {"OXY_ROUND_DOWN_BOX",0,nullptr,(void *)FL_OXY_ROUND_DOWN_BOX}, + {"OXY_BUTTON_UP_BOX",0,nullptr,(void *)FL_OXY_BUTTON_UP_BOX}, + {"OXY_BUTTON_DOWN_BOX",0,nullptr,(void *)FL_OXY_BUTTON_DOWN_BOX}, + {nullptr}, + {"frames",0,nullptr,nullptr,FL_SUBMENU}, + {"UP_FRAME",0,nullptr,(void *)FL_UP_FRAME}, + {"DOWN_FRAME",0,nullptr,(void *)FL_DOWN_FRAME}, + {"THIN_UP_FRAME",0,nullptr,(void *)FL_THIN_UP_FRAME}, + {"THIN_DOWN_FRAME",0,nullptr,(void *)FL_THIN_DOWN_FRAME}, + {"ENGRAVED_FRAME",0,nullptr,(void *)FL_ENGRAVED_FRAME}, + {"EMBOSSED_FRAME",0,nullptr,(void *)FL_EMBOSSED_FRAME}, + {"BORDER_FRAME",0,nullptr,(void *)FL_BORDER_FRAME}, + {"SHADOW_FRAME",0,nullptr,(void *)FL_SHADOW_FRAME}, + {"ROUNDED_FRAME",0,nullptr,(void *)FL_ROUNDED_FRAME}, + {"OVAL_FRAME",0,nullptr,(void *)FL_OVAL_FRAME}, + {"PLASTIC_UP_FRAME",0,nullptr,(void *)FL_PLASTIC_UP_FRAME}, + {"PLASTIC_DOWN_FRAME",0,nullptr,(void *)FL_PLASTIC_DOWN_FRAME}, + {"GTK_UP_FRAME",0,nullptr,(void *)FL_GTK_UP_FRAME}, + {"GTK_DOWN_FRAME",0,nullptr,(void *)FL_GTK_DOWN_FRAME}, + {"GTK_THIN_UP_FRAME",0,nullptr,(void *)FL_GTK_THIN_UP_FRAME}, + {"GTK_THIN_DOWN_FRAME",0,nullptr,(void *)FL_GTK_THIN_DOWN_FRAME}, + {"GLEAM_UP_FRAME",0,nullptr,(void *)FL_GLEAM_UP_FRAME}, + {"GLEAM_DOWN_FRAME",0,nullptr,(void *)FL_GLEAM_DOWN_FRAME}, + {"OXY_UP_FRAME",0,nullptr,(void *)FL_OXY_UP_FRAME}, + {"OXY_DOWN_FRAME",0,nullptr,(void *)FL_OXY_DOWN_FRAME}, + {"OXY_THIN_UP_FRAME",0,nullptr,(void *)FL_OXY_THIN_UP_FRAME}, + {"OXY_THIN_DOWN_FRAME",0,nullptr,(void *)FL_OXY_THIN_DOWN_FRAME}, + {nullptr}, + {nullptr}}; + +const char *boxname(int i) { + if (!i) i = ZERO_ENTRY; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].argument() == i) return boxmenu[j].label(); + return nullptr; +} + +int boxnumber(const char *i) { + if (i[0]=='F' && i[1]=='L' && i[2]=='_') i += 3; + for (int j = 0; j < int(sizeof(boxmenu)/sizeof(*boxmenu)); j++) + if (boxmenu[j].label() && !strcmp(boxmenu[j].label(), i)) { + return int(boxmenu[j].argument()); + } + return 0; +} + + + + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item whenmenu[] = { + // set individual bits + {"FL_WHEN_CHANGED",0,nullptr,(void*)FL_WHEN_CHANGED, FL_MENU_TOGGLE}, + {"FL_WHEN_NOT_CHANGED",0,nullptr,(void*)FL_WHEN_NOT_CHANGED, FL_MENU_TOGGLE}, + {"FL_WHEN_RELEASE",0,nullptr,(void*)FL_WHEN_RELEASE, FL_MENU_TOGGLE}, + {"FL_WHEN_ENTER_KEY",0,nullptr,(void*)FL_WHEN_ENTER_KEY, FL_MENU_TOGGLE}, + {"FL_WHEN_CLOSED",0,nullptr,(void*)FL_WHEN_CLOSED, FL_MENU_TOGGLE|FL_MENU_DIVIDER}, + // set bit combinations + {"FL_WHEN_NEVER",0,nullptr,(void*)FL_WHEN_NEVER}, + {"FL_WHEN_RELEASE_ALWAYS",0,nullptr,(void*)FL_WHEN_RELEASE_ALWAYS}, + {"FL_WHEN_ENTER_KEY_ALWAYS",0,nullptr,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, + {"FL_WHEN_ENTER_KEY_CHANGED",0,nullptr,(void*)FL_WHEN_ENTER_KEY_CHANGED}, + {nullptr}}; + + +static Fl_Menu_Item whensymbolmenu[] = { + /* 0 */ {"FL_WHEN_NEVER",0,nullptr,(void*)FL_WHEN_NEVER}, + /* 1 */ {"FL_WHEN_CHANGED",0,nullptr,(void*)FL_WHEN_CHANGED}, + /* 2 */ {"FL_WHEN_NOT_CHANGED",0,nullptr,(void*)FL_WHEN_NOT_CHANGED}, + /* 3 */ {"FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED",0,nullptr,(void*)(FL_WHEN_CHANGED|FL_WHEN_NOT_CHANGED)}, + /* 4 */ {"FL_WHEN_RELEASE",0,nullptr,(void*)FL_WHEN_RELEASE}, + /* 5 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE",0,nullptr,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE)}, + /* 6 */ {"FL_WHEN_RELEASE_ALWAYS",0,nullptr,(void*)FL_WHEN_RELEASE_ALWAYS}, + /* 7 */ {"FL_WHEN_CHANGED | FL_WHEN_RELEASE_ALWAYS",0,nullptr,(void*)(FL_WHEN_CHANGED|FL_WHEN_RELEASE_ALWAYS)}, + /* 8 */ {"FL_WHEN_ENTER_KEY",0,nullptr,(void*)FL_WHEN_ENTER_KEY}, + /* 9 */ {"FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,nullptr,(void*)(FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, + /* 10 */ {"FL_WHEN_ENTER_KEY_ALWAYS",0,nullptr,(void*)FL_WHEN_ENTER_KEY_ALWAYS}, + /* 11 */ {"FL_WHEN_ENTER_KEY_CHANGED",0,nullptr,(void*)FL_WHEN_ENTER_KEY_CHANGED}, + /* 12 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY",0,nullptr,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY)}, + /* 13 */ {"FL_WHEN_RELEASE | FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY",0,nullptr,(void*)(FL_WHEN_RELEASE|FL_WHEN_CHANGED|FL_WHEN_ENTER_KEY)}, + /* 14 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_ALWAYS",0,nullptr,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_ALWAYS)}, + /* 15 */ {"FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED",0,nullptr,(void*)(FL_WHEN_RELEASE|FL_WHEN_ENTER_KEY_CHANGED)}, + {nullptr} +}; + +// Return a text string representing the Fl_When value n +const char* when_symbol_name(int n) { + static char sym[128]; + if (n == FL_WHEN_CLOSED) { + strcpy(sym, "FL_WHEN_CLOSED"); + } else { + strcpy(sym, whensymbolmenu[n&15].label()); + if (n & FL_WHEN_CLOSED) + strcat(sym, " | FL_WHEN_CLOSED"); + } + return sym; +} + +// Set the check marks in the "when()" menu according to the Fl_When value n +void set_whenmenu(int n) { + if (n&FL_WHEN_CHANGED) whenmenu[0].set(); else whenmenu[0].clear(); + if (n&FL_WHEN_NOT_CHANGED) whenmenu[1].set(); else whenmenu[1].clear(); + if (n&FL_WHEN_RELEASE) whenmenu[2].set(); else whenmenu[2].clear(); + if (n&FL_WHEN_ENTER_KEY) whenmenu[3].set(); else whenmenu[3].clear(); + if (n&FL_WHEN_CLOSED) whenmenu[4].set(); else whenmenu[4].clear(); +} + + +uchar Widget_Node::resizable() const { + if (is_a(Type::Window)) return ((Fl_Window*)o)->resizable() != nullptr; + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) return p->resizable() == o; + else return 0; +} + +void Widget_Node::resizable(uchar v) { + if (v) { + if (resizable()) return; + if (is_a(Type::Window)) ((Fl_Window*)o)->resizable(o); + else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(o); + } + } else { + if (!resizable()) return; + if (is_a(Type::Window)) { + ((Fl_Window*)o)->resizable(nullptr); + } else { + Fl_Group* p = (Fl_Group*)o->parent(); + if (p) p->resizable(nullptr); + } + } +} + + + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item fontmenu[] = { + {"Helvetica"}, + {"Helvetica bold"}, + {"Helvetica italic"}, + {"Helvetica bold italic"}, + {"Courier"}, + {"Courier bold"}, + {"Courier italic"}, + {"Courier bold italic"}, + {"Times"}, + {"Times bold"}, + {"Times italic"}, + {"Times bold italic"}, + {"Symbol"}, + {"Terminal"}, + {"Terminal Bold"}, + {"Zapf Dingbats"}, + {nullptr} +}; + +Fl_Menu_Item fontmenu_w_default[] = { + {"", 0, nullptr, nullptr, FL_MENU_DIVIDER}, + {"Helvetica"}, + {"Helvetica bold"}, + {"Helvetica italic"}, + {"Helvetica bold italic"}, + {"Courier"}, + {"Courier bold"}, + {"Courier italic"}, + {"Courier bold italic"}, + {"Times"}, + {"Times bold"}, + {"Times italic"}, + {"Times bold italic"}, + {"Symbol"}, + {"Terminal"}, + {"Terminal Bold"}, + {"Zapf Dingbats"}, + {nullptr} +}; + + + +extern const char *ui_find_image_name; + +Fl_Menu_Item labeltypemenu[] = { + {"NORMAL_LABEL",0,nullptr,(void*)nullptr}, + {"SHADOW_LABEL",0,nullptr,(void*)FL_SHADOW_LABEL}, + {"ENGRAVED_LABEL",0,nullptr,(void*)FL_ENGRAVED_LABEL}, + {"EMBOSSED_LABEL",0,nullptr,(void*)FL_EMBOSSED_LABEL}, + {"NO_LABEL",0,nullptr,(void*)(FL_NO_LABEL)}, + {nullptr}}; + +void labeltype_cb(Fl_Choice* i, void *v) { + if (v == LOAD) { + int n; + n = current_widget->o->labeltype(); + i->when(FL_WHEN_RELEASE); + for (int j = 0; j < int(sizeof(labeltypemenu)/sizeof(*labeltypemenu)); j++) + if (labeltypemenu[j].argument() == n) {i->value(j); break;} + } else { + int mod = 0; + int m = i->value(); + int n = int(labeltypemenu[m].argument()); + if (n<0) return; // should not happen + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* p = (Widget_Node*)o; + p->o->labeltype((Fl_Labeltype)n); + p->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + +Fl_Menu_Item colormenu[] = { + { "Foreground Color", 0, nullptr, (void*)(fl_intptr_t)FL_FOREGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, + { "Background Color", 0, nullptr, (void*)(fl_intptr_t)FL_BACKGROUND_COLOR, 0, 0, FL_HELVETICA, 11}, + { "Background Color 2", 0, nullptr, (void*)(fl_intptr_t)FL_BACKGROUND2_COLOR, 0, 0, FL_HELVETICA, 11}, + { "Selection Color", 0, nullptr, (void*)(fl_intptr_t)FL_SELECTION_COLOR, 0, 0, FL_HELVETICA, 11}, + { "Inactive Color", 0, nullptr, (void*)(fl_intptr_t)FL_INACTIVE_COLOR, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, + { "Black", 0, nullptr, (void*)(fl_intptr_t)FL_BLACK, 0, 0, FL_HELVETICA, 11}, + { "White", 0, nullptr, (void*)(fl_intptr_t)FL_WHITE, FL_MENU_DIVIDER, 0, FL_HELVETICA, 11}, + { "Gray 0", 0, nullptr, (void*)(fl_intptr_t)FL_GRAY0, 0, 0, FL_HELVETICA, 11}, + { "Dark 3", 0, nullptr, (void*)(fl_intptr_t)FL_DARK3, 0, 0, FL_HELVETICA, 11}, + { "Dark 2", 0, nullptr, (void*)(fl_intptr_t)FL_DARK2, 0, 0, FL_HELVETICA, 11}, + { "Dark 1", 0, nullptr, (void*)(fl_intptr_t)FL_DARK1, 0, 0, FL_HELVETICA, 11}, + { "Light 1", 0, nullptr, (void*)(fl_intptr_t)FL_LIGHT1, 0, 0, FL_HELVETICA, 11}, + { "Light 2", 0, nullptr, (void*)(fl_intptr_t)FL_LIGHT2, 0, 0, FL_HELVETICA, 11}, + { "Light 3", 0, nullptr, (void*)(fl_intptr_t)FL_LIGHT3, 0, 0, FL_HELVETICA, 11}, + { nullptr } +}; + +void color_common(Fl_Color c) { + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + q->o->color(c); q->o->redraw(); + if (q->parent && q->parent->is_a(Type::Tabs)) { + if (q->o->parent()) q->o->parent()->redraw(); + } + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +} + + + +void color2_common(Fl_Color c) { + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + q->o->selection_color(c); q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +} + + + +void labelcolor_common(Fl_Color c) { + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + q->o->labelcolor(c); q->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +} + + + +static Fl_Button* relative(Fl_Widget* o, int i) { + Fl_Group* g = (Fl_Group*)(o->parent()); + return (Fl_Button*)(g->child(g->find(*o)+i)); +} + +static Fl_Menu_Item alignmenu[] = { + {"FL_ALIGN_CENTER",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_CENTER)}, + {"FL_ALIGN_TOP",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_TOP)}, + {"FL_ALIGN_BOTTOM",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM)}, + {"FL_ALIGN_LEFT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_LEFT)}, + {"FL_ALIGN_RIGHT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT)}, + {"FL_ALIGN_INSIDE",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_INSIDE)}, + {"FL_ALIGN_CLIP",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_CLIP)}, + {"FL_ALIGN_WRAP",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_WRAP)}, + {"FL_ALIGN_TEXT_OVER_IMAGE",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_TEXT_OVER_IMAGE)}, + {"FL_ALIGN_TOP_LEFT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_TOP_LEFT)}, + {"FL_ALIGN_TOP_RIGHT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_TOP_RIGHT)}, + {"FL_ALIGN_BOTTOM_LEFT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_LEFT)}, + {"FL_ALIGN_BOTTOM_RIGHT",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_BOTTOM_RIGHT)}, + {"FL_ALIGN_LEFT_TOP",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_TOP)}, + {"FL_ALIGN_RIGHT_TOP",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_TOP)}, + {"FL_ALIGN_LEFT_BOTTOM",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_LEFT_BOTTOM)}, + {"FL_ALIGN_RIGHT_BOTTOM",0,nullptr,(void*)(fl_intptr_t)(FL_ALIGN_RIGHT_BOTTOM)}, + {nullptr}}; + +void align_cb(Fl_Button* i, void *v) { + Fl_Align b = Fl_Align(fl_uintptr_t(i->user_data())); + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {i->deactivate(); return;} else i->activate(); + i->value(current_widget->o->align() & b); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + Fl_Align x = q->o->align(); + Fl_Align y; + if (i->value()) { + y = x | b; + if (b == FL_ALIGN_LEFT || b == FL_ALIGN_TOP) { + Fl_Button *b1 = relative(i,+1); + b1->clear(); + y = y & ~(b1->argument()); + } + if (b == FL_ALIGN_RIGHT || b == FL_ALIGN_BOTTOM) { + Fl_Button *b1 = relative(i,-1); + b1->clear(); + y = y & ~(b1->argument()); + } + } else { + y = x & ~b; + } + if (x != y) { + q->o->align(y); + q->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +void align_position_cb(Fl_Choice *i, void *v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {i->deactivate(); return;} else i->activate(); + Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); + Fl_Align b = current_widget->o->align() & FL_ALIGN_POSITION_MASK; + for (;mi->text;mi++) { + if ((Fl_Align)(mi->argument())==b) + i->value(mi); + } + } else { + const Fl_Menu_Item *mi = i->menu() + i->value(); + Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + Fl_Align x = q->o->align(); + Fl_Align y = (x & ~FL_ALIGN_POSITION_MASK) | b; + if (x != y) { + q->o->align(y); + q->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +void align_text_image_cb(Fl_Choice *i, void *v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {i->deactivate(); return;} else i->activate(); + Fl_Menu_Item *mi = (Fl_Menu_Item*)i->menu(); + Fl_Align b = current_widget->o->align() & FL_ALIGN_IMAGE_MASK; + for (;mi->text;mi++) { + if ((Fl_Align)(mi->argument())==b) + i->value(mi); + } + } else { + const Fl_Menu_Item *mi = i->menu() + i->value(); + Fl_Align b = Fl_Align(fl_uintptr_t(mi->user_data())); + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + Fl_Align x = q->o->align(); + Fl_Align y = (x & ~FL_ALIGN_IMAGE_MASK) | b; + if (x != y) { + q->o->align(y); + q->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +//////////////////////////////////////////////////////////////// + + + + + +//////////////////////////////////////////////////////////////// + +// textstuff: set textfont, textsize, textcolor attributes: + +// default widget returns 0 to indicate not-implemented: +// The first parameter specifies the operation: +// 0: get all values +// 1: set the text font +// 2: set the text size +// 3: set the text color +// 4: get all default values for this type +int Widget_Node::textstuff(int, Fl_Font&, int&, Fl_Color&) { + return 0; +} + + + +void textcolor_common(Fl_Color c) { + Fl_Font n; int s; + int mod = 0; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_widget()) { + Widget_Node* q = (Widget_Node*)o; + q->textstuff(3,n,s,c); q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +} + +//////////////////////////////////////////////////////////////// +// Kludges to the panel for subclasses: + + + + +//static void flex_margin_cb(Fl_Value_Input* i, void* v, +// void (*load_margin)(Fl_Flex*,Fl_Value_Input*), +// int (*update_margin)(Fl_Flex*,int)) { +// if (v == LOAD) { +// if (current_widget->is_a(Type::Flex)) { +// load_margin((Fl_Flex*)current_widget->o, i); +// } +// } else { +// int mod = 0; +// int new_value = (int)i->value(); +// for (Node *o = Fluid.proj.tree.first; o; o = o->next) { +// if (o->selected && o->is_a(Type::Flex)) { +// Flex_Node* q = (Flex_Node*)o; +// Fl_Flex* w = (Fl_Flex*)q->o; +// if (update_margin(w, new_value)) { +// w->layout(); +// mod = 1; +// } +// } +// } +// if (mod) Fluid.proj.set_modflag(1); +// } +//} + + + + +static void load_gap(Fl_Flex *w, Fl_Value_Input* i) +{ + int v = w->gap(); + i->value((double)v); +} + +static int update_gap(Fl_Flex *w, int new_value) +{ + int g = w->gap(); + if (new_value!=g) { + w->gap(new_value); + return 1; + } else { + return 0; + } +} + +void flex_margin_gap_cb(Fl_Value_Input* i, void* v) { + flex_margin_cb(i, v, load_gap, update_gap); +} + +void position_group_cb(Fl_Group* g, void* v) { + if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + g->hide(); + } else { + g->show(); + } + } + propagate_load(g, v); +} + + + +//////////////////////////////////////////////////////////////// + +// subtypes: + +Fl_Menu_Item *Widget_Node::subtypes() {return nullptr;} + + +//////////////////////////////////////////////////////////////// + +void propagate_load(Fl_Group* g, void* v) { + if (v == LOAD) { + Fl_Widget*const* a = g->array(); + for (int i=g->children(); i--;) { + Fl_Widget* o = *a++; + o->do_callback(o, LOAD, FL_REASON_USER); + } + } +} + +void set_cb(Fl_Button*, void*) { + haderror = 0; + Fl_Widget*const* a = the_panel->array(); + for (int i=the_panel->children(); i--;) { + Fl_Widget* o = *a++; + if (o->changed()) { + o->do_callback(); + if (haderror) return; + o->clear_changed(); + } + } +} + +void ok_cb(Fl_Return_Button* o, void* v) { + set_cb(o,v); + if (!haderror) the_panel->hide(); +} + +void toggle_overlays(Fl_Widget *,void *); // in Window_Node.cxx +void overlay_cb(Fl_Button*o,void *v) { + toggle_overlays(o,v); +} + +void leave_live_mode_cb(Fl_Widget*, void*); + +void live_mode_cb(Fl_Button*o,void *) { + /// \todo live mode should end gracefully when the application quits + /// or when the user closes the live widget + static Node *live_type = nullptr; + static Fl_Widget *live_widget = nullptr; + static Fl_Window *live_window = nullptr; + // if 'o' is 0, we must quit live mode + if (!o) { + o = wLiveMode; + o->value(0); + } + if (o->value()) { + if (numselected == 1) { + Fl_Group::current(nullptr); + live_widget = current_widget->enter_live_mode(1); + if (live_widget) { + live_type = current_widget; + Fl_Group::current(nullptr); + int w = live_widget->w(); + int h = live_widget->h(); + live_window = new Fl_Double_Window(w+20, h+55, "Fluid Live Resize"); + live_window->box(FL_FLAT_BOX); + live_window->color(FL_GREEN); + Fl_Group *rsz = new Fl_Group(0, h+20, 130, 35); + rsz->box(FL_NO_BOX); + Fl_Box *rsz_dummy = new Fl_Box(110, h+20, 1, 25); + rsz_dummy->box(FL_NO_BOX); + rsz->resizable(rsz_dummy); + Fl_Button *btn = new Fl_Button(10, h+20, 100, 25, "Exit Live Resize"); + btn->labelsize(12); + btn->callback(leave_live_mode_cb); + rsz->end(); + live_window->add(live_widget); + live_widget->position(10, 10); + live_window->resizable(live_widget); + live_window->set_modal(); // block all other UI + live_window->callback(leave_live_mode_cb); + if (current_widget->is_a(Type::Window)) { + Window_Node *w = (Window_Node*)current_widget; + int mw = w->sr_min_w; if (mw>0) mw += 20; + int mh = w->sr_min_h; if (mh>0) mh += 55; + int MW = w->sr_max_w; if (MW>0) MW += 20; + int MH = w->sr_max_h; if (MH>2) MH += 55; + if (mw || mh || MW || MH) + live_window->size_range(mw, mh, MW, MH); + } + live_window->show(); + live_widget->show(); + } else o->value(0); + } else o->value(0); + } else { + if (live_type) + live_type->leave_live_mode(); + if (live_window) { + live_window->hide(); + Fl::delete_widget(live_window); + } + live_type = nullptr; + live_widget = nullptr; + live_window = nullptr; + } +} + +// update the panel according to current widget set: +void load_panel() { + if (!the_panel) return; + + // find all the Fl_Widget subclasses currently selected: + numselected = 0; + current_widget = nullptr; + if (Fluid.proj.tree.current) { + if (Fluid.proj.tree.current->is_widget()) + current_widget=(Widget_Node*)Fluid.proj.tree.current; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->is_widget() && o->selected) { + numselected++; + if (!current_widget) current_widget = (Widget_Node*)o; + } + } + } + if (current_widget && current_widget->is_a(Type::Grid)) { + if (widget_tab_grid->parent()!=widget_tabs) + widget_tabs->add(widget_tab_grid); + } else { + if (widget_tab_grid->parent()==widget_tabs) { + widget_tabs_repo->add(widget_tab_grid); + } + } + if (current_widget && current_widget->parent && current_widget->parent->is_a(Type::Grid)) { + if (widget_tab_grid_child->parent()!=widget_tabs) + widget_tabs->add(widget_tab_grid_child); + } else { + if (widget_tab_grid_child->parent()==widget_tabs) { + widget_tabs_repo->add(widget_tab_grid_child); + } + } + if (numselected) + propagate_load(the_panel, LOAD); + else + the_panel->hide(); +} + +extern Fl_Window *widgetbin_panel; + +// This is called when user double-clicks an item, open or update the panel: +void Widget_Node::open() { + bool adjust_position = false; + if (!the_panel) { + the_panel = make_widget_panel(); + adjust_position = true; + } + load_panel(); + 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(); +extern void check_redraw_corresponding_parent(Node*); +extern void redraw_browser(); +extern void update_codeview_position(); + +// Called when ui changes what objects are selected: +// p is selected object, null for all deletions (we must throw away +// old panel in that case, as the object may no longer exist) +void selection_changed(Node *p) { + // store all changes to the current selected objects: + if (p && the_panel && the_panel->visible()) { + set_cb(nullptr,nullptr); + // if there was an error, we try to leave the selected set unchanged: + if (haderror) { + Node *q = nullptr; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + o->new_selected = o->selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fluid.proj.tree.current = p; + redraw_browser(); + return; + } + } + // update the selected flags to new set: + Node *q = nullptr; + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + o->selected = o->new_selected; + if (!q && o->selected) q = o; + } + if (!p || !p->selected) p = q; + Fluid.proj.tree.current = p; + check_redraw_corresponding_parent(p); + redraw_overlays(); + // load the panel with the new settings: + load_panel(); + // update the code viewer to show the code for the selected object + update_codeview_position(); +} + +//////////////////////////////////////////////////////////////// +// Writing the C code: + +// test to see if user named a function, or typed in code: +int is_name(const char *c) { + for (; *c; c++) + if ((ispunct(*c)||*c=='\n') && *c!='_' && *c!=':') return 0; + return 1; +} + +// Test to see if name() is an array entry. If so, and this is the +// highest number, return name[num+1]. Return null if not the highest +// number or a field or function. Return name() if not an array entry. +const char *array_name(Widget_Node *o) { + const char *c = o->name(); + if (!c) return nullptr; + const char *d; + for (d = c; *d != '['; d++) { + if (!*d) return c; + if (ispunct(*d) && *d!='_') return nullptr; + } + int num = atoi(d+1); + int sawthis = 0; + Node *t = o->prev; + Node *tp = o; + const char *cn = o->class_name(1); + for (; t && t->class_name(1) == cn; tp = t, t = t->prev) {/*empty*/} + for (t = tp; t && t->class_name(1) == cn; t = t->next) { + if (t == o) {sawthis=1; continue;} + const char *e = t->name(); + if (!e) continue; + if (strncmp(c,e,d-c)) continue; + int n1 = atoi(e+(d-c)+1); + if (n1 > num || (n1==num && sawthis)) return nullptr; + } + static char buffer[128]; + // MRS: we want strncpy() here... + strncpy(buffer,c,d-c+1); + snprintf(buffer+(d-c+1),sizeof(buffer) - (d-c+1), "%d]",num+1); + return buffer; +} + +// Test to see if extra code is a declaration: +int isdeclare(const char *c) { + while (isspace(*c)) c++; + if (*c == '#') return 1; + if (!strncmp(c,"extern",6)) return 1; + if (!strncmp(c,"typedef",7)) return 1; + if (!strncmp(c,"using",5)) return 1; + return 0; +} + +void Widget_Node::write_static(fld::io::Code_Writer& f) { + const char* t = subclassname(this); + if (!subclass() || (is_class() && !strncmp(t, "Fl_", 3))) { + f.write_h_once("#include "); + f.write_h_once("#include ", t); + } + for (int n=0; n < NUM_EXTRA_CODE; n++) { + if (extra_code(n) && isdeclare(extra_code(n))) + f.write_h_once("%s", extra_code(n)); + } + if (callback() && is_name(callback())) { + int write_extern_declaration = 1; + char buf[1024]; snprintf(buf, 1023, "%s(*)", callback()); + if (is_in_class()) { + if (has_function("static void", buf)) + write_extern_declaration = 0; + } else { + if (has_toplevel_function(nullptr, buf)) + write_extern_declaration = 0; + } + if (write_extern_declaration) + f.write_h_once("extern void %s(%s*, %s);", callback(), t, + user_data_type() ? user_data_type() : "void*"); + } + const char* k = class_name(1); + const char* c = array_name(this); + if (c && !k && !is_class()) { + f.write_c("\n"); + if (!public_) f.write_c("static "); + else f.write_h("extern %s *%s;\n", t, c); + if (strchr(c, '[') == nullptr) f.write_c("%s *%s=(%s *)0;\n", t, c, t); + else f.write_c("%s *%s={(%s *)0};\n", t, c, t); + } + if (callback() && !is_name(callback())) { + // see if 'o' or 'v' used, to prevent unused argument warnings: + int use_o = 0; + int use_v = 0; + const char *d; + for (d = callback(); *d;) { + if (*d == 'o' && !is_id(d[1])) use_o = 1; + if (*d == 'v' && !is_id(d[1])) use_v = 1; + do d++; while (is_id(*d)); + while (*d && !is_id(*d)) d++; + } + const char* cn = callback_name(f); + if (k) { + f.write_c("\nvoid %s::%s_i(%s*", k, cn, t); + } else { + f.write_c("\nstatic void %s(%s*", cn, t); + } + if (use_o) f.write_c(" o"); + const char* ut = user_data_type() ? user_data_type() : "void*"; + f.write_c(", %s", ut); + if (use_v) f.write_c(" v"); + f.write_c(") {\n"); + // Matt: disabled f.tag(FD_TAG_GENERIC, 0); + f.write_c_indented(callback(), 1, 0); + if (*(d-1) != ';' && *(d-1) != '}') { + const char *p = strrchr(callback(), '\n'); + if (p) p ++; + else p = callback(); + // Only add trailing semicolon if the last line is not a preprocessor + // statement... + if (*p != '#' && *p) f.write_c(";"); + } + f.write_c("\n"); + // Matt: disabled f.tag(FD_TAG_WIDGET_CALLBACK, get_uid()); + f.write_c("}\n"); + if (k) { + f.write_c("void %s::%s(%s* o, %s v) {\n", k, cn, t, ut); + f.write_c("%s((%s*)(o", f.indent(1), k); + Node *q = nullptr; + for (Node* p = parent; p && p->is_widget(); q = p, p = p->parent) + f.write_c("->parent()"); + if (!q || !q->is_a(Type::Widget_Class)) + f.write_c("->user_data()"); + f.write_c("))->%s_i(o,v);\n}\n", cn); + } + } + if (image) { + if (!f.c_contains(image)) + image->write_static(f, compress_image_); + } + if (inactive) { + if (!f.c_contains(inactive)) + inactive->write_static(f, compress_deimage_); + } +} + +void Widget_Node::write_code1(fld::io::Code_Writer& f) { + const char* t = subclassname(this); + const char *c = array_name(this); + if (c) { + if (class_name(1)) { + f.write_public(public_); + f.write_h("%s%s *%s;\n", f.indent(1), t, c); + } + } + if (class_name(1) && callback() && !is_name(callback())) { + const char* cn = callback_name(f); + const char* ut = user_data_type() ? user_data_type() : "void*"; + f.write_public(0); + f.write_h("%sinline void %s_i(%s*, %s);\n", f.indent(1), cn, t, ut); + f.write_h("%sstatic void %s(%s*, %s);\n", f.indent(1), cn, t, ut); + } + // figure out if local variable will be used (prevent compiler warnings): + int wused = !name() && is_a(Type::Window); + const char *ptr; + + f.varused = wused; + + if (!name() && !f.varused) { + f.varused |= can_have_children(); + + if (!f.varused) { + f.varused_test = 1; + write_widget_code(f); + f.varused_test = 0; + } + } + + if (!f.varused) { + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) + { + int instring = 0; + int inname = 0; + int incomment = 0; + int incppcomment = 0; + for (ptr = extra_code(n); *ptr; ptr ++) { + if (instring) { + if (*ptr == '\\') ptr++; + else if (*ptr == '\"') instring = 0; + } else if (inname && !isalnum(*ptr & 255)) { + inname = 0; + } else if (*ptr == '/' && ptr[1]=='*') { + incomment = 1; ptr++; + } else if (incomment) { + if (*ptr == '*' && ptr[1]=='/') { + incomment = 0; ptr++; + } + } else if (*ptr == '/' && ptr[1]=='/') { + incppcomment = 1; ptr++; + } else if (incppcomment) { + if (*ptr == '\n') + incppcomment = 0; + } else if (*ptr == '\"') { + instring = 1; + } else if (isalnum(*ptr & 255) || *ptr == '_') { + size_t len = strspn(ptr, "0123456789_" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (!strncmp(ptr, "o", len)) { + f.varused = 1; + break; + } else { + ptr += len - 1; + } + } + } + } + } + + f.write_c("%s{ ", f.indent()); + write_comment_inline_c(f); + if (f.varused) f.write_c("%s* o = ", t); + if (name()) f.write_c("%s = ", name()); + if (is_a(Type::Window)) { + // Handle special case where user is faking a Fl_Group type as a window, + // there is no 2-argument constructor in that case: + if (!strstr(t, "Window")) + f.write_c("new %s(0, 0, %d, %d", t, o->w(), o->h()); + else + f.write_c("new %s(%d, %d", t, o->w(), o->h()); + } else if (is_a(Type::Menu_Bar) + && ((Menu_Bar_Node*)this)->is_sys_menu_bar() + && is_in_class()) { + f.write_c("(%s*)new %s(%d, %d, %d, %d", + t, ((Menu_Bar_Node*)this)->sys_menubar_proxy_name(), + o->x(), o->y(), o->w(), o->h()); + } else { + f.write_c("new %s(%d, %d, %d, %d", t, o->x(), o->y(), o->w(), o->h()); + } + if (label() && *label()) { + f.write_c(", "); + switch (Fluid.proj.i18n_type) { + case fld::I18n_Type::NONE : /* None */ + f.write_cstring(label()); + break; + case fld::I18n_Type::GNU : /* GNU gettext */ + f.write_c("%s(", Fluid.proj.i18n_gnu_function.c_str()); + f.write_cstring(label()); + f.write_c(")"); + break; + case fld::I18n_Type::POSIX : /* POSIX catgets */ + f.write_c("catgets(%s,%s,%d,", + Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), + Fluid.proj.i18n_pos_set.c_str(), msgnum()); + f.write_cstring(label()); + f.write_c(")"); + break; + } + } + f.write_c(");\n"); + + f.indentation++; + + // Avoid compiler warning for unused variable. + // Also avoid quality control warnings about incorrect allocation error handling. + if (wused) f.write_c("%sw = o; (void)w;\n", f.indent()); + + write_widget_code(f); +} + +void Widget_Node::write_color(fld::io::Code_Writer& f, const char* field, Fl_Color color) { + const char* color_name = nullptr; + switch (color) { + case FL_FOREGROUND_COLOR: color_name = "FL_FOREGROUND_COLOR"; break; + case FL_BACKGROUND2_COLOR: color_name = "FL_BACKGROUND2_COLOR"; break; + case FL_INACTIVE_COLOR: color_name = "FL_INACTIVE_COLOR"; break; + case FL_SELECTION_COLOR: color_name = "FL_SELECTION_COLOR"; break; + case FL_GRAY0: color_name = "FL_GRAY0"; break; + case FL_DARK3: color_name = "FL_DARK3"; break; + case FL_DARK2: color_name = "FL_DARK2"; break; + case FL_DARK1: color_name = "FL_DARK1"; break; + case FL_BACKGROUND_COLOR: color_name = "FL_BACKGROUND_COLOR"; break; + case FL_LIGHT1: color_name = "FL_LIGHT1"; break; + case FL_LIGHT2: color_name = "FL_LIGHT2"; break; + case FL_LIGHT3: color_name = "FL_LIGHT3"; break; + case FL_BLACK: color_name = "FL_BLACK"; break; + case FL_RED: color_name = "FL_RED"; break; + case FL_GREEN: color_name = "FL_GREEN"; break; + case FL_YELLOW: color_name = "FL_YELLOW"; break; + case FL_BLUE: color_name = "FL_BLUE"; break; + case FL_MAGENTA: color_name = "FL_MAGENTA"; break; + case FL_CYAN: color_name = "FL_CYAN"; break; + case FL_DARK_RED: color_name = "FL_DARK_RED"; break; + case FL_DARK_GREEN: color_name = "FL_DARK_GREEN"; break; + case FL_DARK_YELLOW: color_name = "FL_DARK_YELLOW"; break; + case FL_DARK_BLUE: color_name = "FL_DARK_BLUE"; break; + case FL_DARK_MAGENTA: color_name = "FL_DARK_MAGENTA"; break; + case FL_DARK_CYAN: color_name = "FL_DARK_CYAN"; break; + case FL_WHITE: color_name = "FL_WHITE"; break; + } + const char *var = is_class() ? "this" : name() ? name() : "o"; + if (color_name) { + f.write_c("%s%s->%s(%s);\n", f.indent(), var, field, color_name); + } else { + f.write_c("%s%s->%s((Fl_Color)%d);\n", f.indent(), var, field, color); + } +} + +// this is split from write_code1(fld::io::Code_Writer& f) for Window_Node: +void Widget_Node::write_widget_code(fld::io::Code_Writer& f) { + Fl_Widget* tplate = ((Widget_Node*)factory)->o; + const char *var = is_class() ? "this" : name() ? name() : "o"; + + if (tooltip() && *tooltip()) { + f.write_c("%s%s->tooltip(",f.indent(), var); + switch (Fluid.proj.i18n_type) { + case fld::I18n_Type::NONE : /* None */ + f.write_cstring(tooltip()); + break; + case fld::I18n_Type::GNU : /* GNU gettext */ + f.write_c("%s(", Fluid.proj.i18n_gnu_function.c_str()); + f.write_cstring(tooltip()); + f.write_c(")"); + break; + case fld::I18n_Type::POSIX : /* POSIX catgets */ + f.write_c("catgets(%s,%s,%d,", + Fluid.proj.i18n_pos_file.empty() ? "_catalog" : Fluid.proj.i18n_pos_file.c_str(), + Fluid.proj.i18n_pos_set.c_str(), + msgnum() + 1); + f.write_cstring(tooltip()); + f.write_c(")"); + break; + } + f.write_c(");\n"); + } + + if (is_a(Type::Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) + f.write_c("%s%s->type(%d);\n", f.indent(), var, ((Fl_Spinner*)o)->type()); + else if (o->type() != tplate->type() && !is_a(Type::Window)) + f.write_c("%s%s->type(%d);\n", f.indent(), var, o->type()); + if (o->box() != tplate->box() || subclass()) + f.write_c("%s%s->box(FL_%s);\n", f.indent(), var, boxname(o->box())); + + // write shortcut command if needed + int shortcut = 0; + if (is_button()) shortcut = ((Fl_Button*)o)->shortcut(); + else if (is_a(Type::Input)) shortcut = ((Fl_Input_*)o)->shortcut(); + else if (is_a(Type::Value_Input)) shortcut = ((Fl_Value_Input*)o)->shortcut(); + else if (is_a(Type::Text_Display)) shortcut = ((Fl_Text_Display*)o)->shortcut(); + if (shortcut) { + int s = shortcut; + f.write_c("%s%s->shortcut(", f.indent(), var); + if (Fluid.proj.use_FL_COMMAND) { + if (s & FL_CTRL) { f.write_c("FL_CONTROL|"); s &= ~FL_CTRL; } + if (s & FL_META) { f.write_c("FL_COMMAND|"); s &= ~FL_META; } + } else { + if (s & FL_CTRL) { f.write_c("FL_CTRL|"); s &= ~FL_CTRL; } + if (s & FL_META) { f.write_c("FL_META|"); s &= ~FL_META; } + } + if (s & FL_SHIFT) { f.write_c("FL_SHIFT|"); s &= ~FL_SHIFT; } + if (s & FL_ALT) { f.write_c("FL_ALT|"); s &= ~FL_ALT; } + if ((s < 127) && isprint(s)) + f.write_c("'%c');\n", s); + else + f.write_c("0x%x);\n", s); + } + + if (is_a(Type::Button)) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, + boxname(b->down_box())); + if (b->value()) f.write_c("%s%s->value(1);\n", f.indent(), var); + if (b->compact()) f.write_c("%s%s->compact(%d);\n", f.indent(), var, b->compact()); + } else if (is_a(Type::Input_Choice)) { + Fl_Input_Choice* b = (Fl_Input_Choice*)o; + if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, + boxname(b->down_box())); + } else if (is_a(Type::Menu_Manager_)) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var, + boxname(b->down_box())); + } + if (o->color() != tplate->color() || subclass()) + write_color(f, "color", o->color()); + if (o->selection_color() != tplate->selection_color() || subclass()) + write_color(f, "selection_color", o->selection_color()); + if (image) { + image->write_code(f, bind_image_, var); + if (scale_image_w_ || scale_image_h_) { + f.write_c("%s%s->image()->scale(", f.indent(), var); + if (scale_image_w_>0) + f.write_c("%d, ", scale_image_w_); + else + f.write_c("%s->image()->data_w(), ", var); + if (scale_image_h_>0) + f.write_c("%d, 0, 1);\n", scale_image_h_); + else + f.write_c("%s->image()->data_h(), 0, 1);\n", var); + } + } + if (inactive) { + inactive->write_code(f, bind_deimage_, var, 1); + if (scale_deimage_w_ || scale_deimage_h_) { + f.write_c("%s%s->deimage()->scale(", f.indent(), var); + if (scale_deimage_w_>0) + f.write_c("%d, ", scale_deimage_w_); + else + f.write_c("%s->deimage()->data_w(), ", var); + if (scale_deimage_h_>0) + f.write_c("%d, 0, 1);\n", scale_deimage_h_); + else + f.write_c("%s->deimage()->data_h(), 0, 1);\n", var); + } + } + if (o->labeltype() != tplate->labeltype() || subclass()) + f.write_c("%s%s->labeltype(FL_%s);\n", f.indent(), var, + item_name(labeltypemenu, o->labeltype())); + if (o->labelfont() != tplate->labelfont() || subclass()) + f.write_c("%s%s->labelfont(%d);\n", f.indent(), var, o->labelfont()); + if (o->labelsize() != tplate->labelsize() || subclass()) + f.write_c("%s%s->labelsize(%d);\n", f.indent(), var, o->labelsize()); + if (o->labelcolor() != tplate->labelcolor() || subclass()) + write_color(f, "labelcolor", o->labelcolor()); + if (o->horizontal_label_margin() != tplate->horizontal_label_margin()) + f.write_c("%s%s->horizontal_label_margin(%d);\n", f.indent(), var, o->horizontal_label_margin()); + if (o->vertical_label_margin() != tplate->vertical_label_margin()) + f.write_c("%s%s->vertical_label_margin(%d);\n", f.indent(), var, o->vertical_label_margin()); + if (o->label_image_spacing() != tplate->label_image_spacing()) + f.write_c("%s%s->label_image_spacing(%d);\n", f.indent(), var, o->label_image_spacing()); + if (is_a(Type::Valuator_)) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* t = (Fl_Valuator*)(tplate); + if (v->minimum()!=t->minimum()) + f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); + if (v->maximum()!=t->maximum()) + f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); + if (v->step()!=t->step()) + f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); + if (v->value()) { + if (is_a(Type::Scrollbar)) { // Fl_Scrollbar::value(double) is not available + f.write_c("%s%s->Fl_Slider::value(%g);\n", f.indent(), var, v->value()); + } else { + f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); + } + } + if (is_a(Type::Slider)) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)t)->slider_size(); + if (x != y) f.write_c("%s%s->slider_size(%g);\n", f.indent(), var, x); + } + } + if (is_a(Type::Spinner)) { + Fl_Spinner* v = (Fl_Spinner*)o; + Fl_Spinner* t = (Fl_Spinner*)(tplate); + if (v->minimum()!=t->minimum()) + f.write_c("%s%s->minimum(%g);\n", f.indent(), var, v->minimum()); + if (v->maximum()!=t->maximum()) + f.write_c("%s%s->maximum(%g);\n", f.indent(), var, v->maximum()); + if (v->step()!=t->step()) + f.write_c("%s%s->step(%g);\n", f.indent(), var, v->step()); + if (v->value()!=1.0f) + f.write_c("%s%s->value(%g);\n", f.indent(), var, v->value()); + } + + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font g; int s; Fl_Color c; textstuff(0,g,s,c); + if (g != ff) f.write_c("%s%s->textfont(%d);\n", f.indent(), var, g); + if (s != fs) f.write_c("%s%s->textsize(%d);\n", f.indent(), var, s); + if (c != fc) write_color(f, "textcolor", c); + }} + const char* ud = user_data(); + if (class_name(1) && !parent->is_widget()) ud = "this"; + if (callback()) { + f.write_c("%s%s->callback((Fl_Callback*)%s", f.indent(), var, callback_name(f)); + if (ud) + f.write_c(", (void*)(%s));\n", ud); + else + f.write_c(");\n"); + } else if (ud) { + f.write_c("%s%s->user_data((void*)(%s));\n", f.indent(), var, ud); + } + if (o->align() != tplate->align() || subclass()) { + int i = o->align(); + f.write_c("%s%s->align(Fl_Align(%s", f.indent(), var, + item_name(alignmenu, i & ~FL_ALIGN_INSIDE)); + if (i & FL_ALIGN_INSIDE) f.write_c("|FL_ALIGN_INSIDE"); + f.write_c("));\n"); + } + Fl_When ww = o->when(); + if (ww != tplate->when() || subclass()) + f.write_c("%s%s->when(%s);\n", f.indent(), var, when_symbol_name(ww)); + if (!o->visible() && o->parent()) + f.write_c("%s%s->hide();\n", f.indent(), var); + if (!o->active()) + f.write_c("%s%s->deactivate();\n", f.indent(), var); + if (!is_a(Type::Group) && resizable()) + f.write_c("%sFl_Group::current()->resizable(%s);\n", f.indent(), var); + if (hotspot()) { + if (is_class()) + f.write_c("%shotspot(%s);\n", f.indent(), var); + else if (is_a(Type::Window)) + f.write_c("%s%s->hotspot(%s);\n", f.indent(), var, var); + else + f.write_c("%s%s->window()->hotspot(%s);\n", f.indent(), var, var); + } +} + +void Widget_Node::write_extra_code(fld::io::Code_Writer& f) { + for (int n=0; n < NUM_EXTRA_CODE; n++) + if (extra_code(n) && !isdeclare(extra_code(n))) + f.write_c("%s%s\n", f.indent(), extra_code(n)); +} + +void Widget_Node::write_block_close(fld::io::Code_Writer& f) { + f.indentation--; + f.write_c("%s} // %s* %s\n", f.indent(), subclassname(this), + name() ? name() : "o"); +} + +void Widget_Node::write_code2(fld::io::Code_Writer& f) { + write_extra_code(f); + write_block_close(f); +} + +//////////////////////////////////////////////////////////////// + +void Widget_Node::write_properties(fld::io::Project_Writer &f) { + Node::write_properties(f); + f.write_indent(level+1); + switch (public_) { + case 0: f.write_string("private"); break; + case 1: break; + case 2: f.write_string("protected"); break; + } + if (tooltip() && *tooltip()) { + f.write_string("tooltip"); + f.write_word(tooltip()); + } + if (image_name() && *image_name()) { + if (scale_image_w_ || scale_image_h_) + f.write_string("scale_image {%d %d}", scale_image_w_, scale_image_h_); + f.write_string("image"); + f.write_word(image_name()); + f.write_string("compress_image %d", compress_image_); + } + if (bind_image_) f.write_string("bind_image 1"); + if (inactive_name() && *inactive_name()) { + if (scale_deimage_w_ || scale_deimage_h_) + f.write_string("scale_deimage {%d %d}", scale_deimage_w_, scale_deimage_h_); + f.write_string("deimage"); + f.write_word(inactive_name()); + f.write_string("compress_deimage %d", compress_deimage_); + } + if (bind_deimage_) f.write_string("bind_deimage 1"); + f.write_string("xywh {%d %d %d %d}", o->x(), o->y(), o->w(), o->h()); + Fl_Widget* tplate = ((Widget_Node*)factory)->o; + if (is_a(Type::Spinner) && ((Fl_Spinner*)o)->type() != ((Fl_Spinner*)tplate)->type()) { + f.write_string("type"); + f.write_word(item_name(subtypes(), ((Fl_Spinner*)o)->type())); + } else if (subtypes() && (o->type() != tplate->type() || is_a(Type::Window))) { + f.write_string("type"); + f.write_word(item_name(subtypes(), o->type())); + } + if (o->box() != tplate->box()) { + f.write_string("box"); f.write_word(boxname(o->box()));} + if (is_a(Type::Input)) { + Fl_Input_* b = (Fl_Input_*)o; + if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); + } + if (is_a(Type::Value_Input)) { + Fl_Value_Input* b = (Fl_Value_Input*)o; + if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); + } + if (is_a(Type::Text_Display)) { + Fl_Text_Display* b = (Fl_Text_Display*)o; + if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); + } + if (is_a(Type::Button)) { + Fl_Button* b = (Fl_Button*)o; + if (b->down_box()) { + f.write_string("down_box"); f.write_word(boxname(b->down_box()));} + if (b->shortcut()) f.write_string("shortcut 0x%x", b->shortcut()); + if (b->value()) f.write_string("value 1"); + } else if (is_a(Type::Input_Choice)) { + Fl_Input_Choice* b = (Fl_Input_Choice*)o; + if (b->down_box()) { + f.write_string("down_box"); f.write_word(boxname(b->down_box()));} + } else if (is_a(Type::Menu_)) { + Fl_Menu_* b = (Fl_Menu_*)o; + if (b->down_box()) { + f.write_string("down_box"); f.write_word(boxname(b->down_box()));} + } + if (o->color()!=tplate->color()) + f.write_string("color %d", o->color()); + if (o->selection_color()!=tplate->selection_color()) + f.write_string("selection_color %d", o->selection_color()); + if (o->labeltype()!=tplate->labeltype()) { + f.write_string("labeltype"); + f.write_word(item_name(labeltypemenu, o->labeltype())); + } + if (o->labelfont()!=tplate->labelfont()) + f.write_string("labelfont %d", o->labelfont()); + if (o->labelsize()!=tplate->labelsize()) + f.write_string("labelsize %d", o->labelsize()); + if (o->labelcolor()!=tplate->labelcolor()) + f.write_string("labelcolor %d", o->labelcolor()); + if (o->align()!=tplate->align()) + f.write_string("align %d", o->align()); + if (o->horizontal_label_margin()!=tplate->horizontal_label_margin()) + f.write_string("h_label_margin %d", o->horizontal_label_margin()); + if (o->vertical_label_margin()!=tplate->vertical_label_margin()) + f.write_string("v_label_margin %d", o->vertical_label_margin()); + if (o->label_image_spacing()!=tplate->label_image_spacing()) + f.write_string("image_spacing %d", o->label_image_spacing()); + if (o->when() != tplate->when()) + f.write_string("when %d", o->when()); + if (is_a(Type::Valuator_)) { + Fl_Valuator* v = (Fl_Valuator*)o; + Fl_Valuator* t = (Fl_Valuator*)(tplate); + if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); + if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); + if (v->step()!=t->step()) f.write_string("step %g",v->step()); + if (v->value()!=0.0) f.write_string("value %g",v->value()); + if (is_a(Type::Slider)) { + double x = ((Fl_Slider*)v)->slider_size(); + double y = ((Fl_Slider*)t)->slider_size(); + if (x != y) f.write_string("slider_size %g", x); + } + } + if (is_a(Type::Spinner)) { + Fl_Spinner* v = (Fl_Spinner*)o; + Fl_Spinner* t = (Fl_Spinner*)(tplate); + if (v->minimum()!=t->minimum()) f.write_string("minimum %g",v->minimum()); + if (v->maximum()!=t->maximum()) f.write_string("maximum %g",v->maximum()); + if (v->step()!=t->step()) f.write_string("step %g",v->step()); + if (v->value()!=1.0) f.write_string("value %g",v->value()); + } + {Fl_Font ff; int fs; Fl_Color fc; if (textstuff(4,ff,fs,fc)) { + Fl_Font ft; int s; Fl_Color c; textstuff(0,ft,s,c); + if (ft != ff) f.write_string("textfont %d", ft); + if (s != fs) f.write_string("textsize %d", s); + if (c != fc) f.write_string("textcolor %d", c); + }} + if (!o->visible() && !override_visible_) f.write_string("hide"); + if (!o->active()) f.write_string("deactivate"); + if (resizable()) f.write_string("resizable"); + if (hotspot()) f.write_string(is_a(Type::Menu_Item) ? "divider" : "hotspot"); + for (int n=0; n < NUM_EXTRA_CODE; n++) if (extra_code(n)) { + f.write_indent(level+1); + f.write_string("code%d",n); + f.write_word(extra_code(n)); + } + if (subclass()) { + f.write_indent(level+1); + f.write_string("class"); + f.write_word(subclass()); + } +} + +void Widget_Node::read_property(fld::io::Project_Reader &f, const char *c) { + int x,y,w,h; Fl_Font ft; int s; Fl_Color cc; + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"protected")) { + public_ = 2; + } else if (!strcmp(c,"xywh")) { + if (sscanf(f.read_word(),"%d %d %d %d",&x,&y,&w,&h) == 4) { + x += Fluid.pasteoffset; + y += Fluid.pasteoffset; + // FIXME temporary change! + if (f.read_version>=2.0 && o->parent() && o->parent()!=o->window()) { + x += o->parent()->x(); + y += o->parent()->y(); + } + o->resize(x,y,w,h); + } + } else if (!strcmp(c,"tooltip")) { + tooltip(f.read_word()); + } else if (!strcmp(c,"scale_image")) { + if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { + scale_image_w_ = w; + scale_image_h_ = h; + } + } else if (!strcmp(c,"image")) { + image_name(f.read_word()); + // starting in 2023, `image` is always followed by `compress_image` + // the code below is for compatibility with older .fl files + const char *ext = fl_filename_ext(image_name_); + if ( strcmp(ext, ".jpg") + && strcmp(ext, ".png") + && strcmp(ext, ".svg") + && strcmp(ext, ".svgz")) + compress_image_ = 0; // if it is neither of those, default to uncompressed + } else if (!strcmp(c,"bind_image")) { + bind_image_ = (int)atol(f.read_word()); + } else if (!strcmp(c,"compress_image")) { + compress_image_ = (int)atol(f.read_word()); + } else if (!strcmp(c,"scale_deimage")) { + if (sscanf(f.read_word(),"%d %d",&w,&h) == 2) { + scale_deimage_w_ = w; + scale_deimage_h_ = h; + } + } else if (!strcmp(c,"deimage")) { + inactive_name(f.read_word()); + // starting in 2023, `deimage` is always followed by `compress_deimage` + // the code below is for compatibility with older .fl files + const char *ext = fl_filename_ext(inactive_name_); + if ( strcmp(ext, ".jpg") + && strcmp(ext, ".png") + && strcmp(ext, ".svg") + && strcmp(ext, ".svgz")) + compress_deimage_ = 0; // if it is neither of those, default to uncompressed + } else if (!strcmp(c,"bind_deimage")) { + bind_deimage_ = (int)atol(f.read_word()); + } else if (!strcmp(c,"compress_deimage")) { + compress_deimage_ = (int)atol(f.read_word()); + } else if (!strcmp(c,"type")) { + if (is_a(Type::Spinner)) + ((Fl_Spinner*)o)->type(item_number(subtypes(), f.read_word())); + else + o->type(item_number(subtypes(), f.read_word())); + } else if (!strcmp(c,"box")) { + const char* value = f.read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + o->box((Fl_Boxtype)x); + } else if (sscanf(value,"%d",&x) == 1) o->box((Fl_Boxtype)x); + } else if (is_a(Type::Button) && !strcmp(c,"down_box")) { + const char* value = f.read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Button*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_a(Type::Input_Choice) && !strcmp(c,"down_box")) { + const char* value = f.read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Input_Choice*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_a(Type::Menu_) && !strcmp(c,"down_box")) { + const char* value = f.read_word(); + if ((x = boxnumber(value))) { + if (x == ZERO_ENTRY) x = 0; + ((Fl_Menu_*)o)->down_box((Fl_Boxtype)x); + } + } else if (is_button() && !strcmp(c,"value")) { + const char* value = f.read_word(); + ((Fl_Button*)o)->value(atoi(value)); + } else if (!strcmp(c,"color")) { + const char *cw = f.read_word(); + if (cw[0]=='0' && cw[1]=='x') { + sscanf(cw,"0x%x",&x); + o->color(x); + } else { + int n = sscanf(cw,"%d %d",&x,&y); + if (n == 2) { // back compatibility... + if (x != 47) o->color(x); + o->selection_color(y); + } else { + o->color(x); + } + } + } else if (!strcmp(c,"selection_color")) { + if (sscanf(f.read_word(),"%d",&x)) o->selection_color(x); + } else if (!strcmp(c,"labeltype")) { + c = f.read_word(); + if (!strcmp(c,"image")) { + Image_Asset *i = Image_Asset::find(label()); + if (!i) f.read_error("Image file '%s' not found", label()); + else setimage(i); + image_name(label()); + label(""); + } else { + o->labeltype((Fl_Labeltype)item_number(labeltypemenu,c)); + } + } else if (!strcmp(c,"labelfont")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->labelfont(x); + } else if (!strcmp(c,"labelsize")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->labelsize(x); + } else if (!strcmp(c,"labelcolor")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->labelcolor(x); + } else if (!strcmp(c,"align")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->align(x); + } else if (!strcmp(c,"h_label_margin")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->horizontal_label_margin(x); + } else if (!strcmp(c,"v_label_margin")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->vertical_label_margin(x); + } else if (!strcmp(c,"image_spacing")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->label_image_spacing(x); + } else if (!strcmp(c,"when")) { + if (sscanf(f.read_word(),"%d",&x) == 1) o->when(x); + } else if (!strcmp(c,"minimum")) { + if (is_a(Type::Valuator_)) ((Fl_Valuator*)o)->minimum(strtod(f.read_word(),nullptr)); + if (is_a(Type::Spinner)) ((Fl_Spinner*)o)->minimum(strtod(f.read_word(),nullptr)); + } else if (!strcmp(c,"maximum")) { + if (is_a(Type::Valuator_)) ((Fl_Valuator*)o)->maximum(strtod(f.read_word(),nullptr)); + if (is_a(Type::Spinner)) ((Fl_Spinner*)o)->maximum(strtod(f.read_word(),nullptr)); + } else if (!strcmp(c,"step")) { + if (is_a(Type::Valuator_)) ((Fl_Valuator*)o)->step(strtod(f.read_word(),nullptr)); + if (is_a(Type::Spinner)) ((Fl_Spinner*)o)->step(strtod(f.read_word(),nullptr)); + } else if (!strcmp(c,"value")) { + if (is_a(Type::Valuator_)) ((Fl_Valuator*)o)->value(strtod(f.read_word(),nullptr)); + if (is_a(Type::Spinner)) ((Fl_Spinner*)o)->value(strtod(f.read_word(),nullptr)); + } else if ( (!strcmp(c,"slider_size") || !strcmp(c,"size")) && is_a(Type::Slider)) { + ((Fl_Slider*)o)->slider_size(strtod(f.read_word(),nullptr)); + } else if (!strcmp(c,"textfont")) { + if (sscanf(f.read_word(),"%d",&x) == 1) {ft=(Fl_Font)x; textstuff(1,ft,s,cc);} + } else if (!strcmp(c,"textsize")) { + if (sscanf(f.read_word(),"%d",&x) == 1) {s=x; textstuff(2,ft,s,cc);} + } else if (!strcmp(c,"textcolor")) { + if (sscanf(f.read_word(),"%d",&x) == 1) {cc=(Fl_Color)x;textstuff(3,ft,s,cc);} + } else if (!strcmp(c,"hide")) { + o->hide(); + } else if (!strcmp(c,"deactivate")) { + o->deactivate(); + } else if (!strcmp(c,"resizable")) { + resizable(1); + } else if (!strcmp(c,"hotspot") || !strcmp(c, "divider")) { + hotspot(1); + } else if (!strcmp(c,"class")) { + subclass(f.read_word()); + } else if (!strcmp(c,"shortcut")) { + int shortcut = (int)strtol(f.read_word(),nullptr,0); + if (is_button()) ((Fl_Button*)o)->shortcut(shortcut); + else if (is_a(Type::Input)) ((Fl_Input_*)o)->shortcut(shortcut); + else if (is_a(Type::Value_Input)) ((Fl_Value_Input*)o)->shortcut(shortcut); + else if (is_a(Type::Text_Display)) ((Fl_Text_Display*)o)->shortcut(shortcut); + } else { + if (!strncmp(c,"code",4)) { + int n = atoi(c+4); + if (n >= 0 && n <= NUM_EXTRA_CODE) { + extra_code(n,f.read_word()); + return; + } + } else if (!strcmp(c,"extra_code")) { + extra_code(0,f.read_word()); + return; + } + Node::read_property(f, c); + } +} + +Fl_Menu_Item boxmenu1[] = { + // these extra ones are for looking up fdesign saved strings: + {"NO_FRAME", 0,nullptr,(void *)FL_NO_BOX}, + {"ROUNDED3D_UPBOX", 0,nullptr,(void *)_FL_ROUND_UP_BOX}, + {"ROUNDED3D_DOWNBOX", 0,nullptr,(void *)_FL_ROUND_DOWN_BOX}, + {"OVAL3D_UPBOX", 0,nullptr,(void *)_FL_ROUND_UP_BOX}, + {"OVAL3D_DOWNBOX", 0,nullptr,(void *)_FL_ROUND_DOWN_BOX}, + {"0", 0,nullptr,(void *)ZERO_ENTRY}, + {"1", 0,nullptr,(void *)FL_UP_BOX}, + {"2", 0,nullptr,(void *)FL_DOWN_BOX}, + {"3", 0,nullptr,(void *)FL_FLAT_BOX}, + {"4", 0,nullptr,(void *)FL_BORDER_BOX}, + {"5", 0,nullptr,(void *)FL_SHADOW_BOX}, + {"6", 0,nullptr,(void *)FL_FRAME_BOX}, + {"7", 0,nullptr,(void *)FL_ROUNDED_BOX}, + {"8", 0,nullptr,(void *)FL_RFLAT_BOX}, + {"9", 0,nullptr,(void *)FL_RSHADOW_BOX}, + {"10", 0,nullptr,(void *)FL_UP_FRAME}, + {"11", 0,nullptr,(void *)FL_DOWN_FRAME}, + {nullptr}}; + +int lookup_symbol(const char *, int &, int numberok = 0); + +int Widget_Node::read_fdesign(const char* propname, const char* value) { + int v; + if (!strcmp(propname,"box")) { + float x,y,w,h; + if (sscanf(value,"%f %f %f %f",&x,&y,&w,&h) == 4) { + if (fld::io::fdesign_flip) { + Node *p; + for (p = parent; p && !p->is_a(Type::Window); p = p->parent) {/*empty*/} + if (p && p->is_widget()) y = ((Widget_Node*)p)->o->h()-(y+h); + } + x += Fluid.pasteoffset; + y += Fluid.pasteoffset; + o->resize(int(x),int(y),int(w),int(h)); + } + } else if (!strcmp(propname,"label")) { + label(value); + } else if (!strcmp(propname,"name")) { + this->name(value); + } else if (!strcmp(propname,"callback")) { + callback(value); user_data_type("long"); + } else if (!strcmp(propname,"argument")) { + user_data(value); + } else if (!strcmp(propname,"shortcut")) { + if (value[0]) { + char buf[128]; sprintf(buf,"o->shortcut(\"%s\");",value); + extra_code(0,buf); + } + } else if (!strcmp(propname,"style")) { + if (!strncmp(value,"FL_NORMAL",9)) return 1; + if (!lookup_symbol(value,v,1)) return 0; + o->labelfont(v); o->labeltype((Fl_Labeltype)(v>>8)); + } else if (!strcmp(propname,"size")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelsize(v); + } else if (!strcmp(propname,"type")) { + if (!strncmp(value,"NORMAL",6)) return 1; + if (lookup_symbol(value,v,1)) {o->type(v); return 1;} + if (!strcmp(value+strlen(value)-5,"FRAME")) goto TRY_BOXTYPE; + if (!strcmp(value+strlen(value)-3,"BOX")) goto TRY_BOXTYPE; + return 0; + } else if (!strcmp(propname,"lcol")) { + if (!lookup_symbol(value,v,1)) return 0; + o->labelcolor(v); + } else if (!strcmp(propname,"return")) { + if (!lookup_symbol(value,v,0)) return 0; + o->when(v|FL_WHEN_RELEASE); + } else if (!strcmp(propname,"alignment")) { + if (!lookup_symbol(value,v)) { + // convert old numeric values: + int v1 = atoi(value); if (v1 <= 0 && strcmp(value,"0")) return 0; + v = 0; + if (v1 >= 5) {v = FL_ALIGN_INSIDE; v1 -= 5;} + switch (v1) { + case 0: v += FL_ALIGN_TOP; break; + case 1: v += FL_ALIGN_BOTTOM; break; + case 2: v += FL_ALIGN_LEFT; break; + case 3: v += FL_ALIGN_RIGHT; break; + case 4: v += FL_ALIGN_CENTER; break; + default: return 0; + } + } + o->align(v); + } else if (!strcmp(propname,"resizebox")) { + resizable(1); + } else if (!strcmp(propname,"colors")) { + char* p = (char*)value; + while (*p != ' ') {if (!*p) return 0; p++;} + *p = 0; + int v1; + if (!lookup_symbol(value,v,1) || !lookup_symbol(p+1,v1,1)) { + *p=' '; return 0;} + o->color(v,v1); + } else if (!strcmp(propname,"resize")) { + return !strcmp(value,"FL_RESIZE_ALL"); + } else if (!strcmp(propname,"gravity")) { + return !strcmp(value,"FL_NoGravity FL_NoGravity"); + } else if (!strcmp(propname,"boxtype")) { + TRY_BOXTYPE: + int x = boxnumber(value); + if (!x) {x = item_number(boxmenu1, value); if (x < 0) return 0;} + if (x == ZERO_ENTRY) { + x = 0; + if (o->box() != ((Widget_Node*)factory)->o->box()) return 1; // kludge for frame + } + o->box((Fl_Boxtype)x); + } else { + return 0; + } + return 1; +} + +void leave_live_mode_cb(Fl_Widget*, void*) { + live_mode_cb(nullptr, nullptr); +} + +Fl_Widget *Widget_Node::enter_live_mode(int) { + live_widget = widget(o->x(), o->y(), o->w(), o->h()); + if (live_widget) + copy_properties(); + return live_widget; +} + +Fl_Widget* Widget_Node::propagate_live_mode(Fl_Group* grp) { + live_widget = grp; + copy_properties(); + Node *n; + for (n = next; n && n->level > level; n = n->next) { + if (n->level == level+1) { + Fl_Widget* proxy_child = n->enter_live_mode(); + if (proxy_child && n->is_widget() && ((Widget_Node*)n)->resizable()) { + grp->resizable(proxy_child); + } + } + } + grp->end(); + live_widget = grp; + copy_properties_for_children(); + return live_widget; +} + + +void Widget_Node::leave_live_mode() { +} + +/** + copy all properties from the edit widget to the live widget + */ +void Widget_Node::copy_properties() { + if (!live_widget) + return; + + Fl_Font ff = 0; + int fs = 0; + Fl_Color fc = 0; + textstuff(0, ff, fs, fc); + + // copy all attributes common to all widget types + Fl_Widget *w = live_widget; + w->label(o->label()); + w->tooltip(tooltip()); + w->type(o->type()); + w->box(o->box()); + w->color(o->color()); + w->selection_color(o->selection_color()); + w->labeltype(o->labeltype()); + w->labelfont(o->labelfont()); + w->labelsize(o->labelsize()); + w->labelcolor(o->labelcolor()); + w->align(o->align()); + w->when(o->when()); + + // copy all attributes specific to widgets derived from Fl_Button + if (is_button()) { + Fl_Button* d = (Fl_Button*)live_widget, *s = (Fl_Button*)o; + d->down_box(s->down_box()); + d->shortcut(s->shortcut()); + d->value(s->value()); + } + + // copy all attributes specific to widgets derived from Fl_Input_ + if (is_a(Type::Input)) { + Fl_Input_* d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; + d->shortcut(s->shortcut()); + d->textfont(ff); + d->textsize(fs); + d->textcolor(fc); + } + + // copy all attributes specific to widgets derived from Fl_Value_Input + if (is_a(Type::Value_Input)) { + Fl_Value_Input* d = (Fl_Value_Input*)live_widget, *s = (Fl_Value_Input*)o; + d->shortcut(s->shortcut()); + d->textfont(ff); + d->textsize(fs); + d->textcolor(fc); + } + + // copy all attributes specific to widgets derived from Fl_Text_Display + if (is_a(Type::Text_Display)) { + Fl_Text_Display* d = (Fl_Text_Display*)live_widget, *s = (Fl_Text_Display*)o; + d->shortcut(s->shortcut()); + d->textfont(ff); + d->textsize(fs); + d->textcolor(fc); + } + + // copy all attributes specific to Fl_Valuator and derived classes + if (is_a(Type::Valuator_)) { + Fl_Valuator* d = (Fl_Valuator*)live_widget, *s = (Fl_Valuator*)o; + d->minimum(s->minimum()); + d->maximum(s->maximum()); + d->step(s->step()); + d->value(s->value()); + if (is_a(Type::Slider)) { + Fl_Slider *d = (Fl_Slider*)live_widget, *s = (Fl_Slider*)o; + d->slider_size(s->slider_size()); + } + } + + // copy all attributes specific to Fl_Spinner and derived classes + if (is_a(Type::Spinner)) { + Fl_Spinner* d = (Fl_Spinner*)live_widget, *s = (Fl_Spinner*)o; + d->minimum(s->minimum()); + d->maximum(s->maximum()); + d->step(s->step()); + d->value(s->value()); + } + + if (!o->visible()) + w->hide(); + if (!o->active()) + w->deactivate(); +} + diff --git a/fluid/nodes/Fl_Widget_Type.h b/fluid/nodes/Widget_Node.h similarity index 58% rename from fluid/nodes/Fl_Widget_Type.h rename to fluid/nodes/Widget_Node.h index 6a26921cc..261005590 100644 --- a/fluid/nodes/Fl_Widget_Type.h +++ b/fluid/nodes/Widget_Node.h @@ -1,11 +1,7 @@ // -// Widget type header file for the Fast Light Tool Kit (FLTK). +// Widget Node header file for the Fast Light Tool Kit (FLTK). // -// Type for creating all subclasses of Fl_Widget -// This should have the widget pointer in it, but it is still in the -// Fl_Type base class. -// -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -18,32 +14,35 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FL_WIDGET_TYPE_H -#define _FLUID_FL_WIDGET_TYPE_H +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Node base class. -#include "nodes/Fl_Type.h" +#ifndef FLUID_NODES_WIDGET_NODE_H +#define FLUID_NODES_WIDGET_NODE_H + +#include "nodes/Node.h" #define NUM_EXTRA_CODE 4 -class Fl_Widget_Type; -class Fluid_Image; +class Widget_Node; +class Image_Asset; extern void* const LOAD; -extern Fl_Widget_Type *current_widget; // one of the selected ones +extern Widget_Node *current_widget; // one of the selected ones -extern const char* subclassname(Fl_Type* l); +extern const char* subclassname(Node* l); extern int is_name(const char *c); -void selection_changed(Fl_Type* new_current); -Fl_Type *sort(Fl_Type *parent); -void comment_cb(class Fl_Text_Editor* i, void *v); +void selection_changed(Node* new_current); +Node *sort(Node *parent); -class Fl_Widget_Type : public Fl_Type +class Widget_Node : public Node { - typedef Fl_Type super; + typedef Node super; virtual Fl_Widget *widget(int,int,int,int) = 0; - virtual Fl_Widget_Type *_make() = 0; // virtual constructor - void setlabel(const char *) FL_OVERRIDE; + virtual Widget_Node *_make() = 0; // virtual constructor + void setlabel(const char *) override; const char *extra_code_[NUM_EXTRA_CODE]; const char *subclass_; @@ -60,12 +59,12 @@ protected: /// disabling the output of the "hide" property by the Widget Type. uchar override_visible_; - void write_static(fld::io::Code_Writer& f) FL_OVERRIDE; - void write_code1(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_static(fld::io::Code_Writer& f) override; + void write_code1(fld::io::Code_Writer& f) override; void write_widget_code(fld::io::Code_Writer& f); void write_extra_code(fld::io::Code_Writer& f); void write_block_close(fld::io::Code_Writer& f); - void write_code2(fld::io::Code_Writer& f) FL_OVERRIDE; + void write_code2(fld::io::Code_Writer& f) override; void write_color(fld::io::Code_Writer& f, const char*, Fl_Color); Fl_Widget *live_widget; @@ -79,14 +78,14 @@ public: int scale_image_w_, scale_image_h_; int scale_deimage_w_, scale_deimage_h_; - Fluid_Image *image; - void setimage(Fluid_Image *); - Fluid_Image *inactive; - void setinactive(Fluid_Image *); + Image_Asset *image; + void setimage(Image_Asset *); + Image_Asset *inactive; + void setinactive(Image_Asset *); - Fl_Widget_Type(); - Fl_Type *make(Strategy strategy) FL_OVERRIDE; - void open() FL_OVERRIDE; + Widget_Node(); + Node *make(Strategy strategy) override; + void open() override; const char *extra_code(int n) const {return extra_code_[n];} void extra_code(int n,const char *); @@ -106,27 +105,27 @@ public: virtual int textstuff(int what, Fl_Font &, int &, Fl_Color &); virtual Fl_Menu_Item *subtypes(); - ID id() const FL_OVERRIDE { return ID_Widget_; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Widget_) ? true : super::is_a(inID); } - int is_widget() const FL_OVERRIDE; - int is_true_widget() const FL_OVERRIDE { return 1; } - int is_public() const FL_OVERRIDE; + Type type() const override { return Type::Widget_; } + bool is_a(Type inType) const override { return (inType==Type::Widget_) ? true : super::is_a(inType); } + int is_widget() const override; + int is_true_widget() const override { return 1; } + int is_public() const override; - void write_properties(fld::io::Project_Writer &f) FL_OVERRIDE; - void read_property(fld::io::Project_Reader &f, const char *) FL_OVERRIDE; - int read_fdesign(const char*, const char*) FL_OVERRIDE; + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int read_fdesign(const char*, const char*) override; - Fl_Widget *enter_live_mode(int top=0) FL_OVERRIDE; + Fl_Widget *enter_live_mode(int top=0) override; Fl_Widget *propagate_live_mode(Fl_Group* grp); - void leave_live_mode() FL_OVERRIDE; - void copy_properties() FL_OVERRIDE; + void leave_live_mode() override; + void copy_properties() override; virtual void ideal_size(int &w, int &h); - ~Fl_Widget_Type(); + ~Widget_Node(); void redraw(); }; extern Fl_Window *the_panel; -#endif // _FLUID_FL_WIDGET_TYPE_H +#endif // FLUID_NODES_WIDGET_NODE_H diff --git a/fluid/nodes/Fl_Window_Type.cxx b/fluid/nodes/Window_Node.cxx similarity index 73% rename from fluid/nodes/Fl_Window_Type.cxx rename to fluid/nodes/Window_Node.cxx index 3f68f7980..d6cbe80e6 100644 --- a/fluid/nodes/Fl_Window_Type.cxx +++ b/fluid/nodes/Window_Node.cxx @@ -1,9 +1,5 @@ // -// 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. +// Window Node code file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -18,18 +14,23 @@ // https://www.fltk.org/bugs.php // -#include "nodes/Fl_Window_Type.h" +// +// 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. -#include "app/Fd_Snap_Action.h" -#include "app/fluid.h" -#include "app/project.h" -#include "app/undo.h" +#include "nodes/Window_Node.h" + +#include "app/Snap_Action.h" +#include "Fluid.h" +#include "Project.h" +#include "proj/undo.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" #include "io/Code_Writer.h" #include "nodes/factory.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Grid_Type.h" +#include "nodes/Group_Node.h" +#include "nodes/Grid_Node.h" #include "panels/settings_panel.h" #include "panels/widget_panel.h" #include "widgets/Node_Browser.h" @@ -48,46 +49,47 @@ #include #include #include +#undef min +#undef max +#include extern Fl_Window *the_panel; extern void draw_width(int x, int y, int r, Fl_Align a); extern void draw_height(int x, int y, int b, Fl_Align a); -extern Fl_Preferences fluid_prefs; - // Update the XYWH values in the widget panel... static void update_xywh() { if (current_widget && current_widget->is_widget()) { - Fl_Widget *o = ((Fl_Widget_Type *)current_widget)->o; + Fl_Widget *o = ((Widget_Node *)current_widget)->o; widget_x_input->value(o->x()); widget_y_input->value(o->y()); widget_w_input->value(o->w()); widget_h_input->value(o->h()); - if (Fl_Flex_Type::parent_is_flex(current_widget)) { - widget_flex_size->value(Fl_Flex_Type::size(current_widget)); - widget_flex_fixed->value(Fl_Flex_Type::is_fixed(current_widget)); + if (Flex_Node::parent_is_flex(current_widget)) { + widget_flex_size->value(Flex_Node::size(current_widget)); + widget_flex_fixed->value(Flex_Node::is_fixed(current_widget)); } } } void i18n_type_cb(Fl_Choice *c, void *v) { if (v == LOAD) { - c->value(g_project.i18n_type); + c->value(static_cast(Fluid.proj.i18n_type)); } else { - undo_checkpoint(); - g_project.i18n_type = static_cast(c->value()); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_type = static_cast(c->value()); + Fluid.proj.set_modflag(1); } - switch (g_project.i18n_type) { - case FD_I18N_NONE : /* None */ + switch (Fluid.proj.i18n_type) { + case fld::I18n_Type::NONE : /* None */ i18n_gnu_group->hide(); i18n_posix_group->hide(); break; - case FD_I18N_GNU : /* GNU gettext */ + case fld::I18n_Type::GNU : /* GNU gettext */ i18n_gnu_group->show(); i18n_posix_group->hide(); break; - case FD_I18N_POSIX : /* POSIX cat */ + case fld::I18n_Type::POSIX : /* POSIX cat */ i18n_gnu_group->hide(); i18n_posix_group->show(); break; @@ -109,9 +111,9 @@ void show_settings_cb(Fl_Widget *, void *) { //////////////////////////////////////////////////////////////// Fl_Menu_Item window_type_menu[] = { - {"Single",0,0,(void*)FL_WINDOW}, - {"Double",0,0,(void*)(FL_DOUBLE_WINDOW)}, - {0}}; + {"Single",0,nullptr,(void*)FL_WINDOW}, + {"Double",0,nullptr,(void*)(FL_DOUBLE_WINDOW)}, + {nullptr}}; static int overlays_invisible; @@ -119,17 +121,17 @@ static int overlays_invisible; // an overlay for the fluid ui, and special-cases the FL_NO_BOX. class Overlay_Window : public Fl_Overlay_Window { - void draw() FL_OVERRIDE; - void draw_overlay() FL_OVERRIDE; + void draw() override; + void draw_overlay() override; static void close_cb(Overlay_Window *self, void*); public: - Fl_Window_Type *window; - int handle(int) FL_OVERRIDE; + Window_Node *window; + int handle(int) override; Overlay_Window(int W,int H) : Fl_Overlay_Window(W,H) { - Fl_Group::current(0); + Fl_Group::current(nullptr); callback((Fl_Callback*)close_cb); } - void resize(int,int,int,int) FL_OVERRIDE; + void resize(int,int,int,int) override; uchar *read_image(int &ww, int &hh); }; @@ -140,7 +142,7 @@ public: */ void Overlay_Window::close_cb(Overlay_Window *self, void*) { if (self->visible()) - set_modflag(1, -2); + Fluid.proj.set_modflag(1, -2); self->hide(); } @@ -164,7 +166,7 @@ void Overlay_Window::draw() { fl_rectf(X,Y,CHECKSIZE,CHECKSIZE); } } - if (show_ghosted_outline) { + if (Fluid.show_ghosted_outline) { Fl_Box_Draw_F *old_flat_box = Fl::get_boxtype(FL_FLAT_BOX); Fl::set_boxtype(FL_FLAT_BOX, fd_flat_box_ghosted, 0, 0, 0, 0); Fl_Overlay_Window::draw(); @@ -174,12 +176,10 @@ void Overlay_Window::draw() { } } -extern Fl_Window *main_window; - // Read an image of the overlay window uchar *Overlay_Window::read_image(int &ww, int &hh) { // Create an off-screen buffer for the window... - //main_window->make_current(); + //Fluid.main_window->make_current(); make_current(); ww = w(); @@ -197,13 +197,13 @@ uchar *Overlay_Window::read_image(int &ww, int &hh) { draw(); // Read the screen image... - pixels = fl_read_image(0, 0, 0, ww, hh); + pixels = fl_read_image(nullptr, 0, 0, ww, hh); fl_end_offscreen(); // Cleanup and return... fl_delete_offscreen(offscreen); - main_window->make_current(); + Fluid.main_window->make_current(); return pixels; } @@ -228,22 +228,22 @@ int Overlay_Window::handle(int e) { \param[in] strategy is Strategy::AS_LAST_CHILD or Strategy::AFTER_CURRENT \return new node */ -Fl_Type *Fl_Window_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Window_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; - while (p && (!p->is_code_block() || p->is_a(ID_Widget_Class))) { + while (p && (!p->is_code_block() || p->is_a(Type::Widget_Class))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } if (!p) { fl_message("Please select a function"); - return 0; + return nullptr; } - Fl_Window_Type *myo = new Fl_Window_Type(); + Window_Node *myo = new Window_Node(); if (!this->o) {// template widget this->o = new Fl_Window(100,100); - Fl_Group::current(0); + Fl_Group::current(nullptr); } myo->factory = this; myo->drag = 0; @@ -258,24 +258,24 @@ Fl_Type *Fl_Window_Type::make(Strategy strategy) { return myo; } -void Fl_Window_Type::add_child(Fl_Type* cc, Fl_Type* before) { +void Window_Node::add_child(Node* cc, Node* before) { if (!cc->is_widget()) return; - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; - Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + Widget_Node* c = (Widget_Node*)cc; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; ((Fl_Window*)o)->insert(*(c->o), b); o->redraw(); } -void Fl_Window_Type::remove_child(Fl_Type* cc) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; +void Window_Node::remove_child(Node* cc) { + Widget_Node* c = (Widget_Node*)cc; ((Fl_Window*)o)->remove(c->o); o->redraw(); } -void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { - Fl_Widget_Type* c = (Fl_Widget_Type*)cc; +void Window_Node::move_child(Node* cc, Node* before) { + Widget_Node* c = (Widget_Node*)cc; ((Fl_Window*)o)->remove(c->o); - Fl_Widget* b = before ? ((Fl_Widget_Type*)before)->o : 0; + Fl_Widget* b = before ? ((Widget_Node*)before)->o : nullptr; ((Fl_Window*)o)->insert(*(c->o), b); o->redraw(); } @@ -284,13 +284,13 @@ void Fl_Window_Type::move_child(Fl_Type* cc, Fl_Type* before) { /** \brief Show the Window Type editor window without setting the modified flag. - \see Fl_Window_Type::open() + \see Window_Node::open() */ -void Fl_Window_Type::open_() { +void Window_Node::open_() { Overlay_Window *w = (Overlay_Window *)o; if (w->shown()) { w->show(); - Fl_Widget_Type::open(); + Widget_Node::open(); } else { Fl_Widget *p = w->resizable(); if (!p) w->resizable(w); @@ -304,18 +304,18 @@ void Fl_Window_Type::open_() { \brief Show the Window Type editor window and set the modified flag if needed. Double-click on window widget shows the window, or if already shown, it shows the control panel. - \see Fl_Window_Type::open_() + \see Window_Node::open_() */ -void Fl_Window_Type::open() { +void Window_Node::open() { Overlay_Window *w = (Overlay_Window *)o; if (!w->visible()) { - set_modflag(1, -2); + Fluid.proj.set_modflag(1, -2); } open_(); } // Read an image of the window -uchar *Fl_Window_Type::read_image(int &ww, int &hh) { +uchar *Window_Node::read_image(int &ww, int &hh) { Overlay_Window *w = (Overlay_Window *)o; int hidden = !w->shown(); @@ -328,91 +328,28 @@ uchar *Fl_Window_Type::read_image(int &ww, int &hh) { return idata; } -void Fl_Window_Type::ideal_size(int &w, int &h) { +void Window_Node::ideal_size(int &w, int &h) { w = 480; h = 320; - if (main_window) { + if (Fluid.main_window) { int sx, sy, sw, sh; - Fl_Window *win = main_window; + Fl_Window *win = Fluid.main_window; int screen = Fl::screen_num(win->x(), win->y()); Fl::screen_work_area(sx, sy, sw, sh, screen); - w = fd_min(w, sw*3/4); h = fd_min(h, sh*3/4); + w = std::min(w, sw*3/4); h = std::min(h, sh*3/4); } - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } -// control panel items: - -void modal_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) {i->hide(); return;} - i->show(); - i->value(((Fl_Window_Type *)current_widget)->modal); - } else { - undo_checkpoint(); - ((Fl_Window_Type *)current_widget)->modal = i->value(); - set_modflag(1); - } -} - -void non_modal_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) {i->hide(); return;} - i->show(); - i->value(((Fl_Window_Type *)current_widget)->non_modal); - } else { - undo_checkpoint(); - ((Fl_Window_Type *)current_widget)->non_modal = i->value(); - set_modflag(1); - } -} - -void border_cb(Fl_Light_Button* i, void* v) { - if (v == LOAD) { - if (!current_widget->is_a(ID_Window)) {i->hide(); return;} - i->show(); - i->value(((Fl_Window*)(current_widget->o))->border()); - } else { - undo_checkpoint(); - ((Fl_Window*)(current_widget->o))->border(i->value()); - set_modflag(1); - } -} - -void xclass_cb(Fl_Input* i, void* v) { - if (v == LOAD) { - if (current_widget->is_a(ID_Window)) { - i->show(); - i->parent()->show(); - i->value(((Fl_Window_Type *)current_widget)->xclass); - } else { - i->hide(); - i->parent()->hide(); // hides the "X Class:" label as well - } - } else { - int mod = 0; - undo_checkpoint(); - for (Fl_Type *o = Fl_Type::first; o; o = o->next) { - if (o->selected && o->is_a(ID_Window)) { - mod = 1; - Fl_Window_Type *wt = (Fl_Window_Type *)o; - storestring(i->value(), wt->xclass); - ((Fl_Window*)(wt->o))->xclass(wt->xclass); - } - } - if (mod) set_modflag(1); - } -} //////////////////////////////////////////////////////////////// -void Fl_Window_Type::setlabel(const char *n) { +Window_Node Window_Node::prototype; + +void Window_Node::setlabel(const char *n) { if (o) ((Fl_Window *)o)->label(n); } -// make() is called on this widget when user picks window off New menu: -Fl_Window_Type Fl_Window_type; - // Resize from window manager... void Overlay_Window::resize(int X,int Y,int W,int H) { // Make sure we don't create undo checkpoints if the window does not actually change. @@ -420,20 +357,20 @@ void Overlay_Window::resize(int X,int Y,int W,int H) { if (X!=x() || Y!=y() || W!=w() || H!=h()) { // Set a checkpoint on the first resize event, ignore further resizes until // a different type of checkpoint is triggered. - if (undo_checkpoint_once(kUndoWindowResize)) - set_modflag(1); + if (Fluid.proj.undo.checkpoint(fld::proj::Undo::OnceType::WINDOW_RESIZE)) + Fluid.proj.set_modflag(1); } Fl_Widget* t = resizable(); - if (Fl_Type::allow_layout == 0) { - resizable(0); + if (Fluid.proj.tree.allow_layout == 0) { + resizable(nullptr); } // do not set the mod flag if the window was not resized. In FLUID, all // windows are opened without a given x/y position, so modifying x/y // should not mark the project as dirty if (W!=w() || H!=h()) - set_modflag(1); + Fluid.proj.set_modflag(1); Fl_Overlay_Window::resize(X,Y,W,H); resizable(t); @@ -442,7 +379,7 @@ void Overlay_Window::resize(int X,int Y,int W,int H) { // calculate actual move by moving mouse position (mx,my) to // nearest multiple of gridsize, and snap to original position -void Fl_Window_Type::newdx() { +void Window_Node::newdx() { int mydx, mydy; mydx = mx-x1; mydy = my-y1; @@ -457,16 +394,16 @@ void Fl_Window_Type::newdx() { 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 (Fluid.show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) { + Node *selection = nullptr; // special power for the first selected widget + for (Node *q=next; q && q->level>level; q = q->next) { if (q->selected && q->is_true_widget()) { 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); + fld::app::Snap_Data data = { mydx, mydy, bx, by, br, bt, drag, 4, 4, mydx, mydy, (Widget_Node*)selection, this }; + fld::app::Snap_Action::check_all(data); if (data.x_dist < 4) mydx = data.dx_out; if (data.y_dist < 4) mydy = data.dy_out; } @@ -478,7 +415,7 @@ void Fl_Window_Type::newdx() { } // Move a widget according to dx and dy calculated above -void Fl_Window_Type::newposition(Fl_Widget_Type *myo,int &X,int &Y,int &R,int &T) { +void Window_Node::newposition(Widget_Node *myo,int &X,int &Y,int &R,int &T) { X = myo->o->x(); Y = myo->o->y(); R = X+myo->o->w(); @@ -548,10 +485,10 @@ void fd_hatch(int x, int y, int w, int h, int size=6, int offset=0, int pad=3) { \param[in] group check all children of this group \param[in] x, y, w, h bounding box of this group */ -void Fl_Window_Type::draw_out_of_bounds(Fl_Widget_Type *group, int x, int y, int w, int h) { - for (Fl_Type *p = group->next; p && p->level>group->level; p = p->next) { +void Window_Node::draw_out_of_bounds(Widget_Node *group, int x, int y, int w, int h) { + for (Node *p = group->next; p && p->level>group->level; p = p->next) { if (p->level == group->level+1 && p->is_true_widget()) { - Fl_Widget *o = ((Fl_Widget_Type*)p)->o; + Fl_Widget *o = ((Widget_Node*)p)->o; if (o->x() < x) fd_hatch(o->x(), o->y(), x-o->x(), o->h()); if (o->y() < y) fd_hatch(o->x(), o->y(), o->w(), y-o->y()); if (o->x()+o->w() > x+w) fd_hatch(x+w, o->y(), (o->x()+o->w())-(x+w), o->h()); @@ -563,14 +500,14 @@ void Fl_Window_Type::draw_out_of_bounds(Fl_Widget_Type *group, int x, int y, int /** \brief Draw a hatch pattern for all groups that have out of bounds children. */ -void Fl_Window_Type::draw_out_of_bounds() { +void Window_Node::draw_out_of_bounds() { // get every group in the hierarchy, then draw any overlap of a direct child with that group fl_color(FL_DARK_RED); draw_out_of_bounds(this, 0, 0, o->w(), o->h()); - for (Fl_Type *q=next; q && q->level>level; q = q->next) { + for (Node *q=next; q && q->level>level; q = q->next) { // don't do this for Fl_Scroll (which we currently can't handle in FLUID anyway) - if (q->is_a(ID_Group) && !q->is_a(ID_Scroll)) { - Fl_Widget_Type *w = (Fl_Widget_Type*)q; + if (q->is_a(Type::Group) && !q->is_a(Type::Scroll)) { + Widget_Node *w = (Widget_Node*)q; draw_out_of_bounds(w, w->o->x(), w->o->y(), w->o->w(), w->o->h()); } } @@ -580,25 +517,25 @@ void Fl_Window_Type::draw_out_of_bounds() { /** \brief Compare all children in the same level and hatch overlapping areas. */ -void Fl_Window_Type::draw_overlaps() { +void Window_Node::draw_overlaps() { fl_color(FL_DARK_YELLOW); // loop through all widgets in this window - for (Fl_Type *q=next; q && q->level>level; q = q->next) { + for (Node *q=next; q && q->level>level; q = q->next) { // is it a valid widget if (q->is_true_widget()) { - Fl_Widget_Type *w = (Fl_Widget_Type*)q; + Widget_Node *w = (Widget_Node*)q; // is the widget visible if (w->o->visible()) { int x = w->o->x(), y = w->o->y(); int r = x + w->o->w(), b = y + w->o->h(); - for (Fl_Type *p=q->next; p && p->level>=q->level; p = p->next) { + for (Node *p=q->next; p && p->level>=q->level; p = p->next) { if (p->level==q->level && p->is_true_widget()) { - Fl_Widget_Type *wp = (Fl_Widget_Type*)p; + Widget_Node *wp = (Widget_Node*)p; if (wp->o->visible()) { - int px = fd_max(x, wp->o->x()); - int py = fd_max(y, wp->o->y()); - int pr = fd_min(r, wp->o->x() + wp->o->w()); - int pb = fd_min(b, wp->o->y() + wp->o->h()); + int px = std::max(x, wp->o->x()); + int py = std::max(y, wp->o->y()); + int pr = std::min(r, wp->o->x() + wp->o->w()); + int pb = std::min(b, wp->o->y() + wp->o->h()); if (pr > px && pb > py) fd_hatch(px, py, pr-px, pb-py); } @@ -613,14 +550,14 @@ void Fl_Window_Type::draw_overlaps() { fl_color(FL_RED); } -void Fl_Window_Type::draw_overlay() { +void Window_Node::draw_overlay() { if (recalc) { bx = o->w(); by = o->h(); br = 0; bt = 0; numselected = 0; - for (Fl_Type *q=next; q && q->level>level; q=q->next) + for (Node *q=next; q && q->level>level; q=q->next) if (q->selected && q->is_true_widget()) { numselected++; - Fl_Widget_Type* myo = (Fl_Widget_Type*)q; + Widget_Node* myo = (Widget_Node*)q; if (myo->o->x() < bx) bx = myo->o->x(); if (myo->o->y() < by) by = myo->o->y(); if (myo->o->x()+myo->o->w() > br) br = myo->o->x()+myo->o->w(); @@ -637,7 +574,7 @@ void Fl_Window_Type::draw_overlay() { } if (overlays_invisible && !drag) return; - if (show_restricted) { + if (Fluid.show_restricted) { draw_out_of_bounds(); draw_overlaps(); // TODO: for Fl_Tile, find all areas that are not covered by visible children @@ -648,31 +585,31 @@ 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; // special power for the first selected widget - for (Fl_Type *q=next; q && q->level>level; q = q->next) + Node *selection = nullptr; // special power for the first selected widget + for (Node *q=next; q && q->level>level; q = q->next) if (q->selected && q->is_true_widget()) { if (!selection) selection = q; - Fl_Widget_Type* myo = (Fl_Widget_Type*)q; + Widget_Node* myo = (Widget_Node*)q; int x,y,r,t; newposition(myo,x,y,r,t); - if (show_guides) { + if (Fluid.show_guides) { // If we are in a drag operation, and the parent is a grid, show the grid overlay - if (drag && q->parent && q->parent->is_a(ID_Grid)) { - Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Fl_Grid_Type*)q->parent)->o); + if (drag && q->parent && q->parent->is_a(Type::Grid)) { + Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Grid_Node*)q->parent)->o); grid->draw_overlay(); } } - if (!show_guides || !drag || numselected != 1) { - if (Fl_Flex_Type::parent_is_flex(q) && Fl_Flex_Type::is_fixed(q)) { - Fl_Flex *flex = ((Fl_Flex*)((Fl_Flex_Type*)q->parent)->o); + if (!Fluid.show_guides || !drag || numselected != 1) { + if (Flex_Node::parent_is_flex(q) && Flex_Node::is_fixed(q)) { + Fl_Flex *flex = ((Fl_Flex*)((Flex_Node*)q->parent)->o); Fl_Widget *wgt = myo->o; if (flex->horizontal()) { draw_width(wgt->x(), wgt->y()+15, wgt->x()+wgt->w(), FL_ALIGN_CENTER); } else { draw_height(wgt->x()+15, wgt->y(), wgt->y()+wgt->h(), FL_ALIGN_CENTER); } - } else if (q->is_a(ID_Grid)) { - Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Fl_Grid_Type*)q)->o); + } else if (q->is_a(Type::Grid)) { + Fl_Grid_Proxy *grid = ((Fl_Grid_Proxy*)((Grid_Node*)q)->o); grid->draw_overlay(); } fl_rect(x,y,r-x,t-y); @@ -712,17 +649,15 @@ void Fl_Window_Type::draw_overlay() { 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); + if (Fluid.show_guides && (drag & (FD_DRAG|FD_TOP|FD_LEFT|FD_BOTTOM|FD_RIGHT))) { + fld::app::Snap_Data data = { dx, dy, sx, sy, sr, st, drag, 4, 4, dx, dy, (Widget_Node*)selection, this}; + fld::app::Snap_Action::draw_all(data); } } -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"); +void Window_Node::fix_overlay() { + Fluid.overlay_item->label("Hide O&verlays"); if (overlay_button) overlay_button->label("Hide &Overlays"); overlays_invisible = 0; recalc = 1; @@ -730,45 +665,45 @@ void Fl_Window_Type::fix_overlay() { } // check if we must redraw any parent of tabs/wizard type -void check_redraw_corresponding_parent(Fl_Type *s) { - Fl_Widget_Type * prev_parent = 0; +void check_redraw_corresponding_parent(Node *s) { + Widget_Node * prev_parent = nullptr; if( !s || !s->selected || !s->is_widget()) return; - for (Fl_Type *i=s; i && i->parent; i=i->parent) { - if (i->is_a(ID_Group) && prev_parent) { - if (i->is_a(ID_Tabs)) { - ((Fl_Tabs*)((Fl_Widget_Type*)i)->o)->value(prev_parent->o); + for (Node *i=s; i && i->parent; i=i->parent) { + if (i->is_a(Type::Group) && prev_parent) { + if (i->is_a(Type::Tabs)) { + ((Fl_Tabs*)((Widget_Node*)i)->o)->value(prev_parent->o); return; } - if (i->is_a(ID_Wizard)) { - ((Fl_Wizard*)((Fl_Widget_Type*)i)->o)->value(prev_parent->o); + if (i->is_a(Type::Wizard)) { + ((Fl_Wizard*)((Widget_Node*)i)->o)->value(prev_parent->o); return; } } - if (i->is_a(ID_Group) && s->is_widget()) - prev_parent = (Fl_Widget_Type*)i; + if (i->is_a(Type::Group) && s->is_widget()) + prev_parent = (Widget_Node*)i; } } // do that for every window (when selected set changes): void redraw_overlays() { - for (Fl_Type *o=Fl_Type::first; o; o=o->next) - if (o->is_a(ID_Window)) ((Fl_Window_Type*)o)->fix_overlay(); + for (Node *o=Fluid.proj.tree.first; o; o=o->next) + if (o->is_a(Type::Window)) ((Window_Node*)o)->fix_overlay(); } void toggle_overlays(Fl_Widget *,void *) { overlays_invisible = !overlays_invisible; if (overlays_invisible) { - overlay_item->label("Show O&verlays"); + Fluid.overlay_item->label("Show O&verlays"); if (overlay_button) overlay_button->label("Show &Overlays"); } else { - overlay_item->label("Hide O&verlays"); + Fluid.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_a(ID_Window)) { - Fl_Widget_Type* w = (Fl_Widget_Type*)o; + for (Node *o=Fluid.proj.tree.first; o; o=o->next) + if (o->is_a(Type::Window)) { + Widget_Node* w = (Widget_Node*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } @@ -779,19 +714,19 @@ void toggle_overlays(Fl_Widget *,void *) { dialog. */ void toggle_guides(Fl_Widget *,void *) { - show_guides = !show_guides; - fluid_prefs.set("show_guides", show_guides); + Fluid.show_guides = !Fluid.show_guides; + Fluid.preferences.set("Fluid.show_guides", Fluid.show_guides); - if (show_guides) - guides_item->label("Hide Guides"); + if (Fluid.show_guides) + Fluid.guides_item->label("Hide Guides"); else - guides_item->label("Show Guides"); + Fluid.guides_item->label("Show Guides"); if (guides_button) - guides_button->value(show_guides); + guides_button->value(Fluid.show_guides); - for (Fl_Type *o=Fl_Type::first; o; o=o->next) { - if (o->is_a(ID_Window)) { - Fl_Widget_Type* w = (Fl_Widget_Type*)o; + for (Node *o=Fluid.proj.tree.first; o; o=o->next) { + if (o->is_a(Type::Window)) { + Widget_Node* w = (Widget_Node*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } @@ -802,7 +737,7 @@ void toggle_guides(Fl_Widget *,void *) { This is called from the check button in the Settings dialog. */ void toggle_guides_cb(Fl_Check_Button *o, void *v) { - toggle_guides(NULL, NULL); + toggle_guides(nullptr, nullptr); } /** @@ -811,19 +746,19 @@ void toggle_guides_cb(Fl_Check_Button *o, void *v) { dialog. */ void toggle_restricted(Fl_Widget *,void *) { - show_restricted = !show_restricted; - fluid_prefs.set("show_restricted", show_restricted); + Fluid.show_restricted = !Fluid.show_restricted; + Fluid.preferences.set("Fluid.show_restricted", Fluid.show_restricted); - if (show_restricted) - restricted_item->label("Hide Restricted"); + if (Fluid.show_restricted) + Fluid.restricted_item->label("Hide Restricted"); else - restricted_item->label("Show Restricted"); + Fluid.restricted_item->label("Show Restricted"); if (restricted_button) - restricted_button->value(show_restricted); + restricted_button->value(Fluid.show_restricted); - for (Fl_Type *o=Fl_Type::first; o; o=o->next) { - if (o->is_a(ID_Window)) { - Fl_Widget_Type* w = (Fl_Widget_Type*)o; + for (Node *o=Fluid.proj.tree.first; o; o=o->next) { + if (o->is_a(Type::Window)) { + Widget_Node* w = (Widget_Node*)o; ((Overlay_Window*)(w->o))->redraw_overlay(); } } @@ -833,11 +768,11 @@ void toggle_restricted(Fl_Widget *,void *) { \brief User changes settings to show low contrast groups with a ghosted outline. */ void toggle_ghosted_outline_cb(Fl_Check_Button *,void *) { - show_ghosted_outline = !show_ghosted_outline; - fluid_prefs.set("show_ghosted_outline", show_ghosted_outline); - for (Fl_Type *o=Fl_Type::first; o; o=o->next) { - if (o->is_a(ID_Window)) { - Fl_Widget_Type* w = (Fl_Widget_Type*)o; + Fluid.show_ghosted_outline = !Fluid.show_ghosted_outline; + Fluid.preferences.set("Fluid.show_ghosted_outline", Fluid.show_ghosted_outline); + for (Node *o=Fluid.proj.tree.first; o; o=o->next) { + if (o->is_a(Type::Window)) { + Widget_Node* w = (Widget_Node*)o; ((Overlay_Window*)(w->o))->redraw(); } } @@ -848,16 +783,15 @@ void toggle_ghosted_outline_cb(Fl_Check_Button *,void *) { This is called from the check button in the Settings dialog. */ void toggle_restricted_cb(Fl_Check_Button *o, void *v) { - toggle_restricted(NULL, NULL); + toggle_restricted(nullptr, nullptr); } -extern void select(Fl_Type *,int); -extern void select_only(Fl_Type *); +extern void select(Node *,int); +extern void select_only(Node *); extern void deselect(); -extern Fl_Type* in_this_only; -extern void fix_group_size(Fl_Type *t); +extern Node* in_this_only; +extern void fix_group_size(Node *t); -extern Fl_Menu_Item Main_Menu[]; extern Fl_Menu_Item New_Menu[]; /** @@ -875,30 +809,30 @@ extern Fl_Menu_Item New_Menu[]; \param[in] key if key is not 0, it contains the code of the keypress that caused this call. This must only be set when handle FL_KEYBOARD events. */ -void Fl_Window_Type::moveallchildren(int key) +void Window_Node::moveallchildren(int key) { bool update_widget_panel = false; - undo_checkpoint(); - Fl_Type *i; + Fluid.proj.undo.checkpoint(); + Node *i; for (i=next; i && i->level>level;) { if (i->selected && i->is_true_widget()) { - Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + Widget_Node* myo = (Widget_Node*)i; int x,y,r,t,ow=myo->o->w(),oh=myo->o->h(); newposition(myo,x,y,r,t); - if (myo->is_a(ID_Flex) || myo->is_a(ID_Grid)) { + if (myo->is_a(Type::Flex) || myo->is_a(Type::Grid)) { // Flex and Grid need to be able to layout their children. - allow_layout++; + Fluid.proj.tree.allow_layout++; myo->o->resize(x,y,r-x,t-y); - allow_layout--; + Fluid.proj.tree.allow_layout--; } else { // Other groups are resized without affecting their children, however // they move their children if the entire widget is moved. myo->o->resize(x,y,r-x,t-y); } - if (Fl_Flex_Type::parent_is_flex(myo)) { + if (Flex_Node::parent_is_flex(myo)) { // If the border of a Flex child is move, give that child a fixed size // so that the user request is reflected. - Fl_Flex_Type* ft = (Fl_Flex_Type*)myo->parent; + Flex_Node* ft = (Flex_Node*)myo->parent; Fl_Flex* f = (Fl_Flex*)ft->o; if (key) { ft->keyboard_move_child(myo, key); @@ -918,11 +852,11 @@ void Fl_Window_Type::moveallchildren(int key) } } // relayout the Flex parent - allow_layout++; + Fluid.proj.tree.allow_layout++; f->layout(); - allow_layout--; - } else if (myo->parent && myo->parent->is_a(ID_Grid)) { - Fl_Grid_Type* gt = (Fl_Grid_Type*)myo->parent; + Fluid.proj.tree.allow_layout--; + } else if (myo->parent && myo->parent->is_a(Type::Grid)) { + Grid_Node* gt = (Grid_Node*)myo->parent; Fl_Grid* g = (Fl_Grid*)gt->o; if (key) { gt->keyboard_move_child(myo, key); @@ -933,19 +867,19 @@ void Fl_Window_Type::moveallchildren(int key) gt->child_resized(myo); } } - allow_layout++; + Fluid.proj.tree.allow_layout++; g->layout(); - allow_layout--; + Fluid.proj.tree.allow_layout--; update_widget_panel = true; - } else if (myo->parent && myo->parent->is_a(ID_Group)) { - Fl_Group_Type* gt = (Fl_Group_Type*)myo->parent; + } else if (myo->parent && myo->parent->is_a(Type::Group)) { + Group_Node* gt = (Group_Node*)myo->parent; ((Fl_Group*)gt->o)->init_sizes(); } // move all the children, whether selected or not: - Fl_Type* p; + Node* p; for (p = myo->next; p && p->level>myo->level; p = p->next) - if (p->is_true_widget() && !myo->is_a(ID_Flex) && !myo->is_a(ID_Grid)) { - Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p; + if (p->is_true_widget() && !myo->is_a(Type::Flex) && !myo->is_a(Type::Grid)) { + Widget_Node* myo2 = (Widget_Node*)p; int X,Y,R,T; newposition(myo2,X,Y,R,T); myo2->o->resize(X,Y,R-X,T-Y); @@ -960,7 +894,7 @@ void Fl_Window_Type::moveallchildren(int key) o->redraw(); recalc = 1; ((Overlay_Window *)(this->o))->redraw_overlay(); - set_modflag(1); + Fluid.proj.set_modflag(1); dx = dy = 0; update_xywh(); @@ -969,11 +903,11 @@ void Fl_Window_Type::moveallchildren(int key) } } -int Fl_Window_Type::popupx = 0x7FFFFFFF; // mark as invalid (MAXINT) -int Fl_Window_Type::popupy = 0x7FFFFFFF; +int Window_Node::popupx = 0x7FFFFFFF; // mark as invalid (MAXINT) +int Window_Node::popupy = 0x7FFFFFFF; -int Fl_Window_Type::handle(int event) { - static Fl_Type* selection = NULL; +int Window_Node::handle(int event) { + static Node* selection = nullptr; switch (event) { case FL_DND_ENTER: // printf("DND enter\n"); @@ -982,9 +916,9 @@ int Fl_Window_Type::handle(int event) { { // find the innermost item clicked on: selection = this; - for (Fl_Type* i=next; i && i->level>level; i=i->next) - if (i->is_a(ID_Group)) { - Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + for (Node* i=next; i && i->level>level; i=i->next) + if (i->is_a(Type::Group)) { + Widget_Node* myo = (Widget_Node*)i; if (Fl::event_inside(myo->o) && myo->o->visible_r()) { selection = myo; if (Fl::event_clicks()==1) @@ -1004,12 +938,12 @@ int Fl_Window_Type::handle(int event) { return 1; case FL_PASTE: // printf("DND paste\n"); - { Fl_Type *prototype = typename_to_prototype(Fl::event_text()); - if (prototype==NULL) { + { Node *prototype = typename_to_prototype(Fl::event_text()); + if (prototype==nullptr) { // it's not a FLUID type, so it could be the filename of an image const char *cfn = Fl::event_text(); // printf("DND is filename %s?\n", cfn); - if ((cfn == NULL) || (*cfn == 0)) return 0; + if ((cfn == nullptr) || (*cfn == 0)) return 0; if (strlen(cfn) >= FL_PATH_MAX) return 0; char fn[FL_PATH_MAX+1]; // some platform prepend "file://" or "computer://" or similar text @@ -1033,19 +967,19 @@ int Fl_Window_Type::handle(int event) { if (!img || (img->ld() < 0)) return 0; // ok, so it is an image - now add it as image() or deimage() to the widget // printf("DND check for target %s\n", fn); - Fl_Widget_Type *tgt = NULL; - for (Fl_Type* i=next; i && i->level>level; i=i->next) { + Widget_Node *tgt = nullptr; + for (Node* i=next; i && i->level>level; i=i->next) { if (i->is_widget()) { - Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + Widget_Node* myo = (Widget_Node*)i; if (Fl::event_inside(myo->o) && myo->o->visible_r()) tgt = myo; } } if (tgt) { char rel[FL_PATH_MAX+1]; - enter_project_dir(); + Fluid.proj.enter_project_dir(); fl_filename_relative(rel, FL_PATH_MAX, fn); - leave_project_dir(); + Fluid.proj.leave_project_dir(); // printf("DND image = %s\n", fn); if (Fl::get_key(FL_Alt_L) || Fl::get_key(FL_Alt_R)) { //if (Fl::event_alt()) { // TODO: X11/Wayland does not set the e_state on DND events @@ -1069,21 +1003,21 @@ int Fl_Window_Type::handle(int event) { // If the selected widget at dnd start and the drop target are the same, // or in the same group, add after selection. Otherwise, just add // at the end of the selected group. - if ( Fl_Type::current_dnd->group() + if ( Fluid.proj.tree.current_dnd->group() && selection && selection->group() - && Fl_Type::current_dnd->group()==selection->group()) + && Fluid.proj.tree.current_dnd->group()==selection->group()) { - Fl_Type *cc = Fl_Type::current; - Fl_Type::current = Fl_Type::current_dnd; + Node *cc = Fluid.proj.tree.current; + Fluid.proj.tree.current = Fluid.proj.tree.current_dnd; add_new_widget_from_user(prototype, Strategy::AS_LAST_CHILD); - Fl_Type::current = cc; + Fluid.proj.tree.current = cc; } else { add_new_widget_from_user(prototype, Strategy::AS_LAST_CHILD); } popupx = 0x7FFFFFFF; popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) - in_this_only = NULL; - widget_browser->display(Fl_Type::current); + in_this_only = nullptr; + widget_browser->display(Fluid.proj.tree.current); widget_browser->rebuild(); return 1; } @@ -1099,14 +1033,14 @@ int Fl_Window_Type::handle(int event) { const Fl_Menu_Item* m = New_Menu->popup(mx,my,"New",myprev); if (m && m->callback()) {myprev = m; m->do_callback(this->o);} popupx = 0x7FFFFFFF; popupy = 0x7FFFFFFF; // mark as invalid (MAXINT) - in_this_only = 0; + in_this_only = nullptr; return 1; } // find the innermost item clicked on: selection = this; - {for (Fl_Type* i=next; i && i->level>level; i=i->next) + {for (Node* i=next; i && i->level>level; i=i->next) if (i->is_true_widget()) { - Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + Widget_Node* myo = (Widget_Node*)i; for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) if (!o1->visible()) goto CONTINUE2; if (Fl::event_inside(myo->o)) { @@ -1126,7 +1060,7 @@ int Fl_Window_Type::handle(int event) { if (!drag) drag = FD_DRAG; } // do object-specific selection of other objects: - {Fl_Type* t = selection->click_test(mx, my); + {Node* t = selection->click_test(mx, my); if (t) { //if (t == selection) return 1; // indicates mouse eaten w/o change if (Fl::event_state(FL_SHIFT)) { @@ -1135,7 +1069,7 @@ int Fl_Window_Type::handle(int event) { } else { deselect(); select(t, 1); - if (t->is_a(ID_Menu_Item)) t->open(); + if (t->is_a(Type::Menu_Item)) t->open(); } selection = t; drag = 0; @@ -1158,7 +1092,7 @@ int Fl_Window_Type::handle(int event) { 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(); + Widget_Node::open(); } else { if (mxlevel>level; i=i->next) + for (Node*i=next; i&&i->level>level; i=i->next) if (i->is_true_widget()) { - Fl_Widget_Type* myo = (Fl_Widget_Type*)i; + Widget_Node* myo = (Widget_Node*)i; for (Fl_Widget *o1 = myo->o; o1; o1 = o1->parent()) if (!o1->visible()) goto CONTINUE; if (Fl::event_inside(myo->o)) selection = myo; @@ -1201,10 +1135,10 @@ int Fl_Window_Type::handle(int event) { case FL_Tab: { if (Fl::event_state(FL_SHIFT)) backtab = 1; // find current child: - Fl_Type *i = Fl_Type::current; + Node *i = Fluid.proj.tree.current; while (i && !i->is_true_widget()) i = i->parent; if (!i) return 0; - Fl_Type *p = i->parent; + Node *p = i->parent; while (p && p != this) p = p->parent; if (!p || !p->is_widget()) { i = next; if (!i || i->level <= level) return 0; @@ -1227,9 +1161,9 @@ int Fl_Window_Type::handle(int event) { 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); + fld::app::Snap_Action::get_resize_stepsize(x_step, y_step); else - Fd_Snap_Action::get_move_stepsize(x_step, y_step); + fld::app::Snap_Action::get_move_stepsize(x_step, y_step); dx *= x_step; dy *= y_step; } @@ -1238,7 +1172,7 @@ int Fl_Window_Type::handle(int event) { return 1; case 'o': - toggle_overlays(0, 0); + toggle_overlays(nullptr, nullptr); break; default: @@ -1247,10 +1181,10 @@ int Fl_Window_Type::handle(int event) { case FL_SHORTCUT: { in_this_only = this; // modifies how some menu items work. - const Fl_Menu_Item* m = Main_Menu->test_shortcut(); + const Fl_Menu_Item* m = Fluid.main_menu->test_shortcut(); if (m && m->callback()) m->do_callback(this->o); - in_this_only = 0; - return (m != 0);} + in_this_only = nullptr; + return (m != nullptr);} default: return 0; @@ -1264,8 +1198,8 @@ int Fl_Window_Type::handle(int event) { Write the C++ code that comes before the children of the window are written. \param f the source code output stream */ -void Fl_Window_Type::write_code1(fld::io::Code_Writer& f) { - Fl_Widget_Type::write_code1(f); +void Window_Node::write_code1(fld::io::Code_Writer& f) { + Widget_Node::write_code1(f); } @@ -1273,7 +1207,7 @@ void Fl_Window_Type::write_code1(fld::io::Code_Writer& f) { Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ -void Fl_Window_Type::write_code2(fld::io::Code_Writer& f) { +void Window_Node::write_code2(fld::io::Code_Writer& f) { const char *var = is_class() ? "this" : name() ? name() : "o"; // make the window modal or non-modal if (modal) { @@ -1308,8 +1242,8 @@ void Fl_Window_Type::write_code2(fld::io::Code_Writer& f) { write_block_close(f); } -void Fl_Window_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Widget_Type::write_properties(f); +void Window_Node::write_properties(fld::io::Project_Writer &f) { + Widget_Node::write_properties(f); if (modal) f.write_string("modal"); else if (non_modal) f.write_string("non_modal"); if (!((Fl_Window*)o)->border()) f.write_string("noborder"); @@ -1319,13 +1253,13 @@ void Fl_Window_Type::write_properties(fld::io::Project_Writer &f) { if (o->visible() || override_visible_) f.write_string("visible"); } -void Fl_Window_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Window_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"modal")) { modal = 1; } else if (!strcmp(c,"non_modal")) { non_modal = 1; } else if (!strcmp(c, "visible")) { - if (batch_mode) // don't actually open any windows in batch mode + if (Fluid.batch_mode) // don't actually open any windows in batch mode override_visible_ = 1; else // in interactive mode, we simply show the window open_(); @@ -1340,14 +1274,14 @@ void Fl_Window_Type::read_property(fld::io::Project_Reader &f, const char *c) { sr_min_w = mw; sr_min_h = mh; sr_max_w = MW; sr_max_h = MH; } } else if (!strcmp(c,"xywh")) { - Fl_Widget_Type::read_property(f, c); - pasteoffset = 0; // make it not apply to contents + Widget_Node::read_property(f, c); + Fluid.pasteoffset = 0; // make it not apply to contents } else { - Fl_Widget_Type::read_property(f, c); + Widget_Node::read_property(f, c); } } -int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { +int Window_Node::read_fdesign(const char* propname, const char* value) { int x; o->box(FL_NO_BOX); // because fdesign always puts an Fl_Box next if (!strcmp(propname,"Width")) { @@ -1361,35 +1295,36 @@ int Fl_Window_Type::read_fdesign(const char* propname, const char* value) { } else if (!strcmp(propname,"title")) { label(value); } else { - return Fl_Widget_Type::read_fdesign(propname,value); + return Widget_Node::read_fdesign(propname,value); } return 1; } /////////////////////////////////////////////////////////////////////// -Fl_Widget_Class_Type Fl_Widget_Class_type; -Fl_Widget_Class_Type *current_widget_class = 0; +Widget_Class_Node Widget_Class_Node::prototype; + +Widget_Class_Node *current_widget_class = nullptr; /** Create and add a new Widget Class node. \param[in] strategy add after current or as last child \return new node */ -Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) { - Fl_Type *anchor = Fl_Type::current, *p = anchor; +Node *Widget_Class_Node::make(Strategy strategy) { + Node *anchor = Fluid.proj.tree.current, *p = anchor; if (p && (strategy.placement() == Strategy::AFTER_CURRENT)) p = p->parent; while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) { anchor = p; strategy.placement(Strategy::AFTER_CURRENT); p = p->parent; } - Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type(); + Widget_Class_Node *myo = new Widget_Class_Node(); myo->name("UserInterface"); if (!this->o) {// template widget this->o = new Fl_Window(100,100); - Fl_Group::current(0); + Fl_Group::current(nullptr); } myo->factory = this; myo->drag = 0; @@ -1406,21 +1341,21 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) { return myo; } -void Fl_Widget_Class_Type::write_properties(fld::io::Project_Writer &f) { - Fl_Window_Type::write_properties(f); +void Widget_Class_Node::write_properties(fld::io::Project_Writer &f) { + Window_Node::write_properties(f); if (wc_relative==1) f.write_string("position_relative"); else if (wc_relative==2) f.write_string("position_relative_rescale"); } -void Fl_Widget_Class_Type::read_property(fld::io::Project_Reader &f, const char *c) { +void Widget_Class_Node::read_property(fld::io::Project_Reader &f, const char *c) { if (!strcmp(c,"position_relative")) { wc_relative = 1; } else if (!strcmp(c,"position_relative_rescale")) { wc_relative = 2; } else { - Fl_Window_Type::read_property(f, c); + Window_Node::read_property(f, c); } } @@ -1428,7 +1363,7 @@ void Fl_Widget_Class_Type::read_property(fld::io::Project_Reader &f, const char // This is useful for classes that contain a namespace component static const char *trimclassname(const char *n) { if (!n) - return NULL; + return nullptr; const char *nn; while((nn = strstr(n, "::"))) { n = nn + 2; @@ -1437,9 +1372,9 @@ static const char *trimclassname(const char *n) { } -void Fl_Widget_Class_Type::write_code1(fld::io::Code_Writer& f) { +void Widget_Class_Node::write_code1(fld::io::Code_Writer& f) { #if 0 - Fl_Widget_Type::write_code1(fld::io::Code_Writer& f); + Widget_Node::write_code1(fld::io::Code_Writer& f); #endif // 0 current_widget_class = this; @@ -1507,7 +1442,7 @@ void Fl_Widget_Class_Type::write_code1(fld::io::Code_Writer& f) { Write the C++ code that comes after the children of the window are written. \param f the source code output stream */ -void Fl_Widget_Class_Type::write_code2(fld::io::Code_Writer& f) { +void Widget_Class_Node::write_code2(fld::io::Code_Writer& f) { // make the window modal or non-modal if (modal) { f.write_c("%sset_modal();\n", f.indent()); @@ -1542,21 +1477,21 @@ void Fl_Widget_Class_Type::write_code2(fld::io::Code_Writer& f) { //////////////////////////////////////////////////////////////// // live mode support -Fl_Widget *Fl_Window_Type::enter_live_mode(int) { +Fl_Widget *Window_Node::enter_live_mode(int) { Fl_Window *win = new Fl_Window(10, 10, o->w(), o->h()); return propagate_live_mode(win); } -void Fl_Window_Type::leave_live_mode() { +void Window_Node::leave_live_mode() { } /** copy all properties from the edit widget to the live widget */ -void Fl_Window_Type::copy_properties() { +void Window_Node::copy_properties() { Fl_Window *self = static_cast(o); Fl_Window *live = static_cast(live_widget); if (self->resizable() == self) live->resizable(live); - Fl_Widget_Type::copy_properties(); + Widget_Node::copy_properties(); } diff --git a/fluid/nodes/Window_Node.h b/fluid/nodes/Window_Node.h new file mode 100644 index 000000000..a6846168b --- /dev/null +++ b/fluid/nodes/Window_Node.h @@ -0,0 +1,163 @@ +// +// Window type header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 +// + +// +// Type for creating all subclasses of Fl_Widget +// This should have the widget pointer in it, but it is still in the +// Node base class. + +#ifndef FLUID_NODES_WINDOW_NODE_H +#define FLUID_NODES_WINDOW_NODE_H + +#include "nodes/Group_Node.h" + +class Widget_Class_Node; + +extern Fl_Menu_Item window_type_menu[]; +extern Widget_Class_Node *current_widget_class; + +void toggle_overlays(Fl_Widget *,void *); +void toggle_guides(Fl_Widget *,void *); +void toggle_restricted(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 Window_Node : public Group_Node +{ +public: + typedef Group_Node super; + static Window_Node prototype; +protected: + + Fl_Menu_Item* subtypes() override {return window_type_menu;} + + friend class Overlay_Window; + int mx,my; // mouse position during dragging + int x1,y1; // initial position of selection box + int bx,by,br,bt; // bounding box of selection before snapping + int sx,sy,sr,st; // bounding box of selection after snapping to guides + int dx,dy; + int drag; // which parts of bbox are being moved + int numselected; // number of children selected + void draw_out_of_bounds(Widget_Node *group, int x, int y, int w, int h); + void draw_out_of_bounds(); + void draw_overlaps(); + void draw_overlay(); + void newdx(); + void newposition(Widget_Node *,int &x,int &y,int &w,int &h); + int handle(int); + void setlabel(const char *) override; + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + Widget_Node *_make() override {return nullptr;} // we don't call this + Fl_Widget *widget(int,int,int,int) override {return nullptr;} + int recalc; // set by fix_overlay() + void moveallchildren(int key=0); + Type type() const override { return Type::Window; } + bool is_a(Type inType) const override { return (inType==Type::Window) ? true : super::is_a(inType); } + void open_(); + +public: + + Window_Node() : + mx(0), my(0), + x1(0), y1(0), + bx(0), by(0), br(0), bt(0), + sx(0), sy(0), sr(0), st(0), + dx(0), dy(0), + drag(0), + numselected(0), + recalc(0), + modal(0), non_modal(0), + xclass(nullptr), + sr_min_w(0), sr_min_h(0), sr_max_w(0), sr_max_h(0) + { } + uchar modal, non_modal; + const char *xclass; // junk string, used for shortcut + + Node *make(Strategy strategy) override; + const char *type_name() override {return "Fl_Window";} + const char *alt_type_name() override {return "fltk::Window";} + + void open() override; + void ideal_size(int &w, int &h) override; + + void fix_overlay(); // Update the bounding box, etc + uchar *read_image(int &ww, int &hh); // Read an image of the window + + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + int read_fdesign(const char*, const char*) override; + + void add_child(Node*, Node*) override; + void move_child(Node*, Node*) override; + void remove_child(Node*) override; + + int can_have_children() const override {return 1;} + + Fl_Widget *enter_live_mode(int top=0) override; + void leave_live_mode() override; + void copy_properties() override; + + int sr_min_w, sr_min_h, sr_max_w, sr_max_h; + + static int popupx, popupy; +}; + +class Widget_Class_Node : private Window_Node +{ +public: + typedef Window_Node super; + static Widget_Class_Node prototype; + +protected: + Fl_Menu_Item* subtypes() override {return nullptr;} + +public: + Widget_Class_Node() { + write_public_state = 0; + wc_relative = 0; + } + // state variables for output: + char write_public_state; // true when public: has been printed + char wc_relative; // if 1, reposition all children, if 2, reposition and resize + + void write_properties(fld::io::Project_Writer &f) override; + void read_property(fld::io::Project_Reader &f, const char *) override; + + void write_code1(fld::io::Code_Writer& f) override; + void write_code2(fld::io::Code_Writer& f) override; + Node *make(Strategy strategy) override; + const char *type_name() override {return "widget_class";} + Type type() const override { return Type::Widget_Class; } + bool is_a(Type inType) const override { return (inType==Type::Widget_Class) ? true : super::is_a(inType); } + int can_have_children() const override {return 1;} + int is_code_block() const override {return 1;} + int is_decl_block() const override {return 1;} + int is_class() const override {return 1;} +}; + +#endif // FLUID_NODES_WINDOW_NODE_H diff --git a/fluid/nodes/callbacks.cxx b/fluid/nodes/callbacks.cxx new file mode 100644 index 000000000..f53ca2d6c --- /dev/null +++ b/fluid/nodes/callbacks.cxx @@ -0,0 +1,18 @@ +// +// Fluid Node callbacks code for the Fast Light Tool Kit (FLTK). +// +// Copyright 2025 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 "nodes/callbacks.h" + diff --git a/fluid/nodes/callbacks.h b/fluid/nodes/callbacks.h new file mode 100644 index 000000000..77a38754a --- /dev/null +++ b/fluid/nodes/callbacks.h @@ -0,0 +1,23 @@ +// +// Fluid Node callbacks header file for the Fast Light Tool Kit (FLTK). +// +// Copyright 2025 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_NODES_CALLBACKS_H +#define FLUID_NODES_CALLBACKS_H + +#include "nodes/Node.h" + + +#endif // FLUID_NODES_CALLBACKS_H diff --git a/fluid/nodes/factory.cxx b/fluid/nodes/factory.cxx index ad5d388e1..8388e0202 100644 --- a/fluid/nodes/factory.cxx +++ b/fluid/nodes/factory.cxx @@ -1,13 +1,5 @@ // -// Widget factory code for the Fast Light Tool Kit (FLTK). -// -// Type classes for most of the fltk widgets. Most of the work -// is done by code in Fl_Widget_Type.cxx. Also a factory instance -// of each of these type classes. -// -// This file also contains the "new" menu, which has a pointer -// to a factory instance for every class (both the ones defined -// here and ones in other files) +// Node Factory code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -22,14 +14,41 @@ // https://www.fltk.org/bugs.php // +/** + + + \todo Verify the text + + Type classes for most of the fltk widgets. Most of the work + is done by code in Widget_Node.cxx. Also a factory instance + of each of these type classes. + + This file also contains the "new" menu, which has a pointer + to a factory instance for every class (both the ones defined + here and ones in other files) + + + Type classes for most of the fltk widgets. Most of the work + is done by code in Widget_Node.C. Also a factory instance + of each of these type classes. + + This file also contains the "new" menu, which has a pointer + to a factory instance for every class (both the ones defined + here and ones in other files) + + */ #include "nodes/factory.h" -#include "app/Fd_Snap_Action.h" -#include "app/fluid.h" -#include "app/undo.h" -#include "nodes/Fl_Group_Type.h" -#include "nodes/Fl_Grid_Type.h" -#include "nodes/Fl_Menu_Type.h" +#include "app/Snap_Action.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "nodes/Button_Node.h" +#include "nodes/Function_Node.h" +#include "nodes/Grid_Node.h" +#include "nodes/Group_Node.h" +#include "nodes/Menu_Node.h" +#include "nodes/Widget_Node.h" +#include "nodes/Window_Node.h" #include "rsrcs/pixmaps.h" #include @@ -70,23 +89,26 @@ // ---- Browser_Base ---- static Fl_Menu_Item browser_base_type_menu[] = { - {"No Select", 0, 0, (void*)FL_NORMAL_BROWSER}, - {"Select", 0, 0, (void*)FL_SELECT_BROWSER}, - {"Hold", 0, 0, (void*)FL_HOLD_BROWSER}, - {"Multi", 0, 0, (void*)FL_MULTI_BROWSER}, - {0} + {"No Select", 0, nullptr, (void*)nullptr}, + {"Select", 0, nullptr, (void*)FL_SELECT_BROWSER}, + {"Hold", 0, nullptr, (void*)FL_HOLD_BROWSER}, + {"Multi", 0, nullptr, (void*)FL_MULTI_BROWSER}, + {nullptr} }; /** \brief This is the base class for some browsers types. This class will not be instantiated. */ -class Fl_Browser_Base_Type : public Fl_Widget_Type +class Browser_Base_Node : public Widget_Node { - typedef Fl_Widget_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return browser_base_type_menu; } - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Browser_ *myo = (Fl_Browser_*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Widget_Node super; + static Browser_Base_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return browser_base_type_menu; } + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Browser_ *myo = (Fl_Browser_*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -97,42 +119,44 @@ class Fl_Browser_Base_Type : public Fl_Widget_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { w = 120; h = 160; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Browser_"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Browser_"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Browser_"; } + const char *alt_type_name() override { return "fltk::Browser_"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Browser* b = new Fl_Browser(x, y, w, h); return b; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Browser_Base_Type(); } - ID id() const FL_OVERRIDE { return ID_Browser_; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Browser_) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Browser_Base_Node(); } + Type type() const override { return Type::Browser_; } + bool is_a(Type inType) const override { return (inType==Type::Browser_) ? true : super::is_a(inType); } }; -static Fl_Browser_Base_Type Fl_Browser_Base_type; +Browser_Base_Node Browser_Base_Node::prototype; // ---- Browser ---- /** \brief Handle a plain browser widget. - Most of the work is already done in Fl_Browser_Base_Type. + Most of the work is already done in Browser_Base_Node. */ -class Fl_Browser_Type : public Fl_Browser_Base_Type +class Browser_Node : public Browser_Base_Node { - typedef Fl_Browser_Base_Type super; public: - const char *type_name() FL_OVERRIDE { return "Fl_Browser"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Browser"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Browser_Base_Node super; + static Browser_Node prototype; +public: + const char *type_name() override { return "Fl_Browser"; } + const char *alt_type_name() override { return "fltk::Browser"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Browser* b = new Fl_Browser(x, y, w, h); // Fl_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: - if (!batch_mode) { + if (!Fluid.batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); @@ -141,12 +165,12 @@ public: } return b; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Browser_Type(); } - ID id() const FL_OVERRIDE { return ID_Browser; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Browser) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Browser_Node(); } + Type type() const override { return Type::Browser; } + bool is_a(Type inType) const override { return (inType==Type::Browser) ? true : super::is_a(inType); } }; -static Fl_Browser_Type Fl_Browser_type; +Browser_Node Browser_Node::prototype; // ---- Check Browser ---- @@ -155,17 +179,19 @@ static Fl_Browser_Type Fl_Browser_type; \brief Manage the Check Browser. The Fl_Check_Browser is derived form Fl_Browser_ (underline!), not Fl_Browser. */ -class Fl_Check_Browser_Type : public Fl_Browser_Base_Type +class Check_Browser_Node : public Browser_Base_Node { - typedef Fl_Browser_Base_Type super; public: - const char *type_name() FL_OVERRIDE { return "Fl_Check_Browser"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::CheckBrowser"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Browser_Base_Node super; + static Check_Browser_Node prototype; +public: + const char *type_name() override { return "Fl_Check_Browser"; } + const char *alt_type_name() override { return "fltk::CheckBrowser"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Check_Browser* b = new Fl_Check_Browser(x, y, w, h); // Fl_Check_Browser::add calls fl_height(), which requires the X display open. // Avoid this when compiling so it works w/o a display: - if (!batch_mode) { + if (!Fluid.batch_mode) { char buffer[20]; for (int i = 1; i <= 20; i++) { sprintf(buffer,"Browser Line %d",i); @@ -174,12 +200,12 @@ public: } return b; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Check_Browser_Type(); } - ID id() const FL_OVERRIDE { return ID_Check_Browser; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Check_Browser) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Check_Browser_Node(); } + Type type() const override { return Type::Check_Browser; } + bool is_a(Type inType) const override { return (inType==Type::Check_Browser) ? true : super::is_a(inType); } }; -static Fl_Check_Browser_Type Fl_Check_Browser_type; +Check_Browser_Node Check_Browser_Node::prototype; // ---- File Browser ---- @@ -189,23 +215,25 @@ static Fl_Check_Browser_Type Fl_Check_Browser_type; As oppoesed to the Hold, Multi, and Select Browser, this is not a subclass, but its own implementation, based on Fl_Browser. */ -class Fl_File_Browser_Type : public Fl_Browser_Type +class File_Browser_Node : public Browser_Node { - typedef Fl_Browser_Type super; public: - const char *type_name() FL_OVERRIDE { return "Fl_File_Browser"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::FileBrowser"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Browser_Node super; + static File_Browser_Node prototype; +public: + const char *type_name() override { return "Fl_File_Browser"; } + const char *alt_type_name() override { return "fltk::FileBrowser"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_File_Browser* b = new Fl_File_Browser(x, y, w, h); - if (!batch_mode) b->load("."); + if (!Fluid.batch_mode) b->load("."); return b; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_File_Browser_Type(); } - ID id() const FL_OVERRIDE { return ID_File_Browser; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_File_Browser) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new File_Browser_Node(); } + Type type() const override { return Type::File_Browser; } + bool is_a(Type inType) const override { return (inType==Type::File_Browser) ? true : super::is_a(inType); } }; -static Fl_File_Browser_Type Fl_File_Browser_type; +File_Browser_Node File_Browser_Node::prototype; // ---- Tree Type ------------------------------------------------------ MARK: - @@ -213,25 +241,27 @@ static Fl_File_Browser_Type Fl_File_Browser_type; /** \brief Handle the Tree widget. Fl_Tree is derived from Fl_Group, but FLUID does not support extended Fl_Tree - functionality, so we derive the Type from Fl_Widget_Type. + functionality, so we derive the Type from Widget_Node. \note Updating item_labelfont etc. does not refresh any of the existing items in the tree, so I decided against implementig those via the labelfont UI. */ -class Fl_Tree_Type : public Fl_Widget_Type +class Tree_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Widget_Node super; + static Tree_Node prototype; +public: + void ideal_size(int &w, int &h) override { w = 120; h = 160; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Tree"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::TreeBrowser"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Tree"; } + const char *alt_type_name() override { return "fltk::TreeBrowser"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Tree* b = new Fl_Tree(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { b->add("/A1/B1/C1"); b->add("/A1/B1/C2"); b->add("/A1/B2/C1"); @@ -243,12 +273,12 @@ public: } return b; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Tree_Type(); } - ID id() const FL_OVERRIDE { return ID_Tree; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Tree) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Tree_Node(); } + Type type() const override { return Type::Tree; } + bool is_a(Type inType) const override { return (inType==Type::Tree) ? true : super::is_a(inType); } }; -static Fl_Tree_Type Fl_Tree_type; +Tree_Node Tree_Node::prototype; @@ -257,13 +287,16 @@ static Fl_Tree_Type Fl_Tree_type; /** \brief Handle the Help View widget. Fl_Help_View is derived from Fl_Group, but supporting children is not useful, - so we derive from Fl_Widget_Type. + so we derive from Widget_Node. */ -class Fl_Help_View_Type : public Fl_Widget_Type +class Help_View_Node : public Widget_Node { - typedef Fl_Widget_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Help_View *myo = (Fl_Help_View*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Widget_Node super; + static Help_View_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Help_View *myo = (Fl_Help_View*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -274,27 +307,27 @@ class Fl_Help_View_Type : public Fl_Widget_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { w = 160; h = 120; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Help_View"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::HelpView"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Help_View"; } + const char *alt_type_name() override { return "fltk::HelpView"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Help_View *myo = new Fl_Help_View(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { myo->value("

Fl_Help_View Widget

" "

This is a Fl_Help_View widget.

"); } return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Help_View_Type(); } - ID id() const FL_OVERRIDE { return ID_Help_View; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Help_View) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Help_View_Node(); } + Type type() const override { return Type::Help_View; } + bool is_a(Type inType) const override { return (inType==Type::Help_View) ? true : super::is_a(inType); } }; -static Fl_Help_View_Type Fl_Help_View_type; +Help_View_Node Help_View_Node::prototype; @@ -306,41 +339,46 @@ static Fl_Help_View_Type Fl_Help_View_type; /** \brief Just a base class for all valuators. */ -class Fl_Valuator_Type : public Fl_Widget_Type +class Valuator_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - const char *type_name() FL_OVERRIDE { return "Fl_Valuator"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Valuator"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Widget_Node super; + static Valuator_Node prototype; +public: + const char *type_name() override { return "Fl_Valuator"; } + const char *alt_type_name() override { return "fltk::Valuator"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Slider(x, y, w, h, "Valuator"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Valuator_Type(); } - ID id() const FL_OVERRIDE { return ID_Valuator_; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Valuator_) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Valuator_Node(); } + Type type() const override { return Type::Valuator_; } + bool is_a(Type inType) const override { return (inType==Type::Valuator_) ? true : super::is_a(inType); } }; -static Fl_Valuator_Type Fl_Valuator_type; +Valuator_Node Valuator_Node::prototype; // ---- Counter ---- static Fl_Menu_Item counter_type_menu[] = { - { "Normal", 0, 0, (void*)FL_NORMAL_COUNTER }, - { "Simple", 0, 0, (void*)FL_SIMPLE_COUNTER }, - { 0 } + { "Normal", 0, nullptr, (void*)nullptr }, + { "Simple", 0, nullptr, (void*)FL_SIMPLE_COUNTER }, + { nullptr } }; /** \brief Manage the Counter widget. Strictly speaking, the ideal size should derive from the textsize not the labelsize. */ -class Fl_Counter_Type : public Fl_Valuator_Type +class Counter_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return counter_type_menu; } - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Counter *myo = (Fl_Counter*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Valuator_Node super; + static Counter_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return counter_type_menu; } + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Counter *myo = (Fl_Counter*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -351,22 +389,23 @@ class Fl_Counter_Type : public Fl_Valuator_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 4 * h; // make room for the arrows - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Counter"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Counter"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Counter"; } + const char *alt_type_name() override { return "fltk::Counter"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Counter(x, y, w, h, "counter:"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Counter_Type(); } - ID id() const FL_OVERRIDE { return ID_Counter; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Counter) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Counter_Node(); } + Type type() const override { return Type::Counter; } + bool is_a(Type inType) const override { return (inType==Type::Counter) ? true : super::is_a(inType); } }; -static Fl_Counter_Type Fl_Counter_type; +Counter_Node Counter_Node::prototype; // ---- Adjuster ---- @@ -374,105 +413,116 @@ static Fl_Counter_Type Fl_Counter_type; /** \brief Handle Adjuster widgets which are derived from valuators. */ -class Fl_Adjuster_Type : public Fl_Valuator_Type +class Adjuster_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Valuator_Node super; + static Adjuster_Node prototype; +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->labelsize + 8; w = 3 * h; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Adjuster"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Adjuster"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Adjuster"; } + const char *alt_type_name() override { return "fltk::Adjuster"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Adjuster(x, y, w, h); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Adjuster_Type(); } - ID id() const FL_OVERRIDE { return ID_Adjuster; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Adjuster) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Adjuster_Node(); } + Type type() const override { return Type::Adjuster; } + bool is_a(Type inType) const override { return (inType==Type::Adjuster) ? true : super::is_a(inType); } }; -static Fl_Adjuster_Type Fl_Adjuster_type; +Adjuster_Node Adjuster_Node::prototype; // ---- Dial ---- static Fl_Menu_Item dial_type_menu[] = { - { "Dot", 0, 0, (void*)0 }, - { "Line", 0, 0, (void*)FL_LINE_DIAL }, - { "Fill", 0, 0, (void*)FL_FILL_DIAL }, - { 0 } + { "Dot", 0, nullptr, (void*)nullptr }, + { "Line", 0, nullptr, (void*)FL_LINE_DIAL }, + { "Fill", 0, nullptr, (void*)FL_FILL_DIAL }, + { nullptr } }; /** \brief Manage dials. */ -class Fl_Dial_Type : public Fl_Valuator_Type +class Dial_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return dial_type_menu; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Valuator_Node super; + static Dial_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return dial_type_menu; } +public: + void ideal_size(int &w, int &h) override { w = 60; h = 60; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Dial"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Dial"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Dial"; } + const char *alt_type_name() override { return "fltk::Dial"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Dial(x, y, w, h); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Dial_Type(); } - ID id() const FL_OVERRIDE { return ID_Dial; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Dial) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Dial_Node(); } + Type type() const override { return Type::Dial; } + bool is_a(Type inType) const override { return (inType==Type::Dial) ? true : super::is_a(inType); } }; -static Fl_Dial_Type Fl_Dial_type; + +Dial_Node Dial_Node::prototype; // ---- Roller ---- static Fl_Menu_Item roller_type_menu[] = { - { "Vertical", 0, 0, (void*)0 }, - { "Horizontal", 0, 0, (void*)FL_HORIZONTAL }, - { 0 } + { "Vertical", 0, nullptr, (void*)nullptr }, + { "Horizontal", 0, nullptr, (void*)FL_HORIZONTAL }, + { nullptr } }; /** \brief Manage Roller widgets. They are vertical by default. */ -class Fl_Roller_Type : public Fl_Valuator_Type +class Roller_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return roller_type_menu; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Valuator_Node super; + static Roller_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return roller_type_menu; } +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; w = layout->labelsize + 8; h = 4 * w; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Roller"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Roller"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Roller"; } + const char *alt_type_name() override { return "fltk::Roller"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Roller(x, y, w, h); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Roller_Type(); } - ID id() const FL_OVERRIDE { return ID_Roller; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Roller) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Roller_Node(); } + Type type() const override { return Type::Roller; } + bool is_a(Type inType) const override { return (inType==Type::Roller) ? true : super::is_a(inType); } }; -static Fl_Roller_Type Fl_Roller_type; +Roller_Node Roller_Node::prototype; // ---- Slider ---- static Fl_Menu_Item slider_type_menu[] = { - { "Vertical", 0, 0, (void*)FL_VERT_SLIDER }, - { "Horizontal", 0, 0, (void*)FL_HOR_SLIDER }, - { "Vert Fill", 0, 0, (void*)FL_VERT_FILL_SLIDER }, - { "Horz Fill", 0, 0, (void*)FL_HOR_FILL_SLIDER }, - { "Vert Knob", 0, 0, (void*)FL_VERT_NICE_SLIDER }, - { "Horz Knob", 0, 0, (void*)FL_HOR_NICE_SLIDER }, - { 0 } + { "Vertical", 0, nullptr, (void*)nullptr }, + { "Horizontal", 0, nullptr, (void*)FL_HOR_SLIDER }, + { "Vert Fill", 0, nullptr, (void*)FL_VERT_FILL_SLIDER }, + { "Horz Fill", 0, nullptr, (void*)FL_HOR_FILL_SLIDER }, + { "Vert Knob", 0, nullptr, (void*)FL_VERT_NICE_SLIDER }, + { "Horz Knob", 0, nullptr, (void*)FL_HOR_NICE_SLIDER }, + { nullptr } }; /** @@ -480,55 +530,63 @@ static Fl_Menu_Item slider_type_menu[] = { They are vertical by default. Fl_Value_Slider has its own type. */ -class Fl_Slider_Type : public Fl_Valuator_Type +class Slider_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return slider_type_menu; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Valuator_Node super; + static Slider_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return slider_type_menu; } +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; w = layout->labelsize + 8; h = 4 * w; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Slider"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Slider"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Slider"; } + const char *alt_type_name() override { return "fltk::Slider"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Slider(x, y, w, h, "slider:"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Slider_Type(); } - ID id() const FL_OVERRIDE { return ID_Slider; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Slider) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Slider_Node(); } + Type type() const override { return Type::Slider; } + bool is_a(Type inType) const override { return (inType==Type::Slider) ? true : super::is_a(inType); } }; -static Fl_Slider_Type Fl_Slider_type; +Slider_Node Slider_Node::prototype; // ---- Scrollbar ---- static Fl_Menu_Item scrollbar_type_menu[] = { - { "Vertical", 0, 0, (void*)FL_VERT_SLIDER }, - { "Horizontal", 0, 0, (void*)FL_HOR_SLIDER }, - { 0 } + { "Vertical", 0, nullptr, (void*)nullptr }, + { "Horizontal", 0, nullptr, (void*)FL_HOR_SLIDER }, + { nullptr } }; /** \brief Manage Scrollbars which are derived from Sliders. */ -class Fl_Scrollbar_Type : public Fl_Slider_Type +class Scrollbar_Node : public Slider_Node { - typedef Fl_Slider_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return scrollbar_type_menu; } public: - const char *type_name() FL_OVERRIDE { return "Fl_Scrollbar"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Scrollbar"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Slider_Node super; + static Scrollbar_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return scrollbar_type_menu; } +public: + const char *type_name() override { return "Fl_Scrollbar"; } + const char *alt_type_name() override { return "fltk::Scrollbar"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Scrollbar(x, y, w, h); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Scrollbar_Type(); } - ID id() const FL_OVERRIDE { return ID_Scrollbar; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Scrollbar) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Scrollbar_Node(); } + Type type() const override { return Type::Scrollbar; } + bool is_a(Type inType) const override { return (inType==Type::Scrollbar) ? true : super::is_a(inType); } }; -static Fl_Scrollbar_Type Fl_Scrollbar_type; + +Scrollbar_Node Scrollbar_Node::prototype; // ---- Value Slider ---- @@ -536,11 +594,14 @@ static Fl_Scrollbar_Type Fl_Scrollbar_type; /** \brief Manage Value Sliders and their text settings. */ -class Fl_Value_Slider_Type : public Fl_Slider_Type +class Value_Slider_Node : public Slider_Node { - typedef Fl_Slider_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Value_Slider *myo = (Fl_Value_Slider*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Slider_Node super; + static Value_Slider_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Value_Slider *myo = (Fl_Value_Slider*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -551,17 +612,17 @@ class Fl_Value_Slider_Type : public Fl_Slider_Type return 1; } public: - const char *type_name() FL_OVERRIDE { return "Fl_Value_Slider"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueSlider"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Value_Slider"; } + const char *alt_type_name() override { return "fltk::ValueSlider"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Value_Slider(x, y, w, h, "slider:"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Slider_Type(); } - ID id() const FL_OVERRIDE { return ID_Value_Slider; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Slider) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Value_Slider_Node(); } + Type type() const override { return Type::Value_Slider; } + bool is_a(Type inType) const override { return (inType==Type::Value_Slider) ? true : super::is_a(inType); } }; -static Fl_Value_Slider_Type Fl_Value_Slider_type; +Value_Slider_Node Value_Slider_Node::prototype; // ---- Value Input ---- @@ -569,11 +630,14 @@ static Fl_Value_Slider_Type Fl_Value_Slider_type; /** \brief Manage Value Inputs and their text settings. */ -class Fl_Value_Input_Type : public Fl_Valuator_Type +class Value_Input_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Value_Input *myo = (Fl_Value_Input*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Valuator_Node super; + static Value_Input_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Value_Input *myo = (Fl_Value_Input*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -584,23 +648,24 @@ class Fl_Value_Input_Type : public Fl_Valuator_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Value_Input"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueInput"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Value_Input"; } + const char *alt_type_name() override { return "fltk::ValueInput"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Value_Input *myo = new Fl_Value_Input(x, y, w, h, "value:"); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Input_Type(); } - ID id() const FL_OVERRIDE { return ID_Value_Input; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Input) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Value_Input_Node(); } + Type type() const override { return Type::Value_Input; } + bool is_a(Type inType) const override { return (inType==Type::Value_Input) ? true : super::is_a(inType); } }; -static Fl_Value_Input_Type Fl_Value_Input_type; +Value_Input_Node Value_Input_Node::prototype; // ---- Value Output ---- @@ -608,11 +673,14 @@ static Fl_Value_Input_Type Fl_Value_Input_type; /** \brief Handle Value Output widgets, no shortcut with Value Input unfortunately. */ -class Fl_Value_Output_Type : public Fl_Valuator_Type +class Value_Output_Node : public Valuator_Node { - typedef Fl_Valuator_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Value_Output *myo = (Fl_Value_Output*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Valuator_Node super; + static Value_Output_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Value_Output *myo = (Fl_Value_Output*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -623,23 +691,24 @@ class Fl_Value_Output_Type : public Fl_Valuator_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Value_Output"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::ValueOutput"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Value_Output"; } + const char *alt_type_name() override { return "fltk::ValueOutput"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Value_Output *myo = new Fl_Value_Output(x, y, w, h, "value:"); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Value_Output_Type(); } - ID id() const FL_OVERRIDE { return ID_Value_Output; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Value_Output) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Value_Output_Node(); } + Type type() const override { return Type::Value_Output; } + bool is_a(Type inType) const override { return (inType==Type::Value_Output) ? true : super::is_a(inType); } }; -static Fl_Value_Output_Type Fl_Value_Output_type; +Value_Output_Node Value_Output_Node::prototype; @@ -649,25 +718,28 @@ static Fl_Value_Output_Type Fl_Value_Output_type; // ---- Input ---- static Fl_Menu_Item input_type_menu[] = { - { "Normal", 0, 0, (void*)FL_NORMAL_INPUT }, - { "Multiline", 0, 0, (void*)FL_MULTILINE_INPUT }, - { "Secret", 0, 0, (void*)FL_SECRET_INPUT }, - { "Int", 0, 0, (void*)FL_INT_INPUT }, - { "Float", 0, 0, (void*)FL_FLOAT_INPUT }, - {0} + { "Normal", 0, nullptr, (void*)nullptr }, + { "Multiline", 0, nullptr, (void*)FL_MULTILINE_INPUT }, + { "Secret", 0, nullptr, (void*)FL_SECRET_INPUT }, + { "Int", 0, nullptr, (void*)FL_INT_INPUT }, + { "Float", 0, nullptr, (void*)FL_FLOAT_INPUT }, + {nullptr} }; /** \brief Manage simple text input widgets. The managed class is derived from Fl_Input_, but for simplicity, deriving from - Fl_Widget_Type seems sufficient here. + Widget_Node seems sufficient here. */ -class Fl_Input_Type : public Fl_Widget_Type +class Input_Node : public Widget_Node { - typedef Fl_Widget_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return input_type_menu; } - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Input_ *myo = (Fl_Input_*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Widget_Node super; + static Input_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return input_type_menu; } + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Input_ *myo = (Fl_Input_*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -678,23 +750,24 @@ class Fl_Input_Type : public Fl_Widget_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 6 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Input"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Input"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Input"; } + const char *alt_type_name() override { return "fltk::Input"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Input *myo = new Fl_Input(x, y, w, h, "input:"); myo->value("Text Input"); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Input_Type(); } - ID id() const FL_OVERRIDE { return ID_Input; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Input) ? true : super::is_a(inID); } - void copy_properties() FL_OVERRIDE { - Fl_Widget_Type::copy_properties(); + Widget_Node *_make() override { return new Input_Node(); } + Type type() const override { return Type::Input; } + bool is_a(Type inType) const override { return (inType==Type::Input) ? true : super::is_a(inType); } + void copy_properties() override { + Widget_Node::copy_properties(); Fl_Input_ *d = (Fl_Input_*)live_widget, *s = (Fl_Input_*)o; d->textfont(s->textfont()); d->textsize(s->textsize()); @@ -702,7 +775,8 @@ public: d->shortcut(s->shortcut()); } }; -static Fl_Input_Type Fl_Input_type; + +Input_Node Input_Node::prototype; // ---- File Input ---- @@ -710,60 +784,67 @@ static Fl_Input_Type Fl_Input_type; /** \brief Manage file name input widgets. */ -class Fl_File_Input_Type : public Fl_Input_Type +class File_Input_Node : public Input_Node { - typedef Fl_Input_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return NULL; } // Don't inherit. public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Input_Node super; + static File_Input_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return nullptr; } // Don't inherit. +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8 + 10; // Directoy bar is additional 10 pixels high w = layout->textsize_not_null() * 10 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_File_Input"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::FileInput"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_File_Input"; } + const char *alt_type_name() override { return "fltk::FileInput"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_File_Input *myo = new Fl_File_Input(x, y, w, h, "file:"); myo->value("/usr/include/FL/Fl.H"); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_File_Input_Type(); } - ID id() const FL_OVERRIDE { return ID_File_Input; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_File_Input) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new File_Input_Node(); } + Type type() const override { return Type::File_Input; } + bool is_a(Type inType) const override { return (inType==Type::File_Input) ? true : super::is_a(inType); } }; -static Fl_File_Input_Type Fl_File_Input_type; +File_Input_Node File_Input_Node::prototype; // ---- Output ---- static Fl_Menu_Item output_type_menu[] = { - { "Normal", 0, 0, (void*)FL_NORMAL_OUTPUT }, - { "Multiline", 0, 0, (void*)FL_MULTILINE_OUTPUT }, - { 0 } + { "Normal", 0, nullptr, (void*)FL_NORMAL_OUTPUT }, + { "Multiline", 0, nullptr, (void*)FL_MULTILINE_OUTPUT }, + { nullptr } }; /** \brief Manage Output widgets, derived from Input. */ -class Fl_Output_Type : public Fl_Input_Type +class Output_Node : public Input_Node { - typedef Fl_Input_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return output_type_menu; } public: - const char *type_name() FL_OVERRIDE { return "Fl_Output"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Output"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Input_Node super; + static Output_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return output_type_menu; } +public: + const char *type_name() override { return "Fl_Output"; } + const char *alt_type_name() override { return "fltk::Output"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Output *myo = new Fl_Output(x, y, w, h, "output:"); myo->value("Text Output"); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Output_Type(); } - ID id() const FL_OVERRIDE { return ID_Output; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Output) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Output_Node(); } + Type type() const override { return Type::Output; } + bool is_a(Type inType) const override { return (inType==Type::Output) ? true : super::is_a(inType); } }; -static Fl_Output_Type Fl_Output_type; +Output_Node Output_Node::prototype; @@ -777,11 +858,14 @@ static Fl_Output_Type Fl_Output_type; Fl_Text_Display is actually derived from Fl_Group, but for FLUID, deriving the type from Widget is better. */ -class Fl_Text_Display_Type : public Fl_Widget_Type +class Text_Display_Node : public Widget_Node { - typedef Fl_Widget_Type super; - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Text_Display *myo = (Fl_Text_Display*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Widget_Node super; + static Text_Display_Node prototype; +private: + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Text_Display *myo = (Fl_Text_Display*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -792,27 +876,29 @@ class Fl_Text_Display_Type : public Fl_Widget_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() * 4 + 8; w = layout->textsize_not_null() * 10 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Text_Display"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::TextDisplay"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Text_Display"; } + const char *alt_type_name() override { return "fltk::TextDisplay"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Text_Display *myo = new Fl_Text_Display(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); } return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Text_Display_Type(); } - ID id() const FL_OVERRIDE { return ID_Text_Display; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Text_Display) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Text_Display_Node(); } + Type type() const override { return Type::Text_Display; } + bool is_a(Type inType) const override { return (inType==Type::Text_Display) ? true : super::is_a(inType); } }; -static Fl_Text_Display_Type Fl_Text_Display_type; + +Text_Display_Node Text_Display_Node::prototype; // ---- Text Editor ---- @@ -820,27 +906,29 @@ static Fl_Text_Display_Type Fl_Text_Display_type; /** \brief Manage Text Editors based on Text Display. */ -class Fl_Text_Editor_Type : public Fl_Text_Display_Type +class Text_Editor_Node : public Text_Display_Node { - typedef Fl_Text_Display_Type super; public: - const char *type_name() FL_OVERRIDE {return "Fl_Text_Editor";} - const char *alt_type_name() FL_OVERRIDE {return "fltk::TextEditor";} - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + typedef Text_Display_Node super; + static Text_Editor_Node prototype; +public: + const char *type_name() override {return "Fl_Text_Editor";} + const char *alt_type_name() override {return "fltk::TextEditor";} + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Text_Editor *myo = new Fl_Text_Editor(x, y, w, h); - if (!batch_mode) { + if (!Fluid.batch_mode) { Fl_Text_Buffer *b = new Fl_Text_Buffer(); b->text("Lorem ipsum dolor\nsit amet, consetetur\nsadipscing elitr"); myo->buffer(b); } return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Text_Editor_Type(); } - ID id() const FL_OVERRIDE { return ID_Text_Editor; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Text_Editor) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Text_Editor_Node(); } + Type type() const override { return Type::Text_Editor; } + bool is_a(Type inType) const override { return (inType==Type::Text_Editor) ? true : super::is_a(inType); } }; -static Fl_Text_Editor_Type Fl_Text_Editor_type; +Text_Editor_Node Text_Editor_Node::prototype; // ---- Terminal ---- @@ -848,13 +936,13 @@ static Fl_Text_Editor_Type Fl_Text_Editor_type; /** Use this terminal instead of Fl_Terminal to capture resize actions. */ class Fl_Terminal_Proxy : public Fl_Terminal { public: - Fl_Terminal_Proxy(int x, int y, int w, int h, const char *l=NULL) + Fl_Terminal_Proxy(int x, int y, int w, int h, const char *l=nullptr) : Fl_Terminal(x, y, w, h, l) { } void print_sample_text() { clear_screen_home(false); append("> ls -als"); } - void resize(int x, int y, int w, int h) FL_OVERRIDE { + void resize(int x, int y, int w, int h) override { Fl_Terminal::resize(x, y, w, h); // After a resize, the top text vanishes, so make sure we redraw it. print_sample_text(); @@ -867,7 +955,7 @@ public: Fl_Font tfont_; int tsize_; Fl_Color tcolor_; - Fl_Batchmode_Terminal(int x, int y, int w, int h, const char *l=NULL) + Fl_Batchmode_Terminal(int x, int y, int w, int h, const char *l=nullptr) : Fl_Group(x, y, w, h, l) { // set the defaults that Fl_Terminal would set box(FL_DOWN_BOX); @@ -889,16 +977,18 @@ public: /** \brief Manage a terminal widget. */ -class Fl_Terminal_Type : public Fl_Widget_Type +class Terminal_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - const char *type_name() FL_OVERRIDE { return "Fl_Terminal"; } + typedef Widget_Node super; + static Terminal_Node prototype; +public: + const char *type_name() override { return "Fl_Terminal"; } // Older .fl files with Fl_Simple_Terminal will create a Fl_Terminal instead. - const char *alt_type_name() FL_OVERRIDE { return "Fl_Simple_Terminal"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { - Fl_Widget *ret = NULL; - if (batch_mode) { + const char *alt_type_name() override { return "Fl_Simple_Terminal"; } + Fl_Widget *widget(int x, int y, int w, int h) override { + Fl_Widget *ret = nullptr; + if (Fluid.batch_mode) { ret = new Fl_Batchmode_Terminal(x, y, w, h); } else { Fl_Terminal_Proxy *term = new Fl_Terminal_Proxy(x, y, w+100, h); @@ -906,9 +996,9 @@ public: } return ret; } - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - if (batch_mode) { - Fl_Batchmode_Terminal *myo = (Fl_Batchmode_Terminal*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + if (Fluid.batch_mode) { + Fl_Batchmode_Terminal *myo = (Fl_Batchmode_Terminal*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->tfont_; s = myo->tsize_; c = myo->tcolor_; break; @@ -917,7 +1007,7 @@ public: case 3: myo->tcolor_ = c; break; } } else { - Fl_Terminal_Proxy *myo = (Fl_Terminal_Proxy*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); + Fl_Terminal_Proxy *myo = (Fl_Terminal_Proxy*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -928,12 +1018,12 @@ public: } return 1; } - Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Terminal_Type();} - ID id() const FL_OVERRIDE { return ID_Terminal; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Terminal) ? true : super::is_a(inID); } + Widget_Node *_make() override {return new Terminal_Node();} + Type type() const override { return Type::Terminal; } + bool is_a(Type inType) const override { return (inType==Type::Terminal) ? true : super::is_a(inType); } }; -static Fl_Terminal_Type Fl_Terminal_type; +Terminal_Node Terminal_Node::prototype; // ---- Other ---------------------------------------------------------- MARK: - @@ -945,25 +1035,27 @@ static Fl_Terminal_Type Fl_Terminal_type; \brief Manage box widgets. Ideal size is set to 100x100, snapped to layout. */ -class Fl_Box_Type : public Fl_Widget_Type +class Box_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Widget_Node super; + static Box_Node prototype; +public: + void ideal_size(int &w, int &h) override { w = 100; h = 100; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Box"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Widget"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Box"; } + const char *alt_type_name() override { return "fltk::Widget"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Box(x, y, w, h, "label"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Box_Type(); } - ID id() const FL_OVERRIDE { return ID_Box; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Box) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Box_Node(); } + Type type() const override { return Type::Box; } + bool is_a(Type inType) const override { return (inType==Type::Box) ? true : super::is_a(inType); } }; -static Fl_Box_Type Fl_Box_type; +Box_Node Box_Node::prototype; // ---- Clock ---- @@ -972,25 +1064,27 @@ static Fl_Box_Type Fl_Box_type; \brief Manage Clock widgets. Ideal size is set to 80x80 snapped to layout. */ -class Fl_Clock_Type : public Fl_Widget_Type +class Clock_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Widget_Node super; + static Clock_Node prototype; +public: + void ideal_size(int &w, int &h) override { w = 80; h = 80; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Clock"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Clock"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Clock"; } + const char *alt_type_name() override { return "fltk::Clock"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Clock(x, y, w, h); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Clock_Type(); } - ID id() const FL_OVERRIDE { return ID_Clock; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Clock) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Clock_Node(); } + Type type() const override { return Type::Clock; } + bool is_a(Type inType) const override { return (inType==Type::Clock) ? true : super::is_a(inType); } }; -static Fl_Clock_Type Fl_Clock_type; +Clock_Node Clock_Node::prototype; // ---- Progress ---- @@ -1000,35 +1094,38 @@ static Fl_Clock_Type Fl_Clock_type; Ideal size is set to match the label font and label text width times 3. \note minimum, maximum, and value must be set via extra code fields. */ -class Fl_Progress_Type : public Fl_Widget_Type +class Progress_Node : public Widget_Node { - typedef Fl_Widget_Type super; public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + typedef Widget_Node super; + static Progress_Node prototype; +public: + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->labelsize + 8; w = layout->labelsize * 12; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Progress"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::ProgressBar"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Progress"; } + const char *alt_type_name() override { return "fltk::ProgressBar"; } + Fl_Widget *widget(int x, int y, int w, int h) override { Fl_Progress *myo = new Fl_Progress(x, y, w, h, "label"); myo->value(50); return myo; } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Progress_Type(); } - ID id() const FL_OVERRIDE { return ID_Progress; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Progress) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Progress_Node(); } + Type type() const override { return Type::Progress; } + bool is_a(Type inType) const override { return (inType==Type::Progress) ? true : super::is_a(inType); } }; -static Fl_Progress_Type Fl_Progress_type; +Progress_Node Progress_Node::prototype; // ---- Spinner ---- static Fl_Menu_Item spinner_type_menu[] = { - { "Integer", 0, 0, (void*)FL_INT_INPUT }, - { "Float", 0, 0, (void*)FL_FLOAT_INPUT }, - { 0 } + { "Integer", 0, nullptr, (void*)FL_INT_INPUT }, + { "Float", 0, nullptr, (void*)FL_FLOAT_INPUT }, + { nullptr } }; /** @@ -1036,12 +1133,15 @@ static Fl_Menu_Item spinner_type_menu[] = { \note Fl_Spinner is derived from Fl_Group, *not* Fl_Valuator as one may expect. For FLUID, this means some special handling and no Group support. */ -class Fl_Spinner_Type : public Fl_Widget_Type +class Spinner_Node : public Widget_Node { - typedef Fl_Widget_Type super; - Fl_Menu_Item *subtypes() FL_OVERRIDE { return spinner_type_menu; } - int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) FL_OVERRIDE { - Fl_Spinner *myo = (Fl_Spinner*)(w==4 ? ((Fl_Widget_Type*)factory)->o : o); +public: + typedef Widget_Node super; + static Spinner_Node prototype; +private: + Fl_Menu_Item *subtypes() override { return spinner_type_menu; } + int textstuff(int w, Fl_Font& f, int& s, Fl_Color& c) override { + Fl_Spinner *myo = (Fl_Spinner*)(w==4 ? ((Widget_Node*)factory)->o : o); switch (w) { case 4: case 0: f = (Fl_Font)myo->textfont(); s = myo->textsize(); c = myo->textcolor(); break; @@ -1052,64 +1152,30 @@ class Fl_Spinner_Type : public Fl_Widget_Type return 1; } public: - void ideal_size(int &w, int &h) FL_OVERRIDE { + void ideal_size(int &w, int &h) override { + auto layout = Fluid.proj.layout; h = layout->textsize_not_null() + 8; w = layout->textsize_not_null() * 4 + 8; - Fd_Snap_Action::better_size(w, h); + fld::app::Snap_Action::better_size(w, h); } - const char *type_name() FL_OVERRIDE { return "Fl_Spinner"; } - const char *alt_type_name() FL_OVERRIDE { return "fltk::Spinner"; } - Fl_Widget *widget(int x, int y, int w, int h) FL_OVERRIDE { + const char *type_name() override { return "Fl_Spinner"; } + const char *alt_type_name() override { return "fltk::Spinner"; } + Fl_Widget *widget(int x, int y, int w, int h) override { return new Fl_Spinner(x, y, w, h, "spinner:"); } - Fl_Widget_Type *_make() FL_OVERRIDE { return new Fl_Spinner_Type(); } - ID id() const FL_OVERRIDE { return ID_Spinner; } - bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Spinner) ? true : super::is_a(inID); } + Widget_Node *_make() override { return new Spinner_Node(); } + Type type() const override { return Type::Spinner; } + bool is_a(Type inType) const override { return (inType==Type::Spinner) ? true : super::is_a(inType); } }; -static Fl_Spinner_Type Fl_Spinner_type; +Spinner_Node Spinner_Node::prototype; // ---- Type Factory --------------------------------------------------- MARK: - -extern class Fl_Function_Type Fl_Function_type; -extern class Fl_Code_Type Fl_Code_type; -extern class Fl_CodeBlock_Type Fl_CodeBlock_type; -extern class Fl_Data_Type Fl_Data_type; -extern class Fl_Decl_Type Fl_Decl_type; -extern class Fl_DeclBlock_Type Fl_DeclBlock_type; -extern class Fl_Comment_Type Fl_Comment_type; -extern class Fl_Class_Type Fl_Class_type; -extern class Fl_Window_Type Fl_Window_type; -extern class Fl_Widget_Class_Type Fl_Widget_Class_type; -extern class Fl_Group_Type Fl_Group_type; -extern class Fl_Pack_Type Fl_Pack_type; -extern class Fl_Flex_Type Fl_Flex_type; -extern class Fl_Grid_Type Fl_Grid_type; -extern class Fl_Tabs_Type Fl_Tabs_type; -extern class Fl_Scroll_Type Fl_Scroll_type; -extern class Fl_Table_Type Fl_Table_type; -extern class Fl_Tile_Type Fl_Tile_type; -extern class Fl_Input_Choice_Type Fl_Input_Choice_type; -extern class Fl_Choice_Type Fl_Choice_type; -extern class Fl_Menu_Bar_Type Fl_Menu_Bar_type; -extern class Fl_Menu_Button_Type Fl_Menu_Button_type; -extern class Fl_Menu_Item_Type Fl_Menu_Item_type; -extern class Fl_Checkbox_Menu_Item_Type Fl_Checkbox_Menu_Item_type; -extern class Fl_Radio_Menu_Item_Type Fl_Radio_Menu_Item_type; -extern class Fl_Submenu_Type Fl_Submenu_type; -extern class Fl_Wizard_Type Fl_Wizard_type; - -extern class Fl_Button_Type Fl_Button_type; -extern class Fl_Return_Button_Type Fl_Return_Button_type; -extern class Fl_Light_Button_Type Fl_Light_Button_type; -extern class Fl_Check_Button_Type Fl_Check_Button_type; -extern class Fl_Repeat_Button_Type Fl_Repeat_Button_type; -extern class Fl_Round_Button_Type Fl_Round_Button_type; - -extern void select(Fl_Type *,int); -extern void select_only(Fl_Type *); +extern void select(Node *,int); +extern void select_only(Node *); /** List all known types. @@ -1120,72 +1186,72 @@ extern void select_only(Fl_Type *); \note Make sure that this array stays synchronized to `Fl_Menu_Item New_Menu[]` further down in this file. */ -static Fl_Type *known_types[] = { +static Node *known_types[] = { // functions - (Fl_Type*)&Fl_Function_type, - (Fl_Type*)&Fl_Code_type, - (Fl_Type*)&Fl_CodeBlock_type, - (Fl_Type*)&Fl_Decl_type, - (Fl_Type*)&Fl_DeclBlock_type, - (Fl_Type*)&Fl_Class_type, - (Fl_Type*)&Fl_Widget_Class_type, - (Fl_Type*)&Fl_Comment_type, - (Fl_Type*)&Fl_Data_type, + (Node*)&Function_Node::prototype, + (Node*)&Code_Node::prototype, + (Node*)&CodeBlock_Node::prototype, + (Node*)&Decl_Node::prototype, + (Node*)&DeclBlock_Node::prototype, + (Node*)&Class_Node::prototype, + (Node*)&Widget_Class_Node::prototype, + (Node*)&Comment_Node::prototype, + (Node*)&Data_Node::prototype, // groups - (Fl_Type*)&Fl_Window_type, - (Fl_Type*)&Fl_Group_type, - (Fl_Type*)&Fl_Pack_type, - (Fl_Type*)&Fl_Flex_type, - (Fl_Type*)&Fl_Tabs_type, - (Fl_Type*)&Fl_Scroll_type, - (Fl_Type*)&Fl_Tile_type, - (Fl_Type*)&Fl_Wizard_type, - (Fl_Type*)&Fl_Grid_type, + (Node*)&Window_Node::prototype, + (Node*)&Group_Node::prototype, + (Node*)&Pack_Node::prototype, + (Node*)&Flex_Node::prototype, + (Node*)&Tabs_Node::prototype, + (Node*)&Scroll_Node::prototype, + (Node*)&Tile_Node::prototype, + (Node*)&Wizard_Node::prototype, + (Node*)&Grid_Node::prototype, // buttons - (Fl_Type*)&Fl_Button_type, - (Fl_Type*)&Fl_Return_Button_type, - (Fl_Type*)&Fl_Light_Button_type, - (Fl_Type*)&Fl_Check_Button_type, - (Fl_Type*)&Fl_Repeat_Button_type, - (Fl_Type*)&Fl_Round_Button_type, + (Node*)&Button_Node::prototype, + (Node*)&Return_Button_Node::prototype, + (Node*)&Light_Button_Node::prototype, + (Node*)&Check_Button_Node::prototype, + (Node*)&Repeat_Button_Node::prototype, + (Node*)&Round_Button_Node::prototype, // valuators - (Fl_Type*)&Fl_Slider_type, - (Fl_Type*)&Fl_Scrollbar_type, - (Fl_Type*)&Fl_Value_Slider_type, - (Fl_Type*)&Fl_Adjuster_type, - (Fl_Type*)&Fl_Counter_type, - (Fl_Type*)&Fl_Spinner_type, - (Fl_Type*)&Fl_Dial_type, - (Fl_Type*)&Fl_Roller_type, - (Fl_Type*)&Fl_Value_Input_type, - (Fl_Type*)&Fl_Value_Output_type, + (Node*)&Slider_Node::prototype, + (Node*)&Scrollbar_Node::prototype, + (Node*)&Value_Slider_Node::prototype, + (Node*)&Adjuster_Node::prototype, + (Node*)&Counter_Node::prototype, + (Node*)&Spinner_Node::prototype, + (Node*)&Dial_Node::prototype, + (Node*)&Roller_Node::prototype, + (Node*)&Value_Input_Node::prototype, + (Node*)&Value_Output_Node::prototype, // text - (Fl_Type*)&Fl_Input_type, - (Fl_Type*)&Fl_Output_type, - (Fl_Type*)&Fl_Text_Editor_type, - (Fl_Type*)&Fl_Text_Display_type, - (Fl_Type*)&Fl_File_Input_type, - (Fl_Type*)&Fl_Terminal_type, + (Node*)&Input_Node::prototype, + (Node*)&Output_Node::prototype, + (Node*)&Text_Editor_Node::prototype, + (Node*)&Text_Display_Node::prototype, + (Node*)&File_Input_Node::prototype, + (Node*)&Terminal_Node::prototype, // menus - (Fl_Type*)&Fl_Menu_Bar_type, - (Fl_Type*)&Fl_Menu_Button_type, - (Fl_Type*)&Fl_Choice_type, - (Fl_Type*)&Fl_Input_Choice_type, - (Fl_Type*)&Fl_Submenu_type, - (Fl_Type*)&Fl_Menu_Item_type, - (Fl_Type*)&Fl_Checkbox_Menu_Item_type, - (Fl_Type*)&Fl_Radio_Menu_Item_type, + (Node*)&Menu_Bar_Node::prototype, + (Node*)&Menu_Button_Node::prototype, + (Node*)&Choice_Node::prototype, + (Node*)&Input_Choice_Node::prototype, + (Node*)&Submenu_Node::prototype, + (Node*)&Menu_Item_Node::prototype, + (Node*)&Checkbox_Menu_Item_Node::prototype, + (Node*)&Radio_Menu_Item_Node::prototype, // browsers - (Fl_Type*)&Fl_Browser_type, - (Fl_Type*)&Fl_Check_Browser_type, - (Fl_Type*)&Fl_File_Browser_type, - (Fl_Type*)&Fl_Tree_type, - (Fl_Type*)&Fl_Help_View_type, - (Fl_Type*)&Fl_Table_type, + (Node*)&Browser_Node::prototype, + (Node*)&Check_Browser_Node::prototype, + (Node*)&File_Browser_Node::prototype, + (Node*)&Tree_Node::prototype, + (Node*)&Help_View_Node::prototype, + (Node*)&Table_Node::prototype, // misc - (Fl_Type*)&Fl_Box_type, - (Fl_Type*)&Fl_Clock_type, - (Fl_Type*)&Fl_Progress_type, + (Node*)&Box_Node::prototype, + (Node*)&Clock_Node::prototype, + (Node*)&Progress_Node::prototype, }; /** @@ -1207,19 +1273,21 @@ static Fl_Type *known_types[] = { lower case 't' in type. \param[in] strategy add after current or as last child \param[in] and_open if set to true, call open() on the widget after creating it - \return the newly created type or NULL + \return the newly created type or nullptr \see add_new_widget_from_file(const char*, int) - add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(Node*, int) add_new_widget_from_user(const char*, int) */ -Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open) { - undo_checkpoint(); - undo_suspend(); - Fl_Type *t = ((Fl_Type*)inPrototype)->make(strategy); +Node *add_new_widget_from_user(Node *inPrototype, Strategy strategy, bool and_open) { + Fluid.proj.undo.checkpoint(); + Fluid.proj.undo.suspend(); + auto layout = Fluid.proj.layout; + Node *t = ((Node*)inPrototype)->make(strategy); if (t) { - if (t->is_widget() && !t->is_a(ID_Window)) { - Fl_Widget_Type *wt = (Fl_Widget_Type *)t; + if (t->is_widget() && !t->is_a(Type::Window)) { + auto layout = Fluid.proj.layout; + Widget_Node *wt = (Widget_Node *)t; bool changed = false; // Set font sizes... @@ -1244,71 +1312,71 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool wt->textstuff(2, f, s, c); } - if (changed && t->is_a(ID_Menu_Item)) { - Fl_Type * tt = t->parent; - while (tt && !tt->is_a(ID_Menu_Manager_)) tt = tt->parent; + if (changed && t->is_a(Type::Menu_Item)) { + Node * tt = t->parent; + while (tt && !tt->is_a(Type::Menu_Manager_)) tt = tt->parent; if (tt) - ((Fl_Menu_Manager_Type*)tt)->build_menu(); + ((Menu_Manager_Node*)tt)->build_menu(); } } - if (t->is_true_widget() && !t->is_a(ID_Window)) { + if (t->is_true_widget() && !t->is_a(Type::Window)) { // Resize and/or reposition new widget... - Fl_Widget_Type *wt = (Fl_Widget_Type *)t; + Widget_Node *wt = (Widget_Node *)t; // The parent field is already set at this point, so we can use that // inside ideal_size(). int w = 0, h = 0; wt->ideal_size(w, h); - if ((t->parent && t->parent->is_a(ID_Flex))) { - if (Fl_Window_Type::popupx != 0x7FFFFFFF) - ((Fl_Flex_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); + if ((t->parent && t->parent->is_a(Type::Flex))) { + if (Window_Node::popupx != 0x7FFFFFFF) + ((Flex_Node*)t->parent)->insert_child_at(((Widget_Node*)t)->o, Window_Node::popupx, Window_Node::popupy); t->parent->layout_widget(); - } else if ( wt->is_a(ID_Group) + } else if ( wt->is_a(Type::Group) && wt->parent - && wt->parent->is_a(ID_Tabs) - //&& (Fl_Window_Type::popupx == 0x7FFFFFFF) + && wt->parent->is_a(Type::Tabs) + //&& (Window_Node::popupx == 0x7FFFFFFF) && (layout->top_tabs_margin > 0)) { // If the widget is a group and the parent is tabs and the top tabs // margin is set (and the user is not requesting a specific position) // then prefit the group correctly to the Tabs container. - Fl_Widget *po = ((Fl_Tabs_Type*)wt->parent)->o; + Fl_Widget *po = ((Tabs_Node*)wt->parent)->o; wt->o->resize(po->x(), po->y() + layout->top_tabs_margin, po->w(), po->h() - layout->top_tabs_margin); - } else if ( wt->is_a(ID_Menu_Bar) + } else if ( wt->is_a(Type::Menu_Bar) && wt->parent - && wt->parent->is_a(ID_Window) + && wt->parent->is_a(Type::Window) && (wt->prev == wt->parent)) { // If this is the first child of a window, make the menu bar as wide as // the window and drop it at 0, 0. Otherwise just use the suggested size. w = wt->o->window()->w(); wt->o->resize(0, 0, w, h); } else { - if (Fl_Window_Type::popupx != 0x7FFFFFFF) { + if (Window_Node::popupx != 0x7FFFFFFF) { // If this callback was called from the RMB popup menu in a window, // popupx and popupy will contain the mouse coordinates at RMB event. - wt->o->resize(Fl_Window_Type::popupx, Fl_Window_Type::popupy, w, h); + wt->o->resize(Window_Node::popupx, Window_Node::popupy, w, h); } else { // If popupx is invalid, use the default position and find a good // size for the widget. wt->o->size(w, h); } } - if (t->parent && t->parent->is_a(ID_Grid)) { - if (Fl_Window_Type::popupx != 0x7FFFFFFF) { - ((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy); + if (t->parent && t->parent->is_a(Type::Grid)) { + if (Window_Node::popupx != 0x7FFFFFFF) { + ((Grid_Node*)t->parent)->insert_child_at(((Widget_Node*)t)->o, Window_Node::popupx, Window_Node::popupy); } else { - ((Fl_Grid_Type*)t->parent)->insert_child_at_next_free_cell(((Fl_Widget_Type*)t)->o); + ((Grid_Node*)t->parent)->insert_child_at_next_free_cell(((Widget_Node*)t)->o); } } } - if (t->is_a(ID_Window)) { + if (t->is_a(Type::Window)) { int x = 0, y = 0, w = 480, h = 320; - Fl_Window_Type *wt = (Fl_Window_Type *)t; + Window_Node *wt = (Window_Node *)t; wt->ideal_size(w, h); - if (main_window) { + if (Fluid.main_window) { int sx, sy, sw, sh; - Fl_Window *win = main_window; + Fl_Window *win = Fluid.main_window; int screen = Fl::screen_num(win->x(), win->y()); Fl::screen_work_area(sx, sy, sw, sh, screen); x = sx + sw/2 - w/2; @@ -1318,14 +1386,14 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool } // make the new widget visible select_only(t); - set_modflag(1); + Fluid.proj.set_modflag(1); if (and_open) t->open(); } else { - undo_current --; - undo_last --; + Fluid.proj.undo.current_ --; + Fluid.proj.undo.last_ --; } - undo_resume(); + Fluid.proj.undo.resume(); return t; } @@ -1335,126 +1403,126 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool \param[in] inName find the right prototype by this name \param[in] strategy where to add the node \param[in] and_open if set to true, call open() on the widget after creating it - \return the newly created type or NULL + \return the newly created type or nullptr \see add_new_widget_from_file(const char*, int) - add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(Node*, int) add_new_widget_from_user(const char*, int) */ -Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) { - Fl_Type *prototype = typename_to_prototype(inName); +Node *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open) { + Node *prototype = typename_to_prototype(inName); if (prototype) return add_new_widget_from_user(prototype, strategy, and_open); else - return NULL; + return nullptr; } /** Callback for all non-widget menu items. */ static void cbf(Fl_Widget *, void *v) { - Fl_Type *t = NULL; - if (Fl_Type::current && Fl_Type::current->can_have_children()) - t = ((Fl_Type*)v)->make(Strategy::AS_LAST_CHILD); + Node *t = nullptr; + if (Fluid.proj.tree.current && Fluid.proj.tree.current->can_have_children()) + t = ((Node*)v)->make(Strategy::AS_LAST_CHILD); else - t = ((Fl_Type*)v)->make(Strategy::AFTER_CURRENT); + t = ((Node*)v)->make(Strategy::AFTER_CURRENT); select_only(t); } /** Callback for all widget menu items. - \param[in] v cast to Fl_Type to get the prototype of the type that the user + \param[in] v cast to Node to get the prototype of the type that the user wants to create. */ static void cb(Fl_Widget *, void *v) { - Fl_Type *t = NULL; - if (Fl_Type::current && Fl_Type::current->can_have_children()) - t = add_new_widget_from_user((Fl_Type*)v, Strategy::AS_LAST_CHILD); + Node *t = nullptr; + if (Fluid.proj.tree.current && Fluid.proj.tree.current->can_have_children()) + t = add_new_widget_from_user((Node*)v, Strategy::AS_LAST_CHILD); else - t = add_new_widget_from_user((Fl_Type*)v, Strategy::AFTER_CURRENT); + t = add_new_widget_from_user((Node*)v, Strategy::AFTER_CURRENT); select_only(t); } /** - \note Make sure that this menu stays synchronized to `Fl_Type *known_types[]` + \note Make sure that this menu stays synchronized to `Node *known_types[]` defined further up in this file. */ Fl_Menu_Item New_Menu[] = { -{"Code",0,0,0,FL_SUBMENU}, - {"Function/Method",0,cbf,(void*)&Fl_Function_type}, - {"Code",0,cbf,(void*)&Fl_Code_type}, - {"Code Block",0,cbf,(void*)&Fl_CodeBlock_type}, - {"Declaration",0,cbf,(void*)&Fl_Decl_type}, - {"Declaration Block",0,cbf,(void*)&Fl_DeclBlock_type}, - {"Class",0,cbf,(void*)&Fl_Class_type}, - {"Widget Class",0,cb,(void*)&Fl_Widget_Class_type}, - {"Comment",0,cbf,(void*)&Fl_Comment_type}, - {"Inlined Data",0,cbf,(void*)&Fl_Data_type}, -{0}, -{"Group",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Window_type}, - {0,0,cb,(void*)&Fl_Group_type}, - {0,0,cb,(void*)&Fl_Pack_type}, - {0,0,cb,(void*)&Fl_Flex_type}, - {0,0,cb,(void*)&Fl_Tabs_type}, - {0,0,cb,(void*)&Fl_Scroll_type}, - {0,0,cb,(void*)&Fl_Tile_type}, - {0,0,cb,(void*)&Fl_Wizard_type}, - {0,0,cb,(void*)&Fl_Grid_type}, -{0}, -{"Buttons",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Button_type}, - {0,0,cb,(void*)&Fl_Return_Button_type}, - {0,0,cb,(void*)&Fl_Light_Button_type}, - {0,0,cb,(void*)&Fl_Check_Button_type}, - {0,0,cb,(void*)&Fl_Repeat_Button_type}, - {0,0,cb,(void*)&Fl_Round_Button_type}, -{0}, -{"Valuators",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Slider_type}, - {0,0,cb,(void*)&Fl_Scrollbar_type}, - {0,0,cb,(void*)&Fl_Value_Slider_type}, - {0,0,cb,(void*)&Fl_Adjuster_type}, - {0,0,cb,(void*)&Fl_Counter_type}, - {0,0,cb,(void*)&Fl_Spinner_type}, - {0,0,cb,(void*)&Fl_Dial_type}, - {0,0,cb,(void*)&Fl_Roller_type}, - {0,0,cb,(void*)&Fl_Value_Input_type}, - {0,0,cb,(void*)&Fl_Value_Output_type}, -{0}, -{"Text",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Input_type}, - {0,0,cb,(void*)&Fl_Output_type}, - {0,0,cb,(void*)&Fl_Text_Editor_type}, - {0,0,cb,(void*)&Fl_Text_Display_type}, - {0,0,cb,(void*)&Fl_File_Input_type}, - {0,0,cb,(void*)&Fl_Terminal_type}, -{0}, -{"Menus",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Menu_Bar_type}, - {0,0,cb,(void*)&Fl_Menu_Button_type}, - {0,0,cb,(void*)&Fl_Choice_type}, - {0,0,cb,(void*)&Fl_Input_Choice_type}, - {0,0,cb, (void*)&Fl_Submenu_type}, - {0,0,cb, (void*)&Fl_Menu_Item_type}, - {"Checkbox Menu Item",0,cb, (void*)&Fl_Checkbox_Menu_Item_type}, - {"Radio Menu Item",0,cb, (void*)&Fl_Radio_Menu_Item_type}, -{0}, -{"Browsers",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Browser_type}, - {0,0,cb,(void*)&Fl_Check_Browser_type}, - {0,0,cb,(void*)&Fl_File_Browser_type}, - {0,0,cb,(void*)&Fl_Tree_type}, - {0,0,cb,(void*)&Fl_Help_View_type}, - {0,0,cb,(void*)&Fl_Table_type}, -{0}, -{"Other",0,0,0,FL_SUBMENU}, - {0,0,cb,(void*)&Fl_Box_type}, - {0,0,cb,(void*)&Fl_Clock_type}, - {0,0,cb,(void*)&Fl_Progress_type}, -{0}, -{0}}; + {"Code",0,nullptr,nullptr,FL_SUBMENU}, + {"Function/Method",0,cbf,(void*)&Function_Node::prototype}, + {"Code",0,cbf,(void*)&Code_Node::prototype}, + {"Code Block",0,cbf,(void*)&CodeBlock_Node::prototype}, + {"Declaration",0,cbf,(void*)&Decl_Node::prototype}, + {"Declaration Block",0,cbf,(void*)&DeclBlock_Node::prototype}, + {"Class",0,cbf,(void*)&Class_Node::prototype}, + {"Widget Class",0,cb,(void*)&Widget_Class_Node::prototype}, + {"Comment",0,cbf,(void*)&Comment_Node::prototype}, + {"Inlined Data",0,cbf,(void*)&Data_Node::prototype}, + {nullptr}, + {"Group",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Window_Node::prototype}, + {nullptr,0,cb,(void*)&Group_Node::prototype}, + {nullptr,0,cb,(void*)&Pack_Node::prototype}, + {nullptr,0,cb,(void*)&Flex_Node::prototype}, + {nullptr,0,cb,(void*)&Tabs_Node::prototype}, + {nullptr,0,cb,(void*)&Scroll_Node::prototype}, + {nullptr,0,cb,(void*)&Tile_Node::prototype}, + {nullptr,0,cb,(void*)&Wizard_Node::prototype}, + {nullptr,0,cb,(void*)&Grid_Node::prototype}, + {nullptr}, + {"Buttons",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Button_Node::prototype}, + {nullptr,0,cb,(void*)&Return_Button_Node::prototype}, + {nullptr,0,cb,(void*)&Light_Button_Node::prototype}, + {nullptr,0,cb,(void*)&Check_Button_Node::prototype}, + {nullptr,0,cb,(void*)&Repeat_Button_Node::prototype}, + {nullptr,0,cb,(void*)&Round_Button_Node::prototype}, + {nullptr}, + {"Valuators",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Slider_Node::prototype}, + {nullptr,0,cb,(void*)&Scrollbar_Node::prototype}, + {nullptr,0,cb,(void*)&Value_Slider_Node::prototype}, + {nullptr,0,cb,(void*)&Adjuster_Node::prototype}, + {nullptr,0,cb,(void*)&Counter_Node::prototype}, + {nullptr,0,cb,(void*)&Spinner_Node::prototype}, + {nullptr,0,cb,(void*)&Dial_Node::prototype}, + {nullptr,0,cb,(void*)&Roller_Node::prototype}, + {nullptr,0,cb,(void*)&Value_Input_Node::prototype}, + {nullptr,0,cb,(void*)&Value_Output_Node::prototype}, + {nullptr}, + {"Text",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Input_Node::prototype}, + {nullptr,0,cb,(void*)&Output_Node::prototype}, + {nullptr,0,cb,(void*)&Text_Editor_Node::prototype}, + {nullptr,0,cb,(void*)&Text_Display_Node::prototype}, + {nullptr,0,cb,(void*)&File_Input_Node::prototype}, + {nullptr,0,cb,(void*)&Terminal_Node::prototype}, + {nullptr}, + {"Menus",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Menu_Bar_Node::prototype}, + {nullptr,0,cb,(void*)&Menu_Button_Node::prototype}, + {nullptr,0,cb,(void*)&Choice_Node::prototype}, + {nullptr,0,cb,(void*)&Input_Choice_Node::prototype}, + {nullptr,0,cb, (void*)&Submenu_Node::prototype}, + {nullptr,0,cb, (void*)&Menu_Item_Node::prototype}, + {"Checkbox Menu Item",0,cb, (void*)&Checkbox_Menu_Item_Node::prototype}, + {"Radio Menu Item",0,cb, (void*)&Radio_Menu_Item_Node::prototype}, + {nullptr}, + {"Browsers",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Browser_Node::prototype}, + {nullptr,0,cb,(void*)&Check_Browser_Node::prototype}, + {nullptr,0,cb,(void*)&File_Browser_Node::prototype}, + {nullptr,0,cb,(void*)&Tree_Node::prototype}, + {nullptr,0,cb,(void*)&Help_View_Node::prototype}, + {nullptr,0,cb,(void*)&Table_Node::prototype}, + {nullptr}, + {"Other",0,nullptr,nullptr,FL_SUBMENU}, + {nullptr,0,cb,(void*)&Box_Node::prototype}, + {nullptr,0,cb,(void*)&Clock_Node::prototype}, + {nullptr,0,cb,(void*)&Progress_Node::prototype}, + {nullptr}, + {nullptr}}; #include @@ -1464,8 +1532,8 @@ Fl_Menu_Item New_Menu[] = { The icon may be null. If ic is null only the text is assigned to the label and Fl_Multi_Label is not used. \param[in] mi pointer to tme menu item that will be modified - \param[in] ic icon for the menu, may be NULL - \param[in] txt new label text, may *not* be NULL, will not be copied + \param[in] ic icon for the menu, may be nullptr + \param[in] txt new label text, may *not* be nullptr, will not be copied */ static void make_iconlabel(Fl_Menu_Item *mi, Fl_Image *ic, const char *txt) { @@ -1495,14 +1563,14 @@ void fill_in_New_Menu() { for (unsigned i = 0; i < sizeof(New_Menu)/sizeof(*New_Menu); i++) { Fl_Menu_Item *m = New_Menu+i; if (m->user_data()) { - Fl_Type *t = (Fl_Type*)m->user_data(); + Node *t = (Node*)m->user_data(); if (m->text) { - make_iconlabel( m, pixmap[t->id()], m->label() ); + make_iconlabel( m, pixmap[(int)t->type()], m->label() ); } else { const char *n = t->type_name(); if (!strncmp(n,"Fl_",3)) n += 3; if (!strncmp(n,"fltk::",6)) n += 6; - make_iconlabel( m, pixmap[t->id()], n ); + make_iconlabel( m, pixmap[(int)t->type()], n ); } } } @@ -1511,21 +1579,21 @@ void fill_in_New_Menu() { /** Find the correct prototype for a given type name. \param[in] inName a C string that must match type_name() or alt_type_name() of - one of the known Fl_Type classes. - \return the matching prototype or NULL + one of the known Node classes. + \return the matching prototype or nullptr */ -Fl_Type *typename_to_prototype(const char *inName) +Node *typename_to_prototype(const char *inName) { - if (inName==NULL || *inName==0) - return NULL; + if (inName==nullptr || *inName==0) + return nullptr; for (unsigned i = 0; i < sizeof(known_types)/sizeof(*known_types); i++) { - Fl_Type *prototype = known_types[i]; + Node *prototype = known_types[i]; if (fl_ascii_strcasecmp(inName, prototype->type_name())==0) return prototype; if (fl_ascii_strcasecmp(inName, prototype->alt_type_name())==0) return prototype; } - return NULL; + return nullptr; } /** @@ -1537,16 +1605,16 @@ Fl_Type *typename_to_prototype(const char *inName) \param[in] inName a C string that described the type we want \param[in] strategy add after current or as last child - \return the type node that was created or NULL + \return the type node that was created or nullptr \see add_new_widget_from_file(const char*, int) - add_new_widget_from_user(Fl_Type*, int) + add_new_widget_from_user(Node*, int) add_new_widget_from_user(const char*, int) */ -Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy) { - Fl_Type *prototype = typename_to_prototype(inName); +Node *add_new_widget_from_file(const char *inName, Strategy strategy) { + Node *prototype = typename_to_prototype(inName); if (!prototype) - return NULL; - Fl_Type *new_node = prototype->make(strategy); + return nullptr; + Node *new_node = prototype->make(strategy); return new_node; } diff --git a/fluid/nodes/factory.h b/fluid/nodes/factory.h index f1968b167..172f7e5d4 100644 --- a/fluid/nodes/factory.h +++ b/fluid/nodes/factory.h @@ -1,5 +1,5 @@ // -// Widget type header file for the Fast Light Tool Kit (FLTK). +// Node Factory header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2021 by Bill Spitzak and others. // @@ -14,21 +14,21 @@ // https://www.fltk.org/bugs.php // -#ifndef _FLUID_FACTORY_H -#define _FLUID_FACTORY_H +#ifndef FLUID_NODES_FACTORY_H +#define FLUID_NODES_FACTORY_H -#include "nodes/Fl_Type.h" +#include "nodes/Node.h" struct Fl_Menu_Item; extern Fl_Menu_Item New_Menu[]; void fill_in_New_Menu(); -Fl_Type *typename_to_prototype(const char *inName); +Node *typename_to_prototype(const char *inName); -Fl_Type *add_new_widget_from_file(const char *inName, Strategy strategy); -Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy, bool and_open=true); -Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open=true); +Node *add_new_widget_from_file(const char *inName, Strategy strategy); +Node *add_new_widget_from_user(Node *inPrototype, Strategy strategy, bool and_open=true); +Node *add_new_widget_from_user(const char *inName, Strategy strategy, bool and_open=true); -#endif // _FLUID_FACTORY_H +#endif // FLUID_NODES_FACTORY_H diff --git a/fluid/panels/about_panel.cxx b/fluid/panels/about_panel.cxx index ab36ddc10..6c78314dd 100644 --- a/fluid/panels/about_panel.cxx +++ b/fluid/panels/about_panel.cxx @@ -17,7 +17,6 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "about_panel.h" -void show_help(const char *name); Fl_Double_Window *about_panel=(Fl_Double_Window *)0; @@ -140,14 +139,14 @@ static const unsigned char idata_fluid[] = 99,199,176,225,186,61,16,35,74,220,19,2,0,59}; static Fl_Image *image_fluid() { Fl_GIF_Image::animate = true; - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_Anim_GIF_Image("fluid.animated.gif", idata_fluid, 2545); return image; } static void cb_View(Fl_Button*, void*) { - show_help("license.html"); + Fluid.show_help("license.html"); } static void cb_Close(Fl_Return_Button* o, void*) { diff --git a/fluid/panels/about_panel.fl b/fluid/panels/about_panel.fl index 3b5d54b72..7e7feba5f 100644 --- a/fluid/panels/about_panel.fl +++ b/fluid/panels/about_panel.fl @@ -20,10 +20,10 @@ comment {// } {in_source in_header } -decl {\#include } {public global +decl {\#include "Fluid.h"} {public global } -decl {void show_help(const char *name);} {public local +decl {\#include } {public global } Function {make_about_panel()} {open @@ -60,7 +60,7 @@ Version x.x.x} } Fl_Button {} { label {View License...} - callback {show_help("license.html");} + callback {Fluid.show_help("license.html");} xywh {115 145 123 25} labelcolor 136 } Fl_Return_Button {} { diff --git a/fluid/panels/about_panel.h b/fluid/panels/about_panel.h index 0130a1e44..421b1d40c 100644 --- a/fluid/panels/about_panel.h +++ b/fluid/panels/about_panel.h @@ -19,8 +19,8 @@ #ifndef about_panel_h #define about_panel_h #include +#include "Fluid.h" #include -extern void show_help(const char *name); #include #include "../src/flstring.h" extern Fl_Double_Window *about_panel; diff --git a/fluid/panels/codeview_panel.cxx b/fluid/panels/codeview_panel.cxx index c1c6a1d65..745ad0ad1 100644 --- a/fluid/panels/codeview_panel.cxx +++ b/fluid/panels/codeview_panel.cxx @@ -17,19 +17,20 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "codeview_panel.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include "io/Project_Reader.h" #include "io/Project_Writer.h" +#include "io/String_Writer.h" #include #include #include "../src/flstring.h" -static char *cv_source_filename = NULL; -static char *cv_header_filename = NULL; -static char *cv_design_filename = NULL; +static char *cv_source_filename = nullptr; +static char *cv_header_filename = nullptr; +static char *cv_design_filename = nullptr; int cv_code_choice; -extern void select_only(Fl_Type *o); -extern void reveal_in_browser(Fl_Type *t); +extern void select_only(Node *o); +extern void reveal_in_browser(Node *t); /** Update the header and source code highlighting depending on the @@ -45,29 +46,29 @@ void update_codeview_position() { return; if (cv_autoposition->value()==0) return; - if (codeview_panel && codeview_panel->visible() && Fl_Type::current) { + if (codeview_panel && codeview_panel->visible() && Fluid.proj.tree.current) { int pos0 = 0, pos1 = 0; if (cv_source->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code2_end; break; case 1: // static: callbacks, menu declarations - pos0 = Fl_Type::current->code_static_start; - pos1 = Fl_Type::current->code_static_end; + pos0 = Fluid.proj.tree.current->code_static_start; + pos1 = Fluid.proj.tree.current->code_static_end; break; case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code1_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->code2_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code2_start; + pos1 = Fluid.proj.tree.current->code2_end; break; } if (pos0>=0) { @@ -82,20 +83,20 @@ void update_codeview_position() { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations - pos0 = Fl_Type::current->header_static_start; - pos1 = Fl_Type::current->header_static_end; + pos0 = Fluid.proj.tree.current->header_static_start; + pos1 = Fluid.proj.tree.current->header_static_end; break; case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->header1_start; - pos1 = Fl_Type::current->header2_end; + pos0 = Fluid.proj.tree.current->header1_start; + pos1 = Fluid.proj.tree.current->header2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->header1_start; - pos1 = Fl_Type::current->header1_end; + pos0 = Fluid.proj.tree.current->header1_start; + pos1 = Fluid.proj.tree.current->header1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->header2_start; - pos1 = Fl_Type::current->header2_end; + pos0 = Fluid.proj.tree.current->header2_start; + pos1 = Fluid.proj.tree.current->header2_end; break; } if (pos0>=0) { @@ -111,16 +112,16 @@ void update_codeview_position() { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->proj1_start; - pos1 = Fl_Type::current->proj2_end; + pos0 = Fluid.proj.tree.current->proj1_start; + pos1 = Fluid.proj.tree.current->proj2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->proj1_start; - pos1 = Fl_Type::current->proj1_end; + pos0 = Fluid.proj.tree.current->proj1_start; + pos1 = Fluid.proj.tree.current->proj1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->proj2_start; - pos1 = Fl_Type::current->proj2_end; + pos0 = Fluid.proj.tree.current->proj2_start; + pos1 = Fluid.proj.tree.current->proj2_end; break; } if (pos0>=0) { @@ -154,43 +155,43 @@ void update_codeview_cb(class Fl_Button*, void*) { if (!cv_source_filename) { cv_source_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_source_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX); } if (!cv_header_filename) { cv_header_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_header_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX); } if (!cv_design_filename) { cv_design_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_design_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX); } if (cv_project->visible_r()) { - fld::io::write_file(cv_design_filename, false, true); + fld::io::write_file(Fluid.proj, cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); } else if (cv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; char fn[FL_PATH_MAX+1]; - fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(fn, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); - fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); - write_strings(fn); + fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast(Fluid.proj.i18n_type)]); + fld::io::write_strings(Fluid.proj, fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); cv_strings->scroll(top, 0); } else if (cv_source->visible_r() || cv_header->visible_r()) { - std::string code_file_name_bak = g_project.code_file_name; - g_project.code_file_name = cv_source_filename; - std::string header_file_name_bak = g_project.header_file_name; - g_project.header_file_name = cv_header_filename; + std::string code_file_name_bak = Fluid.proj.code_file_name; + Fluid.proj.code_file_name = cv_source_filename; + std::string header_file_name_bak = Fluid.proj.header_file_name; + Fluid.proj.header_file_name = cv_header_filename; // generate the code and load the files - fld::io::Code_Writer f; + fld::io::Code_Writer f(Fluid.proj); // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { @@ -206,8 +207,8 @@ void update_codeview_cb(class Fl_Button*, void*) { update_codeview_position(); } - g_project.code_file_name = code_file_name_bak; - g_project.header_file_name = header_file_name_bak; + Fluid.proj.code_file_name = code_file_name_bak; + Fluid.proj.header_file_name = header_file_name_bak; } } @@ -236,7 +237,7 @@ void codeview_toggle_visibility() { if (!codeview_panel) { make_codeview(); codeview_panel->callback((Fl_Callback*)toggle_codeview_cb); - Fl_Preferences svp(fluid_prefs, "codeview"); + Fl_Preferences svp(Fluid.preferences, "codeview"); int autorefresh; svp.get("autorefresh", autorefresh, 1); cv_autorefresh->value(autorefresh); @@ -248,15 +249,15 @@ void codeview_toggle_visibility() { if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab)); svp.get("code_choice", cv_code_choice, 2); cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice)); - if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; + if (!Fluid.position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; } if (codeview_panel->visible()) { codeview_panel->hide(); - codeview_item->label("Show Code View"); + Fluid.codeview_item->label("Show Code View"); } else { codeview_panel->show(); - codeview_item->label("Hide Code View"); + Fluid.codeview_item->label("Hide Code View"); update_codeview_cb(0,0); } } @@ -282,7 +283,7 @@ Fl_Button *cv_find_text_case=(Fl_Button *)0; Fl_Input *cv_find_text=(Fl_Input *)0; static void cb_cv_find_text(Fl_Input* o, void*) { - Fl_Text_Display *e = NULL; + Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -303,7 +304,7 @@ static void cb_cv_find_text(Fl_Input* o, void*) { } static void cb_(Fl_Button*, void*) { - Fl_Text_Display *e = NULL; + Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -328,7 +329,7 @@ static void cb_(Fl_Button*, void*) { } static void cb_1(Fl_Button*, void*) { - Fl_Text_Display *e = NULL; + Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -354,13 +355,13 @@ static void cb_1(Fl_Button*, void*) { static void cb_Reveal(Fl_Button*, void*) { if (codeview_panel && codeview_panel->visible()) { - Fl_Type *node = NULL; + Node *node = nullptr; if (cv_source->visible_r()) - node = Fl_Type::find_in_text(0, cv_source->insert_position()); + node = Fluid.proj.tree.find_in_text(0, cv_source->insert_position()); else if (cv_header->visible_r()) - node = Fl_Type::find_in_text(1, cv_header->insert_position()); + node = Fluid.proj.tree.find_in_text(1, cv_header->insert_position()); else if (cv_project->visible_r()) - node = Fl_Type::find_in_text(2, cv_project->insert_position()); + node = Fluid.proj.tree.find_in_text(2, cv_project->insert_position()); if (node) { select_only(node); reveal_in_browser(node); diff --git a/fluid/panels/codeview_panel.fl b/fluid/panels/codeview_panel.fl index ce40ffd8a..fc62fee51 100644 --- a/fluid/panels/codeview_panel.fl +++ b/fluid/panels/codeview_panel.fl @@ -20,10 +20,10 @@ comment {// } {in_source in_header } -decl {\#include "app/fluid.h"} {private local +decl {\#include "Fluid.h"} {private local } -decl {\#include "app/project.h"} {private local +decl {\#include "Project.h"} {private local } decl {\#include "io/Project_Reader.h"} {private local @@ -32,6 +32,9 @@ decl {\#include "io/Project_Reader.h"} {private local decl {\#include "io/Project_Writer.h"} {private local } +decl {\#include "io/String_Writer.h"} {private local +} + decl {\#include } {private local } @@ -41,22 +44,22 @@ decl {\#include } {private local decl {\#include "../src/flstring.h"} {selected private local } -decl {char *cv_source_filename = NULL;} {private local +decl {char *cv_source_filename = nullptr;} {private local } -decl {char *cv_header_filename = NULL;} {private local +decl {char *cv_header_filename = nullptr;} {private local } -decl {char *cv_design_filename = NULL;} {private local +decl {char *cv_design_filename = nullptr;} {private local } decl {int cv_code_choice;} {public local } -decl {extern void select_only(Fl_Type *o);} {private global +decl {extern void select_only(Node *o);} {private global } -decl {extern void reveal_in_browser(Fl_Type *t);} {private global +decl {extern void reveal_in_browser(Node *t);} {private global } Function {update_codeview_position()} { @@ -72,29 +75,29 @@ file.} open return_type void return; if (cv_autoposition->value()==0) return; - if (codeview_panel && codeview_panel->visible() && Fl_Type::current) { + if (codeview_panel && codeview_panel->visible() && Fluid.proj.tree.current) { int pos0 = 0, pos1 = 0; if (cv_source->visible_r()) { switch (cv_code_choice) { case 0: // prolog: not yet (include statements) - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code2_end; break; case 1: // static: callbacks, menu declarations - pos0 = Fl_Type::current->code_static_start; - pos1 = Fl_Type::current->code_static_end; + pos0 = Fluid.proj.tree.current->code_static_start; + pos1 = Fluid.proj.tree.current->code_static_end; break; case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->code1_start; - pos1 = Fl_Type::current->code1_end; + pos0 = Fluid.proj.tree.current->code1_start; + pos1 = Fluid.proj.tree.current->code1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->code2_start; - pos1 = Fl_Type::current->code2_end; + pos0 = Fluid.proj.tree.current->code2_start; + pos1 = Fluid.proj.tree.current->code2_end; break; } if (pos0>=0) { @@ -109,20 +112,20 @@ file.} open return_type void switch (cv_code_choice) { case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations - pos0 = Fl_Type::current->header_static_start; - pos1 = Fl_Type::current->header_static_end; + pos0 = Fluid.proj.tree.current->header_static_start; + pos1 = Fluid.proj.tree.current->header_static_end; break; case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->header1_start; - pos1 = Fl_Type::current->header2_end; + pos0 = Fluid.proj.tree.current->header1_start; + pos1 = Fluid.proj.tree.current->header2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->header1_start; - pos1 = Fl_Type::current->header1_end; + pos0 = Fluid.proj.tree.current->header1_start; + pos1 = Fluid.proj.tree.current->header1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->header2_start; - pos1 = Fl_Type::current->header2_end; + pos0 = Fluid.proj.tree.current->header2_start; + pos1 = Fluid.proj.tree.current->header2_end; break; } if (pos0>=0) { @@ -138,16 +141,16 @@ file.} open return_type void case 0: // prolog: not yet (include statements) case 1: // static: callbacks, menu declarations case 2: // code: entire implementation block including children - pos0 = Fl_Type::current->proj1_start; - pos1 = Fl_Type::current->proj2_end; + pos0 = Fluid.proj.tree.current->proj1_start; + pos1 = Fluid.proj.tree.current->proj2_end; break; case 3: // code1: all implementation code before the children - pos0 = Fl_Type::current->proj1_start; - pos1 = Fl_Type::current->proj1_end; + pos0 = Fluid.proj.tree.current->proj1_start; + pos1 = Fluid.proj.tree.current->proj1_end; break; case 4: // code1: all implementation code before the children - pos0 = Fl_Type::current->proj2_start; - pos1 = Fl_Type::current->proj2_end; + pos0 = Fluid.proj.tree.current->proj2_start; + pos1 = Fluid.proj.tree.current->proj2_end; break; } if (pos0>=0) { @@ -179,43 +182,43 @@ and load those into the Code Viewer widgets.} open return_type void if (!cv_source_filename) { cv_source_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_source_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX); } if (!cv_header_filename) { cv_header_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_header_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX); } if (!cv_design_filename) { cv_design_filename = (char*)malloc(FL_PATH_MAX); - fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(cv_design_filename, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX); } if (cv_project->visible_r()) { - fld::io::write_file(cv_design_filename, false, true); + fld::io::write_file(Fluid.proj, cv_design_filename, false, true); int top = cv_project->top_line(); cv_project->buffer()->loadfile(cv_design_filename); cv_project->scroll(top, 0); } else if (cv_strings->visible_r()) { static const char *exts[] = { ".txt", ".po", ".msg" }; char fn[FL_PATH_MAX+1]; - fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX); + fl_strlcpy(fn, Fluid.get_tmpdir().c_str(), FL_PATH_MAX); fl_strlcat(fn, "strings", FL_PATH_MAX); - fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]); - write_strings(fn); + fl_filename_setext(fn, FL_PATH_MAX, exts[static_cast(Fluid.proj.i18n_type)]); + fld::io::write_strings(Fluid.proj, fn); int top = cv_strings->top_line(); cv_strings->buffer()->loadfile(fn); cv_strings->scroll(top, 0); } else if (cv_source->visible_r() || cv_header->visible_r()) { - std::string code_file_name_bak = g_project.code_file_name; - g_project.code_file_name = cv_source_filename; - std::string header_file_name_bak = g_project.header_file_name; - g_project.header_file_name = cv_header_filename; + std::string code_file_name_bak = Fluid.proj.code_file_name; + Fluid.proj.code_file_name = cv_source_filename; + std::string header_file_name_bak = Fluid.proj.header_file_name; + Fluid.proj.header_file_name = cv_header_filename; // generate the code and load the files - fld::io::Code_Writer f; + fld::io::Code_Writer f(Fluid.proj); // generate files if (f.write_code(cv_source_filename, cv_header_filename, true)) { @@ -231,8 +234,8 @@ and load those into the Code Viewer widgets.} open return_type void update_codeview_position(); } - g_project.code_file_name = code_file_name_bak; - g_project.header_file_name = header_file_name_bak; + Fluid.proj.code_file_name = code_file_name_bak; + Fluid.proj.header_file_name = header_file_name_bak; }} {} } @@ -260,7 +263,7 @@ The state is stored in the app preferences. code {if (!codeview_panel) { make_codeview(); codeview_panel->callback((Fl_Callback*)toggle_codeview_cb); - Fl_Preferences svp(fluid_prefs, "codeview"); + Fl_Preferences svp(Fluid.preferences, "codeview"); int autorefresh; svp.get("autorefresh", autorefresh, 1); cv_autorefresh->value(autorefresh); @@ -272,15 +275,15 @@ The state is stored in the app preferences. if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab)); svp.get("code_choice", cv_code_choice, 2); cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice)); - if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; + if (!Fluid.position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return; } if (codeview_panel->visible()) { codeview_panel->hide(); - codeview_item->label("Show Code View"); + Fluid.codeview_item->label("Show Code View"); } else { codeview_panel->show(); - codeview_item->label("Hide Code View"); + Fluid.codeview_item->label("Hide Code View"); update_codeview_cb(0,0); }} {} } @@ -354,7 +357,7 @@ Function {make_codeview()} {open } Fl_Input cv_find_text { label {Find:} - callback {Fl_Text_Display *e = NULL; + callback {Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -376,7 +379,7 @@ if (e) { } Fl_Button {} { label {<<} - callback {Fl_Text_Display *e = NULL; + callback {Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -402,7 +405,7 @@ if (e) { } Fl_Button {} { label {>>} - callback {Fl_Text_Display *e = NULL; + callback {Fl_Text_Display *e = nullptr; if (cv_source->visible_r()) { e = cv_source; } else if (cv_header->visible_r()) { @@ -429,13 +432,13 @@ if (e) { Fl_Button {} { label Reveal callback {if (codeview_panel && codeview_panel->visible()) { - Fl_Type *node = NULL; + Node *node = nullptr; if (cv_source->visible_r()) - node = Fl_Type::find_in_text(0, cv_source->insert_position()); + node = Fluid.proj.tree.find_in_text(0, cv_source->insert_position()); else if (cv_header->visible_r()) - node = Fl_Type::find_in_text(1, cv_header->insert_position()); + node = Fluid.proj.tree.find_in_text(1, cv_header->insert_position()); else if (cv_project->visible_r()) - node = Fl_Type::find_in_text(2, cv_project->insert_position()); + node = Fluid.proj.tree.find_in_text(2, cv_project->insert_position()); if (node) { select_only(node); reveal_in_browser(node); diff --git a/fluid/panels/function_panel.cxx b/fluid/panels/function_panel.cxx index 4ef8fac64..3703cb157 100644 --- a/fluid/panels/function_panel.cxx +++ b/fluid/panels/function_panel.cxx @@ -17,9 +17,9 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "function_panel.h" -#include "app/fluid.h" -#include "app/undo.h" -#include "nodes/Fl_Type.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "nodes/Node.h" #include "nodes/factory.h" #include "rsrcs/pixmaps.h" #include "widgets/Bin_Button.h" @@ -765,7 +765,7 @@ Fl_Double_Window* make_comment_panel() { void type_make_cb(Fl_Widget*,void*d) { const char *type_name = (const char*)d; - if (Fl_Type::current && Fl_Type::current->can_have_children()) + if (Fluid.proj.tree.current && Fluid.proj.tree.current->can_have_children()) add_new_widget_from_user(type_name, Strategy::AS_LAST_CHILD); else add_new_widget_from_user(type_name, Strategy::AFTER_CURRENT); @@ -773,11 +773,11 @@ void type_make_cb(Fl_Widget*,void*d) { Fl_Window *widgetbin_panel=(Fl_Window *)0; -static void cb_widgetbin_panel(Fl_Window* o, void* v) { +static void cb_widgetbin_panel(Fl_Window*, void*) { if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) - exit_cb((Fl_Widget*)o, v); + Fluid.quit(); else - toggle_widgetbin_cb((Fl_Widget*)o, v); + Fluid.toggle_widget_bin(); } Fl_Window* make_widgetbin() { @@ -790,31 +790,31 @@ Fl_Window* make_widgetbin() { o->tooltip("Function"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Function")); - o->image(pixmap[ID_Function]); + o->image(pixmap[(int)Type::Function]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 21, 24, 24); o->tooltip("Class"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Class")); - o->image(pixmap[ID_Class]); + o->image(pixmap[(int)Type::Class]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(55, 21, 24, 24); o->tooltip("Comment"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("comment")); - o->image(pixmap[ID_Comment]); + o->image(pixmap[(int)Type::Comment]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(5, 46, 24, 24); o->tooltip("Code"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("Code")); - o->image(pixmap[ID_Code]); + o->image(pixmap[(int)Type::Code]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 46, 24, 24); o->tooltip("Code Block"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("CodeBlock")); - o->image(pixmap[ID_CodeBlock]); + o->image(pixmap[(int)Type::CodeBlock]); } // Fl_Button* o { fld::widget::Bin_Window_Button* o = new fld::widget::Bin_Window_Button(55, 46, 24, 24); o->tooltip("Widget Class"); @@ -828,25 +828,25 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("widget_class")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Widget_Class]); + o->image(pixmap[(int)Type::Widget_Class]); } // fld::widget::Bin_Window_Button* o { Fl_Button* o = new Fl_Button(5, 71, 24, 24); o->tooltip("Declaration"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("decl")); - o->image(pixmap[ID_Decl]); + o->image(pixmap[(int)Type::Decl]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(30, 71, 24, 24); o->tooltip("Declaration Block"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("declblock")); - o->image(pixmap[ID_DeclBlock]); + o->image(pixmap[(int)Type::DeclBlock]); } // Fl_Button* o { Fl_Button* o = new Fl_Button(55, 71, 24, 24); o->tooltip("Inline Data"); o->box(FL_THIN_UP_BOX); o->callback((Fl_Callback*)type_make_cb, (void*)("data")); - o->image(pixmap[ID_Data]); + o->image(pixmap[(int)Type::Data]); } // Fl_Button* o o->end(); } // Fl_Group* o @@ -864,7 +864,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Window")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Window]); + o->image(pixmap[(int)Type::Window]); } // fld::widget::Bin_Window_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(114, 21, 24, 24); o->tooltip("Group"); @@ -878,7 +878,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Group")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Group]); + o->image(pixmap[(int)Type::Group]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(139, 21, 24, 24); o->tooltip("Pack"); @@ -892,7 +892,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Pack")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Pack]); + o->image(pixmap[(int)Type::Pack]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(89, 46, 24, 24); o->tooltip("Tabs"); @@ -906,7 +906,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tabs")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Tabs]); + o->image(pixmap[(int)Type::Tabs]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(114, 46, 24, 24); o->tooltip("Scroll"); @@ -920,7 +920,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scroll")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Scroll]); + o->image(pixmap[(int)Type::Scroll]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(139, 46, 24, 24); o->tooltip("Flex"); @@ -934,7 +934,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Flex")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Flex]); + o->image(pixmap[(int)Type::Flex]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(89, 71, 24, 24); o->tooltip("Tile"); @@ -948,7 +948,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tile")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Tile]); + o->image(pixmap[(int)Type::Tile]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(114, 71, 24, 24); o->tooltip("Wizard"); @@ -962,7 +962,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Wizard")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Wizard]); + o->image(pixmap[(int)Type::Wizard]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(139, 71, 24, 24); o->tooltip("Grid"); @@ -976,7 +976,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Grid")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Grid]); + o->image(pixmap[(int)Type::Grid]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -994,7 +994,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Button]); + o->image(pixmap[(int)Type::Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(198, 21, 24, 24); o->tooltip("Return Button"); @@ -1008,7 +1008,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Return_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Return_Button]); + o->image(pixmap[(int)Type::Return_Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(173, 46, 24, 24); o->tooltip("Light Button"); @@ -1022,7 +1022,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Light_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Light_Button]); + o->image(pixmap[(int)Type::Light_Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(198, 46, 24, 24); o->tooltip("Repeat Button"); @@ -1036,7 +1036,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Repeat_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Repeat_Button]); + o->image(pixmap[(int)Type::Repeat_Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(173, 71, 24, 24); o->tooltip("Check Button"); @@ -1050,7 +1050,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Check_Button]); + o->image(pixmap[(int)Type::Check_Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(198, 71, 24, 24); o->tooltip("Round Button"); @@ -1064,7 +1064,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Round_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Round_Button]); + o->image(pixmap[(int)Type::Round_Button]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -1082,7 +1082,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Slider")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Slider]); + o->image(pixmap[(int)Type::Slider]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(257, 21, 24, 24); o->tooltip("Scroll Bar"); @@ -1096,7 +1096,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Scrollbar")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Scrollbar]); + o->image(pixmap[(int)Type::Scrollbar]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(282, 21, 24, 24); o->tooltip("Value Slider"); @@ -1110,7 +1110,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Slider")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Value_Slider]); + o->image(pixmap[(int)Type::Value_Slider]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(307, 21, 24, 24); o->tooltip("Value Output"); @@ -1124,7 +1124,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Output")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Value_Output]); + o->image(pixmap[(int)Type::Value_Output]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(232, 46, 24, 24); o->tooltip("Adjuster"); @@ -1138,7 +1138,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Adjuster")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Adjuster]); + o->image(pixmap[(int)Type::Adjuster]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(257, 46, 24, 24); o->tooltip("Counter"); @@ -1152,7 +1152,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Counter")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Counter]); + o->image(pixmap[(int)Type::Counter]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(282, 46, 24, 24); o->tooltip("Dial"); @@ -1166,7 +1166,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Dial")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Dial]); + o->image(pixmap[(int)Type::Dial]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(232, 71, 24, 24); o->tooltip("Roller"); @@ -1180,7 +1180,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Roller")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Roller]); + o->image(pixmap[(int)Type::Roller]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(257, 71, 24, 24); o->tooltip("Spinner"); @@ -1194,7 +1194,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Spinner")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Spinner]); + o->image(pixmap[(int)Type::Spinner]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(282, 71, 24, 24); o->tooltip("Value Input"); @@ -1208,7 +1208,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Value_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Value_Input]); + o->image(pixmap[(int)Type::Value_Input]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -1226,7 +1226,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Input]); + o->image(pixmap[(int)Type::Input]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(366, 21, 24, 24); o->tooltip("Output"); @@ -1240,7 +1240,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Output")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Output]); + o->image(pixmap[(int)Type::Output]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(341, 46, 24, 24); o->tooltip("Text Edit"); @@ -1254,7 +1254,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Editor")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Text_Editor]); + o->image(pixmap[(int)Type::Text_Editor]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(366, 46, 24, 24); o->tooltip("Text Display"); @@ -1268,7 +1268,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Text_Display")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Text_Display]); + o->image(pixmap[(int)Type::Text_Display]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(341, 71, 24, 24); o->tooltip("File Input"); @@ -1282,7 +1282,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Input")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_File_Input]); + o->image(pixmap[(int)Type::File_Input]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(366, 71, 24, 24); o->tooltip("Terminal"); @@ -1296,7 +1296,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Terminal")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Terminal]); + o->image(pixmap[(int)Type::Terminal]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -1314,7 +1314,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Input_Choice")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Input_Choice]); + o->image(pixmap[(int)Type::Input_Choice]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(425, 21, 24, 24); o->tooltip("Menu Item"); @@ -1328,7 +1328,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("menuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Menu_Item]); + o->image(pixmap[(int)Type::Menu_Item]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(450, 21, 24, 24); o->tooltip("Menu Bar"); @@ -1342,7 +1342,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Bar")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Menu_Bar]); + o->image(pixmap[(int)Type::Menu_Bar]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(400, 46, 24, 24); o->tooltip("Menu Button"); @@ -1356,7 +1356,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Menu_Button")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Menu_Button]); + o->image(pixmap[(int)Type::Menu_Button]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(425, 46, 24, 24); o->tooltip("Checkbox Menu Item"); @@ -1370,7 +1370,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("checkmenuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Checkbox_Menu_Item]); + o->image(pixmap[(int)Type::Checkbox_Menu_Item]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(450, 46, 24, 24); o->tooltip("Sub Menu"); @@ -1384,7 +1384,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("submenu")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Submenu]); + o->image(pixmap[(int)Type::Submenu]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(400, 71, 24, 24); o->tooltip("Choice"); @@ -1398,7 +1398,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Choice")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Choice]); + o->image(pixmap[(int)Type::Choice]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(425, 71, 24, 24); o->tooltip("Radio Menu Item"); @@ -1412,7 +1412,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("radiomenuitem")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Radio_Menu_Item]); + o->image(pixmap[(int)Type::Radio_Menu_Item]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -1430,7 +1430,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Browser]); + o->image(pixmap[(int)Type::Browser]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(509, 21, 24, 24); o->tooltip("Tree"); @@ -1444,7 +1444,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Tree")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Tree]); + o->image(pixmap[(int)Type::Tree]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(484, 46, 24, 24); o->tooltip("Check Browser"); @@ -1458,7 +1458,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Check_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Check_Browser]); + o->image(pixmap[(int)Type::Check_Browser]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(509, 46, 24, 24); o->tooltip("Help Browser"); @@ -1472,7 +1472,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Help_View")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Help_View]); + o->image(pixmap[(int)Type::Help_View]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(484, 71, 24, 24); o->tooltip("File Browser"); @@ -1486,7 +1486,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_File_Browser")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_File_Browser]); + o->image(pixmap[(int)Type::File_Browser]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(509, 71, 24, 24); o->tooltip("Table"); @@ -1500,7 +1500,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Table")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Table]); + o->image(pixmap[(int)Type::Table]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o @@ -1518,7 +1518,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Box")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Box]); + o->image(pixmap[(int)Type::Box]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(567, 21, 24, 24); o->tooltip("Clock"); @@ -1532,7 +1532,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Clock")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Clock]); + o->image(pixmap[(int)Type::Clock]); } // fld::widget::Bin_Button* o { fld::widget::Bin_Button* o = new fld::widget::Bin_Button(542, 46, 24, 24); o->tooltip("Progress"); @@ -1546,7 +1546,7 @@ Fl_Window* make_widgetbin() { o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Progress")); o->align(Fl_Align(FL_ALIGN_CENTER)); o->when(FL_WHEN_RELEASE); - o->image(pixmap[ID_Progress]); + o->image(pixmap[(int)Type::Progress]); } // fld::widget::Bin_Button* o o->end(); } // Fl_Group* o diff --git a/fluid/panels/function_panel.fl b/fluid/panels/function_panel.fl index 7adb2ecea..d07af5c8c 100644 --- a/fluid/panels/function_panel.fl +++ b/fluid/panels/function_panel.fl @@ -25,13 +25,13 @@ comment {// } {in_source in_header } -decl {\#include "app/fluid.h"} {private local +decl {\#include "Fluid.h"} {private local } -decl {\#include "app/undo.h"} {private local +decl {\#include "proj/undo.h"} {private local } -decl {\#include "nodes/Fl_Type.h"} {private local +decl {\#include "nodes/Node.h"} {private local } decl {\#include "nodes/factory.h"} {private local @@ -588,7 +588,7 @@ Function {make_comment_panel()} {open Function {type_make_cb(Fl_Widget*,void*d)} {open return_type void } { code {const char *type_name = (const char*)d; -if (Fl_Type::current && Fl_Type::current->can_have_children()) +if (Fluid.proj.tree.current && Fluid.proj.tree.current->can_have_children()) add_new_widget_from_user(type_name, Strategy::AS_LAST_CHILD); else add_new_widget_from_user(type_name, Strategy::AFTER_CURRENT);} {} @@ -599,9 +599,9 @@ Function {make_widgetbin()} {open Fl_Window widgetbin_panel { label {Widget Bin} callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape) - exit_cb((Fl_Widget*)o, v); + Fluid.quit(); else - toggle_widgetbin_cb((Fl_Widget*)o, v);} open + Fluid.toggle_widget_bin();} open xywh {395 227 600 102} type Single align 80 non_modal visible } { Fl_Group {} { @@ -612,56 +612,56 @@ else user_data {"Function"} callback type_make_cb tooltip Function xywh {5 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Function]);} + code0 {o->image(pixmap[(int)Type::Function]);} } Fl_Button {} { user_data {"Class"} callback type_make_cb tooltip Class xywh {30 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Class]);} + code0 {o->image(pixmap[(int)Type::Class]);} } Fl_Button {} { user_data {"comment"} callback type_make_cb tooltip Comment xywh {55 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Comment]);} + code0 {o->image(pixmap[(int)Type::Comment]);} } Fl_Button {} { user_data {"Code"} callback type_make_cb tooltip Code xywh {5 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Code]);} + code0 {o->image(pixmap[(int)Type::Code]);} } Fl_Button {} { user_data {"CodeBlock"} callback type_make_cb tooltip {Code Block} xywh {30 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_CodeBlock]);} + code0 {o->image(pixmap[(int)Type::CodeBlock]);} } Fl_Button {} { user_data {"widget_class"} callback type_make_cb tooltip {Widget Class} xywh {55 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Widget_Class]);} + code0 {o->image(pixmap[(int)Type::Widget_Class]);} class {fld::widget::Bin_Window_Button} } Fl_Button {} { user_data {"decl"} callback type_make_cb tooltip Declaration xywh {5 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Decl]);} + code0 {o->image(pixmap[(int)Type::Decl]);} } Fl_Button {} { user_data {"declblock"} callback type_make_cb tooltip {Declaration Block} xywh {30 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_DeclBlock]);} + code0 {o->image(pixmap[(int)Type::DeclBlock]);} } Fl_Button {} { user_data {"data"} callback type_make_cb tooltip {Inline Data} xywh {55 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Data]);} + code0 {o->image(pixmap[(int)Type::Data]);} } } Fl_Group {} { @@ -672,63 +672,63 @@ else user_data {"Fl_Window"} callback type_make_cb tooltip Window xywh {89 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Window]);} + code0 {o->image(pixmap[(int)Type::Window]);} class {fld::widget::Bin_Window_Button} } Fl_Button {} { user_data {"Fl_Group"} callback type_make_cb selected tooltip Group xywh {114 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Group]);} + code0 {o->image(pixmap[(int)Type::Group]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Pack"} callback type_make_cb tooltip Pack xywh {139 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Pack]);} + code0 {o->image(pixmap[(int)Type::Pack]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Tabs"} callback type_make_cb tooltip Tabs xywh {89 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Tabs]);} + code0 {o->image(pixmap[(int)Type::Tabs]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Scroll"} callback type_make_cb tooltip Scroll xywh {114 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Scroll]);} + code0 {o->image(pixmap[(int)Type::Scroll]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Flex"} callback type_make_cb tooltip Flex xywh {139 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Flex]);} + code0 {o->image(pixmap[(int)Type::Flex]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Tile"} callback type_make_cb tooltip Tile xywh {89 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Tile]);} + code0 {o->image(pixmap[(int)Type::Tile]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Wizard"} callback type_make_cb tooltip Wizard xywh {114 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Wizard]);} + code0 {o->image(pixmap[(int)Type::Wizard]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Grid"} callback type_make_cb tooltip Grid xywh {139 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Grid]);} + code0 {o->image(pixmap[(int)Type::Grid]);} class {fld::widget::Bin_Button} } } @@ -740,42 +740,42 @@ else user_data {"Fl_Button"} callback type_make_cb tooltip Button xywh {173 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Button]);} + code0 {o->image(pixmap[(int)Type::Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Return_Button"} callback type_make_cb tooltip {Return Button} xywh {198 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Return_Button]);} + code0 {o->image(pixmap[(int)Type::Return_Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Light_Button"} callback type_make_cb tooltip {Light Button} xywh {173 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Light_Button]);} + code0 {o->image(pixmap[(int)Type::Light_Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Repeat_Button"} callback type_make_cb tooltip {Repeat Button} xywh {198 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Repeat_Button]);} + code0 {o->image(pixmap[(int)Type::Repeat_Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Check_Button"} callback type_make_cb tooltip {Check Button} xywh {173 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Check_Button]);} + code0 {o->image(pixmap[(int)Type::Check_Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Round_Button"} callback type_make_cb tooltip {Round Button} xywh {198 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Round_Button]);} + code0 {o->image(pixmap[(int)Type::Round_Button]);} class {fld::widget::Bin_Button} } } @@ -787,70 +787,70 @@ else user_data {"Fl_Slider"} callback type_make_cb tooltip Slider xywh {232 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Slider]);} + code0 {o->image(pixmap[(int)Type::Slider]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Scrollbar"} callback type_make_cb tooltip {Scroll Bar} xywh {257 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Scrollbar]);} + code0 {o->image(pixmap[(int)Type::Scrollbar]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Value_Slider"} callback type_make_cb tooltip {Value Slider} xywh {282 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Value_Slider]);} + code0 {o->image(pixmap[(int)Type::Value_Slider]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Value_Output"} callback type_make_cb tooltip {Value Output} xywh {307 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Value_Output]);} + code0 {o->image(pixmap[(int)Type::Value_Output]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Adjuster"} callback type_make_cb tooltip Adjuster xywh {232 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Adjuster]);} + code0 {o->image(pixmap[(int)Type::Adjuster]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Counter"} callback type_make_cb tooltip Counter xywh {257 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Counter]);} + code0 {o->image(pixmap[(int)Type::Counter]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Dial"} callback type_make_cb tooltip Dial xywh {282 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Dial]);} + code0 {o->image(pixmap[(int)Type::Dial]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Roller"} callback type_make_cb tooltip Roller xywh {232 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Roller]);} + code0 {o->image(pixmap[(int)Type::Roller]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Spinner"} callback type_make_cb tooltip Spinner xywh {257 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Spinner]);} + code0 {o->image(pixmap[(int)Type::Spinner]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Value_Input"} callback type_make_cb tooltip {Value Input} xywh {282 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Value_Input]);} + code0 {o->image(pixmap[(int)Type::Value_Input]);} class {fld::widget::Bin_Button} } } @@ -862,42 +862,42 @@ else user_data {"Fl_Input"} callback type_make_cb tooltip Input xywh {341 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Input]);} + code0 {o->image(pixmap[(int)Type::Input]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Output"} callback type_make_cb tooltip Output xywh {366 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Output]);} + code0 {o->image(pixmap[(int)Type::Output]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Text_Editor"} callback type_make_cb tooltip {Text Edit} xywh {341 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Text_Editor]);} + code0 {o->image(pixmap[(int)Type::Text_Editor]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Text_Display"} callback type_make_cb tooltip {Text Display} xywh {366 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Text_Display]);} + code0 {o->image(pixmap[(int)Type::Text_Display]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_File_Input"} callback type_make_cb tooltip {File Input} xywh {341 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_File_Input]);} + code0 {o->image(pixmap[(int)Type::File_Input]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Terminal"} callback type_make_cb tooltip Terminal xywh {366 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Terminal]);} + code0 {o->image(pixmap[(int)Type::Terminal]);} class {fld::widget::Bin_Button} } } @@ -909,56 +909,56 @@ else user_data {"Fl_Input_Choice"} callback type_make_cb tooltip {Input Choice} xywh {400 22 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Input_Choice]);} + code0 {o->image(pixmap[(int)Type::Input_Choice]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"menuitem"} callback type_make_cb tooltip {Menu Item} xywh {425 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Menu_Item]);} + code0 {o->image(pixmap[(int)Type::Menu_Item]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Menu_Bar"} callback type_make_cb tooltip {Menu Bar} xywh {450 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Menu_Bar]);} + code0 {o->image(pixmap[(int)Type::Menu_Bar]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Menu_Button"} callback type_make_cb tooltip {Menu Button} xywh {400 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Menu_Button]);} + code0 {o->image(pixmap[(int)Type::Menu_Button]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"checkmenuitem"} callback type_make_cb tooltip {Checkbox Menu Item} xywh {425 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Checkbox_Menu_Item]);} + code0 {o->image(pixmap[(int)Type::Checkbox_Menu_Item]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"submenu"} callback type_make_cb tooltip {Sub Menu} xywh {450 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Submenu]);} + code0 {o->image(pixmap[(int)Type::Submenu]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Choice"} callback type_make_cb tooltip Choice xywh {400 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Choice]);} + code0 {o->image(pixmap[(int)Type::Choice]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"radiomenuitem"} callback type_make_cb tooltip {Radio Menu Item} xywh {425 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Radio_Menu_Item]);} + code0 {o->image(pixmap[(int)Type::Radio_Menu_Item]);} class {fld::widget::Bin_Button} } } @@ -970,42 +970,42 @@ else user_data {"Fl_Browser"} callback type_make_cb tooltip Browser xywh {484 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Browser]);} + code0 {o->image(pixmap[(int)Type::Browser]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Tree"} callback type_make_cb tooltip Tree xywh {509 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Tree]);} + code0 {o->image(pixmap[(int)Type::Tree]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Check_Browser"} callback type_make_cb tooltip {Check Browser} xywh {484 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Check_Browser]);} + code0 {o->image(pixmap[(int)Type::Check_Browser]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Help_View"} callback type_make_cb tooltip {Help Browser} xywh {509 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Help_View]);} + code0 {o->image(pixmap[(int)Type::Help_View]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_File_Browser"} callback type_make_cb tooltip {File Browser} xywh {484 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_File_Browser]);} + code0 {o->image(pixmap[(int)Type::File_Browser]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Table"} callback type_make_cb tooltip Table xywh {509 71 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Table]);} + code0 {o->image(pixmap[(int)Type::Table]);} class {fld::widget::Bin_Button} } } @@ -1017,21 +1017,21 @@ else user_data {"Fl_Box"} callback type_make_cb tooltip Box xywh {542 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Box]);} + code0 {o->image(pixmap[(int)Type::Box]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Clock"} callback type_make_cb tooltip Clock xywh {567 21 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Clock]);} + code0 {o->image(pixmap[(int)Type::Clock]);} class {fld::widget::Bin_Button} } Fl_Button {} { user_data {"Fl_Progress"} callback type_make_cb tooltip Progress xywh {542 46 24 24} box THIN_UP_BOX - code0 {o->image(pixmap[ID_Progress]);} + code0 {o->image(pixmap[(int)Type::Progress]);} class {fld::widget::Bin_Button} } } diff --git a/fluid/panels/print_panel.cxx b/fluid/panels/print_panel.cxx deleted file mode 100644 index f585efee5..000000000 --- a/fluid/panels/print_panel.cxx +++ /dev/null @@ -1,586 +0,0 @@ -// -// FLUID print panel for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2020 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 -// - -// generated by Fast Light User Interface Designer (fluid) version 1.0500 - -#include "print_panel.h" -#include "app/fluid.h" -#include -#include "../src/flstring.h" -#include -#include - -Fl_Double_Window *print_panel=(Fl_Double_Window *)0; - -Fl_Group *print_panel_controls=(Fl_Group *)0; - -Fl_Choice *print_choice=(Fl_Choice *)0; - -static void cb_print_choice(Fl_Choice*, void*) { - print_update_status(); -} - -Fl_Button *print_properties=(Fl_Button *)0; - -static void cb_print_properties(Fl_Button*, void*) { - print_properties_panel->show(); -} - -Fl_Box *print_status=(Fl_Box *)0; - -Fl_Round_Button *print_all=(Fl_Round_Button *)0; - -static void cb_print_all(Fl_Round_Button*, void*) { - print_from->deactivate(); - print_to->deactivate(); -} - -Fl_Round_Button *print_pages=(Fl_Round_Button *)0; - -static void cb_print_pages(Fl_Round_Button*, void*) { - print_from->activate(); - print_to->activate(); -} - -Fl_Round_Button *print_selection=(Fl_Round_Button *)0; - -static void cb_print_selection(Fl_Round_Button*, void*) { - print_from->deactivate(); - print_to->deactivate(); -} - -Fl_Int_Input *print_from=(Fl_Int_Input *)0; - -Fl_Int_Input *print_to=(Fl_Int_Input *)0; - -Fl_Spinner *print_copies=(Fl_Spinner *)0; - -static void cb_print_copies(Fl_Spinner*, void*) { - if (print_copies->value() == 1) { - print_collate_button->deactivate(); - print_collate_group[0]->deactivate(); - print_collate_group[1]->deactivate(); - } else { - print_collate_button->activate(); - print_collate_group[0]->activate(); - print_collate_group[1]->activate(); - } -} - -Fl_Check_Button *print_collate_button=(Fl_Check_Button *)0; - -static void cb_print_collate_button(Fl_Check_Button*, void*) { - int i = print_collate_button->value() != 0; - print_collate_group[i]->show(); - print_collate_group[1 - i]->hide(); -} - -Fl_Group *print_collate_group[2]={(Fl_Group *)0}; - -static void cb_Cancel(Fl_Button*, void*) { - print_panel->hide(); -} - -Fl_Progress *print_progress=(Fl_Progress *)0; - -Fl_Double_Window *print_properties_panel=(Fl_Double_Window *)0; - -static void cb_print_properties_panel(Fl_Double_Window*, void*) { - print_properties_panel->hide(); - print_update_status(); -} - -Fl_Choice *print_page_size=(Fl_Choice *)0; - -Fl_Menu_Item menu_print_page_size[] = { - {"Letter", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, - {"A4", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 14, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -#include - -static const char *idata_print_color[] = { -"24 24 17 1", -" \tc None", -".\tc #FFFF00", -"+\tc #C8FF00", -"@\tc #00FF00", -"#\tc #FFC800", -"$\tc #FF0000", -"%\tc #00FFFF", -"&\tc #000000", -"*\tc #FF00FF", -"=\tc #00FFC8", -"-\tc #FF00C8", -";\tc #00C800", -">\tc #C80000", -",\tc #0000C8", -"\'\tc #0000FF", -")\tc #00C8FF", -"!\tc #C800FF", -" ...... ", -" .......... ", -" ............ ", -" .............. ", -" .............. ", -" ................ ", -" ................ ", -" ................ ", -" +@@@@@@+#$$$$$$# ", -" %@@@@@@@&&$$$$$$$* ", -" %%@@@@@@&&&&$$$$$$** ", -" %%%=@@@@&&&&&&$$$$-*** ", -" %%%%@@@;&&&&&&>$$$**** ", -"%%%%%%@@&&&&&&&&$$******", -"%%%%%%%@&&&&&&&&$*******", -"%%%%%%%%,&&&&&&,********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -" %%%%%%%)\'\'\'\'\'\'!******* ", -" %%%%%%%%\'\'\'\'\'\'******** ", -" %%%%%%%%\'\'\'\'******** ", -" %%%%%%%%\'\'******** ", -" %%%%%% ****** " -}; -static Fl_Image *image_print_color() { - static Fl_Image *image = NULL; - if (!image) - image = new Fl_Pixmap(idata_print_color); - return image; -} - -static const char *idata_print_gray[] = { -"24 24 17 1", -" \tc None", -".\tc #E3E3E3", -"+\tc #D2D2D2", -"@\tc #969696", -"#\tc #C2C2C2", -"$\tc #4C4C4C", -"%\tc #B2B2B2", -"&\tc #000000", -"*\tc #696969", -"=\tc #ACACAC", -"-\tc #626262", -";\tc #767676", -">\tc #3C3C3C", -",\tc #161616", -"\'\tc #1C1C1C", -")\tc #929292", -"!\tc #585858", -" ...... ", -" .......... ", -" ............ ", -" .............. ", -" .............. ", -" ................ ", -" ................ ", -" ................ ", -" +@@@@@@+#$$$$$$# ", -" %@@@@@@@&&$$$$$$$* ", -" %%@@@@@@&&&&$$$$$$** ", -" %%%=@@@@&&&&&&$$$$-*** ", -" %%%%@@@;&&&&&&>$$$**** ", -"%%%%%%@@&&&&&&&&$$******", -"%%%%%%%@&&&&&&&&$*******", -"%%%%%%%%,&&&&&&,********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -"%%%%%%%%\'\'\'\'\'\'\'\'********", -" %%%%%%%)\'\'\'\'\'\'!******* ", -" %%%%%%%%\'\'\'\'\'\'******** ", -" %%%%%%%%\'\'\'\'******** ", -" %%%%%%%%\'\'******** ", -" %%%%%% ****** " -}; -static Fl_Image *image_print_gray() { - static Fl_Image *image = NULL; - if (!image) - image = new Fl_Pixmap(idata_print_gray); - return image; -} - -Fl_Button *print_output_mode[4]={(Fl_Button *)0}; - -static void cb_Save(Fl_Return_Button*, void*) { - print_properties_panel->hide(); - - char name[1024]; - int val; - const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); - - snprintf(name, sizeof(name), "%s/page_size", printer); - fluid_prefs.set(name, print_page_size->value()); - - snprintf(name, sizeof(name), "%s/output_mode", printer); - for (val = 0; val < 4; val ++) { - if (print_output_mode[val]->value()) break; - } - fluid_prefs.set(name, val); -} - -static void cb_Cancel1(Fl_Button*, void*) { - print_properties_panel->hide(); - print_update_status(); -} - -static void cb_Use(Fl_Button*, void*) { - print_properties_panel->hide(); -} - -Fl_Double_Window* make_print_panel() { - { print_panel = new Fl_Double_Window(465, 235, "Print"); - { print_panel_controls = new Fl_Group(10, 10, 447, 216); - { print_choice = new Fl_Choice(113, 10, 181, 25, "Printer:"); - print_choice->down_box(FL_BORDER_BOX); - print_choice->labelfont(1); - print_choice->callback((Fl_Callback*)cb_print_choice); - print_choice->when(FL_WHEN_CHANGED); - } // Fl_Choice* print_choice - { print_properties = new Fl_Button(294, 10, 105, 25, "Properties..."); - print_properties->callback((Fl_Callback*)cb_print_properties); - } // Fl_Button* print_properties - { print_status = new Fl_Box(111, 41, 288, 17, "printer/job status"); - print_status->align(Fl_Align(68|FL_ALIGN_INSIDE)); - } // Fl_Box* print_status - { Fl_Group* o = new Fl_Group(10, 86, 227, 105, "Print Range"); - o->box(FL_THIN_DOWN_BOX); - o->labelfont(1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - { print_all = new Fl_Round_Button(20, 96, 38, 25, "All"); - print_all->type(102); - print_all->down_box(FL_ROUND_DOWN_BOX); - print_all->value(1); - print_all->callback((Fl_Callback*)cb_print_all); - } // Fl_Round_Button* print_all - { print_pages = new Fl_Round_Button(20, 126, 64, 25, "Pages"); - print_pages->type(102); - print_pages->down_box(FL_ROUND_DOWN_BOX); - print_pages->callback((Fl_Callback*)cb_print_pages); - } // Fl_Round_Button* print_pages - { print_selection = new Fl_Round_Button(20, 156, 82, 25, "Selection"); - print_selection->type(102); - print_selection->down_box(FL_ROUND_DOWN_BOX); - print_selection->callback((Fl_Callback*)cb_print_selection); - } // Fl_Round_Button* print_selection - { print_from = new Fl_Int_Input(136, 126, 28, 25, "From:"); - print_from->type(2); - print_from->textfont(4); - print_from->deactivate(); - } // Fl_Int_Input* print_from - { print_to = new Fl_Int_Input(199, 126, 28, 25, "To:"); - print_to->type(2); - print_to->textfont(4); - print_to->deactivate(); - } // Fl_Int_Input* print_to - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(247, 86, 210, 105, "Copies"); - o->box(FL_THIN_DOWN_BOX); - o->labelfont(1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - { print_copies = new Fl_Spinner(321, 96, 45, 25, "# Copies:"); - print_copies->callback((Fl_Callback*)cb_print_copies); - print_copies->when(FL_WHEN_CHANGED); - } // Fl_Spinner* print_copies - { print_collate_button = new Fl_Check_Button(376, 96, 64, 25, "Collate"); - print_collate_button->down_box(FL_DOWN_BOX); - print_collate_button->callback((Fl_Callback*)cb_print_collate_button); - print_collate_button->when(FL_WHEN_CHANGED); - print_collate_button->deactivate(); - } // Fl_Check_Button* print_collate_button - { print_collate_group[0] = new Fl_Group(257, 131, 191, 50); - print_collate_group[0]->deactivate(); - { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - o->deactivate(); - } // Fl_Box* o - print_collate_group[0]->end(); - } // Fl_Group* print_collate_group[0] - { print_collate_group[1] = new Fl_Group(257, 131, 191, 50); - print_collate_group[1]->hide(); - print_collate_group[1]->deactivate(); - { Fl_Box* o = new Fl_Box(287, 141, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(272, 136, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(257, 131, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(352, 141, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(337, 136, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(322, 131, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(417, 141, 30, 40, "3"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(402, 136, 30, 40, "2"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - { Fl_Box* o = new Fl_Box(387, 131, 30, 40, "1"); - o->box(FL_BORDER_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->labelsize(11); - o->align(Fl_Align(FL_ALIGN_BOTTOM_RIGHT|FL_ALIGN_INSIDE)); - } // Fl_Box* o - print_collate_group[1]->end(); - } // Fl_Group* print_collate_group[1] - o->end(); - } // Fl_Group* o - { Fl_Return_Button* o = new Fl_Return_Button(309, 201, 70, 25, "Print"); - o->callback((Fl_Callback*)print_cb); - } // Fl_Return_Button* o - { Fl_Button* o = new Fl_Button(389, 201, 68, 25, "Cancel"); - o->callback((Fl_Callback*)cb_Cancel); - } // Fl_Button* o - print_panel_controls->end(); - } // Fl_Group* print_panel_controls - { print_progress = new Fl_Progress(10, 203, 289, 21); - print_progress->selection_color((Fl_Color)4); - print_progress->hide(); - } // Fl_Progress* print_progress - print_panel->set_modal(); - print_panel->end(); - } // Fl_Double_Window* print_panel - { print_properties_panel = new Fl_Double_Window(290, 130, "Printer Properties"); - print_properties_panel->callback((Fl_Callback*)cb_print_properties_panel); - { print_page_size = new Fl_Choice(110, 10, 80, 25, "Page Size:"); - print_page_size->down_box(FL_BORDER_BOX); - print_page_size->labelfont(1); - print_page_size->labelsize(12); - print_page_size->menu(menu_print_page_size); - } // Fl_Choice* print_page_size - { Fl_Group* o = new Fl_Group(110, 45, 170, 40, "Output Mode:"); - o->labelfont(1); - o->labelsize(12); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { print_output_mode[0] = new Fl_Button(110, 45, 30, 40); - print_output_mode[0]->type(102); - print_output_mode[0]->box(FL_BORDER_BOX); - print_output_mode[0]->down_box(FL_BORDER_BOX); - print_output_mode[0]->value(1); - print_output_mode[0]->color(FL_BACKGROUND2_COLOR); - print_output_mode[0]->selection_color(FL_FOREGROUND_COLOR); - print_output_mode[0]->image( image_print_color() ); - } // Fl_Button* print_output_mode[0] - { print_output_mode[1] = new Fl_Button(150, 50, 40, 30); - print_output_mode[1]->type(102); - print_output_mode[1]->box(FL_BORDER_BOX); - print_output_mode[1]->down_box(FL_BORDER_BOX); - print_output_mode[1]->color(FL_BACKGROUND2_COLOR); - print_output_mode[1]->selection_color(FL_FOREGROUND_COLOR); - print_output_mode[1]->image( image_print_color() ); - } // Fl_Button* print_output_mode[1] - { print_output_mode[2] = new Fl_Button(200, 45, 30, 40); - print_output_mode[2]->type(102); - print_output_mode[2]->box(FL_BORDER_BOX); - print_output_mode[2]->down_box(FL_BORDER_BOX); - print_output_mode[2]->color(FL_BACKGROUND2_COLOR); - print_output_mode[2]->selection_color(FL_FOREGROUND_COLOR); - print_output_mode[2]->image( image_print_gray() ); - } // Fl_Button* print_output_mode[2] - { print_output_mode[3] = new Fl_Button(240, 50, 40, 30); - print_output_mode[3]->type(102); - print_output_mode[3]->box(FL_BORDER_BOX); - print_output_mode[3]->down_box(FL_BORDER_BOX); - print_output_mode[3]->color(FL_BACKGROUND2_COLOR); - print_output_mode[3]->selection_color(FL_FOREGROUND_COLOR); - print_output_mode[3]->image( image_print_gray() ); - } // Fl_Button* print_output_mode[3] - o->end(); - } // Fl_Group* o - { Fl_Return_Button* o = new Fl_Return_Button(123, 95, 79, 25, "Save"); - o->callback((Fl_Callback*)cb_Save); - } // Fl_Return_Button* o - { Fl_Button* o = new Fl_Button(212, 95, 68, 25, "Cancel"); - o->callback((Fl_Callback*)cb_Cancel1); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(60, 95, 53, 25, "Use"); - o->callback((Fl_Callback*)cb_Use); - } // Fl_Button* o - print_properties_panel->set_modal(); - print_properties_panel->end(); - } // Fl_Double_Window* print_properties_panel - return print_properties_panel; -} -void print_cb(Fl_Return_Button *, void *); - -void print_load() { - FILE *lpstat; - char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; - int i; - - if (print_choice->size() > 1) { - for (i = 1; print_choice->text(i); i ++) { - free(print_choice->menu()[i].user_data()); - } - } - - print_choice->clear(); - print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); - print_choice->value(0); - - defname[0] = '\0'; - - if ((lpstat = popen("LC_MESSAGES=C LANG=C lpstat -p -d", "r")) != NULL) { - while (fgets(line, sizeof(line), lpstat)) { - if (!strncmp(line, "printer ", 8) && - sscanf(line + 8, "%s", name) == 1) { - for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { - if (*nptr == '/') *qptr++ = '\\'; - } - *qptr = '\0'; - - print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0); - } else if (!strncmp(line, "system default destination: ", 28)) { - if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\0'; - } - } - pclose(lpstat); - } - - if (defname[0]) { - for (i = 1; print_choice->text(i); i ++) { - if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { - print_choice->value(i); - break; - } - } - } else if (print_choice->size() > 2) print_choice->value(1); - - - print_update_status(); -} - -void print_update_status() { - FILE *lpstat; - char command[1024]; - static char status[1024]; - const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); - - if (print_choice->value()) { - snprintf(command, sizeof(command), "lpstat -p '%s'", printer); - if ((lpstat = popen(command, "r")) != NULL) { - if (fgets(status, sizeof(status), lpstat)==0) { /* ignore */ } - pclose(lpstat); - } else strcpy(status, "printer status unavailable"); - } else status[0] = '\0'; - - print_status->label(status); - - char name[1024]; - int val; - - snprintf(name, sizeof(name), "%s/page_size", printer); - fluid_prefs.get(name, val, 0); - print_page_size->value(val); - - snprintf(name, sizeof(name), "%s/output_mode", printer); - fluid_prefs.get(name, val, 0); - print_output_mode[val]->setonly(); -} diff --git a/fluid/panels/print_panel.fl b/fluid/panels/print_panel.fl deleted file mode 100644 index ae1899c3e..000000000 --- a/fluid/panels/print_panel.fl +++ /dev/null @@ -1,358 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -header_name {.h} -code_name {.cxx} -comment {// -// FLUID print panel for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2020 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 -// -} {in_source in_header -} - -decl {\#include "app/fluid.h"} {private local -} - -decl {\#include } {private local -} - -decl {\#include "../src/flstring.h"} {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -Function {make_print_panel()} {open -} { - Fl_Window print_panel { - label Print selected - xywh {465 222 465 235} type Double modal visible - } { - Fl_Group print_panel_controls {open - xywh {10 10 447 216} - } { - Fl_Choice print_choice { - label {Printer:} - callback {print_update_status();} open - xywh {113 10 181 25} down_box BORDER_BOX labelfont 1 when 1 - } {} - Fl_Button print_properties { - label {Properties...} - callback {print_properties_panel->show();} - xywh {294 10 105 25} - } - Fl_Box print_status { - label {printer/job status} - xywh {111 41 288 17} align 84 - } - Fl_Group {} { - label {Print Range} open - xywh {10 86 227 105} box THIN_DOWN_BOX labelfont 1 align 5 - } { - Fl_Round_Button print_all { - label All - callback {print_from->deactivate(); -print_to->deactivate();} - xywh {20 96 38 25} type Radio down_box ROUND_DOWN_BOX value 1 - } - Fl_Round_Button print_pages { - label Pages - callback {print_from->activate(); -print_to->activate();} - xywh {20 126 64 25} type Radio down_box ROUND_DOWN_BOX - } - Fl_Round_Button print_selection { - label Selection - callback {print_from->deactivate(); -print_to->deactivate();} - xywh {20 156 82 25} type Radio down_box ROUND_DOWN_BOX - } - Fl_Input print_from { - label {From:} - xywh {136 126 28 25} type Int textfont 4 deactivate - } - Fl_Input print_to { - label {To:} - xywh {199 126 28 25} type Int textfont 4 deactivate - } - } - Fl_Group {} { - label Copies open - xywh {247 86 210 105} box THIN_DOWN_BOX labelfont 1 align 5 - } { - Fl_Spinner print_copies { - label {\# Copies:} - callback {if (print_copies->value() == 1) { - print_collate_button->deactivate(); - print_collate_group[0]->deactivate(); - print_collate_group[1]->deactivate(); -} else { - print_collate_button->activate(); - print_collate_group[0]->activate(); - print_collate_group[1]->activate(); -}} - xywh {321 96 45 25} when 1 - } - Fl_Check_Button print_collate_button { - label Collate - callback {int i = print_collate_button->value() != 0; -print_collate_group[i]->show(); -print_collate_group[1 - i]->hide();} - xywh {376 96 64 25} down_box DOWN_BOX when 1 deactivate - } - Fl_Group {print_collate_group[0]} { - xywh {257 131 191 50} deactivate - } { - Fl_Box {} { - label 1 - xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 1 - xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 1 - xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 2 - xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 2 - xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 2 - xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 3 - xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 3 - xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - Fl_Box {} { - label 3 - xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 deactivate - } - } - Fl_Group {print_collate_group[1]} { - xywh {257 131 191 50} hide deactivate - } { - Fl_Box {} { - label 3 - xywh {287 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 2 - xywh {272 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 1 - xywh {257 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 3 - xywh {352 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 2 - xywh {337 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 1 - xywh {322 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 3 - xywh {417 141 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 2 - xywh {402 136 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - Fl_Box {} { - label 1 - xywh {387 131 30 40} box BORDER_BOX color 7 labelsize 11 align 26 - } - } - } - Fl_Return_Button {} { - label Print - callback print_cb - xywh {309 201 70 25} - } - Fl_Button {} { - label Cancel - callback {print_panel->hide();} - xywh {389 201 68 25} - } - } - Fl_Progress print_progress { - xywh {10 203 289 21} selection_color 4 hide - } - } - Fl_Window print_properties_panel { - label {Printer Properties} - callback {print_properties_panel->hide(); -print_update_status();} - xywh {462 486 290 130} type Double modal visible - } { - Fl_Choice print_page_size { - label {Page Size:} - xywh {110 10 80 25} down_box BORDER_BOX labelfont 1 labelsize 12 - } { - MenuItem {} { - label Letter - xywh {0 0 35 25} - } - MenuItem {} { - label A4 - xywh {0 0 35 25} - } - } - Fl_Group {} { - label {Output Mode:} open - xywh {110 45 170 40} labelfont 1 labelsize 12 align 4 - } { - Fl_Button {print_output_mode[0]} { - image {../pixmaps/print_color.xpm} compress_image 0 xywh {110 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX value 1 color 7 selection_color 0 - } - Fl_Button {print_output_mode[1]} { - image {../pixmaps/print_color.xpm} compress_image 0 xywh {150 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 - } - Fl_Button {print_output_mode[2]} { - image {../pixmaps/print_gray.xpm} compress_image 0 xywh {200 45 30 40} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 - } - Fl_Button {print_output_mode[3]} { - image {../pixmaps/print_gray.xpm} compress_image 0 xywh {240 50 40 30} type Radio box BORDER_BOX down_box BORDER_BOX color 7 selection_color 0 - } - } - Fl_Return_Button {} { - label Save - callback {print_properties_panel->hide(); - -char name[1024]; -int val; -const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); - -snprintf(name, sizeof(name), "%s/page_size", printer); -fluid_prefs.set(name, print_page_size->value()); - -snprintf(name, sizeof(name), "%s/output_mode", printer); -for (val = 0; val < 4; val ++) { - if (print_output_mode[val]->value()) break; -} -fluid_prefs.set(name, val);} - xywh {123 95 79 25} - } - Fl_Button {} { - label Cancel - callback {print_properties_panel->hide(); -print_update_status();} - xywh {212 95 68 25} - } - Fl_Button {} { - label Use - callback {print_properties_panel->hide();} - xywh {60 95 53 25} - } - } -} - -decl {void print_cb(Fl_Return_Button *, void *);} {public local -} - -Function {print_load()} {open return_type void -} { - code {FILE *lpstat; -char line[1024], name[1024], *nptr, qname[2048], *qptr, defname[1024]; -int i; - -if (print_choice->size() > 1) { - for (i = 1; print_choice->text(i); i ++) { - free(print_choice->menu()[i].user_data()); - } -} - -print_choice->clear(); -print_choice->add("Print To File", 0, 0, 0, FL_MENU_DIVIDER); -print_choice->value(0); - -defname[0] = '\\0'; - -if ((lpstat = popen("LC_MESSAGES=C LANG=C lpstat -p -d", "r")) != NULL) { - while (fgets(line, sizeof(line), lpstat)) { - if (!strncmp(line, "printer ", 8) && - sscanf(line + 8, "%s", name) == 1) { - for (nptr = name, qptr = qname; *nptr; *qptr++ = *nptr++) { - if (*nptr == '/') *qptr++ = '\\\\'; - } - *qptr = '\\0'; - - print_choice->add(qname, 0, 0, (void *)fl_strdup(name), 0); - } else if (!strncmp(line, "system default destination: ", 28)) { - if (sscanf(line + 28, "%s", defname) != 1) defname[0] = '\\0'; - } - } - pclose(lpstat); -} - -if (defname[0]) { - for (i = 1; print_choice->text(i); i ++) { - if (!strcmp((char *)print_choice->menu()[i].user_data(), defname)) { - print_choice->value(i); - break; - } - } -} else if (print_choice->size() > 2) print_choice->value(1); - - -print_update_status();} {} -} - -Function {print_update_status()} {open return_type void -} { - code {FILE *lpstat; -char command[1024]; -static char status[1024]; -const char *printer = (const char *)print_choice->menu()[print_choice->value()].user_data(); - -if (print_choice->value()) { - snprintf(command, sizeof(command), "lpstat -p '%s'", printer); - if ((lpstat = popen(command, "r")) != NULL) { - if (fgets(status, sizeof(status), lpstat)==0) { /* ignore */ } - pclose(lpstat); - } else strcpy(status, "printer status unavailable"); -} else status[0] = '\\0'; - -print_status->label(status); - -char name[1024]; -int val; - -snprintf(name, sizeof(name), "%s/page_size", printer); -fluid_prefs.get(name, val, 0); -print_page_size->value(val); - -snprintf(name, sizeof(name), "%s/output_mode", printer); -fluid_prefs.get(name, val, 0); -print_output_mode[val]->setonly();} {} -} diff --git a/fluid/panels/print_panel.h b/fluid/panels/print_panel.h deleted file mode 100644 index fed8fd3c0..000000000 --- a/fluid/panels/print_panel.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// FLUID print panel for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2020 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 -// - -// generated by Fast Light User Interface Designer (fluid) version 1.0500 - -#ifndef print_panel_h -#define print_panel_h -#include -#include -extern Fl_Double_Window *print_panel; -#include -extern Fl_Group *print_panel_controls; -#include -extern Fl_Choice *print_choice; -#include -extern Fl_Button *print_properties; -#include -extern Fl_Box *print_status; -#include -extern Fl_Round_Button *print_all; -extern Fl_Round_Button *print_pages; -extern Fl_Round_Button *print_selection; -#include -extern Fl_Int_Input *print_from; -extern Fl_Int_Input *print_to; -#include -extern Fl_Spinner *print_copies; -#include -extern Fl_Check_Button *print_collate_button; -extern Fl_Group *print_collate_group[2]; -#include -extern void print_cb(Fl_Return_Button*, void*); -#include -extern Fl_Progress *print_progress; -extern Fl_Double_Window *print_properties_panel; -extern Fl_Choice *print_page_size; -extern Fl_Button *print_output_mode[4]; -Fl_Double_Window* make_print_panel(); -extern Fl_Menu_Item menu_print_page_size[]; -extern void print_cb(Fl_Return_Button *, void *); -void print_load(); -void print_update_status(); -#endif diff --git a/fluid/panels/settings_panel.cxx b/fluid/panels/settings_panel.cxx index 358f90c8d..432613623 100644 --- a/fluid/panels/settings_panel.cxx +++ b/fluid/panels/settings_panel.cxx @@ -17,8 +17,8 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "settings_panel.h" -#include "app/project.h" -#include "app/undo.h" +#include "Project.h" +#include "proj/undo.h" #include #include #include @@ -230,7 +230,7 @@ static const unsigned char idata_general_64[] = 150,102,123,63,248,127,27,97,180,206,27,14,172,151,0,0,0,0,73,69,78,68,174,66, 96,130}; static Fl_Image *image_general_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("general_64.png", idata_general_64, 2162); return image; @@ -242,36 +242,40 @@ static void cb_(Fl_Group* o, void* v) { Fl_Scheme_Choice *scheme_choice=(Fl_Scheme_Choice *)0; +static void cb_scheme_choice(Fl_Scheme_Choice* o, void*) { + Fluid.set_scheme(o->text(o->value())); +} + Fl_Check_Button *tooltips_button=(Fl_Check_Button *)0; static void cb_tooltips_button(Fl_Check_Button*, void*) { Fl_Tooltip::enable(tooltips_button->value()); - fluid_prefs.set("show_tooltips", tooltips_button->value()); + Fluid.preferences.set("show_tooltips", tooltips_button->value()); } Fl_Check_Button *completion_button=(Fl_Check_Button *)0; static void cb_completion_button(Fl_Check_Button*, void*) { - fluid_prefs.set("show_completion_dialogs", completion_button->value()); + Fluid.preferences.set("show_completion_dialogs", completion_button->value()); } Fl_Check_Button *openlast_button=(Fl_Check_Button *)0; static void cb_openlast_button(Fl_Check_Button*, void*) { - fluid_prefs.set("open_previous_file", openlast_button->value()); + Fluid.preferences.set("open_previous_file", openlast_button->value()); } Fl_Check_Button *prevpos_button=(Fl_Check_Button *)0; static void cb_prevpos_button(Fl_Check_Button*, void*) { - fluid_prefs.set("prev_window_pos", prevpos_button->value()); + Fluid.preferences.set("prev_window_pos", prevpos_button->value()); } Fl_Check_Button *show_comments_button=(Fl_Check_Button *)0; static void cb_show_comments_button(Fl_Check_Button*, void*) { - show_comments = show_comments_button->value(); - fluid_prefs.set("show_comments", show_comments); + Fluid.show_comments = show_comments_button->value(); + Fluid.preferences.set("Fluid.show_comments", Fluid.show_comments); redraw_browser(); } @@ -282,24 +286,24 @@ static void cb_1(Fl_Group* o, void* v) { Fl_Spinner *recent_spinner=(Fl_Spinner *)0; static void cb_recent_spinner(Fl_Spinner*, void*) { - fluid_prefs.set("recent_files", recent_spinner->value()); - load_history(); + Fluid.preferences.set("recent_files", recent_spinner->value()); + Fluid.history.load(); } Fl_Check_Button *use_external_editor_button=(Fl_Check_Button *)0; static void cb_use_external_editor_button(Fl_Check_Button*, void*) { - G_use_external_editor = use_external_editor_button->value(); - fluid_prefs.set("use_external_editor", G_use_external_editor); + Fluid.use_external_editor = use_external_editor_button->value(); + Fluid.preferences.set("use_external_editor", Fluid.use_external_editor); redraw_browser(); } Fl_Input *editor_command_input=(Fl_Input *)0; static void cb_editor_command_input(Fl_Input*, void*) { - strncpy(G_external_editor_command, editor_command_input->value(), sizeof(G_external_editor_command)-1); - G_external_editor_command[sizeof(G_external_editor_command)-1] = 0; - fluid_prefs.set("external_editor_command", G_external_editor_command); + strncpy(Fluid.external_editor_command, editor_command_input->value(), sizeof(Fluid.external_editor_command)-1); + Fluid.external_editor_command[sizeof(Fluid.external_editor_command)-1] = 0; + Fluid.preferences.set("external_editor_command", Fluid.external_editor_command); redraw_browser(); } @@ -359,7 +363,7 @@ static const unsigned char idata_document_64[] = 147,239,104,255,202,153,244,20,250,15,100,60,232,29,230,9,101,148,0,0,0,0,73,69, 78,68,174,66,96,130}; static Fl_Image *image_document_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("document_64.png", idata_document_64, 927); return image; @@ -369,11 +373,11 @@ Fl_Input *header_file_input=(Fl_Input *)0; static void cb_header_file_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.header_file_name.c_str()); + o->value(Fluid.proj.header_file_name.c_str()); } else { - if (strcmp(g_project.header_file_name.c_str(), o->value())) { - g_project.header_file_name = o->value(); - set_modflag(1); + if (strcmp(Fluid.proj.header_file_name.c_str(), o->value())) { + Fluid.proj.header_file_name = o->value(); + Fluid.proj.set_modflag(1); } } } @@ -382,11 +386,11 @@ Fl_Input *code_file_input=(Fl_Input *)0; static void cb_code_file_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.code_file_name.c_str()); + o->value(Fluid.proj.code_file_name.c_str()); } else { - if (strcmp(g_project.code_file_name.c_str(), o->value())) { - g_project.code_file_name = o->value(); - set_modflag(1); + if (strcmp(Fluid.proj.code_file_name.c_str(), o->value())) { + Fluid.proj.code_file_name = o->value(); + Fluid.proj.set_modflag(1); } } } @@ -395,11 +399,11 @@ Fl_Check_Button *include_H_from_C_button=(Fl_Check_Button *)0; static void cb_include_H_from_C_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { - o->value(g_project.include_H_from_C); + o->value(Fluid.proj.include_H_from_C); } else { - if (g_project.include_H_from_C != o->value()) { - set_modflag(1); - g_project.include_H_from_C = o->value(); + if (Fluid.proj.include_H_from_C != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.include_H_from_C = o->value(); } } } @@ -408,11 +412,11 @@ Fl_Check_Button *use_FL_COMMAND_button=(Fl_Check_Button *)0; static void cb_use_FL_COMMAND_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { - o->value(g_project.use_FL_COMMAND); + o->value(Fluid.proj.use_FL_COMMAND); } else { - if (g_project.use_FL_COMMAND != o->value()) { - set_modflag(1); - g_project.use_FL_COMMAND = o->value(); + if (Fluid.proj.use_FL_COMMAND != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.use_FL_COMMAND = o->value(); } } } @@ -421,11 +425,11 @@ Fl_Check_Button *utf8_in_src_button=(Fl_Check_Button *)0; static void cb_utf8_in_src_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { - o->value(g_project.utf8_in_src); + o->value(Fluid.proj.utf8_in_src); } else { - if (g_project.utf8_in_src != o->value()) { - set_modflag(1); - g_project.utf8_in_src = o->value(); + if (Fluid.proj.utf8_in_src != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.utf8_in_src = o->value(); } } } @@ -434,11 +438,11 @@ Fl_Check_Button *avoid_early_includes_button=(Fl_Check_Button *)0; static void cb_avoid_early_includes_button(Fl_Check_Button* o, void* v) { if (v == LOAD) { - o->value(g_project.avoid_early_includes); + o->value(Fluid.proj.avoid_early_includes); } else { - if (g_project.avoid_early_includes != o->value()) { - set_modflag(1); - g_project.avoid_early_includes = o->value(); + if (Fluid.proj.avoid_early_includes != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.avoid_early_includes = o->value(); } } } @@ -447,11 +451,11 @@ Fl_Check_Button *w_proj_mergeback=(Fl_Check_Button *)0; static void cb_w_proj_mergeback(Fl_Check_Button* o, void* v) { if (v == LOAD) { - o->value(g_project.write_mergeback_data); + o->value(Fluid.proj.write_mergeback_data); } else { - if (g_project.write_mergeback_data != o->value()) { - set_modflag(1); - g_project.write_mergeback_data = o->value(); + if (Fluid.proj.write_mergeback_data != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.write_mergeback_data = o->value(); } } } @@ -485,7 +489,7 @@ static const unsigned char idata_layout_64[] = 219,234,153,20,127,159,185,12,250,99,90,14,203,239,127,120,165,154,78,208,47, 215,15,118,242,56,45,94,1,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_layout_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("layout_64.png", idata_layout_64, 481); return image; @@ -495,11 +499,11 @@ 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()); + o->value(Fluid.layout_list.current_suite()); } else { int index = o->value(); - g_layout_list.current_suite(index); - g_layout_list.update_dialogs(); + Fluid.layout_list.current_suite(index); + Fluid.layout_list.update_dialogs(); } } @@ -515,21 +519,21 @@ static void cb_2(Fl_Button*, void* v) { if (v == LOAD) return; std::string old_name = "Copy of "; - old_name.append(g_layout_list[g_layout_list.current_suite()].name_); + old_name.append(Fluid.layout_list[Fluid.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) + if (new_name == nullptr) return; - g_layout_list.add(new_name); - g_layout_list.update_dialogs(); + Fluid.layout_list.add(new_name); + Fluid.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) { + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + if (suite.storage_ == fld::Tool_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(); @@ -538,44 +542,44 @@ static void cb_w_layout_menu(Fl_Menu_Button*, void* v) { 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(); + w_layout_menu_storage[static_cast(suite.storage_)]->setonly(); } } static void cb_w_layout_menu_rename(Fl_Menu_*, void*) { // Rename the current layout suite - std::string old_name = g_layout_list[g_layout_list.current_suite()].name_; + std::string old_name = Fluid.layout_list[Fluid.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) + if (new_name == nullptr) return; - g_layout_list.rename(new_name); - g_layout_list.update_dialogs(); + Fluid.layout_list.rename(new_name); + Fluid.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(); + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + suite.storage(fld::Tool_Store::INTERNAL); + Fluid.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(); + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + suite.storage(fld::Tool_Store::USER); + Fluid.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(); + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + suite.storage(fld::Tool_Store::PROJECT); + Fluid.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(); + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + suite.storage(fld::Tool_Store::FILE); + Fluid.layout_list.update_dialogs(); } static void cb_w_layout_menu_load(Fl_Menu_*, void*) { @@ -588,9 +592,9 @@ static void cb_w_layout_menu_load(Fl_Menu_*, void*) { 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(); + Fluid.layout_list.load(new_filename); + //Fluid.layout_list.current_suite(n); + Fluid.layout_list.update_dialogs(); } static void cb_w_layout_menu_save(Fl_Menu_*, void*) { @@ -600,21 +604,21 @@ static void cb_w_layout_menu_save(Fl_Menu_*, void*) { 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"); - std::string filename = g_layout_list.filename_; + std::string filename = Fluid.layout_list.filename_; fnfc.directory(fl_filename_path_str(filename).c_str()); fnfc.preset_file(fl_filename_name_str(filename).c_str()); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; - g_layout_list.filename_ = new_filename; - g_layout_list.save(new_filename); + Fluid.layout_list.filename_ = new_filename; + Fluid.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(); + Fluid.layout_list.remove(Fluid.layout_list.current_suite()); + Fluid.layout_list.update_dialogs(); } Fl_Menu_Item menu_w_layout_menu[] = { @@ -633,193 +637,193 @@ 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); + o->value((double)Fluid.proj.layout->left_window_margin); } else { - layout->left_window_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->top_window_margin); } else { - layout->top_window_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->right_window_margin); } else { - layout->right_window_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->bottom_window_margin); } else { - layout->bottom_window_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->window_grid_x); } else { - layout->window_grid_x = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->window_grid_y); } else { - layout->window_grid_y = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->left_group_margin); } else { - layout->left_group_margin = (int)o->value(); + Fluid.proj.layout->left_group_margin = (int)o->value(); } } static void cb_Top1(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->top_group_margin); + o->value((double)Fluid.proj.layout->top_group_margin); } else { - layout->top_group_margin = (int)o->value(); + Fluid.proj.layout->top_group_margin = (int)o->value(); } } static void cb_Right1(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->right_group_margin); + o->value((double)Fluid.proj.layout->right_group_margin); } else { - layout->right_group_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->bottom_group_margin); } else { - layout->bottom_group_margin = (int)o->value(); + Fluid.proj.layout->bottom_group_margin = (int)o->value(); } } static void cb_Horizontal1(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->group_grid_x); + o->value((double)Fluid.proj.layout->group_grid_x); } else { - layout->group_grid_x = (int)o->value(); + Fluid.proj.layout->group_grid_x = (int)o->value(); } } static void cb_Vertical1(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->group_grid_y); + o->value((double)Fluid.proj.layout->group_grid_y); } else { - layout->group_grid_y = (int)o->value(); + Fluid.proj.layout->group_grid_y = (int)o->value(); } } static void cb_Top2(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->top_tabs_margin); + o->value((double)Fluid.proj.layout->top_tabs_margin); } else { - layout->top_tabs_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->bottom_tabs_margin); } else { - layout->bottom_tabs_margin = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->widget_min_w); } else { - layout->widget_min_w = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->widget_inc_w); } else { - layout->widget_inc_w = (int)o->value(); + Fluid.proj.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); + o->value((double)Fluid.proj.layout->widget_gap_x); } else { - layout->widget_gap_x = (int)o->value(); + Fluid.proj.layout->widget_gap_x = (int)o->value(); } } static void cb_3(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->widget_min_h); + o->value((double)Fluid.proj.layout->widget_min_h); } else { - layout->widget_min_h = (int)o->value(); + Fluid.proj.layout->widget_min_h = (int)o->value(); } } static void cb_4(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->widget_inc_h); + o->value((double)Fluid.proj.layout->widget_inc_h); } else { - layout->widget_inc_h = (int)o->value(); + Fluid.proj.layout->widget_inc_h = (int)o->value(); } } static void cb_5(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value((double)layout->widget_gap_y); + o->value((double)Fluid.proj.layout->widget_gap_y); } else { - layout->widget_gap_y = (int)o->value(); + Fluid.proj.layout->widget_gap_y = (int)o->value(); } } static void cb_6(Fl_Choice* o, void* v) { if (v == LOAD) { - o->value(layout->labelfont+1); + o->value(Fluid.proj.layout->labelfont+1); } else { - layout->labelfont = (int)o->value()-1; + Fluid.proj.layout->labelfont = (int)o->value()-1; } } static void cb_7(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value(layout->labelsize); + o->value(Fluid.proj.layout->labelsize); } else { - layout->labelsize = (int)o->value(); + Fluid.proj.layout->labelsize = (int)o->value(); } } static void cb_8(Fl_Choice* o, void* v) { if (v == LOAD) { - o->value(layout->textfont+1); + o->value(Fluid.proj.layout->textfont+1); } else { - layout->textfont = (int)o->value()-1; + Fluid.proj.layout->textfont = (int)o->value()-1; } } static void cb_9(Fl_Value_Input* o, void* v) { if (v == LOAD) { - o->value(layout->textsize); + o->value(Fluid.proj.layout->textsize); } else { - layout->textsize = (int)o->value(); + Fluid.proj.layout->textsize = (int)o->value(); } } @@ -863,7 +867,7 @@ static const unsigned char idata_shell_64[] = 82,219,229,239,135,114,138,14,109,164,201,83,85,44,126,133,81,55,103,232,191,0, 145,21,211,195,226,88,204,195,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_shell_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("shell_64.png", idata_shell_64, 802); return image; @@ -880,9 +884,9 @@ static void cb_w_settings_shell_list(Fl_Browser* o, void* v) { for (int i=0; ilist_size; i++) { Fd_Shell_Command *cmd = g_shell_config->list[i]; o->add(cmd->name.c_str()); - if (cmd->storage == FD_STORE_USER) + if (cmd->storage == fld::Tool_Store::USER) o->icon(i+1, w_settings_shell_fd_user->image()); - else if (cmd->storage == FD_STORE_PROJECT) + else if (cmd->storage == fld::Tool_Store::PROJECT) o->icon(i+1, w_settings_shell_fd_project->image()); } } @@ -915,11 +919,11 @@ static void cb_a(Fl_Button*, void* v) { w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); - if (cmd->storage == FD_STORE_USER) { + if (cmd->storage == fld::Tool_Store::USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); - } else if (cmd->storage == FD_STORE_PROJECT) { + } else if (cmd->storage == fld::Tool_Store::PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); - set_modflag(1); + Fluid.proj.set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); @@ -945,11 +949,11 @@ static void cb_w_settings_shell_dup(Fl_Button* o, void* v) { w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); - if (cmd->storage == FD_STORE_USER) { + if (cmd->storage == fld::Tool_Store::USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); - } else if (cmd->storage == FD_STORE_PROJECT) { + } else if (cmd->storage == fld::Tool_Store::PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); - set_modflag(1); + Fluid.proj.set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); @@ -971,9 +975,9 @@ static void cb_w_settings_shell_remove(Fl_Button* o, void* v) { } else { if (!selected) return; int ret = fl_choice("Delete the shell command\n\"%s\"?\n\nThis can not be undone.", - "Delete", "Cancel", NULL, g_shell_config->list[selected-1]->name.c_str()); + "Delete", "Cancel", nullptr, g_shell_config->list[selected-1]->name.c_str()); if (ret==1) return; - if (g_shell_config->at(selected-1)->storage == FD_STORE_PROJECT) set_modflag(1); + if (g_shell_config->at(selected-1)->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); g_shell_config->remove(selected-1); w_settings_shell_list->remove(selected); if (selected <= w_settings_shell_list->size()) @@ -1058,7 +1062,7 @@ static void cb_Name(Fl_Input* o, void* v) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->name = o->value(); w_settings_shell_list->text(selected, o->value()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1076,7 +1080,7 @@ static void cb_Menu(Fl_Input* o, void* v) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->label = o->value(); cmd->update_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1099,7 +1103,7 @@ static void cb_Shortcut(Fl_Shortcut_Button* o, void* v) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->shortcut = o->value(); cmd->update_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1108,30 +1112,30 @@ static void cb_Store(Fl_Choice* o, void* v) { int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { - Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; + fld::Tool_Store ts = g_shell_config->list[selected-1]->storage; o->value(o->find_item_with_argument((long)ts)); } else { - o->value(o->find_item_with_argument((long)FD_STORE_USER)); + o->value(o->find_item_with_argument((long)fld::Tool_Store::USER)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; - Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + fld::Tool_Store ts = (fld::Tool_Store)(o->mvalue()->argument()); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); cmd->storage = ts; //w_settings_shell_list->text(selected, cmd->name.c_str()); - if (cmd->storage == FD_STORE_USER) + if (cmd->storage == fld::Tool_Store::USER) w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); - else if (cmd->storage == FD_STORE_PROJECT) + else if (cmd->storage == fld::Tool_Store::PROJECT) w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } Fl_Menu_Item menu_Store[] = { - {"@fd_user User Setting", 0, 0, (void*)(FD_STORE_USER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"@fd_project Project File", 0, 0, (void*)(FD_STORE_PROJECT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"@fd_user User Setting", 0, 0, (void*)(fld::Tool_Store::USER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"@fd_project Project File", 0, 0, (void*)(fld::Tool_Store::PROJECT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {0,0,0,0,0,0,0,0,0} }; @@ -1150,7 +1154,7 @@ static void cb_Condition(Fl_Choice* o, void* v) { int cond = (int)(o->mvalue()->argument()); cmd->condition = cond; g_shell_config->rebuild_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1187,7 +1191,7 @@ static void cb_w_settings_shell_command(Fl_Text_Editor* o, void* v) { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->command = o->buffer()->text(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1211,7 +1215,7 @@ static void cb_w_settings_shell_text_macros(Fl_Menu_Button* o, void*) { int pos = w_settings_shell_command->insert_position(); w_settings_shell_command->buffer()->insert(pos, word); } - w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); + w_settings_shell_command->do_callback(w_settings_shell_command, (void*)nullptr); } } @@ -1266,7 +1270,7 @@ static void cb_save(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1288,7 +1292,7 @@ static void cb_save1(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1310,7 +1314,7 @@ static void cb_save2(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1332,7 +1336,7 @@ static void cb_show(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::DONT_SHOW_TERMINAL; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1354,7 +1358,7 @@ static void cb_clear(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_TERMINAL; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1376,7 +1380,7 @@ static void cb_clear1(Fl_Check_Button* o, void* v) { } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_HISTORY; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } } } @@ -1664,7 +1668,7 @@ static const unsigned char idata_fd_project[] = 213,122,16,176,223,94,207,73,175,70,249,59,81,177,117,128,158,31,49,127,246,30, 207,181,170,20,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_fd_project() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("fd_project.png", idata_fd_project, 6950); return image; @@ -2029,7 +2033,7 @@ static const unsigned char idata_fd_user[] = 116,89,108,93,41,107,255,5,119,155,194,247,64,241,254,70,0,0,0,0,73,69,78,68, 174,66,96,130}; static Fl_Image *image_fd_user() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("fd_user.png", idata_fd_user, 8612); return image; @@ -2108,7 +2112,7 @@ static const unsigned char idata_language_64[] = 157,33,48,255,61,163,226,212,114,146,206,17,166,130,48,126,136,23,88,161,222, 205,191,56,75,123,84,202,251,159,166,0,0,0,0,73,69,78,68,174,66,96,130}; static Fl_Image *image_language_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("language_64.png", idata_language_64, 1450); return image; @@ -2133,11 +2137,11 @@ Fl_Input *i18n_gnu_include_input=(Fl_Input *)0; static void cb_i18n_gnu_include_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_gnu_include.c_str()); + o->value(Fluid.proj.i18n_gnu_include.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_include = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_include = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2145,11 +2149,11 @@ Fl_Input *i18n_gnu_conditional_input=(Fl_Input *)0; static void cb_i18n_gnu_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_gnu_conditional.c_str()); + o->value(Fluid.proj.i18n_gnu_conditional.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_conditional = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_conditional = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2157,11 +2161,11 @@ Fl_Input *i18n_gnu_function_input=(Fl_Input *)0; static void cb_i18n_gnu_function_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_gnu_function.c_str()); + o->value(Fluid.proj.i18n_gnu_function.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_function = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_function = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2169,11 +2173,11 @@ Fl_Input *i18n_gnu_static_function_input=(Fl_Input *)0; static void cb_i18n_gnu_static_function_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_gnu_static_function.c_str()); + o->value(Fluid.proj.i18n_gnu_static_function.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_static_function = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_static_function = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2187,11 +2191,11 @@ Fl_Input *i18n_pos_include_input=(Fl_Input *)0; static void cb_i18n_pos_include_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_pos_include.c_str()); + o->value(Fluid.proj.i18n_pos_include.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_include = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_include = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2199,11 +2203,11 @@ Fl_Input *i18n_pos_conditional_input=(Fl_Input *)0; static void cb_i18n_pos_conditional_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_pos_conditional.c_str()); + o->value(Fluid.proj.i18n_pos_conditional.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_conditional = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_conditional = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2211,11 +2215,11 @@ Fl_Input *i18n_pos_file_input=(Fl_Input *)0; static void cb_i18n_pos_file_input(Fl_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_pos_file.c_str()); + o->value(Fluid.proj.i18n_pos_file.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_file = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_file = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2227,11 +2231,11 @@ Fl_Int_Input *i18n_pos_set_input=(Fl_Int_Input *)0; static void cb_i18n_pos_set_input(Fl_Int_Input* o, void* v) { if (v == LOAD) { - o->value(g_project.i18n_pos_set.c_str()); + o->value(Fluid.proj.i18n_pos_set.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_set = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_set = o->value(); + Fluid.proj.set_modflag(1); } } @@ -2421,7 +2425,7 @@ static const unsigned char idata_user_circle_64[] = 252,106,89,247,128,255,3,60,207,245,248,165,38,113,147,0,0,0,0,73,69,78,68,174, 66,96,130}; static Fl_Image *image_user_circle_64() { - static Fl_Image *image = NULL; + static Fl_Image *image = 0L; if (!image) image = new Fl_PNG_Image("user_circle_64.png", idata_user_circle_64, 3909); return image; @@ -2431,8 +2435,8 @@ Fl_Choice *w_settings_user_commenttext=(Fl_Choice *)0; static void cb_Close(Fl_Button*, void*) { if (g_shell_config) - g_shell_config->write(fluid_prefs, FD_STORE_USER); - g_layout_list.write(fluid_prefs, FD_STORE_USER); + g_shell_config->write(Fluid.preferences, fld::Tool_Store::USER); + Fluid.layout_list.write(Fluid.preferences, fld::Tool_Store::USER); settings_window->hide(); } @@ -2459,10 +2463,10 @@ Fl_Double_Window* make_settings_window() { scheme_choice->labelfont(1); scheme_choice->labelsize(11); scheme_choice->labelcolor(FL_FOREGROUND_COLOR); - scheme_choice->callback((Fl_Callback*)scheme_cb); + scheme_choice->callback((Fl_Callback*)cb_scheme_choice); scheme_choice->align(Fl_Align(FL_ALIGN_LEFT)); scheme_choice->when(FL_WHEN_RELEASE); - init_scheme(); + Fluid.init_scheme(); } // Fl_Scheme_Choice* scheme_choice { Fl_Box* o = new Fl_Box(240, 78, 10, 25); o->hide(); @@ -2480,7 +2484,7 @@ Fl_Double_Window* make_settings_window() { tooltips_button->labelsize(11); tooltips_button->callback((Fl_Callback*)cb_tooltips_button); int b; - fluid_prefs.get("show_tooltips", b, 1); + Fluid.preferences.get("show_tooltips", b, 1); tooltips_button->value(b); Fl_Tooltip::enable(b); } // Fl_Check_Button* tooltips_button @@ -2489,7 +2493,7 @@ Fl_Double_Window* make_settings_window() { completion_button->labelsize(11); completion_button->callback((Fl_Callback*)cb_completion_button); int b; - fluid_prefs.get("show_completion_dialogs", b, 1); + Fluid.preferences.get("show_completion_dialogs", b, 1); completion_button->value(b); } // Fl_Check_Button* completion_button { openlast_button = new Fl_Check_Button(120, 155, 200, 20, "Open Previous File on Startup"); @@ -2497,7 +2501,7 @@ Fl_Double_Window* make_settings_window() { openlast_button->labelsize(11); openlast_button->callback((Fl_Callback*)cb_openlast_button); int b; - fluid_prefs.get("open_previous_file", b, 0); + Fluid.preferences.get("open_previous_file", b, 0); openlast_button->value(b); } // Fl_Check_Button* openlast_button { prevpos_button = new Fl_Check_Button(120, 175, 200, 20, "Remember Window Positions"); @@ -2505,15 +2509,15 @@ Fl_Double_Window* make_settings_window() { prevpos_button->labelsize(11); prevpos_button->callback((Fl_Callback*)cb_prevpos_button); int b; - fluid_prefs.get("prev_window_pos", b, 1); + Fluid.preferences.get("prev_window_pos", b, 1); prevpos_button->value(b); } // Fl_Check_Button* prevpos_button { show_comments_button = new Fl_Check_Button(120, 195, 200, 20, "Show Comments in Browser"); show_comments_button->down_box(FL_DOWN_BOX); show_comments_button->labelsize(11); show_comments_button->callback((Fl_Callback*)cb_show_comments_button); - fluid_prefs.get("show_comments", show_comments, 1); - show_comments_button->value(show_comments); + Fluid.preferences.get("Fluid.show_comments", Fluid.show_comments, 1); + show_comments_button->value(Fluid.show_comments); } // Fl_Check_Button* show_comments_button { Fl_Group* o = new Fl_Group(120, 225, 50, 20); o->callback((Fl_Callback*)cb_1); @@ -2525,7 +2529,7 @@ Fl_Double_Window* make_settings_window() { recent_spinner->callback((Fl_Callback*)cb_recent_spinner); recent_spinner->when(FL_WHEN_CHANGED); int c; - fluid_prefs.get("recent_files", c, 5); + Fluid.preferences.get("recent_files", c, 5); recent_spinner->maximum(10); recent_spinner->value(c); } // Fl_Spinner* recent_spinner @@ -2539,8 +2543,8 @@ Fl_Double_Window* make_settings_window() { use_external_editor_button->down_box(FL_DOWN_BOX); use_external_editor_button->labelsize(11); use_external_editor_button->callback((Fl_Callback*)cb_use_external_editor_button); - fluid_prefs.get("use_external_editor", G_use_external_editor, 0); - use_external_editor_button->value(G_use_external_editor); + Fluid.preferences.get("use_external_editor", Fluid.use_external_editor, 0); + use_external_editor_button->value(Fluid.use_external_editor); } // Fl_Check_Button* use_external_editor_button { editor_command_input = new Fl_Input(120, 255, 200, 20, "External Editor:"); editor_command_input->tooltip("The editor command to open your external text editor.\nInclude any necessary " @@ -2552,8 +2556,8 @@ Fl_Double_Window* make_settings_window() { editor_command_input->textsize(11); editor_command_input->callback((Fl_Callback*)cb_editor_command_input); editor_command_input->when(FL_WHEN_CHANGED); - fluid_prefs.get("external_editor_command", G_external_editor_command, "", sizeof(G_external_editor_command)-1); - editor_command_input->value(G_external_editor_command); + Fluid.preferences.get("external_editor_command", Fluid.external_editor_command, "", sizeof(Fluid.external_editor_command)-1); + editor_command_input->value(Fluid.external_editor_command); } // Fl_Input* editor_command_input { Fl_Box* o = new Fl_Box(120, 300, 0, 20, "Overlays: "); o->labelfont(1); @@ -2565,7 +2569,7 @@ Fl_Double_Window* make_settings_window() { guides_button->down_box(FL_DOWN_BOX); guides_button->labelsize(11); guides_button->callback((Fl_Callback*)toggle_guides_cb); - o->value(show_guides); + o->value(Fluid.show_guides); } // Fl_Check_Button* guides_button { Fl_Check_Button* o = restricted_button = new Fl_Check_Button(120, 320, 200, 20, "Show Restricted Areas"); restricted_button->tooltip("show overlapping and out of bounds areas, show unfilled areas in Fl_Pack grou" @@ -2573,7 +2577,7 @@ Fl_Double_Window* make_settings_window() { restricted_button->down_box(FL_DOWN_BOX); restricted_button->labelsize(11); restricted_button->callback((Fl_Callback*)toggle_restricted_cb); - o->value(show_restricted); + o->value(Fluid.show_restricted); } // Fl_Check_Button* restricted_button { Fl_Check_Button* o = ghosted_outline_button = new Fl_Check_Button(120, 340, 200, 20, "Show Ghosted Group Outlines"); ghosted_outline_button->tooltip("groups with no box type or flat boxtypes without contrast will be rendered wi" @@ -2581,7 +2585,7 @@ Fl_Double_Window* make_settings_window() { ghosted_outline_button->down_box(FL_DOWN_BOX); ghosted_outline_button->labelsize(11); ghosted_outline_button->callback((Fl_Callback*)toggle_ghosted_outline_cb); - o->value(show_ghosted_outline); + o->value(Fluid.show_ghosted_outline); } // Fl_Check_Button* ghosted_outline_button { Fl_Box* o = new Fl_Box(120, 530, 200, 10); o->hide(); @@ -3517,7 +3521,7 @@ static void cb_Clear(Fl_Button*, void*) { Fl_Return_Button *shell_run_button=(Fl_Return_Button *)0; static void cb_shell_run_button(Fl_Return_Button*, void*) { - Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); + Fl_Preferences pos(Fluid.preferences, "shell_run_Window_pos"); pos.set("x", shell_run_window->x()); pos.set("y", shell_run_window->y()); pos.set("w", shell_run_window->w()); diff --git a/fluid/panels/settings_panel.fl b/fluid/panels/settings_panel.fl index 7460ae8af..c66f48bd2 100644 --- a/fluid/panels/settings_panel.fl +++ b/fluid/panels/settings_panel.fl @@ -4,7 +4,7 @@ header_name {.h} code_name {.cxx} snap { ver 1 - current_suite {FLUID (based on FLTK)} + current_suite FLTK current_preset 0 suite { name {FLUID (based on FLTK)} @@ -49,16 +49,16 @@ comment {// } {in_source in_header } -decl {\#include "app/fluid.h"} {public global +decl {\#include "Fluid.h"} {public global } -decl {\#include "app/project.h"} {private local +decl {\#include "Project.h"} {private local } -decl {\#include "app/undo.h"} {private global +decl {\#include "proj/undo.h"} {private global } -decl {\#include "app/Fd_Snap_Action.h"} {public global +decl {\#include "app/Snap_Action.h"} {public global } decl {\#include "app/shell_command.h"} {public global @@ -97,11 +97,7 @@ decl {\#include "../src/flstring.h"} {private global decl {\#include } {private global } -decl {using namespace fld::widget;} {selected private global -} - -decl {void init_scheme(void);} { - comment {// initialize the scheme from preferences} public global +decl {using namespace fld::widget;} {private global } decl {extern struct Fl_Menu_Item *dbmanager_item;} {public local @@ -211,9 +207,9 @@ Function {make_settings_window()} {open } { Fl_Choice scheme_choice { label {Scheme: } - callback scheme_cb open + callback {Fluid.set_scheme(o->text(o->value()));} open selected xywh {120 78 120 25} down_box BORDER_BOX labelfont 1 labelsize 11 - code0 {init_scheme();} + code0 {Fluid.init_scheme();} class Fl_Scheme_Choice } {} Fl_Box {} { @@ -227,45 +223,45 @@ Function {make_settings_window()} {open Fl_Check_Button tooltips_button { label {Show Tooltips} callback {Fl_Tooltip::enable(tooltips_button->value()); -fluid_prefs.set("show_tooltips", tooltips_button->value());} +Fluid.preferences.set("show_tooltips", tooltips_button->value());} xywh {120 115 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} - code1 {fluid_prefs.get("show_tooltips", b, 1);} + code1 {Fluid.preferences.get("show_tooltips", b, 1);} code2 {tooltips_button->value(b);} code3 {Fl_Tooltip::enable(b);} } Fl_Check_Button completion_button { label {Show Completion Dialogs} - callback {fluid_prefs.set("show_completion_dialogs", completion_button->value());} + callback {Fluid.preferences.set("show_completion_dialogs", completion_button->value());} xywh {120 135 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} - code1 {fluid_prefs.get("show_completion_dialogs", b, 1);} + code1 {Fluid.preferences.get("show_completion_dialogs", b, 1);} code2 {completion_button->value(b);} } Fl_Check_Button openlast_button { label {Open Previous File on Startup} - callback {fluid_prefs.set("open_previous_file", openlast_button->value());} + callback {Fluid.preferences.set("open_previous_file", openlast_button->value());} xywh {120 155 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} - code1 {fluid_prefs.get("open_previous_file", b, 0);} + code1 {Fluid.preferences.get("open_previous_file", b, 0);} code2 {openlast_button->value(b);} } Fl_Check_Button prevpos_button { label {Remember Window Positions} - callback {fluid_prefs.set("prev_window_pos", prevpos_button->value());} + callback {Fluid.preferences.set("prev_window_pos", prevpos_button->value());} xywh {120 175 200 20} down_box DOWN_BOX labelsize 11 code0 {int b;} - code1 {fluid_prefs.get("prev_window_pos", b, 1);} + code1 {Fluid.preferences.get("prev_window_pos", b, 1);} code2 {prevpos_button->value(b);} } Fl_Check_Button show_comments_button { label {Show Comments in Browser} - callback {show_comments = show_comments_button->value(); -fluid_prefs.set("show_comments", show_comments); + callback {Fluid.show_comments = show_comments_button->value(); +Fluid.preferences.set("Fluid.show_comments", Fluid.show_comments); redraw_browser();} xywh {120 195 200 20} down_box DOWN_BOX labelsize 11 - code1 {fluid_prefs.get("show_comments", show_comments, 1);} - code2 {show_comments_button->value(show_comments);} + code1 {Fluid.preferences.get("Fluid.show_comments", Fluid.show_comments, 1);} + code2 {show_comments_button->value(Fluid.show_comments);} } Fl_Group {} { callback {propagate_load(o, v);} open @@ -273,11 +269,11 @@ redraw_browser();} } { Fl_Spinner recent_spinner { label {\# Recent Files:} - callback {fluid_prefs.set("recent_files", recent_spinner->value()); -load_history();} + callback {Fluid.preferences.set("recent_files", recent_spinner->value()); +Fluid.history.load();} xywh {120 225 40 20} labelfont 1 labelsize 11 when 1 maximum 10 textsize 11 code0 {int c;} - code1 {fluid_prefs.get("recent_files", c, 5);} + code1 {Fluid.preferences.get("recent_files", c, 5);} code2 {recent_spinner->maximum(10);} code3 {recent_spinner->value(c);} } @@ -287,18 +283,18 @@ load_history();} } Fl_Check_Button use_external_editor_button { label {Use for Code Nodes} - callback {G_use_external_editor = use_external_editor_button->value(); -fluid_prefs.set("use_external_editor", G_use_external_editor); + callback {Fluid.use_external_editor = use_external_editor_button->value(); +Fluid.preferences.set("use_external_editor", Fluid.use_external_editor); redraw_browser();} xywh {120 275 200 20} down_box DOWN_BOX labelsize 11 - code1 {fluid_prefs.get("use_external_editor", G_use_external_editor, 0);} - code2 {use_external_editor_button->value(G_use_external_editor);} + code1 {Fluid.preferences.get("use_external_editor", Fluid.use_external_editor, 0);} + code2 {use_external_editor_button->value(Fluid.use_external_editor);} } Fl_Input editor_command_input { label {External Editor:} - callback {strncpy(G_external_editor_command, editor_command_input->value(), sizeof(G_external_editor_command)-1); -G_external_editor_command[sizeof(G_external_editor_command)-1] = 0; -fluid_prefs.set("external_editor_command", G_external_editor_command); + callback {strncpy(Fluid.external_editor_command, editor_command_input->value(), sizeof(Fluid.external_editor_command)-1); +Fluid.external_editor_command[sizeof(Fluid.external_editor_command)-1] = 0; +Fluid.preferences.set("external_editor_command", Fluid.external_editor_command); redraw_browser();} tooltip {The editor command to open your external text editor. Include any necessary flags to ensure your editor does not background itself. @@ -306,8 +302,8 @@ Examples: gvim -f gedit emacs} xywh {120 255 200 20} labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 - code1 {fluid_prefs.get("external_editor_command", G_external_editor_command, "", sizeof(G_external_editor_command)-1);} - code2 {editor_command_input->value(G_external_editor_command);} + code1 {Fluid.preferences.get("external_editor_command", Fluid.external_editor_command, "", sizeof(Fluid.external_editor_command)-1);} + code2 {editor_command_input->value(Fluid.external_editor_command);} } Fl_Box {} { label {Overlays: } @@ -317,19 +313,19 @@ Examples: label {Show Positioning Guides} callback toggle_guides_cb tooltip {show guides that help to position and resize widgets and enable snapping} xywh {120 300 200 20} down_box DOWN_BOX labelsize 11 - code0 {o->value(show_guides);} + code0 {o->value(Fluid.show_guides);} } Fl_Check_Button restricted_button { label {Show Restricted Areas} callback toggle_restricted_cb tooltip {show overlapping and out of bounds areas, show unfilled areas in Fl_Pack groups} xywh {120 320 200 20} down_box DOWN_BOX labelsize 11 - code0 {o->value(show_restricted);} + code0 {o->value(Fluid.show_restricted);} } Fl_Check_Button ghosted_outline_button { label {Show Ghosted Group Outlines} callback toggle_ghosted_outline_cb tooltip {groups with no box type or flat boxtypes without contrast will be rendered with a dim outline in the editing window only} xywh {120 340 200 20} down_box DOWN_BOX labelsize 11 - code0 {o->value(show_ghosted_outline);} + code0 {o->value(Fluid.show_ghosted_outline);} } Fl_Box {} { xywh {120 530 200 10} hide resizable @@ -356,11 +352,11 @@ or just ".ext" to set extension.} label {Header File:} user_data 1 user_data_type {void*} callback {if (v == LOAD) { - o->value(g_project.header_file_name.c_str()); + o->value(Fluid.proj.header_file_name.c_str()); } else { - if (strcmp(g_project.header_file_name.c_str(), o->value())) { - g_project.header_file_name = o->value(); - set_modflag(1); + if (strcmp(Fluid.proj.header_file_name.c_str(), o->value())) { + Fluid.proj.header_file_name = o->value(); + Fluid.proj.set_modflag(1); } }} tooltip {The name of the generated header file.} xywh {100 112 220 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 @@ -369,11 +365,11 @@ or just ".ext" to set extension.} label {Code File:} user_data 1 user_data_type {void*} callback {if (v == LOAD) { - o->value(g_project.code_file_name.c_str()); + o->value(Fluid.proj.code_file_name.c_str()); } else { - if (strcmp(g_project.code_file_name.c_str(), o->value())) { - g_project.code_file_name = o->value(); - set_modflag(1); + if (strcmp(Fluid.proj.code_file_name.c_str(), o->value())) { + Fluid.proj.code_file_name = o->value(); + Fluid.proj.set_modflag(1); } }} tooltip {The name of the generated code file.} xywh {100 137 220 20} box THIN_DOWN_BOX labelfont 1 labelsize 11 when 1 textfont 4 textsize 11 @@ -381,11 +377,11 @@ or just ".ext" to set extension.} Fl_Check_Button include_H_from_C_button { label {Include Header from Code} callback {if (v == LOAD) { - o->value(g_project.include_H_from_C); + o->value(Fluid.proj.include_H_from_C); } else { - if (g_project.include_H_from_C != o->value()) { - set_modflag(1); - g_project.include_H_from_C = o->value(); + if (Fluid.proj.include_H_from_C != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.include_H_from_C = o->value(); } }} tooltip {Include the header file from the code file.} xywh {100 162 220 20} down_box DOWN_BOX labelsize 11 @@ -397,11 +393,11 @@ or just ".ext" to set extension.} Fl_Check_Button use_FL_COMMAND_button { label {Menu shortcuts use FL_COMMAND} callback {if (v == LOAD) { - o->value(g_project.use_FL_COMMAND); + o->value(Fluid.proj.use_FL_COMMAND); } else { - if (g_project.use_FL_COMMAND != o->value()) { - set_modflag(1); - g_project.use_FL_COMMAND = o->value(); + if (Fluid.proj.use_FL_COMMAND != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.use_FL_COMMAND = o->value(); } }} tooltip {Replace FL_CTRL and FL_META with FL_COMMAND when generating menu shortcuts} xywh {100 205 220 20} down_box DOWN_BOX labelsize 11 @@ -409,11 +405,11 @@ or just ".ext" to set extension.} Fl_Check_Button utf8_in_src_button { label {allow Unicode UTF-8 in source code} callback {if (v == LOAD) { - o->value(g_project.utf8_in_src); + o->value(Fluid.proj.utf8_in_src); } else { - if (g_project.utf8_in_src != o->value()) { - set_modflag(1); - g_project.utf8_in_src = o->value(); + if (Fluid.proj.utf8_in_src != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.utf8_in_src = o->value(); } }} tooltip {For older compilers, characters outside of the printable ASCII range are escaped using octal notation `\\0123`. If this option is checked, Fluid will write UTF-8 characters unchanged.} xywh {100 230 220 20} down_box DOWN_BOX labelsize 11 @@ -421,11 +417,11 @@ or just ".ext" to set extension.} Fl_Check_Button avoid_early_includes_button { label {avoid early include of Fl.H} callback {if (v == LOAD) { - o->value(g_project.avoid_early_includes); + o->value(Fluid.proj.avoid_early_includes); } else { - if (g_project.avoid_early_includes != o->value()) { - set_modflag(1); - g_project.avoid_early_includes = o->value(); + if (Fluid.proj.avoid_early_includes != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.avoid_early_includes = o->value(); } }} tooltip {Do not emit \#include until it is needed by another include file.} xywh {100 255 220 20} down_box DOWN_BOX labelsize 11 @@ -437,11 +433,11 @@ or just ".ext" to set extension.} Fl_Check_Button w_proj_mergeback { label {generate MergeBack data} callback {if (v == LOAD) { - o->value(g_project.write_mergeback_data); + o->value(Fluid.proj.write_mergeback_data); } else { - if (g_project.write_mergeback_data != o->value()) { - set_modflag(1); - g_project.write_mergeback_data = o->value(); + if (Fluid.proj.write_mergeback_data != o->value()) { + Fluid.proj.set_modflag(1); + Fluid.proj.write_mergeback_data = o->value(); } }} comment {// Matt: disabled} @@ -462,11 +458,11 @@ or just ".ext" to set extension.} } Fl_Choice layout_choice { callback {if (v == LOAD) { - o->value(g_layout_list.current_suite()); + o->value(Fluid.layout_list.current_suite()); } else { int index = o->value(); - g_layout_list.current_suite(index); - g_layout_list.update_dialogs(); + Fluid.layout_list.current_suite(index); + Fluid.layout_list.update_dialogs(); }} xywh {85 78 187 24} down_box BORDER_BOX } { @@ -486,19 +482,19 @@ or just ".ext" to set extension.} if (v == LOAD) return; std::string old_name = "Copy of "; -old_name.append(g_layout_list[g_layout_list.current_suite()].name_); +old_name.append(Fluid.layout_list[Fluid.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) +if (new_name == nullptr) return; -g_layout_list.add(new_name); -g_layout_list.update_dialogs();} +Fluid.layout_list.add(new_name); +Fluid.layout_list.update_dialogs();} xywh {272 78 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) { + fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; + if (suite.storage_ == fld::Tool_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(); @@ -507,7 +503,7 @@ g_layout_list.update_dialogs();} 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(); + w_layout_menu_storage[static_cast(suite.storage_)]->setonly(); }} open xywh {296 78 24 24} } { @@ -515,41 +511,41 @@ g_layout_list.update_dialogs();} label {Rename...} callback {// Rename the current layout suite -std::string old_name = g_layout_list[g_layout_list.current_suite()].name_; +std::string old_name = Fluid.layout_list[Fluid.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) +if (new_name == nullptr) return; -g_layout_list.rename(new_name); -g_layout_list.update_dialogs();} +Fluid.layout_list.rename(new_name); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} 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();} + callback {fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; +suite.storage(fld::Tool_Store::INTERNAL); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} type Radio 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();} + callback {fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; +suite.storage(fld::Tool_Store::USER); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} type Radio } 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();} + callback {fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; +suite.storage(fld::Tool_Store::PROJECT); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} type Radio } 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();} + callback {fld::app::Layout_Suite &suite = Fluid.layout_list[Fluid.layout_list.current_suite()]; +suite.storage(fld::Tool_Store::FILE); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} type Radio divider } MenuItem w_layout_menu_load { @@ -563,9 +559,9 @@ 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();} +Fluid.layout_list.load(new_filename); +//Fluid.layout_list.current_suite(n); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} } MenuItem w_layout_menu_save { @@ -576,14 +572,14 @@ g_layout_list.update_dialogs();} 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"); - std::string filename = g_layout_list.filename_; + std::string filename = Fluid.layout_list.filename_; fnfc.directory(fl_filename_path_str(filename).c_str()); fnfc.preset_file(fl_filename_name_str(filename).c_str()); if (fnfc.show() != 0) return; const char *new_filename = fnfc.filename(); if (!new_filename) return; - g_layout_list.filename_ = new_filename; - g_layout_list.save(new_filename);} + Fluid.layout_list.filename_ = new_filename; + Fluid.layout_list.save(new_filename);} xywh {0 0 31 20} divider code0 {\#include } } @@ -591,8 +587,8 @@ g_layout_list.update_dialogs();} label Delete callback {// remove the current suite -g_layout_list.remove(g_layout_list.current_suite()); -g_layout_list.update_dialogs();} +Fluid.layout_list.remove(Fluid.layout_list.current_suite()); +Fluid.layout_list.update_dialogs();} xywh {0 0 31 20} } } @@ -634,36 +630,36 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Left:} callback {if (v == LOAD) { - o->value((double)layout->left_window_margin); + o->value((double)Fluid.proj.layout->left_window_margin); } else { - layout->left_window_margin = (int)o->value(); + Fluid.proj.layout->left_window_margin = (int)o->value(); }} xywh {85 167 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); + o->value((double)Fluid.proj.layout->top_window_margin); } else { - layout->top_window_margin = (int)o->value(); + Fluid.proj.layout->top_window_margin = (int)o->value(); }} xywh {145 167 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); + o->value((double)Fluid.proj.layout->right_window_margin); } else { - layout->right_window_margin = (int)o->value(); + Fluid.proj.layout->right_window_margin = (int)o->value(); }} xywh {205 167 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); + o->value((double)Fluid.proj.layout->bottom_window_margin); } else { - layout->bottom_window_margin = (int)o->value(); + Fluid.proj.layout->bottom_window_margin = (int)o->value(); }} xywh {265 167 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -674,18 +670,18 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Horizontal:} callback {if (v == LOAD) { - o->value((double)layout->window_grid_x); + o->value((double)Fluid.proj.layout->window_grid_x); } else { - layout->window_grid_x = (int)o->value(); + Fluid.proj.layout->window_grid_x = (int)o->value(); }} xywh {85 201 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); + o->value((double)Fluid.proj.layout->window_grid_y); } else { - layout->window_grid_y = (int)o->value(); + Fluid.proj.layout->window_grid_y = (int)o->value(); }} xywh {145 201 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -700,36 +696,36 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Left:} callback {if (v == LOAD) { - o->value((double)layout->left_group_margin); + o->value((double)Fluid.proj.layout->left_group_margin); } else { - layout->left_group_margin = (int)o->value(); + Fluid.proj.layout->left_group_margin = (int)o->value(); }} xywh {85 261 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); + o->value((double)Fluid.proj.layout->top_group_margin); } else { - layout->top_group_margin = (int)o->value(); + Fluid.proj.layout->top_group_margin = (int)o->value(); }} xywh {145 261 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); + o->value((double)Fluid.proj.layout->right_group_margin); } else { - layout->right_group_margin = (int)o->value(); + Fluid.proj.layout->right_group_margin = (int)o->value(); }} xywh {205 261 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); + o->value((double)Fluid.proj.layout->bottom_group_margin); } else { - layout->bottom_group_margin = (int)o->value(); + Fluid.proj.layout->bottom_group_margin = (int)o->value(); }} xywh {265 261 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -740,18 +736,18 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Horizontal:} callback {if (v == LOAD) { - o->value((double)layout->group_grid_x); + o->value((double)Fluid.proj.layout->group_grid_x); } else { - layout->group_grid_x = (int)o->value(); + Fluid.proj.layout->group_grid_x = (int)o->value(); }} xywh {85 295 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); + o->value((double)Fluid.proj.layout->group_grid_y); } else { - layout->group_grid_y = (int)o->value(); + Fluid.proj.layout->group_grid_y = (int)o->value(); }} xywh {145 295 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -766,18 +762,18 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Top:} callback {if (v == LOAD) { - o->value((double)layout->top_tabs_margin); + o->value((double)Fluid.proj.layout->top_tabs_margin); } else { - layout->top_tabs_margin = (int)o->value(); + Fluid.proj.layout->top_tabs_margin = (int)o->value(); }} xywh {85 355 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); + o->value((double)Fluid.proj.layout->bottom_tabs_margin); } else { - layout->bottom_tabs_margin = (int)o->value(); + Fluid.proj.layout->bottom_tabs_margin = (int)o->value(); }} xywh {145 355 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -792,27 +788,27 @@ g_layout_list.update_dialogs();} Fl_Value_Input {} { label {Minimum:} callback {if (v == LOAD) { - o->value((double)layout->widget_min_w); + o->value((double)Fluid.proj.layout->widget_min_w); } else { - layout->widget_min_w = (int)o->value(); + Fluid.proj.layout->widget_min_w = (int)o->value(); }} xywh {85 414 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); + o->value((double)Fluid.proj.layout->widget_inc_w); } else { - layout->widget_inc_w = (int)o->value(); + Fluid.proj.layout->widget_inc_w = (int)o->value(); }} xywh {145 414 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); + o->value((double)Fluid.proj.layout->widget_gap_x); } else { - layout->widget_gap_x = (int)o->value(); + Fluid.proj.layout->widget_gap_x = (int)o->value(); }} xywh {205 414 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -822,25 +818,25 @@ g_layout_list.update_dialogs();} } Fl_Value_Input {} { callback {if (v == LOAD) { - o->value((double)layout->widget_min_h); + o->value((double)Fluid.proj.layout->widget_min_h); } else { - layout->widget_min_h = (int)o->value(); + Fluid.proj.layout->widget_min_h = (int)o->value(); }} xywh {85 440 55 20} labelsize 11 maximum 32767 step 1 textsize 11 } Fl_Value_Input {} { callback {if (v == LOAD) { - o->value((double)layout->widget_inc_h); + o->value((double)Fluid.proj.layout->widget_inc_h); } else { - layout->widget_inc_h = (int)o->value(); + Fluid.proj.layout->widget_inc_h = (int)o->value(); }} xywh {145 440 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); + o->value((double)Fluid.proj.layout->widget_gap_y); } else { - layout->widget_gap_y = (int)o->value(); + Fluid.proj.layout->widget_gap_y = (int)o->value(); }} xywh {205 440 55 20} labelsize 11 align 5 maximum 32767 step 1 textsize 11 } @@ -851,9 +847,9 @@ g_layout_list.update_dialogs();} } { Fl_Choice {} { callback {if (v == LOAD) { - o->value(layout->labelfont+1); + o->value(Fluid.proj.layout->labelfont+1); } else { - layout->labelfont = (int)o->value()-1; + Fluid.proj.layout->labelfont = (int)o->value()-1; }} open tooltip {The style of the label text.} xywh {85 465 150 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item fontmenu_w_default[];} @@ -861,9 +857,9 @@ g_layout_list.update_dialogs();} } {} Fl_Value_Input {} { callback {if (v == LOAD) { - o->value(layout->labelsize); + o->value(Fluid.proj.layout->labelsize); } else { - layout->labelsize = (int)o->value(); + Fluid.proj.layout->labelsize = (int)o->value(); }} tooltip {The size of the label text.} xywh {235 465 50 20} labelsize 11 minimum 1 maximum 1000 step 1 value 14 textsize 11 } @@ -875,9 +871,9 @@ g_layout_list.update_dialogs();} } { Fl_Choice {} { callback {if (v == LOAD) { - o->value(layout->textfont+1); + o->value(Fluid.proj.layout->textfont+1); } else { - layout->textfont = (int)o->value()-1; + Fluid.proj.layout->textfont = (int)o->value()-1; }} open tooltip {The value text style.} xywh {85 490 150 20} box DOWN_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 code0 {extern Fl_Menu_Item fontmenu_w_default[];} @@ -885,9 +881,9 @@ g_layout_list.update_dialogs();} } {} Fl_Value_Input {} { callback {if (v == LOAD) { - o->value(layout->textsize); + o->value(Fluid.proj.layout->textsize); } else { - layout->textsize = (int)o->value(); + Fluid.proj.layout->textsize = (int)o->value(); }} tooltip {The value text size.} xywh {235 490 50 20} labelsize 11 maximum 1000 step 1 value 14 textsize 11 } @@ -917,9 +913,9 @@ list:} for (int i=0; ilist_size; i++) { Fd_Shell_Command *cmd = g_shell_config->list[i]; o->add(cmd->name.c_str()); - if (cmd->storage == FD_STORE_USER) + if (cmd->storage == fld::Tool_Store::USER) o->icon(i+1, w_settings_shell_fd_user->image()); - else if (cmd->storage == FD_STORE_PROJECT) + else if (cmd->storage == fld::Tool_Store::PROJECT) o->icon(i+1, w_settings_shell_fd_project->image()); } } @@ -951,11 +947,11 @@ list:} w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); - if (cmd->storage == FD_STORE_USER) { + if (cmd->storage == fld::Tool_Store::USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); - } else if (cmd->storage == FD_STORE_PROJECT) { + } else if (cmd->storage == fld::Tool_Store::PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); - set_modflag(1); + Fluid.proj.set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); @@ -980,11 +976,11 @@ if (v==LOAD) { w_settings_shell_list->insert(selected+1, cmd->name.c_str()); w_settings_shell_list->deselect(); w_settings_shell_list->value(selected+1); - if (cmd->storage == FD_STORE_USER) { + if (cmd->storage == fld::Tool_Store::USER) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_user->image()); - } else if (cmd->storage == FD_STORE_PROJECT) { + } else if (cmd->storage == fld::Tool_Store::PROJECT) { w_settings_shell_list->icon(selected+1, w_settings_shell_fd_project->image()); - set_modflag(1); + Fluid.proj.set_modflag(1); } w_settings_shell_list->do_callback(); w_settings_shell_cmd->do_callback(w_settings_shell_cmd, LOAD); @@ -1005,9 +1001,9 @@ if (v==LOAD) { } else { if (!selected) return; int ret = fl_choice("Delete the shell command\\n\\"%s\\"?\\n\\nThis can not be undone.", - "Delete", "Cancel", NULL, g_shell_config->list[selected-1]->name.c_str()); + "Delete", "Cancel", nullptr, g_shell_config->list[selected-1]->name.c_str()); if (ret==1) return; - if (g_shell_config->at(selected-1)->storage == FD_STORE_PROJECT) set_modflag(1); + if (g_shell_config->at(selected-1)->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); g_shell_config->remove(selected-1); w_settings_shell_list->remove(selected); if (selected <= w_settings_shell_list->size()) @@ -1109,7 +1105,7 @@ if (v == LOAD) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->name = o->value(); w_settings_shell_list->text(selected, o->value()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {file the shell command under this name in the shell command list} xywh {100 246 220 20} labelfont 1 labelsize 11 when 13 textfont 4 textsize 11 @@ -1128,7 +1124,7 @@ if (v == LOAD) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->label = o->value(); cmd->update_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {label text for the Shell menu in the main menu bar} xywh {100 272 220 20} labelfont 1 labelsize 11 textfont 4 textsize 11 @@ -1152,7 +1148,7 @@ if (v == LOAD) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->shortcut = o->value(); cmd->update_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {an optional keyboard shortcut to run this shell command} xywh {100 297 130 20} labelsize 11 align 16 @@ -1164,35 +1160,35 @@ if (v == LOAD) { callback {int selected = w_settings_shell_list_selected; if (v == LOAD) { if (selected) { - Fd_Tool_Store ts = g_shell_config->list[selected-1]->storage; + fld::Tool_Store ts = g_shell_config->list[selected-1]->storage; o->value(o->find_item_with_argument((long)ts)); } else { - o->value(o->find_item_with_argument((long)FD_STORE_USER)); + o->value(o->find_item_with_argument((long)fld::Tool_Store::USER)); } } else { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; - Fd_Tool_Store ts = (Fd_Tool_Store)(o->mvalue()->argument()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + fld::Tool_Store ts = (fld::Tool_Store)(o->mvalue()->argument()); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); cmd->storage = ts; //w_settings_shell_list->text(selected, cmd->name.c_str()); - if (cmd->storage == FD_STORE_USER) + if (cmd->storage == fld::Tool_Store::USER) w_settings_shell_list->icon(selected, w_settings_shell_fd_user->image()); - else if (cmd->storage == FD_STORE_PROJECT) + else if (cmd->storage == fld::Tool_Store::PROJECT) w_settings_shell_list->icon(selected, w_settings_shell_fd_project->image()); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} open tooltip {store this shell command as a user setting or save it with the .fl project file} xywh {100 322 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 } { MenuItem {} { label {@fd_user User Setting} - user_data FD_STORE_USER user_data_type long + user_data {fld::Tool_Store::USER} user_data_type long xywh {0 0 100 20} labelsize 11 } MenuItem {} { label {@fd_project Project File} - user_data FD_STORE_PROJECT user_data_type long + user_data {fld::Tool_Store::PROJECT} user_data_type long xywh {0 0 100 20} labelsize 11 } } @@ -1212,7 +1208,7 @@ if (v == LOAD) { int cond = (int)(o->mvalue()->argument()); cmd->condition = cond; g_shell_config->rebuild_shell_menu(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} open tooltip {add this command to the main menu bar only if this condition is true} xywh {100 348 130 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 @@ -1278,7 +1274,7 @@ if (v == LOAD) { if (selected) { Fd_Shell_Command *cmd = g_shell_config->list[selected-1]; cmd->command = o->buffer()->text(); - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} xywh {100 373 196 80} labelfont 1 labelsize 11 align 4 textfont 4 textsize 12 resizable @@ -1304,7 +1300,7 @@ if (mi) { int pos = w_settings_shell_command->insert_position(); w_settings_shell_command->buffer()->insert(pos, word); } - w_settings_shell_command->do_callback(w_settings_shell_command, (void*)NULL); + w_settings_shell_command->do_callback(w_settings_shell_command, (void*)nullptr); }} open tooltip {a list of text replacements available for the shell script} xywh {296 373 24 22} labelsize 11 textsize 11 } { @@ -1396,7 +1392,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_PROJECT; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {save the project to the .fl file before running the command} xywh {100 458 110 20} down_box DOWN_BOX labelsize 11 @@ -1419,7 +1415,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_SOURCECODE; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {generate the source code and header file before running the command} xywh {100 478 110 19} down_box DOWN_BOX labelsize 11 @@ -1442,7 +1438,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::SAVE_STRINGS; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {save the internationalisation strings before running the command} xywh {100 498 110 20} down_box DOWN_BOX labelsize 11 @@ -1465,7 +1461,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::DONT_SHOW_TERMINAL; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {show the terminal window when launching this script} xywh {214 458 106 20} down_box DOWN_BOX labelsize 11 @@ -1488,7 +1484,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_TERMINAL; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {clear the teminal window before running this script} xywh {214 478 106 19} down_box DOWN_BOX labelsize 11 @@ -1511,7 +1507,7 @@ if (v == LOAD) { } else { cmd->flags &= ~Fd_Shell_Command::CLEAR_HISTORY; } - if (cmd->storage == FD_STORE_PROJECT) set_modflag(1); + if (cmd->storage == fld::Tool_Store::PROJECT) Fluid.proj.set_modflag(1); } }} tooltip {clear the teminal history in the terminal window} xywh {214 498 106 19} down_box DOWN_BOX labelsize 11 @@ -1564,44 +1560,44 @@ if (v == LOAD) { Fl_Input i18n_gnu_include_input { label {\#include:} callback {if (v == LOAD) { - o->value(g_project.i18n_gnu_include.c_str()); + o->value(Fluid.proj.i18n_gnu_include.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_include = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_include = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_conditional_input { label {Conditional:} callback {if (v == LOAD) { - o->value(g_project.i18n_gnu_conditional.c_str()); + o->value(Fluid.proj.i18n_gnu_conditional.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_conditional = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_conditional = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_function_input { label {Function:} callback {if (v == LOAD) { - o->value(g_project.i18n_gnu_function.c_str()); + o->value(Fluid.proj.i18n_gnu_function.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_function = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_function = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {The function to call to translate labels and tooltips, usually "gettext" or "_"} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_gnu_static_function_input { label {Static Function:} callback {if (v == LOAD) { - o->value(g_project.i18n_gnu_static_function.c_str()); + o->value(Fluid.proj.i18n_gnu_static_function.c_str()); } else { - undo_checkpoint(); - g_project.i18n_gnu_static_function = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_gnu_static_function = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {function to call to translate static text, The function to call to internationalize labels and tooltips, usually "gettext_noop" or "N_"} xywh {100 178 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } @@ -1613,33 +1609,33 @@ if (v == LOAD) { Fl_Input i18n_pos_include_input { label {\#include:} callback {if (v == LOAD) { - o->value(g_project.i18n_pos_include.c_str()); + o->value(Fluid.proj.i18n_pos_include.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_include = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_include = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {The include file for internationalization.} xywh {100 103 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_pos_conditional_input { label {Conditional:} callback {if (v == LOAD) { - o->value(g_project.i18n_pos_conditional.c_str()); + o->value(Fluid.proj.i18n_pos_conditional.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_conditional = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_conditional = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {only include the header file if this preprocessor macro is defined, for example FLTK_GETTEXT_FOUND} xywh {100 128 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } Fl_Input i18n_pos_file_input { label {Catalog:} callback {if (v == LOAD) { - o->value(g_project.i18n_pos_file.c_str()); + o->value(Fluid.proj.i18n_pos_file.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_file = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_file = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {The name of the message catalog.} xywh {100 153 220 20} box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } @@ -1650,11 +1646,11 @@ if (v == LOAD) { Fl_Input i18n_pos_set_input { label {Set:} callback {if (v == LOAD) { - o->value(g_project.i18n_pos_set.c_str()); + o->value(Fluid.proj.i18n_pos_set.c_str()); } else { - undo_checkpoint(); - g_project.i18n_pos_set = o->value(); - set_modflag(1); + Fluid.proj.undo.checkpoint(); + Fluid.proj.i18n_pos_set = o->value(); + Fluid.proj.set_modflag(1); }} tooltip {The message set number.} xywh {100 178 80 20} type Int box THIN_DOWN_BOX labelsize 11 textfont 4 textsize 11 } @@ -1835,8 +1831,8 @@ if (v == LOAD) { Fl_Button {} { label Close callback {if (g_shell_config) - g_shell_config->write(fluid_prefs, FD_STORE_USER); -g_layout_list.write(fluid_prefs, FD_STORE_USER); + g_shell_config->write(Fluid.preferences, fld::Tool_Store::USER); +Fluid.layout_list.write(Fluid.preferences, fld::Tool_Store::USER); settings_window->hide();} tooltip {Close this dialog.} xywh {230 550 100 20} labelsize 11 } @@ -1873,7 +1869,7 @@ shell_run_terminal->append("\\033[2J\\033[3J\\033[H");} } Fl_Return_Button shell_run_button { label Close - callback {Fl_Preferences pos(fluid_prefs, "shell_run_Window_pos"); + callback {Fl_Preferences pos(Fluid.preferences, "shell_run_Window_pos"); pos.set("x", shell_run_window->x()); pos.set("y", shell_run_window->y()); pos.set("w", shell_run_window->w()); diff --git a/fluid/panels/settings_panel.h b/fluid/panels/settings_panel.h index 8aea3a221..c864d23b5 100644 --- a/fluid/panels/settings_panel.h +++ b/fluid/panels/settings_panel.h @@ -19,8 +19,8 @@ #ifndef settings_panel_h #define settings_panel_h #include -#include "app/fluid.h" -#include "app/Fd_Snap_Action.h" +#include "Fluid.h" +#include "app/Snap_Action.h" #include "app/shell_command.h" #include "tools/filename.h" #include "widgets/Node_Browser.h" @@ -28,10 +28,6 @@ #include #include #include -/** - // initialize the scheme from preferences -*/ -void init_scheme(void); extern struct Fl_Menu_Item *dbmanager_item; extern void i18n_cb(Fl_Choice *,void *); extern void scheme_cb(Fl_Scheme_Choice *, void *); @@ -52,7 +48,6 @@ extern Fl_Double_Window *settings_window; #include extern Fl_Tabs *w_settings_tabs; extern Fl_Group *w_settings_general_tab; -extern void scheme_cb(Fl_Scheme_Choice*, void*); extern Fl_Scheme_Choice *scheme_choice; #include extern Fl_Check_Button *tooltips_button; diff --git a/fluid/panels/template_panel.cxx b/fluid/panels/template_panel.cxx index 11227a549..7c2a9ac2b 100644 --- a/fluid/panels/template_panel.cxx +++ b/fluid/panels/template_panel.cxx @@ -17,7 +17,7 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "template_panel.h" -#include "app/fluid.h" +#include "Fluid.h" #include "tools/filename.h" #include #include @@ -84,7 +84,7 @@ static void cb_template_browser(Fl_Browser*, void*) { char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); - if ((ext = strrchr(pngfile, '.')) == NULL) return; + if ((ext = strrchr(pngfile, '.')) == nullptr) return; strcpy(ext, ".png"); img = Fl_Shared_Image::get(pngfile); @@ -183,7 +183,7 @@ void template_clear() { void *filename; for (i = 1; i <= template_browser->size(); i ++) { - if ((filename = template_browser->data(i)) != NULL) free(filename); + if ((filename = template_browser->data(i)) != nullptr) free(filename); } template_browser->deselect(); @@ -208,7 +208,7 @@ void template_delete_cb(Fl_Button *, void *) { char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); - if ((ext = strrchr(pngfile, '.')) != NULL) { + if ((ext = strrchr(pngfile, '.')) != nullptr) { strcpy(ext, ".png"); fl_unlink(pngfile); } @@ -284,12 +284,12 @@ void template_load() { struct dirent **files; int num_files; - fluid_prefs.getUserdataPath(path, sizeof(path)); + Fluid.preferences.getUserdataPath(path, sizeof(path)); strlcat(path, "templates", sizeof(path)); fl_make_path(path); int sample_templates_generated = 0; - fluid_prefs.get("sample_templates_generated", sample_templates_generated, 0); + Fluid.preferences.get("sample_templates_generated", sample_templates_generated, 0); if (sample_templates_generated < 2) { strcpy(filename, path); @@ -311,8 +311,8 @@ void template_load() { template_install(path, "/FLTK_License.fl", tmpl_FLTK_License_fl, sizeof(tmpl_FLTK_License_fl), tmpl_FLTK_License_fl_size); template_install(path, "/1of7GUIs.fl", tmpl_1of7GUIs_fl, sizeof(tmpl_1of7GUIs_fl), tmpl_1of7GUIs_fl_size); sample_templates_generated = 2; - fluid_prefs.set("sample_templates_generated", sample_templates_generated); - fluid_prefs.flush(); + Fluid.preferences.set("sample_templates_generated", sample_templates_generated); + Fluid.preferences.flush(); } num_files = fl_filename_list(path, &files); diff --git a/fluid/panels/template_panel.fl b/fluid/panels/template_panel.fl index b0ba20968..be0376c2c 100644 --- a/fluid/panels/template_panel.fl +++ b/fluid/panels/template_panel.fl @@ -20,7 +20,7 @@ comment {// } {in_source in_header } -decl {\#include "app/fluid.h"} {private local +decl {\#include "Fluid.h"} {private local } decl {\#include "tools/filename.h"} {selected private local @@ -111,7 +111,7 @@ template_delete->activate(); char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); -if ((ext = strrchr(pngfile, '.')) == NULL) return; +if ((ext = strrchr(pngfile, '.')) == nullptr) return; strcpy(ext, ".png"); img = Fl_Shared_Image::get(pngfile); @@ -179,7 +179,7 @@ Function {template_clear()} {return_type void void *filename; for (i = 1; i <= template_browser->size(); i ++) { - if ((filename = template_browser->data(i)) != NULL) free(filename); + if ((filename = template_browser->data(i)) != nullptr) free(filename); } template_browser->deselect(); @@ -205,7 +205,7 @@ if (fl_unlink(flfile)) { char pngfile[1024], *ext; strlcpy(pngfile, flfile, sizeof(pngfile)); -if ((ext = strrchr(pngfile, '.')) != NULL) { +if ((ext = strrchr(pngfile, '.')) != nullptr) { strcpy(ext, ".png"); fl_unlink(pngfile); } @@ -241,12 +241,12 @@ char name[1024], filename[1400], path[1024], *ptr; struct dirent **files; int num_files; -fluid_prefs.getUserdataPath(path, sizeof(path)); +Fluid.preferences.getUserdataPath(path, sizeof(path)); strlcat(path, "templates", sizeof(path)); fl_make_path(path); int sample_templates_generated = 0; -fluid_prefs.get("sample_templates_generated", sample_templates_generated, 0); +Fluid.preferences.get("sample_templates_generated", sample_templates_generated, 0); if (sample_templates_generated < 2) { strcpy(filename, path); @@ -268,8 +268,8 @@ if (sample_templates_generated < 2) { template_install(path, "/FLTK_License.fl", tmpl_FLTK_License_fl, sizeof(tmpl_FLTK_License_fl), tmpl_FLTK_License_fl_size); template_install(path, "/1of7GUIs.fl", tmpl_1of7GUIs_fl, sizeof(tmpl_1of7GUIs_fl), tmpl_1of7GUIs_fl_size); sample_templates_generated = 2; - fluid_prefs.set("sample_templates_generated", sample_templates_generated); - fluid_prefs.flush(); + Fluid.preferences.set("sample_templates_generated", sample_templates_generated); + Fluid.preferences.flush(); } num_files = fl_filename_list(path, &files); diff --git a/fluid/panels/widget_panel.cxx b/fluid/panels/widget_panel.cxx index df903d4a2..61b480f36 100644 --- a/fluid/panels/widget_panel.cxx +++ b/fluid/panels/widget_panel.cxx @@ -17,11 +17,32 @@ // generated by Fast Light User Interface Designer (fluid) version 1.0500 #include "widget_panel.h" -#include "app/undo.h" -#include "nodes/Fl_Widget_Type.h" -#include "nodes/Fl_Grid_Type.h" +#include "Fluid.h" +#include "app/Snap_Action.h" +#include "app/Image_Asset.h" +#include "proj/undo.h" +#include "nodes/Window_Node.h" +#include "nodes/Grid_Node.h" +#include #include -extern void set_modflag(int mf, int mfc=-1); +#include +#include +#include +#define ZERO_ENTRY 1000 +extern const char* when_symbol_name(int n); +extern void set_whenmenu(int n); +extern void redraw_browser(); +const char *c_check(const char *c, int type=0); +extern Fl_Color fl_show_colormap(Fl_Color oldcol); +extern void labelcolor_common(Fl_Color c); +extern void color_common(Fl_Color c); +extern void color2_common(Fl_Color c); +extern void textcolor_common(Fl_Color c); +extern int widget_i; +extern fld::widget::Formula_Input_Vars widget_vars[]; +extern int numselected; +extern Fl_Menu_Item boxmenu[]; +extern int haderror; Fl_Double_Window *image_panel_window=(Fl_Double_Window *)0; @@ -56,14 +77,14 @@ fld::widget::Formula_Input *image_panel_imagew=(fld::widget::Formula_Input *)0; static void cb_image_panel_imagew(fld::widget::Formula_Input* o, void* v) { if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_image_w_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_image_w_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { @@ -78,7 +99,7 @@ static void cb_image_panel_imagew(fld::widget::Formula_Input* o, void* v) { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); } } @@ -86,14 +107,14 @@ fld::widget::Formula_Input *image_panel_imageh=(fld::widget::Formula_Input *)0; static void cb_image_panel_imageh(fld::widget::Formula_Input* o, void* v) { if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_image_h_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_image_h_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { @@ -108,7 +129,7 @@ static void cb_image_panel_imageh(fld::widget::Formula_Input* o, void* v) { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); } } @@ -121,6 +142,42 @@ static void cb_Reset(Fl_Button*, void* v) { } } +static void cb_convert(Fl_Check_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(!current_widget->compress_image_); + } else { + o->deactivate(); + } + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->compress_image_ = !o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_bind(Fl_Check_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(current_widget->bind_image_); + } else { + o->deactivate(); + } + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->bind_image_ = o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *image_panel_deimagegroup=(Fl_Group *)0; Fl_Box *image_panel_dedata=(Fl_Box *)0; @@ -148,14 +205,14 @@ fld::widget::Formula_Input *image_panel_deimagew=(fld::widget::Formula_Input *)0 static void cb_image_panel_deimagew(fld::widget::Formula_Input* o, void* v) { if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_deimage_w_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_deimage_w_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { @@ -170,7 +227,7 @@ static void cb_image_panel_deimagew(fld::widget::Formula_Input* o, void* v) { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); } } @@ -178,14 +235,14 @@ fld::widget::Formula_Input *image_panel_deimageh=(fld::widget::Formula_Input *)0 static void cb_image_panel_deimageh(fld::widget::Formula_Input* o, void* v) { if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_deimage_h_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_deimage_h_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { @@ -200,7 +257,7 @@ static void cb_image_panel_deimageh(fld::widget::Formula_Input* o, void* v) { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); } } @@ -213,6 +270,42 @@ static void cb_Reset1(Fl_Button*, void* v) { } } +static void cb_convert1(Fl_Check_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(!current_widget->compress_deimage_); + } else { + o->deactivate(); + } + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->compress_deimage_ = !o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_bind1(Fl_Check_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(current_widget->bind_deimage_); + } else { + o->deactivate(); + } + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->bind_deimage_ = o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Button *image_panel_close=(Fl_Button *)0; static void cb_image_panel_close(Fl_Button*, void* v) { @@ -291,13 +384,13 @@ Fl_Double_Window* make_image_panel() { "ixel data"); o->down_box(FL_DOWN_BOX); o->labelsize(11); - o->callback((Fl_Callback*)compress_image_cb); + o->callback((Fl_Callback*)cb_convert); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(75, 120, 170, 20, "bind to widget"); o->tooltip("bind the image to the widget, so it will be deleted automatically"); o->down_box(FL_DOWN_BOX); o->labelsize(11); - o->callback((Fl_Callback*)bind_image_cb); + o->callback((Fl_Callback*)cb_bind); o->window()->hotspot(o); } // Fl_Check_Button* o image_panel_imagegroup->end(); @@ -367,13 +460,13 @@ Fl_Double_Window* make_image_panel() { "ixel data"); o->down_box(FL_DOWN_BOX); o->labelsize(11); - o->callback((Fl_Callback*)compress_deimage_cb); + o->callback((Fl_Callback*)cb_convert1); } // Fl_Check_Button* o { Fl_Check_Button* o = new Fl_Check_Button(75, 260, 170, 20, "bind to widget"); o->tooltip("bind the image to the widget, so it will be deleted automatically"); o->down_box(FL_DOWN_BOX); o->labelsize(11); - o->callback((Fl_Callback*)bind_deimage_cb); + o->callback((Fl_Callback*)cb_bind1); } // Fl_Check_Button* o image_panel_deimagegroup->end(); } // Fl_Group* image_panel_deimagegroup @@ -405,7 +498,29 @@ void run_image_panel() { Fl_Shared_Image *img = (Fl_Shared_Image*)image_panel_data->user_data(); if (img) { img->release(); - image_panel_data->user_data(NULL); + image_panel_data->user_data(nullptr); + } +} + +void flex_margin_cb(Fl_Value_Input* i, void* v, void (*load_margin)(Fl_Flex*,Fl_Value_Input*), int (*update_margin)(Fl_Flex*,int)) { + if (v == LOAD) { + if (current_widget->is_a(Type::Flex)) { + load_margin((Fl_Flex*)current_widget->o, i); + } + } else { + int mod = 0; + int new_value = (int)i->value(); + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_a(Type::Flex)) { + Flex_Node* q = (Flex_Node*)o; + Fl_Flex* w = (Fl_Flex*)q->o; + if (update_margin(w, new_value)) { + w->layout(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); } } @@ -421,6 +536,42 @@ Fl_Input *wp_gui_label=(Fl_Input *)0; Fl_Input *widget_image_input=(Fl_Input *)0; +static void cb_widget_image_input(Fl_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(((Widget_Node*)current_widget)->image_name()); + } else o->deactivate(); + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->image_name(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Browse(Fl_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) + o->activate(); + else + o->deactivate(); + } else { + int mod = 0; + Image_Asset *image_asset = ui_find_image(widget_image_input->value()); + if (image_asset) { + widget_image_input->value(image_asset->filename()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->image_name(image_asset->filename()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } + } +} + static void cb_(Fl_Button*, void* v) { if (v != LOAD) { run_image_panel(); @@ -429,6 +580,42 @@ static void cb_(Fl_Button*, void* v) { Fl_Input *widget_deimage_input=(Fl_Input *)0; +static void cb_widget_deimage_input(Fl_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(((Widget_Node*)current_widget)->inactive_name()); + } else o->deactivate(); + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->inactive_name(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Browse1(Fl_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) + o->activate(); + else + o->deactivate(); + } else { + int mod = 0; + Image_Asset *image_asset = ui_find_image(widget_deimage_input->value()); + if (image_asset) { + widget_deimage_input->value(image_asset->filename()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->inactive_name(image_asset->filename()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } + } +} + Fl_Group *wp_gui_alignment=(Fl_Group *)0; Fl_Menu_Item menu_[] = { @@ -462,12 +649,151 @@ Fl_Menu_Item menu_1[] = { fld::widget::Formula_Input *widget_x_input=(fld::widget::Formula_Input *)0; +static void cb_widget_x_input(fld::widget::Formula_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->x()); + o->activate(); + } else o->deactivate(); + } else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(v, w->y(), w->w(), w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); // change the displayed value to the result of the last + // calculation. Keep the formula if it was not used. + } + } +} + fld::widget::Formula_Input *widget_y_input=(fld::widget::Formula_Input *)0; +static void cb_widget_y_input(fld::widget::Formula_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->y()); + o->activate(); + } else o->deactivate(); + } else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), v, w->w(), w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } + } +} + fld::widget::Formula_Input *widget_w_input=(fld::widget::Formula_Input *)0; +static void cb_widget_w_input(fld::widget::Formula_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->w()); + o->activate(); + } else o->deactivate(); + } else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), w->y(), v, w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } + } +} + fld::widget::Formula_Input *widget_h_input=(fld::widget::Formula_Input *)0; +static void cb_widget_h_input(fld::widget::Formula_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->h()); + o->activate(); + } else o->deactivate(); + } else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), w->y(), w->w(), v); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } + } +} + +static void cb_Children(Fl_Choice* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Widget_Class)) { + o->show(); + o->value(((Widget_Class_Node *)current_widget)->wc_relative); + } else { + o->hide(); + } + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Widget_Class)) { + Widget_Class_Node *t = (Widget_Class_Node *)q; + t->wc_relative = o->value(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Menu_Item menu_Children[] = { {"Fixed", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"Reposition", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, @@ -477,48 +803,1239 @@ Fl_Menu_Item menu_Children[] = { Fl_Group *wp_gui_flexp=(Fl_Group *)0; +static void cb_wp_gui_flexp(Fl_Group* o, void* v) { + if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } + } +} + Fl_Value_Input *widget_flex_size=(Fl_Value_Input *)0; +static void cb_widget_flex_size(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->value(Flex_Node::size(current_widget)); + } + } else { + int mod = 0; + int new_size = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (Flex_Node::parent_is_flex(q)) { + Fl_Widget* w = (Fl_Widget*)q->o; + Fl_Flex* f = (Fl_Flex*)((Flex_Node*)q->parent)->o; + int was_fixed = f->fixed(w); + if (new_size==0) { + if (was_fixed) { + f->fixed(w, 0); + f->layout(); + widget_flex_fixed->value(0); + mod = 1; + } + } else { + int old_size = Flex_Node::size(q); + if (old_size!=new_size || !was_fixed) { + f->fixed(w, new_size); + f->layout(); + widget_flex_fixed->value(1); + mod = 1; + } + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Check_Button *widget_flex_fixed=(Fl_Check_Button *)0; +static void cb_widget_flex_fixed(Fl_Check_Button* o, void* v) { + if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->value(Flex_Node::is_fixed(current_widget)); + } + } else { + int mod = 0; + int new_fixed = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (Flex_Node::parent_is_flex(q)) { + Fl_Widget* w = q->o; + Fl_Flex* f = (Fl_Flex*)((Flex_Node*)q->parent)->o; + int was_fixed = f->fixed(w); + if (new_fixed==0) { + if (was_fixed) { + f->fixed(w, 0); + f->layout(); + mod = 1; + } + } else { + if (!was_fixed) { + f->fixed(w, Flex_Node::size(q)); + f->layout(); + mod = 1; + } + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_gui_values=(Fl_Group *)0; +static void cb_wp_gui_values(Fl_Group* o, void* v) { + if (v == LOAD) { + if ( current_widget->is_a(Type::Flex) + || current_widget->is_a(Type::Grid) + || current_widget->is_a(Type::Window)) + { + o->hide(); + } else { + o->show(); + propagate_load(o, v); + } + } +} + +static void cb_Size(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Slider)) {o->deactivate(); return;} + o->activate(); + o->value(((Fl_Slider*)(current_widget->o))->slider_size()); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Slider)) { + ((Fl_Slider*)(q->o))->slider_size(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Minimum(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->minimum()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->minimum()); + } else { + o->deactivate(); + return; + } + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->minimum(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->minimum(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Maximum(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->maximum()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->maximum()); + } else { + o->deactivate(); + return; + } + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->maximum(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->maximum(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Step(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->step()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->step()); + } else { + o->deactivate(); + return; + } + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->step(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->step(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Value(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->value()); + } else if (current_widget->is_button()) { + o->activate(); + o->value(((Fl_Button*)(current_widget->o))->value()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->value()); + } else + o->deactivate(); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->value(n); + mod = 1; + } else if (q->is_button()) { + ((Fl_Button*)(q->o))->value(n != 0); + if (q->is_a(Type::Menu_Item)) q->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->value(n); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_gui_margins=(Fl_Group *)0; +static void cb_wp_gui_margins(Fl_Group* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Flex)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } + } +} + +static void cb_Left(Fl_Value_Input* o, void* v) { + flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(&v, nullptr, nullptr, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=l) { + w->margin(new_value, t, r, b); + return 1; + } else { + return 0; + } + } + ); +} + +static void cb_Top(Fl_Value_Input* o, void* v) { + flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, &v, nullptr, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=t) { + w->margin(l, new_value, r, b); + return 1; + } else { + return 0; + } + } + ); +} + +static void cb_Right(Fl_Value_Input* o, void* v) { + flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, nullptr, &v, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=r) { + w->margin(l, t, new_value, b); + return 1; + } else { + return 0; + } + } + ); +} + +static void cb_Bottom(Fl_Value_Input* o, void* v) { + flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, nullptr, nullptr, &v); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=b) { + w->margin(l, t, r, new_value); + return 1; + } else { + return 0; + } + } + ); +} + +static void cb_Gap(Fl_Value_Input* o, void* v) { + flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* o) -> void + { + int v = w->gap(); + o->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int g = w->gap(); + if (new_value!=g) { + w->gap(new_value); + return 1; + } else { + return 0; + } + } + ); +} + Fl_Group *wp_gui_sizerange=(Fl_Group *)0; +static void cb_wp_gui_sizerange(Fl_Group* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Window)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } + } +} + +static void cb_Minimum1(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_min_w); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_min_w = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_1(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_min_h); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_min_h = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_set(Fl_Button* o, void* v) { + if (v == LOAD) { + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + Window_Node *win = (Window_Node*)q; + win->sr_min_w = win->o->w(); + win->sr_min_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Maximum1(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_max_w); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_max_w = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_2(Fl_Value_Input* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_max_h); + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_max_h = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_set1(Fl_Button* o, void* v) { + if (v == LOAD) { + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + Window_Node *win = (Window_Node*)q; + win->sr_max_w = win->o->w(); + win->sr_max_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Shortcut_Button *wp_gui_shortcut=(Fl_Shortcut_Button *)0; +static void cb_wp_gui_shortcut(Fl_Shortcut_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_button()) + o->value( ((Fl_Button*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Input)) + o->value( ((Fl_Input_*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Value_Input)) + o->value( ((Fl_Value_Input*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Text_Display)) + o->value( ((Fl_Text_Display*)(current_widget->o))->shortcut() ); + else { + o->hide(); + o->parent()->hide(); + return; + } + //i->default_value( i->value() ); // enable the "undo" capability of the shortcut button + o->show(); + o->parent()->show(); + o->redraw(); + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) + if (q->is_button()) { + Fl_Button* b = (Fl_Button*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + if (q->is_a(Type::Menu_Item)) q->redraw(); + } else if (q->is_a(Type::Input)) { + Fl_Input_* b = (Fl_Input_*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } else if (q->is_a(Type::Value_Input)) { + Fl_Value_Input* b = (Fl_Value_Input*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } else if (q->is_a(Type::Text_Display)) { + Fl_Text_Display* b = (Fl_Text_Display*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_gui_xclass=(Fl_Group *)0; +static void cb_3(Fl_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Window)) { + o->show(); + o->parent()->show(); + o->value(((Window_Node *)current_widget)->xclass); + } else { + o->hide(); + o->parent()->hide(); // hides the "X Class:" label as well + } + } else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + mod = 1; + Window_Node *wt = (Window_Node *)q; + storestring(o->value(), wt->xclass); + ((Fl_Window*)(wt->o))->xclass(wt->xclass); + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Border(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Fl_Window*)(current_widget->o))->border()); + } else { + Fluid.proj.undo.checkpoint(); + ((Fl_Window*)(current_widget->o))->border(o->value()); + Fluid.proj.set_modflag(1); + } +} + +static void cb_Modal(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Window_Node *)current_widget)->modal); + } else { + Fluid.proj.undo.checkpoint(); + ((Window_Node *)current_widget)->modal = o->value(); + Fluid.proj.set_modflag(1); + } +} + +static void cb_Nonmodal(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Window_Node *)current_widget)->non_modal); + } else { + Fluid.proj.undo.checkpoint(); + ((Window_Node *)current_widget)->non_modal = o->value(); + Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_gui_attributes=(Fl_Group *)0; +static void cb_Visible(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + o->value(current_widget->o->visible()); + if (current_widget->is_a(Type::Window)) o->deactivate(); + else o->activate(); + } else { + int mod = 0; + int n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + n ? q->o->show() : q->o->hide(); + q->redraw(); + if (n && q->parent && q->parent->type_name()) { + if (q->parent->is_a(Type::Tabs)) { + ((Fl_Tabs *)q->o->parent())->value(q->o); + } else if (q->parent->is_a(Type::Wizard)) { + ((Fl_Wizard *)q->o->parent())->value(q->o); + } + } + } + if (mod) { + Fluid.proj.set_modflag(1); + redraw_browser(); + } + } +} + +static void cb_Active(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + o->value(current_widget->o->active()); + if (current_widget->is_a(Type::Window)) o->deactivate(); + else o->activate(); + } else { + int mod = 0; + int n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + n ? q->o->activate() : q->o->deactivate(); + q->redraw(); + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Resizable(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} + if (numselected > 1) {o->deactivate(); return;} + o->activate(); + o->value(current_widget->resizable()); + } else { + Fluid.proj.undo.checkpoint(); + current_widget->resizable(o->value()); + Fluid.proj.set_modflag(1); + } +} + +static void cb_Hotspot(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + if (numselected > 1) {o->deactivate(); return;} + if (current_widget->is_a(Type::Menu_Item)) o->label("divider"); + else o->label("hotspot"); + o->activate(); + o->value(current_widget->hotspot()); + } else { + Fluid.proj.undo.checkpoint(); + current_widget->hotspot(o->value()); + if (current_widget->is_a(Type::Menu_Item)) { + current_widget->redraw(); + return; + } + if (o->value()) { + Node *p = current_widget->parent; + if (!p || !p->is_widget()) return; + while (!p->is_a(Type::Window)) p = p->parent; + for (Node *q = p->next; q && q->level > p->level; q = q->next) { + if (q->is_widget() && q != current_widget) + ((Widget_Node*)q)->hotspot(0); + } + } + Fluid.proj.set_modflag(1); + } +} + Fl_Input *wp_gui_tooltip=(Fl_Input *)0; +static void cb_wp_gui_tooltip(Fl_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_widget()) { + o->activate(); + o->value(((Widget_Node*)current_widget)->tooltip()); + } else { + o->deactivate(); + } + } else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->tooltip(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_style_tab=(Fl_Group *)0; Fl_Group *wp_style_label=(Fl_Group *)0; +static void cb_4(Fl_Choice* o, void* v) { + if (v == LOAD) { + int n = current_widget->o->labelfont(); + if (n > 15) n = 0; + o->value(n); + } else { + int mod = 0; + int n = o->value(); + if (n <= 0) n = Fluid.proj.layout->labelfont; + if (n <= 0) n = FL_HELVETICA; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->labelfont(n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_5(Fl_Value_Input* o, void* v) { + int n; + if (v == LOAD) { + n = current_widget->o->labelsize(); + } else { + int mod = 0; + n = int(o->value()); + if (n <= 0) n = Fluid.proj.layout->labelsize; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->labelsize(n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } + o->value(n); +} + Fl_Button *w_labelcolor=(Fl_Button *)0; +static void cb_w_labelcolor(Fl_Button* o, void* v) { + Fl_Color c = current_widget->o->labelcolor(); + if (v != LOAD) { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + labelcolor_common(c); + } + o->color(c); + o->labelcolor(fl_contrast(FL_BLACK,c)); + o->redraw(); +} + +static void cb_6(Fl_Menu_Button* o, void* v) { + Fl_Color c = current_widget->o->labelcolor(); + if (v != LOAD) { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + labelcolor_common(c); + w_labelcolor->color(c); + w_labelcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_labelcolor->redraw(); + } +} + Fl_Group *wp_style_box=(Fl_Group *)0; +static void cb_7(Fl_Choice* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); + int n = current_widget->o->box(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < 72 /*int(sizeof(boxmenu)/sizeof(*boxmenu))*/; j++) + if (boxmenu[j].argument() == n) {o->value(j); break;} + } else { + int mod = 0; + int m = o->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->box((Fl_Boxtype)n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Button *w_color=(Fl_Button *)0; +static void cb_w_color(Fl_Button* o, void* v) { + Fl_Color c = current_widget->o->color(); + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + } else { + o->activate(); + } + } else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + color_common(c); + } + o->color(c); + o->labelcolor(fl_contrast(FL_BLACK,c)); + o->redraw(); +} + +static void cb_8(Fl_Menu_Button* o, void* v) { + Fl_Color c = current_widget->o->color(); + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); + } else { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + color_common(c); + w_color->color(c); + w_color->labelcolor(fl_contrast(FL_BLACK,c)); + w_color->redraw(); + } +} + Fl_Group *wp_style_downbox=(Fl_Group *)0; +static void cb_9(Fl_Choice* o, void* v) { + if (v == LOAD) { + int n; + if (current_widget->is_a(Type::Button)) + n = ((Fl_Button*)(current_widget->o))->down_box(); + else if (current_widget->is_a(Type::Input_Choice)) + n = ((Fl_Input_Choice*)(current_widget->o))->down_box(); + else if (current_widget->is_a(Type::Menu_Manager_)) + n = ((Fl_Menu_*)(current_widget->o))->down_box(); + else { + o->deactivate(); return; + } + o->activate(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < 72 /*int(sizeof(boxmenu)/sizeof(*boxmenu))*/; j++) + if (boxmenu[j].argument() == n) {o->value(j); break;} + } else { + int mod = 0; + int m = o->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Button)) { + ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); + if (((Fl_Button*)(q->o))->value()) q->redraw(); + } else if (q->is_a(Type::Input_Choice)) { + ((Fl_Input_Choice*)(q->o))->down_box((Fl_Boxtype)n); + } else if (q->is_a(Type::Menu_Manager_)) { + ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); + } + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Button *w_selectcolor=(Fl_Button *)0; +static void cb_w_selectcolor(Fl_Button* o, void* v) { + Fl_Color c = current_widget->o->selection_color(); + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + return; + } else { + o->activate(); + } + } else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + color2_common(c); + } + o->color(c); + o->labelcolor(fl_contrast(FL_BLACK,c)); + o->redraw(); +} + +static void cb_a(Fl_Menu_Button* o, void* v) { + Fl_Color c = current_widget->o->selection_color(); + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + return; + } else { + o->activate(); + } + } else { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + color2_common(c); + w_selectcolor->color(c); + w_selectcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_selectcolor->redraw(); + } +} + Fl_Group *wp_style_text=(Fl_Group *)0; +static void cb_b(Fl_Choice* o, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {o->deactivate(); return;} + o->activate(); + if (n > 15) n = FL_HELVETICA; + o->value(n); + } else { + int mod = 0; + n = (Fl_Font)o->value(); + if (n <= 0) n = Fluid.proj.layout->textfont; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->textstuff(1,n,s,c); + q->o->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_c(Fl_Value_Input* o, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {o->deactivate(); return;} + o->activate(); + } else { + int mod = 0; + s = int(o->value()); + if (s <= 0) s = Fluid.proj.layout->textsize; + if (s <= 0) s = Fluid.proj.layout->labelsize; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->textstuff(2,n,s,c); + q->o->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } + o->value(s); +} + Fl_Button *w_textcolor=(Fl_Button *)0; +static void cb_w_textcolor(Fl_Button* o, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) { + o->deactivate(); + return; + } + o->activate(); + } else { + c = o->color(); + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + textcolor_common(c); + } + o->color(c); + o->labelcolor(fl_contrast(FL_BLACK,c)); + o->redraw(); +} + +static void cb_d(Fl_Menu_Button* o, void* v) { + Fl_Font n; int s; Fl_Color c; + if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) { + o->deactivate(); + return; + } + o->activate(); + } else { + c = o->color(); + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + textcolor_common(c); + w_textcolor->color(c); + w_textcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_textcolor->redraw(); + } +} + +static void cb_Horizontal(Fl_Value_Input* o, void* v) { + int s; + if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->horizontal_label_margin()); + } + } else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->horizontal_label_margin() != s) { + q->o->horizontal_label_margin(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Vertical(Fl_Value_Input* o, void* v) { + int s; + if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->vertical_label_margin()); + } + } else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->vertical_label_margin() != s) { + q->o->vertical_label_margin(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Image(Fl_Value_Input* o, void* v) { + int s; + if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->label_image_spacing()); + } + } else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->label_image_spacing() != s) { + q->o->label_image_spacing(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_Compact(Fl_Light_Button* o, void* v) { + if (v == LOAD) { + uchar n; + if (current_widget->is_a(Type::Button) && !current_widget->is_a(Type::Menu_Item)) { + n = ((Fl_Button*)(current_widget->o))->compact(); + o->value(n); + o->show(); + } else { + o->hide(); + } + } else { + int mod = 0; + uchar n = (uchar)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Button) && !q->is_a(Type::Menu_Item)) { + uchar v = ((Fl_Button*)(q->o))->compact(); + if (n != v) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + ((Fl_Button*)(q->o))->compact(n); + q->redraw(); + } + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_cpp_tab=(Fl_Group *)0; Fl_Group *wp_cpp_class=(Fl_Group *)0; +static void cb_e(Fl_Input* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + } else { + o->activate(); + o->value(current_widget->subclass()); + } + } else { + int mod = 0; + const char *c = o->value(); + for (Widget_Node *t: Fluid.proj.tree.all_selected_widgets()) { + t->subclass(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_f(Fl_Choice* o, void* v) { + static Fl_Menu_Item empty_type_menu[] = { + {"Normal",0,nullptr,(void*)nullptr}, + {nullptr}}; + + if (v == LOAD) { + Fl_Menu_Item* m = current_widget->subtypes(); + if (!m) { + o->menu(empty_type_menu); + o->value(0); + o->deactivate(); + } else { + o->menu(m); + int j; + for (j = 0;; j++) { + if (!m[j].text) {j = 0; break;} + if (current_widget->is_a(Type::Spinner)) { + if (m[j].argument() == ((Fl_Spinner*)current_widget->o)->type()) break; + } else { + if (m[j].argument() == current_widget->o->type()) break; + } + } + o->value(j); + o->activate(); + } + o->redraw(); + } else { + int mod = 0; + int n = int(o->mvalue()->argument()); + Fl_Menu_Item* m = current_widget->subtypes(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->subtypes()==m) { + if (q->is_a(Type::Spinner)) + ((Fl_Spinner*)q->o)->type(n); + else if (q->is_a(Type::Flex)) + ((Flex_Node*)q)->change_subtype_to(n); + else + q->o->type(n); + q->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Group *wp_cpp_name=(Fl_Group *)0; +static void cb_10(Fl_Input* o, void* v) { + if (v == LOAD) { + static char buf[1024]; + if (numselected != 1) { + snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected); + o->hide(); + } else { + o->value(current_widget->name()); + o->show(); + snprintf(buf, sizeof(buf), "%s Properties", current_widget->title()); + } + + the_panel->label(buf); + } else { + if (numselected == 1) { + current_widget->name(o->value()); + // I don't update window title, as it probably is being closed + // and wm2 (a window manager) barfs if you retitle and then + // hide a window: + // ((Fl_Window*)(o->parent()->parent()->parent()))->label(current_widget->title()); + } + } +} + +static void cb_11(Fl_Choice* o, void* v) { + if (v == LOAD) { + o->value(current_widget->public_); + if (current_widget->is_in_class()) o->show(); else o->hide(); + } else { + int mod = 0; + for (Widget_Node *w: Fluid.proj.tree.all_selected_widgets()) { + if (w->is_in_class()) { + w->public_ = o->value(); + } else { + // if this is not in a class, it can be only private or public + w->public_ = (o->value()>0); + } + mod = 1; + } + if (mod) { + Fluid.proj.set_modflag(1); + redraw_browser(); + } + } +} + Fl_Menu_Item menu_2[] = { {"private", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, {"public", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, @@ -532,19 +2049,155 @@ Fl_Menu_Item menu_3[] = { {0,0,0,0,0,0,0,0,0} }; +static void cb_v_input(Fl_Input* o, void* v) { + int n = fl_int(o->user_data()); + if (v == LOAD) { + o->value(current_widget->extra_code(n)); + } else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c&&c[0]=='#' ? c+1 : c); + if (d) {fl_message("Error in %s: %s",o->label(),d); haderror = 1; return;} + for (Widget_Node *w: Fluid.proj.tree.all_selected_widgets()) { + w->extra_code(n,c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_v_input1(Fl_Input* o, void* v) { + cb_v_input(o, v); +} + +static void cb_v_input2(Fl_Input* o, void* v) { + cb_v_input(o, v); +} + Fl_Input *v_input[4]={(Fl_Input *)0}; -static void cb_1(Fl_Tile*, void* v) { +static void cb_v_input3(Fl_Input* o, void* v) { + cb_v_input(o, v); +} + +static void cb_12(Fl_Tile*, void* v) { wComment->do_callback(wComment, v); wCallback->do_callback(wCallback, v); } Fl_Text_Editor *wComment=(Fl_Text_Editor *)0; +static void cb_wComment(Fl_Text_Editor* o, void* v) { + if (v == LOAD) { + const char *cmttext = current_widget->comment(); + o->buffer()->text( cmttext ? cmttext : "" ); + } else { + int mod = 0; + char *c = o->buffer()->text(); + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->comment(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + free(c); + } +} + fld::widget::Code_Editor *wCallback=(fld::widget::Code_Editor *)0; +static void cb_wCallback(fld::widget::Code_Editor* o, void* v) { + if (v == LOAD) { + const char *cbtext = current_widget->callback(); + o->buffer()->text( cbtext ? cbtext : "" ); + } else { + int mod = 0; + char *c = o->buffer()->text(); + const char *d = c_check(c); + if (d) { + fl_message("Error in callback: %s",d); + if (o->window()) o->window()->make_current(); + haderror = 1; + } + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->callback(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + free(c); + } +} + Fl_Group *wp_cpp_callback=(Fl_Group *)0; +static void cb_13(Fl_Input* o, void* v) { + if (v == LOAD) { + o->value(current_widget->user_data()); + } else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c); + if (d) {fl_message("Error in user_data: %s",d); haderror = 1; return;} + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->user_data(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_When(Fl_Menu_Button* o, void* v) { + if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); + int n = current_widget->o->when(); + set_whenmenu(n); + w_when_box->copy_label(when_symbol_name(n)); + } else { + int mod = 0; + int n = 0; + if (o->mvalue() && ((o->mvalue()->flags & FL_MENU_TOGGLE) == 0) ) { + n = (int)o->mvalue()->argument(); + set_whenmenu(n); + } else { + if (whenmenu[0].value()) n |= FL_WHEN_CHANGED; + if (whenmenu[1].value()) n |= FL_WHEN_NOT_CHANGED; + if (whenmenu[2].value()) n |= FL_WHEN_RELEASE; + if (whenmenu[3].value()) n |= FL_WHEN_ENTER_KEY; + if (whenmenu[4].value()) n |= FL_WHEN_CLOSED; + } + w_when_box->copy_label(when_symbol_name(n)); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->when(n); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + +static void cb_14(Fl_Input_Choice* o, void* v) { + static const char *dflt = "void*"; + if (v == LOAD) { + const char *c = current_widget->user_data_type(); + if (!c) c = dflt; + o->value(c); + } else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c); + if (!*c) o->value(dflt); + else if (!strcmp(c,dflt)) c = nullptr; + if (!d) { + if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) + d = "must be pointer or long"; + } + if (d) {fl_message("Error in type: %s",d); haderror = 1; return;} + for (Node *q: Fluid.proj.tree.all_selected_nodes()) { + q->user_data_type(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +} + Fl_Menu_Item menu_4[] = { {"void*", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, {"long", 0, 0, 0, 0, (uchar)FL_NORMAL_LABEL, 4, 11, 0}, @@ -553,441 +2206,16 @@ Fl_Menu_Item menu_4[] = { Fl_Box *w_when_box=(Fl_Box *)0; -Fl_Group *widget_tab_grid_child=(Fl_Group *)0; +Grid_Tab *widget_tab_grid=(Grid_Tab *)0; -fld::widget::Formula_Input *widget_grid_row_input=(fld::widget::Formula_Input *)0; - -fld::widget::Formula_Input *widget_grid_col_input=(fld::widget::Formula_Input *)0; - -Fl_Box *widget_grid_transient=(Fl_Box *)0; - -static void cb_widget_grid_transient(Fl_Box* o, void* v) { - if (v==LOAD) { - Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; - Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); - // Fl_Grid::Cell *cell = g->cell(child); - // Fl_Grid::Cell *tcell = g->transient_cell(child); - widget_grid_transient->hide(); - widget_grid_unlinked->hide(); - if (g->transient_cell(child)) { - widget_grid_transient->show(); - } else if (!g->cell(child)) { - widget_grid_unlinked->show(); - } - } +static void cb_widget_tab_grid(Grid_Tab* o, void*) { + o->callback((Fl_Callback*)propagate_load); } -Fl_Box *widget_grid_unlinked=(Fl_Box *)0; +Grid_Child_Tab *widget_tab_grid_child=(Grid_Child_Tab *)0; -Fl_Group *wp_gridc_align=(Fl_Group *)0; - -Fl_Menu_Item menu_Horizontal[] = { - {"GRID_LEFT", 0, 0, (void*)((fl_intptr_t)FL_GRID_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_RIGHT", 0, 0, (void*)((fl_intptr_t)FL_GRID_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_HORIZONTAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -Fl_Menu_Item menu_Vertical[] = { - {"GRID_TOP", 0, 0, (void*)((fl_intptr_t)FL_GRID_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_BOTTOM", 0, 0, (void*)((fl_intptr_t)FL_GRID_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_VERTICAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, - {0,0,0,0,0,0,0,0,0} -}; - -Fl_Group *wp_gridc_size=(Fl_Group *)0; - -fld::widget::Formula_Input *widget_grid_rowspan_input=(fld::widget::Formula_Input *)0; - -fld::widget::Formula_Input *widget_grid_colspan_input=(fld::widget::Formula_Input *)0; - -Fl_Group *widget_tab_grid=(Fl_Group *)0; - -fld::widget::Formula_Input *widget_grid_rows=(fld::widget::Formula_Input *)0; - -static void cb_widget_grid_rows(fld::widget::Formula_Input* o, void* v) { - // grid_rows_cb - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - if (v == LOAD) { - o->value(grid->rows()); - } else { - int m = o->value(), old_m = grid->rows(); - if (m < 1) { - m = 1; - o->value(m); - } - if (m < old_m) { - // TODO: verify that this will not unlink existings cells - // Offer a dialog with "delete children", "unlink cells", "cancel" - } - if (m != old_m) { - undo_checkpoint(); - grid->layout(m, grid->cols()); - grid->need_layout(true); - set_modflag(1); - widget_tab_grid->do_callback(widget_tab_grid, LOAD); - } - } -} - -static void cb_2(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_rows->value( widget_grid_rows->value()-1 ); - widget_grid_rows->do_callback(); - } -} - -static void cb_3(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_rows->value( widget_grid_rows->value()+1 ); - widget_grid_rows->do_callback(); - } -} - -fld::widget::Formula_Input *widget_grid_cols=(fld::widget::Formula_Input *)0; - -static void cb_widget_grid_cols(fld::widget::Formula_Input* o, void* v) { - // grid_rows_cb - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - if (v == LOAD) { - o->value(grid->cols()); - } else { - int m = o->value(), old_m = grid->cols(); - if (m < 1) { - m = 1; - o->value(m); - } - if (m < old_m) { - // TODO: verify that this will not unlink existings cells - // Offer a dialog with "delete children", "unlink cells", "cancel" - } - if (m != old_m) { - undo_checkpoint(); - grid->layout(grid->rows(), m); - grid->need_layout(true); - set_modflag(1); - widget_tab_grid->do_callback(widget_tab_grid, LOAD); - } - } -} - -static void cb_4(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_cols->value( widget_grid_cols->value()-1 ); - widget_grid_cols->do_callback(); - } -} - -static void cb_5(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_cols->value( widget_grid_cols->value()+1 ); - widget_grid_cols->do_callback(); - } -} - -Fl_Group *wp_grid_margin=(Fl_Group *)0; - -static void cb_Left(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int m = 0; - if (v == LOAD) { - grid->margin(&m, NULL, NULL, NULL); - o->value(m); - } else { - int m = (int)o->value(), old_m; - grid->margin(&old_m, NULL, NULL, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(m, -1, -1, -1); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Top(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int m = 0; - if (v == LOAD) { - grid->margin(NULL, &m, NULL, NULL); - o->value(m); - } else { - int m = (int)o->value(), old_m; - grid->margin(NULL, &old_m, NULL, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, m, -1, -1); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Right(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int m = 0; - if (v == LOAD) { - grid->margin(NULL, NULL, &m, NULL); - o->value(m); - } else { - int m = (int)o->value(), old_m; - grid->margin(NULL, NULL, &old_m, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, -1, m, -1); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Bottom(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int m = 0; - if (v == LOAD) { - grid->margin(NULL, NULL, NULL, &m); - o->value(m); - } else { - int m = (int)o->value(), old_m; - grid->margin(NULL, NULL, NULL, &old_m); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, -1, -1, m); - grid->need_layout(true); - set_modflag(1); - } - } -} - -Fl_Group *wp_grid_gaps=(Fl_Group *)0; - -static void cb_Row(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - if (v == LOAD) { - int m = 0; - grid->gap(&m, NULL); - o->value(m); - } else { - int m = (int)o->value(), old_m, m2; - grid->gap(&old_m, &m2); - if (m != old_m) { - undo_checkpoint(); - grid->gap(m, m2); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Col(Fl_Value_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - if (v == LOAD) { - int m = 0; - grid->gap(NULL, &m); - o->value(m); - } else { - int m = (int)o->value(), old_m, m2; - grid->gap(&m2, &old_m); - if (m != old_m) { - undo_checkpoint(); - grid->gap(m2, m); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Row1(Fl_Group* o, void* v) { - if (v == LOAD) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (grid) - o->activate(); - else - o->deactivate(); - propagate_load(o, v); - } -} - -fld::widget::Formula_Input *widget_grid_curr_row=(fld::widget::Formula_Input *)0; - -static void cb_widget_grid_curr_row(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int r = o->value(), old_r = r; - if (r < 0) r = 0; - if (r >= grid->rows()) r = grid->rows()-1; - if (r != old_r) o->value(r); - if (v == LOAD) { - // will automatically propagate - } else { - widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); - } -} - -static void cb_6(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); - widget_grid_curr_row->do_callback(); - } -} - -static void cb_7(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); - widget_grid_curr_row->do_callback(); - } -} - -Fl_Group *widget_grid_curr_row_attributes=(Fl_Group *)0; - -static void cb_Height(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int r = widget_grid_curr_row->value(); - if (v == LOAD) { - o->value(grid->row_height(r)); - } else { - int h = o->value(), old_h = grid->row_height(r); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->row_height(r, h); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Weight(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int r = widget_grid_curr_row->value(); - if (v == LOAD) { - o->value(grid->row_weight(r)); - } else { - int h = o->value(), old_h = grid->row_weight(r); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->row_weight(r, h); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Gap(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int r = widget_grid_curr_row->value(); - if (v == LOAD) { - o->value(grid->row_gap(r)); - } else { - int h = o->value(), old_h = grid->row_gap(r); - if (h < -1) h = -1; - if (h != old_h) { - undo_checkpoint(); - grid->row_gap(r, h); - grid->need_layout(true); - set_modflag(1); - } - } -} - -fld::widget::Formula_Input *widget_grid_curr_col=(fld::widget::Formula_Input *)0; - -static void cb_widget_grid_curr_col(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int c = o->value(), old_c = c; - if (c < 0) c = 0; - if (c >= grid->cols()) c = grid->cols()-1; - if (c != old_c) o->value(c); - if (v == LOAD) { - // will automatically propagate - } else { - widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); - } -} - -static void cb_8(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); - widget_grid_curr_col->do_callback(); - } -} - -static void cb_9(Fl_Button*, void* v) { - if (v != LOAD) { - widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); - widget_grid_curr_col->do_callback(); - } -} - -Fl_Group *widget_grid_curr_col_attributes=(Fl_Group *)0; - -static void cb_Width(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int c = widget_grid_curr_col->value(); - if (v == LOAD) { - o->value(grid->col_width(c)); - } else { - int h = o->value(), old_h = grid->col_width(c); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->col_width(c, h); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Weight1(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int c = widget_grid_curr_col->value(); - if (v == LOAD) { - o->value(grid->col_weight(c)); - } else { - int h = o->value(), old_h = grid->col_weight(c); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->col_weight(c, h); - grid->need_layout(true); - set_modflag(1); - } - } -} - -static void cb_Gap1(fld::widget::Formula_Input* o, void* v) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (!grid) return; - int c = widget_grid_curr_col->value(); - if (v == LOAD) { - o->value(grid->col_gap(c)); - } else { - int h = o->value(), old_h = grid->col_gap(c); - if (h < -1) h = -1; - if (h != old_h) { - undo_checkpoint(); - grid->col_gap(c, h); - grid->need_layout(true); - set_modflag(1); - } - } +static void cb_widget_tab_grid_child(Grid_Child_Tab* o, void*) { + o->callback((Fl_Callback*)propagate_load); } Fl_Tabs *widget_tabs_repo=(Fl_Tabs *)0; @@ -1053,13 +2281,13 @@ Fl_Double_Window* make_widget_panel() { widget_image_input->labelfont(1); widget_image_input->labelsize(11); widget_image_input->textsize(11); - widget_image_input->callback((Fl_Callback*)image_cb); + widget_image_input->callback((Fl_Callback*)cb_widget_image_input); Fl_Group::current()->resizable(widget_image_input); } // Fl_Input* widget_image_input { Fl_Button* o = new Fl_Button(295, 65, 89, 20, "Browse..."); o->tooltip("Click to choose the active image."); o->labelsize(11); - o->callback((Fl_Callback*)image_browse_cb); + o->callback((Fl_Callback*)cb_Browse); o->align(Fl_Align(256)); } // Fl_Button* o { Fl_Button* o = new Fl_Button(384, 65, 20, 20, "..."); @@ -1078,13 +2306,13 @@ Fl_Double_Window* make_widget_panel() { widget_deimage_input->labelfont(1); widget_deimage_input->labelsize(11); widget_deimage_input->textsize(11); - widget_deimage_input->callback((Fl_Callback*)inactive_cb); + widget_deimage_input->callback((Fl_Callback*)cb_widget_deimage_input); Fl_Group::current()->resizable(widget_deimage_input); } // Fl_Input* widget_deimage_input { Fl_Button* o = new Fl_Button(295, 90, 89, 20, "Browse..."); o->tooltip("Click to choose the inactive image."); o->labelsize(11); - o->callback((Fl_Callback*)inactive_browse_cb); + o->callback((Fl_Callback*)cb_Browse1); } // Fl_Button* o o->end(); } // Fl_Group* o @@ -1188,7 +2416,7 @@ Fl_Double_Window* make_widget_panel() { widget_x_input->labelsize(11); widget_x_input->labelcolor(FL_FOREGROUND_COLOR); widget_x_input->textsize(11); - widget_x_input->callback((Fl_Callback*)x_cb); + widget_x_input->callback((Fl_Callback*)cb_widget_x_input); widget_x_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_x_input->when(FL_WHEN_RELEASE); } // fld::widget::Formula_Input* widget_x_input @@ -1203,7 +2431,7 @@ Fl_Double_Window* make_widget_panel() { widget_y_input->labelsize(11); widget_y_input->labelcolor(FL_FOREGROUND_COLOR); widget_y_input->textsize(11); - widget_y_input->callback((Fl_Callback*)y_cb); + widget_y_input->callback((Fl_Callback*)cb_widget_y_input); widget_y_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_y_input->when(FL_WHEN_RELEASE); } // fld::widget::Formula_Input* widget_y_input @@ -1218,7 +2446,7 @@ Fl_Double_Window* make_widget_panel() { widget_w_input->labelsize(11); widget_w_input->labelcolor(FL_FOREGROUND_COLOR); widget_w_input->textsize(11); - widget_w_input->callback((Fl_Callback*)w_cb); + widget_w_input->callback((Fl_Callback*)cb_widget_w_input); widget_w_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_w_input->when(FL_WHEN_RELEASE); } // fld::widget::Formula_Input* widget_w_input @@ -1233,7 +2461,7 @@ Fl_Double_Window* make_widget_panel() { widget_h_input->labelsize(11); widget_h_input->labelcolor(FL_FOREGROUND_COLOR); widget_h_input->textsize(11); - widget_h_input->callback((Fl_Callback*)h_cb); + widget_h_input->callback((Fl_Callback*)cb_widget_h_input); widget_h_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); widget_h_input->when(FL_WHEN_RELEASE); } // fld::widget::Formula_Input* widget_h_input @@ -1244,7 +2472,7 @@ Fl_Double_Window* make_widget_panel() { o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)wc_relative_cb); + o->callback((Fl_Callback*)cb_Children); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); o->menu(menu_Children); } // Fl_Choice* o @@ -1258,21 +2486,21 @@ Fl_Double_Window* make_widget_panel() { wp_gui_flexp = new Fl_Group(95, 150, 314, 20, "Flex Parent:"); wp_gui_flexp->labelfont(1); wp_gui_flexp->labelsize(11); - wp_gui_flexp->callback((Fl_Callback*)flex_size_group_cb); + wp_gui_flexp->callback((Fl_Callback*)cb_wp_gui_flexp); wp_gui_flexp->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_flexp->hide(); { widget_flex_size = new Fl_Value_Input(95, 150, 55, 20, "Size:"); widget_flex_size->tooltip("Fixed Width or Height for a horizontal or vertical Fl_Flex Parent."); widget_flex_size->labelsize(11); widget_flex_size->textsize(11); - widget_flex_size->callback((Fl_Callback*)flex_size_cb); + widget_flex_size->callback((Fl_Callback*)cb_widget_flex_size); widget_flex_size->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* widget_flex_size { widget_flex_fixed = new Fl_Check_Button(155, 150, 55, 20, "fixed"); widget_flex_fixed->tooltip("If checked, the size of the widget stays fixed."); widget_flex_fixed->down_box(FL_DOWN_BOX); widget_flex_fixed->labelsize(11); - widget_flex_fixed->callback((Fl_Callback*)flex_fixed_cb); + widget_flex_fixed->callback((Fl_Callback*)cb_widget_flex_fixed); } // Fl_Check_Button* widget_flex_fixed { Fl_Box* o = new Fl_Box(398, 150, 1, 20); Fl_Group::current()->resizable(o); @@ -1282,20 +2510,20 @@ Fl_Double_Window* make_widget_panel() { { wp_gui_values = new Fl_Group(95, 185, 300, 20, "Values:"); wp_gui_values->labelfont(1); wp_gui_values->labelsize(11); - wp_gui_values->callback((Fl_Callback*)values_group_cb); + wp_gui_values->callback((Fl_Callback*)cb_wp_gui_values); wp_gui_values->align(Fl_Align(FL_ALIGN_LEFT)); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Size:"); o->tooltip("The size of the slider."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)slider_size_cb); + o->callback((Fl_Callback*)cb_Size); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20, "Minimum:"); o->tooltip("The minimum value of the widget."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)min_cb); + 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(215, 185, 55, 20, "Maximum:"); @@ -1303,21 +2531,21 @@ Fl_Double_Window* make_widget_panel() { o->labelsize(11); o->value(1); o->textsize(11); - o->callback((Fl_Callback*)max_cb); + o->callback((Fl_Callback*)cb_Maximum); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(275, 185, 55, 20, "Step:"); o->tooltip("The resolution of the widget value."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)step_cb); + o->callback((Fl_Callback*)cb_Step); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(335, 185, 55, 20, "Value:"); o->tooltip("The current widget value."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)value_cb); + o->callback((Fl_Callback*)cb_Value); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); @@ -1329,42 +2557,42 @@ Fl_Double_Window* make_widget_panel() { wp_gui_margins = new Fl_Group(95, 185, 300, 20, "Margins:"); wp_gui_margins->labelfont(1); wp_gui_margins->labelsize(11); - wp_gui_margins->callback((Fl_Callback*)flex_margin_group_cb); + wp_gui_margins->callback((Fl_Callback*)cb_wp_gui_margins); wp_gui_margins->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_margins->hide(); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Left:"); o->tooltip("Left margin in group."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)flex_margin_left_cb); + 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(155, 185, 55, 20, "Top:"); o->tooltip("Top margin in group."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)flex_margin_top_cb); + 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(215, 185, 55, 20, "Right:"); o->tooltip("Right margin in group."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)flex_margin_right_cb); + 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(275, 185, 55, 20, "Bottom:"); o->tooltip("Bottom margin in group."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)flex_margin_bottom_cb); + o->callback((Fl_Callback*)cb_Bottom); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(335, 185, 55, 20, "Gap:"); o->tooltip("Gap between children."); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)flex_margin_gap_cb); + o->callback((Fl_Callback*)cb_Gap); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); @@ -1375,7 +2603,7 @@ Fl_Double_Window* make_widget_panel() { { wp_gui_sizerange = new Fl_Group(95, 185, 300, 20, "Size Range:"); wp_gui_sizerange->labelfont(1); wp_gui_sizerange->labelsize(11); - wp_gui_sizerange->callback((Fl_Callback*)size_range_group_cb); + wp_gui_sizerange->callback((Fl_Callback*)cb_wp_gui_sizerange); wp_gui_sizerange->align(Fl_Align(FL_ALIGN_LEFT)); wp_gui_sizerange->hide(); { Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Minimum Size:"); @@ -1384,7 +2612,7 @@ Fl_Double_Window* make_widget_panel() { o->maximum(2048); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)min_w_cb); + o->callback((Fl_Callback*)cb_Minimum1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20); @@ -1393,12 +2621,12 @@ Fl_Double_Window* make_widget_panel() { o->maximum(2048); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)min_h_cb); + o->callback((Fl_Callback*)cb_1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Button* o = new Fl_Button(215, 185, 25, 20, "set"); o->labelsize(11); - o->callback((Fl_Callback*)set_min_size_cb); + o->callback((Fl_Callback*)cb_set); } // Fl_Button* o { Fl_Value_Input* o = new Fl_Value_Input(245, 185, 55, 20, "Maximum Size:"); o->tooltip("The maximum value of the widget."); @@ -1406,7 +2634,7 @@ Fl_Double_Window* make_widget_panel() { o->maximum(2048); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)max_w_cb); + o->callback((Fl_Callback*)cb_Maximum1); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Value_Input* o = new Fl_Value_Input(305, 185, 55, 20); @@ -1415,12 +2643,12 @@ Fl_Double_Window* make_widget_panel() { o->maximum(2048); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)max_h_cb); + o->callback((Fl_Callback*)cb_2); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Button* o = new Fl_Button(365, 185, 25, 20, "set"); o->labelsize(11); - o->callback((Fl_Callback*)set_max_size_cb); + o->callback((Fl_Callback*)cb_set1); } // Fl_Button* o { Fl_Box* o = new Fl_Box(395, 185, 0, 20); Fl_Group::current()->resizable(o); @@ -1442,7 +2670,7 @@ Fl_Double_Window* make_widget_panel() { wp_gui_shortcut->labelfont(0); wp_gui_shortcut->labelsize(11); wp_gui_shortcut->labelcolor(FL_FOREGROUND_COLOR); - wp_gui_shortcut->callback((Fl_Callback*)shortcut_in_cb); + wp_gui_shortcut->callback((Fl_Callback*)cb_wp_gui_shortcut); wp_gui_shortcut->align(Fl_Align(FL_ALIGN_CENTER)); wp_gui_shortcut->when(FL_WHEN_CHANGED); } // Fl_Shortcut_Button* wp_gui_shortcut @@ -1458,26 +2686,26 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)xclass_cb); + o->callback((Fl_Callback*)cb_3); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Light_Button* o = new Fl_Light_Button(195, 235, 60, 20, "Border"); o->tooltip("Add a border around the window."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)border_cb); + o->callback((Fl_Callback*)cb_Border); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(260, 235, 55, 20, "Modal"); o->tooltip("Make the window modal."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)modal_cb); + o->callback((Fl_Callback*)cb_Modal); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(320, 235, 75, 20, "Nonmodal"); o->tooltip("Make the window non-modal."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)non_modal_cb); + o->callback((Fl_Callback*)cb_Nonmodal); o->align(Fl_Align(132|FL_ALIGN_INSIDE)); } // Fl_Light_Button* o wp_gui_xclass->end(); @@ -1491,26 +2719,26 @@ Fl_Double_Window* make_widget_panel() { o->tooltip("Show the widget."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)visible_cb); + o->callback((Fl_Callback*)cb_Visible); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(160, 260, 60, 20, "Active"); o->tooltip("Activate the widget."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)active_cb); + o->callback((Fl_Callback*)cb_Active); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(225, 260, 75, 20, "Resizable"); o->tooltip("Make the widget resizable."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)resizable_cb); + o->callback((Fl_Callback*)cb_Resizable); o->when(FL_WHEN_CHANGED); } // Fl_Light_Button* o { Fl_Light_Button* o = new Fl_Light_Button(305, 260, 70, 20, "Hotspot"); o->tooltip("Center the window under this widget."); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)hotspot_cb); + o->callback((Fl_Callback*)cb_Hotspot); o->when(FL_WHEN_CHANGED); } // Fl_Light_Button* o { Fl_Box* o = new Fl_Box(395, 260, 0, 20); @@ -1524,7 +2752,7 @@ Fl_Double_Window* make_widget_panel() { wp_gui_tooltip->labelfont(1); wp_gui_tooltip->labelsize(11); wp_gui_tooltip->textsize(11); - wp_gui_tooltip->callback((Fl_Callback*)tooltip_cb); + wp_gui_tooltip->callback((Fl_Callback*)cb_wp_gui_tooltip); } // Fl_Input* wp_gui_tooltip { Fl_Box* o = new Fl_Box(95, 305, 300, 5); o->hide(); @@ -1550,7 +2778,7 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)labelfont_cb); + o->callback((Fl_Callback*)cb_4); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o @@ -1561,15 +2789,15 @@ Fl_Double_Window* make_widget_panel() { o->step(1); o->value(14); o->textsize(11); - o->callback((Fl_Callback*)labelsize_cb); + o->callback((Fl_Callback*)cb_5); } // Fl_Value_Input* o { w_labelcolor = new Fl_Button(296, 40, 90, 20, "Label Color"); w_labelcolor->tooltip("The color of the label text."); w_labelcolor->labelsize(11); - w_labelcolor->callback((Fl_Callback*)labelcolor_cb); + w_labelcolor->callback((Fl_Callback*)cb_w_labelcolor); } // Fl_Button* w_labelcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 40, 18, 20); - o->callback((Fl_Callback*)labelcolor_menu_cb); + o->callback((Fl_Callback*)cb_6); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_label->end(); @@ -1586,17 +2814,17 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)box_cb); + o->callback((Fl_Callback*)cb_7); Fl_Group::current()->resizable(o); o->menu(boxmenu); } // Fl_Choice* o { w_color = new Fl_Button(296, 65, 90, 20, "Color"); w_color->tooltip("The background color of the widget."); w_color->labelsize(11); - w_color->callback((Fl_Callback*)color_cb); + w_color->callback((Fl_Callback*)cb_w_color); } // Fl_Button* w_color { Fl_Menu_Button* o = new Fl_Menu_Button(386, 65, 18, 20); - o->callback((Fl_Callback*)color_menu_cb); + o->callback((Fl_Callback*)cb_8); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_box->end(); @@ -1613,17 +2841,17 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)down_box_cb); + o->callback((Fl_Callback*)cb_9); Fl_Group::current()->resizable(o); o->menu(boxmenu); } // Fl_Choice* o { w_selectcolor = new Fl_Button(296, 90, 90, 20, "Select Color"); w_selectcolor->tooltip("The selection color of the widget."); w_selectcolor->labelsize(11); - w_selectcolor->callback((Fl_Callback*)color2_cb); + w_selectcolor->callback((Fl_Callback*)cb_w_selectcolor); } // Fl_Button* w_selectcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 90, 18, 20); - o->callback((Fl_Callback*)color2_menu_cb); + o->callback((Fl_Callback*)cb_a); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_downbox->end(); @@ -1640,7 +2868,7 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)textfont_cb); + o->callback((Fl_Callback*)cb_b); Fl_Group::current()->resizable(o); o->menu(fontmenu); } // Fl_Choice* o @@ -1651,15 +2879,15 @@ Fl_Double_Window* make_widget_panel() { o->step(1); o->value(14); o->textsize(11); - o->callback((Fl_Callback*)textsize_cb); + o->callback((Fl_Callback*)cb_c); } // Fl_Value_Input* o { w_textcolor = new Fl_Button(296, 115, 90, 20, "Text Color"); w_textcolor->tooltip("The value text color."); w_textcolor->labelsize(11); - w_textcolor->callback((Fl_Callback*)textcolor_cb); + w_textcolor->callback((Fl_Callback*)cb_w_textcolor); } // Fl_Button* w_textcolor { Fl_Menu_Button* o = new Fl_Menu_Button(386, 115, 18, 20); - o->callback((Fl_Callback*)textcolor_menu_cb); + o->callback((Fl_Callback*)cb_d); o->menu(colormenu); } // Fl_Menu_Button* o wp_style_text->end(); @@ -1676,7 +2904,7 @@ Fl_Double_Window* make_widget_panel() { o->maximum(128); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)h_label_margin_cb); + 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(159, 150, 55, 20, "Vertical:"); @@ -1686,16 +2914,16 @@ Fl_Double_Window* make_widget_panel() { o->maximum(127); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)v_label_margin_cb); + o->callback((Fl_Callback*)cb_Vertical); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o - { Fl_Value_Input* o = new Fl_Value_Input(219, 150, 55, 20, "Text to Image:"); + { Fl_Value_Input* o = new Fl_Value_Input(219, 150, 55, 20, "Image Gap:"); o->tooltip("Gap between label image and text in pixels"); o->labelsize(11); o->maximum(255); o->step(1); o->textsize(11); - o->callback((Fl_Callback*)image_spacing_cb); + o->callback((Fl_Callback*)cb_Image); o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); } // Fl_Value_Input* o { Fl_Box* o = new Fl_Box(281, 150, 60, 20); @@ -1709,7 +2937,7 @@ Fl_Double_Window* make_widget_panel() { o->tooltip("use compact box types for closely set buttons"); o->selection_color((Fl_Color)1); o->labelsize(11); - o->callback((Fl_Callback*)compact_cb); + o->callback((Fl_Callback*)cb_Compact); } // Fl_Light_Button* o { Fl_Box* o = new Fl_Box(195, 205, 40, 40); o->labelsize(11); @@ -1733,7 +2961,7 @@ Fl_Double_Window* make_widget_panel() { o->labelsize(11); o->textfont(4); o->textsize(11); - o->callback((Fl_Callback*)subclass_cb, (void*)(4)); + o->callback((Fl_Callback*)cb_e, (void*)(4)); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Choice* o = new Fl_Choice(267, 40, 138, 20); @@ -1742,7 +2970,7 @@ Fl_Double_Window* make_widget_panel() { o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)subtype_cb); + o->callback((Fl_Callback*)cb_f); } // Fl_Choice* o wp_cpp_class->end(); } // Fl_Group* wp_cpp_class @@ -1756,7 +2984,7 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)name_cb); + o->callback((Fl_Callback*)cb_10); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Choice* o = new Fl_Choice(330, 65, 75, 20); @@ -1764,7 +2992,7 @@ Fl_Double_Window* make_widget_panel() { o->down_box(FL_BORDER_BOX); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)name_public_member_cb); + o->callback((Fl_Callback*)cb_11); o->when(FL_WHEN_CHANGED); o->menu(menu_2); } // Fl_Choice* o @@ -1786,31 +3014,31 @@ Fl_Double_Window* make_widget_panel() { v_input[0]->labelsize(11); v_input[0]->textfont(4); v_input[0]->textsize(11); - v_input[0]->callback((Fl_Callback*)v_input_cb, (void*)(0)); + v_input[0]->callback((Fl_Callback*)cb_v_input, (void*)(0)); } // Fl_Input* v_input[0] { v_input[1] = new Fl_Input(95, 110, 310, 20); v_input[1]->tooltip("Extra initialization code for the widget."); v_input[1]->labelsize(11); v_input[1]->textfont(4); v_input[1]->textsize(11); - v_input[1]->callback((Fl_Callback*)v_input_cb, (void*)(1)); + v_input[1]->callback((Fl_Callback*)cb_v_input1, (void*)(1)); } // Fl_Input* v_input[1] { v_input[2] = new Fl_Input(95, 130, 310, 20); v_input[2]->tooltip("Extra initialization code for the widget."); v_input[2]->labelsize(11); v_input[2]->textfont(4); v_input[2]->textsize(11); - v_input[2]->callback((Fl_Callback*)v_input_cb, (void*)(2)); + v_input[2]->callback((Fl_Callback*)cb_v_input2, (void*)(2)); } // Fl_Input* v_input[2] { v_input[3] = new Fl_Input(95, 150, 310, 20); v_input[3]->tooltip("Extra initialization code for the widget."); v_input[3]->labelsize(11); v_input[3]->textfont(4); v_input[3]->textsize(11); - v_input[3]->callback((Fl_Callback*)v_input_cb, (void*)(3)); + v_input[3]->callback((Fl_Callback*)cb_v_input3, (void*)(3)); } // Fl_Input* v_input[3] { Fl_Tile* o = new Fl_Tile(95, 175, 310, 130); - o->callback((Fl_Callback*)cb_1); + o->callback((Fl_Callback*)cb_12); { Fl_Group* o = new Fl_Group(95, 175, 310, 48); o->box(FL_FLAT_BOX); { wComment = new Fl_Text_Editor(95, 175, 310, 45, "Comment:"); @@ -1822,11 +3050,11 @@ Fl_Double_Window* make_widget_panel() { wComment->textfont(6); wComment->textsize(11); wComment->textcolor((Fl_Color)59); + wComment->callback((Fl_Callback*)cb_wComment); wComment->align(Fl_Align(FL_ALIGN_LEFT)); wComment->when(FL_WHEN_CHANGED); Fl_Group::current()->resizable(wComment); wComment->buffer(new Fl_Text_Buffer()); - wComment->callback((Fl_Callback*)comment_cb); } // Fl_Text_Editor* wComment o->end(); } // Fl_Group* o @@ -1844,7 +3072,7 @@ Fl_Double_Window* make_widget_panel() { wCallback->labelcolor(FL_FOREGROUND_COLOR); wCallback->textfont(4); wCallback->textsize(11); - wCallback->callback((Fl_Callback*)callback_cb); + wCallback->callback((Fl_Callback*)cb_wCallback); wCallback->align(Fl_Align(FL_ALIGN_LEFT)); wCallback->when(FL_WHEN_RELEASE); Fl_Group::current()->resizable(wCallback); @@ -1865,7 +3093,7 @@ Fl_Double_Window* make_widget_panel() { o->labelsize(11); o->textfont(4); o->textsize(11); - o->callback((Fl_Callback*)user_data_cb); + o->callback((Fl_Callback*)cb_13); Fl_Group::current()->resizable(o); } // Fl_Input* o { Fl_Menu_Button* o = new Fl_Menu_Button(260, 310, 145, 20, "When"); @@ -1875,7 +3103,7 @@ Fl_Double_Window* make_widget_panel() { o->labelfont(1); o->labelsize(11); o->textsize(11); - o->callback((Fl_Callback*)when_cb); + o->callback((Fl_Callback*)cb_When); o->when(FL_WHEN_CHANGED); o->menu(whenmenu); } // Fl_Menu_Button* o @@ -1892,7 +3120,7 @@ Fl_Double_Window* make_widget_panel() { o->labelsize(11); o->textfont(4); o->textsize(11); - o->callback((Fl_Callback*)user_data_type_cb); + o->callback((Fl_Callback*)cb_14); Fl_Group::current()->resizable(o); o->menu(menu_4); } // Fl_Input_Choice* o @@ -1906,550 +3134,34 @@ Fl_Double_Window* make_widget_panel() { } // Fl_Group* o wp_cpp_tab->end(); } // Fl_Group* wp_cpp_tab - { widget_tab_grid_child = new Fl_Group(10, 30, 400, 330, "Grid Child"); - widget_tab_grid_child->labelsize(11); - widget_tab_grid_child->callback((Fl_Callback*)propagate_load); - widget_tab_grid_child->hide(); - { Fl_Group* o = new Fl_Group(95, 60, 315, 20, "Location:"); - o->box(FL_FLAT_BOX); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)propagate_load); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { widget_grid_row_input = new fld::widget::Formula_Input(95, 60, 40, 20, "Row:"); - widget_grid_row_input->box(FL_DOWN_BOX); - widget_grid_row_input->color(FL_BACKGROUND2_COLOR); - widget_grid_row_input->selection_color(FL_SELECTION_COLOR); - widget_grid_row_input->labeltype(FL_NORMAL_LABEL); - widget_grid_row_input->labelfont(0); - widget_grid_row_input->labelsize(11); - widget_grid_row_input->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_row_input->textsize(11); - widget_grid_row_input->callback((Fl_Callback*)grid_set_row_cb); - widget_grid_row_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_row_input->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_row_input - { Fl_Group* o = new Fl_Group(135, 60, 30, 20); - { Fl_Button* o = new Fl_Button(135, 60, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_dec_row_cb); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 60, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_inc_row_cb); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { widget_grid_col_input = new fld::widget::Formula_Input(175, 60, 40, 20, "Column:"); - widget_grid_col_input->box(FL_DOWN_BOX); - widget_grid_col_input->color(FL_BACKGROUND2_COLOR); - widget_grid_col_input->selection_color(FL_SELECTION_COLOR); - widget_grid_col_input->labeltype(FL_NORMAL_LABEL); - widget_grid_col_input->labelfont(0); - widget_grid_col_input->labelsize(11); - widget_grid_col_input->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_col_input->textsize(11); - widget_grid_col_input->callback((Fl_Callback*)grid_set_col_cb); - widget_grid_col_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_col_input->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_col_input - { Fl_Group* o = new Fl_Group(215, 60, 30, 20); - { Fl_Button* o = new Fl_Button(215, 60, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_dec_col_cb); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(230, 60, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_inc_col_cb); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(395, 60, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - { widget_grid_transient = new Fl_Box(250, 60, 80, 20, "TRANSIENT"); - widget_grid_transient->labelsize(11); - widget_grid_transient->labelcolor((Fl_Color)1); - widget_grid_transient->callback((Fl_Callback*)cb_widget_grid_transient); - } // Fl_Box* widget_grid_transient - { widget_grid_unlinked = new Fl_Box(250, 60, 80, 20, "UNLINKED"); - widget_grid_unlinked->labelsize(11); - widget_grid_unlinked->labelcolor((Fl_Color)1); - widget_grid_unlinked->hide(); - } // Fl_Box* widget_grid_unlinked - o->end(); - } // Fl_Group* o - { wp_gridc_align = new Fl_Group(95, 100, 315, 20, "Align:"); - wp_gridc_align->labelfont(1); - wp_gridc_align->labelsize(11); - wp_gridc_align->callback((Fl_Callback*)propagate_load); - wp_gridc_align->align(Fl_Align(FL_ALIGN_LEFT)); - { Fl_Choice* o = new Fl_Choice(95, 100, 115, 20, "Horizontal"); - o->down_box(FL_BORDER_BOX); - o->labelsize(11); - o->textsize(11); - o->callback((Fl_Callback*)grid_align_horizontal_cb); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->menu(menu_Horizontal); - } // Fl_Choice* o - { Fl_Choice* o = new Fl_Choice(215, 100, 115, 20, "Vertical"); - o->down_box(FL_BORDER_BOX); - o->labelsize(11); - o->textsize(11); - o->callback((Fl_Callback*)grid_align_vertical_cb); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->menu(menu_Vertical); - } // Fl_Choice* o - { Fl_Box* o = new Fl_Box(395, 100, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - wp_gridc_align->end(); - } // Fl_Group* wp_gridc_align - { wp_gridc_size = new Fl_Group(95, 135, 315, 20, "Min. Size:"); - wp_gridc_size->labelfont(1); - wp_gridc_size->labelsize(11); - wp_gridc_size->callback((Fl_Callback*)propagate_load); - wp_gridc_size->align(Fl_Align(FL_ALIGN_LEFT)); - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(95, 135, 55, 20, "Width:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)grid_set_min_wdt_cb); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(155, 135, 55, 20, "Height:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)grid_set_min_hgt_cb); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { Fl_Box* o = new Fl_Box(395, 135, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - wp_gridc_size->end(); - } // Fl_Group* wp_gridc_size - { Fl_Group* o = new Fl_Group(95, 170, 315, 20, "Span:"); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)propagate_load); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { widget_grid_rowspan_input = new fld::widget::Formula_Input(95, 170, 40, 20, "Row Span:"); - widget_grid_rowspan_input->box(FL_DOWN_BOX); - widget_grid_rowspan_input->color(FL_BACKGROUND2_COLOR); - widget_grid_rowspan_input->selection_color(FL_SELECTION_COLOR); - widget_grid_rowspan_input->labeltype(FL_NORMAL_LABEL); - widget_grid_rowspan_input->labelfont(0); - widget_grid_rowspan_input->labelsize(11); - widget_grid_rowspan_input->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_rowspan_input->textsize(11); - widget_grid_rowspan_input->callback((Fl_Callback*)grid_set_rowspan_cb); - widget_grid_rowspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_rowspan_input->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_rowspan_input - { Fl_Group* o = new Fl_Group(135, 170, 30, 20); - { Fl_Button* o = new Fl_Button(135, 170, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_dec_rowspan_cb); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 170, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_inc_rowspan_cb); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { widget_grid_colspan_input = new fld::widget::Formula_Input(175, 170, 40, 20, "Col. Span:"); - widget_grid_colspan_input->box(FL_DOWN_BOX); - widget_grid_colspan_input->color(FL_BACKGROUND2_COLOR); - widget_grid_colspan_input->selection_color(FL_SELECTION_COLOR); - widget_grid_colspan_input->labeltype(FL_NORMAL_LABEL); - widget_grid_colspan_input->labelfont(0); - widget_grid_colspan_input->labelsize(11); - widget_grid_colspan_input->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_colspan_input->textsize(11); - widget_grid_colspan_input->callback((Fl_Callback*)grid_set_colspan_cb); - widget_grid_colspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_colspan_input->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_colspan_input - { Fl_Group* o = new Fl_Group(215, 170, 30, 20); - { Fl_Button* o = new Fl_Button(215, 170, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_dec_colspan_cb); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(230, 170, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)grid_inc_colspan_cb); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(395, 170, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(95, 350, 300, 5); - o->labelsize(11); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - widget_tab_grid_child->end(); - } // Fl_Group* widget_tab_grid_child - { widget_tab_grid = new Fl_Group(10, 30, 400, 330, "Grid"); + { widget_tab_grid = new Grid_Tab(10, 30, 400, 330, "Grid"); + widget_tab_grid->box(FL_NO_BOX); + widget_tab_grid->color(FL_BACKGROUND_COLOR); + widget_tab_grid->selection_color(FL_BACKGROUND_COLOR); + widget_tab_grid->labeltype(FL_NORMAL_LABEL); + widget_tab_grid->labelfont(0); widget_tab_grid->labelsize(11); - widget_tab_grid->callback((Fl_Callback*)propagate_load); + widget_tab_grid->labelcolor(FL_FOREGROUND_COLOR); + widget_tab_grid->callback((Fl_Callback*)cb_widget_tab_grid); + widget_tab_grid->align(Fl_Align(FL_ALIGN_TOP)); + widget_tab_grid->when(FL_WHEN_RELEASE); widget_tab_grid->hide(); - { Fl_Group* o = new Fl_Group(95, 60, 315, 20, "Grid Layout:"); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)propagate_load); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { widget_grid_rows = new fld::widget::Formula_Input(95, 60, 40, 20, "Rows:"); - widget_grid_rows->tooltip("Number of horizontal rows in the Grid group"); - widget_grid_rows->box(FL_DOWN_BOX); - widget_grid_rows->color(FL_BACKGROUND2_COLOR); - widget_grid_rows->selection_color(FL_SELECTION_COLOR); - widget_grid_rows->labeltype(FL_NORMAL_LABEL); - widget_grid_rows->labelfont(0); - widget_grid_rows->labelsize(11); - widget_grid_rows->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_rows->textsize(11); - widget_grid_rows->callback((Fl_Callback*)cb_widget_grid_rows); - widget_grid_rows->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_rows->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_rows - { Fl_Group* o = new Fl_Group(135, 60, 30, 20); - { Fl_Button* o = new Fl_Button(135, 60, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_2); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 60, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_3); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { widget_grid_cols = new fld::widget::Formula_Input(175, 60, 40, 20, "Columns:"); - widget_grid_cols->tooltip("Number of vertical columns in the Grid group"); - widget_grid_cols->box(FL_DOWN_BOX); - widget_grid_cols->color(FL_BACKGROUND2_COLOR); - widget_grid_cols->selection_color(FL_SELECTION_COLOR); - widget_grid_cols->labeltype(FL_NORMAL_LABEL); - widget_grid_cols->labelfont(0); - widget_grid_cols->labelsize(11); - widget_grid_cols->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_cols->textsize(11); - widget_grid_cols->callback((Fl_Callback*)cb_widget_grid_cols); - widget_grid_cols->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_cols->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_cols - { Fl_Group* o = new Fl_Group(215, 60, 30, 20); - { Fl_Button* o = new Fl_Button(215, 60, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_4); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(230, 60, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_5); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(396, 60, 0, 20); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - o->end(); - } // Fl_Group* o - { wp_grid_margin = new Fl_Group(95, 100, 315, 20, "Margins:"); - wp_grid_margin->labelfont(1); - wp_grid_margin->labelsize(11); - wp_grid_margin->callback((Fl_Callback*)propagate_load); - wp_grid_margin->align(Fl_Align(FL_ALIGN_LEFT)); - { Fl_Value_Input* o = new Fl_Value_Input(95, 100, 55, 20, "Left:"); - o->tooltip("Left margin in group."); - o->labelsize(11); - o->maximum(1000); - 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(155, 100, 55, 20, "Top:"); - o->tooltip("Top margin in group."); - o->labelsize(11); - o->maximum(1000); - 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(215, 100, 55, 20, "Right:"); - o->tooltip("Right margin in group."); - o->labelsize(11); - o->maximum(1000); - 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(275, 100, 55, 20, "Bottom:"); - o->tooltip("Bottom margin in group."); - o->labelsize(11); - o->maximum(1000); - 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(396, 100, 0, 20); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - wp_grid_margin->end(); - } // Fl_Group* wp_grid_margin - { wp_grid_gaps = new Fl_Group(95, 135, 315, 20, "Gaps:"); - wp_grid_gaps->labelfont(1); - wp_grid_gaps->labelsize(11); - wp_grid_gaps->callback((Fl_Callback*)propagate_load); - wp_grid_gaps->align(Fl_Align(FL_ALIGN_LEFT)); - { Fl_Value_Input* o = new Fl_Value_Input(95, 135, 55, 20, "Row:"); - o->tooltip("Gap between children."); - o->labelsize(11); - o->maximum(1000); - o->step(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Row); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - } // Fl_Value_Input* o - { Fl_Value_Input* o = new Fl_Value_Input(155, 135, 55, 20, "Col:"); - o->tooltip("Gap between children."); - o->labelsize(11); - o->maximum(1000); - o->step(1); - o->textsize(11); - o->callback((Fl_Callback*)cb_Col); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - } // Fl_Value_Input* o - { Fl_Box* o = new Fl_Box(396, 135, 0, 20); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - wp_grid_gaps->end(); - } // Fl_Group* wp_grid_gaps - { Fl_Group* o = new Fl_Group(95, 175, 315, 20, "Row:"); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_Row1); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { widget_grid_curr_row = new fld::widget::Formula_Input(95, 175, 40, 20, "Index"); - widget_grid_curr_row->box(FL_DOWN_BOX); - widget_grid_curr_row->color(FL_BACKGROUND2_COLOR); - widget_grid_curr_row->selection_color(FL_SELECTION_COLOR); - widget_grid_curr_row->labeltype(FL_NORMAL_LABEL); - widget_grid_curr_row->labelfont(0); - widget_grid_curr_row->labelsize(11); - widget_grid_curr_row->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_curr_row->textsize(11); - widget_grid_curr_row->callback((Fl_Callback*)cb_widget_grid_curr_row); - widget_grid_curr_row->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_curr_row->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_curr_row - { Fl_Group* o = new Fl_Group(135, 175, 30, 20); - o->callback((Fl_Callback*)propagate_load); - { Fl_Button* o = new Fl_Button(135, 175, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_6); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 175, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_7); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(165, 175, 15, 20, ":"); - o->labelsize(11); - } // Fl_Box* o - { widget_grid_curr_row_attributes = new Fl_Group(180, 175, 175, 20); - widget_grid_curr_row_attributes->callback((Fl_Callback*)propagate_load); - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(180, 175, 55, 20, "Height:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Height); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(240, 175, 55, 20, "Weight:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Weight); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(300, 175, 55, 20, "Gap:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Gap); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - widget_grid_curr_row_attributes->end(); - } // Fl_Group* widget_grid_curr_row_attributes - { Fl_Box* o = new Fl_Box(400, 175, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - o->end(); - } // Fl_Group* o - { Fl_Group* o = new Fl_Group(95, 210, 315, 20, "Column:"); - o->labelfont(1); - o->labelsize(11); - o->callback((Fl_Callback*)propagate_load); - o->align(Fl_Align(FL_ALIGN_LEFT)); - { widget_grid_curr_col = new fld::widget::Formula_Input(95, 210, 40, 20, "Index"); - widget_grid_curr_col->box(FL_DOWN_BOX); - widget_grid_curr_col->color(FL_BACKGROUND2_COLOR); - widget_grid_curr_col->selection_color(FL_SELECTION_COLOR); - widget_grid_curr_col->labeltype(FL_NORMAL_LABEL); - widget_grid_curr_col->labelfont(0); - widget_grid_curr_col->labelsize(11); - widget_grid_curr_col->labelcolor(FL_FOREGROUND_COLOR); - widget_grid_curr_col->textsize(11); - widget_grid_curr_col->callback((Fl_Callback*)cb_widget_grid_curr_col); - widget_grid_curr_col->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - widget_grid_curr_col->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* widget_grid_curr_col - { Fl_Group* o = new Fl_Group(135, 210, 30, 20); - { Fl_Button* o = new Fl_Button(135, 210, 15, 20, "-"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_8); - o->clear_visible_focus(); - } // Fl_Button* o - { Fl_Button* o = new Fl_Button(150, 210, 15, 20, "+"); - o->compact(1); - o->labelsize(11); - o->callback((Fl_Callback*)cb_9); - o->clear_visible_focus(); - } // Fl_Button* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(165, 210, 15, 20, ":"); - o->labelsize(11); - } // Fl_Box* o - { widget_grid_curr_col_attributes = new Fl_Group(180, 210, 175, 20); - widget_grid_curr_col_attributes->callback((Fl_Callback*)propagate_load); - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(180, 210, 55, 20, "Width:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Width); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(240, 210, 55, 20, "Weight:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Weight1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(300, 210, 55, 20, "Gap:"); - o->box(FL_DOWN_BOX); - o->color(FL_BACKGROUND2_COLOR); - o->selection_color(FL_SELECTION_COLOR); - o->labeltype(FL_NORMAL_LABEL); - o->labelfont(0); - o->labelsize(11); - o->labelcolor(FL_FOREGROUND_COLOR); - o->textsize(11); - o->callback((Fl_Callback*)cb_Gap1); - o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); - o->when(FL_WHEN_RELEASE); - } // fld::widget::Formula_Input* o - widget_grid_curr_col_attributes->end(); - } // Fl_Group* widget_grid_curr_col_attributes - { Fl_Box* o = new Fl_Box(400, 210, 1, 20); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o - o->end(); - } // Fl_Group* o - { Fl_Box* o = new Fl_Box(95, 350, 300, 5); - o->labelsize(11); - o->hide(); - Fl_Group::current()->resizable(o); - } // Fl_Box* o widget_tab_grid->end(); - } // Fl_Group* widget_tab_grid + } // Grid_Tab* widget_tab_grid + { widget_tab_grid_child = new Grid_Child_Tab(10, 30, 400, 330, "Grid Child"); + widget_tab_grid_child->box(FL_NO_BOX); + widget_tab_grid_child->color(FL_BACKGROUND_COLOR); + widget_tab_grid_child->selection_color(FL_BACKGROUND_COLOR); + widget_tab_grid_child->labeltype(FL_NORMAL_LABEL); + widget_tab_grid_child->labelfont(0); + widget_tab_grid_child->labelsize(11); + widget_tab_grid_child->labelcolor(FL_FOREGROUND_COLOR); + widget_tab_grid_child->callback((Fl_Callback*)cb_widget_tab_grid_child); + widget_tab_grid_child->align(Fl_Align(FL_ALIGN_TOP)); + widget_tab_grid_child->when(FL_WHEN_RELEASE); + widget_tab_grid_child->hide(); + widget_tab_grid_child->end(); + } // Grid_Child_Tab* widget_tab_grid_child o->show(); widget_tabs->end(); Fl_Group::current()->resizable(widget_tabs); diff --git a/fluid/panels/widget_panel.fl b/fluid/panels/widget_panel.fl index 517271e08..026616714 100644 --- a/fluid/panels/widget_panel.fl +++ b/fluid/panels/widget_panel.fl @@ -25,26 +25,76 @@ comment {// } {in_source in_header } -decl {\#include "app/undo.h"} {private global +decl {\#include "panels/widget_panel/Grid_Child_Tab.h"} {public global } -decl {\#include "nodes/Fl_Widget_Type.h"} {private global +decl {\#include "panels/widget_panel/Grid_Tab.h"} {public global } -decl {\#include "nodes/Fl_Grid_Type.h"} {private global +decl {\#include "widgets/Formula_Input.h"} {public global } -decl {\#include "widgets/Formula_Input.h"} {selected public global +decl {class Fl_Flex;} {public global +} + +decl {\#include "Fluid.h"} {private global +} + +decl {\#include "app/Snap_Action.h"} {private global +} + +decl {\#include "app/Image_Asset.h"} {private global +} + +decl {\#include "proj/undo.h"} {private global +} + +decl {\#include "nodes/Window_Node.h"} {private global +} + +decl {\#include "nodes/Grid_Node.h"} {private global +} + +decl {\#include } {private global } decl {\#include } {private global } -decl {extern void set_modflag(int mf, int mfc=-1);} {private local +decl {\#include } {private global +} + +decl {\#include } {private global +} + +decl {\#include } {private global +} + +decl {\#define ZERO_ENTRY 1000} {private global +} + +decl {extern const char* when_symbol_name(int n); +extern void set_whenmenu(int n); +extern void redraw_browser(); +const char *c_check(const char *c, int type=0); +extern Fl_Color fl_show_colormap(Fl_Color oldcol); +extern void labelcolor_common(Fl_Color c); +extern void color_common(Fl_Color c); +extern void color2_common(Fl_Color c); +extern void textcolor_common(Fl_Color c); +extern int widget_i; +extern fld::widget::Formula_Input_Vars widget_vars[];} {private global +} + +decl {extern int numselected; +extern Fl_Menu_Item boxmenu[];} {private global +} + +decl {extern int haderror;} {private global } Function {make_image_panel()} { - comment {Create a panel for editing widget image data} open + comment {Create a panel for editing widget image data} } { Fl_Window image_panel_window { label {Image Options} @@ -87,14 +137,14 @@ Function {make_image_panel()} { Fl_Input image_panel_imagew { label {Width:} callback {if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_image_w_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_image_w_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { @@ -109,7 +159,7 @@ Function {make_image_panel()} { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); }} tooltip {Scale image to this width in pixel units} xywh {75 75 55 20} labelsize 11 align 5 textsize 11 class {fld::widget::Formula_Input} @@ -117,14 +167,14 @@ Function {make_image_panel()} { Fl_Input image_panel_imageh { label {Height:} callback {if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_image_h_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_image_h_ = o->value(); Fl_Image *img = wt->o->image(); if (img) { @@ -139,7 +189,7 @@ Function {make_image_panel()} { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); }} tooltip {Scale image to this height in pixel units} xywh {135 75 55 20} labelsize 11 align 5 textsize 11 class {fld::widget::Formula_Input} @@ -165,12 +215,40 @@ Function {make_image_panel()} { } Fl_Check_Button {} { label {convert to raw pixel data} - callback compress_image_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(!current_widget->compress_image_); + } else { + o->deactivate(); + } +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->compress_image_ = !o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {if unchecked, keep the image in its original format and store the data as is; if checked, convert the image and store it as uncompressed RGB or grayscale pixel data} xywh {75 100 170 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {bind to widget} - callback bind_image_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(current_widget->bind_image_); + } else { + o->deactivate(); + } +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->bind_image_ = o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {bind the image to the widget, so it will be deleted automatically} xywh {75 120 170 20} down_box DOWN_BOX labelsize 11 hotspot } } @@ -209,14 +287,14 @@ Function {make_image_panel()} { Fl_Input image_panel_deimagew { label {Width:} callback {if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_deimage_w_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_deimage_w_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { @@ -231,7 +309,7 @@ Function {make_image_panel()} { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); }} tooltip {Scale image to this width in pixel units} xywh {75 215 55 20} labelsize 11 align 5 textsize 11 class {fld::widget::Formula_Input} @@ -239,14 +317,14 @@ Function {make_image_panel()} { Fl_Input image_panel_deimageh { label {Height:} callback {if (v == LOAD) { - if (current_widget->is_widget() && !current_widget->is_a(ID_Window)) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { o->value(current_widget->scale_deimage_h_); } } else { int mod = 0; - for (Fl_Type *t = Fl_Type::first; t; t = t->next) { + for (Node *t = Fluid.proj.tree.first; t; t = t->next) { if (t->selected && t->is_widget()) { - Fl_Widget_Type* wt = ((Fl_Widget_Type*)t); + Widget_Node* wt = ((Widget_Node*)t); wt->scale_deimage_h_ = o->value(); Fl_Image *img = wt->o->deimage(); if (img) { @@ -261,7 +339,7 @@ Function {make_image_panel()} { mod = 1; } } - if (mod) set_modflag(1); + if (mod) Fluid.proj.set_modflag(1); }} tooltip {Scale image to this height in pixel units} xywh {135 215 55 20} labelsize 11 align 5 textsize 11 class {fld::widget::Formula_Input} @@ -287,12 +365,40 @@ Function {make_image_panel()} { } Fl_Check_Button {} { label {convert to raw pixel data} - callback compress_deimage_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(!current_widget->compress_deimage_); + } else { + o->deactivate(); + } +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->compress_deimage_ = !o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {if unchecked, keep the image in its original format and store the data as is; if checked, convert the image and store it as uncompressed RGB or grayscale pixel data} xywh {75 240 170 20} down_box DOWN_BOX labelsize 11 } Fl_Check_Button {} { label {bind to widget} - callback bind_deimage_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(current_widget->bind_deimage_); + } else { + o->deactivate(); + } +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->bind_deimage_ = o->value(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {bind the image to the widget, so it will be deleted automatically} xywh {75 260 170 20} down_box DOWN_BOX labelsize 11 } } @@ -305,7 +411,7 @@ Function {make_image_panel()} { } } -Function {run_image_panel()} {open return_type void +Function {run_image_panel()} {return_type void } { code {if (!image_panel_window) make_image_panel(); @@ -324,7 +430,30 @@ if (g) Fl_Shared_Image *img = (Fl_Shared_Image*)image_panel_data->user_data(); if (img) { img->release(); - image_panel_data->user_data(NULL); + image_panel_data->user_data(nullptr); +}} {} +} + +Function {flex_margin_cb(Fl_Value_Input* i, void* v, void (*load_margin)(Fl_Flex*,Fl_Value_Input*), int (*update_margin)(Fl_Flex*,int))} {return_type void +} { + code {if (v == LOAD) { + if (current_widget->is_a(Type::Flex)) { + load_margin((Fl_Flex*)current_widget->o, i); + } +} else { + int mod = 0; + int new_value = (int)i->value(); + for (Node *o = Fluid.proj.tree.first; o; o = o->next) { + if (o->selected && o->is_a(Type::Flex)) { + Flex_Node* q = (Flex_Node*)o; + Fl_Flex* w = (Fl_Flex*)q->o; + if (update_margin(w, new_value)) { + w->layout(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); }} {} } @@ -343,7 +472,7 @@ Function {make_widget_panel()} { } { Fl_Group wp_gui_tab { label GUI - callback propagate_load open + callback propagate_load open selected xywh {10 30 400 330} labelsize 11 when 0 resizable } { Fl_Group {} { @@ -369,12 +498,40 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 15 t xywh {95 65 309 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_image_input { - callback image_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(((Widget_Node*)current_widget)->image_name()); + } else o->deactivate(); +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->image_name(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The active image for the widget.} xywh {95 65 200 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Button {} { label {Browse...} - callback image_browse_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) + o->activate(); + else + o->deactivate(); +} else { + int mod = 0; + Image_Asset *image_asset = ui_find_image(widget_image_input->value()); + if (image_asset) { + widget_image_input->value(image_asset->filename()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->image_name(image_asset->filename()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +}} tooltip {Click to choose the active image.} xywh {295 65 89 20} labelsize 11 align 256 } Fl_Button {} { @@ -391,12 +548,40 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 15 t xywh {95 90 309 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_deimage_input { - callback inactive_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) { + o->activate(); + o->value(((Widget_Node*)current_widget)->inactive_name()); + } else o->deactivate(); +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->inactive_name(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The inactive image for the widget.} xywh {95 90 200 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Button {} { label {Browse...} - callback inactive_browse_cb + callback {if (v == LOAD) { + if (current_widget->is_widget() && !current_widget->is_a(Type::Window)) + o->activate(); + else + o->deactivate(); +} else { + int mod = 0; + Image_Asset *image_asset = ui_find_image(widget_deimage_input->value()); + if (image_asset) { + widget_deimage_input->value(image_asset->filename()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->inactive_name(image_asset->filename()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + } +}} tooltip {Click to choose the inactive image.} xywh {295 90 89 20} labelsize 11 } } @@ -568,12 +753,38 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 15 t } Fl_Group {} { label {Position:} - callback position_group_cb open + callback position_group_cb xywh {95 150 314 20} labelfont 1 labelsize 11 align 4 } { Fl_Input widget_x_input { label {X:} - callback x_cb + callback {if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->x()); + o->activate(); + } else o->deactivate(); +} else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(v, w->y(), w->w(), w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); // change the displayed value to the result of the last + // calculation. Keep the formula if it was not used. + } +}} tooltip {The X position of the widget as a number or formula. Formulas can be simple math, including the variables x, px, sx, cx, and i} xywh {95 150 55 20} labelsize 11 align 5 textsize 11 @@ -581,7 +792,32 @@ x, px, sx, cx, and i} xywh {95 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Input widget_y_input { label {Y:} - callback y_cb + callback {if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->y()); + o->activate(); + } else o->deactivate(); +} else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), v, w->w(), w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } +}} tooltip {The Y position of the widget as a number or formula. Formulas can be simple math, including the variables y, py, sy, cy, and i} xywh {155 150 55 20} labelsize 11 align 5 textsize 11 @@ -589,7 +825,32 @@ y, py, sy, cy, and i} xywh {155 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Input widget_w_input { label {Width:} - callback w_cb + callback {if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->w()); + o->activate(); + } else o->deactivate(); +} else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), w->y(), v, w->h()); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } +}} tooltip {The width of the widget as a number or formula. Formulas can be simple math, including the variables w, pw, sw, cw, and i} xywh {215 150 55 20} labelsize 11 align 5 textsize 11 @@ -597,7 +858,32 @@ w, pw, sw, cw, and i} xywh {215 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Input widget_h_input { label {Height:} - callback h_cb + callback {if (v == LOAD) { + if (current_widget->is_true_widget()) { + o->value(((Widget_Node *)current_widget)->o->h()); + o->activate(); + } else o->deactivate(); +} else { + Fluid.proj.undo.checkpoint(); + widget_i = 0; + int mod = 0; + int v = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + Fl_Widget *w = q->o; + o->variables(widget_vars, q); + v = o->value(); + w->resize(w->x(), w->y(), w->w(), v); + if (w->window()) w->window()->redraw(); + widget_i++; + mod = 1; + } + } + if (mod) { + Fluid.proj.set_modflag(1); + o->value(v); + } +}} tooltip {The height of the widget as a number or formula. Formulas can be simple math, including the variables h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 @@ -605,7 +891,25 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Choice {} { label {Children:} - callback wc_relative_cb open + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Widget_Class)) { + o->show(); + o->value(((Widget_Class_Node *)current_widget)->wc_relative); + } else { + o->hide(); + } +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Widget_Class)) { + Widget_Class_Node *t = (Widget_Class_Node *)q; + t->wc_relative = o->value(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {When instantiating a widget class, the children can either be fixed in their original position, automatically be repositioned, or both repsositioned and resized to fit the container.} xywh {335 150 64 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 } { MenuItem {} { @@ -627,18 +931,84 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Group wp_gui_flexp { label {Flex Parent:} - callback flex_size_group_cb + callback {if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } +}} comment {This group is only visible if the parent is an Fl_Flex widget} xywh {95 150 314 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input widget_flex_size { label {Size:} - callback flex_size_cb + callback {if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->value(Flex_Node::size(current_widget)); + } +} else { + int mod = 0; + int new_size = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (Flex_Node::parent_is_flex(q)) { + Fl_Widget* w = (Fl_Widget*)q->o; + Fl_Flex* f = (Fl_Flex*)((Flex_Node*)q->parent)->o; + int was_fixed = f->fixed(w); + if (new_size==0) { + if (was_fixed) { + f->fixed(w, 0); + f->layout(); + widget_flex_fixed->value(0); + mod = 1; + } + } else { + int old_size = Flex_Node::size(q); + if (old_size!=new_size || !was_fixed) { + f->fixed(w, new_size); + f->layout(); + widget_flex_fixed->value(1); + mod = 1; + } + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {Fixed Width or Height for a horizontal or vertical Fl_Flex Parent.} xywh {95 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Check_Button widget_flex_fixed { label fixed - callback flex_fixed_cb + callback {if (v == LOAD) { + if (Flex_Node::parent_is_flex(current_widget)) { + o->value(Flex_Node::is_fixed(current_widget)); + } +} else { + int mod = 0; + int new_fixed = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (Flex_Node::parent_is_flex(q)) { + Fl_Widget* w = q->o; + Fl_Flex* f = (Fl_Flex*)((Flex_Node*)q->parent)->o; + int was_fixed = f->fixed(w); + if (new_fixed==0) { + if (was_fixed) { + f->fixed(w, 0); + f->layout(); + mod = 1; + } + } else { + if (!was_fixed) { + f->fixed(w, Flex_Node::size(q)); + f->layout(); + mod = 1; + } + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {If checked, the size of the widget stays fixed.} xywh {155 150 55 20} down_box DOWN_BOX labelsize 11 } Fl_Box {} { @@ -647,32 +1017,169 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Group wp_gui_values { label {Values:} - callback values_group_cb open + callback {if (v == LOAD) { + if ( current_widget->is_a(Type::Flex) + || current_widget->is_a(Type::Grid) + || current_widget->is_a(Type::Window)) + { + o->hide(); + } else { + o->show(); + propagate_load(o, v); + } +}} open xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 } { Fl_Value_Input {} { label {Size:} - callback slider_size_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Slider)) {o->deactivate(); return;} + o->activate(); + o->value(((Fl_Slider*)(current_widget->o))->slider_size()); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Slider)) { + ((Fl_Slider*)(q->o))->slider_size(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The size of the slider.} xywh {95 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Minimum:} - callback min_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->minimum()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->minimum()); + } else { + o->deactivate(); + return; + } +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->minimum(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->minimum(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The minimum value of the widget.} xywh {155 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Maximum:} - callback max_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->maximum()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->maximum()); + } else { + o->deactivate(); + return; + } +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->maximum(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->maximum(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The maximum value of the widget.} xywh {215 185 55 20} labelsize 11 align 5 value 1 textsize 11 } Fl_Value_Input {} { label {Step:} - callback step_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->step()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->step()); + } else { + o->deactivate(); + return; + } +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->step(n); + q->o->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->step(n); + q->o->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The resolution of the widget value.} xywh {275 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Value:} - callback value_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Valuator_)) { + o->activate(); + o->value(((Fl_Valuator*)(current_widget->o))->value()); + } else if (current_widget->is_button()) { + o->activate(); + o->value(((Fl_Button*)(current_widget->o))->value()); + } else if (current_widget->is_a(Type::Spinner)) { + o->activate(); + o->value(((Fl_Spinner*)(current_widget->o))->value()); + } else + o->deactivate(); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + double n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Valuator_)) { + ((Fl_Valuator*)(q->o))->value(n); + mod = 1; + } else if (q->is_button()) { + ((Fl_Button*)(q->o))->value(n != 0); + if (q->is_a(Type::Menu_Item)) q->redraw(); + mod = 1; + } else if (q->is_a(Type::Spinner)) { + ((Fl_Spinner*)(q->o))->value(n); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The current widget value.} xywh {335 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Box {} { @@ -681,33 +1188,128 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Group wp_gui_margins { label {Margins:} - callback flex_margin_group_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Flex)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } +}} comment {This group is only visible for Fl_Flex widgets} xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input {} { label {Left:} - callback flex_margin_left_cb + callback {flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(&v, nullptr, nullptr, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=l) { + w->margin(new_value, t, r, b); + return 1; + } else { + return 0; + } + } +);} tooltip {Left margin in group.} xywh {95 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Top:} - callback flex_margin_top_cb + callback {flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, &v, nullptr, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=t) { + w->margin(l, new_value, r, b); + return 1; + } else { + return 0; + } + } +);} tooltip {Top margin in group.} xywh {155 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Right:} - callback flex_margin_right_cb + callback {flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, nullptr, &v, nullptr); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=r) { + w->margin(l, t, new_value, b); + return 1; + } else { + return 0; + } + } +);} tooltip {Right margin in group.} xywh {215 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Bottom:} - callback flex_margin_bottom_cb + callback {flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* i) -> void + { + int v; + w->margin(nullptr, nullptr, nullptr, &v); + i->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int l, t, r, b; + w->margin(&l, &t, &r, &b); + if (new_value!=b) { + w->margin(l, t, r, new_value); + return 1; + } else { + return 0; + } + } +);} tooltip {Bottom margin in group.} xywh {275 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Value_Input {} { label {Gap:} - callback flex_margin_gap_cb + callback {flex_margin_cb(o, v, + [](Fl_Flex *w, Fl_Value_Input* o) -> void + { + int v = w->gap(); + o->value((double)v); + }, + [](Fl_Flex *w, int new_value) -> int + { + int g = w->gap(); + if (new_value!=g) { + w->gap(new_value); + return 1; + } else { + return 0; + } + } +);} tooltip {Gap between children.} xywh {335 185 55 20} labelsize 11 align 5 textsize 11 } Fl_Box {} { @@ -716,35 +1318,126 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Group wp_gui_sizerange { label {Size Range:} - callback size_range_group_cb open + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Window)) { + o->show(); + propagate_load(o, v); + } else { + o->hide(); + } +}} xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide } { Fl_Value_Input {} { label {Minimum Size:} - callback min_w_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_min_w); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_min_w = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The size of the slider.} xywh {95 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Value_Input {} { - callback min_h_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_min_h); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_min_h = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The minimum value of the widget.} xywh {155 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Button {} { label set - callback set_min_size_cb + callback {if (v == LOAD) { +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + Window_Node *win = (Window_Node*)q; + win->sr_min_w = win->o->w(); + win->sr_min_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) Fluid.proj.set_modflag(1); +}} xywh {215 185 25 20} labelsize 11 } Fl_Value_Input {} { label {Maximum Size:} - callback max_w_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_max_w); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_max_w = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The maximum value of the widget.} xywh {245 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Value_Input {} { - callback max_h_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) return; + o->value(((Window_Node*)current_widget)->sr_max_h); +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + int n = (int)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + ((Window_Node*)q)->sr_max_h = n; + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The resolution of the widget value.} xywh {305 185 55 20} labelsize 11 align 5 maximum 2048 step 1 textsize 11 } Fl_Button {} { label set - callback set_max_size_cb + callback {if (v == LOAD) { +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + Window_Node *win = (Window_Node*)q; + win->sr_max_w = win->o->w(); + win->sr_max_h = win->o->h(); + mod = 1; + } + } + propagate_load(the_panel, LOAD); + if (mod) Fluid.proj.set_modflag(1); +}} xywh {365 185 25 20} labelsize 11 } Fl_Box {} { @@ -753,11 +1446,51 @@ h, ph, sh, ch, and i} xywh {275 150 55 20} labelsize 11 align 5 textsize 11 } Fl_Group {} { label {Shortcut:} - callback propagate_load open + callback propagate_load xywh {95 210 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Button wp_gui_shortcut { - callback shortcut_in_cb + callback {if (v == LOAD) { + if (current_widget->is_button()) + o->value( ((Fl_Button*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Input)) + o->value( ((Fl_Input_*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Value_Input)) + o->value( ((Fl_Value_Input*)(current_widget->o))->shortcut() ); + else if (current_widget->is_a(Type::Text_Display)) + o->value( ((Fl_Text_Display*)(current_widget->o))->shortcut() ); + else { + o->hide(); + o->parent()->hide(); + return; + } + //i->default_value( i->value() ); // enable the "undo" capability of the shortcut button + o->show(); + o->parent()->show(); + o->redraw(); +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) + if (q->is_button()) { + Fl_Button* b = (Fl_Button*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + if (q->is_a(Type::Menu_Item)) q->redraw(); + } else if (q->is_a(Type::Input)) { + Fl_Input_* b = (Fl_Input_*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } else if (q->is_a(Type::Value_Input)) { + Fl_Value_Input* b = (Fl_Value_Input*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } else if (q->is_a(Type::Text_Display)) { + Fl_Text_Display* b = (Fl_Text_Display*)(q->o); + if (b->shortcut() != (int)o->value()) mod = 1; + b->shortcut(o->value()); + } + if (mod) Fluid.proj.set_modflag(1); +}} comment {This is a special button that grabs keystrokes directly} tooltip {The shortcut key for the widget. Use 'Backspace' key to clear.} xywh {95 210 310 20} box DOWN_BOX color 7 selection_color 12 labelsize 11 when 1 @@ -772,22 +1505,67 @@ Use 'Backspace' key to clear.} xywh {95 210 310 20} box DOWN_BOX color 7 selecti } { Fl_Input {} { label {:} - callback xclass_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Window)) { + o->show(); + o->parent()->show(); + o->value(((Window_Node *)current_widget)->xclass); + } else { + o->hide(); + o->parent()->hide(); // hides the "X Class:" label as well + } +} else { + int mod = 0; + Fluid.proj.undo.checkpoint(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Window)) { + mod = 1; + Window_Node *wt = (Window_Node *)q; + storestring(o->value(), wt->xclass); + ((Fl_Window*)(wt->o))->xclass(wt->xclass); + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The X resource class.} xywh {95 235 95 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Light_Button {} { label Border - callback border_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Fl_Window*)(current_widget->o))->border()); +} else { + Fluid.proj.undo.checkpoint(); + ((Fl_Window*)(current_widget->o))->border(o->value()); + Fluid.proj.set_modflag(1); +}} tooltip {Add a border around the window.} xywh {195 235 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Modal - callback modal_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Window_Node *)current_widget)->modal); +} else { + Fluid.proj.undo.checkpoint(); + ((Window_Node *)current_widget)->modal = o->value(); + Fluid.proj.set_modflag(1); +}} tooltip {Make the window modal.} xywh {260 235 55 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Nonmodal - callback non_modal_cb + callback {if (v == LOAD) { + if (!current_widget->is_a(Type::Window)) {o->hide(); return;} + o->show(); + o->value(((Window_Node *)current_widget)->non_modal); +} else { + Fluid.proj.undo.checkpoint(); + ((Window_Node *)current_widget)->non_modal = o->value(); + Fluid.proj.set_modflag(1); +}} tooltip {Make the window non-modal.} xywh {320 235 75 20} selection_color 1 labelsize 11 align 148 } } @@ -798,22 +1576,96 @@ Use 'Backspace' key to clear.} xywh {95 210 310 20} box DOWN_BOX color 7 selecti } { Fl_Light_Button {} { label Visible - callback visible_cb + callback {if (v == LOAD) { + o->value(current_widget->o->visible()); + if (current_widget->is_a(Type::Window)) o->deactivate(); + else o->activate(); +} else { + int mod = 0; + int n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + n ? q->o->show() : q->o->hide(); + q->redraw(); + if (n && q->parent && q->parent->type_name()) { + if (q->parent->is_a(Type::Tabs)) { + ((Fl_Tabs *)q->o->parent())->value(q->o); + } else if (q->parent->is_a(Type::Wizard)) { + ((Fl_Wizard *)q->o->parent())->value(q->o); + } + } + } + if (mod) { + Fluid.proj.set_modflag(1); + redraw_browser(); + } +}} tooltip {Show the widget.} xywh {95 260 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Active - callback active_cb + callback {if (v == LOAD) { + o->value(current_widget->o->active()); + if (current_widget->is_a(Type::Window)) o->deactivate(); + else o->activate(); +} else { + int mod = 0; + int n = o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + n ? q->o->activate() : q->o->deactivate(); + q->redraw(); + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {Activate the widget.} xywh {160 260 60 20} selection_color 1 labelsize 11 } Fl_Light_Button {} { label Resizable - callback resizable_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} + if (numselected > 1) {o->deactivate(); return;} + o->activate(); + o->value(current_widget->resizable()); +} else { + Fluid.proj.undo.checkpoint(); + current_widget->resizable(o->value()); + Fluid.proj.set_modflag(1); +}} tooltip {Make the widget resizable.} xywh {225 260 75 20} selection_color 1 labelsize 11 when 1 } Fl_Light_Button {} { label Hotspot - callback hotspot_cb + callback {if (v == LOAD) { + if (numselected > 1) {o->deactivate(); return;} + if (current_widget->is_a(Type::Menu_Item)) o->label("divider"); + else o->label("hotspot"); + o->activate(); + o->value(current_widget->hotspot()); +} else { + Fluid.proj.undo.checkpoint(); + current_widget->hotspot(o->value()); + if (current_widget->is_a(Type::Menu_Item)) { + current_widget->redraw(); + return; + } + if (o->value()) { + Node *p = current_widget->parent; + if (!p || !p->is_widget()) return; + while (!p->is_a(Type::Window)) p = p->parent; + for (Node *q = p->next; q && q->level > p->level; q = q->next) { + if (q->is_widget() && q != current_widget) + ((Widget_Node*)q)->hotspot(0); + } + } + Fluid.proj.set_modflag(1); +}} tooltip {Center the window under this widget.} xywh {305 260 70 20} selection_color 1 labelsize 11 when 1 } Fl_Box {} { @@ -822,7 +1674,21 @@ Use 'Backspace' key to clear.} xywh {95 210 310 20} box DOWN_BOX color 7 selecti } Fl_Input wp_gui_tooltip { label {Tooltip:} - callback tooltip_cb + callback {if (v == LOAD) { + if (current_widget->is_widget()) { + o->activate(); + o->value(((Widget_Node*)current_widget)->tooltip()); + } else { + o->deactivate(); + } +} else { + int mod = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->tooltip(o->value()); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The tooltip text for the widget. Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize 11 } @@ -841,22 +1707,69 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize xywh {99 40 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { - callback labelfont_cb open + callback {if (v == LOAD) { + int n = current_widget->o->labelfont(); + if (n > 15) n = 0; + o->value(n); +} else { + int mod = 0; + int n = o->value(); + if (n <= 0) n = Fluid.proj.layout->labelfont; + if (n <= 0) n = FL_HELVETICA; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->labelfont(n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {The style of the label text.} xywh {99 40 148 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 labelsize_cb + callback {int n; +if (v == LOAD) { + n = current_widget->o->labelsize(); +} else { + int mod = 0; + n = int(o->value()); + if (n <= 0) n = Fluid.proj.layout->labelsize; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->labelsize(n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +} +o->value(n);} tooltip {The size of the label text.} xywh {247 40 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 } Fl_Button w_labelcolor { label {Label Color} - callback labelcolor_cb + callback {Fl_Color c = current_widget->o->labelcolor(); +if (v != LOAD) { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + labelcolor_common(c); +} +o->color(c); +o->labelcolor(fl_contrast(FL_BLACK,c)); +o->redraw();} tooltip {The color of the label text.} xywh {296 40 90 20} labelsize 11 } Fl_Menu_Button {} { - callback labelcolor_menu_cb open + callback {Fl_Color c = current_widget->o->labelcolor(); +if (v != LOAD) { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + labelcolor_common(c); + w_labelcolor->color(c); + w_labelcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_labelcolor->redraw(); +}} open xywh {386 40 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} @@ -868,18 +1781,62 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize xywh {99 65 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { - callback box_cb open + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); + int n = current_widget->o->box(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < 72 /*int(sizeof(boxmenu)/sizeof(*boxmenu))*/; j++) + if (boxmenu[j].argument() == n) {o->value(j); break;} +} else { + int mod = 0; + int m = o->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->box((Fl_Boxtype)n); + q->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {The "up" box of the widget.} xywh {100 65 196 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item boxmenu[];} code1 {o->menu(boxmenu);} } {} Fl_Button w_color { label Color - callback color_cb + callback {Fl_Color c = current_widget->o->color(); +if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + } else { + o->activate(); + } +} else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + color_common(c); +} +o->color(c); +o->labelcolor(fl_contrast(FL_BLACK,c)); +o->redraw();} tooltip {The background color of the widget.} xywh {296 65 90 20} labelsize 11 } Fl_Menu_Button {} { - callback color_menu_cb open + callback {Fl_Color c = current_widget->o->color(); +if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); +} else { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + color_common(c); + w_color->color(c); + w_color->labelcolor(fl_contrast(FL_BLACK,c)); + w_color->redraw(); +}} open xywh {386 65 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} @@ -891,18 +1848,83 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize xywh {99 90 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { - callback down_box_cb open + callback {if (v == LOAD) { + int n; + if (current_widget->is_a(Type::Button)) + n = ((Fl_Button*)(current_widget->o))->down_box(); + else if (current_widget->is_a(Type::Input_Choice)) + n = ((Fl_Input_Choice*)(current_widget->o))->down_box(); + else if (current_widget->is_a(Type::Menu_Manager_)) + n = ((Fl_Menu_*)(current_widget->o))->down_box(); + else { + o->deactivate(); return; + } + o->activate(); + if (!n) n = ZERO_ENTRY; + for (int j = 0; j < 72 /*int(sizeof(boxmenu)/sizeof(*boxmenu))*/; j++) + if (boxmenu[j].argument() == n) {o->value(j); break;} +} else { + int mod = 0; + int m = o->value(); + int n = int(boxmenu[m].argument()); + if (!n) return; // should not happen + if (n == ZERO_ENTRY) n = 0; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Button)) { + ((Fl_Button*)(q->o))->down_box((Fl_Boxtype)n); + if (((Fl_Button*)(q->o))->value()) q->redraw(); + } else if (q->is_a(Type::Input_Choice)) { + ((Fl_Input_Choice*)(q->o))->down_box((Fl_Boxtype)n); + } else if (q->is_a(Type::Menu_Manager_)) { + ((Fl_Menu_*)(q->o))->down_box((Fl_Boxtype)n); + } + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {The "down" box of the widget.} xywh {99 90 197 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 textsize 11 resizable code0 {extern Fl_Menu_Item boxmenu[];} code1 {o->menu(boxmenu);} } {} Fl_Button w_selectcolor { label {Select Color} - callback color2_cb + callback {Fl_Color c = current_widget->o->selection_color(); +if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + return; + } else { + o->activate(); + } +} else { + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + color2_common(c); +} +o->color(c); +o->labelcolor(fl_contrast(FL_BLACK,c)); +o->redraw();} tooltip {The selection color of the widget.} xywh {296 90 90 20} labelsize 11 } Fl_Menu_Button {} { - callback color2_menu_cb open + callback {Fl_Color c = current_widget->o->selection_color(); +if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + return; + } else { + o->activate(); + } +} else { + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + color2_common(c); + w_selectcolor->color(c); + w_selectcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_selectcolor->redraw(); +}} open xywh {386 90 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} @@ -914,22 +1936,86 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize xywh {99 115 305 20} labelfont 1 labelsize 11 align 4 } { Fl_Choice {} { - callback textfont_cb open + callback {Fl_Font n; int s; Fl_Color c; +if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {o->deactivate(); return;} + o->activate(); + if (n > 15) n = FL_HELVETICA; + o->value(n); +} else { + int mod = 0; + n = (Fl_Font)o->value(); + if (n <= 0) n = Fluid.proj.layout->textfont; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->textstuff(1,n,s,c); + q->o->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {The value text style.} xywh {99 115 148 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 textsize_cb + callback {Fl_Font n; int s; Fl_Color c; +if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) {o->deactivate(); return;} + o->activate(); +} else { + int mod = 0; + s = int(o->value()); + if (s <= 0) s = Fluid.proj.layout->textsize; + if (s <= 0) s = Fluid.proj.layout->labelsize; + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->textstuff(2,n,s,c); + q->o->redraw(); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +} +o->value(s);} tooltip {The value text size.} xywh {247 115 49 20} labelsize 11 maximum 100 step 1 value 14 textsize 11 } Fl_Button w_textcolor { label {Text Color} - callback textcolor_cb + callback {Fl_Font n; int s; Fl_Color c; +if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) { + o->deactivate(); + return; + } + o->activate(); +} else { + c = o->color(); + Fl_Color d = fl_show_colormap(c); + if (d == c) return; + c = d; + textcolor_common(c); +} +o->color(c); +o->labelcolor(fl_contrast(FL_BLACK,c)); +o->redraw();} tooltip {The value text color.} xywh {296 115 90 20} labelsize 11 } Fl_Menu_Button {} { - callback textcolor_menu_cb open + callback {Fl_Font n; int s; Fl_Color c; +if (v == LOAD) { + if (!current_widget->textstuff(0,n,s,c)) { + o->deactivate(); + return; + } + o->activate(); +} else { + c = o->color(); + Fl_Color d = (Fl_Color)(o->mvalue()->argument()); + if (d == c) return; + c = d; + textcolor_common(c); + w_textcolor->color(c); + w_textcolor->labelcolor(fl_contrast(FL_BLACK,c)); + w_textcolor->redraw(); +}} open xywh {386 115 18 20} code0 {extern Fl_Menu_Item colormenu[];} code1 {o->menu(colormenu);} @@ -942,17 +2028,89 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize } { Fl_Value_Input {} { label {Horizontal:} - callback h_label_margin_cb + callback {int s; +if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->horizontal_label_margin()); + } +} else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->horizontal_label_margin() != s) { + q->o->horizontal_label_margin(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {Spacing between label and the horizontally aligned side of the widget.} xywh {99 150 55 20} labelsize 11 align 5 minimum -127 maximum 128 step 1 textsize 11 } Fl_Value_Input {} { label {Vertical:} - callback v_label_margin_cb + callback {int s; +if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->vertical_label_margin()); + } +} else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->vertical_label_margin() != s) { + q->o->vertical_label_margin(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {Spacing between label and the vertically aligned side of the widget.} xywh {159 150 55 20} labelsize 11 align 5 minimum -127 maximum 127 step 1 textsize 11 } Fl_Value_Input {} { - label {Text to Image:} - callback image_spacing_cb + label {Image Gap:} + callback {int s; +if (v == LOAD) { + if (!current_widget->is_true_widget()) { + o->deactivate(); + o->value(0); + } else { + o->activate(); + o->value(((Widget_Node*)current_widget)->o->label_image_spacing()); + } +} else { + int mod = 0; + s = int(o->value()); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_true_widget()) { + if (q->o->label_image_spacing() != s) { + q->o->label_image_spacing(s); + if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window()) + q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels + q->o->redraw(); + mod = 1; + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {Gap between label image and text in pixels} xywh {219 150 55 20} labelsize 11 align 5 maximum 255 step 1 textsize 11 } Fl_Box {} { @@ -961,7 +2119,33 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize } Fl_Light_Button {} { label Compact - callback compact_cb + callback {if (v == LOAD) { + uchar n; + if (current_widget->is_a(Type::Button) && !current_widget->is_a(Type::Menu_Item)) { + n = ((Fl_Button*)(current_widget->o))->compact(); + o->value(n); + o->show(); + } else { + o->hide(); + } +} else { + int mod = 0; + uchar n = (uchar)o->value(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->is_a(Type::Button) && !q->is_a(Type::Menu_Item)) { + uchar v = ((Fl_Button*)(q->o))->compact(); + if (n != v) { + if (!mod) { + mod = 1; + Fluid.proj.undo.checkpoint(); + } + ((Fl_Button*)(q->o))->compact(n); + q->redraw(); + } + } + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {use compact box types for closely set buttons} xywh {99 175 90 20} selection_color 1 labelsize 11 } Fl_Box {} { @@ -970,7 +2154,7 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize } Fl_Group wp_cpp_tab { label {C++} - callback propagate_load open + callback propagate_load xywh {10 30 400 330} labelsize 11 when 0 hide } { Fl_Group wp_cpp_class { @@ -980,25 +2164,120 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize } { Fl_Input {} { user_data 4 - callback subclass_cb + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) { + o->deactivate(); + } else { + o->activate(); + o->value(current_widget->subclass()); + } + } else { + int mod = 0; + const char *c = o->value(); + for (Widget_Node *t: Fluid.proj.tree.all_selected_widgets()) { + t->subclass(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + }} tooltip {The widget subclass.} xywh {95 40 172 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } Fl_Choice {} { - callback subtype_cb open + callback {static Fl_Menu_Item empty_type_menu[] = { + {"Normal",0,nullptr,(void*)nullptr}, + {nullptr}}; + + if (v == LOAD) { + Fl_Menu_Item* m = current_widget->subtypes(); + if (!m) { + o->menu(empty_type_menu); + o->value(0); + o->deactivate(); + } else { + o->menu(m); + int j; + for (j = 0;; j++) { + if (!m[j].text) {j = 0; break;} + if (current_widget->is_a(Type::Spinner)) { + if (m[j].argument() == ((Fl_Spinner*)current_widget->o)->type()) break; + } else { + if (m[j].argument() == current_widget->o->type()) break; + } + } + o->value(j); + o->activate(); + } + o->redraw(); + } else { + int mod = 0; + int n = int(o->mvalue()->argument()); + Fl_Menu_Item* m = current_widget->subtypes(); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + if (q->subtypes()==m) { + if (q->is_a(Type::Spinner)) + ((Fl_Spinner*)q->o)->type(n); + else if (q->is_a(Type::Flex)) + ((Flex_Node*)q)->change_subtype_to(n); + else + q->o->type(n); + q->redraw(); + mod = 1; + } + } + if (mod) Fluid.proj.set_modflag(1); + }} open tooltip {The widget subtype.} xywh {267 40 138 20} box THIN_UP_BOX down_box BORDER_BOX labelsize 11 textsize 11 } {} } Fl_Group wp_cpp_name { label {Name:} - callback propagate_load + callback propagate_load open xywh {95 65 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { - callback name_cb + callback {if (v == LOAD) { + static char buf[1024]; + if (numselected != 1) { + snprintf(buf, sizeof(buf), "Widget Properties (%d widgets)", numselected); + o->hide(); + } else { + o->value(current_widget->name()); + o->show(); + snprintf(buf, sizeof(buf), "%s Properties", current_widget->title()); + } + + the_panel->label(buf); + } else { + if (numselected == 1) { + current_widget->name(o->value()); + // I don't update window title, as it probably is being closed + // and wm2 (a window manager) barfs if you retitle and then + // hide a window: + // ((Fl_Window*)(o->parent()->parent()->parent()))->label(current_widget->title()); + } + }} tooltip {The name of the widget.} xywh {95 65 235 20} labelfont 1 labelsize 11 textsize 11 resizable } Fl_Choice {} { - callback name_public_member_cb open + callback {if (v == LOAD) { + o->value(current_widget->public_); + if (current_widget->is_in_class()) o->show(); else o->hide(); +} else { + int mod = 0; + for (Widget_Node *w: Fluid.proj.tree.all_selected_widgets()) { + if (w->is_in_class()) { + w->public_ = o->value(); + } else { + // if this is not in a class, it can be only private or public + w->public_ = (o->value()>0); + } + mod = 1; + } + if (mod) { + Fluid.proj.set_modflag(1); + redraw_browser(); + } +}} open tooltip {Change member access attribute.} xywh {330 65 75 20} down_box BORDER_BOX labelsize 11 when 1 textsize 11 } { MenuItem {} { @@ -1036,22 +2315,35 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize Fl_Input {v_input[0]} { label {Extra Code:} user_data 0 - callback v_input_cb + callback {int n = fl_int(o->user_data()); + if (v == LOAD) { + o->value(current_widget->extra_code(n)); + } else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c&&c[0]=='\#' ? c+1 : c); + if (d) {fl_message("Error in %s: %s",o->label(),d); haderror = 1; return;} + for (Widget_Node *w: Fluid.proj.tree.all_selected_widgets()) { + w->extra_code(n,c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + }} tooltip {Extra initialization code for the widget.} xywh {95 90 310 20} labelfont 1 labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[1]} { user_data 1 - callback v_input_cb + callback {cb_v_input(o, v);} tooltip {Extra initialization code for the widget.} xywh {95 110 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[2]} { user_data 2 - callback v_input_cb + callback {cb_v_input(o, v);} tooltip {Extra initialization code for the widget.} xywh {95 130 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Input {v_input[3]} { user_data 3 - callback v_input_cb + callback {cb_v_input(o, v);} tooltip {Extra initialization code for the widget.} xywh {95 150 310 20} labelsize 11 textfont 4 textsize 11 } Fl_Tile {} { @@ -1064,9 +2356,21 @@ wCallback->do_callback(wCallback, v);} open } { Fl_Text_Editor wComment { label {Comment:} + callback {if (v == LOAD) { + const char *cmttext = current_widget->comment(); + o->buffer()->text( cmttext ? cmttext : "" ); + } else { + int mod = 0; + char *c = o->buffer()->text(); + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->comment(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + free(c); + }} tooltip {Write a comment that will appear in the source code and in the widget tree overview.} xywh {95 175 310 45} box DOWN_BOX labelfont 1 labelsize 11 align 4 when 1 textfont 6 textsize 11 textcolor 59 resizable code0 {wComment->buffer(new Fl_Text_Buffer());} - code1 {wComment->callback((Fl_Callback*)comment_cb);} } } Fl_Group {} {open @@ -1074,7 +2378,25 @@ wCallback->do_callback(wCallback, v);} open } { Fl_Text_Editor wCallback { label {Callback:} - callback callback_cb + callback {if (v == LOAD) { + const char *cbtext = current_widget->callback(); + o->buffer()->text( cbtext ? cbtext : "" ); + } else { + int mod = 0; + char *c = o->buffer()->text(); + const char *d = c_check(c); + if (d) { + fl_message("Error in callback: %s",d); + if (o->window()) o->window()->make_current(); + haderror = 1; + } + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->callback(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); + free(c); + }} tooltip {The callback function or code for the widget. Use the variable name 'o' to access the Widget pointer and 'v' to access the user value.} xywh {95 225 310 80} box DOWN_BOX labelfont 1 labelsize 11 align 4 textfont 4 textsize 11 resizable code0 {\#include "widgets/Code_Editor.h"} class {fld::widget::Code_Editor} @@ -1087,12 +2409,48 @@ wCallback->do_callback(wCallback, v);} open xywh {95 310 310 20} labelfont 1 labelsize 11 align 4 } { Fl_Input {} { - callback user_data_cb + callback {if (v == LOAD) { + o->value(current_widget->user_data()); +} else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c); + if (d) {fl_message("Error in user_data: %s",d); haderror = 1; return;} + for (Node *n: Fluid.proj.tree.all_selected_nodes()) { + n->user_data(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} tooltip {The user data to pass into the callback code.} xywh {95 310 158 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } Fl_Menu_Button {} { label When - callback when_cb open + callback {if (v == LOAD) { + if (current_widget->is_a(Type::Menu_Item)) {o->deactivate(); return;} else o->activate(); + int n = current_widget->o->when(); + set_whenmenu(n); + w_when_box->copy_label(when_symbol_name(n)); +} else { + int mod = 0; + int n = 0; + if (o->mvalue() && ((o->mvalue()->flags & FL_MENU_TOGGLE) == 0) ) { + n = (int)o->mvalue()->argument(); + set_whenmenu(n); + } else { + if (whenmenu[0].value()) n |= FL_WHEN_CHANGED; + if (whenmenu[1].value()) n |= FL_WHEN_NOT_CHANGED; + if (whenmenu[2].value()) n |= FL_WHEN_RELEASE; + if (whenmenu[3].value()) n |= FL_WHEN_ENTER_KEY; + if (whenmenu[4].value()) n |= FL_WHEN_CLOSED; + } + w_when_box->copy_label(when_symbol_name(n)); + for (Widget_Node *q: Fluid.proj.tree.all_selected_widgets()) { + q->o->when(n); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {When to call the callback function.} xywh {260 310 145 20} box THIN_UP_BOX down_box BORDER_BOX labelfont 1 labelsize 11 when 1 textsize 11 code0 {extern Fl_Menu_Item whenmenu[];} code1 {o->menu(whenmenu);} @@ -1104,7 +2462,28 @@ wCallback->do_callback(wCallback, v);} open xywh {95 332 310 26} labelfont 1 labelsize 11 align 4 } { Fl_Input_Choice {} { - callback user_data_type_cb open + callback {static const char *dflt = "void*"; +if (v == LOAD) { + const char *c = current_widget->user_data_type(); + if (!c) c = dflt; + o->value(c); +} else { + int mod = 0; + const char *c = o->value(); + const char *d = c_check(c); + if (!*c) o->value(dflt); + else if (!strcmp(c,dflt)) c = nullptr; + if (!d) { + if (c && *c && c[strlen(c)-1] != '*' && strcmp(c,"long")) + d = "must be pointer or long"; + } + if (d) {fl_message("Error in type: %s",d); haderror = 1; return;} + for (Node *q: Fluid.proj.tree.all_selected_nodes()) { + q->user_data_type(c); + mod = 1; + } + if (mod) Fluid.proj.set_modflag(1); +}} open tooltip {The type of the user data.} xywh {95 335 158 20} labelfont 1 labelsize 11 textfont 4 textsize 11 resizable } { MenuItem {} { @@ -1122,720 +2501,18 @@ wCallback->do_callback(wCallback, v);} open } } } - Fl_Group widget_tab_grid_child { - label {Grid Child} - callback propagate_load open - xywh {10 30 400 330} labelsize 11 hide - } { - Fl_Group {} { - label {Location:} - callback propagate_load open - xywh {95 60 315 20} box FLAT_BOX labelfont 1 labelsize 11 align 4 - } { - Fl_Input widget_grid_row_input { - label {Row:} - callback grid_set_row_cb - xywh {95 60 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {135 60 30 20} - } { - Fl_Button {} { - label {-} - callback grid_dec_row_cb - xywh {135 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback grid_inc_row_cb - xywh {150 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Input widget_grid_col_input { - label {Column:} - callback grid_set_col_cb - xywh {175 60 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {215 60 30 20} - } { - Fl_Button {} { - label {-} - callback grid_dec_col_cb - xywh {215 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback grid_inc_col_cb - xywh {230 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Box {} { - xywh {395 60 1 20} hide resizable - } - Fl_Box widget_grid_transient { - label TRANSIENT - callback {if (v==LOAD) { - Fl_Widget *child = ((Fl_Widget_Type*)current_widget)->o; - Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Fl_Widget_Type*)current_widget->parent)->o); -// Fl_Grid::Cell *cell = g->cell(child); -// Fl_Grid::Cell *tcell = g->transient_cell(child); - widget_grid_transient->hide(); - widget_grid_unlinked->hide(); - if (g->transient_cell(child)) { - widget_grid_transient->show(); - } else if (!g->cell(child)) { - widget_grid_unlinked->show(); - } -}} - xywh {250 60 80 20} labelsize 11 labelcolor 1 - } - Fl_Box widget_grid_unlinked { - label UNLINKED - xywh {250 60 80 20} labelsize 11 labelcolor 1 hide - } - } - Fl_Group wp_gridc_align { - label {Align:} - callback propagate_load open - xywh {95 100 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Choice {} { - label Horizontal - callback grid_align_horizontal_cb open - xywh {95 100 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 - } { - MenuItem GRID_LEFT { - label GRID_LEFT - user_data {(fl_intptr_t)FL_GRID_LEFT} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_CENTER - user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_RIGHT - user_data {(fl_intptr_t)FL_GRID_RIGHT} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_FILL - user_data {(fl_intptr_t)FL_GRID_HORIZONTAL} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - } - Fl_Choice {} { - label Vertical - callback grid_align_vertical_cb open - xywh {215 100 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 - } { - MenuItem {} { - label GRID_TOP - user_data {(fl_intptr_t)FL_GRID_TOP} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_CENTER - user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_BOTTOM - user_data {(fl_intptr_t)FL_GRID_BOTTOM} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - MenuItem {} { - label GRID_FILL - user_data {(fl_intptr_t)FL_GRID_VERTICAL} user_data_type long - xywh {10 10 31 20} labelsize 11 - } - } - Fl_Box {} { - xywh {395 100 1 20} hide resizable - } - } - Fl_Group wp_gridc_size { - label {Min. Size:} - callback propagate_load open - xywh {95 135 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Input {} { - label {Width:} - callback grid_set_min_wdt_cb - xywh {95 135 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Input {} { - label {Height:} - callback grid_set_min_hgt_cb - xywh {155 135 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Box {} { - xywh {395 135 1 20} hide resizable - } - } - Fl_Group {} { - label {Span:} - callback propagate_load open - xywh {95 170 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Input widget_grid_rowspan_input { - label {Row Span:} - callback grid_set_rowspan_cb - xywh {95 170 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {135 170 30 20} - } { - Fl_Button {} { - label {-} - callback grid_dec_rowspan_cb - xywh {135 170 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback grid_inc_rowspan_cb - xywh {150 170 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Input widget_grid_colspan_input { - label {Col. Span:} - callback grid_set_colspan_cb - xywh {175 170 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {215 170 30 20} - } { - Fl_Button {} { - label {-} - callback grid_dec_colspan_cb - xywh {215 170 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback grid_inc_colspan_cb - xywh {230 170 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Box {} { - xywh {395 170 1 20} hide resizable - } - } - Fl_Box {} { - xywh {95 350 300 5} labelsize 11 hide resizable - } - } Fl_Group widget_tab_grid { label Grid - callback propagate_load open + callback {o->callback((Fl_Callback*)propagate_load);} open xywh {10 30 400 330} labelsize 11 hide - } { - Fl_Group {} { - label {Grid Layout:} - callback propagate_load open - xywh {95 60 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Input widget_grid_rows { - label {Rows:} - callback {// grid_rows_cb -Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -if (v == LOAD) { - o->value(grid->rows()); -} else { - int m = o->value(), old_m = grid->rows(); - if (m < 1) { - m = 1; - o->value(m); - } - if (m < old_m) { - // TODO: verify that this will not unlink existings cells - // Offer a dialog with "delete children", "unlink cells", "cancel" - } - if (m != old_m) { - undo_checkpoint(); - grid->layout(m, grid->cols()); - grid->need_layout(true); - set_modflag(1); - widget_tab_grid->do_callback(widget_tab_grid, LOAD); - } -}} - tooltip {Number of horizontal rows in the Grid group} xywh {95 60 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {135 60 30 20} - } { - Fl_Button {} { - label {-} - callback {if (v != LOAD) { - widget_grid_rows->value( widget_grid_rows->value()-1 ); - widget_grid_rows->do_callback(); -}} - xywh {135 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback {if (v != LOAD) { - widget_grid_rows->value( widget_grid_rows->value()+1 ); - widget_grid_rows->do_callback(); -}} - xywh {150 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Input widget_grid_cols { - label {Columns:} - callback {// grid_rows_cb -Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -if (v == LOAD) { - o->value(grid->cols()); -} else { - int m = o->value(), old_m = grid->cols(); - if (m < 1) { - m = 1; - o->value(m); - } - if (m < old_m) { - // TODO: verify that this will not unlink existings cells - // Offer a dialog with "delete children", "unlink cells", "cancel" - } - if (m != old_m) { - undo_checkpoint(); - grid->layout(grid->rows(), m); - grid->need_layout(true); - set_modflag(1); - widget_tab_grid->do_callback(widget_tab_grid, LOAD); - } -}} - tooltip {Number of vertical columns in the Grid group} xywh {175 60 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {215 60 30 20} - } { - Fl_Button {} { - label {-} - callback {if (v != LOAD) { - widget_grid_cols->value( widget_grid_cols->value()-1 ); - widget_grid_cols->do_callback(); -}} - xywh {215 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback {if (v != LOAD) { - widget_grid_cols->value( widget_grid_cols->value()+1 ); - widget_grid_cols->do_callback(); -}} - xywh {230 60 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Box {} { - xywh {396 60 0 20} resizable - } - } - Fl_Group wp_grid_margin { - label {Margins:} - callback propagate_load open - xywh {95 100 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Value_Input {} { - label {Left:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int m = 0; -if (v == LOAD) { - grid->margin(&m, NULL, NULL, NULL); - o->value(m); -} else { - int m = (int)o->value(), old_m; - grid->margin(&old_m, NULL, NULL, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(m, -1, -1, -1); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Left margin in group.} xywh {95 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Value_Input {} { - label {Top:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int m = 0; -if (v == LOAD) { - grid->margin(NULL, &m, NULL, NULL); - o->value(m); -} else { - int m = (int)o->value(), old_m; - grid->margin(NULL, &old_m, NULL, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, m, -1, -1); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Top margin in group.} xywh {155 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Value_Input {} { - label {Right:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int m = 0; -if (v == LOAD) { - grid->margin(NULL, NULL, &m, NULL); - o->value(m); -} else { - int m = (int)o->value(), old_m; - grid->margin(NULL, NULL, &old_m, NULL); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, -1, m, -1); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Right margin in group.} xywh {215 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Value_Input {} { - label {Bottom:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int m = 0; -if (v == LOAD) { - grid->margin(NULL, NULL, NULL, &m); - o->value(m); -} else { - int m = (int)o->value(), old_m; - grid->margin(NULL, NULL, NULL, &old_m); - if (m != old_m) { - undo_checkpoint(); - grid->margin(-1, -1, -1, m); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Bottom margin in group.} xywh {275 100 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Box {} { - xywh {396 100 0 20} resizable - } - } - Fl_Group wp_grid_gaps { - label {Gaps:} - callback propagate_load open - xywh {95 135 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Value_Input {} { - label {Row:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -if (v == LOAD) { - int m = 0; - grid->gap(&m, NULL); - o->value(m); -} else { - int m = (int)o->value(), old_m, m2; - grid->gap(&old_m, &m2); - if (m != old_m) { - undo_checkpoint(); - grid->gap(m, m2); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Gap between children.} xywh {95 135 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Value_Input {} { - label {Col:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -if (v == LOAD) { - int m = 0; - grid->gap(NULL, &m); - o->value(m); -} else { - int m = (int)o->value(), old_m, m2; - grid->gap(&m2, &old_m); - if (m != old_m) { - undo_checkpoint(); - grid->gap(m2, m); - grid->need_layout(true); - set_modflag(1); - } -}} - tooltip {Gap between children.} xywh {155 135 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 - } - Fl_Box {} { - xywh {396 135 0 20} resizable - } - } - Fl_Group {} { - label {Row:} - callback {if (v == LOAD) { - Fl_Grid *grid = Fl_Grid_Type::selected(); - if (grid) - o->activate(); - else - o->deactivate(); - propagate_load(o, v); -}} open - xywh {95 175 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Input widget_grid_curr_row { - label Index - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int r = o->value(), old_r = r; -if (r < 0) r = 0; -if (r >= grid->rows()) r = grid->rows()-1; -if (r != old_r) o->value(r); -if (v == LOAD) { - // will automatically propagate -} else { - widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); -}} - xywh {95 175 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} { - callback propagate_load open - xywh {135 175 30 20} - } { - Fl_Button {} { - label {-} - callback {if (v != LOAD) { - widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); - widget_grid_curr_row->do_callback(); -}} - xywh {135 175 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback {if (v != LOAD) { - widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); - widget_grid_curr_row->do_callback(); -}} - xywh {150 175 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Box {} { - label {:} - xywh {165 175 15 20} labelsize 11 - } - Fl_Group widget_grid_curr_row_attributes { - callback propagate_load open - xywh {180 175 175 20} - } { - Fl_Input {} { - label {Height:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int r = widget_grid_curr_row->value(); -if (v == LOAD) { - o->value(grid->row_height(r)); -} else { - int h = o->value(), old_h = grid->row_height(r); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->row_height(r, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {180 175 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Input {} { - label {Weight:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int r = widget_grid_curr_row->value(); -if (v == LOAD) { - o->value(grid->row_weight(r)); -} else { - int h = o->value(), old_h = grid->row_weight(r); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->row_weight(r, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {240 175 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Input {} { - label {Gap:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int r = widget_grid_curr_row->value(); -if (v == LOAD) { - o->value(grid->row_gap(r)); -} else { - int h = o->value(), old_h = grid->row_gap(r); - if (h < -1) h = -1; - if (h != old_h) { - undo_checkpoint(); - grid->row_gap(r, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {300 175 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - } - Fl_Box {} { - xywh {400 175 1 20} hide resizable - } - } - Fl_Group {} { - label {Column:} - callback propagate_load open - xywh {95 210 315 20} labelfont 1 labelsize 11 align 4 - } { - Fl_Input widget_grid_curr_col { - label Index - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int c = o->value(), old_c = c; -if (c < 0) c = 0; -if (c >= grid->cols()) c = grid->cols()-1; -if (c != old_c) o->value(c); -if (v == LOAD) { - // will automatically propagate -} else { - widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); -}} - xywh {95 210 40 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Group {} {open - xywh {135 210 30 20} - } { - Fl_Button {} { - label {-} - callback {if (v != LOAD) { - widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); - widget_grid_curr_col->do_callback(); -}} - xywh {135 210 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - Fl_Button {} { - label {+} - callback {if (v != LOAD) { - widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); - widget_grid_curr_col->do_callback(); -}} - xywh {150 210 15 20} labelsize 11 - code0 {o->clear_visible_focus();} compact 1 - } - } - Fl_Box {} { - label {:} - xywh {165 210 15 20} labelsize 11 - } - Fl_Group widget_grid_curr_col_attributes { - callback propagate_load open - xywh {180 210 175 20} - } { - Fl_Input {} { - label {Width:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int c = widget_grid_curr_col->value(); -if (v == LOAD) { - o->value(grid->col_width(c)); -} else { - int h = o->value(), old_h = grid->col_width(c); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->col_width(c, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {180 210 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Input {} { - label {Weight:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int c = widget_grid_curr_col->value(); -if (v == LOAD) { - o->value(grid->col_weight(c)); -} else { - int h = o->value(), old_h = grid->col_weight(c); - if (h < 0) h = 0; - if (h != old_h) { - undo_checkpoint(); - grid->col_weight(c, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {240 210 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - Fl_Input {} { - label {Gap:} - callback {Fl_Grid *grid = Fl_Grid_Type::selected(); -if (!grid) return; -int c = widget_grid_curr_col->value(); -if (v == LOAD) { - o->value(grid->col_gap(c)); -} else { - int h = o->value(), old_h = grid->col_gap(c); - if (h < -1) h = -1; - if (h != old_h) { - undo_checkpoint(); - grid->col_gap(c, h); - grid->need_layout(true); - set_modflag(1); - } -}} - xywh {300 210 55 20} labelsize 11 align 5 textsize 11 - class {fld::widget::Formula_Input} - } - } - Fl_Box {} { - xywh {400 210 1 20} hide resizable - } - } - Fl_Box {} { - xywh {95 350 300 5} labelsize 11 hide resizable - } - } + class Grid_Tab + } {} + Fl_Group widget_tab_grid_child { + label {Grid Child} + callback {o->callback((Fl_Callback*)propagate_load);} open + xywh {10 30 400 330} labelsize 11 hide + class Grid_Child_Tab + } {} } Fl_Tabs widget_tabs_repo { xywh {10 10 400 350} hide diff --git a/fluid/panels/widget_panel.h b/fluid/panels/widget_panel.h index bac21a771..80ccd4171 100644 --- a/fluid/panels/widget_panel.h +++ b/fluid/panels/widget_panel.h @@ -19,7 +19,10 @@ #ifndef widget_panel_h #define widget_panel_h #include +#include "panels/widget_panel/Grid_Child_Tab.h" +#include "panels/widget_panel/Grid_Tab.h" #include "widgets/Formula_Input.h" +class Fl_Flex; #include extern Fl_Double_Window *image_panel_window; #include @@ -32,17 +35,14 @@ extern fld::widget::Formula_Input *image_panel_imagew; extern fld::widget::Formula_Input *image_panel_imageh; #include #include -extern void compress_image_cb(Fl_Check_Button*, void*); -extern void bind_image_cb(Fl_Check_Button*, void*); extern Fl_Group *image_panel_deimagegroup; extern Fl_Box *image_panel_dedata; extern fld::widget::Formula_Input *image_panel_deimagew; extern fld::widget::Formula_Input *image_panel_deimageh; -extern void compress_deimage_cb(Fl_Check_Button*, void*); -extern void bind_deimage_cb(Fl_Check_Button*, void*); extern Fl_Button *image_panel_close; Fl_Double_Window* make_image_panel(); void run_image_panel(); +void flex_margin_cb(Fl_Value_Input* i, void* v, void (*load_margin)(Fl_Flex*,Fl_Value_Input*), int (*update_margin)(Fl_Flex*,int)); #include extern Fl_Tabs *widget_tabs; extern Fl_Group *wp_gui_tab; @@ -52,159 +52,59 @@ extern Fl_Input *wp_gui_label; #include extern Fl_Menu_Item labeltypemenu[]; extern void labeltype_cb(Fl_Choice*, void*); -extern void image_cb(Fl_Input*, void*); extern Fl_Input *widget_image_input; -extern void image_browse_cb(Fl_Button*, void*); -extern void inactive_cb(Fl_Input*, void*); extern Fl_Input *widget_deimage_input; -extern void inactive_browse_cb(Fl_Button*, void*); extern Fl_Group *wp_gui_alignment; extern void align_cb(Fl_Button*, void*); extern void align_text_image_cb(Fl_Choice*, void*); extern void align_position_cb(Fl_Choice*, void*); extern void position_group_cb(Fl_Group*, void*); -extern void x_cb(fld::widget::Formula_Input*, void*); extern fld::widget::Formula_Input *widget_x_input; -extern void y_cb(fld::widget::Formula_Input*, void*); extern fld::widget::Formula_Input *widget_y_input; -extern void w_cb(fld::widget::Formula_Input*, void*); extern fld::widget::Formula_Input *widget_w_input; -extern void h_cb(fld::widget::Formula_Input*, void*); extern fld::widget::Formula_Input *widget_h_input; -extern void wc_relative_cb(Fl_Choice*, void*); -extern void flex_size_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_flexp; #include -extern void flex_size_cb(Fl_Value_Input*, void*); extern Fl_Value_Input *widget_flex_size; -extern void flex_fixed_cb(Fl_Check_Button*, void*); extern Fl_Check_Button *widget_flex_fixed; -extern void values_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_values; -extern void slider_size_cb(Fl_Value_Input*, void*); -extern void min_cb(Fl_Value_Input*, void*); -extern void max_cb(Fl_Value_Input*, void*); -extern void step_cb(Fl_Value_Input*, void*); -extern void value_cb(Fl_Value_Input*, void*); -extern void flex_margin_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_margins; -extern void flex_margin_left_cb(Fl_Value_Input*, void*); -extern void flex_margin_top_cb(Fl_Value_Input*, void*); -extern void flex_margin_right_cb(Fl_Value_Input*, void*); -extern void flex_margin_bottom_cb(Fl_Value_Input*, void*); -extern void flex_margin_gap_cb(Fl_Value_Input*, void*); -extern void size_range_group_cb(Fl_Group*, void*); extern Fl_Group *wp_gui_sizerange; -extern void min_w_cb(Fl_Value_Input*, void*); -extern void min_h_cb(Fl_Value_Input*, void*); -extern void set_min_size_cb(Fl_Button*, void*); -extern void max_w_cb(Fl_Value_Input*, void*); -extern void max_h_cb(Fl_Value_Input*, void*); -extern void set_max_size_cb(Fl_Button*, void*); #include -extern void shortcut_in_cb(Fl_Shortcut_Button*, void*); extern Fl_Shortcut_Button *wp_gui_shortcut; extern Fl_Group *wp_gui_xclass; -extern void xclass_cb(Fl_Input*, void*); #include -extern void border_cb(Fl_Light_Button*, void*); -extern void modal_cb(Fl_Light_Button*, void*); -extern void non_modal_cb(Fl_Light_Button*, void*); extern Fl_Group *wp_gui_attributes; -extern void visible_cb(Fl_Light_Button*, void*); -extern void active_cb(Fl_Light_Button*, void*); -extern void resizable_cb(Fl_Light_Button*, void*); -extern void hotspot_cb(Fl_Light_Button*, void*); -extern void tooltip_cb(Fl_Input*, void*); extern Fl_Input *wp_gui_tooltip; extern Fl_Group *wp_style_tab; extern Fl_Group *wp_style_label; extern Fl_Menu_Item fontmenu[]; -extern void labelfont_cb(Fl_Choice*, void*); -extern void labelsize_cb(Fl_Value_Input*, void*); -extern void labelcolor_cb(Fl_Button*, void*); extern Fl_Button *w_labelcolor; #include extern Fl_Menu_Item colormenu[]; -extern void labelcolor_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_box; extern Fl_Menu_Item boxmenu[]; -extern void box_cb(Fl_Choice*, void*); -extern void color_cb(Fl_Button*, void*); extern Fl_Button *w_color; -extern void color_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_downbox; -extern void down_box_cb(Fl_Choice*, void*); -extern void color2_cb(Fl_Button*, void*); extern Fl_Button *w_selectcolor; -extern void color2_menu_cb(Fl_Menu_Button*, void*); extern Fl_Group *wp_style_text; -extern void textfont_cb(Fl_Choice*, void*); -extern void textsize_cb(Fl_Value_Input*, void*); -extern void textcolor_cb(Fl_Button*, void*); extern Fl_Button *w_textcolor; -extern void textcolor_menu_cb(Fl_Menu_Button*, void*); -extern void h_label_margin_cb(Fl_Value_Input*, void*); -extern void v_label_margin_cb(Fl_Value_Input*, void*); -extern void image_spacing_cb(Fl_Value_Input*, void*); -extern void compact_cb(Fl_Light_Button*, void*); extern Fl_Group *wp_cpp_tab; extern Fl_Group *wp_cpp_class; -extern void subclass_cb(Fl_Input*, void*); -extern void subtype_cb(Fl_Choice*, void*); extern Fl_Group *wp_cpp_name; -extern void name_cb(Fl_Input*, void*); -extern void name_public_member_cb(Fl_Choice*, void*); extern void name_public_cb(Fl_Choice*, void*); -extern void v_input_cb(Fl_Input*, void*); extern Fl_Input *v_input[4]; #include #include extern Fl_Text_Editor *wComment; #include "widgets/Code_Editor.h" -extern void callback_cb(fld::widget::Code_Editor*, void*); extern fld::widget::Code_Editor *wCallback; extern Fl_Group *wp_cpp_callback; -extern void user_data_cb(Fl_Input*, void*); extern Fl_Menu_Item whenmenu[]; -extern void when_cb(Fl_Menu_Button*, void*); #include -extern void user_data_type_cb(Fl_Input_Choice*, void*); extern Fl_Box *w_when_box; -extern Fl_Group *widget_tab_grid_child; -extern void grid_set_row_cb(fld::widget::Formula_Input*, void*); -extern fld::widget::Formula_Input *widget_grid_row_input; -extern void grid_dec_row_cb(Fl_Button*, void*); -extern void grid_inc_row_cb(Fl_Button*, void*); -extern void grid_set_col_cb(fld::widget::Formula_Input*, void*); -extern fld::widget::Formula_Input *widget_grid_col_input; -extern void grid_dec_col_cb(Fl_Button*, void*); -extern void grid_inc_col_cb(Fl_Button*, void*); -extern Fl_Box *widget_grid_transient; -extern Fl_Box *widget_grid_unlinked; -extern Fl_Group *wp_gridc_align; -extern void grid_align_horizontal_cb(Fl_Choice*, void*); -extern void grid_align_vertical_cb(Fl_Choice*, void*); -extern Fl_Group *wp_gridc_size; -extern void grid_set_min_wdt_cb(fld::widget::Formula_Input*, void*); -extern void grid_set_min_hgt_cb(fld::widget::Formula_Input*, void*); -extern void grid_set_rowspan_cb(fld::widget::Formula_Input*, void*); -extern fld::widget::Formula_Input *widget_grid_rowspan_input; -extern void grid_dec_rowspan_cb(Fl_Button*, void*); -extern void grid_inc_rowspan_cb(Fl_Button*, void*); -extern void grid_set_colspan_cb(fld::widget::Formula_Input*, void*); -extern fld::widget::Formula_Input *widget_grid_colspan_input; -extern void grid_dec_colspan_cb(Fl_Button*, void*); -extern void grid_inc_colspan_cb(Fl_Button*, void*); -extern Fl_Group *widget_tab_grid; -extern fld::widget::Formula_Input *widget_grid_rows; -extern fld::widget::Formula_Input *widget_grid_cols; -extern Fl_Group *wp_grid_margin; -extern Fl_Group *wp_grid_gaps; -extern fld::widget::Formula_Input *widget_grid_curr_row; -extern Fl_Group *widget_grid_curr_row_attributes; -extern fld::widget::Formula_Input *widget_grid_curr_col; -extern Fl_Group *widget_grid_curr_col_attributes; +extern Grid_Tab *widget_tab_grid; +extern Grid_Child_Tab *widget_tab_grid_child; extern Fl_Tabs *widget_tabs_repo; extern void live_mode_cb(Fl_Button*, void*); extern Fl_Button *wLiveMode; @@ -219,7 +119,4 @@ extern Fl_Menu_Item menu_Children[]; extern Fl_Menu_Item menu_2[]; extern Fl_Menu_Item menu_3[]; extern Fl_Menu_Item menu_4[]; -extern Fl_Menu_Item menu_Horizontal[]; -#define GRID_LEFT (menu_Horizontal+0) -extern Fl_Menu_Item menu_Vertical[]; #endif diff --git a/fluid/panels/widget_panel/Grid_Child_Tab.cxx b/fluid/panels/widget_panel/Grid_Child_Tab.cxx new file mode 100644 index 000000000..b0f943803 --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Child_Tab.cxx @@ -0,0 +1,538 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0500 + +#include "Grid_Child_Tab.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "nodes/Grid_Node.h" +extern Grid_Child_Tab *widget_tab_grid_child; + +void Grid_Child_Tab::cb_widget_grid_row_input_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 8); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); +} +void Grid_Child_Tab::cb_widget_grid_row_input(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_widget_grid_row_input_i(o,v); +} + +void Grid_Child_Tab::cb__i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_row_input, v, 0x0100 + 8); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb__i(o,v); +} + +void Grid_Child_Tab::cb_1_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_row_input, v, 0x0200 + 8); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_1(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_1_i(o,v); +} + +void Grid_Child_Tab::cb_widget_grid_col_input_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 9); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); +} +void Grid_Child_Tab::cb_widget_grid_col_input(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_widget_grid_col_input_i(o,v); +} + +void Grid_Child_Tab::cb_2_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_col_input, v, 0x0100 + 9); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_2(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_2_i(o,v); +} + +void Grid_Child_Tab::cb_3_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_col_input, v, 0x0200 + 9); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_3(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_3_i(o,v); +} + +void Grid_Child_Tab::cb_widget_grid_transient_i(Fl_Box* o, void* v) { + if (v==LOAD) { + Fl_Widget *child = ((Widget_Node*)current_widget)->o; + Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Widget_Node*)current_widget->parent)->o); + // Fl_Grid::Cell *cell = g->cell(child); + // Fl_Grid::Cell *tcell = g->transient_cell(child); + widget_grid_transient->hide(); + widget_grid_unlinked->hide(); + if (g->transient_cell(child)) { + widget_grid_transient->show(); + } else if (!g->cell(child)) { + widget_grid_unlinked->show(); + } + } +} +void Grid_Child_Tab::cb_widget_grid_transient(Fl_Box* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_widget_grid_transient_i(o,v); +} + +void Grid_Child_Tab::cb_Horizontal_i(Fl_Choice* o, void* v) { + if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + int mask = (FL_GRID_LEFT | FL_GRID_RIGHT | FL_GRID_HORIZONTAL); + Fl_Grid *g = ((Fl_Grid*)((Widget_Node*)current_widget->parent)->o); + if (v == LOAD) { + int a = FL_GRID_FILL & mask; + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + a = cell->align() & mask; + } + const Fl_Menu_Item *mi = o->find_item_with_argument(a); + if (mi) o->value(mi); + } else { + Fluid.proj.undo.checkpoint(); + int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; + const Fl_Menu_Item *mi = o->mvalue(); + if (mi) v = (int)mi->argument(); + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + old_v = cell->align() & mask; + if (old_v != v) { + cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); + g->need_layout(true); + g->redraw(); + Fluid.proj.set_modflag(1); + } + } + } +} +void Grid_Child_Tab::cb_Horizontal(Fl_Choice* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_Horizontal_i(o,v); +} + +Fl_Menu_Item Grid_Child_Tab::menu_Horizontal[] = { + {"GRID_LEFT", 0, 0, (void*)((fl_intptr_t)FL_GRID_LEFT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_RIGHT", 0, 0, (void*)((fl_intptr_t)FL_GRID_RIGHT), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_HORIZONTAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; +Fl_Menu_Item* Grid_Child_Tab::GRID_LEFT = Grid_Child_Tab::menu_Horizontal + 0; + +void Grid_Child_Tab::cb_Vertical_i(Fl_Choice* o, void* v) { + if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + int mask = (FL_GRID_TOP | FL_GRID_BOTTOM | FL_GRID_VERTICAL); + Fl_Grid *g = ((Fl_Grid*)((Widget_Node*)current_widget->parent)->o); + if (v == LOAD) { + int a = FL_GRID_FILL & mask; + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + a = cell->align() & mask; + } + const Fl_Menu_Item *mi = o->find_item_with_argument(a); + if (mi) o->value(mi); + } else { + Fluid.proj.undo.checkpoint(); + int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; + const Fl_Menu_Item *mi = o->mvalue(); + if (mi) v = (int)mi->argument(); + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + old_v = cell->align() & mask; + if (old_v != v) { + cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); + g->need_layout(true); + g->redraw(); + Fluid.proj.set_modflag(1); + } + } + } +} +void Grid_Child_Tab::cb_Vertical(Fl_Choice* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_Vertical_i(o,v); +} + +Fl_Menu_Item Grid_Child_Tab::menu_Vertical[] = { + {"GRID_TOP", 0, 0, (void*)((fl_intptr_t)FL_GRID_TOP), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_CENTER", 0, 0, (void*)((fl_intptr_t)FL_GRID_CENTER), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_BOTTOM", 0, 0, (void*)((fl_intptr_t)FL_GRID_BOTTOM), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {"GRID_FILL", 0, 0, (void*)((fl_intptr_t)FL_GRID_VERTICAL), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0}, + {0,0,0,0,0,0,0,0,0} +}; + +void Grid_Child_Tab::cb_Width_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 12); +} +void Grid_Child_Tab::cb_Width(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_Width_i(o,v); +} + +void Grid_Child_Tab::cb_Height_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 13); +} +void Grid_Child_Tab::cb_Height(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_Height_i(o,v); +} + +void Grid_Child_Tab::cb_widget_grid_rowspan_input_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 10); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); +} +void Grid_Child_Tab::cb_widget_grid_rowspan_input(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_widget_grid_rowspan_input_i(o,v); +} + +void Grid_Child_Tab::cb_4_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_rowspan_input, v, 0x0100 + 10); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_4(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_4_i(o,v); +} + +void Grid_Child_Tab::cb_5_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_rowspan_input, v, 0x0200 + 10); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_5(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_5_i(o,v); +} + +void Grid_Child_Tab::cb_widget_grid_colspan_input_i(fld::widget::Formula_Input* o, void* v) { + grid_child_cb(o, v, 11); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); +} +void Grid_Child_Tab::cb_widget_grid_colspan_input(fld::widget::Formula_Input* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()))->cb_widget_grid_colspan_input_i(o,v); +} + +void Grid_Child_Tab::cb_6_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_colspan_input, v, 0x0100 + 11); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_6(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_6_i(o,v); +} + +void Grid_Child_Tab::cb_7_i(Fl_Button*, void* v) { + if (v!=LOAD) { + grid_child_cb(widget_grid_colspan_input, v, 0x0200 + 11); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + } +} +void Grid_Child_Tab::cb_7(Fl_Button* o, void* v) { + ((Grid_Child_Tab*)(o->parent()->parent()->parent()))->cb_7_i(o,v); +} + +Grid_Child_Tab::Grid_Child_Tab(int X, int Y, int W, int H, const char *L) : + Fl_Group(0, 0, 400, 330, L) +{ + this->labelsize(11); + this->callback((Fl_Callback*)propagate_load); + { Fl_Group* o = new Fl_Group(85, 30, 315, 20, "Location:"); + o->box(FL_FLAT_BOX); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(Fl_Align(FL_ALIGN_LEFT)); + { widget_grid_row_input = new fld::widget::Formula_Input(85, 30, 40, 20, "Row:"); + widget_grid_row_input->box(FL_DOWN_BOX); + widget_grid_row_input->color(FL_BACKGROUND2_COLOR); + widget_grid_row_input->selection_color(FL_SELECTION_COLOR); + widget_grid_row_input->labeltype(FL_NORMAL_LABEL); + widget_grid_row_input->labelfont(0); + widget_grid_row_input->labelsize(11); + widget_grid_row_input->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_row_input->textsize(11); + widget_grid_row_input->callback((Fl_Callback*)cb_widget_grid_row_input); + widget_grid_row_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_row_input->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_row_input + { Fl_Group* o = new Fl_Group(125, 30, 30, 20); + { Fl_Button* o = new Fl_Button(125, 30, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(140, 30, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_1); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { widget_grid_col_input = new fld::widget::Formula_Input(165, 30, 40, 20, "Column:"); + widget_grid_col_input->box(FL_DOWN_BOX); + widget_grid_col_input->color(FL_BACKGROUND2_COLOR); + widget_grid_col_input->selection_color(FL_SELECTION_COLOR); + widget_grid_col_input->labeltype(FL_NORMAL_LABEL); + widget_grid_col_input->labelfont(0); + widget_grid_col_input->labelsize(11); + widget_grid_col_input->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_col_input->textsize(11); + widget_grid_col_input->callback((Fl_Callback*)cb_widget_grid_col_input); + widget_grid_col_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_col_input->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_col_input + { Fl_Group* o = new Fl_Group(205, 30, 30, 20); + { Fl_Button* o = new Fl_Button(205, 30, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_2); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(220, 30, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_3); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(385, 30, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + { widget_grid_transient = new Fl_Box(240, 30, 80, 20, "TRANSIENT"); + widget_grid_transient->labelsize(11); + widget_grid_transient->labelcolor((Fl_Color)1); + widget_grid_transient->callback((Fl_Callback*)cb_widget_grid_transient); + } // Fl_Box* widget_grid_transient + { widget_grid_unlinked = new Fl_Box(240, 30, 80, 20, "UNLINKED"); + widget_grid_unlinked->labelsize(11); + widget_grid_unlinked->labelcolor((Fl_Color)1); + widget_grid_unlinked->hide(); + } // Fl_Box* widget_grid_unlinked + o->end(); + } // Fl_Group* o + { wp_gridc_align = new Fl_Group(85, 70, 315, 20, "Align:"); + wp_gridc_align->labelfont(1); + wp_gridc_align->labelsize(11); + wp_gridc_align->callback((Fl_Callback*)propagate_load); + wp_gridc_align->align(Fl_Align(FL_ALIGN_LEFT)); + { Fl_Choice* o = new Fl_Choice(85, 70, 115, 20, "Horizontal"); + o->down_box(FL_BORDER_BOX); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)cb_Horizontal); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->menu(menu_Horizontal); + } // Fl_Choice* o + { Fl_Choice* o = new Fl_Choice(205, 70, 115, 20, "Vertical"); + o->down_box(FL_BORDER_BOX); + o->labelsize(11); + o->textsize(11); + o->callback((Fl_Callback*)cb_Vertical); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->menu(menu_Vertical); + } // Fl_Choice* o + { Fl_Box* o = new Fl_Box(385, 70, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + wp_gridc_align->end(); + } // Fl_Group* wp_gridc_align + { wp_gridc_size = new Fl_Group(85, 105, 315, 20, "Min. Size:"); + wp_gridc_size->labelfont(1); + wp_gridc_size->labelsize(11); + wp_gridc_size->callback((Fl_Callback*)propagate_load); + wp_gridc_size->align(Fl_Align(FL_ALIGN_LEFT)); + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(85, 105, 55, 20, "Width:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Width); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(145, 105, 55, 20, "Height:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Height); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { Fl_Box* o = new Fl_Box(385, 105, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + wp_gridc_size->end(); + } // Fl_Group* wp_gridc_size + { Fl_Group* o = new Fl_Group(85, 140, 315, 20, "Span:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(Fl_Align(FL_ALIGN_LEFT)); + { widget_grid_rowspan_input = new fld::widget::Formula_Input(85, 140, 40, 20, "Row Span:"); + widget_grid_rowspan_input->box(FL_DOWN_BOX); + widget_grid_rowspan_input->color(FL_BACKGROUND2_COLOR); + widget_grid_rowspan_input->selection_color(FL_SELECTION_COLOR); + widget_grid_rowspan_input->labeltype(FL_NORMAL_LABEL); + widget_grid_rowspan_input->labelfont(0); + widget_grid_rowspan_input->labelsize(11); + widget_grid_rowspan_input->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_rowspan_input->textsize(11); + widget_grid_rowspan_input->callback((Fl_Callback*)cb_widget_grid_rowspan_input); + widget_grid_rowspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_rowspan_input->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_rowspan_input + { Fl_Group* o = new Fl_Group(125, 140, 30, 20); + { Fl_Button* o = new Fl_Button(125, 140, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_4); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(140, 140, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_5); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { widget_grid_colspan_input = new fld::widget::Formula_Input(165, 140, 40, 20, "Col. Span:"); + widget_grid_colspan_input->box(FL_DOWN_BOX); + widget_grid_colspan_input->color(FL_BACKGROUND2_COLOR); + widget_grid_colspan_input->selection_color(FL_SELECTION_COLOR); + widget_grid_colspan_input->labeltype(FL_NORMAL_LABEL); + widget_grid_colspan_input->labelfont(0); + widget_grid_colspan_input->labelsize(11); + widget_grid_colspan_input->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_colspan_input->textsize(11); + widget_grid_colspan_input->callback((Fl_Callback*)cb_widget_grid_colspan_input); + widget_grid_colspan_input->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_colspan_input->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_colspan_input + { Fl_Group* o = new Fl_Group(205, 140, 30, 20); + { Fl_Button* o = new Fl_Button(205, 140, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_6); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(220, 140, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_7); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(385, 140, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(85, 320, 300, 5); + o->labelsize(11); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + end(); + resize(X, Y, W, H); +} + +void Grid_Child_Tab::grid_child_cb(fld::widget::Formula_Input* i, void* v, int what) { + if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + Fl_Widget *child = ((Widget_Node*)current_widget)->o; + Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Widget_Node*)current_widget->parent)->o); + Fl_Grid::Cell *cell = g->any_cell(child); + if (v == LOAD) { + int v = -1; + if (cell) { + switch (what & 0x00ff) { + case 8: v = cell->row(); break; + case 9: v = cell->col(); break; + case 10: v = cell->rowspan(); break; + case 11: v = cell->colspan(); break; + case 12: cell->minimum_size(&v, nullptr); break; + case 13: cell->minimum_size(nullptr, &v); break; + } + } + i->value(v); + } else { + Fluid.proj.undo.checkpoint(); + int v2 = -2, old_v = -2, v = i->value(); + if (i==widget_grid_row_input) v2 = widget_grid_col_input->value(); + if (i==widget_grid_col_input) v2 = widget_grid_row_input->value(); + Fl_Grid::Cell *new_cell = nullptr; + if (cell) { + switch (what & 0x00ff) { + case 8: old_v = cell->row(); v2 = cell->col(); break; + case 9: old_v = cell->col(); v2 = cell->row(); break; + case 10: old_v = cell->rowspan(); break; + case 11: old_v = cell->colspan(); break; + case 12: cell->minimum_size(&old_v, &v2); break; + case 13: cell->minimum_size(&v2, &old_v); break; + } + } + switch (what & 0xff00) { + case 0x0100: v--; break; + case 0x0200: v++; break; + } + if (old_v != v) { + switch (what & 0x00ff) { + case 8: + if (v2 == -1 && v >= 0) v2 = 0; + g->move_cell(current_widget->o, v, v2, 2); i->value(v); + break; + case 9: + if (v2 == -1 && v >= 0) v2 = 0; + g->move_cell(current_widget->o, v2, v, 2); i->value(v); + break; + case 10: if (cell && cell->row()+v<=g->rows() && v>0) cell->rowspan(v); + break; + case 11: if (cell && cell->col()+v<=g->cols() && v>0) cell->colspan(v); + break; + case 12: if (cell && v>=0) cell->minimum_size(v, v2); + break; + case 13: if (cell && v>=0) cell->minimum_size(v2, v); + break; + } + if (!cell && new_cell) + new_cell->minimum_size(20, 20); + g->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} diff --git a/fluid/panels/widget_panel/Grid_Child_Tab.fl b/fluid/panels/widget_panel/Grid_Child_Tab.fl new file mode 100644 index 000000000..161eab696 --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Child_Tab.fl @@ -0,0 +1,397 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +header_name {.h} +code_name {.cxx} +decl {\#include "widgets/Formula_Input.h"} {public global +} + +decl {\#include "Fluid.h"} {private global +} + +decl {\#include "proj/undo.h"} {private global +} + +decl {\#include "nodes/Grid_Node.h"} {private global +} + +decl {extern Grid_Child_Tab *widget_tab_grid_child;} {private global +} + +widget_class Grid_Child_Tab { + label Grid + callback propagate_load open + xywh {480 287 400 330} labelsize 11 resizable visible position_relative_rescale +} { + Fl_Group {} { + label {Location:} + callback propagate_load open + xywh {85 30 315 20} box FLAT_BOX labelfont 1 labelsize 11 align 4 + } { + Fl_Input widget_grid_row_input { + label {Row:} + callback {grid_child_cb(o, v, 8); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD);} + xywh {85 30 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {125 30 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_row_input, v, 0x0100 + 8); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {125 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_row_input, v, 0x0200 + 8); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {140 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Input widget_grid_col_input { + label {Column:} + callback {grid_child_cb(o, v, 9); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD);} + xywh {165 30 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {205 30 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_col_input, v, 0x0100 + 9); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {205 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_col_input, v, 0x0200 + 9); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {220 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Box {} { + xywh {385 30 1 20} hide resizable + } + Fl_Box widget_grid_transient { + label TRANSIENT + callback {if (v==LOAD) { + Fl_Widget *child = ((Widget_Node*)current_widget)->o; + Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Widget_Node*)current_widget->parent)->o); +// Fl_Grid::Cell *cell = g->cell(child); +// Fl_Grid::Cell *tcell = g->transient_cell(child); + widget_grid_transient->hide(); + widget_grid_unlinked->hide(); + if (g->transient_cell(child)) { + widget_grid_transient->show(); + } else if (!g->cell(child)) { + widget_grid_unlinked->show(); + } +}} + xywh {240 30 80 20} labelsize 11 labelcolor 1 + } + Fl_Box widget_grid_unlinked { + label UNLINKED + xywh {240 30 80 20} labelsize 11 labelcolor 1 hide + } + } + Fl_Group wp_gridc_align { + label {Align:} + callback propagate_load + xywh {85 70 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Choice {} { + label Horizontal + callback {if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + int mask = (FL_GRID_LEFT | FL_GRID_RIGHT | FL_GRID_HORIZONTAL); + Fl_Grid *g = ((Fl_Grid*)((Widget_Node*)current_widget->parent)->o); + if (v == LOAD) { + int a = FL_GRID_FILL & mask; + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + a = cell->align() & mask; + } + const Fl_Menu_Item *mi = o->find_item_with_argument(a); + if (mi) o->value(mi); + } else { + Fluid.proj.undo.checkpoint(); + int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; + const Fl_Menu_Item *mi = o->mvalue(); + if (mi) v = (int)mi->argument(); + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + old_v = cell->align() & mask; + if (old_v != v) { + cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); + g->need_layout(true); + g->redraw(); + Fluid.proj.set_modflag(1); + } + } + }} open + xywh {85 70 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 + } { + MenuItem GRID_LEFT { + label GRID_LEFT + user_data {(fl_intptr_t)FL_GRID_LEFT} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_CENTER + user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_RIGHT + user_data {(fl_intptr_t)FL_GRID_RIGHT} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_FILL + user_data {(fl_intptr_t)FL_GRID_HORIZONTAL} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + } + Fl_Choice {} { + label Vertical + callback {if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + int mask = (FL_GRID_TOP | FL_GRID_BOTTOM | FL_GRID_VERTICAL); + Fl_Grid *g = ((Fl_Grid*)((Widget_Node*)current_widget->parent)->o); + if (v == LOAD) { + int a = FL_GRID_FILL & mask; + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + a = cell->align() & mask; + } + const Fl_Menu_Item *mi = o->find_item_with_argument(a); + if (mi) o->value(mi); + } else { + Fluid.proj.undo.checkpoint(); + int v = FL_GRID_FILL & mask, old_v = FL_GRID_FILL & mask; + const Fl_Menu_Item *mi = o->mvalue(); + if (mi) v = (int)mi->argument(); + Fl_Grid::Cell *cell = g->cell(current_widget->o); + if (cell) { + old_v = cell->align() & mask; + if (old_v != v) { + cell->align((Fl_Grid_Align)(v | (cell->align() & ~mask))); + g->need_layout(true); + g->redraw(); + Fluid.proj.set_modflag(1); + } + } + }} open selected + xywh {205 70 115 20} down_box BORDER_BOX labelsize 11 align 5 textsize 11 + } { + MenuItem {} { + label GRID_TOP + user_data {(fl_intptr_t)FL_GRID_TOP} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_CENTER + user_data {(fl_intptr_t)FL_GRID_CENTER} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_BOTTOM + user_data {(fl_intptr_t)FL_GRID_BOTTOM} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + MenuItem {} { + label GRID_FILL + user_data {(fl_intptr_t)FL_GRID_VERTICAL} user_data_type long + xywh {20 20 31 20} labelsize 11 + } + } + Fl_Box {} { + xywh {385 70 1 20} hide resizable + } + } + Fl_Group wp_gridc_size { + label {Min. Size:} + callback propagate_load + xywh {85 105 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input {} { + label {Width:} + callback {grid_child_cb(o, v, 12);} + xywh {85 105 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Input {} { + label {Height:} + callback {grid_child_cb(o, v, 13);} + xywh {145 105 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Box {} { + xywh {385 105 1 20} hide resizable + } + } + Fl_Group {} { + label {Span:} + callback propagate_load + xywh {85 140 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input widget_grid_rowspan_input { + label {Row Span:} + callback {grid_child_cb(o, v, 10); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD);} + xywh {85 140 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {125 140 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_rowspan_input, v, 0x0100 + 10); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {125 140 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_rowspan_input, v, 0x0200 + 10); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {140 140 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Input widget_grid_colspan_input { + label {Col. Span:} + callback {grid_child_cb(o, v, 11); + if (v!=LOAD) widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD);} + xywh {165 140 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {205 140 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_colspan_input, v, 0x0100 + 11); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {205 140 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v!=LOAD) { + grid_child_cb(widget_grid_colspan_input, v, 0x0200 + 11); + widget_tab_grid_child->do_callback(widget_tab_grid_child, LOAD); + }} + xywh {220 140 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Box {} { + xywh {385 140 1 20} hide resizable + } + } + Fl_Box {} { + xywh {85 320 300 5} labelsize 11 hide resizable + } + Function {grid_child_cb(fld::widget::Formula_Input* i, void* v, int what)} {open return_type void + } { + code {if ( !current_widget + || !current_widget->parent + || !current_widget->parent->is_a(Type::Grid)) + { + return; + } + Fl_Widget *child = ((Widget_Node*)current_widget)->o; + Fl_Grid_Proxy *g = ((Fl_Grid_Proxy*)((Widget_Node*)current_widget->parent)->o); + Fl_Grid::Cell *cell = g->any_cell(child); + if (v == LOAD) { + int v = -1; + if (cell) { + switch (what & 0x00ff) { + case 8: v = cell->row(); break; + case 9: v = cell->col(); break; + case 10: v = cell->rowspan(); break; + case 11: v = cell->colspan(); break; + case 12: cell->minimum_size(&v, nullptr); break; + case 13: cell->minimum_size(nullptr, &v); break; + } + } + i->value(v); + } else { + Fluid.proj.undo.checkpoint(); + int v2 = -2, old_v = -2, v = i->value(); + if (i==widget_grid_row_input) v2 = widget_grid_col_input->value(); + if (i==widget_grid_col_input) v2 = widget_grid_row_input->value(); + Fl_Grid::Cell *new_cell = nullptr; + if (cell) { + switch (what & 0x00ff) { + case 8: old_v = cell->row(); v2 = cell->col(); break; + case 9: old_v = cell->col(); v2 = cell->row(); break; + case 10: old_v = cell->rowspan(); break; + case 11: old_v = cell->colspan(); break; + case 12: cell->minimum_size(&old_v, &v2); break; + case 13: cell->minimum_size(&v2, &old_v); break; + } + } + switch (what & 0xff00) { + case 0x0100: v--; break; + case 0x0200: v++; break; + } + if (old_v != v) { + switch (what & 0x00ff) { + case 8: + if (v2 == -1 && v >= 0) v2 = 0; + g->move_cell(current_widget->o, v, v2, 2); i->value(v); + break; + case 9: + if (v2 == -1 && v >= 0) v2 = 0; + g->move_cell(current_widget->o, v2, v, 2); i->value(v); + break; + case 10: if (cell && cell->row()+v<=g->rows() && v>0) cell->rowspan(v); + break; + case 11: if (cell && cell->col()+v<=g->cols() && v>0) cell->colspan(v); + break; + case 12: if (cell && v>=0) cell->minimum_size(v, v2); + break; + case 13: if (cell && v>=0) cell->minimum_size(v2, v); + break; + } + if (!cell && new_cell) + new_cell->minimum_size(20, 20); + g->need_layout(true); + Fluid.proj.set_modflag(1); + } + }} {} + } +} diff --git a/fluid/panels/widget_panel/Grid_Child_Tab.h b/fluid/panels/widget_panel/Grid_Child_Tab.h new file mode 100644 index 000000000..93cfda78b --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Child_Tab.h @@ -0,0 +1,79 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0500 + +#ifndef Grid_Child_Tab_h +#define Grid_Child_Tab_h +#include +#include "widgets/Formula_Input.h" +#include +extern void propagate_load(Fl_Group*, void*); +#include +#include +#include + +class Grid_Child_Tab : public Fl_Group { +public: + Grid_Child_Tab(int X, int Y, int W, int H, const char *L = 0); + fld::widget::Formula_Input *widget_grid_row_input; +private: + inline void cb_widget_grid_row_input_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_row_input(fld::widget::Formula_Input*, void*); + inline void cb__i(Fl_Button*, void*); + static void cb_(Fl_Button*, void*); + inline void cb_1_i(Fl_Button*, void*); + static void cb_1(Fl_Button*, void*); +public: + fld::widget::Formula_Input *widget_grid_col_input; +private: + inline void cb_widget_grid_col_input_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_col_input(fld::widget::Formula_Input*, void*); + inline void cb_2_i(Fl_Button*, void*); + static void cb_2(Fl_Button*, void*); + inline void cb_3_i(Fl_Button*, void*); + static void cb_3(Fl_Button*, void*); +public: + Fl_Box *widget_grid_transient; +private: + inline void cb_widget_grid_transient_i(Fl_Box*, void*); + static void cb_widget_grid_transient(Fl_Box*, void*); +public: + Fl_Box *widget_grid_unlinked; + Fl_Group *wp_gridc_align; +private: + inline void cb_Horizontal_i(Fl_Choice*, void*); + static void cb_Horizontal(Fl_Choice*, void*); + static Fl_Menu_Item menu_Horizontal[]; +public: + static Fl_Menu_Item *GRID_LEFT; +private: + inline void cb_Vertical_i(Fl_Choice*, void*); + static void cb_Vertical(Fl_Choice*, void*); + static Fl_Menu_Item menu_Vertical[]; +public: + Fl_Group *wp_gridc_size; +private: + inline void cb_Width_i(fld::widget::Formula_Input*, void*); + static void cb_Width(fld::widget::Formula_Input*, void*); + inline void cb_Height_i(fld::widget::Formula_Input*, void*); + static void cb_Height(fld::widget::Formula_Input*, void*); +public: + fld::widget::Formula_Input *widget_grid_rowspan_input; +private: + inline void cb_widget_grid_rowspan_input_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_rowspan_input(fld::widget::Formula_Input*, void*); + inline void cb_4_i(Fl_Button*, void*); + static void cb_4(Fl_Button*, void*); + inline void cb_5_i(Fl_Button*, void*); + static void cb_5(Fl_Button*, void*); +public: + fld::widget::Formula_Input *widget_grid_colspan_input; +private: + inline void cb_widget_grid_colspan_input_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_colspan_input(fld::widget::Formula_Input*, void*); + inline void cb_6_i(Fl_Button*, void*); + static void cb_6(Fl_Button*, void*); + inline void cb_7_i(Fl_Button*, void*); + static void cb_7(Fl_Button*, void*); +public: + void grid_child_cb(fld::widget::Formula_Input* i, void* v, int what); +}; +#endif diff --git a/fluid/panels/widget_panel/Grid_Tab.cxx b/fluid/panels/widget_panel/Grid_Tab.cxx new file mode 100644 index 000000000..756d957ac --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Tab.cxx @@ -0,0 +1,778 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0500 + +#include "Grid_Tab.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "nodes/Grid_Node.h" +extern Grid_Tab *widget_tab_grid; + +void Grid_Tab::cb_widget_grid_rows_i(fld::widget::Formula_Input* o, void* v) { + // grid_rows_cb + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + if (v == LOAD) { + o->value(grid->rows()); + } else { + int m = o->value(), old_m = grid->rows(); + if (m < 1) { + m = 1; + o->value(m); + } + if (m < old_m) { + // TODO: verify that this will not unlink existings cells + // Offer a dialog with "delete children", "unlink cells", "cancel" + } + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->layout(m, grid->cols()); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + widget_tab_grid->do_callback(widget_tab_grid, LOAD); + } + } +} +void Grid_Tab::cb_widget_grid_rows(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_widget_grid_rows_i(o,v); +} + +void Grid_Tab::cb__i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_rows->value( widget_grid_rows->value()-1 ); + widget_grid_rows->do_callback(); + } +} +void Grid_Tab::cb_(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb__i(o,v); +} + +void Grid_Tab::cb_1_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_rows->value( widget_grid_rows->value()+1 ); + widget_grid_rows->do_callback(); + } +} +void Grid_Tab::cb_1(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_1_i(o,v); +} + +void Grid_Tab::cb_widget_grid_cols_i(fld::widget::Formula_Input* o, void* v) { + // grid_rows_cb + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + if (v == LOAD) { + o->value(grid->cols()); + } else { + int m = o->value(), old_m = grid->cols(); + if (m < 1) { + m = 1; + o->value(m); + } + if (m < old_m) { + // TODO: verify that this will not unlink existings cells + // Offer a dialog with "delete children", "unlink cells", "cancel" + } + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->layout(grid->rows(), m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + widget_tab_grid->do_callback(widget_tab_grid, LOAD); + } + } +} +void Grid_Tab::cb_widget_grid_cols(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_widget_grid_cols_i(o,v); +} + +void Grid_Tab::cb_2_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_cols->value( widget_grid_cols->value()-1 ); + widget_grid_cols->do_callback(); + } +} +void Grid_Tab::cb_2(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_2_i(o,v); +} + +void Grid_Tab::cb_3_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_cols->value( widget_grid_cols->value()+1 ); + widget_grid_cols->do_callback(); + } +} +void Grid_Tab::cb_3(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_3_i(o,v); +} + +void Grid_Tab::cb_Left_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int m = 0; + if (v == LOAD) { + grid->margin(&m, nullptr, nullptr, nullptr); + o->value(m); + } else { + int m = (int)o->value(), old_m; + grid->margin(&old_m, nullptr, nullptr, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(m, -1, -1, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Left(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Left_i(o,v); +} + +void Grid_Tab::cb_Top_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int m = 0; + if (v == LOAD) { + grid->margin(nullptr, &m, nullptr, nullptr); + o->value(m); + } else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, &old_m, nullptr, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, m, -1, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Top(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Top_i(o,v); +} + +void Grid_Tab::cb_Right_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int m = 0; + if (v == LOAD) { + grid->margin(nullptr, nullptr, &m, nullptr); + o->value(m); + } else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, nullptr, &old_m, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, -1, m, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Right(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Right_i(o,v); +} + +void Grid_Tab::cb_Bottom_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int m = 0; + if (v == LOAD) { + grid->margin(nullptr, nullptr, nullptr, &m); + o->value(m); + } else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, nullptr, nullptr, &old_m); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, -1, -1, m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Bottom(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Bottom_i(o,v); +} + +void Grid_Tab::cb_Row_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + if (v == LOAD) { + int m = 0; + grid->gap(&m, nullptr); + o->value(m); + } else { + int m = (int)o->value(), old_m, m2; + grid->gap(&old_m, &m2); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->gap(m, m2); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Row(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Row_i(o,v); +} + +void Grid_Tab::cb_Col_i(Fl_Value_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + if (v == LOAD) { + int m = 0; + grid->gap(nullptr, &m); + o->value(m); + } else { + int m = (int)o->value(), old_m, m2; + grid->gap(&m2, &old_m); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->gap(m2, m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Col(Fl_Value_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_Col_i(o,v); +} + +void Grid_Tab::cb_Row1_i(Fl_Group* o, void* v) { + if (v == LOAD) { + Fl_Grid *grid = Grid_Node::selected(); + if (grid) + o->activate(); + else + o->deactivate(); + propagate_load(o, v); + } +} +void Grid_Tab::cb_Row1(Fl_Group* o, void* v) { + ((Grid_Tab*)(o->parent()))->cb_Row1_i(o,v); +} + +void Grid_Tab::cb_widget_grid_curr_row_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int r = o->value(), old_r = r; + if (r < 0) r = 0; + if (r >= grid->rows()) r = grid->rows()-1; + if (r != old_r) o->value(r); + if (v == LOAD) { + // will automatically propagate + } else { + widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); + } +} +void Grid_Tab::cb_widget_grid_curr_row(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_widget_grid_curr_row_i(o,v); +} + +void Grid_Tab::cb_4_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); + widget_grid_curr_row->do_callback(); + } +} +void Grid_Tab::cb_4(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_4_i(o,v); +} + +void Grid_Tab::cb_5_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); + widget_grid_curr_row->do_callback(); + } +} +void Grid_Tab::cb_5(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_5_i(o,v); +} + +void Grid_Tab::cb_Height_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int r = widget_grid_curr_row->value(); + if (v == LOAD) { + o->value(grid->row_height(r)); + } else { + int h = o->value(), old_h = grid->row_height(r); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_height(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Height(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Height_i(o,v); +} + +void Grid_Tab::cb_Weight_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int r = widget_grid_curr_row->value(); + if (v == LOAD) { + o->value(grid->row_weight(r)); + } else { + int h = o->value(), old_h = grid->row_weight(r); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_weight(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Weight(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Weight_i(o,v); +} + +void Grid_Tab::cb_Gap_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int r = widget_grid_curr_row->value(); + if (v == LOAD) { + o->value(grid->row_gap(r)); + } else { + int h = o->value(), old_h = grid->row_gap(r); + if (h < -1) h = -1; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_gap(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Gap(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Gap_i(o,v); +} + +void Grid_Tab::cb_widget_grid_curr_col_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int c = o->value(), old_c = c; + if (c < 0) c = 0; + if (c >= grid->cols()) c = grid->cols()-1; + if (c != old_c) o->value(c); + if (v == LOAD) { + // will automatically propagate + } else { + widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); + } +} +void Grid_Tab::cb_widget_grid_curr_col(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()))->cb_widget_grid_curr_col_i(o,v); +} + +void Grid_Tab::cb_6_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); + widget_grid_curr_col->do_callback(); + } +} +void Grid_Tab::cb_6(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_6_i(o,v); +} + +void Grid_Tab::cb_7_i(Fl_Button*, void* v) { + if (v != LOAD) { + widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); + widget_grid_curr_col->do_callback(); + } +} +void Grid_Tab::cb_7(Fl_Button* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_7_i(o,v); +} + +void Grid_Tab::cb_Width_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int c = widget_grid_curr_col->value(); + if (v == LOAD) { + o->value(grid->col_width(c)); + } else { + int h = o->value(), old_h = grid->col_width(c); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_width(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Width(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Width_i(o,v); +} + +void Grid_Tab::cb_Weight1_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int c = widget_grid_curr_col->value(); + if (v == LOAD) { + o->value(grid->col_weight(c)); + } else { + int h = o->value(), old_h = grid->col_weight(c); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_weight(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Weight1(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Weight1_i(o,v); +} + +void Grid_Tab::cb_Gap1_i(fld::widget::Formula_Input* o, void* v) { + Fl_Grid *grid = Grid_Node::selected(); + if (!grid) return; + int c = widget_grid_curr_col->value(); + if (v == LOAD) { + o->value(grid->col_gap(c)); + } else { + int h = o->value(), old_h = grid->col_gap(c); + if (h < -1) h = -1; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_gap(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } + } +} +void Grid_Tab::cb_Gap1(fld::widget::Formula_Input* o, void* v) { + ((Grid_Tab*)(o->parent()->parent()->parent()))->cb_Gap1_i(o,v); +} + +Grid_Tab::Grid_Tab(int X, int Y, int W, int H, const char *L) : + Fl_Group(0, 0, 400, 330, L) +{ + this->labelsize(11); + this->callback((Fl_Callback*)propagate_load); + { Fl_Group* o = new Fl_Group(85, 30, 315, 20, "Grid Layout:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(Fl_Align(FL_ALIGN_LEFT)); + { widget_grid_rows = new fld::widget::Formula_Input(85, 30, 40, 20, "Rows:"); + widget_grid_rows->tooltip("Number of horizontal rows in the Grid group"); + widget_grid_rows->box(FL_DOWN_BOX); + widget_grid_rows->color(FL_BACKGROUND2_COLOR); + widget_grid_rows->selection_color(FL_SELECTION_COLOR); + widget_grid_rows->labeltype(FL_NORMAL_LABEL); + widget_grid_rows->labelfont(0); + widget_grid_rows->labelsize(11); + widget_grid_rows->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_rows->textsize(11); + widget_grid_rows->callback((Fl_Callback*)cb_widget_grid_rows); + widget_grid_rows->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_rows->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_rows + { Fl_Group* o = new Fl_Group(125, 30, 30, 20); + { Fl_Button* o = new Fl_Button(125, 30, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(140, 30, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_1); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { widget_grid_cols = new fld::widget::Formula_Input(165, 30, 40, 20, "Columns:"); + widget_grid_cols->tooltip("Number of vertical columns in the Grid group"); + widget_grid_cols->box(FL_DOWN_BOX); + widget_grid_cols->color(FL_BACKGROUND2_COLOR); + widget_grid_cols->selection_color(FL_SELECTION_COLOR); + widget_grid_cols->labeltype(FL_NORMAL_LABEL); + widget_grid_cols->labelfont(0); + widget_grid_cols->labelsize(11); + widget_grid_cols->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_cols->textsize(11); + widget_grid_cols->callback((Fl_Callback*)cb_widget_grid_cols); + widget_grid_cols->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_cols->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_cols + { Fl_Group* o = new Fl_Group(205, 30, 30, 20); + { Fl_Button* o = new Fl_Button(205, 30, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_2); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(220, 30, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_3); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(386, 30, 0, 20); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { wp_grid_margin = new Fl_Group(85, 70, 315, 20, "Margins:"); + wp_grid_margin->labelfont(1); + wp_grid_margin->labelsize(11); + wp_grid_margin->callback((Fl_Callback*)propagate_load); + wp_grid_margin->align(Fl_Align(FL_ALIGN_LEFT)); + { Fl_Value_Input* o = new Fl_Value_Input(85, 70, 55, 20, "Left:"); + o->tooltip("Left margin in group."); + o->labelsize(11); + o->maximum(1000); + 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(145, 70, 55, 20, "Top:"); + o->tooltip("Top margin in group."); + o->labelsize(11); + o->maximum(1000); + 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(205, 70, 55, 20, "Right:"); + o->tooltip("Right margin in group."); + o->labelsize(11); + o->maximum(1000); + 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(265, 70, 55, 20, "Bottom:"); + o->tooltip("Bottom margin in group."); + o->labelsize(11); + o->maximum(1000); + 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(386, 70, 0, 20); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + wp_grid_margin->end(); + } // Fl_Group* wp_grid_margin + { wp_grid_gaps = new Fl_Group(85, 105, 315, 20, "Gaps:"); + wp_grid_gaps->labelfont(1); + wp_grid_gaps->labelsize(11); + wp_grid_gaps->callback((Fl_Callback*)propagate_load); + wp_grid_gaps->align(Fl_Align(FL_ALIGN_LEFT)); + { Fl_Value_Input* o = new Fl_Value_Input(85, 105, 55, 20, "Row:"); + o->tooltip("Gap between children."); + o->labelsize(11); + o->maximum(1000); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)cb_Row); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Value_Input* o + { Fl_Value_Input* o = new Fl_Value_Input(145, 105, 55, 20, "Col:"); + o->tooltip("Gap between children."); + o->labelsize(11); + o->maximum(1000); + o->step(1); + o->textsize(11); + o->callback((Fl_Callback*)cb_Col); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + } // Fl_Value_Input* o + { Fl_Box* o = new Fl_Box(386, 105, 0, 20); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + wp_grid_gaps->end(); + } // Fl_Group* wp_grid_gaps + { Fl_Group* o = new Fl_Group(85, 145, 315, 20, "Row:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_Row1); + o->align(Fl_Align(FL_ALIGN_LEFT)); + { widget_grid_curr_row = new fld::widget::Formula_Input(85, 145, 40, 20, "Index"); + widget_grid_curr_row->box(FL_DOWN_BOX); + widget_grid_curr_row->color(FL_BACKGROUND2_COLOR); + widget_grid_curr_row->selection_color(FL_SELECTION_COLOR); + widget_grid_curr_row->labeltype(FL_NORMAL_LABEL); + widget_grid_curr_row->labelfont(0); + widget_grid_curr_row->labelsize(11); + widget_grid_curr_row->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_curr_row->textsize(11); + widget_grid_curr_row->callback((Fl_Callback*)cb_widget_grid_curr_row); + widget_grid_curr_row->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_curr_row->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_curr_row + { Fl_Group* o = new Fl_Group(125, 145, 30, 20); + o->callback((Fl_Callback*)propagate_load); + { Fl_Button* o = new Fl_Button(125, 145, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_4); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(140, 145, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_5); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(155, 145, 15, 20, ":"); + o->labelsize(11); + } // Fl_Box* o + { widget_grid_curr_row_attributes = new Fl_Group(170, 145, 175, 20); + widget_grid_curr_row_attributes->callback((Fl_Callback*)propagate_load); + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(170, 145, 55, 20, "Height:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Height); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(230, 145, 55, 20, "Weight:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Weight); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(290, 145, 55, 20, "Gap:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Gap); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + widget_grid_curr_row_attributes->end(); + } // Fl_Group* widget_grid_curr_row_attributes + { Fl_Box* o = new Fl_Box(390, 145, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { Fl_Group* o = new Fl_Group(85, 180, 315, 20, "Column:"); + o->labelfont(1); + o->labelsize(11); + o->callback((Fl_Callback*)propagate_load); + o->align(Fl_Align(FL_ALIGN_LEFT)); + { widget_grid_curr_col = new fld::widget::Formula_Input(85, 180, 40, 20, "Index"); + widget_grid_curr_col->box(FL_DOWN_BOX); + widget_grid_curr_col->color(FL_BACKGROUND2_COLOR); + widget_grid_curr_col->selection_color(FL_SELECTION_COLOR); + widget_grid_curr_col->labeltype(FL_NORMAL_LABEL); + widget_grid_curr_col->labelfont(0); + widget_grid_curr_col->labelsize(11); + widget_grid_curr_col->labelcolor(FL_FOREGROUND_COLOR); + widget_grid_curr_col->textsize(11); + widget_grid_curr_col->callback((Fl_Callback*)cb_widget_grid_curr_col); + widget_grid_curr_col->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + widget_grid_curr_col->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* widget_grid_curr_col + { Fl_Group* o = new Fl_Group(125, 180, 30, 20); + { Fl_Button* o = new Fl_Button(125, 180, 15, 20, "-"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_6); + o->clear_visible_focus(); + } // Fl_Button* o + { Fl_Button* o = new Fl_Button(140, 180, 15, 20, "+"); + o->compact(1); + o->labelsize(11); + o->callback((Fl_Callback*)cb_7); + o->clear_visible_focus(); + } // Fl_Button* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(155, 180, 15, 20, ":"); + o->labelsize(11); + } // Fl_Box* o + { widget_grid_curr_col_attributes = new Fl_Group(170, 180, 175, 20); + widget_grid_curr_col_attributes->callback((Fl_Callback*)propagate_load); + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(170, 180, 55, 20, "Width:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Width); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(230, 180, 55, 20, "Weight:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Weight1); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + { fld::widget::Formula_Input* o = new fld::widget::Formula_Input(290, 180, 55, 20, "Gap:"); + o->box(FL_DOWN_BOX); + o->color(FL_BACKGROUND2_COLOR); + o->selection_color(FL_SELECTION_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(0); + o->labelsize(11); + o->labelcolor(FL_FOREGROUND_COLOR); + o->textsize(11); + o->callback((Fl_Callback*)cb_Gap1); + o->align(Fl_Align(FL_ALIGN_TOP_LEFT)); + o->when(FL_WHEN_RELEASE); + } // fld::widget::Formula_Input* o + widget_grid_curr_col_attributes->end(); + } // Fl_Group* widget_grid_curr_col_attributes + { Fl_Box* o = new Fl_Box(390, 180, 1, 20); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + o->end(); + } // Fl_Group* o + { Fl_Box* o = new Fl_Box(85, 320, 300, 5); + o->labelsize(11); + o->hide(); + Fl_Group::current()->resizable(o); + } // Fl_Box* o + end(); + resize(X, Y, W, H); +} diff --git a/fluid/panels/widget_panel/Grid_Tab.fl b/fluid/panels/widget_panel/Grid_Tab.fl new file mode 100644 index 000000000..e37610ca5 --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Tab.fl @@ -0,0 +1,515 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +header_name {.h} +code_name {.cxx} +decl {\#include "widgets/Formula_Input.h"} {public global +} + +decl {\#include "Fluid.h"} {private global +} + +decl {\#include "proj/undo.h"} {private global +} + +decl {\#include "nodes/Grid_Node.h"} {private global +} + +decl {extern Grid_Tab *widget_tab_grid;} {selected private global +} + +widget_class Grid_Tab { + label Grid + callback propagate_load open + xywh {480 287 400 330} labelsize 11 resizable visible position_relative_rescale +} { + Fl_Group {} { + label {Grid Layout:} + callback propagate_load open + xywh {85 30 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input widget_grid_rows { + label {Rows:} + callback {// grid_rows_cb +Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +if (v == LOAD) { + o->value(grid->rows()); +} else { + int m = o->value(), old_m = grid->rows(); + if (m < 1) { + m = 1; + o->value(m); + } + if (m < old_m) { + // TODO: verify that this will not unlink existings cells + // Offer a dialog with "delete children", "unlink cells", "cancel" + } + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->layout(m, grid->cols()); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + widget_tab_grid->do_callback(widget_tab_grid, LOAD); + } +}} + tooltip {Number of horizontal rows in the Grid group} xywh {85 30 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {125 30 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v != LOAD) { + widget_grid_rows->value( widget_grid_rows->value()-1 ); + widget_grid_rows->do_callback(); +}} + xywh {125 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v != LOAD) { + widget_grid_rows->value( widget_grid_rows->value()+1 ); + widget_grid_rows->do_callback(); +}} + xywh {140 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Input widget_grid_cols { + label {Columns:} + callback {// grid_rows_cb +Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +if (v == LOAD) { + o->value(grid->cols()); +} else { + int m = o->value(), old_m = grid->cols(); + if (m < 1) { + m = 1; + o->value(m); + } + if (m < old_m) { + // TODO: verify that this will not unlink existings cells + // Offer a dialog with "delete children", "unlink cells", "cancel" + } + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->layout(grid->rows(), m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + widget_tab_grid->do_callback(widget_tab_grid, LOAD); + } +}} + tooltip {Number of vertical columns in the Grid group} xywh {165 30 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {205 30 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v != LOAD) { + widget_grid_cols->value( widget_grid_cols->value()-1 ); + widget_grid_cols->do_callback(); +}} + xywh {205 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v != LOAD) { + widget_grid_cols->value( widget_grid_cols->value()+1 ); + widget_grid_cols->do_callback(); +}} + xywh {220 30 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Box {} { + xywh {386 30 0 20} resizable + } + } + Fl_Group wp_grid_margin { + label {Margins:} + callback propagate_load open + xywh {85 70 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Value_Input {} { + label {Left:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int m = 0; +if (v == LOAD) { + grid->margin(&m, nullptr, nullptr, nullptr); + o->value(m); +} else { + int m = (int)o->value(), old_m; + grid->margin(&old_m, nullptr, nullptr, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(m, -1, -1, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Left margin in group.} xywh {85 70 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Value_Input {} { + label {Top:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int m = 0; +if (v == LOAD) { + grid->margin(nullptr, &m, nullptr, nullptr); + o->value(m); +} else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, &old_m, nullptr, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, m, -1, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Top margin in group.} xywh {145 70 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Value_Input {} { + label {Right:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int m = 0; +if (v == LOAD) { + grid->margin(nullptr, nullptr, &m, nullptr); + o->value(m); +} else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, nullptr, &old_m, nullptr); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, -1, m, -1); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Right margin in group.} xywh {205 70 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Value_Input {} { + label {Bottom:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int m = 0; +if (v == LOAD) { + grid->margin(nullptr, nullptr, nullptr, &m); + o->value(m); +} else { + int m = (int)o->value(), old_m; + grid->margin(nullptr, nullptr, nullptr, &old_m); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->margin(-1, -1, -1, m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Bottom margin in group.} xywh {265 70 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Box {} { + xywh {386 70 0 20} resizable + } + } + Fl_Group wp_grid_gaps { + label {Gaps:} + callback propagate_load open + xywh {85 105 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Value_Input {} { + label {Row:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +if (v == LOAD) { + int m = 0; + grid->gap(&m, nullptr); + o->value(m); +} else { + int m = (int)o->value(), old_m, m2; + grid->gap(&old_m, &m2); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->gap(m, m2); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Gap between children.} xywh {85 105 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Value_Input {} { + label {Col:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +if (v == LOAD) { + int m = 0; + grid->gap(nullptr, &m); + o->value(m); +} else { + int m = (int)o->value(), old_m, m2; + grid->gap(&m2, &old_m); + if (m != old_m) { + Fluid.proj.undo.checkpoint(); + grid->gap(m2, m); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + tooltip {Gap between children.} xywh {145 105 55 20} labelsize 11 align 5 maximum 1000 step 1 textsize 11 + } + Fl_Box {} { + xywh {386 105 0 20} resizable + } + } + Fl_Group {} { + label {Row:} + callback {if (v == LOAD) { + Fl_Grid *grid = Grid_Node::selected(); + if (grid) + o->activate(); + else + o->deactivate(); + propagate_load(o, v); +}} open + xywh {85 145 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input widget_grid_curr_row { + label Index + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int r = o->value(), old_r = r; +if (r < 0) r = 0; +if (r >= grid->rows()) r = grid->rows()-1; +if (r != old_r) o->value(r); +if (v == LOAD) { + // will automatically propagate +} else { + widget_grid_curr_row_attributes->do_callback(widget_grid_curr_row_attributes, LOAD); +}} + xywh {85 145 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} { + callback propagate_load open + xywh {125 145 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v != LOAD) { + widget_grid_curr_row->value( widget_grid_curr_row->value()-1 ); + widget_grid_curr_row->do_callback(); +}} + xywh {125 145 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v != LOAD) { + widget_grid_curr_row->value( widget_grid_curr_row->value()+1 ); + widget_grid_curr_row->do_callback(); +}} + xywh {140 145 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Box {} { + label {:} + xywh {155 145 15 20} labelsize 11 + } + Fl_Group widget_grid_curr_row_attributes { + callback propagate_load open + xywh {170 145 175 20} + } { + Fl_Input {} { + label {Height:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int r = widget_grid_curr_row->value(); +if (v == LOAD) { + o->value(grid->row_height(r)); +} else { + int h = o->value(), old_h = grid->row_height(r); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_height(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {170 145 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Input {} { + label {Weight:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int r = widget_grid_curr_row->value(); +if (v == LOAD) { + o->value(grid->row_weight(r)); +} else { + int h = o->value(), old_h = grid->row_weight(r); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_weight(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {230 145 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Input {} { + label {Gap:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int r = widget_grid_curr_row->value(); +if (v == LOAD) { + o->value(grid->row_gap(r)); +} else { + int h = o->value(), old_h = grid->row_gap(r); + if (h < -1) h = -1; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->row_gap(r, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {290 145 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + } + Fl_Box {} { + xywh {390 145 1 20} hide resizable + } + } + Fl_Group {} { + label {Column:} + callback propagate_load open + xywh {85 180 315 20} labelfont 1 labelsize 11 align 4 + } { + Fl_Input widget_grid_curr_col { + label Index + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int c = o->value(), old_c = c; +if (c < 0) c = 0; +if (c >= grid->cols()) c = grid->cols()-1; +if (c != old_c) o->value(c); +if (v == LOAD) { + // will automatically propagate +} else { + widget_grid_curr_col_attributes->do_callback(widget_grid_curr_col_attributes, LOAD); +}} + xywh {85 180 40 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Group {} {open + xywh {125 180 30 20} + } { + Fl_Button {} { + label {-} + callback {if (v != LOAD) { + widget_grid_curr_col->value( widget_grid_curr_col->value()-1 ); + widget_grid_curr_col->do_callback(); +}} + xywh {125 180 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + Fl_Button {} { + label {+} + callback {if (v != LOAD) { + widget_grid_curr_col->value( widget_grid_curr_col->value()+1 ); + widget_grid_curr_col->do_callback(); +}} + xywh {140 180 15 20} labelsize 11 + code0 {o->clear_visible_focus();} compact 1 + } + } + Fl_Box {} { + label {:} + xywh {155 180 15 20} labelsize 11 + } + Fl_Group widget_grid_curr_col_attributes { + callback propagate_load open + xywh {170 180 175 20} + } { + Fl_Input {} { + label {Width:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int c = widget_grid_curr_col->value(); +if (v == LOAD) { + o->value(grid->col_width(c)); +} else { + int h = o->value(), old_h = grid->col_width(c); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_width(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {170 180 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Input {} { + label {Weight:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int c = widget_grid_curr_col->value(); +if (v == LOAD) { + o->value(grid->col_weight(c)); +} else { + int h = o->value(), old_h = grid->col_weight(c); + if (h < 0) h = 0; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_weight(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {230 180 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + Fl_Input {} { + label {Gap:} + callback {Fl_Grid *grid = Grid_Node::selected(); +if (!grid) return; +int c = widget_grid_curr_col->value(); +if (v == LOAD) { + o->value(grid->col_gap(c)); +} else { + int h = o->value(), old_h = grid->col_gap(c); + if (h < -1) h = -1; + if (h != old_h) { + Fluid.proj.undo.checkpoint(); + grid->col_gap(c, h); + grid->need_layout(true); + Fluid.proj.set_modflag(1); + } +}} + xywh {290 180 55 20} labelsize 11 align 5 textsize 11 + class {fld::widget::Formula_Input} + } + } + Fl_Box {} { + xywh {390 180 1 20} hide resizable + } + } + Fl_Box {} { + xywh {85 320 300 5} labelsize 11 hide resizable + } +} diff --git a/fluid/panels/widget_panel/Grid_Tab.h b/fluid/panels/widget_panel/Grid_Tab.h new file mode 100644 index 000000000..4b06a9e43 --- /dev/null +++ b/fluid/panels/widget_panel/Grid_Tab.h @@ -0,0 +1,90 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.0500 + +#ifndef Grid_Tab_h +#define Grid_Tab_h +#include +#include "widgets/Formula_Input.h" +#include +extern void propagate_load(Fl_Group*, void*); +#include +#include +#include + +class Grid_Tab : public Fl_Group { +public: + Grid_Tab(int X, int Y, int W, int H, const char *L = 0); + fld::widget::Formula_Input *widget_grid_rows; +private: + inline void cb_widget_grid_rows_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_rows(fld::widget::Formula_Input*, void*); + inline void cb__i(Fl_Button*, void*); + static void cb_(Fl_Button*, void*); + inline void cb_1_i(Fl_Button*, void*); + static void cb_1(Fl_Button*, void*); +public: + fld::widget::Formula_Input *widget_grid_cols; +private: + inline void cb_widget_grid_cols_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_cols(fld::widget::Formula_Input*, void*); + inline void cb_2_i(Fl_Button*, void*); + static void cb_2(Fl_Button*, void*); + inline void cb_3_i(Fl_Button*, void*); + static void cb_3(Fl_Button*, void*); +public: + Fl_Group *wp_grid_margin; +private: + inline void cb_Left_i(Fl_Value_Input*, void*); + static void cb_Left(Fl_Value_Input*, void*); + inline void cb_Top_i(Fl_Value_Input*, void*); + static void cb_Top(Fl_Value_Input*, void*); + inline void cb_Right_i(Fl_Value_Input*, void*); + static void cb_Right(Fl_Value_Input*, void*); + inline void cb_Bottom_i(Fl_Value_Input*, void*); + static void cb_Bottom(Fl_Value_Input*, void*); +public: + Fl_Group *wp_grid_gaps; +private: + inline void cb_Row_i(Fl_Value_Input*, void*); + static void cb_Row(Fl_Value_Input*, void*); + inline void cb_Col_i(Fl_Value_Input*, void*); + static void cb_Col(Fl_Value_Input*, void*); + inline void cb_Row1_i(Fl_Group*, void*); + static void cb_Row1(Fl_Group*, void*); +public: + fld::widget::Formula_Input *widget_grid_curr_row; +private: + inline void cb_widget_grid_curr_row_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_curr_row(fld::widget::Formula_Input*, void*); + inline void cb_4_i(Fl_Button*, void*); + static void cb_4(Fl_Button*, void*); + inline void cb_5_i(Fl_Button*, void*); + static void cb_5(Fl_Button*, void*); +public: + Fl_Group *widget_grid_curr_row_attributes; +private: + inline void cb_Height_i(fld::widget::Formula_Input*, void*); + static void cb_Height(fld::widget::Formula_Input*, void*); + inline void cb_Weight_i(fld::widget::Formula_Input*, void*); + static void cb_Weight(fld::widget::Formula_Input*, void*); + inline void cb_Gap_i(fld::widget::Formula_Input*, void*); + static void cb_Gap(fld::widget::Formula_Input*, void*); +public: + fld::widget::Formula_Input *widget_grid_curr_col; +private: + inline void cb_widget_grid_curr_col_i(fld::widget::Formula_Input*, void*); + static void cb_widget_grid_curr_col(fld::widget::Formula_Input*, void*); + inline void cb_6_i(Fl_Button*, void*); + static void cb_6(Fl_Button*, void*); + inline void cb_7_i(Fl_Button*, void*); + static void cb_7(Fl_Button*, void*); +public: + Fl_Group *widget_grid_curr_col_attributes; +private: + inline void cb_Width_i(fld::widget::Formula_Input*, void*); + static void cb_Width(fld::widget::Formula_Input*, void*); + inline void cb_Weight1_i(fld::widget::Formula_Input*, void*); + static void cb_Weight1(fld::widget::Formula_Input*, void*); + inline void cb_Gap1_i(fld::widget::Formula_Input*, void*); + static void cb_Gap1(fld::widget::Formula_Input*, void*); +}; +#endif diff --git a/fluid/app/align_widget.cxx b/fluid/proj/align_widget.cxx similarity index 63% rename from fluid/app/align_widget.cxx rename to fluid/proj/align_widget.cxx index a9badf9e4..9ce9e2b62 100644 --- a/fluid/app/align_widget.cxx +++ b/fluid/proj/align_widget.cxx @@ -1,7 +1,7 @@ // // Alignment code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -14,11 +14,11 @@ // https://www.fltk.org/bugs.php // -#include "app/align_widget.h" +#include "proj/align_widget.h" -#include "app/fluid.h" -#include "app/undo.h" -#include "nodes/Fl_Group_Type.h" +#include "Fluid.h" +#include "proj/undo.h" +#include "nodes/Group_Node.h" #include #include @@ -35,43 +35,43 @@ void align_widget_cb(Fl_Widget*, long how) { const int max = 32768, min = -32768; int left, right, top, bot, wdt, hgt, n; - Fl_Type *o; + Node *o; int changed = 0; switch ( how ) { //---- align case 10: // align left left = max; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->x()x(); BREAK_ON_FIRST; } if (left!=max) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(left, w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 11: // align h.center left = max; right = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->x()x(); if (w->x()+w->w()>right) @@ -81,17 +81,17 @@ void align_widget_cb(Fl_Widget*, long how) if (left!=max) { int center2 = left+right; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } @@ -99,62 +99,62 @@ void align_widget_cb(Fl_Widget*, long how) break; case 12: // align right right = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->x()+w->w()>right) right = w->x()+w->w(); BREAK_ON_FIRST; } if (right!=min) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(right-w->w(), w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 13: // align top top = max; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->y()y(); BREAK_ON_FIRST; } if (top!=max) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(w->x(), top, w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 14: // align v.center top = max; bot = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->y()y(); if (w->y()+w->h()>bot) @@ -164,17 +164,17 @@ void align_widget_cb(Fl_Widget*, long how) if (top!=max) { int center2 = top+bot; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } @@ -182,26 +182,26 @@ void align_widget_cb(Fl_Widget*, long how) break; case 15: // align bottom bot = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->y()+w->h()>bot) bot = w->y()+w->h(); BREAK_ON_FIRST; } if (bot!=min) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize( w->x(), bot-w->h(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } @@ -209,10 +209,10 @@ void align_widget_cb(Fl_Widget*, long how) //---- space evenly case 20: // space evenly across left = max; right = min; wdt = 0; n = 0; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->x()x(); if (w->x()+w->w()>right) @@ -226,17 +226,17 @@ void align_widget_cb(Fl_Widget*, long how) { wdt = wdt/n*n; // make sure that all gaps are the same, possibly moving the rightmost widget int cnt = 0, wsum = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(left+wsum+wdt*cnt/n, w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); cnt++; @@ -246,10 +246,10 @@ void align_widget_cb(Fl_Widget*, long how) break; case 21: // space evenly down top = max; bot = min; hgt = 0, n = 0; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->y()y(); if (w->y()+w->h()>bot) @@ -263,17 +263,17 @@ void align_widget_cb(Fl_Widget*, long how) { hgt = hgt/n*n; // make sure that all gaps are the same, possibly moving the rightmost widget int cnt = 0, hsum = 0; - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(w->x(), top+hsum+hgt*cnt/n, w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); cnt++; @@ -284,62 +284,62 @@ void align_widget_cb(Fl_Widget*, long how) //---- make same size case 30: // same width wdt = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->w()>wdt) wdt = w->w(); BREAK_ON_FIRST; } if (wdt!=min) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize(w->x(), w->y(), wdt, w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 31: // same height hgt = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->h()>hgt) hgt = w->h(); BREAK_ON_FIRST; } if (hgt!=min) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize( w->x(), w->y(), w->w(), hgt); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 32: // same size hgt = min; wdt = min; - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; if (w->w()>wdt) wdt = w->w(); if (w->h()>hgt) @@ -347,68 +347,68 @@ void align_widget_cb(Fl_Widget*, long how) BREAK_ON_FIRST; } if (hgt!=min) - for (Fl_Type *o = Fl_Type::first; o; o = o->next) + for (Node *o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget()) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Type::allow_layout++; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fluid.proj.tree.allow_layout++; w->resize( w->x(), w->y(), wdt, hgt); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; //---- center in group case 40: // center hor - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget() && o->parent) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fl_Widget *p = ((Widget_Node *)o->parent)->o; int center2; if (w->window() == p) center2 = p->w(); else center2 = 2*p->x()+p->w(); - Fl_Type::allow_layout++; + Fluid.proj.tree.allow_layout++; w->resize((center2-w->w())/2, w->y(), w->w(), w->h()); - Fl_Type::allow_layout--; + Fluid.proj.tree.allow_layout--; w->redraw(); if (w->window()) w->window()->redraw(); } break; case 41: // center vert - for (o = Fl_Type::first; o; o = o->next) + for (o = Fluid.proj.tree.first; o; o = o->next) if (o->selected && o->is_widget() && o->parent) { if (!changed) { changed = 1; - undo_checkpoint(); + Fluid.proj.undo.checkpoint(); } - Fl_Widget *w = ((Fl_Widget_Type *)o)->o; - Fl_Widget *p = ((Fl_Widget_Type *)o->parent)->o; + Fl_Widget *w = ((Widget_Node *)o)->o; + Fl_Widget *p = ((Widget_Node *)o->parent)->o; int center2; if (w->window() == p) center2 = p->h(); else center2 = 2*p->y()+p->h(); - Fl_Type::allow_layout++; + Fluid.proj.tree.allow_layout++; w->resize(w->x(), (center2-w->h())/2, w->w(), w->h()); - Fl_Type::allow_layout--; - set_modflag(1); + Fluid.proj.tree.allow_layout--; + Fluid.proj.set_modflag(1); w->redraw(); if (w->window()) w->window()->redraw(); } break; } if (changed) - set_modflag(1); + Fluid.proj.set_modflag(1); } diff --git a/fluid/app/align_widget.h b/fluid/proj/align_widget.h similarity index 91% rename from fluid/app/align_widget.h rename to fluid/proj/align_widget.h index f04372215..88860b7ce 100644 --- a/fluid/app/align_widget.h +++ b/fluid/proj/align_widget.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-2025 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/app/mergeback.cxx b/fluid/proj/mergeback.cxx similarity index 88% rename from fluid/app/mergeback.cxx rename to fluid/proj/mergeback.cxx index e0eafe500..12f272638 100644 --- a/fluid/app/mergeback.cxx +++ b/fluid/proj/mergeback.cxx @@ -1,7 +1,7 @@ // -// MergeBack routines for the Fast Light Tool Kit (FLTK). +// MergeBack code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 2023-2025 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 @@ -17,13 +17,13 @@ #if 0 // Matt: disabled -#include "app/mergeback.h" +#include "proj/mergeback.h" -#include "app/fluid.h" -#include "app/undo.h" +#include "Fluid.h" +#include "proj/undo.h" #include "io/Code_Writer.h" -#include "nodes/Fl_Function_Type.h" -#include "nodes/Fl_Widget_Type.h" +#include "nodes/Function_Node.h" +#include "nodes/Widget_Node.h" #include #include @@ -62,7 +62,7 @@ extern void redraw_browser(); can not be transferred back into the project. Modifications to code blocks and callbacks (CODE, CALLBACK) can be merged back - into the project. Their corresponding Fl_Type is found using the unique + into the project. Their corresponding Node is found using the unique node id that is part of the tag. The block is only merged back if the crc's from the project and from the edited block differ. @@ -102,7 +102,7 @@ extern void redraw_browser(); \return see above */ int merge_back(const std::string &s, const std::string &p, int task) { - if (g_project.write_mergeback_data) { + if (Fluid.proj.write_mergeback_data) { Fd_Mergeback mergeback; return mergeback.merge_back(s, p, task); } else { @@ -113,7 +113,7 @@ int merge_back(const std::string &s, const std::string &p, int task) { /** Allocate and initialize MergeBack class. */ Fd_Mergeback::Fd_Mergeback() : - code(NULL), + code(nullptr), line_no(0), tag_error(0), num_changed_code(0), @@ -226,7 +226,7 @@ int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std: msg += "\n\nClick Cancel to abort the MergeBack operation.\n" "Click Merge to merge all code changes back into\n" "the open project."; - int c = fl_choice(msg.c_str(), "Cancel", "Merge", NULL, + int c = fl_choice(msg.c_str(), "Cancel", "Merge", nullptr, code_filename.c_str(), proj_filename.c_str(), num_changed_code, num_uid_not_found, num_changed_structure, num_possible_override); @@ -239,7 +239,7 @@ int Fd_Mergeback::ask_user_to_merge(const std::string &code_filename, const std: Return findings in num_changed_code, num_changed_code, and num_uid_not_found. */ void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_crc, int uid) { - Fl_Type *tp = Fl_Type::find_by_uid(uid); + Node *tp = Node::find_by_uid(uid); if (tp && tp->is_true_widget()) { std::string cb = tp->callback(); cb += "\n"; unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); @@ -261,7 +261,7 @@ void Fd_Mergeback::analyse_callback(unsigned long code_crc, unsigned long tag_cr Return findings in num_changed_code, num_changed_code, and num_uid_not_found. */ void Fd_Mergeback::analyse_code(unsigned long code_crc, unsigned long tag_crc, int uid) { - Fl_Type *tp = Fl_Type::find_by_uid(uid); + Node *tp = Node::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { std::string code = tp->name(); code += "\n"; unsigned long project_crc = fld::io::Code_Writer::block_crc(code.c_str()); @@ -354,7 +354,7 @@ int Fd_Mergeback::analyse() { \return 1 if the project changed */ int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long code_crc, int uid) { - Fl_Type *tp = Fl_Type::find_by_uid(uid); + Node *tp = Node::find_by_uid(uid); if (tp && tp->is_true_widget()) { std::string cb = tp->callback(); cb += "\n"; unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); @@ -370,7 +370,7 @@ int Fd_Mergeback::apply_callback(long block_end, long block_start, unsigned long \return 1 if the project changed */ int Fd_Mergeback::apply_code(long block_end, long block_start, unsigned long code_crc, int uid) { - Fl_Type *tp = Fl_Type::find_by_uid(uid); + Node *tp = Node::find_by_uid(uid); if (tp && tp->is_a(ID_Code)) { std::string cb = tp->name(); cb += "\n"; unsigned long project_crc = fld::io::Code_Writer::block_crc(cb.c_str()); @@ -477,7 +477,7 @@ int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int tas if (task == FD_MERGEBACK_APPLY) { ret = apply(); if (ret == 1) { - set_modflag(1); + Fluid.proj.set_modflag(1); redraw_browser(); load_panel(); } @@ -485,9 +485,55 @@ int Fd_Mergeback::merge_back(const std::string &s, const std::string &p, int tas } } while (0); fclose(code); - code = NULL; + code = nullptr; return ret; } +#if 0 +// Matt: disabled +/** + Merge the possibly modified content of code files back into the project. + */ +int mergeback_code_files() +{ + flush_text_widgets(); + if (!filename) return 1; + if (!Fluid.proj.write_mergeback_data) { + fl_message("MergeBack is not enabled for this project.\n" + "Please enable MergeBack in the project settings\n" + "dialog and re-save the project file and the code."); + return 0; + } + + std::string proj_filename = Fluid.proj.projectfile_path() + Fluid.proj.projectfile_name(); + std::string code_filename; +#if 1 + if (!Fluid.batch_mode) { + Fl_Preferences build_records(Fl_Preferences::USER_L, "fltk.org", "fluid-build"); + Fl_Preferences path(build_records, proj_filename.c_str()); + int i, n = proj_filename.size(); + for (i=0; i @@ -40,106 +40,104 @@ # include #endif // _WIN32 && !__CYGWIN__ - -// // This file implements an undo system using temporary files; ideally // we'd like to do this in memory, however the current data structures // and design aren't well-suited... Instead, we save and restore // checkpoint files. -// extern Fl_Window* the_panel; -int undo_current = 0; // Current undo level in buffer -int undo_last = 0; // Last undo level in buffer -int undo_max = 0; // Maximum undo level used -int undo_save = -1; // Last undo level that was saved -static int undo_paused = 0; // Undo checkpointing paused? -int undo_once_type = 0; // Suspend further undos of the same type +using namespace fld; +using namespace fld::proj; + + +Undo::Undo(Project &p) +: proj_( p ) +{ } + +Undo::~Undo() { + // TODO: delete old undo files when calling the destructor. +} // Return the undo filename. // The filename is constructed in a static internal buffer and // this buffer is overwritten by every call of this function. // The return value is a pointer to this internal string. -static char *undo_filename(int level) { - static char undo_path[FL_PATH_MAX] = ""; // Undo path - static unsigned int undo_path_len = 0; // length w/o filename - - if (!undo_path_len) { - fluid_prefs.getUserdataPath(undo_path, sizeof(undo_path)); - undo_path_len = (unsigned int)strlen(undo_path); +char *Undo::filename(int level) { + if (!path_len_) { + Fluid.preferences.getUserdataPath(path_, sizeof(path_)); + path_len_ = (unsigned int)strlen(path_); } // append filename: "undo_PID_LEVEL.fl" - snprintf(undo_path + undo_path_len, - sizeof(undo_path) - undo_path_len - 1, + snprintf(path_ + path_len_, + sizeof(path_) - path_len_ - 1, "undo_%d_%d.fl", getpid(), level); - return undo_path; + return path_; } // Redo menu callback -void redo_cb(Fl_Widget *, void *) { +void Undo::redo() { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); - undo_once_type = 0; + once_type_ = OnceType::ALWAYS; - if (undo_current >= undo_last) { + if (current_ >= last_) { fl_beep(); return; } - undo_suspend(); + suspend(); if (widget_browser) { widget_browser->save_scroll_position(); widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); - if (!fld::io::read_file(undo_filename(undo_current + 1), 0)) { + if (!fld::io::read_file(proj_, filename(current_ + 1), 0)) { // Unable to read checkpoint file, don't redo... widget_browser->rebuild(); - g_project.update_settings_dialog(); - undo_resume(); + proj_.update_settings_dialog(); + resume(); return; } if (reload_panel) { - for (Fl_Type *t = Fl_Type::first; t; t=t->next) { - if (t->is_widget() && t->selected) - t->open(); + for (auto w: Fluid.proj.tree.all_selected_widgets()) { + w->open(); } } if (widget_browser) widget_browser->restore_scroll_position(); - undo_current ++; + current_ ++; // Update modified flag... - set_modflag(undo_current != undo_save); + proj_.set_modflag(current_ != save_); widget_browser->rebuild(); - g_project.update_settings_dialog(); + proj_.update_settings_dialog(); // Update undo/redo menu items... - // if (undo_current >= undo_last) Main_Menu[redo_item].deactivate(); - // Main_Menu[undo_item].activate(); - undo_resume(); + // if (current_ >= last_) main_menu[redo_item].deactivate(); + // main_menu[undo_item].activate(); + resume(); } // Undo menu callback -void undo_cb(Fl_Widget *, void *) { +void Undo::undo() { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); - undo_once_type = 0; + once_type_ = OnceType::ALWAYS; - if (undo_current <= 0) { + if (current_ <= 0) { fl_beep(); return; } - if (undo_current == undo_last) { - fld::io::write_file(undo_filename(undo_current)); + if (current_ == last_) { + fld::io::write_file(proj_, filename(current_)); } - undo_suspend(); + suspend(); // Undo first deletes all widgets which resets the widget_tree browser. // Save the current scroll position, so we don't scroll back to 0 at undo. // TODO: make the scroll position part of the .fl project file @@ -148,16 +146,16 @@ void undo_cb(Fl_Widget *, void *) { widget_browser->new_list(); } int reload_panel = (the_panel && the_panel->visible()); - if (!fld::io::read_file(undo_filename(undo_current - 1), 0)) { + if (!fld::io::read_file(proj_, filename(current_ - 1), 0)) { // Unable to read checkpoint file, don't undo... widget_browser->rebuild(); - g_project.update_settings_dialog(); - set_modflag(0, 0); - undo_resume(); + proj_.update_settings_dialog(); + proj_.set_modflag(0, 0); + resume(); return; } if (reload_panel) { - for (Fl_Type *t = Fl_Type::first; t; t=t->next) { + for (Node *t = Fluid.proj.tree.first; t; t=t->next) { if (t->is_widget() && t->selected) { t->open(); break; @@ -168,32 +166,32 @@ void undo_cb(Fl_Widget *, void *) { // Ideally, we would save the browser position inside the undo file. if (widget_browser) widget_browser->restore_scroll_position(); - undo_current --; + current_ --; // Update modified flag... - set_modflag(undo_current != undo_save); + proj_.set_modflag(current_ != save_); // Update undo/redo menu items... - // if (undo_current <= 0) Main_Menu[undo_item].deactivate(); - // Main_Menu[redo_item].activate(); + // if (current_ <= 0) main_menu[undo_item].deactivate(); + // main_menu[redo_item].activate(); widget_browser->rebuild(); - g_project.update_settings_dialog(); - undo_resume(); + proj_.update_settings_dialog(); + resume(); } /** \param[in] type set a new type, or set to 0 to clear the once_type without setting a checkpoint \return 1 if the checkpoint was set, 0 if this is a repeating event */ -int undo_checkpoint_once(int type) { - if (type == 0) { - undo_once_type = 0; +int Undo::checkpoint(OnceType type) { + if (type == OnceType::ALWAYS) { + once_type_ = OnceType::ALWAYS; return 0; } - if (undo_paused) return 0; - if (undo_once_type != type) { - undo_checkpoint(); - undo_once_type = type; + if (paused_) return 0; + if (once_type_ != type) { + checkpoint(); + once_type_ = type; return 1; } else { // do not add more checkpoints for the same undo type @@ -202,64 +200,72 @@ int undo_checkpoint_once(int type) { } // Save current file to undo buffer -void undo_checkpoint() { - // printf("undo_checkpoint(): undo_current=%d, undo_paused=%d, modflag=%d\n", - // undo_current, undo_paused, modflag); +void Undo::checkpoint() { + // printf("checkpoint(): current_=%d, paused_=%d, modflag=%d\n", + // current_, paused_, modflag); - // Don't checkpoint if undo_suspend() has been called... - if (undo_paused) return; + // Don't checkpoint if suspend() has been called... + if (paused_) return; // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); - undo_once_type = 0; + once_type_ = OnceType::ALWAYS; // Save the current UI to a checkpoint file... - const char *filename = undo_filename(undo_current); - if (!fld::io::write_file(filename)) { + const char *file = filename(current_); + if (!fld::io::write_file(proj_, file)) { // Don't attempt to do undo stuff if we can't write a checkpoint file... - perror(filename); + perror(file); return; } // Update the saved level... - if (modflag && undo_current <= undo_save) undo_save = -1; - else if (!modflag) undo_save = undo_current; + if (proj_.modflag && current_ <= save_) save_ = -1; + else if (!proj_.modflag) save_ = current_; // Update the current undo level... - undo_current ++; - undo_last = undo_current; - if (undo_current > undo_max) undo_max = undo_current; + current_ ++; + last_ = current_; + if (current_ > max_) max_ = current_; // Enable the Undo and disable the Redo menu items... - // Main_Menu[undo_item].activate(); - // Main_Menu[redo_item].deactivate(); + // main_menu[undo_item].activate(); + // main_menu[redo_item].deactivate(); } // Clear undo buffer -void undo_clear() { +void Undo::clear() { // int undo_item = main_menubar->find_index(undo_cb); // int redo_item = main_menubar->find_index(redo_cb); // Remove old checkpoint files... - for (int i = 0; i <= undo_max; i ++) { - fl_unlink(undo_filename(i)); + for (int i = 0; i <= max_; i ++) { + fl_unlink(filename(i)); } // Reset current, last, and save indices... - undo_current = undo_last = undo_max = 0; - if (modflag) undo_save = -1; - else undo_save = 0; + current_ = last_ = max_ = 0; + if (proj_.modflag) save_ = -1; + else save_ = 0; // Disable the Undo and Redo menu items... - // Main_Menu[undo_item].deactivate(); - // Main_Menu[redo_item].deactivate(); + // main_menu[undo_item].deactivate(); + // main_menu[redo_item].deactivate(); } // Resume undo checkpoints -void undo_resume() { - undo_paused--; +void Undo::resume() { + paused_--; } // Suspend undo checkpoints -void undo_suspend() { - undo_paused++; +void Undo::suspend() { + paused_++; +} + +void Undo::undo_cb(Fl_Widget *, void *) { + Fluid.proj.undo.undo(); +} + +void Undo::redo_cb(Fl_Widget *, void *) { + Fluid.proj.undo.redo(); } diff --git a/fluid/proj/undo.h b/fluid/proj/undo.h new file mode 100644 index 000000000..f87c747bd --- /dev/null +++ b/fluid/proj/undo.h @@ -0,0 +1,93 @@ +// +// Fluid Undo header for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2025 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 undo_h +#define undo_h + +#include + +class Fl_Widget; + +namespace fld { + +class Project; + +namespace proj { + +class Undo +{ +public: + + enum class OnceType { + ALWAYS = 0, + WINDOW_RESIZE + }; + + /// Link Undo class to this project. + Project &proj_; + /// Current undo level in buffer + int current_ = 0; + /// Last undo level in buffer + int last_ = 0; + // Maximum undo level used + int max_ = 0; + /// Last undo level that was saved + int save_ = -1; + // Undo checkpointing paused? + int paused_ = 0; + // Undo file path + char path_[FL_PATH_MAX] { }; + // length w/o filename + unsigned int path_len_ = 0; + /// Suspend further undos of the same type + OnceType once_type_ = OnceType::ALWAYS; + +public: + + // Constructor. + Undo(Project &p); + // Destructor. + ~Undo(); + + // Save current file to undo buffer + void checkpoint(); + // Save undo buffer once until a different checkpoint type is called + int checkpoint(OnceType type); + // Clear undo buffer + void clear(); + // Resume undo checkpoints + void resume(); + // Suspend undo checkpoints + void suspend(); + // Return the undo filename. + char *filename(int level); + + // Redo menu callback + void redo(); + // Undo menu callback + void undo(); + + // Redo menu callback + static void redo_cb(Fl_Widget *, void *); + // Undo menu callback + static void undo_cb(Fl_Widget *, void *); +}; + +} // namespace fld +} // namespace proj + + +#endif // !undo_h diff --git a/fluid/rsrcs/pixmaps.cxx b/fluid/rsrcs/pixmaps.cxx index dbcebe043..640cf79d9 100644 --- a/fluid/rsrcs/pixmaps.cxx +++ b/fluid/rsrcs/pixmaps.cxx @@ -1,7 +1,7 @@ // -// Fluid Image management for the Fast Light Tool Kit (FLTK). +// Fluid GUI Image code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -16,7 +16,7 @@ #include "rsrcs/pixmaps.h" -#include "nodes/Fl_Type.h" +#include "nodes/Node.h" #include @@ -90,7 +90,7 @@ Fl_Pixmap *protected_pixmap; Fl_Pixmap *invisible_pixmap; Fl_Pixmap *compressed_pixmap; -Fl_Pixmap *pixmap[ID_Max_] = { NULL }; +Fl_Pixmap *pixmap[(int)Type::Max_] = { nullptr }; /** Draw a zoom cross pointing in all four diagonal directions @@ -152,74 +152,74 @@ void loadPixmaps() invisible_pixmap = new Fl_Pixmap(invisible_xpm); invisible_pixmap->scale(16, 16); compressed_pixmap = new Fl_Pixmap(compressed_xpm); compressed_pixmap->scale(16, 16); - pixmap[ID_Window] = tmp = new Fl_Pixmap(flWindow_xpm); tmp->scale(16, 16); - pixmap[ID_Button] = tmp = new Fl_Pixmap(flButton_xpm); tmp->scale(16, 16); - pixmap[ID_Check_Button] = tmp = new Fl_Pixmap(flCheckButton_xpm); tmp->scale(16, 16); - pixmap[ID_Round_Button] = tmp = new Fl_Pixmap(flRoundButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Window] = tmp = new Fl_Pixmap(flWindow_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Button] = tmp = new Fl_Pixmap(flButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Check_Button] = tmp = new Fl_Pixmap(flCheckButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Round_Button] = tmp = new Fl_Pixmap(flRoundButton_xpm); tmp->scale(16, 16); - pixmap[ID_Box] = tmp = new Fl_Pixmap(flBox_xpm); tmp->scale(16, 16); - pixmap[ID_Group] = tmp = new Fl_Pixmap(flGroup_xpm); tmp->scale(16, 16); - pixmap[ID_Function] = tmp = new Fl_Pixmap(flFunction_xpm); tmp->scale(16, 16); - pixmap[ID_Code] = tmp = new Fl_Pixmap(flCode_xpm); tmp->scale(16, 16); - pixmap[ID_CodeBlock] = tmp = new Fl_Pixmap(flCodeBlock_xpm); tmp->scale(16, 16); - pixmap[ID_Decl] = tmp = new Fl_Pixmap(flDeclaration_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Box] = tmp = new Fl_Pixmap(flBox_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Group] = tmp = new Fl_Pixmap(flGroup_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Function] = tmp = new Fl_Pixmap(flFunction_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Code] = tmp = new Fl_Pixmap(flCode_xpm); tmp->scale(16, 16); + pixmap[(int)Type::CodeBlock] = tmp = new Fl_Pixmap(flCodeBlock_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Decl] = tmp = new Fl_Pixmap(flDeclaration_xpm); tmp->scale(16, 16); - pixmap[ID_DeclBlock] = tmp = new Fl_Pixmap(flDeclarationBlock_xpm); tmp->scale(16, 16); - pixmap[ID_Class] = tmp = new Fl_Pixmap(flClass_xpm); tmp->scale(16, 16); - pixmap[ID_Tabs] = tmp = new Fl_Pixmap(flTabs_xpm); tmp->scale(16, 16); - pixmap[ID_Input] = tmp = new Fl_Pixmap(flInput_xpm); tmp->scale(16, 16); - pixmap[ID_Choice] = tmp = new Fl_Pixmap(flChoice_xpm); tmp->scale(16, 16); + pixmap[(int)Type::DeclBlock] = tmp = new Fl_Pixmap(flDeclarationBlock_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Class] = tmp = new Fl_Pixmap(flClass_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Tabs] = tmp = new Fl_Pixmap(flTabs_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Input] = tmp = new Fl_Pixmap(flInput_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Choice] = tmp = new Fl_Pixmap(flChoice_xpm); tmp->scale(16, 16); - pixmap[ID_Menu_Item] = tmp = new Fl_Pixmap(flMenuitem_xpm); tmp->scale(16, 16); - pixmap[ID_Menu_Bar] = tmp = new Fl_Pixmap(flMenubar_xpm); tmp->scale(16, 16); - pixmap[ID_Submenu] = tmp = new Fl_Pixmap(flSubmenu_xpm); tmp->scale(16, 16); - pixmap[ID_Scroll] = tmp = new Fl_Pixmap(flScroll_xpm); tmp->scale(16, 16); - pixmap[ID_Tile] = tmp = new Fl_Pixmap(flTile_xpm); tmp->scale(16, 16); - pixmap[ID_Wizard] = tmp = new Fl_Pixmap(flWizard_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Menu_Item] = tmp = new Fl_Pixmap(flMenuitem_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Menu_Bar] = tmp = new Fl_Pixmap(flMenubar_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Submenu] = tmp = new Fl_Pixmap(flSubmenu_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Scroll] = tmp = new Fl_Pixmap(flScroll_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Tile] = tmp = new Fl_Pixmap(flTile_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Wizard] = tmp = new Fl_Pixmap(flWizard_xpm); tmp->scale(16, 16); - pixmap[ID_Pack] = tmp = new Fl_Pixmap(flPack_xpm); tmp->scale(16, 16); - pixmap[ID_Return_Button] = tmp = new Fl_Pixmap(flReturnButton_xpm); tmp->scale(16, 16); - pixmap[ID_Light_Button] = tmp = new Fl_Pixmap(flLightButton_xpm); tmp->scale(16, 16); - pixmap[ID_Repeat_Button] = tmp = new Fl_Pixmap(flRepeatButton_xpm); tmp->scale(16, 16); - pixmap[ID_Menu_Button] = tmp = new Fl_Pixmap(flMenuButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Pack] = tmp = new Fl_Pixmap(flPack_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Return_Button] = tmp = new Fl_Pixmap(flReturnButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Light_Button] = tmp = new Fl_Pixmap(flLightButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Repeat_Button] = tmp = new Fl_Pixmap(flRepeatButton_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Menu_Button] = tmp = new Fl_Pixmap(flMenuButton_xpm); tmp->scale(16, 16); - pixmap[ID_Output] = tmp = new Fl_Pixmap(flOutput_xpm); tmp->scale(16, 16); - pixmap[ID_Text_Display] = tmp = new Fl_Pixmap(flTextDisplay_xpm); tmp->scale(16, 16); - pixmap[ID_Text_Editor] = tmp = new Fl_Pixmap(flTextEdit_xpm); tmp->scale(16, 16); - pixmap[ID_File_Input] = tmp = new Fl_Pixmap(flFileInput_xpm); tmp->scale(16, 16); - pixmap[ID_Browser] = tmp = new Fl_Pixmap(flBrowser_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Output] = tmp = new Fl_Pixmap(flOutput_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Text_Display] = tmp = new Fl_Pixmap(flTextDisplay_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Text_Editor] = tmp = new Fl_Pixmap(flTextEdit_xpm); tmp->scale(16, 16); + pixmap[(int)Type::File_Input] = tmp = new Fl_Pixmap(flFileInput_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Browser] = tmp = new Fl_Pixmap(flBrowser_xpm); tmp->scale(16, 16); - pixmap[ID_Check_Browser] = tmp = new Fl_Pixmap(flCheckBrowser_xpm); tmp->scale(16, 16); - pixmap[ID_File_Browser] = tmp = new Fl_Pixmap(flFileBrowser_xpm); tmp->scale(16, 16); - pixmap[ID_Clock] = tmp = new Fl_Pixmap(flClock_xpm); tmp->scale(16, 16); - pixmap[ID_Help_View] = tmp = new Fl_Pixmap(flHelp_xpm); tmp->scale(16, 16); - pixmap[ID_Progress] = tmp = new Fl_Pixmap(flProgress_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Check_Browser] = tmp = new Fl_Pixmap(flCheckBrowser_xpm); tmp->scale(16, 16); + pixmap[(int)Type::File_Browser] = tmp = new Fl_Pixmap(flFileBrowser_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Clock] = tmp = new Fl_Pixmap(flClock_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Help_View] = tmp = new Fl_Pixmap(flHelp_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Progress] = tmp = new Fl_Pixmap(flProgress_xpm); tmp->scale(16, 16); - pixmap[ID_Slider] = tmp = new Fl_Pixmap(flSlider_xpm); tmp->scale(16, 16); - pixmap[ID_Scrollbar] = tmp = new Fl_Pixmap(flScrollBar_xpm); tmp->scale(16, 16); - pixmap[ID_Value_Slider] = tmp = new Fl_Pixmap(flValueSlider_xpm); tmp->scale(16, 16); - pixmap[ID_Adjuster] = tmp = new Fl_Pixmap(flAdjuster_xpm); tmp->scale(16, 16); - pixmap[ID_Counter] = tmp = new Fl_Pixmap(flCounter_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Slider] = tmp = new Fl_Pixmap(flSlider_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Scrollbar] = tmp = new Fl_Pixmap(flScrollBar_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Value_Slider] = tmp = new Fl_Pixmap(flValueSlider_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Adjuster] = tmp = new Fl_Pixmap(flAdjuster_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Counter] = tmp = new Fl_Pixmap(flCounter_xpm); tmp->scale(16, 16); - pixmap[ID_Dial] = tmp = new Fl_Pixmap(flDial_xpm); tmp->scale(16, 16); - pixmap[ID_Roller] = tmp = new Fl_Pixmap(flRoller_xpm); tmp->scale(16, 16); - pixmap[ID_Value_Input] = tmp = new Fl_Pixmap(flValueInput_xpm); tmp->scale(16, 16); - pixmap[ID_Value_Output] = tmp = new Fl_Pixmap(flValueOutput_xpm); tmp->scale(16, 16); - pixmap[ID_Comment] = tmp = new Fl_Pixmap(flComment_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Dial] = tmp = new Fl_Pixmap(flDial_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Roller] = tmp = new Fl_Pixmap(flRoller_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Value_Input] = tmp = new Fl_Pixmap(flValueInput_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Value_Output] = tmp = new Fl_Pixmap(flValueOutput_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Comment] = tmp = new Fl_Pixmap(flComment_xpm); tmp->scale(16, 16); - pixmap[ID_Spinner] = tmp = new Fl_Pixmap(flSpinner_xpm); tmp->scale(16, 16); - pixmap[ID_Widget_Class] = tmp = new Fl_Pixmap(flWidgetClass_xpm); tmp->scale(16, 16); - pixmap[ID_Data] = tmp = new Fl_Pixmap(flData_xpm); tmp->scale(16, 16); - pixmap[ID_Tree] = tmp = new Fl_Pixmap(flTree_xpm); tmp->scale(16, 16); - pixmap[ID_Table] = tmp = new Fl_Pixmap(flTable_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Spinner] = tmp = new Fl_Pixmap(flSpinner_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Widget_Class] = tmp = new Fl_Pixmap(flWidgetClass_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Data] = tmp = new Fl_Pixmap(flData_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Tree] = tmp = new Fl_Pixmap(flTree_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Table] = tmp = new Fl_Pixmap(flTable_xpm); tmp->scale(16, 16); - pixmap[ID_Terminal] = tmp = new Fl_Pixmap(flSimpleTerminal_xpm); tmp->scale(16, 16); - pixmap[ID_Input_Choice] = tmp = new Fl_Pixmap(flInputChoice_xpm); tmp->scale(16, 16); - pixmap[ID_Checkbox_Menu_Item] = tmp = new Fl_Pixmap(flCheckMenuitem_xpm); tmp->scale(16, 16); - pixmap[ID_Radio_Menu_Item] = tmp = new Fl_Pixmap(flRadioMenuitem_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Terminal] = tmp = new Fl_Pixmap(flSimpleTerminal_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Input_Choice] = tmp = new Fl_Pixmap(flInputChoice_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Checkbox_Menu_Item] = tmp = new Fl_Pixmap(flCheckMenuitem_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Radio_Menu_Item] = tmp = new Fl_Pixmap(flRadioMenuitem_xpm); tmp->scale(16, 16); - pixmap[ID_Flex] = tmp = new Fl_Pixmap(flFlex_xpm); tmp->scale(16, 16); - pixmap[ID_Grid] = tmp = new Fl_Pixmap(flGrid_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Flex] = tmp = new Fl_Pixmap(flFlex_xpm); tmp->scale(16, 16); + pixmap[(int)Type::Grid] = tmp = new Fl_Pixmap(flGrid_xpm); tmp->scale(16, 16); fl_add_symbol("fd_zoom", fd_zoom, 1); } diff --git a/fluid/rsrcs/pixmaps.h b/fluid/rsrcs/pixmaps.h index 628bcd199..a09362f3d 100644 --- a/fluid/rsrcs/pixmaps.h +++ b/fluid/rsrcs/pixmaps.h @@ -1,7 +1,7 @@ // -// Fluid Image management for the Fast Light Tool Kit (FLTK). +// Fluid GUI Image header for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2021 by Bill Spitzak and others. +// Copyright 1998-2025 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/tools/ExternalCodeEditor_UNIX.cxx b/fluid/tools/ExternalCodeEditor_UNIX.cxx index bf472d896..9e9ffd00e 100644 --- a/fluid/tools/ExternalCodeEditor_UNIX.cxx +++ b/fluid/tools/ExternalCodeEditor_UNIX.cxx @@ -5,8 +5,8 @@ #include "ExternalCodeEditor_UNIX.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include /* Fl_Timeout_Handler.. */ #include /* fl_alert() */ @@ -23,9 +23,11 @@ #include /* free().. */ #include /* snprintf().. */ +using namespace fld; + // Static local data static int L_editors_open = 0; // keep track of #editors open -static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback +static Fl_Timeout_Handler L_update_timer_cb = nullptr; // app's update timer callback // [Static/Local] See if file exists static int is_file(const char *filename) { @@ -57,7 +59,7 @@ static int is_dir(const char *dirname) { */ ExternalCodeEditor::ExternalCodeEditor() { pid_ = -1; - filename_ = 0; + filename_ = nullptr; file_mtime_ = 0; file_size_ = 0; alert_pipe_[0] = alert_pipe_[1] = -1; @@ -69,11 +71,11 @@ ExternalCodeEditor::ExternalCodeEditor() { This also closes the external editor. */ ExternalCodeEditor::~ExternalCodeEditor() { - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("ExternalCodeEditor() DTOR CALLED (this=%p, pid=%ld)\n", (void*)this, (long)pid_); close_editor(); // close editor, delete tmp file - set_filename(0); // free()s filename + set_filename(nullptr); // free()s filename if (alert_pipe_open_) { Fl::remove_fd(alert_pipe_[0]); @@ -85,12 +87,12 @@ ExternalCodeEditor::~ExternalCodeEditor() { /** Set the filename for the file we wish to edit. Handles memory allocation/free. - If set to NULL, frees memory. + If set to nullptr, frees memory. \param[in] val new filename */ void ExternalCodeEditor::set_filename(const char *val) { if ( filename_ ) free((void*)filename_); - filename_ = val ? fl_strdup(val) : 0; + filename_ = val ? fl_strdup(val) : nullptr; } /** @@ -105,7 +107,7 @@ int ExternalCodeEditor::is_editing() { Wait for editor to close */ void ExternalCodeEditor::close_editor() { - if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pid_)); + if ( Fluid.debug_external_editor ) printf("close_editor() called: pid=%ld\n", long(pid_)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { @@ -119,7 +121,7 @@ void ExternalCodeEditor::close_editor() { switch ( fl_choice("Please close external editor\npid=%ld file=%s", "Force Close", // button 0 "Closed", // button 1 - 0, // button 2 + nullptr, // button 2 long(pid_), filename() ) ) { case 0: // Force Close kill_editor(); @@ -141,7 +143,7 @@ void ExternalCodeEditor::close_editor() { The dtor calls this to ensure no editors remain running when fluid exits. */ void ExternalCodeEditor::kill_editor() { - if ( G_debug ) printf("kill_editor() called: pid=%ld\n", (long)pid_); + if ( Fluid.debug_external_editor ) printf("kill_editor() called: pid=%ld\n", (long)pid_); if ( !is_editing() ) return; // editor not running? return.. kill(pid_, SIGTERM); // kill editor int wcount = 0; @@ -164,7 +166,7 @@ void ExternalCodeEditor::kill_editor() { } continue; case 1: // process reaped (reap_editor() sets pid_ to -1) - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("*** REAPED KILLED EXTERNAL EDITOR: PID %ld\n", (long)pid_reaped); break; } @@ -185,7 +187,7 @@ void ExternalCodeEditor::kill_editor() { \return -1 error getting file info (strerror() has reason) */ int ExternalCodeEditor::handle_changes(const char **code, int force) { - code[0] = 0; + code[0] = nullptr; if ( !is_editing() ) return 0; // Get current time/size info, see if file changed int changed = 0; @@ -239,13 +241,13 @@ int ExternalCodeEditor::remove_tmpfile() { if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { - if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); + if ( Fluid.debug_external_editor ) printf("Removing tmpfile '%s'\n", tmpfile); if ( remove(tmpfile) < 0 ) { fl_alert("WARNING: Can't remove() '%s': %s", tmpfile, strerror(errno)); return -1; } } - set_filename(0); + set_filename(nullptr); file_mtime_ = 0; file_size_ = 0; return 1; @@ -268,7 +270,7 @@ const char* ExternalCodeEditor::tmpdir_name() { void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { - if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); + if ( Fluid.debug_external_editor ) printf("Removing tmpdir '%s'\n", tmpdir); if ( rmdir(tmpdir) < 0 ) { fl_alert("WARNING: Can't rmdir() '%s': %s", tmpdir, strerror(errno)); } @@ -278,7 +280,7 @@ void ExternalCodeEditor::tmpdir_clear() { /** Creates temp dir (if doesn't exist) and returns the dirname as a static string. - \return NULL on error, dialog shows reason. + \return nullptr on error, dialog shows reason. */ const char* ExternalCodeEditor::create_tmpdir() { const char *dirname = tmpdir_name(); @@ -286,7 +288,7 @@ const char* ExternalCodeEditor::create_tmpdir() { if ( mkdir(dirname, 0777) < 0 ) { fl_alert("can't create directory '%s': %s", dirname, strerror(errno)); - return NULL; + return nullptr; } } return dirname; @@ -294,13 +296,13 @@ const char* ExternalCodeEditor::create_tmpdir() { /** Returns temp filename in static buffer. - \return NULL if can't, posts dialog explaining why. + \return nullptr if can't, posts dialog explaining why. */ const char* ExternalCodeEditor::tmp_filename() { static char path[FL_PATH_MAX+1]; const char *tmpdir = create_tmpdir(); - if ( !tmpdir ) return 0; - const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx" + if ( !tmpdir ) return nullptr; + const char *ext = Fluid.proj.code_file_name.c_str(); // e.g. ".cxx" snprintf(path, FL_PATH_MAX, "%s/%p%s", tmpdir, (void*)this, ext); path[FL_PATH_MAX] = 0; return path; @@ -308,12 +310,12 @@ const char* ExternalCodeEditor::tmp_filename() { /** Save string 'code' to 'filename', returning file's mtime/size. - 'code' can be NULL -- writes an empty file if so. + 'code' can be nullptr -- writes an empty file if so. \return 0 on success \return -1 on error (posts dialog with reason) */ static int save_file(const char *filename, const char *code) { - if ( code == 0 ) code = ""; // NULL? write an empty file + if ( code == nullptr ) code = ""; // nullptr? write an empty file int fd = open(filename, O_WRONLY|O_CREAT, 0666); if ( fd == -1 ) { fl_alert("ERROR: open() '%s': %s", filename, strerror(errno)); @@ -336,7 +338,7 @@ static int save_file(const char *filename, const char *code) { /** Convert string 's' to array of argv[], useful for execve(). - - 's' will be modified (words will be NULL separated) + - 's' will be modified (words will be nullptr separated) - argv[] will end up pointing to the words of 's' - Caller must free argv with: free(argv); \return -1 in case of memory allocation error @@ -346,14 +348,14 @@ static int make_args(char *s, // string containing words (gets trashed!) int *aargc, // pointer to argc char ***aargv) { // pointer to argv char *ss, **argv; - if ((argv=(char**)malloc(sizeof(char*) * (strlen(s)/2)))==NULL) { + if ((argv=(char**)malloc(sizeof(char*) * (strlen(s)/2)))==nullptr) { return -1; } int t; - for(t=0; (t==0)?(ss=strtok(s," \t")):(ss=strtok(0," \t")); t++) { + for(t=0; (t==0)?(ss=strtok(s," \t")):(ss=strtok(nullptr," \t")); t++) { argv[t] = ss; } - argv[t] = 0; + argv[t] = nullptr; aargv[0] = argv; aargc[0] = t; return(t); @@ -383,7 +385,7 @@ void ExternalCodeEditor::open_alert_pipe() { */ int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { - if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", + if ( Fluid.debug_external_editor ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); char cmd[1024]; snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename); @@ -399,7 +401,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, // NOTE: no FLTK calls after a fork. Use a pipe to tell the app if the // command can't launch int nargs; - char **args = 0; + char **args = nullptr; if (make_args(cmd, &nargs, &args) > 0) { execvp(args[0], args); // run command - doesn't return if succeeds if (alert_pipe_open_) { @@ -416,7 +418,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, default: // parent if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pid_, L_editors_open); break; } @@ -426,7 +428,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, /** Try to reap external editor process. - If 'pid_reaped' not NULL, returns PID of reaped editor. + If 'pid_reaped' not nullptr, returns PID of reaped editor. \return -2: editor not open \return -1: waitpid() failed (errno has reason) @@ -453,7 +455,7 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) { { stop_update_timer(); } break; } - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } @@ -462,7 +464,7 @@ int ExternalCodeEditor::reap_editor(pid_t *pid_reaped) { Open external editor using 'editor_cmd' to edit 'code'. 'code' contains multiline code to be edited as a temp file. - 'code' can be NULL -- edits an empty file if so. + 'code' can be nullptr -- edits an empty file if so. \return 0 if succeeds \return -1 if can't open editor (already open, etc), @@ -492,7 +494,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, filename(), (long)pid_); return 0; case 1: // process reaped, wpid is pid reaped - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", (long)wpid); break; // fall thru to open new editor instance } @@ -512,7 +514,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, file_mtime_ = sbuf.st_mtime; file_size_ = sbuf.st_size; if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor - if ( G_debug ) printf("Editor failed to start\n"); + if ( Fluid.debug_external_editor ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } return 0; @@ -523,7 +525,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, */ void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); + if ( Fluid.debug_external_editor ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } @@ -532,7 +534,7 @@ void ExternalCodeEditor::start_update_timer() { */ void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); + if ( Fluid.debug_external_editor ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } diff --git a/fluid/tools/ExternalCodeEditor_UNIX.h b/fluid/tools/ExternalCodeEditor_UNIX.h index 644f22afa..2142d5a10 100644 --- a/fluid/tools/ExternalCodeEditor_UNIX.h +++ b/fluid/tools/ExternalCodeEditor_UNIX.h @@ -7,7 +7,7 @@ #ifndef _EXTCODEEDITOR_H #define _EXTCODEEDITOR_H -#include "app/fluid.h" +#include "Fluid.h" #include @@ -42,7 +42,7 @@ public: ExternalCodeEditor(); ~ExternalCodeEditor(); int is_editing(); - int reap_editor(pid_t *pid_reaped=NULL); + int reap_editor(pid_t *pid_reaped=nullptr); void close_editor(); const char *filename() { return filename_; } int open_editor(const char *editor_cmd, const char *code); diff --git a/fluid/tools/ExternalCodeEditor_WIN32.cxx b/fluid/tools/ExternalCodeEditor_WIN32.cxx index 09688d16a..64d791400 100644 --- a/fluid/tools/ExternalCodeEditor_WIN32.cxx +++ b/fluid/tools/ExternalCodeEditor_WIN32.cxx @@ -17,8 +17,8 @@ // Note: This entire file Windows only. #include "tools/ExternalCodeEditor_WIN32.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include // Fl_Timeout_Handler.. #include // fl_alert() @@ -28,17 +28,17 @@ #include // snprintf() #include -extern int G_debug; // defined in fluid.cxx +using namespace fld; // Static local data static int L_editors_open = 0; // keep track of #editors open static Fl_Timeout_Handler L_update_timer_cb = 0; // app's update timer callback -static wchar_t *wbuf = NULL; -static char *abuf = NULL; +static wchar_t *wbuf = nullptr; +static char *abuf = nullptr; static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) { unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8); - unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length + unsigned wn = fl_utf8toUtf16(utf8, len, nullptr, 0) + 1; // Query length wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn); wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string wbuf[wn] = 0; @@ -47,7 +47,7 @@ static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) { static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) { unsigned len = (unsigned)wcslen(wstr); - unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length + unsigned wn = fl_utf8fromwc(nullptr, 0, wstr, len) + 1; // query length utf8 = (char *)realloc(utf8, wn); wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string utf8[wn] = 0; @@ -68,7 +68,7 @@ static const char *get_ms_errmsg() { DWORD msize = 0; // Get error message from Windows - msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, NULL); + msize = FormatMessageW(flags, 0, lastErr, langid, (LPWSTR)&mbuf, 0, nullptr); if ( msize == 0 ) { _snprintf(emsg, sizeof(emsg), "Error #%ld", (unsigned long)lastErr); } else { @@ -119,7 +119,7 @@ ExternalCodeEditor::~ExternalCodeEditor() { } // [Protected] Set the filename. Handles memory allocation/free -// If set to NULL, frees memory. +// If set to nullptr, frees memory. // void ExternalCodeEditor::set_filename(const char *val) { if ( filename_ ) free((void*)filename_); @@ -137,7 +137,7 @@ static BOOL CALLBACK terminate_app_enum(HWND hwnd, LPARAM lParam) { GetWindowThreadProcessId(hwnd, &dwID); if (dwID == (DWORD)lParam) { PostMessage(hwnd, WM_CLOSE, 0, 0); - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("terminate_app_enum() sends WIN_CLOSE to hwnd=%p\n", (void*)hwnd); } return TRUE; @@ -154,12 +154,12 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) { // Wait on handle. If it closes, great. If it times out, use TerminateProcess() int ret = 0; if ( WaitForSingleObject(hProc, msecTimeout) != WAIT_OBJECT_0 ) { - if ( G_debug ) { + if ( Fluid.debug_external_editor ) { printf("WARNING: sent WIN_CLOSE, but timeout after %ld msecs.." "trying TerminateProcess\n", msecTimeout); } if ( TerminateProcess(hProc, 0) == 0 ) { - if ( G_debug ) { + if ( Fluid.debug_external_editor ) { printf("ERROR: TerminateProcess() for pid=%ld failed: %s\n", long(pid), get_ms_errmsg()); } @@ -176,7 +176,7 @@ static int terminate_app(DWORD pid, DWORD msecTimeout) { // [Protected] Wait for editor to close void ExternalCodeEditor::close_editor() { - if ( G_debug ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId)); + if ( Fluid.debug_external_editor ) printf("close_editor() called: pid=%ld\n", long(pinfo_.dwProcessId)); // Wait until editor is closed + reaped while ( is_editing() ) { switch ( reap_editor() ) { @@ -210,7 +210,7 @@ void ExternalCodeEditor::close_editor() { // The dtor calls this to ensure no editors remain running when fluid exits. // void ExternalCodeEditor::kill_editor() { - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("kill_editor() called: pid=%ld\n", (long)pinfo_.dwProcessId); if ( !is_editing() ) return; switch ( terminate_app(pinfo_.dwProcessId, 500) ) { // kill editor, wait up to 1/2 sec to die @@ -222,7 +222,7 @@ void ExternalCodeEditor::kill_editor() { case 0: { // success -- process reaped DWORD pid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("*** kill_editor() REAP pid=%ld #open=%ld\n", long(pid), long(L_editors_open)); break; @@ -252,10 +252,10 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) { HANDLE fh = CreateFileW(wbuf, // file to read GENERIC_READ, // reading only FILE_SHARE_READ, // sharing -- allow read share; just getting file size - NULL, // security + nullptr, // security OPEN_EXISTING, // create flags -- must exist 0, // misc flags - NULL); // templates + nullptr); // templates if ( fh == INVALID_HANDLE_VALUE ) return -1; LARGE_INTEGER fsize; // Get file size @@ -315,18 +315,18 @@ int ExternalCodeEditor::handle_changes(const char **code, int force) { // int ExternalCodeEditor::remove_tmpfile() { const char *tmpfile = filename(); - if ( G_debug ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)"); + if ( Fluid.debug_external_editor ) printf("remove_tmpfile() '%s'\n", tmpfile ? tmpfile : "(empty)"); if ( !tmpfile ) return 0; // Filename set? remove (if exists) and zero filename/mtime/size if ( is_file(tmpfile) ) { - if ( G_debug ) printf("Removing tmpfile '%s'\n", tmpfile); + if ( Fluid.debug_external_editor ) printf("Removing tmpfile '%s'\n", tmpfile); utf8_to_wchar(tmpfile, wbuf); if (DeleteFileW(wbuf) == 0) { fl_alert("WARNING: Can't DeleteFile() '%s': %s", tmpfile, get_ms_errmsg()); return -1; } } else { - if ( G_debug ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile); + if ( Fluid.debug_external_editor ) printf("remove_tmpfile(): is_file(%s) failed\n", tmpfile); } set_filename(0); memset(&file_mtime_, 0, sizeof(file_mtime_)); @@ -348,7 +348,7 @@ const char* ExternalCodeEditor::tmpdir_name() { static char dirname[100]; _snprintf(dirname, sizeof(dirname), "%s.fluid-%ld", tempdir, (long)GetCurrentProcessId()); - if ( G_debug ) printf("tmpdir_name(): '%s'\n", dirname); + if ( Fluid.debug_external_editor ) printf("tmpdir_name(): '%s'\n", dirname); return dirname; } @@ -358,7 +358,7 @@ const char* ExternalCodeEditor::tmpdir_name() { void ExternalCodeEditor::tmpdir_clear() { const char *tmpdir = tmpdir_name(); if ( is_dir(tmpdir) ) { - if ( G_debug ) printf("Removing tmpdir '%s'\n", tmpdir); + if ( Fluid.debug_external_editor ) printf("Removing tmpdir '%s'\n", tmpdir); utf8_to_wchar(tmpdir, wbuf); if ( RemoveDirectoryW(wbuf) == 0 ) { fl_alert("WARNING: Can't RemoveDirectory() '%s': %s", @@ -368,7 +368,7 @@ void ExternalCodeEditor::tmpdir_clear() { } // [Protected] Creates temp dir (if doesn't exist) and returns the dirname -// as a static string. Returns NULL on error, dialog shows reason. +// as a static string. Returns nullptr on error, dialog shows reason. // const char* ExternalCodeEditor::create_tmpdir() { const char *dirname = tmpdir_name(); @@ -377,27 +377,27 @@ const char* ExternalCodeEditor::create_tmpdir() { if (CreateDirectoryW(wbuf, 0) == 0) { fl_alert("can't create directory '%s': %s", dirname, get_ms_errmsg()); - return NULL; + return nullptr; } } return dirname; } // [Protected] Returns temp filename in static buffer. -// Returns NULL if can't, posts dialog explaining why. +// Returns nullptr if can't, posts dialog explaining why. // const char* ExternalCodeEditor::tmp_filename() { static char path[512]; const char *tmpdir = create_tmpdir(); if ( !tmpdir ) return 0; - const char *ext = g_project.code_file_name.c_str(); // e.g. ".cxx" + const char *ext = Fluid.proj.code_file_name.c_str(); // e.g. ".cxx" _snprintf(path, sizeof(path), "%s\\%p%s", tmpdir, (void*)this, ext); path[sizeof(path)-1] = 0; return path; } // [Static/Local] Save string 'code' to 'filename', returning file's mtime/size -// 'code' can be NULL -- writes an empty file if so. +// 'code' can be nullptr -- writes an empty file if so. // Returns: // 0 on success // -1 on error (posts dialog with reason) @@ -406,17 +406,17 @@ static int save_file(const char *filename, const char *code, FILETIME &file_mtime, // return these since in win32 it's.. LARGE_INTEGER &file_size) { // ..efficient to get while file open - if ( code == 0 ) code = ""; // NULL? write an empty file + if ( code == 0 ) code = ""; // nullptr? write an empty file memset(&file_mtime, 0, sizeof(file_mtime)); memset(&file_size, 0, sizeof(file_size)); utf8_to_wchar(filename, wbuf); HANDLE fh = CreateFileW(wbuf, // filename GENERIC_WRITE, // write only 0, // sharing -- no share during write - NULL, // security + nullptr, // security CREATE_ALWAYS, // create flags -- recreate FILE_ATTRIBUTE_NORMAL, // misc flags - NULL); // templates + nullptr); // templates if ( fh == INVALID_HANDLE_VALUE ) { fl_alert("ERROR: couldn't create file '%s': %s", filename, get_ms_errmsg()); @@ -426,7 +426,7 @@ static int save_file(const char *filename, DWORD clen = (DWORD)strlen(code); DWORD count = 0; int ret = 0; - if ( WriteFile(fh, code, clen, &count, NULL) == 0 ) { + if ( WriteFile(fh, code, clen, &count, nullptr) == 0 ) { fl_alert("ERROR: WriteFile() '%s': %s", filename, get_ms_errmsg()); ret = -1; // fallthru to CloseHandle() } else if ( count != clen ) { @@ -459,7 +459,7 @@ static int save_file(const char *filename, // int ExternalCodeEditor::start_editor(const char *editor_cmd, const char *filename) { - if ( G_debug ) printf("start_editor() cmd='%s', filename='%s'\n", + if ( Fluid.debug_external_editor ) printf("start_editor() cmd='%s', filename='%s'\n", editor_cmd, filename); // Startup info STARTUPINFOW sinfo; @@ -474,14 +474,14 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, _snprintf(cmd, sizeof(cmd), "%s %s", editor_cmd, filename); utf8_to_wchar(cmd, wbuf); // Start editor process - if (CreateProcessW(NULL, // app name + if (CreateProcessW(nullptr, // app name wbuf, // command to exec - NULL, // secure attribs - NULL, // thread secure attribs + nullptr, // secure attribs + nullptr, // thread secure attribs FALSE, // handle inheritance 0, // creation flags - NULL, // environ block - NULL, // current dir + nullptr, // environ block + nullptr, // current dir &sinfo, // startup info &pinfo_) == 0 ) { // process info fl_alert("CreateProcess() failed to start '%s': %s", @@ -490,7 +490,7 @@ int ExternalCodeEditor::start_editor(const char *editor_cmd, } if ( L_editors_open++ == 0 ) // first editor? start timers { start_update_timer(); } - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("--- EDITOR STARTED: pid_=%ld #open=%d\n", (long)pinfo_.dwProcessId, L_editors_open); return 0; @@ -512,7 +512,7 @@ void ExternalCodeEditor::reap_cleanup() { } // [Public] Try to reap external editor process -// If 'pid_reaped' not NULL, returns PID of reaped editor. +// If 'pid_reaped' not nullptr, returns PID of reaped editor. // Returns: // -2 -- editor not open // -1 -- WaitForSingleObject() failed (get_ms_errmsg() has reason) @@ -534,7 +534,7 @@ int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) { DWORD wpid = pinfo_.dwProcessId; // save pid reap_cleanup(); // clears pinfo_ if ( pid_reaped ) *pid_reaped = wpid; // return pid to caller - if ( G_debug ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", + if ( Fluid.debug_external_editor ) printf("*** EDITOR REAPED: pid=%ld #open=%d\n", long(wpid), L_editors_open); return 1; } @@ -548,7 +548,7 @@ int ExternalCodeEditor::reap_editor(DWORD *pid_reaped) { // [Public] Open external editor using 'editor_cmd' to edit 'code'. // // 'code' contains multiline code to be edited as a temp file. -// 'code' can be NULL -- edits an empty file if so. +// 'code' can be nullptr -- edits an empty file if so. // // Returns: // 0 if succeeds @@ -579,7 +579,7 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, filename(), long(pinfo_.dwProcessId)); return 0; case 1: // process reaped, wpid is pid reaped - if ( G_debug ) + if ( Fluid.debug_external_editor ) printf("*** REAPED EXTERNAL EDITOR: PID %ld\n", long(wpid)); break; // fall thru to open new editor instance } @@ -592,12 +592,12 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, return -1; // errors were shown in dialog } if ( start_editor(editor_cmd, filename()) < 0 ) { // open file in external editor - if ( G_debug ) printf("Editor failed to start\n"); + if ( Fluid.debug_external_editor ) printf("Editor failed to start\n"); return -1; // errors were shown in dialog } // New editor opened -- start update timer (if not already) if ( L_update_timer_cb && !Fl::has_timeout(L_update_timer_cb) ) { - if ( G_debug ) printf("--- Editor opened: STARTING UPDATE TIMER\n"); + if ( Fluid.debug_external_editor ) printf("--- Editor opened: STARTING UPDATE TIMER\n"); Fl::add_timeout(2.0, L_update_timer_cb); } return 0; @@ -606,14 +606,14 @@ int ExternalCodeEditor::open_editor(const char *editor_cmd, // [Public/Static] Start update timer void ExternalCodeEditor::start_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STARTING UPDATES\n"); + if ( Fluid.debug_external_editor ) printf("--- TIMER: STARTING UPDATES\n"); Fl::add_timeout(2.0, L_update_timer_cb); } // [Public/Static] Stop update timer void ExternalCodeEditor::stop_update_timer() { if ( !L_update_timer_cb ) return; - if ( G_debug ) printf("--- TIMER: STOPPING UPDATES\n"); + if ( Fluid.debug_external_editor ) printf("--- TIMER: STOPPING UPDATES\n"); Fl::remove_timeout(L_update_timer_cb); } diff --git a/fluid/tools/ExternalCodeEditor_WIN32.h b/fluid/tools/ExternalCodeEditor_WIN32.h index 97d93e495..83c50a742 100644 --- a/fluid/tools/ExternalCodeEditor_WIN32.h +++ b/fluid/tools/ExternalCodeEditor_WIN32.h @@ -43,7 +43,7 @@ public: ExternalCodeEditor(); ~ExternalCodeEditor(); int is_editing(); - int reap_editor(DWORD *pid_reaped=NULL); + int reap_editor(DWORD *pid_reaped=nullptr); void close_editor(); const char *filename() { return filename_; } int open_editor(const char *editor_cmd, const char *code); diff --git a/fluid/tools/autodoc.cxx b/fluid/tools/autodoc.cxx index 295ab8d2f..c87b59bc2 100644 --- a/fluid/tools/autodoc.cxx +++ b/fluid/tools/autodoc.cxx @@ -18,11 +18,11 @@ #include "tools/autodoc.h" -#include "app/fluid.h" -#include "app/project.h" +#include "Fluid.h" +#include "Project.h" #include "nodes/factory.h" -#include "nodes/Fl_Widget_Type.h" -#include "nodes/Fl_Window_Type.h" +#include "nodes/Widget_Node.h" +#include "nodes/Window_Node.h" #include "panels/widget_panel.h" #include "panels/function_panel.h" #include "panels/settings_panel.h" @@ -232,7 +232,7 @@ void blend_alpha_bottom(const Fl_RGB_Image *img, int dy) { created in FLTK resolution, even if the screen uses a higher resolution. \param[in] filename the snapshot will be written to this file in png format - \param[in] w draw a bounding box around all widgets in the NULL terminated list + \param[in] w draw a bounding box around all widgets in the nullptr terminated list \param[in] frame add a margin around the bounding box \param[in] blend add another margin around the bounding box that fades to full transparency \param[in] scale scale everything by this factor before saving it @@ -342,7 +342,7 @@ int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2, const Fl_Rect &blend, double scale) { - Fl_Widget *ww[3] = { w1, w2, NULL }; + Fl_Widget *ww[3] = { w1, w2, nullptr }; return fl_snapshot(filename, ww, frame, blend, scale); } @@ -363,7 +363,7 @@ int fl_snapshot(const char *filename, Fl_Widget *w, const Fl_Rect &blend, double scale) { - Fl_Widget *ww[2] = { w, NULL }; + Fl_Widget *ww[2] = { w, nullptr }; return fl_snapshot(filename, ww, frame, blend, scale); } @@ -383,27 +383,27 @@ void run_autodoc(const std::string &target_dir) { // Fl::scheme("gtk+"); // Create a silly project that contains all widgets that we want to document - new_project(false); + Fluid.new_project(false); - /*Fl_Type *t_func = */ add_new_widget_from_user("Function", Strategy::AS_LAST_CHILD, false); - Fl_Window_Type *t_win = (Fl_Window_Type*)add_new_widget_from_user("Fl_Window", Strategy::AS_LAST_CHILD, false); + /*Node *t_func = */ add_new_widget_from_user("Function", Strategy::AS_LAST_CHILD, false); + Window_Node *t_win = (Window_Node*)add_new_widget_from_user("Fl_Window", Strategy::AS_LAST_CHILD, false); t_win->label("My Main Window"); - Fl_Widget_Type *t_grp = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Group", Strategy::AS_LAST_CHILD, false); + Widget_Node *t_grp = (Widget_Node*)add_new_widget_from_user("Fl_Group", Strategy::AS_LAST_CHILD, false); t_grp->public_ = 0; - Fl_Widget_Type *t_btn = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); + Widget_Node *t_btn = (Widget_Node*)add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); t_btn->comment("Don't press this button!"); t_btn->name("emergency_btn"); ((Fl_Button*)t_btn->o)->shortcut(FL_COMMAND|'g'); - Fl_Type *t_sldr = add_new_widget_from_user("Fl_Slider", Strategy::AS_LAST_CHILD, false); - Fl_Type *t_inp = add_new_widget_from_user("Fl_Input", Strategy::AS_LAST_CHILD, false); - Fl_Type *t_flx = add_new_widget_from_user("Fl_Flex", Strategy::AS_LAST_CHILD, false); - Fl_Type *t_flxc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); + Node *t_sldr = add_new_widget_from_user("Fl_Slider", Strategy::AS_LAST_CHILD, false); + Node *t_inp = add_new_widget_from_user("Fl_Input", Strategy::AS_LAST_CHILD, false); + Node *t_flx = add_new_widget_from_user("Fl_Flex", Strategy::AS_LAST_CHILD, false); + Node *t_flxc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); select_only(t_grp); - Fl_Type *t_grd = add_new_widget_from_user("Fl_Grid", Strategy::AS_LAST_CHILD, false); - Fl_Type *t_grdc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); + Node *t_grd = add_new_widget_from_user("Fl_Grid", Strategy::AS_LAST_CHILD, false); + Node *t_grdc = add_new_widget_from_user("Fl_Button", Strategy::AS_LAST_CHILD, false); widget_browser->rebuild(); - g_project.update_settings_dialog(); + Fluid.proj.update_settings_dialog(); // TODO: FLUID overview @@ -417,9 +417,9 @@ void run_autodoc(const std::string &target_dir) { // explain menubar? // explain widget browser // explain widget browser entry - main_window->size(350, 320); - fl_snapshot((target_dir + "main_window.png").c_str(), main_window, win_margin, win_blend); - fl_snapshot((target_dir + "main_menubar.png").c_str(), main_menubar, row_margin, row_blend); + Fluid.main_window->size(350, 320); + fl_snapshot((target_dir + "Fluid.main_window.png").c_str(), Fluid.main_window, win_margin, win_blend); + fl_snapshot((target_dir + "main_menubar.png").c_str(), Fluid.main_menubar, row_margin, row_blend); fl_snapshot((target_dir + "main_browser.png").c_str(), widget_browser, FL_SNAP_AREA_CLEAR, Fl_Rect(0, 30, FL_SNAP_TO_WINDOW, 100), row_blend, 2.0); @@ -453,7 +453,7 @@ void run_autodoc(const std::string &target_dir) { codeview_panel->show(); Fl::wait(0.2); Fl::flush(); - update_codeview_cb(NULL, NULL); // must be visible on screen for this to work + update_codeview_cb(nullptr, nullptr); // must be visible on screen for this to work cv_tab->value(cv_source_tab); codeview_panel->redraw(); Fl::flush(); @@ -487,41 +487,41 @@ void run_autodoc(const std::string &target_dir) { // ---- dialog types // list and show all non-widget types and their respective dialog boxes - // -- ID_Function + // -- Type::Function Fl_Window *adoc_function_panel = make_function_panel(); f_name_input->value("count_trees(const char *forest_name)"); f_return_type_input->value("unsigned int"); fl_snapshot((target_dir + "function_panel.png").c_str(), adoc_function_panel, win_margin, win_blend); adoc_function_panel->hide(); - // -- ID_Code + // -- Type::Code Fl_Window *adoc_code_panel = make_code_panel(); code_input->buffer()->text("// increment user count\nif (new_user) {\n user_count++;\n}\n"); fl_snapshot((target_dir + "code_panel.png").c_str(), adoc_code_panel, win_margin, win_blend); adoc_code_panel->hide(); - // -- ID_CodeBlock + // -- Type::CodeBlock Fl_Window *adoc_codeblock_panel = make_codeblock_panel(); code_before_input->value("if (test())"); code_after_input->value("// test widgets added..."); fl_snapshot((target_dir + "codeblock_panel.png").c_str(), adoc_codeblock_panel, win_margin, win_blend); adoc_codeblock_panel->hide(); - // -- ID_Decl + // -- Type::Decl Fl_Window *adoc_decl_panel = make_decl_panel(); decl_class_choice->hide(); decl_input->buffer()->text("const char *damage = \"'tis but a scratch\";"); fl_snapshot((target_dir + "decl_panel.png").c_str(), adoc_decl_panel, win_margin, win_blend); adoc_decl_panel->hide(); - // -- ID_DeclBlock + // -- Type::DeclBlock Fl_Window *adoc_declblock_panel = make_declblock_panel(); declblock_before_input->value("#ifdef NDEBUG"); declblock_after_input->value("#endif // NDEBUG"); fl_snapshot((target_dir + "declblock_panel.png").c_str(), adoc_declblock_panel, win_margin, win_blend); adoc_declblock_panel->hide(); - // -- ID_Class + // -- Type::Class Fl_Window *adoc_class_panel = make_class_panel(); decl_class_choice->hide(); c_name_input->value("Zoo_Giraffe"); @@ -529,15 +529,15 @@ void run_autodoc(const std::string &target_dir) { fl_snapshot((target_dir + "class_panel.png").c_str(), adoc_class_panel, win_margin, win_blend); adoc_class_panel->hide(); - // -- ID_Widget_Class is handled like Fl_Window_Type + // -- Type::Widget_Class is handled like Window_Node - // -- ID_Comment + // -- Type::Comment Fl_Window *adoc_comment_panel = make_comment_panel(); comment_input->buffer()->text("Make sure that the giraffe gets enough hay,\nbut the monkey can't reach it."); fl_snapshot((target_dir + "comment_panel.png").c_str(), adoc_comment_panel, win_margin, win_blend); adoc_comment_panel->hide(); - // -- ID_Data + // -- Type::Data Fl_Window *adoc_data_panel = make_data_panel(); data_class_choice->hide(); data_input->value("emulated_ROM"); diff --git a/fluid/tools/autodoc.h b/fluid/tools/autodoc.h index 33b0bd6fc..136a7e119 100644 --- a/fluid/tools/autodoc.h +++ b/fluid/tools/autodoc.h @@ -1,5 +1,5 @@ // -// Widget snapshot header-only file for the Fast Light Tool Kit (FLTK). +// Self-generate snapshots of user interface for FLUID documentation. // // Copyright 2023-2025 by Bill Spitzak and others. // diff --git a/fluid/tools/filename.cxx b/fluid/tools/filename.cxx index bbd749ce1..a5d6e22b3 100644 --- a/fluid/tools/filename.cxx +++ b/fluid/tools/filename.cxx @@ -1,7 +1,7 @@ // -// Filename expansion routines for the Fast Light Tool Kit (FLTK). +// Filename handling code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2023 by Bill Spitzak and others. +// Copyright 1998-2025 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 @@ -95,3 +95,31 @@ std::string fl_filename_shortened(const std::string &filename, int max_chars) { return homed_filename; } } + +/** + Make sure that a path name ends with a forward slash. + \param[in] str directory or path name + \return a new string, ending with a '/' + */ +std::string fld::end_with_slash(const std::string &str) { + char last = str[str.size()-1]; + if (last !='/' && last != '\\') + return str + "/"; + else + return str; +} + +/** + Replace Windows '\\' directory separator with UNix '/' separators. + \param[in] fn a file path in Unix or Windows format + \return a copy of the file path in Unix format. + */ +std::string fld::fix_separators(const std::string &fn) { + std::string ret = fn; + for (size_t i=0; i @@ -57,7 +57,7 @@ int fld::widget::Bin_Button::handle(int inEvent) Fl_Button::handle(FL_RELEASE); // make it into a dnd event const char *type_name = (const char*)user_data(); - Fl_Type::current_dnd = Fl_Type::current; + Fluid.proj.tree.current_dnd = Fluid.proj.tree.current; Fl::copy(type_name, (int)strlen(type_name)+1, 0); Fl::dnd(); return 1; @@ -81,7 +81,7 @@ int fld::widget::Bin_Button::handle(int inEvent) */ int fld::widget::Bin_Window_Button::handle(int inEvent) { - static Fl_Window *drag_win = NULL; + static Fl_Window *drag_win = nullptr; int ret = 0; switch (inEvent) { case FL_PUSH: @@ -107,18 +107,18 @@ int fld::widget::Bin_Window_Button::handle(int inEvent) case FL_RELEASE: if (drag_win) { Fl::delete_widget(drag_win); - drag_win = NULL; + drag_win = nullptr; // create a new window here - Fl_Type *prototype = typename_to_prototype((char*)user_data()); + Node *prototype = typename_to_prototype((char*)user_data()); if (prototype) { - Fl_Type *new_type = add_new_widget_from_user(prototype, Strategy::AFTER_CURRENT); - if (new_type && new_type->is_a(ID_Window)) { - Fl_Window_Type *new_window = (Fl_Window_Type*)new_type; + Node *new_type = add_new_widget_from_user(prototype, Strategy::AFTER_CURRENT); + if (new_type && new_type->is_a(Type::Window)) { + Window_Node *new_window = (Window_Node*)new_type; Fl_Window *w = (Fl_Window *)new_window->o; w->position(Fl::event_x_root(), Fl::event_y_root()); } } - widget_browser->display(Fl_Type::current); + widget_browser->display(Fluid.proj.tree.current); widget_browser->rebuild(); } return Fl_Button::handle(inEvent); diff --git a/fluid/widgets/Code_Editor.cxx b/fluid/widgets/Code_Editor.cxx index a145b5055..b4379c845 100644 --- a/fluid/widgets/Code_Editor.cxx +++ b/fluid/widgets/Code_Editor.cxx @@ -1,6 +1,5 @@ // // Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -15,6 +14,8 @@ // https://www.fltk.org/bugs.php // +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. + // // Include necessary headers... // @@ -230,11 +231,11 @@ Code_Editor::Code_Editor(int X, int Y, int W, int H, const char *L) : */ Code_Editor::~Code_Editor() { Fl_Text_Buffer *buf = mStyleBuffer; - mStyleBuffer = 0; + mStyleBuffer = nullptr; delete buf; buf = mBuffer; - buffer(0); + buffer(nullptr); delete buf; } diff --git a/fluid/widgets/Code_Editor.h b/fluid/widgets/Code_Editor.h index ef8df0e0d..49afe7e25 100644 --- a/fluid/widgets/Code_Editor.h +++ b/fluid/widgets/Code_Editor.h @@ -1,6 +1,5 @@ // // Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -18,6 +17,8 @@ #ifndef FLUID_WIDGETS_CODE_EDITOR_H #define FLUID_WIDGETS_CODE_EDITOR_H +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. + // // Include necessary headers... // @@ -49,7 +50,7 @@ class Code_Editor : public Fl_Text_Editor { static int auto_indent(int, Code_Editor* e); public: - Code_Editor(int X, int Y, int W, int H, const char *L=0); + Code_Editor(int X, int Y, int W, int H, const char *L=nullptr); ~Code_Editor(); void textsize(Fl_Fontsize s); diff --git a/fluid/widgets/Code_Viewer.cxx b/fluid/widgets/Code_Viewer.cxx index 82a71f4f6..fdbfdc626 100644 --- a/fluid/widgets/Code_Viewer.cxx +++ b/fluid/widgets/Code_Viewer.cxx @@ -1,6 +1,5 @@ // -// Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// Code viewer widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -15,6 +14,8 @@ // https://www.fltk.org/bugs.php // +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. + // // Include necessary headers... // diff --git a/fluid/widgets/Code_Viewer.h b/fluid/widgets/Code_Viewer.h index 5bf8b870a..4198fd433 100644 --- a/fluid/widgets/Code_Viewer.h +++ b/fluid/widgets/Code_Viewer.h @@ -1,6 +1,5 @@ // -// Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// Code viewer widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -18,6 +17,8 @@ #ifndef FLUID_WIDGETS_CODE_VIEWER_H #define FLUID_WIDGETS_CODE_VIEWER_H +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. + // // Include necessary headers... // diff --git a/fluid/widgets/Formula_Input.cxx b/fluid/widgets/Formula_Input.cxx index b26bd83e3..dadebe674 100644 --- a/fluid/widgets/Formula_Input.cxx +++ b/fluid/widgets/Formula_Input.cxx @@ -1,5 +1,5 @@ // -// Widget type code for the Fast Light Tool Kit (FLTK). +// Formula Int Input widget code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -209,7 +209,7 @@ int Formula_Input::handle(int event) { } /** Set the list of the available variables - \param vars array of variables, last entry `has name_` set to `NULL` + \param vars array of variables, last entry `has name_` set to `nullptr` \param user_data is forwarded to the Variable callback */ void Formula_Input::variables(Formula_Input_Vars *vars, void *user_data) { vars_ = vars; diff --git a/fluid/widgets/Formula_Input.h b/fluid/widgets/Formula_Input.h index 5307cdc88..060c1e157 100644 --- a/fluid/widgets/Formula_Input.h +++ b/fluid/widgets/Formula_Input.h @@ -1,5 +1,5 @@ // -// Formula_Input widget header file for the Fast Light Tool Kit (FLTK). +// Formula Int Input widget header file for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -29,7 +29,7 @@ typedef int (Fluid_Coord_Callback)(Formula_Input const *, void*); // Entry for a list of variables available to an input field. // Formula_Input::variables() expects an array of -// Formula_Input_Vars with the last entry's name_ set to NULL. +// Formula_Input_Vars with the last entry's name_ set to nullptr. typedef struct Formula_Input_Vars { const char *name_; Fluid_Coord_Callback *callback_; diff --git a/fluid/widgets/Node_Browser.cxx b/fluid/widgets/Node_Browser.cxx index fafe236cf..745282e23 100644 --- a/fluid/widgets/Node_Browser.cxx +++ b/fluid/widgets/Node_Browser.cxx @@ -1,5 +1,5 @@ // -// Widget Browser code for the Fast Light Tool Kit (FLTK). +// Widget Tree Browser code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -16,8 +16,8 @@ #include "widgets/Node_Browser.h" -#include "app/fluid.h" -#include "nodes/Fl_Widget_Type.h" +#include "Fluid.h" +#include "nodes/Widget_Node.h" #include "rsrcs/pixmaps.h" #include @@ -41,9 +41,9 @@ using namespace fld::widget; The Widget Browser is derived from the FLTK basic browser, extending tree browsing functionality by using the \c depth component of the double - linked list of \c Fl_Type items. + linked list of \c Node items. - \see Fl_Type + \see Node */ @@ -81,9 +81,9 @@ Fl_Widget *make_widget_browser(int x,int y,int w,int h) { /** Make sure that the caller is visible in the widget browser. \param[in] caller scroll the browser in y so that caller - is visible (may be NULL) + is visible (may be nullptr) */ -void redraw_widget_browser(Fl_Type *caller) +void redraw_widget_browser(Node *caller) { if (caller) widget_browser->display(caller); @@ -95,7 +95,7 @@ void redraw_widget_browser(Fl_Type *caller) \param[in] o (de)select this node \param[in] v the new selection state (1=select, 0=de-select) */ -void select(Fl_Type *o, int v) { +void select(Node *o, int v) { widget_browser->select(o,v,1); } @@ -103,7 +103,7 @@ void select(Fl_Type *o, int v) { Select a single node in the widget browser, deselect all others. \param[in] o select this node */ -void select_only(Fl_Type *o) { +void select_only(Node *o) { widget_browser->select_only(o,1); } @@ -122,8 +122,8 @@ void deselect() { \param[in] t show this item */ -void reveal_in_browser(Fl_Type *t) { - Fl_Type *p = t->parent; +void reveal_in_browser(Node *t) { + Node *p = t->parent; if (p) { for (;;) { if (p->folded_) @@ -165,7 +165,7 @@ static char *copy_trunc(char *p, const char *str, int maxl, int quote, int trunc { int size = 0; // truncated string size in characters int bs; // size of UTF-8 character in bytes - if (!p) return NULL; // bad buffer + if (!p) return nullptr; // bad buffer if (!str) { // no input string if (quote) { *p++='"'; *p++='"'; } *p = 0; @@ -206,7 +206,7 @@ static char *copy_trunc(char *p, const char *str, int maxl, int quote, int trunc Fluid currently generates only one instance of this browser. If we want to use multiple browser at some point, we need to refactor a few global - variables, i.e. Fl_Type::first and Fl_Type::last . + variables, i.e. Fluid.proj.tree.first and Fluid.proj.tree.last . \param[in] X, Y, W, H position and size of widget \param[in] l optional label @@ -226,25 +226,25 @@ Node_Browser::Node_Browser(int X,int Y,int W,int H,const char*l) : \return the first item */ void *Node_Browser::item_first() const { - return Fl_Type::first; + return Fluid.proj.tree.first; } /** Override the method to find the next item in the list of elements. \param l this item - \return the next item, irregardless of tree depth, or NULL at the end + \return the next item, irregardless of tree depth, or nullptr at the end */ void *Node_Browser::item_next(void *l) const { - return ((Fl_Type*)l)->next; + return ((Node*)l)->next; } /** Override the method to find the previous item in the list of elements. \param l this item - \return the previous item, irregardless of tree depth, or NULL at the start + \return the previous item, irregardless of tree depth, or nullptr at the start */ void *Node_Browser::item_prev(void *l) const { - return ((Fl_Type*)l)->prev; + return ((Node*)l)->prev; } /** @@ -254,7 +254,7 @@ void *Node_Browser::item_prev(void *l) const { \todo what is the difference between selected and new_selected, and why do we do this? */ int Node_Browser::item_selected(void *l) const { - return ((Fl_Type*)l)->new_selected; + return ((Node*)l)->new_selected; } /** @@ -263,7 +263,7 @@ int Node_Browser::item_selected(void *l) const { \param[in] v 1 if selecting, 0 if not */ void Node_Browser::item_select(void *l,int v) { - ((Fl_Type*)l)->new_selected = v; + ((Node*)l)->new_selected = v; } /** @@ -272,9 +272,9 @@ void Node_Browser::item_select(void *l,int v) { \return height in FLTK units (used to be pixels before high res screens) */ int Node_Browser::item_height(void *l) const { - Fl_Type *t = (Fl_Type*)l; + Node *t = (Node*)l; if (t->visible) { - if (show_comments && t->comment()) + if (Fluid.show_comments && t->comment()) return textsize()*2+4; else return textsize()+5; @@ -307,13 +307,13 @@ int Node_Browser::incr_height() const { text, possibly abbreviated with an ellipsis. \param v v is a pointer to the actual widget type and can be cast safely - to Fl_Type + to Node \param X,Y these give the position in window coordinates of the top left corner of this line */ void Node_Browser::item_draw(void *v, int X, int Y, int, int) const { // cast to a more general type - Fl_Type *l = (Fl_Type *)v; + Node *l = (Node *)v; char buf[500]; // edit buffer: large enough to hold 80 UTF-8 chars + nul @@ -331,7 +331,7 @@ void Node_Browser::item_draw(void *v, int X, int Y, int, int) const { // items can contain a comment. If they do, the comment gets a second text // line inside this browser line int comment_incr = 0; - if (show_comments && l->comment()) { + if (Fluid.show_comments && l->comment()) { // -- comment copy_trunc(buf, l->comment(), 80, 0, 1); comment_incr = textsize()-1; @@ -370,7 +370,7 @@ void Node_Browser::item_draw(void *v, int X, int Y, int, int) const { } // Width=18: Draw the icon associated with the type. - Fl_Pixmap *pm = pixmap[l->id()]; + Fl_Pixmap *pm = pixmap[(int)l->type()]; if (pm) pm->draw(X-18, Y); // Add tags on top of the icon for locked and protected types. @@ -380,11 +380,11 @@ void Node_Browser::item_draw(void *v, int X, int Y, int, int) const { } if ( l->is_widget() - && !l->is_a(ID_Window) - && ((Fl_Widget_Type*)l)->o - && !((Fl_Widget_Type*)l)->o->visible() - && (!l->parent || ( !l->parent->is_a(ID_Tabs) - && !l->parent->is_a(ID_Wizard) ) ) + && !l->is_a(Type::Window) + && ((Widget_Node*)l)->o + && !((Widget_Node*)l)->o->visible() + && (!l->parent || ( !l->parent->is_a(Type::Tabs) + && !l->parent->is_a(Type::Wizard) ) ) ) { invisible_pixmap->draw(X - 17, Y); @@ -424,7 +424,7 @@ void Node_Browser::item_draw(void *v, int X, int Y, int, int) const { else fl_color(func_color); copy_trunc(buf, l->title(), 55, 0, 0); } else { - if (l->is_a(ID_Comment)) { + if (l->is_a(Type::Comment)) { // -- comment (in main line, not above entry) fl_font(comment_font, textsize()); if (l->new_selected) fl_color(fl_contrast(comment_color, FL_SELECTION_COLOR)); @@ -458,7 +458,7 @@ int Node_Browser::item_width(void *v) const { char buf[500]; // edit buffer: large enough to hold 80 UTF-8 chars + nul - Fl_Type *l = (Fl_Type *)v; + Node *l = (Node *)v; if (!l->visible) return 0; @@ -490,7 +490,7 @@ int Node_Browser::item_width(void *v) const { Callback to tell the Fluid UI when the list of selected items changed. */ void Node_Browser::callback() { - selection_changed((Fl_Type*)selection()); + selection_changed((Node*)selection()); } /** @@ -508,13 +508,13 @@ void Node_Browser::callback() { \return 0 if the event is not supported, and 1 if the event was "used up" */ int Node_Browser::handle(int e) { - static Fl_Type *title; - Fl_Type *l; + static Node *title; + Node *l; int X,Y,W,H; bbox(X,Y,W,H); switch (e) { case FL_PUSH: if (!Fl::event_inside(X,Y,W,H)) break; - l = (Fl_Type*)find_item(Fl::event_y()); + l = (Node*)find_item(Fl::event_y()); if (l) { X += 3 + 12*l->level - hposition(); if (l->can_have_children() && Fl::event_x()>X && Fl::event_x()level - hposition(); if (l->can_have_children() && Fl::event_x()>X && Fl::event_x()new_selected && (Fl::event_clicks() || Fl::event_state(FL_CTRL))) l->open(); break; @@ -550,14 +550,14 @@ int Node_Browser::handle(int e) { if (l) { if (!l->folded_) { l->folded_ = 1; - for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next) + for (Node*k = l->next; k&&k->level>l->level; k = k->next) k->visible = 0; } else { l->folded_ = 0; - for (Fl_Type*k=l->next; k&&k->level>l->level;) { + for (Node*k=l->next; k&&k->level>l->level;) { k->visible = 1; if (k->can_have_children() && k->folded_) { - Fl_Type *j; + Node *j; for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/} k = j; } else @@ -602,9 +602,9 @@ void Node_Browser::rebuild() { /** Rebuild the browser layout and make sure that the given item is visible. - \param[in] inNode pointer to a widget node derived from Fl_Type. + \param[in] inNode pointer to a widget node derived from Node. */ -void Node_Browser::display(Fl_Type *inNode) { +void Node_Browser::display(Node *inNode) { if (!inNode) { // Alternative: find the first (last?) visible selected item. return; @@ -613,7 +613,7 @@ void Node_Browser::display(Fl_Type *inNode) { int currentV = vposition(), newV = currentV; int nodeV = 0; // find the inNode in the tree and check, if it is already visible - Fl_Type *p=Fl_Type::first; + Node *p=Fluid.proj.tree.first; for ( ; p && p!=inNode; p=p->next) { if (p->visible) nodeV += item_height(p) + linespacing(); @@ -640,7 +640,7 @@ void Node_Browser::display(Fl_Type *inNode) { void Node_Browser::load_prefs() { int c; - Fl_Preferences p(fluid_prefs, "widget_browser"); + Fl_Preferences p(Fluid.preferences, "widget_browser"); p.get("label_color", c, 72); label_color = c; p.get("label_font", c, FL_HELVETICA); label_font = c; p.get("class_color", c, FL_FOREGROUND_COLOR); class_color = c; @@ -656,7 +656,7 @@ void Node_Browser::load_prefs() { } void Node_Browser::save_prefs() { - Fl_Preferences p(fluid_prefs, "widget_browser"); + Fl_Preferences p(Fluid.preferences, "widget_browser"); p.set("label_color", (int)label_color); p.set("label_font", (int)label_font); p.set("class_color", (int)class_color); diff --git a/fluid/widgets/Node_Browser.h b/fluid/widgets/Node_Browser.h index 5ac74b50a..eec1e7960 100644 --- a/fluid/widgets/Node_Browser.h +++ b/fluid/widgets/Node_Browser.h @@ -1,5 +1,5 @@ // -// Widget Browser code for the Fast Light Tool Kit (FLTK). +// Widget Tree Browser code for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -19,20 +19,20 @@ #include -class Fl_Type; +class Node; namespace fld { namespace widget { class Node_Browser : public Fl_Browser_ { - friend class Fl_Type; + friend class Node; static void callback_stub(Fl_Widget *o, void *) { ((Node_Browser *)o)->callback(); } - Fl_Type* pushedtitle { nullptr }; + Node* pushedtitle { nullptr }; int saved_h_scroll_ { 0 }; int saved_v_scroll_ { 0 }; @@ -55,7 +55,7 @@ public: void restore_scroll_position(); void rebuild(); void new_list() { Fl_Browser_::new_list(); } - void display(Fl_Type *); + void display(Node *); void load_prefs(); void save_prefs(); @@ -78,11 +78,11 @@ public: extern void redraw_browser(); extern Fl_Widget *make_widget_browser(int x,int y,int w,int h); -extern void redraw_widget_browser(Fl_Type *caller); -extern void select(Fl_Type *o, int v); -extern void select_only(Fl_Type *o); +extern void redraw_widget_browser(Node *caller); +extern void select(Node *o, int v); +extern void select_only(Node *o); extern void deselect(); -extern void reveal_in_browser(Fl_Type *t); +extern void reveal_in_browser(Node *t); extern fld::widget::Node_Browser *widget_browser; diff --git a/fluid/widgets/Text_Viewer.cxx b/fluid/widgets/Text_Viewer.cxx index ba2d145fe..5ae821d6b 100644 --- a/fluid/widgets/Text_Viewer.cxx +++ b/fluid/widgets/Text_Viewer.cxx @@ -1,6 +1,5 @@ // -// Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// Text Viewer widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // @@ -40,7 +39,7 @@ Text_Viewer::Text_Viewer(int X, int Y, int W, int H, const char *L) */ Text_Viewer::~Text_Viewer() { Fl_Text_Buffer *buf = mBuffer; - buffer(0); + buffer(nullptr); delete buf; } diff --git a/fluid/widgets/Text_Viewer.h b/fluid/widgets/Text_Viewer.h index 1e5810d50..98fa9200f 100644 --- a/fluid/widgets/Text_Viewer.h +++ b/fluid/widgets/Text_Viewer.h @@ -1,6 +1,5 @@ // -// Code editor widget for the Fast Light Tool Kit (FLTK). -// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// Text Viewer widget for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2025 by Bill Spitzak and others. // diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx index 6d0f991d9..7d48d78d1 100644 --- a/src/Fl_Tabs.cxx +++ b/src/Fl_Tabs.cxx @@ -398,7 +398,7 @@ void Fl_Tabs::take_focus(Fl_Widget *o) { \return 0 if o is invalid or was deleted by the callback and must no longer be used */ int Fl_Tabs::maybe_do_callback(Fl_Widget *o) { - // chaeck if o is valid + // check if o is valid if ( o == NULL ) return 0; diff --git a/test/preferences.fl b/test/preferences.fl index ea3633db1..6d074fdbb 100644 --- a/test/preferences.fl +++ b/test/preferences.fl @@ -138,8 +138,7 @@ Function {} {open return_type int code {readLanguagePrefs(); Fl_Input::cut_menu_text = gettext("Cut"); Fl_Input::copy_menu_text = gettext("Copy"); -Fl_Input::paste_menu_text = gettext("Paste");} {selected - } +Fl_Input::paste_menu_text = gettext("Paste");} {} Fl_Window myWindow { label {My Preferences} callback closeWindowCB open @@ -188,7 +187,7 @@ Fl_Input::paste_menu_text = gettext("Paste");} {selected xywh {0 0 100 20} } MenuItem {} { - label {flip flops} + label {flip flops} selected xywh {0 0 100 20} } MenuItem {} {