diff --git a/.github/workflows/build_fluid_docs.yml b/.github/workflows/build_fluid_docs.yml
new file mode 100644
index 000000000..57b30aff3
--- /dev/null
+++ b/.github/workflows/build_fluid_docs.yml
@@ -0,0 +1,84 @@
+#
+# This script builds the FLUID User Handbook as html directory and pdf
+# document on a Linux machine.
+#
+
+name: 'Build FLUID User Handbook'
+
+# This job must be called explicitly form the 'Actions' tab in GitHub
+on: [workflow_dispatch]
+
+permissions:
+ contents: read
+
+jobs:
+ build-html:
+ runs-on: ubuntu-latest
+
+## This can also run on macOS, but BasicTeX will not generate the pdf document
+# runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install prerequisites
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y libwayland-dev wayland-protocols libdbus-1-dev libxkbcommon-dev libpango1.0-dev libgtk-3-dev
+ sudo apt-get install -y doxygen
+ sudo apt-get install -y doxygen-latex
+ sudo apt-get install -y xvfb
+ sudo apt-get install -y x11-xkb-utils xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic x11-apps
+
+## Use the following line when 1.10.0 becomes available on Ubuntu. On 4/14/24 it's 1.9.2
+# sudo apt-get install -y doxygen=1.10.0
+
+## xvfb creates a headless X server for us, so we can render snapshot with FLUID
+
+## We need at least Doxygen on macOS. BasicTeX is not enough though.
+# brew install doxygen
+# brew install --cask basictex
+# eval "$(/usr/libexec/path_helper)"
+
+ - name: Create Build Environment
+ run: cmake -E make_directory ${{github.workspace}}/build
+
+ - name: Configure CMake
+ shell: bash
+ working-directory: ${{github.workspace}}/build
+ run: |
+ cmake $GITHUB_WORKSPACE \
+ -D CMAKE_BUILD_TYPE=Debug \
+ -D CMAKE_CXX_STANDARD=11 \
+ -D CMAKE_CXX_EXTENSIONS=OFF \
+ -D CMAKE_C_FLAGS_INIT="-Wall -Wunused" \
+ -D CMAKE_CXX_FLAGS_INIT="-Wall -Wunused -Wsuggest-override" \
+ -D FLTK_BUILD_FLTK_OPTIONS=OFF \
+ -D FLTK_BUILD_FLUID=ON \
+ -D FLTK_BUILD_GL=OFF \
+ -D FLTK_BUILD_TEST=OFF \
+ -D FLTK_BUILD_FLUID_DOCS=ON
+
+ - name: Build
+ working-directory: ${{github.workspace}}/build
+ shell: bash
+ run: |
+ Xvfb :19 -screen 0 1024x768x16 &
+ export DISPLAY=:19
+ cmake --build . --config Debug --target fluid_docs
+ cmake --build . --config Debug --target fluid_pdf
+ - name: Store html docs as an artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: fluid-html
+ path: build/fluid/documentation/html
+ retention-days: 3
+ overwrite: true
+ - name: Store pdf docs as an artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: fluid-pdf
+ path: build/fluid/documentation/fluid.pdf
+ retention-days: 3
+ overwrite: true
+
diff --git a/CMake/options.cmake b/CMake/options.cmake
index b242c5f40..c1aa0dcea 100644
--- a/CMake/options.cmake
+++ b/CMake/options.cmake
@@ -459,6 +459,8 @@ endif()
if(DOXYGEN_FOUND)
option(FLTK_BUILD_HTML_DOCS "build html docs" ON)
option(FLTK_INSTALL_HTML_DOCS "install html docs" OFF)
+ option(FLTK_BUILD_FLUID_DOCS "build FLUID docs" OFF)
+ option(FLTK_INSTALL_FLUID_DOCS "install FLUID docs" OFF)
option(FLTK_INCLUDE_DRIVER_DOCS "include driver (developer) docs" OFF)
mark_as_advanced(FLTK_INCLUDE_DRIVER_DOCS)
@@ -473,6 +475,10 @@ if(FLTK_BUILD_HTML_DOCS OR FLTK_BUILD_PDF_DOCS)
add_subdirectory(documentation)
endif(FLTK_BUILD_HTML_DOCS OR FLTK_BUILD_PDF_DOCS)
+if(FLTK_BUILD_FLUID_DOCS)
+ add_subdirectory(fluid/documentation)
+endif(FLTK_BUILD_FLUID_DOCS)
+
#######################################################################
# Include optional Cairo support
#######################################################################
diff --git a/README.CMake.txt b/README.CMake.txt
index b117b6b9f..a915b3b23 100644
--- a/README.CMake.txt
+++ b/README.CMake.txt
@@ -325,6 +325,12 @@ FLTK_BUILD_PDF_DOCS - default ON
You can safely leave these two options ON if you want to save build time
because the docs are not built automatically.
+FLTK_BUILD_FLUID_DOCS - default OFF
+ If this option is ON, the FLUID user documentation will be built. If
+ FLTK_BUILD_PDF_DOCS is ON, the FLUID documentation will be generated
+ in PDF forma. To generate the screen shots used in the handbook,
+ the CMake build mode must be set to "Debug".
+
FLTK_INCLUDE_DRIVER_DOCS - default OFF
This option adds driver documentation to HTML and PDF docs (if ON). This
option is marked as "advanced" since it is only useful for FLTK developers
@@ -332,9 +338,10 @@ FLTK_INCLUDE_DRIVER_DOCS - default OFF
options above is ON as well.
FLTK_INSTALL_HTML_DOCS - default OFF
+FLTK_INSTALL_FLUID_DOCS - default OFF
FLTK_INSTALL_PDF_DOCS - default OFF
- If these options are ON then the HTML and/or PDF docs are installed
- when the 'install' target is executed, e.g. with `make install'. You
+ If these options are ON then the HTML, FLUID, and/or PDF docs are installed
+ when the 'install' target is executed, e.g. with `make install'. You
need to select above options FLTK_BUILD_*_DOCS as well.
diff --git a/documentation/CMakeLists.txt b/documentation/CMakeLists.txt
index 4d7b5174a..cf9699449 100644
--- a/documentation/CMakeLists.txt
+++ b/documentation/CMakeLists.txt
@@ -52,7 +52,7 @@ if(GENERATE_DOCS)
# find git revision
# FIXME: This must also work with tarballs where git is not available.
- # For now we just ignore errors and set GIT_REVISION = "unkown".
+ # For now we just ignore errors and set GIT_REVISION = "unknown".
# In the future tarball/zip generation should create a file
# that contains the git revision.
diff --git a/documentation/Doxyfile.in b/documentation/Doxyfile.in
index 130dd1845..56df6bdcd 100644
--- a/documentation/Doxyfile.in
+++ b/documentation/Doxyfile.in
@@ -794,7 +794,6 @@ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/index.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/events.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/subclassing.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/opengl.dox \
- @CMAKE_CURRENT_SOURCE_DIR@/src/fluid.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/fltk-options.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/advanced.dox \
@CMAKE_CURRENT_SOURCE_DIR@/src/unicode.dox \
diff --git a/documentation/Makefile b/documentation/Makefile
index 0b176246b..6760e4622 100644
--- a/documentation/Makefile
+++ b/documentation/Makefile
@@ -36,7 +36,6 @@ HTMLFILES = \
$(SRC_DOCDIR)/events.dox \
$(SRC_DOCDIR)/subclassing.dox \
$(SRC_DOCDIR)/opengl.dox \
- $(SRC_DOCDIR)/fluid.dox \
$(SRC_DOCDIR)/fltk-options.dox \
$(SRC_DOCDIR)/advanced.dox \
$(SRC_DOCDIR)/unicode.dox \
diff --git a/documentation/src/examples.dox b/documentation/src/examples.dox
index fa7bcd9e3..992b85523 100644
--- a/documentation/src/examples.dox
+++ b/documentation/src/examples.dox
@@ -252,7 +252,7 @@ and shows OpenGL text.
\subsection examples_CubeView CubeView
\par
-\c CubeView shows how to create a UI containing OpenGL with Fluid.
+\c CubeView shows how to create a UI containing OpenGL with FLUID.
\subsection examples_cursor cursor
@@ -577,7 +577,7 @@ come in handy. They remember any kind of data between program launches.
\subsection examples_radio radio
\par
-The \c radio tool was created entirely with fluid. It
+The \c radio tool was created entirely with FLUID. It
shows some of the available button types and tests radio
button behavior.
@@ -658,7 +658,7 @@ The \c table demo shows the features of the Fl_Table widget.
\subsection examples_tabs tabs
\par
-The \c tabs tool was created with fluid. It tests
+The \c tabs tool was created with FLUID. It tests
correct hiding and redisplaying of tabs, navigation across tabs,
resize behavior, and no unneeded redrawing of invisible widgets.
@@ -733,13 +733,13 @@ font draws each of the Unicode code points ranging between U+0020 and U+FFFF.
while the focus stays in the original window.
-\subsection examples_fluid fluid
+\subsection examples_fluid FLUID
\par
-\c fluid is not only a big test program, but also a very
-useful visual UI designer. Many parts of \c fluid were
-created using \c fluid. See the \link fluid Fluid Tutorial \endlink
-for more details.
+\c FLUID is not only a big test program, but also a very
+useful visual UI designer. Many parts of \c FLUID were
+created using \c FLUID. Check out the FLUID User Manual and
+the tutorials that come with it at https://www.fltk.org/documentation.php .
diff --git a/documentation/src/fltk-options.dox b/documentation/src/fltk-options.dox
index 047801507..20365d12c 100644
--- a/documentation/src/fltk-options.dox
+++ b/documentation/src/fltk-options.dox
@@ -41,8 +41,8 @@ tool called fltk-options.
`fltk-options` is a hybrid app that is part of FLTK and can be installed on
the target system. It includes an up-to-date man page.
-\image html fluid-edit-global-fltk-settings.png "fltk-options Application"
-\image latex fluid-edit-global-fltk-settings.png "fltk-options Application" width=10cm
+\image html fltk-options.png "fltk-options Application"
+\image latex fltk-options.png "fltk-options Application" width=10cm
When fltk-options is called without any command-line arguments, it opens in
interactive mode and provides a user interface to view and alter all
@@ -67,9 +67,9 @@ A full list of options can be found in the manual at Fl::Fl_Option.
diff --git a/documentation/src/fluid-edit-global-fltk-settings.png b/documentation/src/fltk-options.png
similarity index 100%
rename from documentation/src/fluid-edit-global-fltk-settings.png
rename to documentation/src/fltk-options.png
diff --git a/documentation/src/fluid-catgets.png b/documentation/src/fluid-catgets.png
deleted file mode 100644
index e68b42c96..000000000
Binary files a/documentation/src/fluid-catgets.png and /dev/null differ
diff --git a/documentation/src/fluid-edit-gui-settings.png b/documentation/src/fluid-edit-gui-settings.png
deleted file mode 100644
index ce3cadc9d..000000000
Binary files a/documentation/src/fluid-edit-gui-settings.png and /dev/null differ
diff --git a/documentation/src/fluid-edit-proj-settings.png b/documentation/src/fluid-edit-proj-settings.png
deleted file mode 100644
index 0b44bb199..000000000
Binary files a/documentation/src/fluid-edit-proj-settings.png and /dev/null differ
diff --git a/documentation/src/fluid-gettext.png b/documentation/src/fluid-gettext.png
deleted file mode 100644
index 70845f035..000000000
Binary files a/documentation/src/fluid-gettext.png and /dev/null differ
diff --git a/documentation/src/fluid-layout-grid-and-size-settings.png b/documentation/src/fluid-layout-grid-and-size-settings.png
deleted file mode 100644
index a9f441fd9..000000000
Binary files a/documentation/src/fluid-layout-grid-and-size-settings.png and /dev/null differ
diff --git a/documentation/src/fluid-org.png b/documentation/src/fluid-org.png
deleted file mode 100644
index dd464597c..000000000
Binary files a/documentation/src/fluid-org.png and /dev/null differ
diff --git a/documentation/src/fluid-org.xcf b/documentation/src/fluid-org.xcf
deleted file mode 100644
index 09e98e67c..000000000
Binary files a/documentation/src/fluid-org.xcf and /dev/null differ
diff --git a/documentation/src/fluid.dox b/documentation/src/fluid.dox
deleted file mode 100644
index ebfdaaafe..000000000
--- a/documentation/src/fluid.dox
+++ /dev/null
@@ -1,1760 +0,0 @@
-/**
-
-
-
-
- \page fluid Programming with FLUID
-
-This chapter shows how to use the Fast Light User-Interface Designer
-("FLUID") to create your GUIs.
-
-Subchapters:
-
-\li \ref fluid_what_is_fluid
-\li \ref fluid_fluid_under_unix
-\li \ref fluid_fluid_under_windows
-\li \ref fluid_compiling_fl_files
-\li \ref fluid_tutorial
-\li \ref fluid_references
-\li \ref fluid_templates
-\li \ref fluid_i18n
-\li \ref fluid_limitations
-\li \ref fluid_hotkeys
-\li \ref fluid_licenses
-
-\section fluid_what_is_fluid What is FLUID?
-
-The Fast Light User Interface Designer, or FLUID, is a
-graphical editor that is used to produce FLTK source code. FLUID
-edits and saves its state in .fl files. These files
-are text, and you can (with care) edit them in a text editor,
-perhaps to get some special effects. The .fl file format is explained
-in detail in fluid/README_fl.txt
-
-FLUID can "compile" the .fl file into a
-.cxx and a .h file. The .cxx file
-defines all the objects from the .fl file and the
-.h file declares all the global ones. FLUID also
-supports localization (\ref fluid_i18n "Internationalization")
-of label strings and tooltips using message files and the GNU gettext or
-POSIX catgets interfaces.
-
-A simple program can be made by putting all your code (including a
-\p main() function) into the .fl file and thus making the
-.cxx file a
-single source file to compile. Most programs are more complex than
-this, so you write other .cxx files that call the FLUID functions.
-These .cxx files must
-\p \#include
-the .h file or they can
-\p \#include
-the .cxx file so it still appears to be a single source file.
-
- \image html fluid-org.png "FLUID organization"
- \image latex fluid-org.png "FLUID organization" width=12cm
-
-Normally the FLUID file defines one or more functions or classes which
-output C++ code. Each function defines one or more FLTK
-windows and all the widgets that go inside those windows.
-
-Widgets created by FLUID are either "named", "complex named" or
-"unnamed". A named widget has a legal C++ variable identifier as its
-name (i.e. only alphanumeric and underscore). In this case FLUID
-defines a global variable or class member that will point at the widget
-after the function defining it is called. A complex named object has
-punctuation such as '.' or '->' or any other symbols
-in its name. In this case FLUID assigns a pointer to the widget to the name,
-but does not attempt to declare it. This can be used to get the widgets into
-structures. An unnamed widget has a blank name and no pointer is stored.
-
-Widgets may either call a named callback function that you write in
-another source file, or you can supply a small piece of C++ source and
-FLUID will write a private callback function into the .cxx file.
-
-\section fluid_fluid_under_unix Running FLUID Under UNIX
-
-To run FLUID under UNIX, type:
-
-\code
-fluid filename.fl &
-\endcode
-
-to edit the .fl file filename.fl.
-If the file does not exist
-you will get an error pop-up, but if you dismiss it you will be editing
-a blank file of that name. You can run FLUID without any name, in
-which case you will be editing an unnamed blank setup (but you can use
-save-as to write it to a file).
-
-You can provide any of the standard FLTK switches before the filename:
-
-\code
--display host:n.n
--geometry WxH+X+Y
--title windowtitle
--name classname
--iconic
--fg color
--bg color
--bg2 color
--scheme schemename
-\endcode
-
-Changing the colors may be useful to see what your interface
-will look at if the user calls it with the same switches.
-Similarly, using "-scheme plastic" will show how the interface
-will look using the "plastic" scheme.
-
-In the current version, if you don't put FLUID into the
-background with '&' then you will be able to abort FLUID by
-typing CTRL-C on the terminal. It will exit
-immediately, losing any changes.
-
-\section fluid_fluid_under_windows Running FLUID Under Microsoft Windows
-
-To run FLUID under Windows, double-click on the \e FLUID.exe
-file. You can also run FLUID from the Command Prompt window.
-FLUID always runs in the background under Windows.
-
-\section fluid_compiling_fl_files Compiling .fl Files
-
-FLUID can also be called as a command-line
-"compiler" to create the .cxx and .h
-file from a .fl file. To do this type:
-
-\code
-fluid -c filename.fl
-\endcode
-
-This is the same as the menu 'File/Write Code...'.
-It will read the filename.fl file and write
-filename.cxx and filename.h. Any leading
-directory on filename.fl will be stripped, so they are
-always written to the current directory. If there are any errors
-reading or writing the files, FLUID will print the error and
-exit with a non-zero code. You can use the following lines in a
-makefile to automate the creation of the source and header
-files:
-
-\code
-my_panels.h my_panels.cxx: my_panels.fl
- fluid -c my_panels.fl
-\endcode
-
-Most versions of make support rules that cause .fl
-files to be compiled:
-
-\code
-.SUFFIXES: .fl .cxx .h
-.fl.h .fl.cxx:
- fluid -c $<
-\endcode
-
-If you use
-
-\code
-fluid -cs filename.fl
-\endcode
-
-FLUID will also write the "strings" for internationalization in file
-'filename.txt' (menu: 'File/Write Strings...').
-
-Finally there is another option which is useful for program developers
-who have many .fl files and want to upgrade them to the current FLUID
-version. FLUID will read the \p filename.fl file, save it, and exit
-immediately. This writes the file with current syntax and options and
-the current FLTK version in the header of the file. Use
-
-\code
-fluid -u filename.fl
-\endcode
-
-to 'upgrade' \p filename.fl . You may combine this with '-c' or '-cs'.
-
-\note All these commands overwrite existing files w/o warning. You should
-particularly take care when running 'fluid -u' since this overwrites the
-original .fl source file.
-
-
-\section fluid_tutorial A Short Tutorial
-
-FLUID is an amazingly powerful little program. However, this
-power comes at a price as it is not always obvious how to
-accomplish seemingly simple tasks with it. This tutorial will
-show you how to generate a complete user interface class with
-FLUID that is used for the CubeView program provided with FLTK.
-
-\image html cubeview.png "CubeView demo"
-\image latex cubeview.png "CubeView demo" width=10cm
-
-The window is of class CubeViewUI, and is completely generated by FLUID,
-including class member functions. The central display of the cube is a
-separate subclass of Fl_Gl_Window called CubeView. CubeViewUI manages
-CubeView using callbacks from the various sliders and rollers to
-manipulate the viewing angle and zoom of CubeView.
-
-At the completion of this tutorial you will (hopefully) understand how to:
-
--# Use FLUID to create a complete user interface class, including
- constructor and any member functions necessary.
--# Use FLUID to set callback member functions of custom widget classes.
--# Subclass an Fl_Gl_Window to suit your purposes.
-
-\subsection fluid_cubeview The CubeView Class
-
-The CubeView class is a subclass of Fl_Gl_Window. It has methods for
-setting the zoom, the \e x and \e y pan, and the rotation angle
-about the \e x and \e y axes.
-
-You can safely skip this section as long as you realize that CubeView
-is a sublass of Fl_Gl_Window and will respond to calls from
-CubeViewUI, generated by FLUID.
-
-\par The CubeView Class Definition
-
-Here is the CubeView class definition, as given by its header file
-"test/CubeView.h":
-
-
-
-\code
-#include
-#include
-#include
-
-class CubeView : public Fl_Gl_Window {
-
-public:
- CubeView(int x, int y, int w, int h, const char *l = 0);
-
- // This value determines the scaling factor used to draw the cube.
- double size;
-
- /* Set the rotation about the vertical (y) axis.
- *
- * This function is called by the horizontal roller in
- * CubeViewUI and the initialize button in CubeViewUI.
- */
- void v_angle(double angle) { vAng = angle; }
-
- // Return the rotation about the vertical (y) axis.
- double v_angle() const { return vAng; }
-
- /* Set the rotation about the horizontal (x) axis.
- *
- * This function is called by the vertical roller in
- * CubeViewUI and the initialize button in CubeViewUI.
- */
-
- void h_angle(double angle) { hAng = angle; }
-
- // The rotation about the horizontal (x) axis.
- double h_angle() const { return hAng; }
-
- /* Sets the x shift of the cube view camera.
- *
- * This function is called by the slider in CubeViewUI
- * and the initialize button in CubeViewUI.
- */
- void panx(double x) { xshift = x; }
-
- /* Sets the y shift of the cube view camera.
- *
- * This function is called by the slider in CubeViewUI
- * and the initialize button in CubeViewUI.
- */
- void pany(double y) { yshift = y; }
-
- /* The widget class draw() override.
- *
- * The draw() function initializes Gl for another round of
- * drawing, then calls specialized functions for drawing each
- * of the entities displayed in the cube view.
- */
- void draw();
-
-private:
- /* Draw the cube boundaries.
- *
- * Draw the faces of the cube using the boxv[] vertices,
- * using GL_LINE_LOOP for the faces.
- */
- void drawCube();
-
- double vAng, hAng;
- double xshift, yshift;
-
- float boxv0[3]; float boxv1[3];
- float boxv2[3]; float boxv3[3];
- float boxv4[3]; float boxv5[3];
- float boxv6[3]; float boxv7[3];
-};
-\endcode
-
-\par The CubeView Class Implementation
-
-Here is the CubeView implementation. It is very similar to the
-"CubeView" demo included with FLTK.
-
-
-
-\code
-#include "CubeView.h"
-#include
-
-CubeView::CubeView(int x, int y, int w, int h, const char *l)
- : Fl_Gl_Window(x, y, w, h, l)
-{
- Fl::use_high_res_GL(1);
- vAng = 0.0;
- hAng = 0.0;
- size = 10.0;
- xshift = 0.0;
- yshift = 0.0;
-
- /* The cube definition. These are the vertices of a unit cube
- * centered on the origin.*/
-
- boxv0[0] = -0.5; boxv0[1] = -0.5; boxv0[2] = -0.5;
- boxv1[0] = 0.5; boxv1[1] = -0.5; boxv1[2] = -0.5;
- boxv2[0] = 0.5; boxv2[1] = 0.5; boxv2[2] = -0.5;
- boxv3[0] = -0.5; boxv3[1] = 0.5; boxv3[2] = -0.5;
- boxv4[0] = -0.5; boxv4[1] = -0.5; boxv4[2] = 0.5;
- boxv5[0] = 0.5; boxv5[1] = -0.5; boxv5[2] = 0.5;
- boxv6[0] = 0.5; boxv6[1] = 0.5; boxv6[2] = 0.5;
- boxv7[0] = -0.5; boxv7[1] = 0.5; boxv7[2] = 0.5;
-}
-
-void CubeView::drawCube() {
-/* Draw a colored cube */
-#define ALPHA 0.5
- glShadeModel(GL_FLAT);
-
- glBegin(GL_QUADS);
- glColor4f(0.0, 0.0, 1.0, ALPHA);
- glVertex3fv(boxv0);
- glVertex3fv(boxv1);
- glVertex3fv(boxv2);
- glVertex3fv(boxv3);
-
- glColor4f(1.0, 1.0, 0.0, ALPHA);
- glVertex3fv(boxv0);
- glVertex3fv(boxv4);
- glVertex3fv(boxv5);
- glVertex3fv(boxv1);
-
- glColor4f(0.0, 1.0, 1.0, ALPHA);
- glVertex3fv(boxv2);
- glVertex3fv(boxv6);
- glVertex3fv(boxv7);
- glVertex3fv(boxv3);
-
- glColor4f(1.0, 0.0, 0.0, ALPHA);
- glVertex3fv(boxv4);
- glVertex3fv(boxv5);
- glVertex3fv(boxv6);
- glVertex3fv(boxv7);
-
- glColor4f(1.0, 0.0, 1.0, ALPHA);
- glVertex3fv(boxv0);
- glVertex3fv(boxv3);
- glVertex3fv(boxv7);
- glVertex3fv(boxv4);
-
- glColor4f(0.0, 1.0, 0.0, ALPHA);
- glVertex3fv(boxv1);
- glVertex3fv(boxv5);
- glVertex3fv(boxv6);
- glVertex3fv(boxv2);
- glEnd();
-
- glColor3f(1.0, 1.0, 1.0);
- glBegin(GL_LINES);
- glVertex3fv(boxv0);
- glVertex3fv(boxv1);
-
- glVertex3fv(boxv1);
- glVertex3fv(boxv2);
-
- glVertex3fv(boxv2);
- glVertex3fv(boxv3);
-
- glVertex3fv(boxv3);
- glVertex3fv(boxv0);
-
- glVertex3fv(boxv4);
- glVertex3fv(boxv5);
-
- glVertex3fv(boxv5);
- glVertex3fv(boxv6);
-
- glVertex3fv(boxv6);
- glVertex3fv(boxv7);
-
- glVertex3fv(boxv7);
- glVertex3fv(boxv4);
-
- glVertex3fv(boxv0);
- glVertex3fv(boxv4);
-
- glVertex3fv(boxv1);
- glVertex3fv(boxv5);
-
- glVertex3fv(boxv2);
- glVertex3fv(boxv6);
-
- glVertex3fv(boxv3);
- glVertex3fv(boxv7);
- glEnd();
-} // drawCube
-
-void CubeView::draw() {
- if (!valid()) {
- glLoadIdentity();
- glViewport(0, 0, pixel_w(), pixel_h());
- glOrtho(-10, 10, -10, 10, -20050, 10000);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix();
-
- glTranslatef((GLfloat)xshift, (GLfloat)yshift, 0);
- glRotatef((GLfloat)hAng, 0, 1, 0);
- glRotatef((GLfloat)vAng, 1, 0, 0);
- glScalef(float(size), float(size), float(size));
-
- drawCube();
-
- glPopMatrix();
-}
-\endcode
-
-\subsection fluid_cubeview_ui The CubeViewUI Class
-
-We will completely construct a window to display and control the
-CubeView defined in the previous section using FLUID.
-
-\par Defining the CubeViewUI Class
-
-Once you have started FLUID, the first step in defining a class is to
-create a new class within FLUID using the New->Code->Class
-menu item. Name the class "CubeViewUI" and leave the subclass blank.
-We do not need any inheritance for this window. You should see the
-new class declaration in the FLUID browser window.
-
-\image html fluid1.png "FLUID file for CubeView"
-\image latex fluid1.png "FLUID file for CubeView" width=10cm
-
-\par Adding the Class Constructor
-
-Click on the CubeViewUI class in the FLUID window and add a new method
-by selecting New->Code->Function/Method. The name of the
-function will also be CubeViewUI. FLUID will understand that this will
-be the constructor for the class and will generate the appropriate
-code. Make sure you declare the constructor public.
-
-Then add a window to the CubeViewUI class. Highlight the name of
-the constructor in the FLUID browser window and click on
-New->Group->Window. In a similar manner add the
-following to the CubeViewUI constructor:
-
-\li A horizontal roller named \p hrot
-\li A vertical roller named \p vrot
-\li A horizontal slider named \p xpan
-\li A vertical slider named \p ypan
-\li A horizontal value slider named \p zoom
-
-None of these additions need be public. And they shouldn't be
-unless you plan to expose them as part of the interface for
-CubeViewUI.
-
-When you are finished you should have something like this:
-
-\image html fluid2.png "FLUID window containing CubeView demo"
-\image latex fluid2.png "FLUID window containing CubeView demo" width=10cm
-
-We will talk about the \p show() method that is highlighted
-shortly.
-
-\par Adding the CubeView Widget
-
-What we have is nice, but does little to show our cube. We have already
-defined the CubeView class and we would like to show it within the
-CubeViewUI.
-
-The CubeView class inherits the Fl_Gl_Window class, which
-is created in the same way as an Fl_Box widget. Use
-New->Other->Box to add a square box to the main window.
-This will be no ordinary box, however.
-
-The Box properties window will appear. The key to letting CubeViewUI
-display CubeView is to enter CubeView in the Class: text
-entry box. This tells FLUID that it is not an Fl_Box, but a
-similar widget with the same constructor.
-
-In the Extra Code: field enter \#include "CubeView.h"
-
-This \p \#include is important, as we have just included
-CubeView as a member of CubeViewUI, so any public CubeView methods are
-now available to CubeViewUI.
-
-\image html fluid3-cxx.png "CubeView methods"
-\image latex fluid3-cxx.png "CubeView methods" width=10cm
-
-\par Defining the Callbacks
-
-Each of the widgets we defined before adding CubeView can have
-callbacks that call CubeView methods. You can call an external
-function or put a short amount of code in the Callback
-field of the widget panel. For example, the callback for the
-\p ypan slider is:
-
-\code
-cube->pany(((Fl_Slider *)o)->value());
-cube->redraw();
-\endcode
-
-We call cube->redraw() after changing the value to update
-the CubeView window. CubeView could easily be modified to do this, but
-it is nice to keep this exposed. In the case where you may want to do
-more than one view change only redrawing once saves a lot of time.
-
-There is no reason to wait until after you have added CubeView to
-enter these callbacks. FLUID assumes you are smart enough not to refer
-to members or functions that don't exist.
-
-\par Adding a Class Method
-
-You can add class methods within FLUID that have nothing to do with the
-GUI. As an example add a show function so that CubeViewUI can actually
-appear on the screen.
-
-Make sure the top level CubeViewUI is selected and select
-New->Code->Function/Method. Just use the name
-\p show(). We don't need a return value here, and since we will
-not be adding any widgets to this method FLUID will assign it a return
-type of \p void.
-
-\image html fluid4.png "CubeView constructor"
-\image latex fluid4.png "CubeView constructor" width=10cm
-
-Once the new method has been added, highlight its name and select
-New->Code->Code. Enter the method's code in the code window.
-
-\subsection fluid_addconst Adding Constructor Initialization Code
-
-If you need to add code to initialize a class, for example setting
-initial values of the horizontal and vertical angles in the
-CubeView, you can simply highlight the constructor and select
-New->Code->Code. Add any required code.
-
-\subsection fluid_gencode Generating the Code
-
-Now that we have completely defined the CubeViewUI, we have to generate
-the code. There is one last trick to ensure this all works. Open the
-preferences dialog from Edit->Preferences.
-
-At the bottom of the preferences dialog box is the key:
-"Include Header from Code".
-Select that option and set your desired file
-extensions and you are in business. You can include the CubeViewUI.h
-(or whatever extension you prefer) as you would any other C++ class.
-
-
-
-\section fluid_references FLUID Reference
-
-The following sections describe each of the windows in FLUID.
-
-\subsection fluid_browser The Widget Browser
-
-The main window shows a menu bar and a scrolling browser of
-all the defined widgets. The name of the .fl file being
-edited is shown in the window title.
-
-The widgets are stored in a hierarchy. You can open and close a
-level by clicking the "triangle" at the left of a widget.
-The leftmost widgets are the \e parents, and all the widgets
-listed below them are their \e children. Parents don't have to have
-any children.
-
-The top level of the hierarchy is composed of \e functions and
-\e classes. Each of these will produce a single C++ public function
-or class in the output .cxx file. Calling the function or
-instantiating the class will create all of the child widgets.
-
-The second level of the hierarchy contains the \e windows.
-Each of these produces an instance of class Fl_Window.
-
-Below that are either \e widgets (subclasses of Fl_Widget) or
-\e groups of widgets (including other groups). Plain groups are for
-layout, navigation, and resize purposes. Tab groups provide the
-well-known file-card tab interface.
-
-Widgets are shown in the browser by either their \e name (such
-as "main_panel" in the example), or by their \e type
-and \e label (such as "Button "the green"").
-
-You \e select widgets by clicking on their names, which highlights
-them (you can also select widgets from any displayed window). You can
-select many widgets by dragging the mouse across them, or by using
-Shift+Click to toggle them on and off. To select no widgets, click in
-the blank area under the last widget. Note that hidden children may
-be selected even when there is no visual indication of this.
-
-You \e open widgets by double-clicking on them, or (to open several
-widgets you have picked) by typing the F1 key. A control panel will appear
-so you can change the widget(s).
-
-\subsection fluid_menu_items Menu Items
-
-The menu bar at the top is duplicated as a pop-up menu on any
-displayed window. The shortcuts for all the menu items work in any
-window. The menu items are:
-
-\par File/Open... (Ctrl+o)
-
-\par
-Discards the current editing session and reads in a different
-.fl file. You are asked for confirmation if you have
-changed the current file.
-
-\par
-FLUID can also read .fd files produced by the Forms
-and XForms "fdesign" programs. It is best to
-File/Merge them instead of opening them. FLUID does not
-understand everything in a .fd file, and will print a
-warning message on the controlling terminal for all data it does
-not understand. You will probably need to edit the resulting
-setup to fix these errors. Be careful not to save the file
-without changing the name, as FLUID will write over the
-.fd file with its own format, which fdesign cannot read!
-
-\par File/Insert... (Ctrl+i)
-
-\par
-Inserts the contents of another .fl file, without
-changing the name of the current .fl file. All the
-functions (even if they have the same names as the current ones)
-are added, and you will have to use cut/paste to put the widgets
-where you want.
-
-\par File/Save (Ctrl+s)
-
-\par
-Writes the current data to the .fl file. If the
-file is unnamed then FLUID will ask for a filename.
-
-\par File/Save As... (Ctrl+Shift+S)
-
-\par
-Asks for a new filename and saves the file.
-
-\par File/Save A Copy...
-
-\par
-Save a copy of the .fl data to a different file.
-
-\par File/Revert...
-
-\par
-Revert the .fl data to a previously saved state.
-
-\par File/New From Template...
-
-\par
-Create a new user interface design from a previously saved template.
-This can be useful for including a predefined enterprise copyright message
-for projects, or for managing boilerplate code for repeating project code.
-
-\par File/Save As Template...
-
-\par
-Save the current project as a starting point for future projects.
-
-\par File/Print... (Ctrl-P)
-
-\par
-Generate a printout containing all currently open windows within your project.
-
-\par File/Write Code (Ctrl+Shift+C)
-
-\par
-"Compiles" the data into a .cxx and .h
-file. These are exactly the same as the files you get when you run
-FLUID with the \c -c switch.
-
-\par
-The output file names are the same as the .fl file, with
-the leading directory and trailing ".fl" stripped, and
-".h" or ".cxx" appended.
-
-\par File/Write Strings (Ctrl+Shift+W)
-
-\par
-Writes a message file for all of the text labels defined in
-the current file.
-
-\par
-The output file name is the same as the .fl file,
-with the leading directory and trailing ".fl"
-stripped, and ".txt", ".po", or ".msg" appended depending on the
-\ref fluid_i18n "Internationalization Mode".
-
-\par File/Quit (Ctrl+q)
-
-\par
-Exits FLUID. You are asked for confirmation if you have
-changed the current file.
-
-\par Edit/Undo (Ctrl+z) and Redo (Shift+Ctrl+z)
-
-\par
-FLUID saves the project state for undo and redo operations after every
-major change.
-
-\par Edit/Cut (Ctrl+x)
-
-\par
-Deletes the selected widgets and all of their children.
-These are saved to a "clipboard" file and can be
-pasted back into any FLUID window.
-
-\par Edit/Copy (Ctrl+c)
-
-\par
-Copies the selected widgets and all of their children to the
-"clipboard" file.
-
-\par Edit/Paste (Ctrl+v)
-
-\par
-Pastes the widgets from the clipboard file.
-
-\par
-If the widget is a window, it is added to whatever function
-is selected, or contained in the current selection.
-
-\par
-If the widget is a normal widget, it is added to whatever
-window or group is selected. If none is, it is added to the
-window or group that is the parent of the current selection.
-
-\par
-To avoid confusion, it is best to select exactly one widget
-before doing a paste.
-
-\par
-Cut/paste is the only way to change the parent of a
-widget.
-
-\par Edit/Select All (Ctrl+a)
-
-\par
-Selects all widgets in the same group as the current selection.
-
-\par
-If they are all selected already then this selects all
-widgets in that group's parent. Repeatedly typing Ctrl+a will
-select larger and larger groups of widgets until everything is
-selected.
-
-\par Edit/Properties... (F1 or double click)
-
-\par
-Displays the current widget in the attributes panel. If the
-widget is a window and it is not visible then the window is
-shown instead.
-
-\par Edit/Sort
-
-\par
-Sorts the selected widgets into left to right, top to bottom order.
-You need to do this to make navigation keys in FLTK work correctly.
-You may then fine-tune the sorting with "Earlier" and "Later".
-This does not affect the positions of windows or functions.
-
-\par Edit/Earlier (F2)
-
-\par
-Moves all of the selected widgets one earlier in order among
-the children of their parent (if possible). This will affect
-navigation order, and if the widgets overlap it will affect how
-they draw, as the later widget is drawn on top of the earlier
-one. You can also use this to reorder functions, classes, and
-windows within functions.
-
-\par Edit/Later (F3)
-
-\par
-Moves all of the selected widgets one later in order among
-the children of their parent (if possible).
-
-\par Edit/Group (F7)
-
-\par
-Creates a new Fl_Group and make all the currently
-selected widgets children of it.
-
-\par Edit/Ungroup (F8)
-
-\par
-Deletes the parent group if all the children of a group are
-selected.
-
-\par Edit/Show or Hide Overlays (Ctrl+Shift+O)
-
-\par
-Toggles the display of the red overlays off, without changing
-the selection. This makes it easier to see box borders and how
-the layout looks. The overlays will be forced back on if you
-change the selection.
-
-\par Edit/Show or Hide Guides (Ctrl+Shift+G)
-
-\par
-Guides can be used to arrange a widget layout easily and consistently. They
-indicating preferred widget positions and sizes with user definable margins,
-grids, and gap sizes. See the "Layout" tab in the "Settings" dialog.
-
-\par
-This menu item enables and disable guides and the snapping action when dragging
-widgets and their borders.
-
-\par Edit/Show or Hide Restricted (Ctrl+Shift+R)
-
-\par
-It is recommended to ensure that user interface elements within FLTK do not
-exceed the size of their container group or overlap with each other.
-By activating this button, a hatch pattern is enabled, visually highlighting
-areas where restricted or undefined behavior may occur.
-
-\par Edit/Show or Hide Widget Bin (Alt+B)
-
-\par
-The widget bin provides quick access to all widget types supported by FLUID.
-Layouts can be created by clicking on elements in the widget bin, or by dragging
-them from the bin to their position within the layout. This button shows or
-hides the widget bin.
-
-\par Edit/Show or Hide Source Code (Shift+Alt+S)
-
-\par
-This button shows or hides the source code preview window. Any change to the
-layout or code in the layout editores can be previewed and verified immediatly
-in the Code View window.
-
-\par Edit/Settings... (Alt+p)
-
-\par
-Displays the FLUID settings panel. The settings panel contains tabs for
-general FLUID settings, project setting, layout preferences, custom shell
-commands, and the internationalisation settings for GNU Gettext
-and POSIX catgets.
-
-\par
-Under the "Project" tab you control the extensions or names of the files
-that are generated by FLUID. If you check the "Include Header from Code"
-button the code file will include the header file automatically.
-
-\par
-Under the "Locale" tab are the \ref fluid_i18n "internationalization"
-options, described later in this chapter.
-
-\image html fluid-edit-gui-settings.png "FLUID General Settings Tab"
-\image latex fluid-edit-gui-settings.png "FLUID General Settings Tab" width=10cm
-
-\image html fluid-edit-proj-settings.png "FLUID Project Settings Tab"
-\image latex fluid-edit-proj-settings.png "FLUID Project Settings Tab" width=10cm
-
-\par New/Code/Function
-
-\par
-Creates a new C function. You will be asked for a name for
-the function. This name should be a legal C++ function
-template, without the return type. You can pass arguments which
-can be referred to by code you type into the individual widgets.
-
-\par
-If the function contains any unnamed windows, it will be
-declared as returning an Fl_Window pointer. The unnamed window
-will be returned from it (more than one unnamed window is
-useless). If the function contains only named windows, it will
-be declared as returning nothing (\c void ).
-
-\par
-It is possible to make the .cxx output be a
-self-contained program that can be compiled and executed. This
-is done by deleting the function name so
-\p main(argc,argv) is used. The function will call
-\p show() on all the windows it creates and then call
-\p Fl::run(). This can also be used to test resize
-behavior or other parts of the user interface.
-
-\par
-You can change the function name by double-clicking on the
-function.
-
-\par New/Window
-
-\par
-Creates a new Fl_Window widget. The window is added
-to the currently selected function, or to the function
-containing the currently selected item. The window will appear,
-sized to 100x100. You can resize it to whatever size you
-require.
-
-\par
-The widget panel will also appear and is described later in
-this chapter.
-
-\par New/...
-
-\par
-All other items on the New menu are subclasses of
-Fl_Widget. Creating them will add them to the
-currently selected group or window, or the group or window
-containing the currently selected widget. The initial
-dimensions and position are chosen by copying the current
-widget, if possible.
-
-\par
-When you create the widget you will get the widget's control
-panel, which is described later in this chapter.
-
-\par Layout/Align/...
-
-\par
-Align all selected widgets to the first widget in the selection.
-
-\par Layout/Space Evenly/...
-
-\par
-Space all selected widgets evenly inside the selected space.
-Widgets will be sorted from first to last.
-
-\par Layout/Make Same Size/...
-
-\par
-Make all selected widgets the same size as the first selected widget.
-
-\par Layout/Center in Group/...
-
-\par
-Center all selected widgets relative to their parent widget
-
-\par Layout/Grid and Size Settings... (Ctrl+g)
-
-\par
-Displays the grid settings panel.
-
-\par
-This panel controls dimensions that all widgets snap to when you move
-and resize them, and for the "snap" which is how far a widget has to be
-dragged from its original position to actually change.
-
-Layout preferences are defined using margins to parent groups and window, gaps
-between widget, and /orr by overlaying a grid over a group or window. A layout
-comes as a suite of three presets, one for the main application window, one
-for dialog boxes, and one for toolboxes.
-
-FLUID comes with two include layout suites. `FLTK` was used to design FLUID and
-other included apps, and `Grid` is a more ridgid grid layout. Users can add
-more suites, import and export them, and include them into their .fl
-project files.
-
-\image html fluid-layout-grid-and-size-settings.png "FLUID Layout/Grid Settings Window"
-\image latex fluid-layout-grid-and-size-settings.png "FLUID Layout/Grid Settings Window" width=10cm
-
-\par Shell/Execute Command... (Alt+x)
-
-\par
-Displays the shell command panel. The shell command
-is commonly used to run a 'make' script to compile the FLTK output.
-
-\par Shell/Execute Again (Alt+g)
-
-\par
-Run the shell command again.
-
-\par Help/Repid development with FLUID
-
-\par
-Shows this chapter of the manual.
-
-\par Help/FLTK Programmers Manual
-
-\par
-Shows the contents page of the manual
-
-\par Help/About FLUID
-
-\par
-Pops up a panel showing the version of FLUID.
-
-\subsection fluid_widget_panel The Widget Panel
-
-When you double-click on a widget or a set of widgets you
-will get the "widget attribute panel".
-
-When you change attributes using this panel, the changes are
-reflected immediately in the window. It is useful to hit the
-"Hide Overlays" button (or type Ctrl+Shift+O) to hide the
-red overlay so you can see the widgets more accurately,
-especially when setting the box type.
-
-If you have several widgets selected, they may have different
-values for the fields. In this case the value for \e one of
-the widgets is shown. But if you change this value, \e all
-of the selected widgets are changed to the new value.
-
-Hitting "OK" makes the changes permanent.
-Selecting a different widget also makes the changes permanent.
-FLUID checks for simple syntax errors such as mismatched
-parenthesis in any code before saving any text.
-
-
-
-\image html fluid_widget_gui.png "The FLUID widget GUI attributes"
-\image latex fluid_widget_gui.png "The FLUID widget GUI attributes" width=10cm
-
-\section fluid_widget_attributes GUI Attributes
-
-\par Not all fields in the Widget attributes dialog will be visible
-for all types of widgets.
-
-\par Label (text field)
-
-\par
-String to print next to or inside the button. You can put
-newlines into the string to make multiple lines. The easiest way
-is by typing Ctrl+j.
-
-\par
-\ref common_labels "Symbols"
-can be added to the label using the at sign ("@").
-
-\par Label (pull down menu)
-
-\par
-How to draw the label. Normal, shadowed, engraved, and
-embossed change the appearance of the text.
-
-\par Image
-
-\par
-The active image for the widget. Click on the
-\b Browse... button to pick an image file using the file
-chooser.
-
-\par Inactive
-
-\par
-The inactive image for the widget. Click on the
-\b Browse... button to pick an image file using the file
-chooser.
-
-\par Alignment (buttons)
-
-\par
-Where to draw the label. The arrows put it on that side of the
-widget, you can combine them to put it in the corner. The "box"
-button puts the label inside the widget, rather than outside.
-
-\par
-The \b clip button clips the label to the widget box, the
-\b wrap button wraps any text in the label, and the
-text image button puts the text over the image instead of under
-the image.
-
-\par Position (text fields)
-
-\par
-The position fields show the current position and size of the
-widget box. Enter new values to move and/or resize a widget.
-
-\par
-These fields understand basic math and variables.
-Appending +10 to the X coordinate will move a widget 10 units
-to the right without having to reenter the value.
-Entering the formula w+3 in the Width field will widen all
-selected Widgets by 3 units.
-The formula py+i*20 in the Y field will order all selected
-widgets vertically in their group by increments of 20 units.
-
-\par
-
-
Name
Value
-
`i`
zero based counter of selected widgets
-
`x`, `y`, `w`, `h`
position and size of the current widget
-
`px`, `py`, `pw`, `ph`
dimensions of the parent widget
-
`sx`, `sy`, `sw`, `sh`
dimensions of the previous sibling
-
`cx`, `cy`, `cw`, `ch`
bounding box of all children
-
-
-\par Values (text fields)
-
-\par
-The values and limits of the current widget. Depending on the
-type of widget, some or all of these fields may be inactive.
-
-\par Shortcut
-
-\par
-The shortcut key to activate the widget. Click on the
-shortcut button and press any key sequence to set the shortcut.
-
-\par Attributes (buttons)
-
-\par
-The \b Visible button controls whether the widget is
-visible (on) or hidden (off) initially. Don't change this for
-windows or for the immediate children of a Tabs group.
-
-\par
-The \b Active button controls whether the widget is
-activated (on) or deactivated (off) initially. Most widgets
-appear greyed out when deactivated.
-
-\par
-The \b Resizable button controls whether the window is
-resizeable. In addition all the size changes of a window or
-group will go "into" the resizable child. If you have
-a large data display surrounded by buttons, you probably want
-that data area to be resizable. You can get more complex
-behavior by making invisible boxes the resizable widget, or by
-using hierarchies of groups. Unfortunately the only way to test
-it is to compile the program. Resizing the FLUID window is
-\e not the same as what will happen in the user program.
-
-\par
-The \b Hotspot button causes the parent window to be
-positioned with that widget centered on the mouse. This
-position is determined when the FLUID function is called,
-so you should call it immediately before showing the window. If
-you want the window to hide and then reappear at a new position,
-you should have your program set the hotspot itself just before
-\p show().
-
-\par
-The \b Border button turns the window manager border on
-or off. On most window managers you will have to close the
-window and reopen it to see the effect.
-
-\par X Class (text field)
-
-\par
-The string typed into here is passed to the X window manager
-as the class. This can change the icon or window decorations.
-On most (all?) window managers you will have to close the window
-and reopen it to see the effect.
-
-\image html fluid_widget_style.png "The FLUID widget Style attributes"
-\image latex fluid_widget_style.png "The FLUID widget Style attributes" width=10cm
-
-\subsection fluid_style_attributes Style Attributes
-
-\par Label Font (pulldown menu)
-
-\par
-Font to draw the label in. Ignored by symbols, bitmaps, and
-pixmaps. Your program can change the actual font used by these
-"slots" in case you want some font other than the 16
-provided.
-
-\par Label Size (pulldown menu)
-
-\par
-Pixel size (height) for the font to draw the label in.
-Ignored by symbols, bitmaps, and pixmaps. To see the result
-without dismissing the panel, type the new number and then Tab.
-
-\par Label Color (button)
-
-\par
-Color to draw the label. Ignored by pixmaps (bitmaps,
-however, do use this color as the foreground color).
-
-\par Box (pulldown menu)
-
-\par
-The boxtype to draw as a background for the widget.
-
-\par
-Many widgets will work, and draw faster, with a
-"frame" instead of a "box". A frame does
-not draw the colored interior, leaving whatever was already
-there visible. Be careful, as FLUID may draw this ok but the
-real program may leave unwanted stuff inside the widget.
-
-\par
-If a window is filled with child widgets, you can speed up
-redrawing by changing the window's box type to
-"NO_BOX". FLUID will display a checkerboard for any
-areas that are not colored in by boxes. Note that this
-checkerboard is not drawn by the resulting program. Instead
-random garbage will be displayed.
-
-\par Down Box (pulldown menu)
-
-\par
-The boxtype to draw when a button is pressed or for some
-parts of other widgets like scrollbars and valuators.
-
-\par Color (button)
-
-\par
-The color to draw the box with.
-
-\par Select Color (button)
-
-\par
-Some widgets will use this color for certain parts. FLUID
-does not always show the result of this: this is the color
-buttons draw in when pushed down, and the color of input fields
-when they have the focus.
-
-\par Text Font, Size, and Color
-
-\par
-Some widgets display text, such as input fields, pull-down
-menus, and browsers.
-
-\image html fluid_widget_cxx.png "The FLUID widget C++ attributes"
-\image latex fluid_widget_cxx.png "The FLUID widget C++ attributes" width=10cm
-
-\subsection fluid_cpp_attributes C++ Attributes
-
-\par Class
-
-\par
-This is how you use your own subclasses of
-Fl_Widget. Whatever identifier you type in here will
-be the class that is instantiated.
-
-\par
-In addition, no \p \#include header file is put in the
-.h file. You must provide a \p \#include line as
-the first line of the "Extra Code" which declares your
-subclass.
-
-\par
-The class must be similar to the class you are spoofing. It
-does not have to be a subclass. It is sometimes useful to
-change this to another FLTK class. For windows you can select either
-\p Single or \p Double in the drop-down box right to the "Class:" field
-to get a normal window (Fl_Window) or a double-buffered window
-(Fl_Double_Window), respectively.
-
-\par Type (upper-right pulldown menu)
-
-\par
-Some classes have subtypes that modify their appearance or behavior.
-You pick the subtype off of this menu.
-
-\par Name (text field)
-
-\par
-Name of a variable to declare, and to store a pointer to this
-widget into. This variable will be of type "*". If the name is
-blank then no variable is created.
-
-\par
-You can name several widgets with "name[0]", "name[1]", "name[2]", etc.
-This will cause FLUID to declare an array of pointers. The array
-is big enough that the highest number found can be stored. All widgets
-in the array must be the same type.
-
-\par Public (button)
-
-\par
-Controls whether the widget is publicly accessible. When
-embedding widgets in a C++ class, this controls whether the
-widget is \p public or \p private in the class.
-Otherwise it controls whether the widget is declared
-\p static or global (\p extern ).
-
-\par Extra Code (text fields)
-
-\par
-These four fields let you type in literal lines of code to
-dump into the .h or .cxx files.
-
-\par
-If the text starts with a \# or the word
-\p extern then FLUID thinks this is an "include"
-line, and it is written to the .h file. If the same
-include line occurs several times then only one copy is
-written.
-
-\par
-All other lines are "code" lines. The current
-widget is pointed to by the local variable \p o. The
-window being constructed is pointed to by the local variable
-\p w. You can also access any arguments passed to the
-function here, and any named widgets that are before this one.
-
-\par
-FLUID will check for matching parenthesis, braces, and
-quotes, but does not do much other error checking. Be careful
-here, as it may be hard to figure out what widget is producing
-an error in the compiler. If you need more than four lines you
-probably should call a function in your own .cxx
-code.
-
-\par Callback (text field)
-
-\par
-This can either be the name of a function, or a small snippet
-of code. If you enter anything other than letters, numbers, and the
-underscore then FLUID treats it as code.
-
-\par
-A name refers to a function in your own code. It must be
-declared as void name(*,void*).
-
-\par
-A code snippet is inserted into a static function in the
-.cxx output file. The function prototype is
-void name(class *o, void *v)
-so that you can refer to the widget as \p o and the \p user_data()
-as \p v. FLUID will check for matching parenthesis, braces,
-and quotes, but does not do much other error checking. Be
-careful here, as it may be hard to figure out what widget is
-producing an error in the compiler.
-
-\par
-If the callback is blank then no callback is set.
-
-\par User Data (text field)
-
-\par
-This is a value for the \p user_data() of the widget.
-If blank the default value of zero is used. This can be any
-piece of C code that can be cast to a \p void pointer.
-
-\par Type (text field)
-
-\par
-The \p void* in the callback function prototypes is
-replaced with this. You may want to use \p long for old
-XForms code. Be warned that anything other than \p void*
-is not guaranteed to work! However on most architectures other
-pointer types are ok, and \p long is usually ok, too.
-
-\par When (pulldown menu)
-
-\par
-When to do the callback. This can be \b Never,
-\b Changed, \b Release, or \b Enter Key. The value of
-Enter Key is only useful for text input fields.
-
-\par
-There are other rare but useful values for the
-\p when() field that are not in the menu. You should use
-the extra code fields to put these values in.
-
-\par No Change (button)
-
-\par
-The No Change button means the callback is done on the
-matching event even if the data is not changed.
-
-\section fluid_selecting_moving Selecting and Moving Widgets
-
-Double-clicking a window name in the browser will display it,
-if not displayed yet. From this display you can select widgets,
-sets of widgets, and move or resize them. To close a window
-either double-click it or type \c ESC.
-
-To select a widget, click it. To select several widgets drag
-a rectangle around them. Holding down shift will toggle the
-selection of the widgets instead.
-
-You cannot pick hidden widgets. You also cannot choose some
-widgets if they are completely overlapped by later widgets. Use
-the browser to select these widgets.
-
-The selected widgets are shown with a red "overlay"
-line around them. You can move the widgets by dragging this
-box. Or you can resize them by dragging the outer edges and
-corners. Hold down the Alt key while dragging the mouse to
-defeat the snap-to-grid effect for fine positioning.
-
-If there is a tab box displayed you can change which child is
-visible by clicking on the file tabs. The child you pick is
-selected.
-
-The arrow, tab, and shift+tab keys "navigate" the
-selection. Left, right, tab, or shift+tab move to the next or
-previous widgets in the hierarchy. Hit the right arrow enough
-and you will select every widget in the window. Up/down widgets
-move to the previous/next widgets that overlap horizontally. If
-the navigation does not seem to work you probably need to
-"Sort" the widgets. This is important if you have
-input fields, as FLTK uses the same rules when using arrow keys
-to move between input fields.
-
-To "open" a widget, double click it. To open
-several widgets select them and then type F1 or pick
-"Edit/Open" off the pop-up menu.
-
-Type Ctrl+o to temporarily toggle the overlay off without
-changing the selection, so you can see the widget borders.
-
-You can resize the window by using the window manager border
-controls. FLTK will attempt to round the window size to the
-nearest multiple of the grid size and makes it big enough to
-contain all the widgets (it does this using illegal X methods,
-so it is possible it will barf with some window managers!).
-Notice that the actual window in your program may not be
-resizable, and if it is, the effect on child widgets may be
-different.
-
-The panel for the window (which you get by double-clicking
-it) is almost identical to the panel for any other Fl_Widget.
-There are three extra items:
-
-\section fluid_images Image Labels
-
-The \e contents of the image files in the \b Image
-and \b Inactive text fields are written to the .cxx
-file. If many widgets share the same image then only one copy is
-written. Since the image data is embedded in the generated
-source code, you need only distribute the C++ code and not the
-image files themselves.
-
-However, the \e filenames are stored in the .fl
-file so you will need the image files as well to read the
-.fl file. Filenames are relative to the location of the
-.fl file and not necessarily the current directory. We
-recommend you either put the images in the same directory as the
-.fl file, or use absolute path names.
-
-\par Notes for All Image Types
-
-\par
-FLUID runs using the default visual of your X server. This
-may be 8 bits, which will give you dithered images. You may get
-better results in your actual program by adding the code
-"Fl::visual(FL_RGB)" to your code right before the
-first window is displayed.
-
-\par
-All widgets with the same image on them share the same code
-and source X pixmap. Thus once you have put an image on a
-widget, it is nearly free to put the same image on many other
-widgets.
-
-\par
-If you edit an image at the same time you are using it in FLUID,
-the only way to convince FLUID to read the image file again is to
-remove the image from all widgets that are using it or re-load the
-.fl file.
-
-\par
-Don't rely on how FLTK crops images that are outside the
-widget, as this may change in future versions! The cropping of
-inside labels will probably be unchanged.
-
-\par
-To more accurately place images, make a new "box"
-widget and put the image in that as the label.
-
-\par XBM (X Bitmap) Files
-
-\par
-FLUID reads X bitmap files which use C source code to define
-a bitmap. Sometimes they are stored with the ".h" or
-".bm" extension rather than the standard
-".xbm" extension.
-
-\par
-FLUID writes code to construct an Fl_Bitmap image and use it
-to label the widget. The '1' bits in the bitmap are drawn using
-the label color of the widget. You can change this color in the
-FLUID widget attributes panel. The '0' bits are transparent.
-
-\par
-The program "bitmap" on the X distribution does an
-adequate job of editing bitmaps.
-
-\par XPM (X Pixmap) Files
-
-\par
-FLUID reads X pixmap files as used by the \p libxpm
-library. These files use C source code to define a pixmap. The
-filenames usually have the ".xpm" extension.
-
-\par
-FLUID writes code to construct an Fl_Pixmap image and use it
-to label the widget. The label color of the widget is ignored,
-even for 2-color images that could be a bitmap. XPM files can
-mark a single color as being transparent, and FLTK uses this
-information to generate a transparency mask for the image.
-
-\par
-We have not found any good editors for small iconic pictures.
-For pixmaps we have used
-XPaint
-and the KDE icon editor.
-
-\par BMP Files
-
-\par
-FLUID reads Windows BMP image files which are often used in
-Windows applications for icons. FLUID converts BMP files into
-(modified) XPM format and uses an Fl_BMP_Image image to label the
-widget. Transparency is handled the same as for XPM files. All
-image data is uncompressed when written to the source file, so
-the code may be much bigger than the .bmp file.
-
-\par GIF Files
-
-\par
-FLUID reads GIF image files which are often used in HTML
-documents to make icons. FLUID converts GIF files into
-(modified) XPM format and uses an Fl_GIF_Image image to label the
-widget. Transparency is handled the same as for XPM files. All
-image data is uncompressed when written to the source file, so
-the code may be much bigger than the .gif file. Only
-the first image of an animated GIF file is used.
-
-\par JPEG Files
-
-\par
-If FLTK is compiled with JPEG support, FLUID can read JPEG
-image files which are often used for digital photos. FLUID uses
-an Fl_JPEG_Image image to label the widget, and writes
-uncompressed RGB or grayscale data to the source file.
-
-\par PNG (Portable Network Graphics) Files
-
-\par
-If FLTK is compiled with PNG support, FLUID can read PNG
-image files which are often used in HTML documents. FLUID uses a
-Fl_PNG_Image image to label the widget, and writes uncompressed
-RGB or grayscale data to the source file. PNG images can provide
-a full alpha channel for partial transparency, and FLTK supports
-this as best as possible on each platform.
-
-\section fluid_templates FLUID Templates
-
-\par
-Fluid can store a number of project templates. Project templates
-are great for storing often used boilerplate code for fast access.
-A common use would be projects with readily prepared copyright messages.
-
-\par
-A sample template for FLTK projects is included with Fluid.
-
-\par
-Choose "File > New From Template..." to create a new project
-based on a template file. In the template dialog, select one of
-the existing templates. All occurrences of the word
-"@INSTANCE@" in the template are replaced with the text in
-the "Instance" field. To create the new project click "New".
-
-\par
-To add your current project as a new template, choose
-"File > Save As Template...", fill in a name, and click "Save".
-
-\par
-To delete a template, open the template dialog using
-"New from Template" or "Save As Template", then select any
-existing template, and click "Delete Template".
-
-\section fluid_i18n Internationalization with FLUID
-
-FLUID supports internationalization (I18N for short) of label
-strings and tooltips used by widgets. The GNU gettext option also
-supports deferred translation of statically initialised menu item
-labels. The preferences window (Ctrl+p) provides access
-to the I18N options.
-
-\subsection fluid_i18n_methods I18N Methods
-
-FLUID supports three methods of I18N: none, GNU
-gettext, and POSIX catgets. The "none" method is the
-default and just passes the label strings as-is to the widget
-constructors.
-
-The "GNU gettext" method uses GNU gettext (or a similar
-text-based I18N library) to retrieve a localized string before
-calling the widget constructor.
-
-The "POSIX catgets" method uses the POSIX catgets function to
-retrieve a numbered message from a message catalog before
-calling the widget constructor.
-
-\subsection fluid_gettext_i18n Using GNU gettext for I18N
-
-FLUID's code support for GNU gettext is limited to calling a
-function or macro to retrieve the localized label; you still
-need to call \p setlocale() and \p textdomain() or
-\p bindtextdomain() to select the appropriate language and
-message file.
-
-To use GNU gettext for I18N, open the preferences window and
-choose "GNU gettext" from the \b Use: chooser. Four new input
-fields will then appear to control the include file and
-function/macro names to use when retrieving localized label
-strings in dynamic allocation and static initialisation.
-
- \image html fluid-gettext.png "Internationalization using GNU gettext"
- \image latex fluid-gettext.png "Internationalization using GNU gettext" width=10cm
-
-The \b \#include
-field controls the header file to include for
-I18N; by default this is \b , the
-standard I18N file for GNU gettext.
-
-If the \b Conditional: field contains a macro name, i18n will only be compiled
-into the product if this macro is defined. The build system should define the
-macro only if all required headers and libraries are available. If the macro
-is not defined, no headers are included and `gettext` passes text through
-untranslated.
-
-The \b Function: field controls the function (or macro) that
-will retrieve the localized message; by default the
-\p gettext function will be called.
-
-The **Static Function:** field names a macro that will mark static text
-fields for extraction with the `xgettext` tool. The default macro name is
-\p gettext_noop and will be defined as `#define gettext_noop(text) text`
-right after the `#include` statement. Fluid will do its best to call
-`gettext` on static texts later, after the textdomain was set by the user.
-
-\see [GNU gettext special cases](https://www.gnu.org/software/gettext/manual/html_node/Special-cases.html)
-
-\subsection fluid_catgets_i18n Using POSIX catgets for I18N
-
-FLUID's code support for POSIX catgets allows you to use a
-global message file for all interfaces or a file specific to
-each .fl file; you still need to call
-\p setlocale() to select the appropriate language.
-
-To use POSIX catgets for I18N, open the preferences window
-and choose "POSIX catgets" from the \b Use: chooser. Three new
-input fields will then appear to control the include file,
-catalog file, and set number for retrieving the localized label
-strings.
-
- \image html fluid-catgets.png "Internationalization using POSIX catgets"
- \image latex fluid-catgets.png "Internationalization using POSIX catgets" width=10cm
-
-The \b \#include
-field controls the header file to include for
-I18N; by default this is \b , the
-standard I18N file for POSIX catgets.
-
-The \b File: field controls the name of the catalog file
-variable to use when retrieving localized messages; by default
-the file field is empty which forces a local (static) catalog
-file to be used for all of the windows defined in your
-.fl file.
-
-The \b Set: field controls the set number in the catalog file.
-The default set is 1 and rarely needs to be changed.
-
-\section fluid_limitations Known Limitations
-
-Declaration Blocks can be used to temporarily block out already
-designed code using \#if 0 and \#endif
-type construction. This will effectively avoid compilation of
-blocks of code. However, static code and data generated by this
-segment (menu items, images, include statements, etc.) will still
-be generated and likely cause compile-time warnings.
-
-\section fluid_hotkeys Keyboard Shortcuts
-
-On Apple computers, use the Apple Command key instead of Ctrl.
-
-
-\endhtmlonly
-
-*/
diff --git a/documentation/src/fluid1.png b/documentation/src/fluid1.png
deleted file mode 100644
index dbded1c3a..000000000
Binary files a/documentation/src/fluid1.png and /dev/null differ
diff --git a/documentation/src/fluid2.png b/documentation/src/fluid2.png
deleted file mode 100644
index 7c8faca2a..000000000
Binary files a/documentation/src/fluid2.png and /dev/null differ
diff --git a/documentation/src/fluid3-cxx.png b/documentation/src/fluid3-cxx.png
deleted file mode 100644
index 57ed92d95..000000000
Binary files a/documentation/src/fluid3-cxx.png and /dev/null differ
diff --git a/documentation/src/fluid3-gui.png b/documentation/src/fluid3-gui.png
deleted file mode 100644
index 48d564c8a..000000000
Binary files a/documentation/src/fluid3-gui.png and /dev/null differ
diff --git a/documentation/src/fluid3-style.png b/documentation/src/fluid3-style.png
deleted file mode 100644
index b7d02a2ab..000000000
Binary files a/documentation/src/fluid3-style.png and /dev/null differ
diff --git a/documentation/src/fluid4.png b/documentation/src/fluid4.png
deleted file mode 100644
index 60cec7458..000000000
Binary files a/documentation/src/fluid4.png and /dev/null differ
diff --git a/documentation/src/fluid_widget_cxx.png b/documentation/src/fluid_widget_cxx.png
deleted file mode 100644
index c5261fb56..000000000
Binary files a/documentation/src/fluid_widget_cxx.png and /dev/null differ
diff --git a/documentation/src/fluid_widget_gui.png b/documentation/src/fluid_widget_gui.png
deleted file mode 100644
index df26e7316..000000000
Binary files a/documentation/src/fluid_widget_gui.png and /dev/null differ
diff --git a/documentation/src/fluid_widget_style.png b/documentation/src/fluid_widget_style.png
deleted file mode 100644
index fd44a0fd0..000000000
Binary files a/documentation/src/fluid_widget_style.png and /dev/null differ
diff --git a/documentation/src/index.dox b/documentation/src/index.dox
index 48494d229..e82bccfd6 100644
--- a/documentation/src/index.dox
+++ b/documentation/src/index.dox
@@ -67,11 +67,6 @@
\subpage opengl
- \subpage fluid
- - \ref fluid_widget_attributes
- - \ref fluid_selecting_moving
- - \ref fluid_images
-
\subpage fltk-options
\subpage advanced
diff --git a/documentation/src/intro.dox b/documentation/src/intro.dox
index 7e441b502..48eee0dc8 100644
--- a/documentation/src/intro.dox
+++ b/documentation/src/intro.dox
@@ -142,6 +142,17 @@ the toolkit, which was already in use by several people, Bill
came up with "FLTK", including a bogus excuse that it
stands for "The Fast Light Toolkit".
+\section intro_fluid FLUID
+
+FLTK comes bundled with FLUID. FLUID, short for Fast Light User Interface
+Designer, is a graphical editor capable of generating C++ source code and
+header files ready for compilation. These files ultimately create the graphical
+user interface for an application.
+
+The FLUID User Handbook is available at https://www.fltk.org/documentation.php .
+It can also be compiled from the FLTK source repository using the `fluid_docs`
+target in the CMake build environment.
+
\section intro_cmake Building and Installing FLTK with CMake
Starting with version 1.4, the recommended FLTK building system
diff --git a/documentation/src/opengl.dox b/documentation/src/opengl.dox
index 6ab4dc2f7..14f33a625 100644
--- a/documentation/src/opengl.dox
+++ b/documentation/src/opengl.dox
@@ -164,9 +164,7 @@ loading functions by doing:
Your main program can now create one of your windows by doing
new MyWindow(...).
-You can also use your new window class in
-\ref fluid "FLUID"
-by:
+You can also use your new window class in FLUID by:
-# Putting your class definition in a \p MyWindow.H file.
-# Creating a Fl_Box widget in FLUID.
@@ -670,8 +668,8 @@ Link with libGLEW.so (with X11 or Wayland), libglew32.a (with MinGW) or glew32.l
[Index]
diff --git a/documentation/src/osissues.dox b/documentation/src/osissues.dox
index faf7178b7..43e29463e 100644
--- a/documentation/src/osissues.dox
+++ b/documentation/src/osissues.dox
@@ -968,7 +968,7 @@ internally in the same way.
\subsection osissues_mac_files Mac File System Specifics
-\par Resource Forks
+\par Resource Forks (OS X pre 10.6)
FLTK does not access the resource fork of an application.
However, a minimal resource fork must be created for OS X
diff --git a/documentation/src/preface.dox b/documentation/src/preface.dox
index 67304fbd2..0bfc54c55 100644
--- a/documentation/src/preface.dox
+++ b/documentation/src/preface.dox
@@ -31,7 +31,6 @@ This manual is organized into the following chapters and appendices:
\li \ref events
\li \ref subclassing
\li \ref opengl
-\li \ref fluid
\li \ref fltk-options
\li \ref advanced
\li \ref unicode
diff --git a/documentation/src/subclassing.dox b/documentation/src/subclassing.dox
index bbf750b15..e37924bf9 100644
--- a/documentation/src/subclassing.dox
+++ b/documentation/src/subclassing.dox
@@ -40,9 +40,7 @@ The constructor should have the following arguments:
MyClass(int x, int y, int w, int h, const char *label = 0);
\endcode
-This will allow the class to be used in
-\ref fluid "FLUID"
-without problems.
+This will allow the class to be used in FLUID without problems.
The constructor must call the constructor for the base class and
pass the same arguments:
diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt
index bb3b9fe51..b9065616b 100644
--- a/fluid/CMakeLists.txt
+++ b/fluid/CMakeLists.txt
@@ -37,7 +37,8 @@ set(CPPFILES
Fluid_Image.cxx
about_panel.cxx
align_widget.cxx
- alignment_panel.cxx
+ settings_panel.cxx
+ autodoc.cxx
code.cxx
custom_widgets.cxx
factory.cxx
@@ -47,7 +48,7 @@ set(CPPFILES
mergeback.cxx
pixmaps.cxx
shell_command.cxx
- sourceview_panel.cxx
+ codeview_panel.cxx
template_panel.cxx
undo.cxx
widget_browser.cxx
@@ -71,19 +72,19 @@ set(HEADERFILES
StyleParse.h
about_panel.h
align_widget.h
- alignment_panel.h
+ settings_panel.h
+ autodoc.h
code.h
comments.h
custom_widgets.h
factory.h
file.h
- fluid.h
function_panel.h
mergeback.h
print_panel.h
pixmaps.h
shell_command.h
- sourceview_panel.h
+ codeview_panel.h
template_panel.h
undo.h
widget_browser.h
diff --git a/fluid/CodeEditor.h b/fluid/CodeEditor.h
index 9886705aa..9cfa50abe 100644
--- a/fluid/CodeEditor.h
+++ b/fluid/CodeEditor.h
@@ -72,7 +72,7 @@ public:
/**
A widget derived from CodeEditor with highlighting for code blocks.
- This widget is used by the SourceView system to show the design's
+ This widget is used by the codeview system to show the design's
source and header code. The secondary highlighting show the text
part that corresponds to the selected widget(s).
*/
diff --git a/fluid/Fd_Snap_Action.cxx b/fluid/Fd_Snap_Action.cxx
index ffd944cd8..ce3d6f082 100644
--- a/fluid/Fd_Snap_Action.cxx
+++ b/fluid/Fd_Snap_Action.cxx
@@ -17,7 +17,7 @@
#include "Fd_Snap_Action.h"
#include "Fl_Group_Type.h"
-#include "alignment_panel.h"
+#include "settings_panel.h"
#include "shell_command.h" // get and set Fl_String preferences
#include "file.h"
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx
index 6dc9fc927..22bcf7265 100644
--- a/fluid/Fl_Function_Type.cxx
+++ b/fluid/Fl_Function_Type.cxx
@@ -1279,7 +1279,7 @@ void Fl_Data_Type::write_code1(Fd_Code_Writer& f) {
int nData = -1;
int uncompressedDataSize = 0;
// path should be set correctly already
- if (filename_ && !f.write_sourceview) {
+ if (filename_ && !f.write_codeview) {
enter_project_dir();
FILE *f = fl_fopen(filename_, "rb");
leave_project_dir();
@@ -1395,8 +1395,8 @@ void Fl_Data_Type::write_code1(Fd_Code_Writer& f) {
}
}
// if we are in interactive mode, we pop up a warning dialog
- // giving the error: (batch_mode && !write_sourceview) ???
- if (message && !f.write_sourceview) {
+ // giving the error: (batch_mode && !write_codeview) ???
+ if (message && !f.write_codeview) {
if (batch_mode)
fprintf(stderr, "FLUID ERROR: %s %s\n", message, fn);
else
@@ -1535,9 +1535,11 @@ BREAK2:
*/
void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) {
const char* c = name();
- if (public_)
- f.write_h("%s\n", c);
- f.write_c("%s\n", c);
+ if (c && *c) {
+ if (public_)
+ f.write_h("%s\n", c);
+ f.write_c("%s\n", c);
+ }
}
/**
@@ -1545,9 +1547,11 @@ void Fl_DeclBlock_Type::write_code1(Fd_Code_Writer& f) {
*/
void Fl_DeclBlock_Type::write_code2(Fd_Code_Writer& f) {
const char* c = after;
- if (public_)
- f.write_h("%s\n", c);
- f.write_c("%s\n", c);
+ if (c && *c) {
+ if (public_)
+ f.write_h("%s\n", c);
+ f.write_c("%s\n", c);
+ }
}
// ---- Fl_Comment_Type declaration
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index e1b184327..a649ea311 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -696,8 +696,8 @@ void Fl_Type::move_before(Fl_Type* g) {
// write a widget and all its children:
void Fl_Type::write(Fd_Project_Writer &f) {
- if (f.write_sourceview()) proj1_start = (int)ftell(f.file()) + 1;
- if (f.write_sourceview()) proj2_start = (int)ftell(f.file()) + 1;
+ if (f.write_codeview()) proj1_start = (int)ftell(f.file()) + 1;
+ if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1;
f.write_indent(level);
f.write_word(type_name());
@@ -712,9 +712,9 @@ void Fl_Type::write(Fd_Project_Writer &f) {
write_properties(f);
if (parent) parent->write_parent_properties(f, this, true);
f.write_close(level);
- if (f.write_sourceview()) proj1_end = (int)ftell(f.file());
+ if (f.write_codeview()) proj1_end = (int)ftell(f.file());
if (!is_parent()) {
- if (f.write_sourceview()) proj2_end = (int)ftell(f.file());
+ if (f.write_codeview()) proj2_end = (int)ftell(f.file());
return;
}
// now do children:
@@ -722,9 +722,9 @@ void Fl_Type::write(Fd_Project_Writer &f) {
Fl_Type *child;
for (child = next; child && child->level > level; child = child->next)
if (child->level == level+1) child->write(f);
- if (f.write_sourceview()) proj2_start = (int)ftell(f.file()) + 1;
+ if (f.write_codeview()) proj2_start = (int)ftell(f.file()) + 1;
f.write_close(level);
- if (f.write_sourceview()) proj2_end = (int)ftell(f.file());
+ if (f.write_codeview()) proj2_end = (int)ftell(f.file());
}
void Fl_Type::write_properties(Fd_Project_Writer &f) {
@@ -1092,7 +1092,7 @@ Fl_Type *Fl_Type::find_by_uid(unsigned short uid) {
return NULL;
}
-/** Find a type node by using the sourceview text positions.
+/** Find a type node by using the codeview text positions.
\param[in] text_type 0=source file, 1=header, 2=.fl project file
\param[in] crsr cursor position in text
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
index 39a9bb30b..67e7c8965 100644
--- a/fluid/Fl_Type.h
+++ b/fluid/Fl_Type.h
@@ -146,7 +146,7 @@ public: // things that should not be public:
Fl_Type *factory;
const char *callback_name(Fd_Code_Writer& f);
- // text positions of this type in code, header, and project file (see SourceView)
+ // text positions of this type in code, header, and project file (see codeview)
int code_static_start, code_static_end;
int code1_start, code1_end;
int code2_start, code2_end;
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
index 310792d0c..485cb8d8f 100644
--- a/fluid/Fl_Widget_Type.cxx
+++ b/fluid/Fl_Widget_Type.cxx
@@ -24,7 +24,7 @@
#include "file.h"
#include "code.h"
#include "Fluid_Image.h"
-#include "alignment_panel.h"
+#include "settings_panel.h"
#include "widget_panel.h"
#include "undo.h"
#include "mergeback.h"
@@ -383,7 +383,7 @@ void name_public_cb(Fl_Choice* i, void* v) {
/* Treating UNDO for text widget.
Goal: we want to continuously update the UI while the user is typing text
- (changing the label, in this case). Source View does deferred updates, and
+ (changing the label, in this case). Code View does deferred updates, and
the widget browser and widget panel update on every keystroke. At the same
time, we want to limit undo actions to few and logical units.
@@ -2727,7 +2727,7 @@ void Fl_Widget_Type::open() {
extern void redraw_overlays();
extern void check_redraw_corresponding_parent(Fl_Type*);
extern void redraw_browser();
-extern void update_sourceview_position();
+extern void update_codeview_position();
// Called when ui changes what objects are selected:
// p is selected object, null for all deletions (we must throw away
@@ -2761,8 +2761,8 @@ void selection_changed(Fl_Type *p) {
redraw_overlays();
// load the panel with the new settings:
load_panel();
- // update the source viewer to show the code for the selected object
- update_sourceview_position();
+ // update the code viewer to show the code for the selected object
+ update_codeview_position();
}
////////////////////////////////////////////////////////////////
diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h
index b1773a501..40470c544 100644
--- a/fluid/Fl_Widget_Type.h
+++ b/fluid/Fl_Widget_Type.h
@@ -127,5 +127,6 @@ public:
void redraw();
};
+extern Fl_Window *the_panel;
#endif // _FLUID_FL_WIDGET_TYPE_H
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index bc848ed75..b68af4406 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -25,7 +25,7 @@
#include "fluid.h"
#include "widget_browser.h"
#include "undo.h"
-#include "alignment_panel.h"
+#include "settings_panel.h"
#include "file.h"
#include "code.h"
#include "widget_panel.h"
diff --git a/fluid/Makefile b/fluid/Makefile
index 75a785e71..eb5b8c192 100644
--- a/fluid/Makefile
+++ b/fluid/Makefile
@@ -31,7 +31,8 @@ CPPFILES = \
Fluid_Image.cxx \
about_panel.cxx \
align_widget.cxx \
- alignment_panel.cxx \
+ settings_panel.cxx \
+ autodoc.cxx \
code.cxx \
custom_widgets.cxx \
factory.cxx \
@@ -42,7 +43,7 @@ CPPFILES = \
mergeback.cxx \
pixmaps.cxx \
shell_command.cxx \
- sourceview_panel.cxx \
+ codeview_panel.cxx \
template_panel.cxx \
undo.cxx \
widget_browser.cxx \
@@ -141,9 +142,9 @@ uninstall-osx:
rebuild: fluid$(EXEEXT)
echo 'Rebuilding fluid (.fl) and .cxx/.h files from .fl files ...'
./fluid$(EXEEXT) -u -c about_panel.fl
- ./fluid$(EXEEXT) -u -c alignment_panel.fl
+ ./fluid$(EXEEXT) -u -c settings_panel.fl
./fluid$(EXEEXT) -u -c function_panel.fl
./fluid$(EXEEXT) -u -c print_panel.fl
- ./fluid$(EXEEXT) -u -c sourceview_panel.fl
+ ./fluid$(EXEEXT) -u -c codeview_panel.fl
./fluid$(EXEEXT) -u -c template_panel.fl
./fluid$(EXEEXT) -u -c widget_panel.fl
diff --git a/fluid/autodoc.cxx b/fluid/autodoc.cxx
new file mode 100644
index 000000000..63818d8af
--- /dev/null
+++ b/fluid/autodoc.cxx
@@ -0,0 +1,602 @@
+//
+// Self-generate snapshots of user interface for FLUID documentation.
+//
+// Copyright 2024 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 NDEBUG
+
+#include "autodoc.h"
+#include "fluid.h"
+#include "factory.h"
+#include "widget_browser.h"
+#include "widget_panel.h"
+#include "Fl_Widget_Type.h"
+#include "Fl_Window_Type.h"
+#include "function_panel.h"
+#include "settings_panel.h"
+#include "codeview_panel.h"
+
+#include
+#include
+#include
+#include
+#include
+
+extern Fl_Double_Window *settings_window;
+
+/** \file autodoc.cxx
+
+ \todo Implement a function to snapshot a window including decoration
+ - see: void Fl_Widget_Surface::draw_decorated_window(Fl_Window *win, int win_offset_x, int win_offset_y)
+ - see: void Fl_Widget_Surface::origin(int x, int y)
+ - see: void Fl_Widget_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y)
+ - see: void Fl_Widget_Surface::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y)
+
+ \todo Implement a version that snaps multiple windows in a desktop style situation.
+
+ \todo a version that takes snapshots of a range of menu items
+
+ \todo implement FL_SNAP_TO_GROUP, possibly with a number on how many groups up in the hierarchy
+ */
+
+/** \addtogroup fl_drawings
+ @{
+ */
+
+const int FL_SNAP_TO_WINDOW = 0x7f000000;
+
+static Fl_Box snap_clear_(0, 0, 0, 0);
+Fl_Widget *FL_SNAP_AREA_CLEAR = &snap_clear_;
+
+static inline int fl_min(int a, int b) { return a < b ? a : b; }
+static inline uchar fl_min(uchar a, uchar b) { return a < b ? a : b; }
+static inline int fl_max(int a, int b) { return a > b ? a : b; }
+
+/**
+ Create a rect by providing a margin around a zero size rectangle.
+ \param[in] dx, dy positive integers, move margin up and left
+ \param[in] dr, db move margin to the right and down
+ */
+Fl_Margin::Fl_Margin(int dx, int dy, int dr, int db)
+ : Fl_Rect(-dx, -dy, dx+dr, dy+db)
+{
+}
+
+/**
+ Convert an RGB image into an RGBA image.
+ \param[inout] image pointer to an RGB image, deletes the RGB image, returns the RGBA image
+ \return 0 if the image is now in RGBA format, or -1 if it can't be converted
+ */
+static int convert_RGB_to_RGBA(Fl_RGB_Image *&img) {
+ if (img->d() == 4)
+ return 0;
+ if (img->d() != 3)
+ return -1;
+
+ // Copy pixel data from RGB to RGBA raw data
+ int img_w = img->w();
+ int img_h = img->h();
+ uchar *data = new uchar[img_w * img_h * 4], *dst = data;
+ int ld = img->ld(); if (ld == 0) ld = img_w * 3;
+ int i, j;
+ for (i=0; idata()[0] + i * ld;
+ for (j=0; jd() != 4)
+ return;
+ if (dx > img->w())
+ return;
+ if (dx > 0) {
+ int max_x = dx, max_y = img->h();
+ int ld = img->ld(); if (ld == 0) ld = img->w() * img->d();
+ float a = 255/max_x;
+ for (int i = 0; i < max_x; i++) {
+ uchar *rgba = (uchar*)img->data()[0] + i * img->d();
+ uchar alpha = static_cast(i * a);
+ for (int j = 0; j < max_y; j++) {
+ rgba[3] = fl_min(alpha, rgba[3]);
+ rgba += ld;
+ }
+ }
+ }
+}
+
+/**
+ Blend the top lines of the alpha channel of an RBGA image to full transparency.
+ \param[in] img must be an RGBA image
+ \param[in] dy number of lines to blend
+ */
+void blend_alpha_top(const Fl_RGB_Image *img, int dy) {
+ if (img->d() != 4)
+ return;
+ if (dy > img->h())
+ return;
+ if (dy > 0) {
+ int max_x = img->w(), max_y = dy;
+ int ld = img->ld(); if (ld == 0) ld = img->w() * img->d();
+ float a = 255/max_y;
+ for (int i = 0; i < max_y; i++) {
+ uchar *rgba = (uchar*)img->data()[0] + i * ld;
+ uchar alpha = static_cast(i * a);
+ for (int j = 0; j < max_x; j++) {
+ rgba[3] = fl_min(alpha, rgba[3]);
+ rgba += 4;
+ }
+ }
+ }
+}
+
+/**
+ Blend the right side lines of the alpha channel of an RBGA image to full transparency.
+ \param[in] img must be an RGBA image
+ \param[in] dx number of lines to blend
+ */
+void blend_alpha_right(const Fl_RGB_Image *img, int dx) {
+ if (img->d() != 4)
+ return;
+ if (dx > img->w())
+ return;
+ if (dx > 0) {
+ int max_x = dx, max_y = img->h();
+ int ld = img->ld(); if (ld == 0) ld = img->w() * img->d();
+ float a = 255/max_x;
+ for (int i = 0; i < max_x; i++) {
+ uchar *rgba = (uchar*)img->data()[0] + (img->w()-i-1) * img->d();
+ uchar alpha = static_cast(i * a);
+ for (int j = 0; j < max_y; j++) {
+ rgba[3] = fl_min(alpha, rgba[3]);
+ rgba += ld;
+ }
+ }
+ }
+}
+
+/**
+ Blend the bottom lines of the alpha channel of an RBGA image to full transparency.
+ \param[in] img must be an RGBA image
+ \param[in] dy number of lines to blend
+ */
+void blend_alpha_bottom(const Fl_RGB_Image *img, int dy) {
+ if (img->d() != 4)
+ return;
+ if (dy > img->h())
+ return;
+ if (dy > 0) {
+ int max_x = img->w(), max_y = dy;
+ int ld = img->ld(); if (ld == 0) ld = img->w() * img->d();
+ float a = 255/max_y;
+ for (int i = 0; i < max_y; i++) {
+ uchar *rgba = (uchar*)img->data()[0] + (img->h()-i-1) * ld;
+ uchar alpha = static_cast(i * a);
+ for (int j = 0; j < max_x; j++) {
+ rgba[3] = fl_min(alpha, rgba[3]);
+ rgba += 4;
+ }
+ }
+ }
+}
+
+/**
+ Take a snapshot of a number of widgets and save it as a png image.
+
+ Draw a rectangular snapshot that fits around all widgets inside a window.
+ All widgets must be inside the same window. It's up to the caller to ensure
+ that widgets are visible. This includes children of `Fl_Tabs`.
+
+ Outside labels of widgets are not taken into account, but a `frame` can be
+ provided to grow the snapshot rectangle. Setting individual parameters of the
+ frame to `FL_SNAP_TO_WINDOW` will extend the snapshot to the borders of the
+ top level window.
+
+ Another `blend` frame can be added around the image that fades to full
+ transparency on selected sides.
+
+ Use `Fl_Margin` to create `frame` and `blend` using positive integers to grow
+ the rectangle to the left, top, right, and bottom.
+
+ The image can be scaled after all processing. Note that snapshot is always
+ created in FLTK resolution, even if the screen uses a higher resolution.
+
+ \param[in] filename the snapshot will be written to this file in png format
+ \param[in] w draw a bounding box around all widgets in the NULL terminated list
+ \param[in] frame add a margin around the bounding box
+ \param[in] blend add another margin around the bounding box that fades to full transparency
+ \param[in] scale scale everything by this factor before saving it
+ \return the result of fl_write_png or -3 if another error occurred
+ */
+int fl_snapshot(const char *filename, Fl_Widget **w,
+ const Fl_Rect &frame,
+ const Fl_Rect &blend,
+ double scale)
+{
+ int i, min_x = 0, min_y = 0, max_x = 0, max_y = 0, bb_w, bb_h, img_w, img_h;
+
+ // Get the bounding box for all widgets and make sure that all widgets are shown
+ for (i=0; w[i]; i++) {
+ int x, y;
+ Fl_Widget *ww = w[i];
+ if (ww == FL_SNAP_AREA_CLEAR) {
+ min_x = max_x = 0;
+ min_y = max_y = 0;
+ } else {
+ ww->top_window_offset(x, y);
+ if (i==0) {
+ min_x = x; max_x = x + ww->w();
+ min_y = y; max_y = y + ww->h();
+ } else {
+ min_x = fl_min(min_x, x); max_x = fl_max(max_x, x + ww->w());
+ min_y = fl_min(min_y, y); max_y = fl_max(max_y, y + ww->h());
+ }
+ }
+
+ // this does not help us with Fl_Tab groups
+ while (ww) { ww->show(); ww = ww->parent(); }
+ }
+
+ // Check for special values in frame and adjust bounding box
+ Fl_Rect c_frame = frame;
+ if (frame.x() == -FL_SNAP_TO_WINDOW) c_frame.x(-min_x);
+ if (frame.y() == -FL_SNAP_TO_WINDOW) c_frame.y(-min_y);
+ if (frame.r() == FL_SNAP_TO_WINDOW) c_frame.r(w[0]->top_window()->w()-max_x);
+ if (frame.b() == FL_SNAP_TO_WINDOW) c_frame.b(w[0]->top_window()->h()-max_y);
+
+ min_x += c_frame.x(); max_x += c_frame.r();
+ min_y += c_frame.y(); max_y += c_frame.b();
+ bb_w = max_x - min_x; bb_h = max_y - min_y;
+ img_w = bb_w + blend.w();
+ img_h = bb_h + blend.h();
+
+ // Generate the Image Surface
+ Fl_Image_Surface *srfc = new Fl_Image_Surface(img_w, img_h);
+ Fl_Image_Surface::push_current(srfc);
+
+ // Draw the background
+ fl_rectf(0, 0, img_w, img_h, 0x1395bf00);
+
+ // Draw the top level window
+ srfc->draw(w[0]->top_window(), -blend.x()-min_x, -blend.y()-min_y);
+ Fl_Image_Surface::pop_current();
+ Fl_RGB_Image *img = srfc->image();
+
+ // Do we want an alpha blended extension of the frame?
+ if ((blend.x()<0 || blend.y()<0 || blend.r()>0 || blend.b()>0)) {
+ if (convert_RGB_to_RGBA(img) == -1) {
+ delete img;
+ delete srfc;
+ return -3;
+ }
+ if (blend.x() < 0) blend_alpha_left(img, -blend.x());
+ if (blend.y() < 0) blend_alpha_top(img, -blend.y());
+ if (blend.r() > 0) blend_alpha_right(img, blend.r());
+ if (blend.b() > 0) blend_alpha_bottom(img, blend.b());
+ }
+
+ // If scale is set, scale the image
+ if (scale != 1.0) {
+ Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR);
+ Fl_RGB_Image *scaled_img = (Fl_RGB_Image*)img->copy(img->w()*scale, img->h()*scale);
+ delete img;
+ img = scaled_img;
+ }
+
+ // Write the image to disk
+ int ret = fl_write_png(filename, img);
+
+ // Clean up
+ delete img;
+ delete srfc;
+ return ret;
+}
+
+/**
+ Take a snapshot of the size of the bounding box around two widgets and save it as a png image.
+
+ \param[in] filename the snapshot will be written to this file in png format
+ \param[in] w1, w2 top left and bottom right widget
+ \param[in] frame add a margin around the bounding box
+ \param[in] blend add another margin around the bounding box that fades to full transparency
+ \param[in] scale scale everything by this factor before saving it
+ \return the result of fl_write_png or -3 if another error occurred
+
+ \see fl_snapshot(const char*, Fl_Widget**, const Fl_Rect&, const Fl_Rect&, double)
+ */
+int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2,
+ const Fl_Rect &frame,
+ const Fl_Rect &blend,
+ double scale)
+{
+ Fl_Widget *ww[3] = { w1, w2, NULL };
+ return fl_snapshot(filename, ww, frame, blend, scale);
+}
+
+/**
+ Take a snapshot of a widget inside its window and save it as a png image.
+
+ \param[in] filename the snapshot will be written to this file in png format
+ \param[in] w snap this window, can also be a groups
+ \param[in] frame add a margin around the bounding box
+ \param[in] blend add another margin around the bounding box that fades to full transparency
+ \param[in] scale scale everything by this factor before saving it
+ \return the result of fl_write_png or -3 if another error occurred
+
+ \see fl_snapshot(const char*, Fl_Widget**, const Fl_Rect&, const Fl_Rect&, double)
+ */
+int fl_snapshot(const char *filename, Fl_Widget *w,
+ const Fl_Rect &frame,
+ const Fl_Rect &blend,
+ double scale)
+{
+ Fl_Widget *ww[2] = { w, NULL };
+ return fl_snapshot(filename, ww, frame, blend, scale);
+}
+
+/** @} */
+
+
+void run_autodoc(const Fl_String &target_dir) {
+ // A list of all the margins we will use later
+ Fl_Margin win_margin(0, 0, 0, 0);
+ Fl_Margin win_blend(10, 10, 10, 10);
+ Fl_Margin tab_margin(FL_SNAP_TO_WINDOW, 32, FL_SNAP_TO_WINDOW, 4);
+ Fl_Margin xtab_margin(FL_SNAP_TO_WINDOW, 50, FL_SNAP_TO_WINDOW, 4);
+ Fl_Margin row_margin(FL_SNAP_TO_WINDOW, 4, FL_SNAP_TO_WINDOW, 4);
+ Fl_Margin xrow_margin(FL_SNAP_TO_WINDOW, 14, FL_SNAP_TO_WINDOW, 4);
+ Fl_Margin row_blend(0, 10, 0, 10);
+
+// Fl::scheme("gtk+");
+
+ // Create a silly project that contains all widgets that we want to document
+ new_project(false);
+
+ /*Fl_Type *t_func = */ add_new_widget_from_user("Function", kAddAsLastChild, false);
+ Fl_Window_Type *t_win = (Fl_Window_Type*)add_new_widget_from_user("Fl_Window", kAddAsLastChild, false);
+ t_win->label("My Main Window");
+ Fl_Widget_Type *t_grp = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Group", kAddAsLastChild, false);
+ t_grp->public_ = 0;
+ Fl_Widget_Type *t_btn = (Fl_Widget_Type*)add_new_widget_from_user("Fl_Button", kAddAsLastChild, false);
+ t_btn->comment("Don't press this button!");
+ t_btn->name("emergency_btn");
+ ((Fl_Button*)t_btn->o)->shortcut(FL_COMMAND|'g');
+ Fl_Type *t_sldr = add_new_widget_from_user("Fl_Slider", kAddAsLastChild, false);
+ Fl_Type *t_inp = add_new_widget_from_user("Fl_Input", kAddAsLastChild, false);
+ Fl_Type *t_flx = add_new_widget_from_user("Fl_Flex", kAddAsLastChild, false);
+ Fl_Type *t_flxc = add_new_widget_from_user("Fl_Button", kAddAsLastChild, false);
+ select_only(t_grp);
+ Fl_Type *t_grd = add_new_widget_from_user("Fl_Grid", kAddAsLastChild, false);
+ Fl_Type *t_grdc = add_new_widget_from_user("Fl_Button", kAddAsLastChild, false);
+
+ widget_browser->rebuild();
+ g_project.update_settings_dialog();
+
+ // TODO: FLUID overview
+
+ // TODO: explain FLUID command line usage
+
+ // TODO: take a snapshot of FLUID in a desktop situation
+ // (main, toolbar, document, widget editor, code view)
+
+ // ---- main window
+ // explain titlebar
+ // explain menubar?
+ // explain widget browser
+ // explain widget browser entry
+ main_window->size(350, 320);
+ fl_snapshot((target_dir + "main_window.png").c_str(), main_window, win_margin, win_blend);
+ fl_snapshot((target_dir + "main_menubar.png").c_str(), main_menubar, row_margin, row_blend);
+ fl_snapshot((target_dir + "main_browser.png").c_str(), widget_browser, FL_SNAP_AREA_CLEAR,
+ Fl_Rect(0, 30, FL_SNAP_TO_WINDOW, 100), row_blend, 2.0);
+
+
+ // TODO: document view
+ // explain dnd
+ // explain selection, multiple selection, keyboard shortcuts
+ // explain mouse functionality and alignment
+ // explain live resize
+ // arrow: move by 1
+ // shift: resize by one
+ // Meta: move by Widget Gap
+ // Shift Meta: resize by Widget Increment
+
+ // ---- widget bin
+ // show grouping
+ // explain non-widget types and where they will be located
+ // explain widgets types an their dnd option
+ // explain menu arrays
+ // list exceptions (subwindow, scroll)
+ if (!widgetbin_panel) make_widgetbin();
+ fl_snapshot((target_dir + "widgetbin_panel.png").c_str(), widgetbin_panel, win_margin, win_blend);
+
+ // ---- code view
+ // explain functionality
+ // explain live update and choices
+ // show various tabs
+ // explain find and locate
+ if (!codeview_panel) make_codeview();
+ update_codeview_cb(NULL, NULL);
+ cv_tab->value(cv_source_tab);
+ fl_snapshot((target_dir + "codeview_panel.png").c_str(), codeview_panel, win_margin, win_blend);
+ fl_snapshot((target_dir + "cv_find_row.png").c_str(), cv_find_row, row_margin, row_blend);
+ fl_snapshot((target_dir + "cv_settings_row.png").c_str(), cv_settings_row, row_margin, row_blend);
+
+ // ---- settings dialog
+ // show and explain all tabs
+ fl_snapshot((target_dir + "w_settings.png").c_str(), settings_window, win_margin, win_blend);
+ fl_snapshot((target_dir + "w_settings_general_tab.png").c_str(), w_settings_general_tab, xtab_margin, row_blend);
+ w_settings_tabs->value(w_settings_project_tab);
+ fl_snapshot((target_dir + "w_settings_project_tab.png").c_str(), w_settings_project_tab, xtab_margin, row_blend);
+ w_settings_tabs->value(w_settings_layout_tab);
+ fl_snapshot((target_dir + "w_settings_layout_tab.png").c_str(), w_settings_layout_tab, xtab_margin, row_blend);
+ w_settings_tabs->value(w_settings_shell_tab);
+ w_settings_shell_list->value(1);
+ w_settings_shell_list->do_callback();
+ fl_snapshot((target_dir + "w_settings_shell_tab.png").c_str(), w_settings_shell_tab, xtab_margin, row_blend);
+ w_settings_tabs->value(w_settings_i18n_tab);
+ i18n_type_chooser->value(1);
+ i18n_type_chooser->do_callback();
+ fl_snapshot((target_dir + "w_settings_i18n_gnu.png").c_str(), i18n_type_chooser, i18n_gnu_static_function_input, row_margin, row_blend);
+ i18n_type_chooser->value(2);
+ i18n_type_chooser->do_callback();
+ fl_snapshot((target_dir + "w_settings_i18n_psx.png").c_str(), i18n_type_chooser, i18n_pos_set_input, row_margin, row_blend);
+ w_settings_tabs->value(w_settings_user_tab);
+ fl_snapshot((target_dir + "w_settings_user_tab.png").c_str(), w_settings_user_tab, xtab_margin, row_blend);
+
+
+ // ---- dialog types
+ // list and show all non-widget types and their respective dialog boxes
+
+ // -- ID_Function
+ Fl_Window *adoc_function_panel = make_function_panel();
+ f_name_input->value("count_trees(const char *forest_name)");
+ f_return_type_input->value("unsigned int");
+ fl_snapshot((target_dir + "function_panel.png").c_str(), adoc_function_panel, win_margin, win_blend);
+ adoc_function_panel->hide();
+
+ // -- ID_Code
+ Fl_Window *adoc_code_panel = make_code_panel();
+ code_input->buffer()->text("// increment user count\nif (new_user) {\n user_count++;\n}\n");
+ fl_snapshot((target_dir + "code_panel.png").c_str(), adoc_code_panel, win_margin, win_blend);
+ adoc_code_panel->hide();
+
+ // -- ID_CodeBlock
+ Fl_Window *adoc_codeblock_panel = make_codeblock_panel();
+ code_before_input->value("if (test())");
+ code_after_input->value("// test widgets added...");
+ fl_snapshot((target_dir + "codeblock_panel.png").c_str(), adoc_codeblock_panel, win_margin, win_blend);
+ adoc_codeblock_panel->hide();
+
+ // -- ID_Decl
+ Fl_Window *adoc_decl_panel = make_decl_panel();
+ decl_class_choice->hide();
+ decl_input->buffer()->text("const char *damage = \"'tis but a scratch\";");
+ fl_snapshot((target_dir + "decl_panel.png").c_str(), adoc_decl_panel, win_margin, win_blend);
+ adoc_decl_panel->hide();
+
+ // -- ID_DeclBlock
+ Fl_Window *adoc_declblock_panel = make_declblock_panel();
+ decl_before_input->value("#ifdef NDEBUG");
+ decl_after_input->value("#endif // NDEBUG");
+ fl_snapshot((target_dir + "declblock_panel.png").c_str(), adoc_declblock_panel, win_margin, win_blend);
+ adoc_declblock_panel->hide();
+
+ // -- ID_Class
+ Fl_Window *adoc_class_panel = make_class_panel();
+ decl_class_choice->hide();
+ c_name_input->value("Zoo_Giraffe");
+ c_subclass_input->value("Zoo_Animal");
+ fl_snapshot((target_dir + "class_panel.png").c_str(), adoc_class_panel, win_margin, win_blend);
+ adoc_class_panel->hide();
+
+ // -- ID_Widget_Class is handled like Fl_Window_Type
+
+ // -- ID_Comment
+ Fl_Window *adoc_comment_panel = make_comment_panel();
+ comment_input->buffer()->text("Make sure that the giraffe gets enough hay,\nbut the monkey can't reach it.");
+ fl_snapshot((target_dir + "comment_panel.png").c_str(), adoc_comment_panel, win_margin, win_blend);
+ adoc_comment_panel->hide();
+
+ // -- ID_Data
+ Fl_Window *adoc_data_panel = make_data_panel();
+ data_class_choice->hide();
+ data_input->value("emulated_ROM");
+ data_filename->value("./ROM.bin");
+ fl_snapshot((target_dir + "data_panel.png").c_str(), adoc_data_panel, win_margin, win_blend);
+ adoc_data_panel->hide();
+
+
+ // ---- widget dialog
+ t_win->open(); // open the window
+ t_win->open(); // open the panel
+ select_only(t_win);
+
+ // -- snapshot of the widget properties panel
+ fl_snapshot((target_dir + "widget_panel.png").c_str(), the_panel, win_margin, win_blend);
+ fl_snapshot((target_dir + "wLiveMode.png").c_str(), wLiveMode, row_margin, row_blend);
+
+ // -- snapshot of the GUI tab
+ widget_tabs->value(wp_gui_tab);
+ fl_snapshot((target_dir + "wp_gui_tab.png").c_str(), wp_gui_tab, tab_margin, row_blend);
+ fl_snapshot((target_dir + "wp_gui_label.png").c_str(), wp_gui_label, row_margin, row_blend);
+ select_only(t_btn);
+ fl_snapshot((target_dir + "wp_gui_image.png").c_str(), widget_image_input, widget_deimage_input, row_margin, row_blend);
+ fl_snapshot((target_dir + "wp_gui_alignment.png").c_str(), wp_gui_alignment, row_margin, row_blend);
+ fl_snapshot((target_dir + "wp_gui_size.png").c_str(), widget_x_input, xrow_margin, row_blend);
+ select_only(t_sldr);
+ fl_snapshot((target_dir + "wp_gui_values.png").c_str(), wp_gui_values, xrow_margin, row_blend);
+ select_only(t_flxc);
+ fl_snapshot((target_dir + "wp_gui_flexp.png").c_str(), wp_gui_flexp, xrow_margin, row_blend);
+ select_only(t_flx);
+ fl_snapshot((target_dir + "wp_gui_margins.png").c_str(), wp_gui_margins, xrow_margin, row_blend);
+ select_only(t_win);
+ fl_snapshot((target_dir + "wp_gui_sizerange.png").c_str(), wp_gui_sizerange, xrow_margin, row_blend);
+ select_only(t_btn);
+ fl_snapshot((target_dir + "wp_gui_shortcut.png").c_str(), wp_gui_shortcut, row_margin, row_blend);
+ select_only(t_win);
+ fl_snapshot((target_dir + "wp_gui_xclass.png").c_str(), wp_gui_xclass, row_margin, row_blend);
+ select_only(t_btn);
+ fl_snapshot((target_dir + "wp_gui_attributes.png").c_str(), wp_gui_attributes, row_margin, row_blend);
+ fl_snapshot((target_dir + "wp_gui_tooltip.png").c_str(), wp_gui_tooltip, row_margin, row_blend);
+
+ // -- snapshot of the style tab
+ widget_tabs->value(wp_style_tab);
+ select_only(t_inp);
+ fl_snapshot((target_dir + "wp_style_tab.png").c_str(), wp_style_tab, tab_margin, row_blend);
+ fl_snapshot((target_dir + "wp_style_label.png").c_str(), wp_style_label, row_margin, row_blend);
+ select_only(t_btn);
+ fl_snapshot((target_dir + "wp_style_box.png").c_str(), wp_style_box, wp_style_downbox, row_margin, row_blend);
+ select_only(t_inp);
+ fl_snapshot((target_dir + "wp_style_text.png").c_str(), wp_style_text, row_margin, row_blend);
+
+ // -- snapshot of the C++ tab
+ widget_tabs->value(wp_cpp_tab);
+ select_only(t_btn);
+ fl_snapshot((target_dir + "wp_cpp_tab.png").c_str(), wp_cpp_tab, tab_margin, row_blend);
+ fl_snapshot((target_dir + "wp_cpp_class.png").c_str(), wp_cpp_class, row_margin, row_blend);
+ fl_snapshot((target_dir + "wp_cpp_name.png").c_str(), wp_cpp_name, row_margin, row_blend);
+ fl_snapshot((target_dir + "v_input.png").c_str(), v_input[0], v_input[3], row_margin, row_blend);
+ fl_snapshot((target_dir + "wComment.png").c_str(), wComment, row_margin, row_blend);
+ fl_snapshot((target_dir + "wp_cpp_callback.png").c_str(), wCallback, w_when_box, row_margin, row_blend);
+
+ // -- snapshot of the Grid tab
+ select_only(t_grd);
+ widget_tabs->value(widget_tab_grid);
+ fl_snapshot((target_dir + "wp_grid_tab.png").c_str(), widget_tab_grid, tab_margin, row_blend);
+
+ // -- snapshot of the Grid Child tab
+ select_only(t_grdc);
+ widget_tabs->value(widget_tab_grid_child);
+ fl_snapshot((target_dir + "wp_gridc_tab.png").c_str(), widget_tab_grid_child, tab_margin, row_blend);
+}
+
+
+#endif // NDEBUG
diff --git a/fluid/autodoc.h b/fluid/autodoc.h
new file mode 100644
index 000000000..060b166ab
--- /dev/null
+++ b/fluid/autodoc.h
@@ -0,0 +1,59 @@
+//
+// Widget snapshot header-only file for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 2023-2024 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 autodoc.h
+ \brief tools to take snapshots of UI elements for documentation purposes
+ */
+
+#ifndef fl_screenshot_H
+#define fl_screenshot_H
+
+#include "../src/Fl_String.H"
+
+#include
+#include
+#include
+
+/** Class to initialize a Rect by providing the margin around a rect. */
+class Fl_Margin : public Fl_Rect {
+public:
+ Fl_Margin(int dx, int dy, int dr, int db);
+};
+
+int fl_snapshot(const char *filename, Fl_Widget **w,
+ const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4),
+ const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4),
+ double scale=1.0);
+
+int fl_snapshot(const char *filename, Fl_Widget *w1, Fl_Widget *w2,
+ const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4),
+ const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4),
+ double scale=1.0);
+
+int fl_snapshot(const char *filename, Fl_Widget *w,
+ const Fl_Rect &frame = Fl_Margin(4, 4, 4, 4),
+ const Fl_Rect &blend = Fl_Margin(4, 4, 4, 4),
+ double scale=1.0);
+
+extern const int FL_SNAP_TO_WINDOW;
+
+extern Fl_Widget *FL_SNAP_AREA_CLEAR;
+
+extern void run_autodoc(const Fl_String &target_dir);
+
+#endif
+
diff --git a/fluid/code.cxx b/fluid/code.cxx
index eef2aac47..24088ca11 100644
--- a/fluid/code.cxx
+++ b/fluid/code.cxx
@@ -414,7 +414,7 @@ void Fd_Code_Writer::write_cstring(const char *s, int length) {
}
// if we are rendering to the source code preview window, and the text is
// longer than four lines, we only render a placeholder.
- if (write_sourceview && ((s==NULL) || (length>300))) {
+ if (write_codeview && ((s==NULL) || (length>300))) {
if (length>=0)
crc_printf("\" ... %d bytes of text... \"", length);
else
@@ -523,7 +523,7 @@ void Fd_Code_Writer::write_cdata(const char *s, int length) {
varused = 1;
return;
}
- if (write_sourceview) {
+ if (write_codeview) {
if (length>=0)
crc_printf("{ /* ... %d bytes of binary data... */ }", length);
else
@@ -707,11 +707,11 @@ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) {
// write all code that comes before the children code
// (but don't write the last comment until the very end)
if (!(p==Fl_Type::last && p->is_a(ID_Comment))) {
- if (write_sourceview) p->code1_start = (int)ftell(code_file);
- if (write_sourceview) p->header1_start = (int)ftell(header_file);
+ if (write_codeview) p->code1_start = (int)ftell(code_file);
+ if (write_codeview) p->header1_start = (int)ftell(header_file);
p->write_code1(*this);
- if (write_sourceview) p->code1_end = (int)ftell(code_file);
- if (write_sourceview) p->header1_end = (int)ftell(header_file);
+ if (write_codeview) p->code1_end = (int)ftell(code_file);
+ if (write_codeview) p->header1_end = (int)ftell(header_file);
}
// recursively write the code of all children
Fl_Type* q;
@@ -730,11 +730,11 @@ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) {
}
// write all code that come after the children
- if (write_sourceview) p->code2_start = (int)ftell(code_file);
- if (write_sourceview) p->header2_start = (int)ftell(header_file);
+ if (write_codeview) p->code2_start = (int)ftell(code_file);
+ if (write_codeview) p->header2_start = (int)ftell(header_file);
p->write_code2(*this);
- if (write_sourceview) p->code2_end = (int)ftell(code_file);
- if (write_sourceview) p->header2_end = (int)ftell(header_file);
+ if (write_codeview) p->code2_end = (int)ftell(code_file);
+ if (write_codeview) p->header2_end = (int)ftell(header_file);
for (q = p->next; q && q->level > p->level;) {
if (is_class_member(q) || is_comment_before_class_member(q)) {
@@ -752,11 +752,11 @@ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) {
} else {
for (q = p->next; q && q->level > p->level;) q = write_code(q);
// write all code that come after the children
- if (write_sourceview) p->code2_start = (int)ftell(code_file);
- if (write_sourceview) p->header2_start = (int)ftell(header_file);
+ if (write_codeview) p->code2_start = (int)ftell(code_file);
+ if (write_codeview) p->header2_start = (int)ftell(header_file);
p->write_code2(*this);
- if (write_sourceview) p->code2_end = (int)ftell(code_file);
- if (write_sourceview) p->header2_end = (int)ftell(header_file);
+ if (write_codeview) p->code2_end = (int)ftell(code_file);
+ if (write_codeview) p->header2_end = (int)ftell(header_file);
}
return q;
}
@@ -772,8 +772,8 @@ Fl_Type* Fd_Code_Writer::write_code(Fl_Type* p) {
\param[in] t filename of the header file
\return 0 if the operation failed, 1 if it was successful
*/
-int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview) {
- write_sourceview = to_sourceview;
+int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_codeview) {
+ write_codeview = to_codeview;
delete id_root; id_root = 0;
indentation = 0;
current_class = 0L;
@@ -791,7 +791,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview)
header_file = f;
}
// Remember the last code file location for MergeBack
- if (s && g_project.write_mergeback_data && !to_sourceview) {
+ if (s && g_project.write_mergeback_data && !to_codeview) {
Fl_String proj_filename = g_project.projectfile_path() + g_project.projectfile_name();
int i, n = proj_filename.size();
for (i=0; iis_a(ID_Comment)) {
- if (write_sourceview) {
+ if (write_codeview) {
first_type->code1_start = first_type->code2_start = (int)ftell(code_file);
first_type->header1_start = first_type->header2_start = (int)ftell(header_file);
}
// it is ok to write non-recursive code here, because comments have no children or code2 blocks
first_type->write_code1(*this);
- if (write_sourceview) {
+ if (write_codeview) {
first_type->code1_end = first_type->code2_end = (int)ftell(code_file);
first_type->header1_end = first_type->header2_end = (int)ftell(header_file);
}
@@ -835,7 +835,7 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview)
write_h_once("#include ");
}
if (t && g_project.include_H_from_C) {
- if (to_sourceview) {
+ if (to_codeview) {
write_c("#include \"CodeView.h\"\n");
} else if (g_project.header_file_name[0] == '.' && strchr(g_project.header_file_name.c_str(), '/') == NULL) {
write_c("#include \"%s\"\n", fl_filename_name(t));
@@ -896,17 +896,17 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview)
}
for (Fl_Type* p = first_type; p;) {
// write all static data for this & all children first
- if (write_sourceview) p->header_static_start = (int)ftell(header_file);
- if (write_sourceview) p->code_static_start = (int)ftell(code_file);
+ if (write_codeview) p->header_static_start = (int)ftell(header_file);
+ if (write_codeview) p->code_static_start = (int)ftell(code_file);
p->write_static(*this);
- if (write_sourceview) p->code_static_end = (int)ftell(code_file);
- if (write_sourceview) p->header_static_end = (int)ftell(header_file);
+ if (write_codeview) p->code_static_end = (int)ftell(code_file);
+ if (write_codeview) p->header_static_end = (int)ftell(header_file);
for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next) {
- if (write_sourceview) q->header_static_start = (int)ftell(header_file);
- if (write_sourceview) q->code_static_start = (int)ftell(code_file);
+ if (write_codeview) q->header_static_start = (int)ftell(header_file);
+ if (write_codeview) q->code_static_start = (int)ftell(code_file);
q->write_static(*this);
- if (write_sourceview) q->code_static_end = (int)ftell(code_file);
- if (write_sourceview) q->header_static_end = (int)ftell(header_file);
+ if (write_codeview) q->code_static_end = (int)ftell(code_file);
+ if (write_codeview) q->header_static_end = (int)ftell(header_file);
}
// then write the nested code:
p = write_code(p);
@@ -918,12 +918,12 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview)
Fl_Type* last_type = Fl_Type::last;
if (last_type && (last_type != Fl_Type::first) && last_type->is_a(ID_Comment)) {
- if (write_sourceview) {
+ if (write_codeview) {
last_type->code1_start = last_type->code2_start = (int)ftell(code_file);
last_type->header1_start = last_type->header2_start = (int)ftell(header_file);
}
last_type->write_code1(*this);
- if (write_sourceview) {
+ if (write_codeview) {
last_type->code1_end = last_type->code2_end = (int)ftell(code_file);
last_type->header1_end = last_type->header2_end = (int)ftell(header_file);
}
@@ -973,7 +973,7 @@ Fd_Code_Writer::Fd_Code_Writer()
block_buffer_(NULL),
block_buffer_size_(0),
indentation(0),
- write_sourceview(false),
+ write_codeview(false),
varused_test(0),
varused(0)
{
diff --git a/fluid/code.h b/fluid/code.h
index bac7bc756..8581c90f8 100644
--- a/fluid/code.h
+++ b/fluid/code.h
@@ -68,7 +68,7 @@ public:
int indentation;
/// set if we write abbreviated file for the source code previewer
/// (disables binary data blocks, for example)
- bool write_sourceview;
+ bool write_codeview;
/// 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:
@@ -100,7 +100,7 @@ public:
void write_hc(const char *, int, const char*, const char*);
void write_c_indented(const char *textlines, int inIndent, char inTrailwWith);
Fl_Type* write_code(Fl_Type* p);
- int write_code(const char *cfile, const char *hfile, bool to_sourceview=false);
+ 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);
diff --git a/fluid/codeview_panel.cxx b/fluid/codeview_panel.cxx
new file mode 100644
index 000000000..0ca8c0d3a
--- /dev/null
+++ b/fluid/codeview_panel.cxx
@@ -0,0 +1,548 @@
+//
+// Code dialogs 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
+//
+
+// generated by Fast Light User Interface Designer (fluid) version 1.0400
+
+#include "codeview_panel.h"
+#include "fluid.h"
+#include "file.h"
+#include "../src/flstring.h"
+#include
+#include
+static char *cv_source_filename = NULL;
+static char *cv_header_filename = NULL;
+static char *cv_design_filename = NULL;
+int cv_code_choice;
+extern void select_only(Fl_Type *o);
+extern void reveal_in_browser(Fl_Type *t);
+
+/**
+ Update the header and source code highlighting depending on the
+ currently selected object
+
+ The Code View system offers an immediate preview of the code
+ files that will be generated by FLUID. It also marks the code
+ generated for the last selected item in the header and the source
+ file.
+*/
+void update_codeview_position() {
+ if (!codeview_panel || !codeview_panel->visible())
+ return;
+ if (cv_autoposition->value()==0)
+ return;
+ if (codeview_panel && codeview_panel->visible() && Fl_Type::current) {
+ int pos0 = 0, pos1 = 0;
+ if (cv_source->visible_r()) {
+ switch (cv_code_choice) {
+ case 0: // prolog: not yet (include statements)
+ pos0 = Fl_Type::current->code1_start;
+ pos1 = Fl_Type::current->code2_end;
+ break;
+ case 1: // static: callbacks, menu declarations
+ pos0 = Fl_Type::current->code_static_start;
+ pos1 = Fl_Type::current->code_static_end;
+ break;
+ case 2: // code: entire implementation block including children
+ pos0 = Fl_Type::current->code1_start;
+ pos1 = Fl_Type::current->code2_end;
+ break;
+ case 3: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->code1_start;
+ pos1 = Fl_Type::current->code1_end;
+ break;
+ case 4: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->code2_start;
+ pos1 = Fl_Type::current->code2_end;
+ break;
+ }
+ if (pos0>=0) {
+ if (pos1buffer()->line_end(pos0);
+ cv_source->buffer()->highlight(pos0, pos1);
+ int line = cv_source->buffer()->count_lines(0, pos0);
+ cv_source->scroll(line, 0);
+ }
+ }
+ if (cv_header->visible_r()) {
+ switch (cv_code_choice) {
+ case 0: // prolog: not yet (include statements)
+ case 1: // static: callbacks, menu declarations
+ pos0 = Fl_Type::current->header_static_start;
+ pos1 = Fl_Type::current->header_static_end;
+ break;
+ case 2: // code: entire implementation block including children
+ pos0 = Fl_Type::current->header1_start;
+ pos1 = Fl_Type::current->header2_end;
+ break;
+ case 3: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->header1_start;
+ pos1 = Fl_Type::current->header1_end;
+ break;
+ case 4: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->header2_start;
+ pos1 = Fl_Type::current->header2_end;
+ break;
+ }
+ if (pos0>=0) {
+ if (pos1buffer()->line_end(pos0);
+ cv_header->buffer()->highlight(pos0, pos1);
+ int line = cv_header->buffer()->count_lines(0, pos0);
+ cv_header->scroll(line, 0);
+ }
+ }
+ if (cv_project->visible_r()) {
+ switch (cv_code_choice) {
+ case 0: // prolog: not yet (include statements)
+ case 1: // static: callbacks, menu declarations
+ case 2: // code: entire implementation block including children
+ pos0 = Fl_Type::current->proj1_start;
+ pos1 = Fl_Type::current->proj2_end;
+ break;
+ case 3: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->proj1_start;
+ pos1 = Fl_Type::current->proj1_end;
+ break;
+ case 4: // code1: all implementation code before the children
+ pos0 = Fl_Type::current->proj2_start;
+ pos1 = Fl_Type::current->proj2_end;
+ break;
+ }
+ if (pos0>=0) {
+ if (pos1buffer()->line_end(pos0);
+ cv_project->buffer()->highlight(pos0, pos1);
+ int line = cv_project->buffer()->count_lines(0, pos0);
+ cv_project->scroll(line, 0);
+ }
+ }
+ }
+}
+
+/**
+ Callback to update the codeview position.
+*/
+void update_codeview_position_cb(class Fl_Tabs*, void*) {
+ // make sure that the selected tab shows the current view
+ update_codeview_cb(0,0);
+ // highlight the selected widget in the selected tab
+ update_codeview_position();
+}
+
+/**
+ Generate a header, source, strings, or design file in a temporary directory
+ and load those into the Code Viewer widgets.
+*/
+void update_codeview_cb(class Fl_Button*, void*) {
+ if (!codeview_panel || !codeview_panel->visible())
+ return;
+
+ if (!cv_source_filename) {
+ cv_source_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX);
+ }
+ if (!cv_header_filename) {
+ cv_header_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX);
+ }
+ if (!cv_design_filename) {
+ cv_design_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX);
+ }
+
+ if (cv_project->visible_r()) {
+ write_file(cv_design_filename, false, true);
+ int top = cv_project->top_line();
+ cv_project->buffer()->loadfile(cv_design_filename);
+ cv_project->scroll(top, 0);
+ } else if (cv_strings->visible_r()) {
+ static const char *exts[] = { ".txt", ".po", ".msg" };
+ char fn[FL_PATH_MAX+1];
+ fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(fn, "strings", FL_PATH_MAX);
+ fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]);
+ write_strings(fn);
+ int top = cv_strings->top_line();
+ cv_strings->buffer()->loadfile(fn);
+ cv_strings->scroll(top, 0);
+ } else if (cv_source->visible_r() || cv_header->visible_r()) {
+ Fl_String code_file_name_bak = g_project.code_file_name;
+ g_project.code_file_name = cv_source_filename;
+ Fl_String header_file_name_bak = g_project.header_file_name;
+ g_project.header_file_name = cv_header_filename;
+
+ // generate the code and load the files
+ Fd_Code_Writer f;
+ // generate files
+ if (f.write_code(cv_source_filename, cv_header_filename, true))
+ {
+ // load file into source editor
+ int pos = cv_source->top_line();
+ cv_source->buffer()->loadfile(cv_source_filename);
+ cv_source->scroll(pos, 0);
+ // load file into header editor
+ pos = cv_header->top_line();
+ cv_header->buffer()->loadfile(cv_header_filename);
+ cv_header->scroll(pos, 0);
+ // update the source code highlighting
+ update_codeview_position();
+ }
+
+ g_project.code_file_name = code_file_name_bak;
+ g_project.header_file_name = header_file_name_bak;
+ }
+}
+
+/**
+ This is called by the timer itself
+*/
+void update_codeview_timer(void*) {
+ update_codeview_cb(0,0);
+}
+
+void codeview_defer_update() {
+ // we will only update earliest 0.5 seconds after the last change, and only
+ // if no other change was made, so dragging a widget will not generate any
+ // CPU load
+ Fl::remove_timeout(update_codeview_timer, 0);
+ Fl::add_timeout(0.5, update_codeview_timer, 0);
+}
+
+/**
+ Show or hide the source code preview.
+ The state is stored in the app preferences.
+*/
+void codeview_toggle_visibility() {
+ if (!codeview_panel) {
+ make_codeview();
+ codeview_panel->callback((Fl_Callback*)toggle_codeview_cb);
+ Fl_Preferences svp(fluid_prefs, "codeview");
+ int autorefresh;
+ svp.get("autorefresh", autorefresh, 1);
+ cv_autorefresh->value(autorefresh);
+ int autoposition;
+ svp.get("autoposition", autoposition, 1);
+ cv_autoposition->value(autoposition);
+ int tab;
+ svp.get("tab", tab, 0);
+ if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab));
+ svp.get("code_choice", cv_code_choice, 2);
+ cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice));
+ if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return;
+ }
+
+ if (codeview_panel->visible()) {
+ codeview_panel->hide();
+ codeview_item->label("Show Code View");
+ } else {
+ codeview_panel->show();
+ codeview_item->label("Hide Code View");
+ update_codeview_cb(0,0);
+ }
+}
+
+Fl_Double_Window *codeview_panel=(Fl_Double_Window *)0;
+
+Fl_Tabs *cv_tab=(Fl_Tabs *)0;
+
+Fl_Group *cv_source_tab=(Fl_Group *)0;
+
+CodeViewer *cv_source=(CodeViewer *)0;
+
+CodeViewer *cv_header=(CodeViewer *)0;
+
+TextViewer *cv_strings=(TextViewer *)0;
+
+TextViewer *cv_project=(TextViewer *)0;
+
+Fl_Group *cv_find_row=(Fl_Group *)0;
+
+Fl_Button *cv_find_text_case=(Fl_Button *)0;
+
+Fl_Input *cv_find_text=(Fl_Input *)0;
+
+static void cb_cv_find_text(Fl_Input* o, void*) {
+ Fl_Text_Display *e = NULL;
+ if (cv_source->visible_r()) {
+ e = cv_source;
+ } else if (cv_header->visible_r()) {
+ e = cv_header;
+ } else if (cv_project->visible_r()) {
+ e = cv_project;
+ }
+ if (e) {
+ Fl_Text_Buffer *b = e->buffer();
+ int pos = e->insert_position();
+ int found = b->search_forward(pos, o->value(), &pos, cv_find_text_case->value());
+ if (found) {
+ b->select(pos, pos + (int)strlen(o->value()));
+ e->insert_position(pos);
+ e->show_insert_position();
+ }
+ }
+}
+
+static void cb_(Fl_Button*, void*) {
+ Fl_Text_Display *e = NULL;
+ if (cv_source->visible_r()) {
+ e = cv_source;
+ } else if (cv_header->visible_r()) {
+ e = cv_header;
+ } else if (cv_project->visible_r()) {
+ e = cv_project;
+ }
+ if (e) {
+ const char *needle = cv_find_text->value();
+ Fl_Text_Buffer *b = e->buffer();
+ int pos = e->insert_position()-1;
+ if (pos < 0) pos = b->length()-1;
+ int found = b->search_backward(pos, needle, &pos, cv_find_text_case->value());
+ if (!found)
+ found = b->search_backward(b->length()-1, needle, &pos, cv_find_text_case->value());
+ if (found) {
+ b->select(pos, pos + (int)strlen(needle));
+ e->insert_position(pos);
+ e->show_insert_position();
+ }
+ }
+}
+
+static void cb_1(Fl_Button*, void*) {
+ Fl_Text_Display *e = NULL;
+ if (cv_source->visible_r()) {
+ e = cv_source;
+ } else if (cv_header->visible_r()) {
+ e = cv_header;
+ } else if (cv_project->visible_r()) {
+ e = cv_project;
+ }
+ if (e) {
+ const char *needle = cv_find_text->value();
+ Fl_Text_Buffer *b = e->buffer();
+ int pos = e->insert_position() + 1;
+ if (pos+1 >= b->length()) pos = 0;
+ int found = b->search_forward(pos, needle, &pos, cv_find_text_case->value());
+ if (!found && (pos > 0))
+ found = b->search_forward(0, needle, &pos, cv_find_text_case->value());
+ if (found) {
+ b->select(pos, pos + (int)strlen(needle));
+ e->insert_position(pos);
+ e->show_insert_position();
+ }
+ }
+}
+
+static void cb_Reveal(Fl_Button*, void*) {
+ if (codeview_panel && codeview_panel->visible()) {
+ Fl_Type *node = NULL;
+ if (cv_source->visible_r())
+ node = Fl_Type::find_in_text(0, cv_source->insert_position());
+ else if (cv_header->visible_r())
+ node = Fl_Type::find_in_text(1, cv_header->insert_position());
+ else if (cv_project->visible_r())
+ node = Fl_Type::find_in_text(2, cv_project->insert_position());
+ if (node) {
+ select_only(node);
+ reveal_in_browser(node);
+ if (Fl::event_clicks()==1) // double click
+ node->open();
+ }
+ }
+}
+
+Fl_Group *cv_settings_row=(Fl_Group *)0;
+
+Fl_Light_Button *cv_autorefresh=(Fl_Light_Button *)0;
+
+Fl_Light_Button *cv_autoposition=(Fl_Light_Button *)0;
+
+Fl_Choice *cv_code_choice_w=(Fl_Choice *)0;
+
+static void cb_cv_code_choice_w(Fl_Choice* o, void*) {
+ cv_code_choice = (int)o->mvalue()->argument();
+ update_codeview_position();
+}
+
+Fl_Menu_Item menu_cv_code_choice_w[] = {
+ {"prolog", 0, 0, (void*)(0), 16, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
+ {"static", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
+ {"code", 0, 0, (void*)(2), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
+ {"code 1", 0, 0, (void*)(3), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
+ {"code 2", 0, 0, (void*)(4), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
+ {0,0,0,0,0,0,0,0,0}
+};
+
+Fl_Double_Window* make_codeview() {
+ { codeview_panel = new Fl_Double_Window(520, 515, "Code View");
+ codeview_panel->callback((Fl_Callback*)toggle_codeview_cb);
+ codeview_panel->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
+ { cv_tab = new Fl_Tabs(10, 10, 500, 440);
+ cv_tab->selection_color((Fl_Color)4);
+ cv_tab->labelcolor(FL_BACKGROUND2_COLOR);
+ cv_tab->callback((Fl_Callback*)update_codeview_position_cb);
+ { cv_source_tab = new Fl_Group(10, 35, 500, 415, "Source");
+ cv_source_tab->labelsize(13);
+ { CodeViewer* o = cv_source = new CodeViewer(10, 40, 500, 410);
+ cv_source->box(FL_DOWN_FRAME);
+ cv_source->color(FL_BACKGROUND2_COLOR);
+ cv_source->selection_color(FL_SELECTION_COLOR);
+ cv_source->labeltype(FL_NORMAL_LABEL);
+ cv_source->labelfont(0);
+ cv_source->labelsize(14);
+ cv_source->labelcolor(FL_FOREGROUND_COLOR);
+ cv_source->textfont(4);
+ cv_source->textsize(11);
+ cv_source->align(Fl_Align(FL_ALIGN_TOP));
+ cv_source->when(FL_WHEN_RELEASE);
+ Fl_Group::current()->resizable(cv_source);
+ o->linenumber_width(60);
+ o->linenumber_size(o->Fl_Text_Display::textsize());
+ } // CodeViewer* cv_source
+ cv_source_tab->end();
+ Fl_Group::current()->resizable(cv_source_tab);
+ } // Fl_Group* cv_source_tab
+ { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Header");
+ o->labelsize(13);
+ o->hide();
+ { CodeViewer* o = cv_header = new CodeViewer(10, 40, 500, 410);
+ cv_header->box(FL_DOWN_FRAME);
+ cv_header->color(FL_BACKGROUND2_COLOR);
+ cv_header->selection_color(FL_SELECTION_COLOR);
+ cv_header->labeltype(FL_NORMAL_LABEL);
+ cv_header->labelfont(0);
+ cv_header->labelsize(14);
+ cv_header->labelcolor(FL_FOREGROUND_COLOR);
+ cv_header->textfont(4);
+ cv_header->textsize(11);
+ cv_header->align(Fl_Align(FL_ALIGN_TOP));
+ cv_header->when(FL_WHEN_RELEASE);
+ Fl_Group::current()->resizable(cv_header);
+ o->linenumber_width(60);
+ o->linenumber_size(o->Fl_Text_Display::textsize());
+ } // CodeViewer* cv_header
+ o->end();
+ } // Fl_Group* o
+ { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Strings");
+ o->labelsize(13);
+ o->hide();
+ { TextViewer* o = cv_strings = new TextViewer(10, 40, 500, 410);
+ cv_strings->box(FL_DOWN_FRAME);
+ cv_strings->color(FL_BACKGROUND2_COLOR);
+ cv_strings->selection_color(FL_SELECTION_COLOR);
+ cv_strings->labeltype(FL_NORMAL_LABEL);
+ cv_strings->labelfont(0);
+ cv_strings->labelsize(14);
+ cv_strings->labelcolor(FL_FOREGROUND_COLOR);
+ cv_strings->textfont(4);
+ cv_strings->textsize(11);
+ cv_strings->align(Fl_Align(FL_ALIGN_TOP));
+ cv_strings->when(FL_WHEN_RELEASE);
+ Fl_Group::current()->resizable(cv_strings);
+ o->linenumber_width(60);
+ o->linenumber_size(o->Fl_Text_Display::textsize());
+ } // TextViewer* cv_strings
+ o->end();
+ } // Fl_Group* o
+ { Fl_Group* o = new Fl_Group(10, 35, 500, 415, "Project");
+ o->labelsize(13);
+ o->hide();
+ { TextViewer* o = cv_project = new TextViewer(10, 40, 500, 410);
+ cv_project->box(FL_DOWN_FRAME);
+ cv_project->color(FL_BACKGROUND2_COLOR);
+ cv_project->selection_color(FL_SELECTION_COLOR);
+ cv_project->labeltype(FL_NORMAL_LABEL);
+ cv_project->labelfont(0);
+ cv_project->labelsize(14);
+ cv_project->labelcolor(FL_FOREGROUND_COLOR);
+ cv_project->textfont(4);
+ cv_project->textsize(11);
+ cv_project->align(Fl_Align(FL_ALIGN_TOP));
+ cv_project->when(FL_WHEN_RELEASE);
+ Fl_Group::current()->resizable(cv_project);
+ o->linenumber_width(60);
+ o->linenumber_size(o->Fl_Text_Display::textsize());
+ } // TextViewer* cv_project
+ o->end();
+ } // Fl_Group* o
+ cv_tab->end();
+ Fl_Group::current()->resizable(cv_tab);
+ } // Fl_Tabs* cv_tab
+ { cv_find_row = new Fl_Group(10, 460, 500, 20);
+ { cv_find_text_case = new Fl_Button(244, 460, 25, 20, "aA");
+ cv_find_text_case->type(1);
+ cv_find_text_case->labelsize(11);
+ } // Fl_Button* cv_find_text_case
+ { cv_find_text = new Fl_Input(40, 460, 200, 20, "Find:");
+ cv_find_text->labelsize(11);
+ cv_find_text->textsize(11);
+ cv_find_text->callback((Fl_Callback*)cb_cv_find_text);
+ cv_find_text->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY_CHANGED);
+ } // Fl_Input* cv_find_text
+ { Fl_Button* o = new Fl_Button(273, 460, 25, 20, "<<");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)cb_);
+ } // Fl_Button* o
+ { Fl_Button* o = new Fl_Button(298, 460, 25, 20, ">>");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)cb_1);
+ } // Fl_Button* o
+ { Fl_Button* o = new Fl_Button(327, 460, 61, 20, "Reveal");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)cb_Reveal);
+ } // Fl_Button* o
+ { Fl_Box* o = new Fl_Box(490, 460, 20, 20);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ cv_find_row->end();
+ } // Fl_Group* cv_find_row
+ { cv_settings_row = new Fl_Group(10, 485, 500, 20);
+ { Fl_Button* o = new Fl_Button(10, 485, 61, 20, "Refresh");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)update_codeview_cb);
+ } // Fl_Button* o
+ { Fl_Light_Button* o = cv_autorefresh = new Fl_Light_Button(77, 485, 91, 20, "Auto-Refresh");
+ cv_autorefresh->labelsize(11);
+ o->callback((Fl_Callback*)update_codeview_cb);
+ } // Fl_Light_Button* cv_autorefresh
+ { cv_autoposition = new Fl_Light_Button(172, 485, 89, 20, "Auto-Position");
+ cv_autoposition->labelsize(11);
+ } // Fl_Light_Button* cv_autoposition
+ { cv_code_choice_w = new Fl_Choice(265, 485, 70, 20);
+ cv_code_choice_w->down_box(FL_BORDER_BOX);
+ cv_code_choice_w->labelsize(11);
+ cv_code_choice_w->textsize(11);
+ cv_code_choice_w->callback((Fl_Callback*)cb_cv_code_choice_w);
+ cv_code_choice_w->menu(menu_cv_code_choice_w);
+ } // Fl_Choice* cv_code_choice_w
+ { Fl_Box* o = new Fl_Box(375, 485, 80, 20);
+ Fl_Group::current()->resizable(o);
+ } // Fl_Box* o
+ { Fl_Button* o = new Fl_Button(460, 485, 50, 20, "Close");
+ o->labelsize(11);
+ o->callback((Fl_Callback*)toggle_codeview_b_cb);
+ } // Fl_Button* o
+ cv_settings_row->end();
+ } // Fl_Group* cv_settings_row
+ codeview_panel->size_range(384, 120);
+ codeview_panel->end();
+ } // Fl_Double_Window* codeview_panel
+ return codeview_panel;
+}
+
+//
diff --git a/fluid/sourceview_panel.fl b/fluid/codeview_panel.fl
similarity index 61%
rename from fluid/sourceview_panel.fl
rename to fluid/codeview_panel.fl
index 2159a065a..51ac5f4ab 100644
--- a/fluid/sourceview_panel.fl
+++ b/fluid/codeview_panel.fl
@@ -26,7 +26,7 @@ decl {\#include "fluid.h"} {private local
decl {\#include "file.h"} {private local
}
-decl {\#include "../src/flstring.h"} {private local
+decl {\#include "../src/flstring.h"} {selected private local
}
decl {\#include } {private local
@@ -35,16 +35,16 @@ decl {\#include } {private local
decl {\#include } {private local
}
-decl {char *sv_source_filename = NULL;} {private local
+decl {char *cv_source_filename = NULL;} {private local
}
-decl {char *sv_header_filename = NULL;} {private local
+decl {char *cv_header_filename = NULL;} {private local
}
-decl {char *sv_design_filename = NULL;} {private local
+decl {char *cv_design_filename = NULL;} {private local
}
-decl {int sv_code_choice;} {public local
+decl {int cv_code_choice;} {public local
}
decl {extern void select_only(Fl_Type *o);} {private global
@@ -53,23 +53,23 @@ decl {extern void select_only(Fl_Type *o);} {private global
decl {extern void reveal_in_browser(Fl_Type *t);} {private global
}
-Function {update_sourceview_position()} {
+Function {update_codeview_position()} {
comment {Update the header and source code highlighting depending on the
currently selected object
-The Source View system offers an immediate preview of the code
+The Code View system offers an immediate preview of the code
files that will be generated by FLUID. It also marks the code
generated for the last selected item in the header and the source
file.} open return_type void
} {
- code {if (!sourceview_panel || !sourceview_panel->visible())
+ code {if (!codeview_panel || !codeview_panel->visible())
return;
- if (sv_autoposition->value()==0)
+ if (cv_autoposition->value()==0)
return;
- if (sourceview_panel && sourceview_panel->visible() && Fl_Type::current) {
+ if (codeview_panel && codeview_panel->visible() && Fl_Type::current) {
int pos0 = 0, pos1 = 0;
- if (sv_source->visible_r()) {
- switch (sv_code_choice) {
+ if (cv_source->visible_r()) {
+ switch (cv_code_choice) {
case 0: // prolog: not yet (include statements)
pos0 = Fl_Type::current->code1_start;
pos1 = Fl_Type::current->code2_end;
@@ -93,14 +93,14 @@ file.} open return_type void
}
if (pos0>=0) {
if (pos1buffer()->line_end(pos0);
- sv_source->buffer()->highlight(pos0, pos1);
- int line = sv_source->buffer()->count_lines(0, pos0);
- sv_source->scroll(line, 0);
+ pos1 = cv_source->buffer()->line_end(pos0);
+ cv_source->buffer()->highlight(pos0, pos1);
+ int line = cv_source->buffer()->count_lines(0, pos0);
+ cv_source->scroll(line, 0);
}
}
- if (sv_header->visible_r()) {
- switch (sv_code_choice) {
+ if (cv_header->visible_r()) {
+ switch (cv_code_choice) {
case 0: // prolog: not yet (include statements)
case 1: // static: callbacks, menu declarations
pos0 = Fl_Type::current->header_static_start;
@@ -121,14 +121,14 @@ file.} open return_type void
}
if (pos0>=0) {
if (pos1buffer()->line_end(pos0);
- sv_header->buffer()->highlight(pos0, pos1);
- int line = sv_header->buffer()->count_lines(0, pos0);
- sv_header->scroll(line, 0);
+ pos1 = cv_header->buffer()->line_end(pos0);
+ cv_header->buffer()->highlight(pos0, pos1);
+ int line = cv_header->buffer()->count_lines(0, pos0);
+ cv_header->scroll(line, 0);
}
}
- if (sv_project->visible_r()) {
- switch (sv_code_choice) {
+ if (cv_project->visible_r()) {
+ switch (cv_code_choice) {
case 0: // prolog: not yet (include statements)
case 1: // static: callbacks, menu declarations
case 2: // code: entire implementation block including children
@@ -146,83 +146,83 @@ file.} open return_type void
}
if (pos0>=0) {
if (pos1buffer()->line_end(pos0);
- sv_project->buffer()->highlight(pos0, pos1);
- int line = sv_project->buffer()->count_lines(0, pos0);
- sv_project->scroll(line, 0);
+ pos1 = cv_project->buffer()->line_end(pos0);
+ cv_project->buffer()->highlight(pos0, pos1);
+ int line = cv_project->buffer()->count_lines(0, pos0);
+ cv_project->scroll(line, 0);
}
}
}} {}
}
-Function {update_sourceview_position_cb(class Fl_Tabs*, void*)} {
- comment {Callback to update the sourceview position.} open return_type void
+Function {update_codeview_position_cb(class Fl_Tabs*, void*)} {
+ comment {Callback to update the codeview position.} open return_type void
} {
code {// make sure that the selected tab shows the current view
- update_sourceview_cb(0,0);
+ update_codeview_cb(0,0);
// highlight the selected widget in the selected tab
- update_sourceview_position();} {}
+ update_codeview_position();} {}
}
-Function {update_sourceview_cb(class Fl_Button*, void*)} {
+Function {update_codeview_cb(class Fl_Button*, void*)} {
comment {Generate a header, source, strings, or design file in a temporary directory
and load those into the Code Viewer widgets.} open return_type void
} {
- code {if (!sourceview_panel || !sourceview_panel->visible())
+ code {if (!codeview_panel || !codeview_panel->visible())
return;
- if (!sv_source_filename) {
- sv_source_filename = (char*)malloc(FL_PATH_MAX);
- fl_strlcpy(sv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX);
- fl_strlcat(sv_source_filename, "source_view_tmp.cxx", FL_PATH_MAX);
+ if (!cv_source_filename) {
+ cv_source_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_source_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_source_filename, "codeview_tmp.cxx", FL_PATH_MAX);
}
- if (!sv_header_filename) {
- sv_header_filename = (char*)malloc(FL_PATH_MAX);
- fl_strlcpy(sv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX);
- fl_strlcat(sv_header_filename, "source_view_tmp.h", FL_PATH_MAX);
+ if (!cv_header_filename) {
+ cv_header_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_header_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_header_filename, "codeview_tmp.h", FL_PATH_MAX);
}
- if (!sv_design_filename) {
- sv_design_filename = (char*)malloc(FL_PATH_MAX);
- fl_strlcpy(sv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX);
- fl_strlcat(sv_design_filename, "source_view_tmp.fl", FL_PATH_MAX);
+ if (!cv_design_filename) {
+ cv_design_filename = (char*)malloc(FL_PATH_MAX);
+ fl_strlcpy(cv_design_filename, get_tmpdir().c_str(), FL_PATH_MAX);
+ fl_strlcat(cv_design_filename, "codeview_tmp.fl", FL_PATH_MAX);
}
- if (sv_project->visible_r()) {
- write_file(sv_design_filename, false, true);
- int top = sv_project->top_line();
- sv_project->buffer()->loadfile(sv_design_filename);
- sv_project->scroll(top, 0);
- } else if (sv_strings->visible_r()) {
+ if (cv_project->visible_r()) {
+ write_file(cv_design_filename, false, true);
+ int top = cv_project->top_line();
+ cv_project->buffer()->loadfile(cv_design_filename);
+ cv_project->scroll(top, 0);
+ } else if (cv_strings->visible_r()) {
static const char *exts[] = { ".txt", ".po", ".msg" };
char fn[FL_PATH_MAX+1];
fl_strlcpy(fn, get_tmpdir().c_str(), FL_PATH_MAX);
fl_strlcat(fn, "strings", FL_PATH_MAX);
fl_filename_setext(fn, FL_PATH_MAX, exts[g_project.i18n_type]);
write_strings(fn);
- int top = sv_strings->top_line();
- sv_strings->buffer()->loadfile(fn);
- sv_strings->scroll(top, 0);
- } else if (sv_source->visible_r() || sv_header->visible_r()) {
+ int top = cv_strings->top_line();
+ cv_strings->buffer()->loadfile(fn);
+ cv_strings->scroll(top, 0);
+ } else if (cv_source->visible_r() || cv_header->visible_r()) {
Fl_String code_file_name_bak = g_project.code_file_name;
- g_project.code_file_name = sv_source_filename;
+ g_project.code_file_name = cv_source_filename;
Fl_String header_file_name_bak = g_project.header_file_name;
- g_project.header_file_name = sv_header_filename;
+ g_project.header_file_name = cv_header_filename;
// generate the code and load the files
Fd_Code_Writer f;
// generate files
- if (f.write_code(sv_source_filename, sv_header_filename, true))
+ if (f.write_code(cv_source_filename, cv_header_filename, true))
{
// load file into source editor
- int pos = sv_source->top_line();
- sv_source->buffer()->loadfile(sv_source_filename);
- sv_source->scroll(pos, 0);
+ int pos = cv_source->top_line();
+ cv_source->buffer()->loadfile(cv_source_filename);
+ cv_source->scroll(pos, 0);
// load file into header editor
- pos = sv_header->top_line();
- sv_header->buffer()->loadfile(sv_header_filename);
- sv_header->scroll(pos, 0);
+ pos = cv_header->top_line();
+ cv_header->buffer()->loadfile(cv_header_filename);
+ cv_header->scroll(pos, 0);
// update the source code highlighting
- update_sourceview_position();
+ update_codeview_position();
}
g_project.code_file_name = code_file_name_bak;
@@ -230,71 +230,71 @@ and load those into the Code Viewer widgets.} open return_type void
}} {}
}
-Function {update_sourceview_timer(void*)} {
+Function {update_codeview_timer(void*)} {
comment {This is called by the timer itself
} open return_type void
} {
- code {update_sourceview_cb(0,0);} {}
+ code {update_codeview_cb(0,0);} {}
}
-Function {sourceview_defer_update()} {open return_type void
+Function {codeview_defer_update()} {open return_type void
} {
code {// we will only update earliest 0.5 seconds after the last change, and only
// if no other change was made, so dragging a widget will not generate any
// CPU load
- Fl::remove_timeout(update_sourceview_timer, 0);
- Fl::add_timeout(0.5, update_sourceview_timer, 0);} {}
+ Fl::remove_timeout(update_codeview_timer, 0);
+ Fl::add_timeout(0.5, update_codeview_timer, 0);} {}
}
-Function {sourceview_toggle_visibility()} {
+Function {codeview_toggle_visibility()} {
comment {Show or hide the source code preview.
The state is stored in the app preferences.
} open return_type void
} {
- code {if (!sourceview_panel) {
- make_sourceview();
- sourceview_panel->callback((Fl_Callback*)toggle_sourceview_cb);
- Fl_Preferences svp(fluid_prefs, "sourceview");
+ code {if (!codeview_panel) {
+ make_codeview();
+ codeview_panel->callback((Fl_Callback*)toggle_codeview_cb);
+ Fl_Preferences svp(fluid_prefs, "codeview");
int autorefresh;
svp.get("autorefresh", autorefresh, 1);
- sv_autorefresh->value(autorefresh);
+ cv_autorefresh->value(autorefresh);
int autoposition;
svp.get("autoposition", autoposition, 1);
- sv_autoposition->value(autoposition);
+ cv_autoposition->value(autoposition);
int tab;
svp.get("tab", tab, 0);
- if (tab>=0 && tabchildren()) sv_tab->value(sv_tab->child(tab));
- svp.get("code_choice", sv_code_choice, 2);
- sv_code_choice_w->value(sv_code_choice_w->find_item_with_argument(sv_code_choice));
- if (!position_window(sourceview_panel,"sourceview_pos", 0, 320, 120, 550, 500)) return;
+ if (tab>=0 && tabchildren()) cv_tab->value(cv_tab->child(tab));
+ svp.get("code_choice", cv_code_choice, 2);
+ cv_code_choice_w->value(cv_code_choice_w->find_item_with_argument(cv_code_choice));
+ if (!position_window(codeview_panel,"codeview_pos", 0, 320, 120, 550, 500)) return;
}
- if (sourceview_panel->visible()) {
- sourceview_panel->hide();
- sourceview_item->label("Show Source Code...");
+ if (codeview_panel->visible()) {
+ codeview_panel->hide();
+ codeview_item->label("Show Code View");
} else {
- sourceview_panel->show();
- sourceview_item->label("Hide Source Code...");
- update_sourceview_cb(0,0);
+ codeview_panel->show();
+ codeview_item->label("Hide Code View");
+ update_codeview_cb(0,0);
}} {}
}
-Function {make_sourceview()} {open
+Function {make_codeview()} {open
} {
- Fl_Window sourceview_panel {
+ Fl_Window codeview_panel {
label {Code View}
- callback toggle_sourceview_cb open
+ callback toggle_codeview_cb open
xywh {389 507 520 515} type Double align 80 resizable size_range {384 120 0 0} visible
} {
- Fl_Tabs sv_tab {
- callback update_sourceview_position_cb open
+ Fl_Tabs cv_tab {
+ callback update_codeview_position_cb open
xywh {10 10 500 440} selection_color 4 labelcolor 7 resizable
} {
- Fl_Group {} {
+ Fl_Group cv_source_tab {
label Source open
xywh {10 35 500 415} labelsize 13 resizable
} {
- Fl_Text_Editor sv_source {
+ Fl_Text_Editor cv_source {
xywh {10 40 500 410} textfont 4 textsize 11 resizable
code0 {\#include "CodeEditor.h"}
code1 {o->linenumber_width(60);}
@@ -306,7 +306,7 @@ Function {make_sourceview()} {open
label Header open
xywh {10 35 500 415} labelsize 13 hide
} {
- Fl_Text_Editor sv_header {
+ Fl_Text_Editor cv_header {
xywh {10 40 500 410} textfont 4 textsize 11 resizable
code0 {\#include "CodeEditor.h"}
code1 {o->linenumber_width(60);}
@@ -318,7 +318,7 @@ Function {make_sourceview()} {open
label Strings open
xywh {10 35 500 415} labelsize 13 hide
} {
- Fl_Text_Display sv_strings {
+ Fl_Text_Display cv_strings {
xywh {10 40 500 410} textfont 4 textsize 11 resizable
code1 {o->linenumber_width(60);}
code2 {o->linenumber_size(o->Fl_Text_Display::textsize());}
@@ -329,7 +329,7 @@ Function {make_sourceview()} {open
label Project open
xywh {10 35 500 415} labelsize 13 hide
} {
- Fl_Text_Display sv_project {
+ Fl_Text_Display cv_project {
xywh {10 40 500 410} textfont 4 textsize 11 resizable
code1 {o->linenumber_width(60);}
code2 {o->linenumber_size(o->Fl_Text_Display::textsize());}
@@ -337,27 +337,27 @@ Function {make_sourceview()} {open
}
}
}
- Fl_Group {} {open
+ Fl_Group cv_find_row {open
xywh {10 460 500 20}
} {
- Fl_Button sv_find_text_case {
+ Fl_Button cv_find_text_case {
label aA
xywh {244 460 25 20} type Toggle labelsize 11
}
- Fl_Input sv_find_text {
+ Fl_Input cv_find_text {
label {Find:}
callback {Fl_Text_Display *e = NULL;
-if (sv_source->visible_r()) {
- e = sv_source;
-} else if (sv_header->visible_r()) {
- e = sv_header;
-} else if (sv_project->visible_r()) {
- e = sv_project;
+if (cv_source->visible_r()) {
+ e = cv_source;
+} else if (cv_header->visible_r()) {
+ e = cv_header;
+} else if (cv_project->visible_r()) {
+ e = cv_project;
}
if (e) {
Fl_Text_Buffer *b = e->buffer();
int pos = e->insert_position();
- int found = b->search_forward(pos, o->value(), &pos, sv_find_text_case->value());
+ int found = b->search_forward(pos, o->value(), &pos, cv_find_text_case->value());
if (found) {
b->select(pos, pos + (int)strlen(o->value()));
e->insert_position(pos);
@@ -369,47 +369,47 @@ if (e) {
Fl_Button {} {
label {<<}
callback {Fl_Text_Display *e = NULL;
-if (sv_source->visible_r()) {
- e = sv_source;
-} else if (sv_header->visible_r()) {
- e = sv_header;
-} else if (sv_project->visible_r()) {
- e = sv_project;
+if (cv_source->visible_r()) {
+ e = cv_source;
+} else if (cv_header->visible_r()) {
+ e = cv_header;
+} else if (cv_project->visible_r()) {
+ e = cv_project;
}
if (e) {
- const char *needle = sv_find_text->value();
+ const char *needle = cv_find_text->value();
Fl_Text_Buffer *b = e->buffer();
int pos = e->insert_position()-1;
if (pos < 0) pos = b->length()-1;
- int found = b->search_backward(pos, needle, &pos, sv_find_text_case->value());
+ int found = b->search_backward(pos, needle, &pos, cv_find_text_case->value());
if (!found)
- found = b->search_backward(b->length()-1, needle, &pos, sv_find_text_case->value());
+ found = b->search_backward(b->length()-1, needle, &pos, cv_find_text_case->value());
if (found) {
b->select(pos, pos + (int)strlen(needle));
e->insert_position(pos);
e->show_insert_position();
}
-}} selected
+}}
xywh {273 460 25 20} labelsize 11
}
Fl_Button {} {
label {>>}
callback {Fl_Text_Display *e = NULL;
-if (sv_source->visible_r()) {
- e = sv_source;
-} else if (sv_header->visible_r()) {
- e = sv_header;
-} else if (sv_project->visible_r()) {
- e = sv_project;
+if (cv_source->visible_r()) {
+ e = cv_source;
+} else if (cv_header->visible_r()) {
+ e = cv_header;
+} else if (cv_project->visible_r()) {
+ e = cv_project;
}
if (e) {
- const char *needle = sv_find_text->value();
+ const char *needle = cv_find_text->value();
Fl_Text_Buffer *b = e->buffer();
int pos = e->insert_position() + 1;
if (pos+1 >= b->length()) pos = 0;
- int found = b->search_forward(pos, needle, &pos, sv_find_text_case->value());
+ int found = b->search_forward(pos, needle, &pos, cv_find_text_case->value());
if (!found && (pos > 0))
- found = b->search_forward(0, needle, &pos, sv_find_text_case->value());
+ found = b->search_forward(0, needle, &pos, cv_find_text_case->value());
if (found) {
b->select(pos, pos + (int)strlen(needle));
e->insert_position(pos);
@@ -420,14 +420,14 @@ if (e) {
}
Fl_Button {} {
label Reveal
- callback {if (sourceview_panel && sourceview_panel->visible()) {
+ callback {if (codeview_panel && codeview_panel->visible()) {
Fl_Type *node = NULL;
- if (sv_source->visible_r())
- node = Fl_Type::find_in_text(0, sv_source->insert_position());
- else if (sv_header->visible_r())
- node = Fl_Type::find_in_text(1, sv_header->insert_position());
- else if (sv_project->visible_r())
- node = Fl_Type::find_in_text(2, sv_project->insert_position());
+ if (cv_source->visible_r())
+ node = Fl_Type::find_in_text(0, cv_source->insert_position());
+ else if (cv_header->visible_r())
+ node = Fl_Type::find_in_text(1, cv_header->insert_position());
+ else if (cv_project->visible_r())
+ node = Fl_Type::find_in_text(2, cv_project->insert_position());
if (node) {
select_only(node);
reveal_in_browser(node);
@@ -441,26 +441,26 @@ if (e) {
xywh {490 460 20 20} resizable
}
}
- Fl_Group {} {open
+ Fl_Group cv_settings_row {open
xywh {10 485 500 20}
} {
Fl_Button {} {
label Refresh
- callback update_sourceview_cb
+ callback update_codeview_cb
xywh {10 485 61 20} labelsize 11
}
- Fl_Light_Button sv_autorefresh {
+ Fl_Light_Button cv_autorefresh {
label {Auto-Refresh}
xywh {77 485 91 20} labelsize 11
- code0 {o->callback((Fl_Callback*)update_sourceview_cb);}
+ code0 {o->callback((Fl_Callback*)update_codeview_cb);}
}
- Fl_Light_Button sv_autoposition {
+ Fl_Light_Button cv_autoposition {
label {Auto-Position}
xywh {172 485 89 20} labelsize 11
}
- Fl_Choice sv_code_choice_w {
- callback {sv_code_choice = (int)o->mvalue()->argument();
-update_sourceview_position();} open
+ Fl_Choice cv_code_choice_w {
+ callback {cv_code_choice = (int)o->mvalue()->argument();
+update_codeview_position();} open
xywh {265 485 70 20} down_box BORDER_BOX labelsize 11 textsize 11
} {
MenuItem {} {
@@ -494,7 +494,7 @@ update_sourceview_position();} open
}
Fl_Button {} {
label Close
- callback toggle_sourceview_b_cb
+ callback toggle_codeview_b_cb
xywh {460 485 50 20} labelsize 11
}
}
diff --git a/fluid/codeview_panel.h b/fluid/codeview_panel.h
new file mode 100644
index 000000000..8fa566346
--- /dev/null
+++ b/fluid/codeview_panel.h
@@ -0,0 +1,58 @@
+//
+// Code dialogs 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
+//
+
+// generated by Fast Light User Interface Designer (fluid) version 1.0400
+
+#ifndef codeview_panel_h
+#define codeview_panel_h
+#include
+extern int cv_code_choice;
+void update_codeview_position();
+void update_codeview_position_cb(class Fl_Tabs*, void*);
+void update_codeview_cb(class Fl_Button*, void*);
+void update_codeview_timer(void*);
+void codeview_defer_update();
+void codeview_toggle_visibility();
+#include
+extern void toggle_codeview_cb(Fl_Double_Window*, void*);
+extern Fl_Double_Window *codeview_panel;
+#include
+extern Fl_Tabs *cv_tab;
+#include
+extern Fl_Group *cv_source_tab;
+#include "CodeEditor.h"
+extern CodeViewer *cv_source;
+extern CodeViewer *cv_header;
+extern TextViewer *cv_strings;
+extern TextViewer *cv_project;
+extern Fl_Group *cv_find_row;
+#include
+extern Fl_Button *cv_find_text_case;
+#include
+extern Fl_Input *cv_find_text;
+#include
+extern Fl_Group *cv_settings_row;
+#include
+extern Fl_Light_Button *cv_autorefresh;
+extern Fl_Light_Button *cv_autoposition;
+#include
+extern Fl_Choice *cv_code_choice_w;
+extern void toggle_codeview_b_cb(Fl_Button*, void*);
+Fl_Double_Window* make_codeview();
+extern Fl_Menu_Item menu_cv_code_choice_w[];
+#endif
+
+//
diff --git a/fluid/custom_widgets.cxx b/fluid/custom_widgets.cxx
index 99cfbbbdf..887e2ba14 100644
--- a/fluid/custom_widgets.cxx
+++ b/fluid/custom_widgets.cxx
@@ -55,7 +55,7 @@ int Widget_Bin_Button::handle(int inEvent)
// fake a drag outside of the widget
Fl::e_x = x()-1;
Fl_Button::handle(inEvent);
- // fake a buttton release
+ // fake a button release
Fl_Button::handle(FL_RELEASE);
// make it into a dnd event
const char *type_name = (const char*)user_data();
diff --git a/fluid/documentation/CMakeLists.txt b/fluid/documentation/CMakeLists.txt
new file mode 100644
index 000000000..fb2fac442
--- /dev/null
+++ b/fluid/documentation/CMakeLists.txt
@@ -0,0 +1,232 @@
+#
+# CMakeLists.txt to build docs for the FLTK project using CMake (www.cmake.org)
+#
+# Copyright 1998-2024 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
+#
+
+set(DOCS)
+set(GIT_REVISION "")
+set(YEAR "")
+set(CURRENT_DATE "")
+
+#------------------------------------------------
+# generate files used for both HTML and PDF docs
+#------------------------------------------------
+
+if(FLTK_BUILD_FLUID_DOCS OR FLTK_BUILD_PDF_DOCS)
+
+ # create required variables
+
+ execute_process(COMMAND date "+%Y"
+ OUTPUT_VARIABLE YEAR
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # note: current locale is used for abbreviated month
+ execute_process(COMMAND date "+%b %d, %Y"
+ OUTPUT_VARIABLE CURRENT_DATE
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+
+ # find git revision
+
+ # FIXME: This must also work with tarballs where git is not available.
+ # For now we just ignore errors and set GIT_REVISION = "unknown".
+ # In the future tarball/zip generation should create a file
+ # that contains the git revision.
+
+ execute_process(COMMAND
+ git rev-parse --short=10 HEAD
+ OUTPUT_VARIABLE GIT_REVISION
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ WORKING_DIRECTORY ${FLTK_SOURCE_DIR}
+ ERROR_QUIET
+ )
+
+ # set to "'unknown'" if git is not available
+ if(GIT_REVISION STREQUAL "")
+ set(GIT_REVISION "'unknown'")
+ endif()
+
+ # Find "short" doxygen version if it was built from Git
+ # Note: this is still needed in CMake 3.12.0 but later CMake versions
+ # (notably 3.25) remove the Git revision in 'DOXYGEN_VERSION'.
+ # Todo: Find the "first good" CMake version and remove this redundant
+ # code once we require this as our minimal version and replace the
+ # variable DOXYGEN_VERSION_SHORT with DOXYGEN_VERSION below.
+
+ if(DOXYGEN_FOUND)
+ # strip trailing git revision if doxygen was built from source
+ string(REGEX REPLACE " .*$" "" DOXYGEN_VERSION_SHORT ${DOXYGEN_VERSION})
+ endif(DOXYGEN_FOUND)
+
+ # configure copyright.dox (includes current year)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/copyright.dox.in
+ ${CMAKE_CURRENT_BINARY_DIR}/copyright.dox
+ @ONLY
+ )
+
+ # configure generated.dox (includes date and versions)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/generated.dox.in
+ ${CMAKE_CURRENT_BINARY_DIR}/generated.dox
+ @ONLY
+ )
+
+endif(FLTK_BUILD_FLUID_DOCS OR FLTK_BUILD_PDF_DOCS)
+
+#-------------------------------
+# build FLUID html documentation
+#-------------------------------
+
+if(FLTK_BUILD_FLUID_DOCS)
+
+ #list(APPEND DOCS html)
+
+ # generate Doxygen file "Doxyfile"
+
+ set(GENERATE_FLUID_HTML YES)
+ set(GENERATE_LATEX NO)
+ set(LATEX_HEADER "")
+ set(FL_HTML_INDEX "FL_HTML_INDEX")
+ set(DOXYFILE "Doxyfile")
+ set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}_error.log")
+
+ # configure Doxygen input file for HTML docs (Doxyfile.in)
+
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}.in
+ @ONLY
+ )
+
+ # convert Doxyfile to used doxygen version
+
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/convert_doxyfile
+ ${DOXYGEN_EXECUTABLE}
+ ${DOXYFILE}.in
+ ${DOXYFILE}
+ ${LOGFILE}
+ BYPRODUCTS ${LOGFILE}
+ COMMENT "Converting ${DOXYFILE} to doxygen version ${DOXYGEN_VERSION_SHORT}" VERBATIM
+ )
+
+ # generate screen shot using FLUID --autodoc target_dir
+ # generate HTML documentation
+
+ add_custom_target(fluid_docs
+ COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/src/
+ COMMAND fltk::fluid -scheme gtk+ --autodoc ${CMAKE_CURRENT_BINARY_DIR}/src/
+ COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating HTML documentation" VERBATIM
+ )
+ add_dependencies(fluid_docs fltk::fluid)
+
+endif(FLTK_BUILD_FLUID_DOCS)
+
+#--------------------------
+# build pdf documentation
+#--------------------------
+
+if(FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS)
+
+ # generate Doxygen input file "Doxybook"
+
+ set(GENERATE_FLUID_HTML NO)
+ set(GENERATE_LATEX YES)
+ set(LATEX_HEADER "${CMAKE_CURRENT_BINARY_DIR}/fluid-book.tex")
+ set(FL_HTML_INDEX "FL_NO_HTML_INDEX")
+ set(DOXYFILE "Doxybook")
+ set(LOGFILE "${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}_error.log")
+
+ # configure Doxygen input file for PDF docs (Doxybook.in)
+
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}.in
+ @ONLY
+ )
+
+ # convert Doxybook to current doxygen version
+
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/convert_doxyfile
+ ${DOXYGEN_EXECUTABLE}
+ ${DOXYFILE}.in
+ ${DOXYFILE}
+ ${LOGFILE}
+ BYPRODUCTS ${LOGFILE}
+ COMMENT "Converting ${DOXYFILE} to doxygen version ${DOXYGEN_VERSION_SHORT}" VERBATIM
+ )
+
+ # generate LaTeX title fluid-title.tex
+
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/fluid-title.tex.in
+ ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex
+ @ONLY
+ )
+
+ # generate fluid.pdf
+
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make_header
+ ${DOXYGEN_EXECUTABLE}
+ ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex
+ ${CMAKE_CURRENT_BINARY_DIR}/fluid-book.tex
+ COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE}
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/make_pdf
+ COMMAND cp -f latex/refman.pdf fluid.pdf
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${DOXYFILE}
+ ${CMAKE_CURRENT_BINARY_DIR}/fluid-title.tex
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Generating FLUID PDF documentation" VERBATIM
+ )
+
+ # add target 'pdf'
+
+ add_custom_target(fluid_pdf
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf
+ )
+ add_dependencies(fluid_pdf fluid_docs)
+
+endif(FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS)
+
+#---------------------------------------
+# install FLUID html + pdf documentation
+#---------------------------------------
+
+if(FLTK_INSTALL_FLUID_DOCS AND FLTK_BUILD_FLUID_DOCS)
+
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
+ DESTINATION ${FLTK_DATADIR}/doc/fltk/fluid
+ )
+
+endif(FLTK_INSTALL_FLUID_DOCS AND FLTK_BUILD_FLUID_DOCS)
+
+if(FLTK_INSTALL_PDF_DOCS AND FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS)
+
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/fluid.pdf
+ DESTINATION ${FLTK_DATADIR}/doc/fltk/
+ )
+
+endif(FLTK_INSTALL_PDF_DOCS AND FLTK_BUILD_PDF_DOCS AND FLTK_BUILD_FLUID_DOCS)
diff --git a/fluid/documentation/Doxyfile.in b/fluid/documentation/Doxyfile.in
new file mode 100644
index 000000000..f625dd52a
--- /dev/null
+++ b/fluid/documentation/Doxyfile.in
@@ -0,0 +1,2485 @@
+# Doxyfile 1.8.14
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "FLUID for FLTK @FLTK_VERSION@"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = .
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 0.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 0
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if ... \endif and \cond
+# ... \endcond blocks.
+
+ENABLED_SECTIONS = @FL_HTML_INDEX@
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = @CMAKE_CURRENT_SOURCE_DIR@/src/index.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_introduction.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_commandline.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_interactive.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_main_window.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_widgetbin_panel.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_edit_window.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_functional_nodes.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_widget_panel.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_setting_dialog.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_codeview_panel.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_tutorial.dox \
+ @CMAKE_CURRENT_SOURCE_DIR@/src/page_appendices.dox
+
+# @FLTK_SOURCE_DIR@/fluid
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
+
+FILE_PATTERNS = *.H \
+ *.h \
+ *.c \
+ *.cxx \
+ *.dox
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+# @FLTK_SOURCE_DIR@/src/drivers/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+# */src/*_win32.cxx \
+# */src/*_mac.cxx \
+# */src/*_x.cxx \
+# */src/xdg* \
+# */src/text-input*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+# @CMAKE_CURRENT_SOURCE_DIR@/../test \
+# @CMAKE_CURRENT_SOURCE_DIR@/../examples \
+# @CMAKE_CURRENT_BINARY_DIR@ \
+# @CMAKE_CURRENT_SOURCE_DIR@
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *.cxx \
+ *.h \
+ *.H \
+ *.fl
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = @CMAKE_CURRENT_SOURCE_DIR@/src \
+ @CMAKE_CURRENT_BINARY_DIR@/src
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+#
+#
+# where is the value of the INPUT_FILTER tag, and is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+# fl_ \
+# FL_ \
+# Fl_
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = @GENERATE_FLUID_HTML@
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+# Note: since doxygen 1.9.5
+
+HTML_COLORSTYLE = TOGGLE
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via Javascript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have Javascript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = YES
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use + S
+# (what the is depends on the OS and browser, but it is typically
+# , /