summaryrefslogtreecommitdiff
path: root/fluid/Fluid.cxx
diff options
context:
space:
mode:
authormaxim nikonov <maxim.nikonov@hqo.co>2026-02-06 02:33:41 +0500
committermaxim nikonov <maxim.nikonov@hqo.co>2026-02-06 02:33:41 +0500
commit43e0a37906afabb0b3b091b8d3eac9a910cae50c (patch)
treed2a037c2bf0dc395fddb08e32ebfcf2795503b7c /fluid/Fluid.cxx
parent4ce4967c33d56e4b56d85d11fe0e0be91e159f5d (diff)
wip
Diffstat (limited to 'fluid/Fluid.cxx')
-rw-r--r--fluid/Fluid.cxx868
1 files changed, 316 insertions, 552 deletions
diff --git a/fluid/Fluid.cxx b/fluid/Fluid.cxx
index 083d00257..7d838d11a 100644
--- a/fluid/Fluid.cxx
+++ b/fluid/Fluid.cxx
@@ -40,59 +40,55 @@
#include "widgets/Node_Browser.h"
#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
#include <FL/fl_ask.H>
-#ifdef __APPLE__
-#include <FL/platform.H> // for fl_open_callback
-#endif
#include <FL/Fl_Help_Dialog.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/Fl_Native_File_Chooser.H>
#include <FL/Fl_Printer.H>
+#include <FL/Fl_File_Icon.H>
#include <FL/fl_string_functions.h>
-#include <locale.h> // setlocale()..
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
#include "../src/flstring.h"
+#ifdef __APPLE__
+#include <FL/platform.H>
+#endif
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
-fld::Application Fluid;
-using namespace fld;
+fld::Application Fluid;
/**
Timer to watch for external editor modifications.
-
- If one or more external editors open, check if their files were modified.
- If so: reload to ram, update size/mtime records, and change fluid's
- 'modified' state.
*/
static void external_editor_timer(void*) {
int editors_open = ExternalCodeEditor::editors_open();
- if ( Fluid.debug_external_editor ) printf("--- TIMER --- External editors open=%d\n", editors_open);
- if ( editors_open > 0 ) {
- // Walk tree looking for files modified by external editors.
+ if (Fluid.debug_external_editor) printf("--- TIMER --- External editors open=%d\n", editors_open);
+ if (editors_open > 0) {
int modified = 0;
for (Node *p: Fluid.proj.tree.all_nodes()) {
- if ( p->is_a(FLD_NODE_TYPE_Code) ) {
+ if (p->is_a(FLD_NODE_TYPE_Code)) {
Code_Node *code = static_cast<Code_Node*>(p);
- // Code changed by external editor?
- if ( code->handle_editor_changes() ) { // updates ram, file size/mtime
+ if (code->handle_editor_changes()) {
modified++;
}
- if ( code->is_editing() ) { // editor open?
- code->reap_editor(); // Try to reap; maybe it recently closed
+ if (code->is_editing()) {
+ code->reap_editor();
}
}
}
- if ( modified ) Fluid.proj.set_modflag(1);
+ if (modified) Fluid.proj.set_modflag(1);
}
- // Repeat timeout if editors still open
- // The ExternalCodeEditor class handles start/stopping timer, we just
- // repeat_timeout() if it's already on. NOTE: above code may have reaped
- // only open editor, which would disable further timeouts. So *recheck*
- // if editors still open, to ensure we don't accidentally re-enable them.
- //
- if ( ExternalCodeEditor::editors_open() ) {
+ if (ExternalCodeEditor::editors_open()) {
Fl::repeat_timeout(2.0, external_editor_timer);
}
}
@@ -100,36 +96,58 @@ static void external_editor_timer(void*) {
/**
Create the Fluid application.
- This creates the basic app with an empty project and reads the Fluid
- preferences database.
*/
-Application::Application()
-: preferences( Fl_Preferences::USER_L, "fltk.org", "fluid" )
-{ }
+fld::Application::Application()
+: current_project_(new fld::Project()),
+ tmpdir_create_called(0),
+ preferences(Fl_Preferences::USER_L, "fltk.org", "fluid"),
+ layout_list(0),
+ batch_mode(0),
+ show_guides(1),
+ show_restricted(1),
+ show_ghosted_outline(1),
+ show_comments(1),
+ use_external_editor(0),
+ debug_external_editor(0),
+ main_window(0),
+ main_menubar(0),
+ save_item(0),
+ history_item(0),
+ widgetbin_item(0),
+ codeview_item(0),
+ overlay_item(0),
+ overlay_button(0),
+ guides_item(0),
+ restricted_item(0),
+ pasteoffset(0),
+ ipasteoffset(0),
+ help_dialog(0),
+ proj(*current_project_)
+{
+ launch_path_[0] = '\0';
+ tmpdir_path_[0] = '\0';
+ external_editor_command[0] = '\0';
+}
/**
- Start Fluid.
-
- Fluid can run in interactive mode with a full user interface to design new
- user interfaces and write the C++ files to manage them,
+ Destructor.
+ */
+fld::Application::~Application() {
+ delete current_project_;
+}
- Fluid can run form the command line in batch mode to convert .fl design files
- into C++ source and header files. In batch mode, no display is needed,
- particularly no X11 connection will be attempted on Linux/Unix.
- \param[in] argc number of arguments in the list
- \param[in] argv pointer to an array of arguments
- \return in batch mode, an error code will be returned via \c exit() . This
- function return 1, if there was an error in the parameters list.
- \todo On Windows, Fluid can under certain conditions open a dialog box, even
- in batch mode. Is that intentional? Does it circumvent issues with Windows'
- stderr and stdout?
+/**
+ Start Fluid.
*/
-int Application::run(int argc,char **argv) {
- setlocale(LC_ALL, ""); // enable multi-language errors in file chooser
- setlocale(LC_NUMERIC, "C"); // make sure numeric values are written correctly
- launch_path_ = end_with_slash(fl_getcwd_str()); // store the current path at launch
+int fld::Application::run(int argc, char **argv) {
+ setlocale(LC_ALL, "");
+ setlocale(LC_NUMERIC, "C");
+
+ // store the current path at launch
+ fl_getcwd(launch_path_, FL_PATH_MAX);
+ fld_end_with_slash(launch_path_, FL_PATH_MAX, launch_path_);
int i = 1;
if ((i = args.load(argc, argv)) == -1)
@@ -140,8 +158,8 @@ int Application::run(int argc,char **argv) {
::exit(0);
}
- const char *c = nullptr;
- if (args.autodoc_path.empty())
+ const char *c = 0;
+ if (args.autodoc_path[0] == '\0')
c = argv[i];
fl_register_images();
@@ -152,81 +170,76 @@ int Application::run(int argc,char **argv) {
if (batch_mode) {
proj.set_filename(c);
} else {
- // In GUI mode, filenames must always be absolute.
- proj.set_filename(fl_filename_absolute_str(c));
+ char abs_path[FL_PATH_MAX];
+ fl_filename_absolute(abs_path, FL_PATH_MAX, c);
+ proj.set_filename(abs_path);
}
}
if (!batch_mode) {
#ifdef __APPLE__
fl_open_callback(apple_open_cb);
-#endif // __APPLE__
+#endif
Fl::visual((Fl_Mode)(FL_DOUBLE|FL_INDEX));
Fl_File_Icon::load_system_icons();
main_window->callback(exit_cb);
- position_window(main_window,"main_window_pos", 1, 10, 30, FLD_WINWIDTH, FLD_WINHEIGHT );
+ position_window(main_window, "main_window_pos", 1, 10, 30, FLD_WINWIDTH, FLD_WINHEIGHT);
if (g_shell_config) {
g_shell_config->read(preferences, FLD_TOOL_STORE_USER);
g_shell_config->update_settings_dialog();
g_shell_config->rebuild_shell_menu();
}
- Fluid.layout_list.read(preferences, FLD_TOOL_STORE_USER);
- main_window->show(argc,argv);
+ layout_list->read(preferences, FLD_TOOL_STORE_USER);
+ main_window->show(argc, argv);
toggle_widget_bin();
- toggle_codeview_cb(nullptr,nullptr);
- if (!c && openlast_button->value() && history.abspath[0][0] && args.autodoc_path.empty()) {
- // Open previous file when no file specified...
+ toggle_codeview_cb(0, 0);
+ if (!c && openlast_button->value() && history.abspath[0][0] && args.autodoc_path[0] == '\0') {
open_project_file(history.abspath[0]);
}
}
proj.undo.suspend();
- if (c && !fld::io::read_file(proj, c,0)) {
+ if (c && !fld::io::read_file(proj, c, 0)) {
if (batch_mode) {
- fprintf(stderr,"%s : %s\n", c, strerror(errno));
+ fprintf(stderr, "%s : %s\n", c, strerror(errno));
exit(1);
}
fl_message("Can't read %s: %s", c, strerror(errno));
}
proj.undo.resume();
- // command line args override code and header filenames from the project file
- // in batch mode only
if (batch_mode) {
- if (!args.code_filename.empty()) {
+ if (args.code_filename[0]) {
proj.code_file_set = 1;
- proj.code_file_name = args.code_filename;
+ proj.set_code_file_name(args.code_filename);
}
- if (!args.header_filename.empty()) {
+ if (args.header_filename[0]) {
proj.header_file_set = 1;
- proj.header_file_name = args.header_filename;
+ proj.set_header_file_name(args.header_filename);
}
}
- if (args.update_file) { // fluid -u
+ if (args.update_file) {
fld::io::write_file(proj, c, 0);
if (!args.compile_file)
exit(0);
}
- if (args.compile_file) { // fluid -c[s]
+ if (args.compile_file) {
if (args.compile_strings)
proj.write_strings();
- write_code_files();
+ write_code_files(0);
exit(0);
}
- // don't lock up if inconsistent command line arguments were given
if (batch_mode)
exit(0);
proj.set_modflag(0);
proj.undo.clear();
- // Set (but do not start) timer callback for external editor updates
ExternalCodeEditor::set_update_timer_callback(external_editor_timer);
#ifndef NDEBUG
- // check if the user wants FLUID to generate image for the user documentation
- if (!args.autodoc_path.empty()) {
+ if (args.autodoc_path[0]) {
run_autodoc(args.autodoc_path);
proj.set_modflag(0, 0);
quit();
@@ -243,33 +256,26 @@ int Application::run(int argc,char **argv) {
/**
- Exit Fluid; we hope you had a nice experience.
- If the design was modified, a dialog will ask for confirmation.
+ Exit Fluid.
*/
-void Application::quit() {
+void fld::Application::quit() {
if (shell_command_running()) {
int choice = fl_choice("Previous shell command still running!",
- "Cancel",
- "Exit",
- nullptr);
- if (choice == 0) { // user chose to cancel the exit operation
- return;
- }
+ "Cancel", "Exit", 0);
+ if (choice == 0) return;
}
flush_text_widgets();
- // verify user intention
- if (confirm_project_clear() == false)
+ if (confirm_project_clear() == 0)
return;
- // Stop any external editor update timers
ExternalCodeEditor::stop_update_timer();
- save_position(main_window,"main_window_pos");
+ save_position(main_window, "main_window_pos");
if (widgetbin_panel) {
- save_position(widgetbin_panel,"widgetbin_pos");
+ save_position(widgetbin_panel, "widgetbin_pos");
delete widgetbin_panel;
}
if (codeview_panel) {
@@ -278,12 +284,12 @@ void Application::quit() {
svp.set("autoposition", cv_autoposition->value());
svp.set("tab", cv_tab->find(cv_tab->value()));
svp.set("code_choice", cv_code_choice);
- save_position(codeview_panel,"codeview_pos");
+ save_position(codeview_panel, "codeview_pos");
delete codeview_panel;
- codeview_panel = nullptr;
+ codeview_panel = 0;
}
if (shell_run_window) {
- save_position(shell_run_window,"shell_run_Window_pos");
+ save_position(shell_run_window, "shell_run_Window_pos");
}
if (about_panel)
@@ -293,13 +299,10 @@ void Application::quit() {
if (g_shell_config)
g_shell_config->write(preferences, FLD_TOOL_STORE_USER);
- Fluid.layout_list.write(preferences, FLD_TOOL_STORE_USER);
+ layout_list->write(preferences, FLD_TOOL_STORE_USER);
proj.undo.clear();
- // Destroy tree
- // Doing so causes dtors to automatically close all external editors
- // and cleans up editor tmp files. Then remove fluid tmpdir /last/.
proj.reset();
ExternalCodeEditor::tmpdir_clear();
delete_tmpdir();
@@ -310,35 +313,27 @@ void Application::quit() {
/**
Return the working directory path at application launch.
- \return a reference to the '/' terminated path.
*/
-const std::string &Application::launch_path() const {
+const char *fld::Application::launch_path() const {
return launch_path_;
}
/**
Generate a path to a directory for temporary data storage.
- \see delete_tmpdir(), get_tmpdir()
- \todo remove duplicate API or reuse ExternalCodeEditor::create_tmpdir()!
*/
-void Application::create_tmpdir() {
+void fld::Application::create_tmpdir() {
if (tmpdir_create_called)
return;
- tmpdir_create_called = true;
+ tmpdir_create_called = 1;
char buf[128];
+ char path[FL_PATH_MAX];
+
#ifdef _WIN32
- // The usual temp file locations on Windows are
- // %system%\Windows\Temp
- // %userprofiles%\AppData\Local
- // usually resolving into
- // C:/Windows/Temp/
- // C:\Users\<username>\AppData\Local\Temp
- fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId());
- std::string name = buf;
- wchar_t tempdirW[FL_PATH_MAX+1];
- char tempdir[FL_PATH_MAX+1];
+ fl_snprintf(buf, sizeof(buf) - 1, "fluid-%ld/", (long)GetCurrentProcessId());
+ wchar_t tempdirW[FL_PATH_MAX + 1];
+ char tempdir[FL_PATH_MAX + 1];
unsigned len = GetTempPathW(FL_PATH_MAX, tempdirW);
if (len == 0) {
strcpy(tempdir, "c:/windows/temp/");
@@ -346,38 +341,34 @@ void Application::create_tmpdir() {
unsigned wn = fl_utf8fromwc(tempdir, FL_PATH_MAX, tempdirW, len);
tempdir[wn] = 0;
}
- std::string path = tempdir;
- end_with_slash(path);
- path += name;
- fl_make_path(path.c_str());
- if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path;
+ fld_end_with_slash(path, FL_PATH_MAX, tempdir);
+ strlcat(path, buf, FL_PATH_MAX);
+ fl_make_path(path);
+ if (fl_access(path, 6) == 0) strlcpy(tmpdir_path_, path, FL_PATH_MAX);
#else
- fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", getpid());
- std::string name = buf;
- auto path_temp = fl_getenv("TMPDIR");
- std::string path = path_temp ? path_temp : "";
- if (!path.empty()) {
- end_with_slash(path);
- path += name;
- fl_make_path(path.c_str());
- if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path;
+ fl_snprintf(buf, sizeof(buf) - 1, "fluid-%d/", getpid());
+ const char *path_temp = fl_getenv("TMPDIR");
+ if (path_temp && *path_temp) {
+ fld_end_with_slash(path, FL_PATH_MAX, path_temp);
+ strlcat(path, buf, FL_PATH_MAX);
+ fl_make_path(path);
+ if (fl_access(path, 6) == 0) strlcpy(tmpdir_path_, path, FL_PATH_MAX);
}
- if (tmpdir_path.empty()) {
- path = std::string("/tmp/") + name;
- fl_make_path(path.c_str());
- if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path;
+ if (tmpdir_path_[0] == '\0') {
+ snprintf(path, FL_PATH_MAX, "/tmp/%s", buf);
+ fl_make_path(path);
+ if (fl_access(path, 6) == 0) strlcpy(tmpdir_path_, path, FL_PATH_MAX);
}
#endif
- if (tmpdir_path.empty()) {
- char pbuf[FL_PATH_MAX+1];
+ if (tmpdir_path_[0] == '\0') {
+ char pbuf[FL_PATH_MAX + 1];
preferences.get_userdata_path(pbuf, FL_PATH_MAX);
- path = std::string(pbuf);
- end_with_slash(path);
- path += name;
- fl_make_path(path.c_str());
- if (fl_access(path.c_str(), 6) == 0) tmpdir_path = path;
+ fld_end_with_slash(path, FL_PATH_MAX, pbuf);
+ strlcat(path, buf, FL_PATH_MAX);
+ fl_make_path(path);
+ if (fl_access(path, 6) == 0) strlcpy(tmpdir_path_, path, FL_PATH_MAX);
}
- if (tmpdir_path.empty()) {
+ if (tmpdir_path_[0] == '\0') {
if (batch_mode) {
fprintf(stderr, "ERROR: Can't create directory for temporary data storage.\n");
} else {
@@ -389,32 +380,30 @@ void Application::create_tmpdir() {
/**
Delete the temporary directory and all its contents.
- \see create_tmpdir(), get_tmpdir()
*/
-void Application::delete_tmpdir() {
- // was a temporary directory created
+void fld::Application::delete_tmpdir() {
if (!tmpdir_create_called)
return;
- if (tmpdir_path.empty())
+ if (tmpdir_path_[0] == '\0')
return;
- // first delete all files that may still be left in the temp directory
struct dirent **de;
- int n_de = fl_filename_list(tmpdir_path.c_str(), &de);
+ int n_de = fl_filename_list(tmpdir_path_, &de);
if (n_de >= 0) {
- for (int i=0; i<n_de; i++) {
- std::string path = tmpdir_path + de[i]->d_name;
- fl_unlink(path.c_str());
+ int i;
+ for (i = 0; i < n_de; i++) {
+ char filepath[FL_PATH_MAX];
+ snprintf(filepath, FL_PATH_MAX, "%s%s", tmpdir_path_, de[i]->d_name);
+ fl_unlink(filepath);
}
fl_filename_free_list(&de, n_de);
}
- // then delete the directory itself
- if (fl_rmdir(tmpdir_path.c_str()) < 0) {
+ if (fl_rmdir(tmpdir_path_) < 0) {
if (batch_mode) {
- fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno));
+ fprintf(stderr, "WARNING: Can't delete tmpdir '%s': %s", tmpdir_path_, strerror(errno));
} else {
- fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path.c_str(), strerror(errno));
+ fl_alert("WARNING: Can't delete tmpdir '%s': %s", tmpdir_path_, strerror(errno));
}
}
}
@@ -422,23 +411,18 @@ void Application::delete_tmpdir() {
/**
Return the path to a temporary directory for this instance of Fluid.
- Fluid will do its best to clear and delete this directory when exiting.
- \return the path to the temporary directory, ending in a '/', or and empty
- string if no directory could be created.
*/
-const std::string &Application::get_tmpdir() {
+const char *fld::Application::get_tmpdir() {
if (!tmpdir_create_called)
create_tmpdir();
- return tmpdir_path;
+ return tmpdir_path_;
}
/**
Return the path and filename of a temporary file for cut or duplicated data.
- \param[in] which 0 gets the cut/copy/paste buffer, 1 gets the duplication buffer
- \return a pointer to a string in a static buffer
*/
-const char *Application::cutfname(int which) {
+const char *fld::Application::cutfname(int which) {
static char name[2][FL_PATH_MAX];
static char beenhere = 0;
@@ -456,90 +440,69 @@ const char *Application::cutfname(int which) {
/**
Clear the current project and create a new, empty one.
-
- If the current project was modified, FLUID will give the user the opportunity
- to save the old project first.
-
- \param[in] user_must_confirm if set, a confimation dialog is presented to the
- user before resetting the project. Default is `true`.
- \return false if the operation was canceled
*/
-bool Application::new_project(bool user_must_confirm) {
- // verify user intention
- if ((user_must_confirm) && (confirm_project_clear() == false))
- return false;
+int fld::Application::new_project(int user_must_confirm) {
+ if ((user_must_confirm) && (confirm_project_clear() == 0))
+ return 0;
- // clear the current project
proj.reset();
- proj.set_filename(nullptr);
+ proj.clear_filename();
proj.set_modflag(0, 0);
widget_browser->rebuild();
proj.update_settings_dialog();
- // all is clear to continue
- return true;
+ return 1;
}
/**
- Open a file chooser and load an exiting project file.
-
- If the current project was modified, FLUID will give the user the opportunity
- to save the old project first.
+ Open a file chooser and load an existing project file.
+ */
+int fld::Application::open_project_file(const char *filename_arg) {
+ if (confirm_project_clear() == 0)
+ return 0;
- If no filename is given, FLUID will open a file chooser dialog.
+ char new_filename[FL_PATH_MAX];
+ new_filename[0] = '\0';
- \param[in] filename_arg load from this file, or show file chooser if empty
- \return false if the operation was canceled or failed otherwise
- */
-bool Application::open_project_file(const std::string &filename_arg) {
- // verify user intention
- if (confirm_project_clear() == false)
- return false;
-
- // ask for a filename if none was given
- std::string new_filename = filename_arg;
- if (new_filename.empty()) {
- new_filename = open_project_filechooser("Open Project File");
- if (new_filename.empty()) {
- return false;
+ if (!filename_arg || !*filename_arg) {
+ open_project_filechooser(new_filename, FL_PATH_MAX, "Open Project File");
+ if (new_filename[0] == '\0') {
+ return 0;
}
+ } else {
+ strlcpy(new_filename, filename_arg, FL_PATH_MAX);
}
- // clear the project and merge a file by the given name
- new_project(false);
- bool success = merge_project_file(new_filename);
+ new_project(0);
+ int success = merge_project_file(new_filename);
if (success) mergeback_on_load();
return success;
}
/**
- Load a project from the give file name and path.
-
- The project file is inserted at the currently selected type.
+ Load a project from the given file name and path.
+ */
+int fld::Application::merge_project_file(const char *filename_arg) {
+ int is_a_merge = (!proj.tree.empty());
+ const char *title = is_a_merge ? "Merge Project File" : "Open Project File";
- If no filename is given, FLUID will open a file chooser dialog.
+ char new_filename[FL_PATH_MAX];
+ new_filename[0] = '\0';
- \param[in] filename_arg path and name of the new project file
- \return false if the operation failed
- */
-bool Application::merge_project_file(const std::string &filename_arg) {
- bool is_a_merge = (!proj.tree.empty());
- std::string title = is_a_merge ? "Merge Project File" : "Open Project File";
-
- // ask for a filename if none was given
- std::string new_filename = filename_arg;
- if (new_filename.empty()) {
- new_filename = open_project_filechooser(title);
- if (new_filename.empty()) {
- return false;
+ if (!filename_arg || !*filename_arg) {
+ open_project_filechooser(new_filename, FL_PATH_MAX, title);
+ if (new_filename[0] == '\0') {
+ return 0;
}
+ } else {
+ strlcpy(new_filename, filename_arg, FL_PATH_MAX);
}
- const char *c = new_filename.c_str();
+ const char *c = new_filename;
const char *oldfilename = proj.proj_filename;
- proj.proj_filename = nullptr;
+ proj.proj_filename = 0;
proj.set_filename(c);
if (is_a_merge) proj.undo.checkpoint();
proj.undo.suspend();
@@ -551,32 +514,26 @@ bool Application::merge_project_file(const std::string &filename_arg) {
free((void *)proj.proj_filename);
proj.proj_filename = oldfilename;
if (main_window) proj.set_modflag(proj.modflag);
- return false;
+ return 0;
}
proj.undo.resume();
widget_browser->rebuild();
if (is_a_merge) {
- // Inserting a file; restore the original filename...
proj.set_filename(oldfilename);
proj.set_modflag(1);
} else {
- // Loaded a file; free the old filename...
proj.set_modflag(0, 0);
proj.undo.clear();
}
if (oldfilename) free((void *)oldfilename);
- return true;
+ return 1;
}
/**
- Save the current design to the file given by \c filename.
- If automatic, this overwrites an existing file. If interactive, if will
- verify with the user.
- \param[in] v if v is not nullptr, or no filename is set, open a filechooser.
- if (v is (void*)2, don;t update the project filename ("save copy...")
+ Save the current design to the file given by filename.
*/
-void Application::save_project_file(void *v) {
+void fld::Application::save_project_file(void *v) {
flush_text_widgets();
Fl_Native_File_Chooser fnfc;
const char *c = proj.proj_filename;
@@ -586,25 +543,25 @@ void Application::save_project_file(void *v) {
#ifndef __APPLE__
fnfc.options(Fl_Native_File_Chooser::NEW_FOLDER);
#else
- // Apple file choosers always ask to confirm
- fnfc.options(Fl_Native_File_Chooser::NEW_FOLDER|Fl_Native_File_Chooser::SAVEAS_CONFIRM);
+ fnfc.options(Fl_Native_File_Chooser::NEW_FOLDER | Fl_Native_File_Chooser::SAVEAS_CONFIRM);
#endif
fnfc.filter("FLUID Files\t*.f[ld]");
if (proj.proj_filename) {
- if (!proj.projectfile_path().empty())
- fnfc.directory(proj.projectfile_path().c_str());
- if (!proj.projectfile_name().empty())
- fnfc.preset_file(proj.projectfile_name().c_str());
+ char proj_path[FL_PATH_MAX];
+ proj.projectfile_path(proj_path, FL_PATH_MAX);
+ if (proj_path[0]) fnfc.directory(proj_path);
+ const char *proj_name = proj.projectfile_name();
+ if (proj_name) fnfc.preset_file(proj_name);
}
fnfc.filter("Fluid Project\t*.fl\nAny\t*");
if (fnfc.show() != 0) return;
c = fnfc.filename();
#ifndef __APPLE__
if (!fl_access(c, 0)) {
- std::string basename = fl_filename_name_str(std::string(c));
+ const char *basename = fl_filename_name(c);
if (fl_choice("The file \"%s\" already exists.\n"
"Do you want to replace it?", "Cancel",
- "Replace", nullptr, basename.c_str()) == 0) return;
+ "Replace", 0, basename) == 0) return;
}
#endif
if (v != (void *)2) proj.set_filename(c);
@@ -622,13 +579,12 @@ void Application::save_project_file(void *v) {
/**
- Reload the file set by \c filename, replacing the current design.
- If the design was modified, a dialog will ask for confirmation.
+ Reload the file set by filename, replacing the current design.
*/
-void Application::revert_project() {
- if ( proj.modflag) {
+void fld::Application::revert_project() {
+ if (proj.modflag) {
if (!fl_choice("This user interface has been changed. Really revert?",
- "Cancel", "Revert", nullptr)) return;
+ "Cancel", "Revert", 0)) return;
}
proj.undo.suspend();
if (!fld::io::read_file(proj, proj.proj_filename, 0)) {
@@ -648,18 +604,11 @@ void Application::revert_project() {
/**
Open the template browser and load a new file from templates.
-
- If the current project was modified, FLUID will give the user the opportunity
- to save the old project first.
-
- \return false if the operation was canceled or failed otherwise
*/
-bool Application::new_project_from_template() {
- // clear the current project first
- if (new_project() == false)
- return false;
+int fld::Application::new_project_from_template() {
+ if (new_project(1) == 0)
+ return 0;
- // Setup the template panel...
if (!template_panel) make_template_panel();
template_clear();
@@ -680,55 +629,46 @@ bool Application::new_project_from_template() {
template_panel->label("New");
- //if ( template_browser->size() == 1 ) { // only one item?
- template_browser->value(1); // select it
+ template_browser->value(1);
template_browser->do_callback();
- //}
- // Show the panel and wait for the user to do something...
template_panel->show();
while (template_panel->shown()) Fl::wait();
- // See if the user chose anything...
int item = template_browser->value();
- if (item < 1) return false;
+ if (item < 1) return 0;
- // Load the template, if any...
const char *tname = (const char *)template_browser->data(item);
if (tname) {
- // Grab the instance name...
const char *iname = template_instance->value();
if (iname && *iname) {
- // Copy the template to a temp file, then read it in...
char line[1024], *ptr, *next;
FILE *infile, *outfile;
- if ((infile = fl_fopen(tname, "rb")) == nullptr) {
+ if ((infile = fl_fopen(tname, "rb")) == 0) {
fl_alert("Error reading template file \"%s\":\n%s", tname,
strerror(errno));
proj.set_modflag(0);
proj.undo.clear();
- return false;
+ return 0;
}
- if ((outfile = fl_fopen(cutfname(1), "wb")) == nullptr) {
+ if ((outfile = fl_fopen(cutfname(1), "wb")) == 0) {
fl_alert("Error writing buffer file \"%s\":\n%s", cutfname(1),
strerror(errno));
fclose(infile);
proj.set_modflag(0);
proj.undo.clear();
- return false;
+ return 0;
}
while (fgets(line, sizeof(line), infile)) {
- // Replace @INSTANCE@ with the instance name...
- for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != nullptr; ptr = next + 10) {
+ for (ptr = line; (next = strstr(ptr, "@INSTANCE@")) != 0; ptr = next + 10) {
fwrite(ptr, next - ptr, 1, outfile);
fputs(iname, outfile);
}
-
fputs(ptr, outfile);
}
@@ -740,7 +680,6 @@ bool Application::new_project_from_template() {
fl_unlink(cutfname(1));
proj.undo.resume();
} else {
- // No instance name, so read the template without replacements...
proj.undo.suspend();
fld::io::read_file(proj, tname, 0);
proj.undo.resume();
@@ -752,69 +691,66 @@ bool Application::new_project_from_template() {
proj.set_modflag(0);
proj.undo.clear();
- return true;
+ return 1;
}
/**
Open the dialog to allow the user to print the current window.
*/
-void Application::print_snapshots() {
+void fld::Application::print_snapshots() {
int w, h, ww, hh;
int frompage, topage;
- int num_windows = 0; // Number of windows
- Window_Node *windows[1000]; // Windows to print
- int winpage; // Current window page
+ int num_windows = 0;
+ Window_Node *windows[1000];
+ int winpage;
Fl_Window *win;
- for (auto w: proj.tree.all_widgets()) {
- if (w->is_a(FLD_NODE_TYPE_Window)) {
- Window_Node *win_t = static_cast<Window_Node*>(w);
+ for (Node *wn: proj.tree.all_nodes()) {
+ if (wn->is_a(FLD_NODE_TYPE_Window)) {
+ Window_Node *win_t = static_cast<Window_Node*>(wn);
+ Fl_Window *win_w = static_cast<Fl_Window*>(win_t->o);
+ if (!win_w->shown()) continue;
windows[num_windows] = win_t;
- Fl_Window *win = static_cast<Fl_Window*>(win_t->o);
- if (!win->shown()) continue;
- num_windows ++;
+ num_windows++;
}
}
Fl_Printer printjob;
- if ( printjob.start_job(num_windows, &frompage, &topage) ) return;
+ if (printjob.start_job(num_windows, &frompage, &topage)) return;
int pagecount = 0;
for (winpage = 0; winpage < num_windows; winpage++) {
float scale = 1, scale_x = 1, scale_y = 1;
- if (winpage+1 < frompage || winpage+1 > topage) continue;
+ if (winpage + 1 < frompage || winpage + 1 > topage) continue;
printjob.start_page();
printjob.printable_rect(&w, &h);
- // Get the time and date...
- time_t curtime = time(nullptr);
+ time_t curtime = time(0);
struct tm *curdate = localtime(&curtime);
char date[1024];
strftime(date, sizeof(date), "%c", curdate);
fl_font(FL_HELVETICA, 12);
fl_color(FL_BLACK);
- fl_draw(date, (w - (int)fl_width(date))/2, fl_height());
- sprintf(date, "%d/%d", ++pagecount, topage-frompage+1);
+ fl_draw(date, (w - (int)fl_width(date)) / 2, fl_height());
+ sprintf(date, "%d/%d", ++pagecount, topage - frompage + 1);
fl_draw(date, w - (int)fl_width(date), fl_height());
- // Get the base filename...
- std::string basename = fl_filename_name_str(std::string(proj.proj_filename));
- fl_draw(basename.c_str(), 0, fl_height());
+ const char *basename = fl_filename_name(proj.proj_filename);
+ if (basename) fl_draw(basename, 0, fl_height());
- // print centered and scaled to fit in the page
win = (Fl_Window*)windows[winpage]->o;
ww = win->decorated_w();
- if(ww > w) scale_x = float(w)/ww;
+ if (ww > w) scale_x = float(w) / ww;
hh = win->decorated_h();
- if(hh > h) scale_y = float(h)/hh;
+ if (hh > h) scale_y = float(h) / hh;
if (scale_x < scale) scale = scale_x;
if (scale_y < scale) scale = scale_y;
if (scale < 1) {
printjob.scale(scale);
printjob.printable_rect(&w, &h);
}
- printjob.origin(w/2, h/2);
- printjob.print_window(win, -ww/2, -hh/2);
+ printjob.origin(w / 2, h / 2);
+ printjob.print_window(win, -ww / 2, -hh / 2);
printjob.end_page();
}
printjob.end_job();
@@ -823,66 +759,49 @@ void Application::print_snapshots() {
/**
Generate the C++ source and header filenames and write those files.
-
- This function creates the source filename by setting the file
- extension to \c code_file_name and a header filename
- with the extension \c header_file_name which are both
- settable by the user.
-
- If the code filename has not been set yet, a "save file as" dialog will be
- presented to the user.
-
- In batch_mode, the function will either be silent, or, if opening or writing
- the files fails, write an error message to \c stderr and exit with exit code 1.
-
- In interactive mode, it will pop up an error message, or, if the user
- hasn't disabled that, pop up a confirmation message.
-
- \param[in] dont_show_completion_dialog don't show the completion dialog
- \return 1 if the operation failed, 0 if it succeeded
*/
-int Application::write_code_files(bool dont_show_completion_dialog)
-{
- // -- handle user interface issues
+int fld::Application::write_code_files(int dont_show_completion_dialog) {
flush_text_widgets();
if (!proj.proj_filename) {
- save_project_file(nullptr);
+ save_project_file(0);
if (!proj.proj_filename) return 1;
}
- // -- generate the file names with absolute paths
fld::io::Code_Writer f(proj);
- std::string code_filename = proj.codefile_path() + proj.codefile_name();
- std::string header_filename = proj.headerfile_path() + proj.headerfile_name();
- // -- write the code and header files
+ char code_path[FL_PATH_MAX], code_name[FL_PATH_MAX];
+ char header_path[FL_PATH_MAX], header_name[FL_PATH_MAX];
+ proj.codefile_path(code_path, FL_PATH_MAX);
+ proj.codefile_name(code_name, FL_PATH_MAX);
+ proj.headerfile_path(header_path, FL_PATH_MAX);
+ proj.headerfile_name(header_name, FL_PATH_MAX);
+
+ char code_filename[FL_PATH_MAX], header_filename[FL_PATH_MAX];
+ snprintf(code_filename, FL_PATH_MAX, "%s%s", code_path, code_name);
+ snprintf(header_filename, FL_PATH_MAX, "%s%s", header_path, header_name);
+
if (!batch_mode) proj.enter_project_dir();
- int x = f.write_code(code_filename.c_str(), header_filename.c_str());
- std::string code_filename_rel = fl_filename_relative_str(code_filename);
- std::string header_filename_rel = fl_filename_relative_str(header_filename);
+ int x = f.write_code(code_filename, header_filename);
+
+ char code_filename_rel[FL_PATH_MAX], header_filename_rel[FL_PATH_MAX];
+ fl_filename_relative(code_filename_rel, FL_PATH_MAX, code_filename);
+ fl_filename_relative(header_filename_rel, FL_PATH_MAX, header_filename);
if (!batch_mode) proj.leave_project_dir();
- // -- print error message in batch mode or pop up an error or confirmation dialog box
if (batch_mode) {
if (!x) {
fprintf(stderr, "%s and %s: %s\n",
- code_filename_rel.c_str(),
- header_filename_rel.c_str(),
- strerror(errno));
+ code_filename_rel, header_filename_rel, strerror(errno));
exit(1);
}
} else {
if (!x) {
fl_message("Can't write %s or %s: %s",
- code_filename_rel.c_str(),
- header_filename_rel.c_str(),
- strerror(errno));
+ code_filename_rel, header_filename_rel, strerror(errno));
} else {
proj.set_modflag(-1, 0);
- if (dont_show_completion_dialog==false && completion_button->value()) {
- fl_message("Wrote %s and %s",
- code_filename_rel.c_str(),
- header_filename_rel.c_str());
+ if (dont_show_completion_dialog == 0 && completion_button->value()) {
+ fl_message("Wrote %s and %s", code_filename_rel, header_filename_rel);
}
}
}
@@ -890,16 +809,13 @@ int Application::write_code_files(bool dont_show_completion_dialog)
}
-/**
- User chose to cut the currently selected widgets.
- */
-void Application::cut_selected() {
+void fld::Application::cut_selected() {
if (!proj.tree.current) {
fl_beep();
return;
}
flush_text_widgets();
- if (!fld::io::write_file(proj, cutfname(),1)) {
+ if (!fld::io::write_file(proj, cutfname(), 1)) {
fl_message("Can't write %s: %s", cutfname(), strerror(errno));
return;
}
@@ -914,10 +830,7 @@ void Application::cut_selected() {
}
-/**
- User chose to copy the currently selected widgets.
- */
-void Application::copy_selected() {
+void fld::Application::copy_selected() {
flush_text_widgets();
if (!proj.tree.current) {
fl_beep();
@@ -925,32 +838,21 @@ void Application::copy_selected() {
}
flush_text_widgets();
ipasteoffset = 10;
- if (!fld::io::write_file(proj, cutfname(),1)) {
+ if (!fld::io::write_file(proj, cutfname(), 1)) {
fl_message("Can't write %s: %s", cutfname(), strerror(errno));
return;
}
}
-/**
- User chose to paste the widgets from the cut buffer.
-
- This function will paste the widgets in the cut buffer after the currently
- selected widget. If the currently selected widget is a group widget and
- it is not folded, the new widgets will be added inside the group.
- */
-void Application::paste_from_clipboard() {
+void fld::Application::paste_from_clipboard() {
pasteoffset = ipasteoffset;
proj.undo.checkpoint();
proj.undo.suspend();
Strategy strategy = Strategy::FROM_FILE_AFTER_CURRENT;
if (proj.tree.current && proj.tree.current->can_have_children()) {
if (proj.tree.current->folded_ == 0) {
- // If the current widget is a group widget and it is not folded,
- // add the new widgets inside the group.
strategy = Strategy::FROM_FILE_AS_LAST_CHILD;
- // The following alternative also works quite nicely
- //strategy = Strategy::FROM_FILE_AS_FIRST_CHILD;
}
}
if (!fld::io::read_file(proj, cutfname(), 1, strategy)) {
@@ -965,28 +867,19 @@ void Application::paste_from_clipboard() {
}
-/**
- Duplicate the selected widgets.
-
- This code is a bit complex because it needs to find the last selected
- widget with the lowest level, so that the new widgets are inserted after
- this one.
- */
-void Application::duplicate_selected() {
+void fld::Application::duplicate_selected() {
if (!proj.tree.current) {
fl_beep();
return;
}
- // flush the text widgets to make sure the user's changes are saved:
flush_text_widgets();
- // find the last selected node with the lowest level:
int lowest_level = 9999;
- Node *new_insert = nullptr;
+ Node *new_insert = 0;
if (proj.tree.current->selected) {
- for (auto t: proj.tree.all_selected_nodes()) {
- if (t->level <= lowest_level) {
+ for (Node *t: proj.tree.all_nodes()) {
+ if (t->selected && t->level <= lowest_level) {
lowest_level = t->level;
new_insert = t;
}
@@ -995,14 +888,12 @@ void Application::duplicate_selected() {
if (new_insert)
proj.tree.current = new_insert;
- // write the selected widgets to a file:
- if (!fld::io::write_file(proj, cutfname(1),1)) {
+ if (!fld::io::write_file(proj, cutfname(1), 1)) {
fl_message("Can't write %s: %s", cutfname(1), strerror(errno));
return;
}
- // read the file and add the widgets after the current one:
- pasteoffset = 0;
+ pasteoffset = 0;
proj.undo.checkpoint();
proj.undo.suspend();
if (!fld::io::read_file(proj, cutfname(1), 1, Strategy::FROM_FILE_AFTER_CURRENT)) {
@@ -1015,10 +906,7 @@ void Application::duplicate_selected() {
}
-/**
- User chose to delete the currently selected widgets.
- */
-void Application::delete_selected() {
+void fld::Application::delete_selected() {
if (!proj.tree.current) {
fl_beep();
return;
@@ -1034,10 +922,7 @@ void Application::delete_selected() {
}
-/**
- Show the editor for the \c current Node.
- */
-void Application::edit_selected() {
+void fld::Application::edit_selected() {
if (!proj.tree.current) {
fl_message("Please select a widget");
return;
@@ -1046,25 +931,18 @@ void Application::edit_selected() {
}
-/**
- User wants to sort selected widgets by y coordinate.
- */
-void Application::sort_selected() {
+void fld::Application::sort_selected() {
proj.undo.checkpoint();
- sort((Node*)nullptr);
+ sort((Node*)0);
widget_browser->rebuild();
proj.set_modflag(1);
}
-/**
- Show or hide the widget bin.
- The state is stored in the app preferences.
- */
-void Application::toggle_widget_bin() {
+void fld::Application::toggle_widget_bin() {
if (!widgetbin_panel) {
make_widgetbin();
- if (!position_window(widgetbin_panel,"widgetbin_pos", 1, 320, 30)) return;
+ if (!position_window(widgetbin_panel, "widgetbin_pos", 1, 320, 30)) return;
}
if (widgetbin_panel->visible()) {
@@ -1077,34 +955,26 @@ void Application::toggle_widget_bin() {
}
-/**
- Open a dialog to show the HTML help page form the FLTK documentation folder.
- \param[in] name name of the HTML help file.
- */
-void Application::show_help(const char *name) {
- const char *docdir;
- char helpname[FL_PATH_MAX];
+void fld::Application::show_help(const char *name) {
+ const char *docdir;
+ char helpname[FL_PATH_MAX];
if (!help_dialog) help_dialog = new Fl_Help_Dialog();
- if ((docdir = fl_getenv("FLTK_DOCDIR")) == nullptr) {
+ if ((docdir = fl_getenv("FLTK_DOCDIR")) == 0) {
docdir = FLTK_DOCDIR;
}
snprintf(helpname, sizeof(helpname), "%s/%s", docdir, name);
- // make sure that we can read the file
FILE *f = fopen(helpname, "rb");
if (f) {
fclose(f);
help_dialog->load(helpname);
} else {
- // if we can not read the file, we display the canned version instead
- // or ask the native browser to open the page on www.fltk.org
- if (strcmp(name, "fluid.html")==0) {
+ if (strcmp(name, "fluid.html") == 0) {
if (!Fl_Shared_Image::find("embedded:/fluid_flow_chart_800.png"))
new Fl_PNG_Image("embedded:/fluid_flow_chart_800.png", fluid_flow_chart_800_png, sizeof(fluid_flow_chart_800_png));
- help_dialog->value
- (
+ help_dialog->value(
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
"<html><head><title>FLTK: Programming with FLUID</title></head><body>\n"
"<h2>What is FLUID?</h2>\n"
@@ -1129,11 +999,11 @@ void Application::show_help(const char *name) {
"<p>More information is available online at <a href="
"\"https://www.fltk.org/doc-1.5/fluid.html\">https://www.fltk.org/</a>"
"</body></html>"
- );
- } else if (strcmp(name, "license.html")==0) {
+ );
+ } else if (strcmp(name, "license.html") == 0) {
fl_open_uri("https://www.fltk.org/doc-1.5/license.html");
return;
- } else if (strcmp(name, "index.html")==0) {
+ } else if (strcmp(name, "index.html") == 0) {
fl_open_uri("https://www.fltk.org/doc-1.5/index.html");
return;
} else {
@@ -1146,25 +1016,13 @@ void Application::show_help(const char *name) {
}
-/**
- Open the "About" dialog.
- */
-void Application::about() {
-#if 1
+void fld::Application::about() {
if (!about_panel) make_about_panel();
about_panel->show();
-#else
- for (auto &n: proj.tree.all_nodes()) {
- puts(n.name());
- }
-#endif
}
-/**
- Build the main app window and create a few other dialogs.
- */
-void Application::make_main_window() {
+void fld::Application::make_main_window() {
if (!batch_mode) {
preferences.get("show_guides", show_guides, 1);
preferences.get("show_restricted", show_restricted, 1);
@@ -1176,15 +1034,14 @@ void Application::make_main_window() {
if (!main_window) {
Fl_Widget *o;
loadPixmaps();
- main_window = new Fl_Double_Window(FLD_WINWIDTH,FLD_WINHEIGHT,"fluid");
+ main_window = new Fl_Double_Window(FLD_WINWIDTH, FLD_WINHEIGHT, "fluid");
main_window->box(FL_NO_BOX);
- o = make_widget_browser(0,FLD_MENUHEIGHT,FLD_BROWSERWIDTH,FLD_BROWSERHEIGHT);
+ o = make_widget_browser(0, FLD_MENUHEIGHT, FLD_BROWSERWIDTH, FLD_BROWSERHEIGHT);
o->box(FL_FLAT_BOX);
o->tooltip("Double-click to view or change an item.");
main_window->resizable(o);
- main_menubar = new fld::widget::App_Menu_Bar(0,0,FLD_BROWSERWIDTH,FLD_MENUHEIGHT);
+ main_menubar = new fld::widget::App_Menu_Bar(0, 0, FLD_BROWSERWIDTH, FLD_MENUHEIGHT);
main_menubar->menu(main_menu);
- // quick access to all dynamic menu items
save_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_save_cb);
history_item = (Fl_Menu_Item*)main_menubar->find_item(menu_file_open_history_cb);
widgetbin_item = (Fl_Menu_Item*)main_menubar->find_item(toggle_widgetbin_cb);
@@ -1206,110 +1063,68 @@ void Application::make_main_window() {
}
-/**
- Open a native file chooser to allow choosing a project file for reading.
-
- Path and filename are preset with the current project filename, if there
- is one.
-
- \param title a text describing the action after selecting a file (load, merge, ...)
- \return the file path and name, or an empty string if the operation was canceled
- */
-std::string Application::open_project_filechooser(const std::string &title) {
+void fld::Application::open_project_filechooser(char *result, int result_size, const char *title) {
+ result[0] = '\0';
Fl_Native_File_Chooser dialog;
- dialog.title(title.c_str());
+ dialog.title(title);
dialog.type(Fl_Native_File_Chooser::BROWSE_FILE);
dialog.filter("FLUID Files\t*.f[ld]\n");
if (proj.proj_filename) {
- std::string current_project_file = proj.proj_filename;
- dialog.directory(fl_filename_path_str(current_project_file).c_str());
- dialog.preset_file(fl_filename_name_str(current_project_file).c_str());
+ char path[FL_PATH_MAX];
+ fl_filename_path(path, FL_PATH_MAX, proj.proj_filename);
+ dialog.directory(path);
+ dialog.preset_file(fl_filename_name(proj.proj_filename));
}
if (dialog.show() != 0)
- return std::string();
- return std::string(dialog.filename());
+ return;
+ strlcpy(result, dialog.filename(), result_size);
}
-/**
- Give the user the opportunity to save a project before clearing it.
-
- If the project has unsaved changes, this function pops up a dialog, that
- allows the user to save the project, continue without saving the project,
- or to cancel the operation.
-
- If the user chooses to save, and no filename was set, a file dialog allows
- the user to pick a name and location, or to cancel the operation.
-
- \return false if the user aborted the operation and the calling function
- should abort as well
- */
-bool Application::confirm_project_clear() {
- if (proj.modflag == 0) return true;
+int fld::Application::confirm_project_clear() {
+ if (proj.modflag == 0) return 1;
switch (fl_choice("This project has unsaved changes. Do you want to save\n"
"the project file before proceeding?",
"Cancel", "Save", "Don't Save"))
{
- case 0 : /* Cancel */
- return false;
- case 1 : /* Save */
- save_project_file(nullptr);
- if (proj.modflag) return false; // user canceled the "Save As" dialog
+ case 0:
+ return 0;
+ case 1:
+ save_project_file(0);
+ if (proj.modflag) return 0;
}
- return true;
+ return 1;
}
-/**
- Ensure that text widgets in the widget panel propagates apply current changes.
- By temporarily clearing the text focus, all text widgets with changed text
- will unfocus and call their respective callbacks, propagating those changes to
- their data set.
- */
-void Application::flush_text_widgets() {
+void fld::Application::flush_text_widgets() {
if (Fl::focus() && (Fl::focus()->top_window() == the_panel)) {
Fl_Widget *old_focus = Fl::focus();
- Fl::focus(nullptr); // trigger callback of the widget that is losing focus
+ Fl::focus(0);
Fl::focus(old_focus);
}
}
-/**
- Position the given window window based on entries in the app preferences.
- Customisable by user; feature can be switched off.
- The window is not shown or hidden by this function, but a value is returned
- to indicate the state to the caller.
- \param[in] w position this window
- \param[in] prefsName name of the preferences item that stores the window settings
- \param[in] Visible default value if window is hidden or shown
- \param[in] X, Y, W, H default size and position if nothing is specified in the preferences
- \return 1 if the caller should make the window visible, 0 if hidden.
- */
-char Application::position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) {
+char fld::Application::position_window(Fl_Window *w, const char *prefsName, int Visible, int X, int Y, int W, int H) {
Fl_Preferences pos(preferences, prefsName);
if (prevpos_button->value()) {
pos.get("x", X, X);
pos.get("y", Y, Y);
- if ( W!=0 ) {
+ if (W != 0) {
pos.get("w", W, W);
pos.get("h", H, H);
- w->resize( X, Y, W, H );
+ w->resize(X, Y, W, H);
+ } else {
+ w->position(X, Y);
}
- else
- w->position( X, Y );
}
pos.get("visible", Visible, Visible);
return Visible;
}
-/**
- Save the position and visibility state of a window to the app preferences.
- \param[in] w save this window data
- \param[in] prefsName name of the preferences item that stores the window settings
- */
-void Application::save_position(Fl_Window *w, const char *prefsName) {
+void fld::Application::save_position(Fl_Window *w, const char *prefsName) {
Fl_Preferences pos(preferences, prefsName);
pos.set("x", w->x());
pos.set("y", w->y());
@@ -1319,74 +1134,31 @@ void Application::save_position(Fl_Window *w, const char *prefsName) {
}
-/**
- Change the app's and hence preview the design's scheme.
-
- The scheme setting is stored in the app preferences
- - in key \p 'scheme_name' since 1.4.0
- - in key \p 'scheme' (index: 0 - 4) in 1.3.x
-
- This callback is triggered by changing the scheme in the
- Fl_Scheme_Choice widget (\p Edit/GUI Settings).
-
- \param[in] choice the calling widget
-
- \see init_scheme() for choice values and backwards compatibility
- */
-void Application::set_scheme(const char *new_scheme) {
+void fld::Application::set_scheme(const char *new_scheme) {
if (batch_mode)
return;
- // set the new scheme only if the scheme was changed
if (Fl::is_scheme(new_scheme))
return;
Fl::scheme(new_scheme);
preferences.set("scheme_name", new_scheme);
- // Backwards compatibility: store 1.3 scheme index (1-4).
- // We assume that index 0-3 (base, plastic, gtk+, gleam) are in the
- // same order as in 1.3.x (index 1-4), higher values are ignored
-
int scheme_index = scheme_choice->value();
- if (scheme_index <= 3) // max. index for 1.3.x (Gleam)
- preferences.set("scheme", scheme_index + 1); // compensate for different indexing
+ if (scheme_index <= 3)
+ preferences.set("scheme", scheme_index + 1);
}
-/**
- Read Fluid's scheme preferences and set the app's scheme.
-
- Since FLTK 1.4.0 the scheme \b name is stored as a character string
- with key "scheme_name" in the preference database.
-
- In FLTK 1.3.x the scheme preference was stored as an integer index
- with key "scheme" in the database. The known schemes were hardcoded in
- Fluid's sources (here for reference):
-
- | Index | 1.3 Scheme Name | Choice | 1.4 Scheme Name |
- |-------|-----------------|-------|-----------------|
- | 0 | Default (same as None) | n/a | n/a |
- | 1 | None (same as Default) | 0 | base |
- | 2 | Plastic | 1 | plastic |
- | 3 | GTK+ | 2 | gtk+ |
- | 4 | Gleam | 3 | gleam |
- | n/a | n/a | 4 | oxy |
-
- The new Fluid tries to keep backwards compatibility and reads both
- keys (\p scheme and \p scheme_name). If the latter is defined, it is used.
- If not the old \p scheme (index) is used - but we need to subtract one to
- get the new Fl_Scheme_Choice index (column "Choice" above).
- */
-void Application::init_scheme() {
- int scheme_index = 0; // scheme index for backwards compatibility (1.3.x)
- char *scheme_name = nullptr; // scheme name since 1.4.0
- preferences.get("scheme_name", scheme_name, "XXX"); // XXX means: not set => fallback 1.3.x
+void fld::Application::init_scheme() {
+ int scheme_index = 0;
+ char *scheme_name = 0;
+ preferences.get("scheme_name", scheme_name, "XXX");
if (!strcmp(scheme_name, "XXX")) {
preferences.get("scheme", scheme_index, 0);
if (scheme_index > 0) {
scheme_index--;
- scheme_choice->value(scheme_index); // set the choice value
+ scheme_choice->value(scheme_index);
}
if (scheme_index < 0)
scheme_index = 0;
@@ -1395,9 +1167,7 @@ void Application::init_scheme() {
scheme_name = const_cast<char *>(scheme_choice->text(scheme_index));
preferences.set("scheme_name", scheme_name);
}
- // Set the new scheme only if it was not overridden by the -scheme
- // command line option
- if (Fl::scheme() == nullptr) {
+ if (Fl::scheme() == 0) {
Fl::scheme(scheme_name);
}
free(scheme_name);
@@ -1405,13 +1175,7 @@ void Application::init_scheme() {
#ifdef __APPLE__
-/**
- Handle app launch with an associated filename (macOS only).
- Should there be a modified design already, Fluid asks for user confirmation.
- \param[in] c the filename of the new design
- */
-void Application::apple_open_cb(const char *c) {
- Fluid.open_project_file(std::string(c));
+void fld::Application::apple_open_cb(const char *c) {
+ Fluid.open_project_file(c);
}
-#endif // __APPLE__
-
+#endif