Fluid: restructuring and rejuvenation of the source code.
Some checks are pending
Build and Test / build-linux (push) Waiting to run
Build and Test / build-wayland (push) Waiting to run
Build and Test / build-macos (push) Waiting to run
Build and Test / build-windows (push) Waiting to run

* 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`.
This commit is contained in:
Matthias Melcher
2025-03-16 17:16:12 -04:00
committed by GitHub
parent 13a7073a1e
commit 51a55bc736
117 changed files with 17426 additions and 15689 deletions

View File

@@ -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)

1392
fluid/Fluid.cxx Normal file

File diff suppressed because it is too large Load Diff

219
fluid/Fluid.h Normal file
View File

@@ -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 <FL/Fl_Preferences.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/filename.H>
#include <string>
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

335
fluid/Project.cxx Normal file
View File

@@ -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 = "<libintl.h>";
i18n_gnu_conditional = "";
i18n_gnu_function = "gettext";
i18n_gnu_static_function = "gettext_noop";
i18n_pos_include = "<nl_types.h>";
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();
}

View File

@@ -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 <string>
// ---- 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 `<libintl.h>` or `"gettext.h"` for GNU gettext.
std::string i18n_gnu_include = "<libintl.h>";
// 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 `<nl_types.h>` for Posix catgets.
std::string i18n_pos_include = "<nl_types.h>";
// 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, <FL/Fl.H> 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 `<libintl.h>` 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 `<nl_types.h>` 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, <FL/Fl.H> 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

View File

@@ -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 <word>
Type Node <word>
"uid" <4-digit-hex> : since Oct 2023, optional, a unique id for this node
within the project file
@@ -392,12 +392,12 @@ Type "Function" <word> : function signature
“C” : if set, function is extern “C”
“return_type” <word> : 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 <word> : C++ code, for example "if (test())"
"after" <word> : C++ code or comment following the closing '}'
... : inherits more from Fl_Type
... : inherits more from Node
Type "decl" <word> : C++ code to declare a variable or class member
@@ -405,7 +405,7 @@ Type "decl" <word> : 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" <word> : C++ variable name
@@ -418,21 +418,21 @@ Type "declblock" <word> : C++ code
none or "public" or "protected" : defaults to private (obsolete)
"map" <word> : integer value, default is 2 (CODE_IN_SOURCE),
see Fl_DeclBlock_Type::write_map_
see DeclBlock_Node::write_map_
"after" <word> : C++ code or comment following the block
... : inherits more from Fl_Type
... : inherits more from Node
Type "comment" <word> : 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" <word> <word> : prefix, class name
none or "private" or "protected" : defaults to public
":" <word> : name of super class
... : inherits more from Fl_Type
... : inherits more from Node
Type "Fl_Widget" <word> : C++ variable name
@@ -487,7 +487,7 @@ Type "Fl_Widget" <word> : C++ variable name
"shortcut" <word> : integer
"code0" or "code1" or "code2" or "code3" <word> : C++ extra code lines
"extra_code" <word> : C++ extra code lines
... : inherits more from Fl_Type
... : inherits more from Node
Type "Fl_Button" <word> : C++ variable name

View File

@@ -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 <FL/Fl.H>
#include <FL/Fl_Widget.H>
#include <FL/Fl_Window.H>
#include <FL/fl_string_functions.h>
#include <FL/fl_utf8.h> // fl_fopen()
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_SVG_Image.H>
#include <FL/Fl_Anim_GIF_Image.H>
#include "../src/flstring.h"
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
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 <FL/Fl_Image.H>\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 <FL/Fl_Anim_GIF_Image.H>\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 <FL/Fl_GIF_Image.H>\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 <FL/Fl_BMP_Image.H>\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 <FL/Fl_Pixmap.H>\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 <FL/Fl_Bitmap.H>\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 <FL/Fl_JPEG_Image.H>\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 <FL/Fl_PNG_Image.H>\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 <FL/Fl_SVG_Image.H>\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; a<numimages; a++) {
if (images[a] == this) {
numimages--;
for (; a < numimages; a++) {
images[a] = images[a+1];
}
break;
}
}
}
if (img) img->release();
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;
}

532
fluid/app/Image_Asset.cxx Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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 <FL/Fl_Shared_Image.H>
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

190
fluid/app/Menu.cxx Normal file
View File

@@ -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 <FL/Fl_Menu_Bar.H>
// 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();
}

29
fluid/app/Menu.h Normal file
View File

@@ -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 <FL/Fl_Menu_Item.H>
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

File diff suppressed because it is too large Load Diff

View File

@@ -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 <string>
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

136
fluid/app/args.cxx Normal file
View File

@@ -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 <FL/Fl.H>
#include <FL/filename.H>
#include <FL/fl_ask.H>
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 <switches> 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 <name> : .cxx output filename, or extension if <name> starts with '.'\n"
" -h <name> : .h output filename, or extension if <name> 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;
}

55
fluid/app/args.h Normal file
View File

@@ -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 <string>
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

File diff suppressed because it is too large Load Diff

View File

@@ -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 <FL/Fl_Preferences.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/filename.H>
#include <string>
#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

115
fluid/app/history.cxx Normal file
View File

@@ -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();
}

45
fluid/app/history.h Normal file
View File

@@ -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 <tools/filename.h>
#include <FL/filename.H>
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

View File

@@ -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 = "<libintl.h>";
i18n_gnu_conditional = "";
i18n_gnu_function = "gettext";
i18n_gnu_static_function = "gettext_noop";
i18n_pos_include = "<nl_types.h>";
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), "");
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <FL/Enumerations.H>
@@ -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();

143
fluid/app/templates.cxx Normal file
View File

@@ -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 <FL/filename.H>
#include <FL/fl_ask.H>
#include <FL/Fl_PNG_Image.H>
#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
}

29
fluid/app/templates.h Normal file
View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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 <stdarg.h>
#include <stdio.h>
#include <string>
#include <set>
#include <map>
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<std::string, void*> 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<std::string> 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<std::string> text_in_code { };
/// searchable tree for pointers that are only written once to the code file
Fd_Pointer_Tree *ptr_in_code;
std::set<void*> 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

View File

@@ -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 <FL/Fl_Window.H>
@@ -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<Fd_I18n_Type>(atoi(read_word()));
proj_.i18n_type = static_cast<fld::I18n_Type>(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()) { // <prefix> <name>
((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);
}
}

View File

@@ -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 <FL/fl_attr.h>
#include <stdio.h>
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);

View File

@@ -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<int>(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;
}

View File

@@ -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 <stdio.h>
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();

142
fluid/io/String_Writer.cxx Normal file
View File

@@ -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);
}

33
fluid/io/String_Writer.h Normal file
View File

@@ -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 <string>
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

View File

@@ -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);
}

166
fluid/nodes/Button_Node.cxx Normal file
View File

@@ -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 <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Repeat_Button.H>
#include <FL/Fl_Round_Button.H>
#include <stdlib.h>
// ---- 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;

149
fluid/nodes/Button_Node.h Normal file
View File

@@ -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

View File

@@ -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 <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Repeat_Button.H>
#include <FL/Fl_Round_Button.H>
#include <stdlib.h>
// ---- 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;

View File

@@ -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

View File

@@ -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 <FL/Fl_Widget.H>
#include <FL/Fl_Menu.H>
#include <FL/fl_draw.H>
#include <FL/fl_attr.h>
#include <stdarg.h>
#include <stdlib.h>
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

View File

@@ -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/Fl_Grid.H>
// ---- 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

View File

@@ -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 <FL/Fl_Tabs.H>
#include <FL/Fl_Pack.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Wizard.H>
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

View File

@@ -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 <FL/Fl_Choice.H>
#include <FL/Fl_Menu_.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Menu_Bar.H>
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

File diff suppressed because it is too large Load Diff

View File

@@ -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

277
fluid/nodes/Function_Node.h Normal file
View File

@@ -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 <FL/Fl_Widget.H>
#include <FL/Fl_Menu.H>
#include <FL/fl_draw.H>
#include <FL/fl_attr.h>
#include <stdarg.h>
#include <stdlib.h>
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

File diff suppressed because it is too large Load Diff

82
fluid/nodes/Grid_Node.h Normal file
View File

@@ -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 <FL/Fl_Grid.H>
// ---- 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

File diff suppressed because it is too large Load Diff

261
fluid/nodes/Group_Node.h Normal file
View File

@@ -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 <FL/Fl_Tabs.H>
#include <FL/Fl_Pack.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Wizard.H>
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

Some files were not shown because too many files have changed in this diff Show More