Separate FLUID user documentation, screen shot automation (#936)
* CMake integration, no autotiools * alignment panel is now correctly renamed to setting panel * source view is now correctly renamed to code view * Merge FLTK FLUID docs into FLUID user manual. * Add two simple entry tutorials * Remove FLUID chapter form FLTK docs. * GitHub action to generate HTML and PDF docs and make the available as artefacts
84
.github/workflows/build_fluid_docs.yml
vendored
Normal file
@ -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
|
||||
|
@ -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
|
||||
#######################################################################
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 <i>fluid</i>. It
|
||||
The \c radio tool was created entirely with <i>FLUID</i>. 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 <i>fluid</i>. It tests
|
||||
The \c tabs tool was created with <i>FLUID</i>. 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 .
|
||||
|
||||
|
||||
|
||||
|
@ -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.
|
||||
<table summary="navigation bar" width="100%" border="0">
|
||||
<tr>
|
||||
<td width="45%" align="LEFT">
|
||||
<a class="el" href="fluid.html">
|
||||
<a class="el" href="opengl.html">
|
||||
[Prev]
|
||||
Programming with FLUID
|
||||
Using OpenGL
|
||||
</a>
|
||||
</td>
|
||||
<td width="10%" align="CENTER">
|
||||
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 156 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 53 KiB |
@ -67,11 +67,6 @@
|
||||
|
||||
\subpage opengl
|
||||
|
||||
\subpage fluid
|
||||
- \ref fluid_widget_attributes
|
||||
- \ref fluid_selecting_moving
|
||||
- \ref fluid_images
|
||||
|
||||
\subpage fltk-options
|
||||
|
||||
\subpage advanced
|
||||
|
@ -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
|
||||
|
@ -164,9 +164,7 @@ loading functions by doing:
|
||||
Your main program can now create one of your windows by doing
|
||||
<tt>new MyWindow(...)</tt>.
|
||||
|
||||
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
|
||||
<a class="el" href="index.html">[Index]</a>
|
||||
</td>
|
||||
<td width="45%" align="RIGHT">
|
||||
<a class="el" href="fluid.html">
|
||||
Programming with FLUID
|
||||
<a class="el" href="fltk-options.html">
|
||||
FLTK Runtime Options
|
||||
[Next]
|
||||
</a>
|
||||
</td>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
*/
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
@ -127,5 +127,6 @@ public:
|
||||
void redraw();
|
||||
};
|
||||
|
||||
extern Fl_Window *the_panel;
|
||||
|
||||
#endif // _FLUID_FL_WIDGET_TYPE_H
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
602
fluid/autodoc.cxx
Normal file
@ -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 <FL/Enumerations.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl_Image_Surface.H>
|
||||
#include <FL/Fl_PNG_Image.H>
|
||||
#include <FL/Fl_Menu_Bar.H>
|
||||
|
||||
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; i<img_h; i++) {
|
||||
const uchar *src = (const uchar*)img->data()[0] + i * ld;
|
||||
for (j=0; j<img_w; j++) {
|
||||
*dst++ = *src++;
|
||||
*dst++ = *src++;
|
||||
*dst++ = *src++;
|
||||
*dst++ = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the old image
|
||||
delete img;
|
||||
// Create the new image
|
||||
img = new Fl_RGB_Image(data, img_w, img_h, 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Blend the left 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_left(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] + i * img->d();
|
||||
uchar alpha = static_cast<uchar>(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<uchar>(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<uchar>(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<uchar>(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
|
59
fluid/autodoc.h
Normal file
@ -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 <FL/Fl_Export.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Rect.H>
|
||||
|
||||
/** 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
|
||||
|
@ -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; i<n; i++) if (proj_filename[i]=='\\') proj_filename[i] = '/';
|
||||
@ -803,13 +803,13 @@ int Fd_Code_Writer::write_code(const char *s, const char *t, bool to_sourceview)
|
||||
// a copyright notice. We print that before anything else in the file!
|
||||
Fl_Type* first_type = Fl_Type::first;
|
||||
if (first_type && first_type->is_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 <FL/Fl.H>");
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
548
fluid/codeview_panel.cxx
Normal file
@ -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 <FL/Fl_Tabs.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
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 (pos1<pos0)
|
||||
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 (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 (pos1<pos0)
|
||||
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 (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 (pos1<pos0)
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
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 && tab<cv_tab->children()) 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;
|
||||
}
|
||||
|
||||
//
|
@ -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 <FL/Fl_Tabs.H>} {private local
|
||||
@ -35,16 +35,16 @@ decl {\#include <FL/Fl_Tabs.H>} {private local
|
||||
decl {\#include <FL/Fl_Button.H>} {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 (pos1<pos0)
|
||||
pos1 = sv_source->buffer()->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 (pos1<pos0)
|
||||
pos1 = sv_header->buffer()->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 (pos1<pos0)
|
||||
pos1 = sv_project->buffer()->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 && tab<sv_tab->children()) 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 && tab<cv_tab->children()) 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
|
||||
}
|
||||
}
|
58
fluid/codeview_panel.h
Normal file
@ -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 <FL/Fl.H>
|
||||
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 <FL/Fl_Double_Window.H>
|
||||
extern void toggle_codeview_cb(Fl_Double_Window*, void*);
|
||||
extern Fl_Double_Window *codeview_panel;
|
||||
#include <FL/Fl_Tabs.H>
|
||||
extern Fl_Tabs *cv_tab;
|
||||
#include <FL/Fl_Group.H>
|
||||
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 <FL/Fl_Button.H>
|
||||
extern Fl_Button *cv_find_text_case;
|
||||
#include <FL/Fl_Input.H>
|
||||
extern Fl_Input *cv_find_text;
|
||||
#include <FL/Fl_Box.H>
|
||||
extern Fl_Group *cv_settings_row;
|
||||
#include <FL/Fl_Light_Button.H>
|
||||
extern Fl_Light_Button *cv_autorefresh;
|
||||
extern Fl_Light_Button *cv_autoposition;
|
||||
#include <FL/Fl_Choice.H>
|
||||
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
|
||||
|
||||
//
|
@ -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();
|
||||
|
232
fluid/documentation/CMakeLists.txt
Normal file
@ -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)
|
2485
fluid/documentation/Doxyfile.in
Normal file
44
fluid/documentation/convert_doxyfile
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Convert 'Doxyfile.in' to 'Doxyfile' or 'Doxybook' for doxygen docs
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ sh convert_doxyfile doxygen_path input output logfile
|
||||
#
|
||||
# where
|
||||
# - 'doxygen_path' is the full path to the doxygen executable or just
|
||||
# 'doxygen' if this is in the user's PATH. If the full path is used
|
||||
# an arbitrary doxygen executable and thus doxygen version can be used.
|
||||
# - 'input' is the file 'Doxyfile.in' stored in Git or any other file.
|
||||
# - 'output' is the generated doxygen file, usually either 'Doxyfile'
|
||||
# or 'Doxybook' which will be used subsequently to generate the
|
||||
# HTML or PDF docs, respectively.
|
||||
#
|
||||
# Doxygen warnings and errors are stored in 'logfile' for review.
|
||||
#
|
||||
#=======================================================================
|
||||
# This script requires a posix shell and uses the following commands:
|
||||
# 'echo', 'date', and (obviously) doxygen.
|
||||
#=======================================================================
|
||||
|
||||
# doxygen command, input and output file names
|
||||
|
||||
DOXYGEN="$1"
|
||||
INFILE="$2"
|
||||
OUTFILE="$3"
|
||||
LOGFILE="$4"
|
||||
|
||||
# get doxygen version
|
||||
|
||||
VERSION=$("$DOXYGEN" --version)
|
||||
|
||||
# write info header to LOGFILE
|
||||
|
||||
echo "$OUTFILE created by doxygen version $VERSION" > $LOGFILE
|
||||
echo " at `date`" >> $LOGFILE
|
||||
echo "" >> $LOGFILE
|
||||
|
||||
# convert doxygen file and append errors and warnings to LOGFILE
|
||||
|
||||
"${DOXYGEN}" -u -s - < $INFILE > $OUTFILE 2>> $LOGFILE
|
1
fluid/documentation/copyright.dox.in
Normal file
@ -0,0 +1 @@
|
||||
Copyright © 1998 - @YEAR@ by Bill Spitzak and others.
|
6
fluid/documentation/generated.dox.in
Normal file
@ -0,0 +1,6 @@
|
||||
<br>
|
||||
<small>
|
||||
Generated on @CURRENT_DATE@
|
||||
from Git revision @GIT_REVISION@
|
||||
by Doxygen @DOXYGEN_VERSION_SHORT@
|
||||
</small>
|
63
fluid/documentation/make_header
Executable file
@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Create a new LaTeX header file for doxygen PDF docs
|
||||
#
|
||||
# Note: this LaTeX file depends on Doxygen and LaTeX versions, resp.
|
||||
# and needs therefore to be created with current Doxygen and LaTeX
|
||||
# versions on the build system.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# $ sh make_header doxygen_path input-file output-file
|
||||
#
|
||||
# where
|
||||
# - 'doxygen_path' is the full path to the doxygen executable
|
||||
# or just 'doxygen'. If the full path is used an arbitrary
|
||||
# doxygen executable and thus doxygen version can be used.
|
||||
# - 'input-file' is the pure (LaTeX) title page (template)
|
||||
# - 'output-file' is the generated (LaTeX) title page (template)
|
||||
# that is used by `make' or `cmake` to generate the final LaTeX
|
||||
# page header (combined doxygen template + FLTK title page).
|
||||
#
|
||||
#=======================================================================
|
||||
# This script requires a posix shell and uses the following commands:
|
||||
# cat, rm and sed and (obviously) doxygen
|
||||
#=======================================================================
|
||||
|
||||
# input and output file names
|
||||
DOXY_CMD="$1"
|
||||
FLTK_HEAD="$2"
|
||||
DOXY_HEAD="$3"
|
||||
# temp file
|
||||
DOXY_TEMP="doxy-header.tex.$$"
|
||||
|
||||
if test x$FLTK_HEAD = x; then
|
||||
echo "usage: $0 fltk-header-file output-file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test x$DOXY_HEAD = x; then
|
||||
echo "usage: $0 fltk-header-file output-file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the doxygen LaTeX header template and replace the LaTeX
|
||||
# code between (and including) the lines containing
|
||||
# - 'begin{titlepage}' and
|
||||
# - 'end{titlepage}'
|
||||
# with our PDF document title page (LaTeX code) and write the
|
||||
# result to $DOXY_HEAD.
|
||||
|
||||
"$DOXY_CMD" -w latex $DOXY_TEMP /dev/null /dev/null
|
||||
|
||||
# combine three parts of these files to the output file
|
||||
# using '( ... ) > $DOXY_HEAD' to write (concatenate)
|
||||
# all three parts to one file
|
||||
|
||||
( sed -e'/begin{titlepage}/,$d' < $DOXY_TEMP
|
||||
cat $FLTK_HEAD
|
||||
sed -e'1,/end{titlepage}/d' < $DOXY_TEMP
|
||||
) > $DOXY_HEAD
|
||||
|
||||
# cleanup
|
||||
rm -f $DOXY_TEMP
|
41
fluid/documentation/make_pdf
Executable file
@ -0,0 +1,41 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Makefile helper script for the Fast Light Tool Kit (FLTK) documentation.
|
||||
#
|
||||
# Copyright 1998-2020 by Bill Spitzak and others.
|
||||
#
|
||||
# This library is free software. Distribution and use rights are outlined in
|
||||
# the file "COPYING" which should have been included with this file. If this
|
||||
# file is missing or damaged, see the license at:
|
||||
#
|
||||
# https://www.fltk.org/COPYING.php
|
||||
#
|
||||
# Please see the following page on how to report bugs and issues:
|
||||
#
|
||||
# https://www.fltk.org/bugs.php
|
||||
#
|
||||
|
||||
# This script generates latex/refman.pdf after doxygen has been executed.
|
||||
#
|
||||
# Input: run `doxygen Doxybook' (creates files in subdirectory latex)
|
||||
# Output: latex/refman.pdf (if successful)
|
||||
#
|
||||
# Next step: cp -f latex/refman.pdf fluid.pdf (why is this extra step needed ?)
|
||||
#
|
||||
# Working directory: fltk/documentation
|
||||
#
|
||||
# Used in: Makefile and CMakeLists.txt
|
||||
|
||||
( cd latex
|
||||
pdflatex --interaction=nonstopmode refman.tex
|
||||
makeindex refman.idx
|
||||
pdflatex --interaction=nonstopmode refman.tex
|
||||
latex_count=5
|
||||
while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log \
|
||||
&& [ $latex_count -gt 0 ]
|
||||
do
|
||||
echo "Rerunning pdflatex ..."
|
||||
pdflatex --interaction=nonstopmode refman.tex
|
||||
latex_count=`expr $latex_count - 1`
|
||||
done
|
||||
cd ..) > pdfall.log 2>&1
|
BIN
fluid/documentation/src/1of7GUIs.png
Normal file
After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
fluid/documentation/src/edit_live_resize.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
fluid/documentation/src/edit_outside.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
fluid/documentation/src/edit_overlap.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
fluid/documentation/src/edit_select_group.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
fluid/documentation/src/edit_select_multiple.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
fluid/documentation/src/edit_snap_grid.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
fluid/documentation/src/edit_snap_group.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
fluid/documentation/src/edit_snap_sibling.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
fluid/documentation/src/edit_snap_size.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
fluid/documentation/src/edit_window.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
fluid/documentation/src/flBox.png
Normal file
After Width: | Height: | Size: 453 B |
BIN
fluid/documentation/src/flClass.png
Normal file
After Width: | Height: | Size: 176 B |
BIN
fluid/documentation/src/flCode.png
Normal file
After Width: | Height: | Size: 120 B |
BIN
fluid/documentation/src/flCodeBlock.png
Normal file
After Width: | Height: | Size: 210 B |
BIN
fluid/documentation/src/flComment.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
fluid/documentation/src/flData.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
fluid/documentation/src/flDeclaration.png
Normal file
After Width: | Height: | Size: 165 B |
BIN
fluid/documentation/src/flDeclarationBlock.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
fluid/documentation/src/flFunction.png
Normal file
After Width: | Height: | Size: 200 B |
BIN
fluid/documentation/src/flWidgetClass.png
Normal file
After Width: | Height: | Size: 202 B |
BIN
fluid/documentation/src/flWindow.png
Normal file
After Width: | Height: | Size: 488 B |
BIN
fluid/documentation/src/fluid-128.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
35
fluid/documentation/src/fluid-title.tex.in
Normal file
@ -0,0 +1,35 @@
|
||||
%
|
||||
% FLUID PDF documentation title page (LaTeX)
|
||||
%
|
||||
\begin{titlepage}
|
||||
\vspace*{4cm}
|
||||
\begin{center}%
|
||||
{\Huge FLUID for FLTK @FLTK_VERSION@ User Manual}\\
|
||||
\vspace*{2cm}
|
||||
\begin{DoxyImageNoCaption}
|
||||
\mbox{\includegraphics[width=4cm]{fluid-128.png}}
|
||||
\end{DoxyImageNoCaption}\\
|
||||
\vspace*{2cm}
|
||||
{\Large
|
||||
By F. Costantini, D. Gibson, M. Melcher, \\
|
||||
A. Schlosser, B. Spitzak, and M. Sweet.}\\
|
||||
\vspace*{1.5cm}
|
||||
{\large Copyright © 1998 - @YEAR@ by Bill Spitzak and others.}\\
|
||||
\vspace*{0.75cm}
|
||||
{\small
|
||||
This software and manual are provided under the terms of the GNU Library General Public License.}\\
|
||||
{\small
|
||||
Permission is granted to reproduce this manual or any portion for any purpose,}\\
|
||||
{\small
|
||||
provided this copyright and permission notice are preserved.}\\
|
||||
\vspace*{1.5cm}
|
||||
{\large Generated by Doxygen @DOXY_VERSION@}\\
|
||||
\vspace*{0.5cm}
|
||||
\today{}\\
|
||||
\vspace*{0.5cm}
|
||||
{\small Git revision @GIT_REVISION@}\\
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
%
|
||||
% end of FLUID PDF documentation title page (LaTeX)
|
||||
%
|
BIN
fluid/documentation/src/fluid1.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
fluid/documentation/src/fluid2.png
Normal file
After Width: | Height: | Size: 99 KiB |
BIN
fluid/documentation/src/fluid3-cxx.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
fluid/documentation/src/fluid4.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
fluid/documentation/src/fluid_flow_chart.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
fluid/documentation/src/fluid_flow_chart_800.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
fluid/documentation/src/fluid_gui_overview_800.png
Normal file
After Width: | Height: | Size: 326 KiB |
118
fluid/documentation/src/index.dox
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
|
||||
/**
|
||||
|
||||
\cond FL_HTML_INDEX
|
||||
|
||||
\mainpage FLUID User Manual
|
||||
|
||||
|
||||
<TABLE CELLPADDING="8" CELLSPACING="0" SUMMARY="TITLE BAR" WIDTH="100%" BORDER="0">
|
||||
<TR>
|
||||
<TD><CENTER>
|
||||
\image html fluid-128.png
|
||||
\image latex fluid-128.png "" width=3cm
|
||||
</CENTER></TD>
|
||||
<TD><CENTER>
|
||||
<B>FLUID 1.4.0 User Manual</B>
|
||||
|
||||
By F. Costantini, D. Gibson, M. Melcher,
|
||||
A. Schlosser, B. Spitzak and M. Sweet.
|
||||
|
||||
Copyright © 1998 - 2024 by Bill Spitzak and others.
|
||||
</CENTER></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE CELLPADDING="8" CELLSPACING="0" SUMMARY="TITLE BAR" WIDTH="100%" BORDER="0">
|
||||
<TR>
|
||||
<TD style="text-align: center;">
|
||||
This software and manual are provided under the terms of the GNU
|
||||
Library General Public License. Permission is granted to reproduce
|
||||
this manual or any portion for any purpose, provided this copyright
|
||||
and permission notice are preserved.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE CELLPADDING="8" CELLSPACING="0" SUMMARY="Table of Contents" WIDTH="100%" BORDER="0">
|
||||
<TR>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">
|
||||
|
||||
\subpage page_introduction
|
||||
- \ref introduction_workflow
|
||||
|
||||
\subpage page_commandline
|
||||
- \ref commandline_options
|
||||
- \ref commandline_passive
|
||||
- \ref commandline_windows
|
||||
|
||||
\subpage page_interactive
|
||||
|
||||
\subpage page_main_window
|
||||
- \ref main_titlebar
|
||||
- \ref main_menubar
|
||||
- \ref main_widget_browser
|
||||
- \ref main_menu_items
|
||||
|
||||
\subpage page_widgetbin_panel
|
||||
|
||||
\subpage page_edit_window
|
||||
- \ref edit_selection
|
||||
- \ref edit_layout
|
||||
- \ref edit_snap
|
||||
- \ref edit_resize
|
||||
|
||||
\subpage page_widget_panel
|
||||
- \ref widget_panel_gui
|
||||
- \ref widget_panel_style
|
||||
- \ref widget_panel_cpp
|
||||
- \ref widget_panel_grid
|
||||
- \ref widget_panel_gridc
|
||||
|
||||
</TD>
|
||||
<TD ALIGN="LEFT" VALIGN="TOP">
|
||||
|
||||
\subpage page_functional_nodes
|
||||
- \ref functional_function
|
||||
- \ref functional_code
|
||||
- \ref functional_codeblock
|
||||
- \ref functional_decl
|
||||
- \ref functional_declblock
|
||||
- \ref functional_class
|
||||
- \ref functional_widgetclass
|
||||
- \ref functional_comment
|
||||
- \ref functional_data
|
||||
|
||||
\subpage page_codeview_panel
|
||||
- \ref codeview_find
|
||||
- \ref codeview_settings
|
||||
|
||||
\subpage page_setting_dialog
|
||||
- \ref setting_general
|
||||
- \ref setting_project
|
||||
- \ref setting_layout
|
||||
- \ref setting_shell
|
||||
- \ref setting_i18n
|
||||
- \ref setting_user
|
||||
|
||||
\subpage page_tutorial
|
||||
- \ref fluid_hello_world_tutorial
|
||||
- \ref fluid_1of7guis_tutorial
|
||||
- \ref fluid_cubeview_tutorial
|
||||
- \ref fluid_cubeview_ui
|
||||
- \ref fluid_addconst
|
||||
- \ref fluid_gencode
|
||||
|
||||
\subpage page_appendices
|
||||
- \ref appendix_keyboard_shortcuts
|
||||
- \ref appendix_fileformat
|
||||
- \ref appendix_licenses
|
||||
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
\endcond
|
||||
|
||||
*/
|
BIN
fluid/documentation/src/main_titlebar.png
Normal file
After Width: | Height: | Size: 15 KiB |
92
fluid/documentation/src/page_appendices.dox
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
|
||||
\page page_appendices Appendices
|
||||
|
||||
\tableofcontents
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section appendix_keyboard_shortcuts Keyboard Shortcuts
|
||||
|
||||
On Apple computers, use the Apple Command key instead of Ctrl.
|
||||
|
||||
| Key Combo | Function |
|
||||
| :-------: | :------- |
|
||||
| `F1` | open widget dialog |
|
||||
| `F2` | move widget earlier in tree |
|
||||
| `F3` | move widget later in tree |
|
||||
| `F7` | move widgets into group |
|
||||
| `F8` | ungroup widgets |
|
||||
| `Delete` | delete selected widgets |
|
||||
| `Ctrl-1..9` | load project from history |
|
||||
| `Ctrl-A` | select all |
|
||||
| `Shift-Ctrl-A` | select none |
|
||||
| `Alt-B` | show or hide Widget Bin |
|
||||
| `Ctrl-C` | copy widgets |
|
||||
| `Alt-C` | show or hide Code View window |
|
||||
| `Shift-Ctrl-C` | generate C++ code files |
|
||||
| `Ctrl-G` | grid setting dialog |
|
||||
| `Ctrl-I` | merge project file into current project |
|
||||
| `Ctrl-N` | start a new project, close the current project |
|
||||
| `Shift-Ctrl-N` | new project from template |
|
||||
| `Ctrl-O` | open project file |
|
||||
| `Shift-Ctrl-O` | toggle overlays |
|
||||
| `Ctrl-P` | print all visible project windows |
|
||||
| `Alt-P` | open FLUID settings dialog |
|
||||
| `Ctrl-Q` | quit FLUID |
|
||||
| `Ctrl-S` | save project |
|
||||
| `Shift-Ctrl-S` | save project with new name |
|
||||
| `Ctrl-U` | duplicate selected widgets |
|
||||
| `Ctrl-V` | paste last copied widgets |
|
||||
| `Shift-Ctrl-W` | write i18n translation file |
|
||||
| `Ctrl-X` | cut selected widgets |
|
||||
| `Alt-X` | show shell command settings |
|
||||
| `Ctrl-Z` | undo |
|
||||
| `Shift-Ctrl-Z` | redo |
|
||||
|
||||
<!-- | `Alt-G` | rund last shell command again | -->
|
||||
|
||||
|
||||
| Action | Function in Layout Editor |
|
||||
| :----: | :------------------------ |
|
||||
| `left mouse button (LMB)` | select one widget |
|
||||
| `LMB-drag` | select multiple widgets with selection box |
|
||||
| `Shift-LMB` | extend widget selection |
|
||||
| `Shift-LMB-Drag` | toggle selection in selection box |
|
||||
| `Shift-LMB-Drag` | resize window proportionally |
|
||||
| `Tab` | select next widget |
|
||||
| `Shift-Tab` | select previous widget |
|
||||
| `Arrow` | move selected widgets by one unit |
|
||||
| `Shift-Arrow` | resize by one unit |
|
||||
| `Ctrl-Arrow` | move by grid units |
|
||||
| `Shift-Ctrl-Arrow` | resize by grid units |
|
||||
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section appendix_fileformat .fl File Format
|
||||
|
||||
FLUID edits and saves its state in `.fl` project 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 described in detail in the file
|
||||
`fluid/README_fl.txt` which is part of the FLTK source code repository.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section appendix_licenses External Licenses
|
||||
|
||||
FLUID uses graphical images based on the Zendesk Garden Stroke icon set:
|
||||
|
||||
[https://github.com/zendeskgarden](https://github.com/zendeskgarden)
|
||||
Garden Stroke is licensed under the
|
||||
[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
|
||||
|
||||
FLUID includes templates based on 7GUIs:
|
||||
|
||||
[7GUIs](https://7guis.github.io/7guis/) was created as a spin-off
|
||||
of the master’s thesis Comparison of Object-Oriented and Functional
|
||||
Programming for GUI Development by Eugen Kiss at the Human-Computer
|
||||
Interaction group of the Leibniz Universität Hannover in 2014.
|
||||
|
||||
With kind permission by Prof. Dr. Michael Rohs.
|
||||
|
||||
*/
|
76
fluid/documentation/src/page_codeview_panel.dox
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
|
||||
\page page_codeview_panel Code View Panel
|
||||
|
||||
\tableofcontents
|
||||
|
||||
# The Code View Panel #
|
||||
|
||||
\image html codeview_panel.png "Code View Panel"
|
||||
\image latex codeview_panel.png "Code View Panel" width=9cm
|
||||
|
||||
The Code View panel shows all code files that can be generated by FLUID.
|
||||
|
||||
The Code View window can be activated via the main
|
||||
menu: *Edit* > *Show Source Code* . FLUID will remember the state and
|
||||
dimensions of the Code View panel.
|
||||
|
||||
If the Auto-Refresh option is selected, the code views will be updated
|
||||
automatically while editing the project.
|
||||
|
||||
Code View has four tabs. The first tab shows the source code. Inlined data
|
||||
is omitted in the code view for brevity.
|
||||
|
||||
The second tab shows the content of the header file. The size of inline data
|
||||
is not calculated and shown as `-1`.
|
||||
|
||||
The third tab shows the list of labels and tooltips as they would be written
|
||||
to a translation file, using the selected project internationalization method.
|
||||
|
||||
The fourth tab previews the contents of the `.fl` project file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section codeview_find Code View Find
|
||||
|
||||
\image html cv_find_row.png
|
||||
\image latex cv_find_row.png "Find in Code" width=9cm
|
||||
|
||||
This group of buttons makes it easy to find any text in the Source, Header, or
|
||||
Project file. Press *Reveal* to select the widget that generated the indicated
|
||||
line of code.
|
||||
|
||||
__Find__: enter any text you may want to find in the current tab
|
||||
|
||||
__aA__: press this button to activate case sensitive search
|
||||
|
||||
__<<__, __>>__: find the previous or next occurrence
|
||||
|
||||
__Reveal__: clicking this button reveals the widget that generated the
|
||||
selected code in the widget browser
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section codeview_settings Code View Settings
|
||||
|
||||
\image html cv_settings_row.png
|
||||
\image latex cv_settings_row.png "Code View Settings" width=9cm
|
||||
|
||||
__Refresh__: preview the code in the selected tab as it would be generated
|
||||
for the project in its current state
|
||||
|
||||
__Auto-Refresh__: Automatically refresh the code view when the project changes.
|
||||
The Auto Refresh is designed to use relatively little resources, even when
|
||||
continuously updating the selected code tab.
|
||||
The Code View window can usually stay open and auto refresh during the entire
|
||||
design process, even for relatively complex GUIs.
|
||||
|
||||
__Auto-Position__: highlight and reposition to the source code generated by
|
||||
the currently selected widget whenever the selection changes
|
||||
|
||||
__code...__: choose the type of code that is highlighted. In source
|
||||
files, *static* code is generated by Menu Items, *code* refers to widget
|
||||
creation code, *code1* is the part before possible children, *code2* is
|
||||
code generated after children. In header files, *static* highlights
|
||||
`#include` statements generated by a widget, *code* refers to
|
||||
the widget declaration.
|
||||
|
||||
*/
|
124
fluid/documentation/src/page_commandline.dox
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
|
||||
\page page_commandline Command Line
|
||||
|
||||
\tableofcontents
|
||||
|
||||
FLUID can be used in interactive and in command line mode. If launched with
|
||||
`-c`, followed by a project filename, FLUID will convert the project file
|
||||
into C++ source files without ever opening a window (or opening an X11 server
|
||||
connection under Linux/X11). This makes FLUID a great command line tool
|
||||
for build processes with complex project files that reference
|
||||
external resources. For example, an image referenced by a `.fl` file can be
|
||||
modified and recompiled into the application binary without the need to reload
|
||||
it in an interactive FLUID session.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section commandline_options Command Line Options
|
||||
|
||||
To launch FLUID in interactive mode from the command line, you can give it an
|
||||
optional name of a project file. If no name is given, it will launch with an
|
||||
empty project, or with the last open project, if so selected in the
|
||||
application setting dialog.
|
||||
|
||||
The ampersand `&` is optional on Linux machines and lets FLUID run in its
|
||||
own new process, giving the shell back to the caller.
|
||||
|
||||
```
|
||||
fluid 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.
|
||||
|
||||
FLUID understands all of the standard FLTK switches before the filename:
|
||||
|
||||
```
|
||||
-display host:n.n
|
||||
-geometry WxH+X+Y
|
||||
-title windowtitle
|
||||
-name classname
|
||||
-iconic
|
||||
-fg color
|
||||
-bg color
|
||||
-bg2 color
|
||||
-scheme schemename
|
||||
```
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section commandline_passive Compile Tool Options
|
||||
|
||||
FLUID can also be called as a command-line only tool to create
|
||||
the `.cxx` and `.h` file from a `.fl` file directly. To do this type:
|
||||
|
||||
```
|
||||
fluid -c filename.fl
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
my_panels.h my_panels.cxx: my_panels.fl
|
||||
fluid -c my_panels.fl
|
||||
```
|
||||
|
||||
Most versions of "make" support rules that cause `.fl` files to be compiled:
|
||||
|
||||
```
|
||||
.SUFFIXES: .fl .cxx .h
|
||||
.fl.h .fl.cxx:
|
||||
fluid -c $<
|
||||
```
|
||||
|
||||
Check `README.CMake.txt` for examples on how to integrate FLUID into the
|
||||
`CMake` build process.
|
||||
|
||||
If you use
|
||||
|
||||
\code
|
||||
fluid -cs filename.fl
|
||||
\endcode
|
||||
|
||||
FLUID will also write the "strings" for internationalization into the file
|
||||
'filename.txt', 'filename.po', or 'filename.msg', depending on the chosen type
|
||||
of i18n (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 `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
|
||||
|
||||
```
|
||||
fluid -u filename.fl
|
||||
```
|
||||
|
||||
to 'upgrade' `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` project file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section commandline_windows Windows Specifics
|
||||
|
||||
FLTK uses Linux-style forward slashes to separate path segments in file names.
|
||||
When running on Windows, FLUID will understand Microsoft drive names and
|
||||
backward slashes as path separators and convert them internally into
|
||||
forward slashes.
|
||||
|
||||
Under Windows, binaries can only be defined either as command line tools, or
|
||||
as interactive apps. FLTK generates two almost identical binaries under
|
||||
Windows. `fluid.exe` is meant to be used in interactive mode, and
|
||||
`fluid-cmd.exe` is generated for the command line. Both tools do exactly the
|
||||
same thing, except `fluid-cmd.exe` can use stdio to output error messages.
|
||||
|
||||
*/
|
179
fluid/documentation/src/page_edit_window.dox
Normal file
@ -0,0 +1,179 @@
|
||||
/**
|
||||
|
||||
\page page_edit_window Layout Editor Window
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\image html edit_window.png "Layout Editor Window"
|
||||
\image latex edit_window.png "Layout Editor Window" width=7cm
|
||||
|
||||
The Layout Editor window is used to interactively add groups and widgets, and
|
||||
resize and align them. The editor window already looks very much like the
|
||||
final product that will be built by the FLUID generated C++ source code.
|
||||
|
||||
To create a user interface, first add a function to the project tree by either
|
||||
clicking the Function icon in the widget bin, or by selecting __New* > Code >
|
||||
Function/Method__ from the main menu.
|
||||
|
||||
Now just drag the Window icon from the widget bin onto the desktop. FLUID
|
||||
will generate code that instantiates this window when the function is called.
|
||||
The return value of the function is a pointer to that window, unless changed
|
||||
in the Function Panel. Widgets can be added to the window by dragging them from
|
||||
the widget bin. If a widget is dropped on a group, it will automatically
|
||||
become a child of that group.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section edit_selection Selecting and Moving Widgets
|
||||
|
||||
To move or resize a widget, it must be selected first by clicking on it.
|
||||
Multiple widgets can be selected by holding down the Shift key when clicking
|
||||
on them, or by dragging a selection box around widgets. Widgets can also be
|
||||
selected in the widget browser the main window. Shift-click will select a
|
||||
range of widgets, Ctrl-click will add widgets to the selection.
|
||||
|
||||
\image html edit_select_multiple.png
|
||||
\image latex edit_select_multiple.png "Select Multiple Widgets" width=5cm
|
||||
|
||||
Menu items are selected by clicking on the menu button and selecting it from
|
||||
the popup menu. Multiple menu items can only be selected in the widget browser
|
||||
in the main application window.
|
||||
|
||||
Once selected, widgets can be moved by clicking and dragging the center
|
||||
of the selection box. The outer edges allow resizing in one direction, and
|
||||
dragging the corners resizes widgets horizontally and vertically.
|
||||
|
||||
Widgets can also be repositioned with the arrow keys. Without a shift key,
|
||||
the selection moves by a single pixel. With the Meta key held down, they
|
||||
move by the amount indicated in the *Gap* field in the *Widget* section of
|
||||
the *Layout* setting panel.
|
||||
|
||||
Holding down the Shift key resizes a selected widget by moving the bottom
|
||||
right corner of the widget. Holding Shift and Meta while pressing arrow keys
|
||||
resizes by the amount in the *Widget* *Gap* layout setting.
|
||||
|
||||
Children of groups that reposition their contained widgets may behave
|
||||
differently. Pressing the arrow keys on children of `Fl_Grid` will move
|
||||
the widget from grid cell to grid cell instead. Resizing a child of `Fl_Flex`
|
||||
will also mark the child size as `fixed`.
|
||||
|
||||
The tab and shift+tab keys "navigate" the selection. Tab or shift+tab move to
|
||||
the next or previous widgets in the hierarchy. 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 tab keys
|
||||
to move between input fields.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section edit_layout Layout Helpers
|
||||
|
||||
\image html edit_overlap.png
|
||||
\image latex edit_overlap.png "Overlapping Widgets" width=5cm
|
||||
|
||||
In FLTK, the behavior of overlapping children of a group is undefined. If
|
||||
enabled in the settings, FLUID will show overlapping widgets in a group
|
||||
with a green hash pattern.
|
||||
|
||||
\image html edit_outside.png
|
||||
\image latex edit_outside.png "Out Of Bounds" width=5cm
|
||||
|
||||
The behavior of widgets that reach outside the bounds of their parent group
|
||||
is also undefined. They may be visible, but confuse the user when they don't
|
||||
react to mouse clicks or don't redraw as expected. Outside widgets are marked
|
||||
with a red hash pattern.
|
||||
|
||||
Note that `Fl_Tile` requires that all children exactly fill the area of the
|
||||
tile group to function properly. The hash patterns are great helpers to align
|
||||
children correctly.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section edit_snap Layout Alignment
|
||||
|
||||
FLUID layouts are a handful of rules that help creating a clean and consistent
|
||||
user interface. When repositioning widgets, the mouse pointer snaps to the
|
||||
closest position based on those rules. A guide line is drawn for the rule that was
|
||||
applied. Guides and snaps can be disabled with `Ctrl-Shift-G` or via the
|
||||
*Edit* > *Hide Guides* menu.
|
||||
|
||||
\image html edit_snap_group.png
|
||||
\image latex edit_snap_group.png "Snap To Group" width=5cm
|
||||
|
||||
If a horizontal or vertical outline snaps to the group, the
|
||||
border of that group will highlight. If the outline snaps to the margin
|
||||
of the parent window or group, an additional arrow is drawn.
|
||||
|
||||
Children of `Fl_Tabs` use the top and bottom margin from the *Tabs*
|
||||
section. If all children use this rule, the margin height will also be the
|
||||
height of all tabs.
|
||||
|
||||
\image html edit_snap_sibling.png
|
||||
\image latex edit_snap_sibling.png "Snap To Sibling" width=5cm
|
||||
|
||||
The selection can also snap to the outline of other widgets in the same group,
|
||||
or to the outline plus the Widget Gap. The outline that triggers the snap
|
||||
action is highlighted.
|
||||
|
||||
Note that only the first snap guide found is drawn for horizontal and vertical
|
||||
movement. Multiple rules may apply, but are not highlighted.
|
||||
|
||||
\image html edit_snap_size.png
|
||||
\image latex edit_snap_size.png "Snap To Size" width=7cm
|
||||
|
||||
Widget size rules define a minimum size and an increment value that may
|
||||
be applied multiple times to the size. For example, with a minimum width of 25
|
||||
and an increment of 10, the widget will snap horizontally to 25, 35, 45,
|
||||
55, etc. .
|
||||
|
||||
\image html edit_snap_grid.png
|
||||
\image latex edit_snap_grid.png "Snap To Grid" width=5cm
|
||||
|
||||
The grid rule is the easiest to explain. All corners of a selection snap to
|
||||
a fixed grid. If the selected widgets are children of a window, they will snap
|
||||
to the window grid. If they are in a group, they snap to the group grid.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section edit_resize Live Resize
|
||||
|
||||
\image html edit_select_group.png
|
||||
\image latex edit_select_group.png "Selected Group" width=9cm
|
||||
|
||||
The Resizable system within FLTK is smart, but not always obvious. When
|
||||
constructing a sophisticated GUI, it is helpful to organize widgets into
|
||||
multiple levels of nested groups. Sometimes, incorporating an invisible
|
||||
resizable box can improve the behavior of a group. FLUID offers a Live Resize
|
||||
feature, allowing designers to experiment with resizing at each level within
|
||||
the hierarchy independently.
|
||||
|
||||
To test the resizing behavior of a group, begin by selecting it:
|
||||
|
||||
\image html edit_live_resize.png
|
||||
\image latex edit_live_resize.png "Live Resize" width=7cm
|
||||
|
||||
Click on *Live Resize* in the widget panel. FLUID will generate a new window
|
||||
with all the resizing attributes inherited from the original design. This
|
||||
enables the designer to thoroughly test the behavior and limitations,
|
||||
making adjustments until they are satisfied. This streamlined process makes
|
||||
it significantly easier to address resizing behavior at a higher level,
|
||||
particularly once the lower levels are behaving as intended.
|
||||
|
||||
In the example above, the radio buttons are not fixed to the left side of
|
||||
the group and the text snippet "of the bed" does not stay aligned
|
||||
to "right side". To fix this, a thin hidden box could be added to the right
|
||||
edge of the group that holds the radio button which is then marked `resizable`.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section edit_limits Limitations
|
||||
|
||||
Almost all FLTK widgets can be edited with FLUID. Notable exceptions include
|
||||
|
||||
- FLUID does not support an `Fl_Window` inside another `Fl_Window`
|
||||
- widgets inside `Fl_Scroll` can not be created in the hidden areas of the
|
||||
scrollable rectangle. It is recommended to organize the children in
|
||||
a separate Widget Class that is derived from `Fl_Scroll` and then inserted
|
||||
as a single custom widget.
|
||||
- children of `Fl_Pack` are not automatically reorganized to fit the packing
|
||||
group. Again, a Widget Class is recommended here.
|
||||
- if children of `Fl_Grid` are again some kind of group, their internal layout
|
||||
may not follow changes in the grid widgets. It's best to complete the grid
|
||||
first, then add children to the grid cells, size them correctly, and
|
||||
then finally lay out the grid cell children.
|
||||
|
||||
*/
|
450
fluid/documentation/src/page_functional_nodes.dox
Normal file
@ -0,0 +1,450 @@
|
||||
/**
|
||||
|
||||
\page page_functional_nodes Functional Node Panels
|
||||
|
||||
\tableofcontents
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_function Function and Method Panel
|
||||
|
||||
![](flFunction.png) Functions and Methods
|
||||
|
||||
Fluid can generate C functions, C++ functions, and methods in classes.
|
||||
Functions can contain widgets to build windows and dialogs. *Code* nodes can
|
||||
be used to add more source code to a function.
|
||||
|
||||
### Parents ###
|
||||
|
||||
To generate a function, the function node must be created at the top level or
|
||||
inside a declaration block. If added inside a class node, this node generates
|
||||
a method inside that class.
|
||||
|
||||
### Children ###
|
||||
|
||||
Function nodes can contain code nodes and windows that in turn contain widgets.
|
||||
If the function node has no children, only a forward declaration will be
|
||||
created in the header, but no source code will be generated.
|
||||
|
||||
\image html function_panel.png "Function/Method Properties"
|
||||
\image latex function_panel.png "Function/Method Properties" width=7cm
|
||||
|
||||
### Declaring a Function ###
|
||||
|
||||
A function node at the top level or inside a declaration block generates a C
|
||||
or C++ function.
|
||||
|
||||
The *Name* field contains the function name and all arguments.
|
||||
If the *Name* field is left empty, Fluid will generate a typical 'main()' function.
|
||||
```
|
||||
// .cxx
|
||||
int main(int argc, char **argv) {
|
||||
// code generated by children
|
||||
w->show(argc, argv); // <-- code generated if function has a child widget
|
||||
Fl::run();
|
||||
}
|
||||
```
|
||||
|
||||
If a function node has a name but no children, a forward declaration is
|
||||
generated in the header, but the implementation in the source file is omitted.
|
||||
This is used to reference functions in other modules.
|
||||
```
|
||||
// .h
|
||||
void make_window();
|
||||
```
|
||||
|
||||
If the function contains one or more Code nodes, the implementation code will
|
||||
be generated. The default return type is `void`. Text in the *Return Type* field
|
||||
overrides the default type.
|
||||
```
|
||||
// .cxx
|
||||
void make_window() {
|
||||
// code generated by children
|
||||
}
|
||||
```
|
||||
|
||||
If the function contains one or more windows, a pointer to the first window
|
||||
will be returned. The default return type will match the window class.
|
||||
```
|
||||
// .h
|
||||
Fl_Window* make_window();
|
||||
```
|
||||
|
||||
```
|
||||
// .cxx
|
||||
Fl_Window* make_window() {
|
||||
Fl_Window* w;
|
||||
// code generated by children:
|
||||
// w = new Fl_Window(...)
|
||||
return w;
|
||||
}
|
||||
```
|
||||
|
||||
#### Options for Functions ####
|
||||
|
||||
Choosing *static* in the pulldown menu will generate the function `static` in
|
||||
the source file. No forward declaration will be generated in the header file.
|
||||
```
|
||||
// .cxx
|
||||
static Fl_Window* make_window() { ... }
|
||||
```
|
||||
|
||||
Choosing *global* will generate a forward declaration of the function in the
|
||||
header file and no `static` attribute in the source file.
|
||||
```
|
||||
// .h
|
||||
void make_window();
|
||||
// .cxx
|
||||
Fl_Window* make_window() { ... }
|
||||
```
|
||||
|
||||
Additionally,
|
||||
if the *C* option is checked, the function will be declared as a plain C
|
||||
function in the header file.
|
||||
```
|
||||
// .h
|
||||
extern "C" { void my_plain_c_function(); }
|
||||
// .cxx
|
||||
void my_plain_c_function() { ... }
|
||||
```
|
||||
|
||||
The *local* option will generate a function in the source file with no `static`
|
||||
attribute. No forward declaration will be generated in the header file.
|
||||
```
|
||||
// .cxx
|
||||
Fl_Window* make_window() { ... }
|
||||
```
|
||||
|
||||
### Declaring a Method ###
|
||||
|
||||
A function node inside a class node generates a C++ method. If a method node has
|
||||
no children, the declaration is generated in the header, but no implementation
|
||||
in the source file.
|
||||
```
|
||||
// .h
|
||||
class UserInterface {
|
||||
public:
|
||||
void make_window();
|
||||
};
|
||||
```
|
||||
|
||||
If the method contains one or more Code nodes, an implementation will also be
|
||||
generated.
|
||||
|
||||
```
|
||||
// .cxx
|
||||
void UserInterface::make_window() {
|
||||
printf("Hello, World!\n");
|
||||
}
|
||||
```
|
||||
|
||||
If the method contains at least one widget, a pointer to the topmost widget
|
||||
will be returned and the return type will be generated accordingly.
|
||||
```
|
||||
// .h
|
||||
class UserInterface {
|
||||
public:
|
||||
Fl_Double_Window* make_window();
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
// .cxx
|
||||
Fl_Double_Window* UserInterface::make_window() {
|
||||
Fl_Double_Window* w;
|
||||
// code generated by children
|
||||
return w;
|
||||
}
|
||||
```
|
||||
|
||||
#### Options for Methods ####
|
||||
|
||||
Class access can be defined with the pulldown menu. It provides a choice of
|
||||
`private`, `protected`, and `public`.
|
||||
|
||||
Fluid recognizes the keyword `static` or `virtual` at the beginning of the
|
||||
*return type* and will generate the declaration including the keyword, but will
|
||||
omit it in the implementation. The return type defaults still apply if there
|
||||
is no text after the keyword.
|
||||
|
||||
#### Further Options ####
|
||||
|
||||
Users can define a comment text in the *comment* field. The first line of the
|
||||
comment will be shown in the widget browser. The comment text will be generated
|
||||
in the source file before the function.
|
||||
```
|
||||
// .cxx
|
||||
//
|
||||
// My multilen comment will be here... .
|
||||
// Fluid may actually use C style comment markers.
|
||||
//
|
||||
Fl_Window* make_window() {
|
||||
```
|
||||
|
||||
FLUID recognizes default values in the argument list and generates them in the
|
||||
declaration, but omits them in the implementation.
|
||||
|
||||
A short function body can be appended in the *Name* field. With no child, this
|
||||
creates an inlined function in the header file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_code C Source Code
|
||||
|
||||
![](flCode.png) Code
|
||||
|
||||
Code nodes hold arbitrary C++ code that is copied verbatim into the
|
||||
source code file. They are commonly used inside Function nodes.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Code nodes can be added inside Functions, Code Blocks, and Widget Classes.
|
||||
|
||||
\image html code_panel.png "Code Properties"
|
||||
\image latex code_panel.png "Code Properties" width=9cm
|
||||
|
||||
The Code Properties panel features a syntax-highlighting C++ code editor.
|
||||
Some basic bracket and braces match checking is done when closing the dialog.
|
||||
|
||||
When inside a Function or Code Block, the C++ code is inserted directly.
|
||||
Inside a Widget Class, the code will be added to the constructor of the
|
||||
widget class.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_codeblock Code Block
|
||||
|
||||
![](flCodeBlock.png) Code Block
|
||||
|
||||
Code Blocks are used when a single function generates different GUI elements
|
||||
conditionally.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Code Blocks are used inside functions and methods.
|
||||
|
||||
### Children ###
|
||||
|
||||
Code Blocks can contain widgets, code, or more code blocks.
|
||||
|
||||
\image html codeblock_panel.png "Code Block Properties"
|
||||
\image latex codeblock_panel.png "Code Block Properties" width=7cm
|
||||
|
||||
The two fields expect the code before and after the `{ ... }` statements. The
|
||||
second field can be empty.
|
||||
|
||||
Two consecutive Code Blocks can be used to generate `else`/`else if`
|
||||
statements by leaving the second field of the first node empty.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_decl Declaration
|
||||
|
||||
![](flDeclaration.png) Declaration
|
||||
|
||||
### Parents ###
|
||||
|
||||
Declarations can be added at the top level or inside classes and widget classes.
|
||||
|
||||
\image html decl_panel.png "Declaration Properties"
|
||||
\image latex decl_panel.png "Declaration Properties" width=7cm
|
||||
|
||||
Declaration nodes are quite flexible and can be a simple variable declaration
|
||||
such as `int i;`. But include statements are also allowed, as are type
|
||||
declarations, and comments. FLUID does its best to understand user intention,
|
||||
but the generated code should be verified by the user.
|
||||
|
||||
Declarations nodes at the top level can selectively generate code in the header
|
||||
and /or in the source file. If a declaration is inside a class, the user can
|
||||
select if the class member is *private*, *protected*, or *public* instead.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_declblock Declaration Block
|
||||
|
||||
![](flDeclarationBlock.png) Declaration Block
|
||||
|
||||
Declaration Blocks are a way to selectively compile child nodes via
|
||||
preprocessor commands, typically `#ifdef TEST` and `#endif`.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Declaration Blocks can be created at the top level or inside classes.
|
||||
|
||||
### Children ###
|
||||
|
||||
Declaration Blocks can contain classes, functions, methods, declarations, and
|
||||
comments.
|
||||
|
||||
\image html declblock_panel.png "Declaration Block Properties"
|
||||
\image latex declblock_panel.png "Declaration Block Properties" width=7cm
|
||||
|
||||
Users can select if the block is generated in the source file only, or in the
|
||||
header file as well. The two input fields are used to enter the line of code
|
||||
before and after the child nodes. Two consecutive Declaration Blocks can be
|
||||
used to generate `#else`/`#elif` style code by leaving the second field of
|
||||
the first node empty.
|
||||
|
||||
\note Declaration Blocks are not smart, and child nodes may still generate
|
||||
unexpected code outside the scope of this block. This may change in future
|
||||
versions of FLUID.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_class Classes
|
||||
|
||||
![](flClass.png) Class
|
||||
|
||||
FLUID can generate code to implement C++ classes. Classes can be used to keep
|
||||
dialogs and groups of UI elements organized. See Widget Class nodes as an
|
||||
alternative to implement compound widgets.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Class nodes can be created at top level or inside a Class or Widget
|
||||
Class node.
|
||||
|
||||
### Children ###
|
||||
|
||||
Class nodes can contain Functions, Declarations, Widgets, Data, and
|
||||
other classes.
|
||||
|
||||
\image html class_panel.png "Class Properties"
|
||||
\image latex class_panel.png "Class Properties" width=7cm
|
||||
|
||||
The *Name:* and *Subclass of:* fields should be set to standard C++ class
|
||||
names.
|
||||
|
||||
Function nodes inside classes are implemented as methods. Constructors and
|
||||
destructors are recognized and implemented as such. Inlined data is declared
|
||||
as a static class member.
|
||||
|
||||
Note that methods without a code or widget node are only declared in the
|
||||
header file, but no code is generated for them in the source file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_widgetclass Widget Class
|
||||
|
||||
![](flWidgetClass.png) Widget Class
|
||||
|
||||
The Widget Class node creates a new widget type by deriving a class from another
|
||||
widget class. These are often compound widgets derived from `Fl_Group`. A less
|
||||
automated but more flexible way to implement compound widgets is the Class node.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Widget Class nodes can be created at top level or inside a Class or Widget
|
||||
Class node.
|
||||
|
||||
### Children ###
|
||||
|
||||
Widget Class nodes can contain Functions, Declarations, Widgets, Data, and
|
||||
other classes.
|
||||
|
||||
### Properties ###
|
||||
|
||||
Widget Class nodes use the Widget panel to edit their properties. The super
|
||||
class can be set in the *C++* tab in the *Class* field. If that field is empty,
|
||||
FLUID derives from `Fl_Group`.
|
||||
|
||||
The Widget Class always creates a constructor with the common widget parameters:
|
||||
```
|
||||
MyWidget::MyWidget(int X, int Y, int W, int H, const char *L)
|
||||
: Fl_Group(X, Y, W, H, L) { ... }
|
||||
```
|
||||
|
||||
If the super class name contains the text `Window`, two more constructors
|
||||
and a common initializer method are created:
|
||||
```
|
||||
MyWidget::MyWidget(int W, int H, const char *L) :
|
||||
Fl_Window(0, 0, W, H, L) { ... }
|
||||
|
||||
MyWidget::MyWidget() :
|
||||
Fl_Window(0, 0, 480, 320, 0) { ... }
|
||||
|
||||
void MyWidget::_MyWidget() { ... }
|
||||
```
|
||||
|
||||
Code and Widget nodes are then added to the constructor. Function nodes are
|
||||
added as methods to the class. Declarations are added as class members.
|
||||
Data nodes generate static class members.
|
||||
|
||||
It may be useful to design compound widgets with a variable size. The Widget
|
||||
Panel provides a choice menu in the *GUI* tab's *Position* row under
|
||||
*Children*. The options *resize* and *reposition* generate code to fix up
|
||||
the coordinates of the widget after instantiation.
|
||||
|
||||
Note that methods without a code or widget node are only declared in the
|
||||
header file, but no code is generated for them in the source file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_comment Comments
|
||||
|
||||
![](flComment.png) Comment
|
||||
|
||||
This node adds a comment block to the generated source code.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Comment nodes can be added inside Functions, Code Blocks, and Widget Classes.
|
||||
If a Comment node is the top node in a tree, it will appear in the source
|
||||
files even before the `// generated by FLUID ...` line.
|
||||
|
||||
\image html comment_panel.png "Comment Properties"
|
||||
\image latex comment_panel.png "Comment Properties" width=9cm
|
||||
|
||||
Comment blocks are generated by adding `// ` to the start of each line unless
|
||||
the first line of a comment starts with `/``*`. In that case, FLUID assumes
|
||||
a correct block comment and will copy the text verbatim.
|
||||
|
||||
Comments can be generated in the header file, the source file, or both.
|
||||
|
||||
FLUID keeps a small database of predefined comments. Users can add reoccurring
|
||||
comment blocks, license information for example, to this database via the
|
||||
pulldown menu.
|
||||
|
||||
Comments can also be imported from an external file.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section functional_data Inlined Data
|
||||
|
||||
![](flData.png) Inlined Data
|
||||
|
||||
The Data node makes it easy to inline data from an external file into the
|
||||
source code.
|
||||
|
||||
### Parents ###
|
||||
|
||||
Data nodes can be added at the top level or inside Widget Classes, Classes,
|
||||
and Declaration Blocks.
|
||||
|
||||
\image html data_panel.png "Data Properties"
|
||||
\image latex data_panel.png "Data Properties" width=7cm
|
||||
|
||||
At top level, or inside a Declaration Block, Data can be declared *in source
|
||||
file only*, *static in source file*, or *in source and extern in header*.
|
||||
|
||||
If Data is inside a Class node, it is always declared `static`. The user can
|
||||
select *private*, *protected*, or *public*.
|
||||
|
||||
Data in binary mode will be stored in an `unsigned char` array. The data size
|
||||
can be queried with `sizeof()`. In Text mode, it will be stored as `const
|
||||
char*` and terminated with a `NUL` character.
|
||||
|
||||
In compressed mode, data will be compressed with zlib `compress()` and stored
|
||||
in an `unsigned char` array. A second variable, holding the original data size,
|
||||
is declared `int` by appending `_size` to the variable name.
|
||||
|
||||
```
|
||||
// .cxx
|
||||
int myInlineData_size = 12034;
|
||||
unsigned char myInlineData[380] = { 65, 128, ... };
|
||||
```
|
||||
|
||||
The Variable Name should be a regular C++ name. The Filename field expects
|
||||
the path and name of a file, relative to the location of the .fl file.
|
||||
|
||||
*/
|
57
fluid/documentation/src/page_interactive.dox
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
|
||||
\page page_interactive Interactive Mode
|
||||
|
||||
\tableofcontents
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
In interactive mode, FLUID allows users to construct and modify their GUI
|
||||
design by organizing widgets hierarchically through drag-and-drop actions.
|
||||
The project windows provide a live preview of the final UI layout.
|
||||
Most widget attributes can be adjusted in detail using the
|
||||
\ref page_widget_panel.
|
||||
|
||||
Users can also incorporate C++ coding elements such as functions, code blocks,
|
||||
and classes. FLUID supports the integration of external sources, for
|
||||
example images, text, or binary data, by embedding them directly into the
|
||||
generated source code.
|
||||
|
||||
\image html fluid_gui_overview_800.png
|
||||
\image latex fluid_gui_overview_800.png "FLUID Overview"
|
||||
|
||||
A typical FLUID session manages the widget hierarchy in the main application
|
||||
window on the left. The project file name is shown in the title bar. In the
|
||||
example above, we edit the FLTK _Preferences_ example file
|
||||
`test/preferences.fl`.
|
||||
|
||||
\see \ref page_main_window
|
||||
|
||||
The layout editor window left of center, titled
|
||||
"My Preferences" shows the GUI design as it will be generated by the C++
|
||||
source file. The widgets "shower", "shave", and "brush teeth" are shown
|
||||
in their selected state and can now be resized or moved by grabbing any of
|
||||
the red boxes around the selection frame.
|
||||
|
||||
\see \ref page_edit_window
|
||||
|
||||
To the right, we have the "Widget Properties" panel. We can use this to
|
||||
edit many more parameters of the selected widget. If multiple widgets are
|
||||
selected, changes are applied to all of them where appropriate.
|
||||
|
||||
\see \ref page_widget_panel
|
||||
|
||||
The Widget Bin at the top is an optional tool bar (__Edit > Show Widget Bin__,
|
||||
Alt-B). It gives quick access to all widget and code types. Widgets can
|
||||
be added by clicking onto the tool, or by dragging them out of the tool box
|
||||
into the layout editor.
|
||||
|
||||
\see \ref page_widgetbin_panel
|
||||
|
||||
The optional panel on the right shows a live source code preview. This is
|
||||
very helpful for verifying how changes in the GUI will be reflected in the
|
||||
generated C++ code (__Edit > Show Code View__, Alt-C).
|
||||
|
||||
\see \ref page_codeview_panel
|
||||
|
||||
*/
|
69
fluid/documentation/src/page_introduction.dox
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
|
||||
\page page_introduction Introduction
|
||||
|
||||
\tableofcontents
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\image latex fluid-128.png "FLUID" width=3cm
|
||||
|
||||
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 an FLTK based graphical user interface
|
||||
for an application.
|
||||
|
||||
The FLTK programming manual is available at https://www.fltk.org/documentation.php .
|
||||
|
||||
This manual provides instructions on launching FLUID as a command line tool
|
||||
and integrating `.fl` project files into the application build process.
|
||||
FLTK utilizes _CMake_, but other build systems and IDEs capable of running
|
||||
external tools can also build applications based on FLUID.
|
||||
|
||||
The majority of the manual focuses on using FLUID as an interactive GUI
|
||||
design tool. It covers an overview of windows, menu items, and dialog boxes,
|
||||
detailing how to create visually appealing and consistent user experiences
|
||||
through drag and drop functionality, a "what you see is what you get" editor,
|
||||
and alignment tools. The \ref page_setting_dialog will detail the process of initiating
|
||||
a new project, creating an alignment template, and incorporating
|
||||
internationalization.
|
||||
|
||||
Several tutorials will explain how to generate small apps in FLUID alone,
|
||||
and how to create more complex user interfaces, followed by some advanced
|
||||
subjects like creating integrated reusable widget classes.
|
||||
|
||||
The appendices contain additional technical information for reference.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
|
||||
\section introduction_workflow Workflow
|
||||
|
||||
FLUID stores user interface designs within `.fl` project files. These files
|
||||
are transformed into a binary application through a multi-step process.
|
||||
Initially, FLUID converts `.fl` files into C++ source and header files.
|
||||
Subsequently, these files are compiled into object files, which are then
|
||||
linked with other object files to form an executable binary.
|
||||
FLUID-generated header files give access to UI elements from other C++ modules
|
||||
within the project. FLUID can also generate forward declarations to
|
||||
variables and callback functions that are defined and implemented in other
|
||||
C++ modules.
|
||||
|
||||
\image html fluid_flow_chart_800.png "FLUID Workflow"
|
||||
\image latex fluid_flow_chart.png "FLUID Workflow"
|
||||
|
||||
Small applications can be fully designed and developed with FLUID alone.
|
||||
Users have the option to include shell scripts in FLUID projects, enabling
|
||||
them to directly call compilers and linkers to produce the binaries.
|
||||
|
||||
For medium-sized projects, a build system such as _CMake_ or an IDE
|
||||
with integrated build setup is recommended. FLUID in interactive mode
|
||||
can pre-generate C++ code files for direct compilation by the IDE.
|
||||
|
||||
In larger projects, FLUID projects frequently reference external resources
|
||||
such as graphics, binary data, and internationalized text.
|
||||
In such scenarios, it is very useful to distribute the `.fl` project files
|
||||
instead of prebuilt source files. FLUID in command-line mode can then be
|
||||
called as an external tool, dynamically generating C++ source code from all
|
||||
external resources at build time.
|
||||
|
||||
*/
|
371
fluid/documentation/src/page_main_window.dox
Normal file
@ -0,0 +1,371 @@
|
||||
/**
|
||||
|
||||
\page page_main_window Main Application Window
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\image html main_window.png "Main Application Window"
|
||||
\image latex main_window.png "Main Application Window" width=5cm
|
||||
|
||||
A FLUID project is a hierarchy of nodes. Each node holds information to
|
||||
generate C++ source code which in turn generates the user interface that
|
||||
is created in the layout editor windows. Projects usually define one or more
|
||||
functions. These functions can generate one or more
|
||||
FLTK windows and all the widgets that go inside those windows.
|
||||
|
||||
The FLUID Main Window is split into three parts. The title bar shows the
|
||||
status of the source and project files. The menu bar provides a wealth of
|
||||
menu items for all major actions in FLUID. The biggest part of the
|
||||
app window is the widget browser, a tree structure that lists every code
|
||||
node and widget in the project.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section main_titlebar Title Bar
|
||||
|
||||
\image html main_titlebar.png
|
||||
\image latex main_titlebar.png "Title Bar" width=5cm
|
||||
|
||||
The title bar shows the status of the project file, _function_panel.fl_ in this
|
||||
case, followed by an asterisk if the project was changed after it was saved.
|
||||
If the asterisk shows, FLUID will ask the user to save changes before closing
|
||||
the project, loading another project, or starting a new one. Pressing `Ctrl-S`
|
||||
will save the project and make the asterisk disappear.
|
||||
|
||||
The _.cxx_ in the title bar reflects the status of header and source files
|
||||
in relation to the project. A trailing asterisk indicates that the project and code
|
||||
files differ. Pressing `Ctrl-Shift-C` to write the code files will make this
|
||||
asterisk go away.
|
||||
|
||||
\note FLUID currently supports only one open project at a time.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section main_menubar Application Menu Bar
|
||||
|
||||
\image html main_menubar.png
|
||||
\image latex main_menubar.png "Main Menu" width=5cm
|
||||
|
||||
The menu bar is the true control center of FLUID. All actions start here.
|
||||
|
||||
The *File* menu offers the common file operation for FLUID projects. Projects
|
||||
can be loaded, merged, and saved. *Print* will print a snapshot of all open
|
||||
project windows.
|
||||
The *New From Template* item opens a dialog that provides access to a small
|
||||
number of sample projects. More projects can be added using *Save as Template*.
|
||||
|
||||
Use *Write Code* to write the header and source code files, and *Write Strings*
|
||||
to write the translation file if one of the internationalization options
|
||||
is active.
|
||||
|
||||
The *Edit* menu is mainly used to manipulate widgets within the widget tree.
|
||||
The bottom entries toggle various dialogs and pop up the settings panel.
|
||||
|
||||
The *New* menu holds a list of all widgets that can be used in FLUID. They
|
||||
are grouped by functionality, very similarly to the widget bin. New widgets are
|
||||
added inside or right after the selected widget. If the parent widget is not
|
||||
compatible, FLUID tries to find another location for the widget. If that also
|
||||
fails, FLUID will pop up a dialog, describing the required parent type.
|
||||
|
||||
The *Layout* menu is used to adjust the position and size of widgets in
|
||||
relation to each other.
|
||||
|
||||
The *Shell* menu gives quick access to user definable shell scripts. Note that
|
||||
scripts can be stored inside `.fl` project files.
|
||||
|
||||
\see \ref main_menu_items
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section main_widget_browser Widget Tree View
|
||||
|
||||
\image html main_browser.png
|
||||
\image latex main_browser.png "Widget Browser" width=5cm
|
||||
|
||||
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 <tt>.cxx</tt> 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. <i>Tab groups</i> provide the
|
||||
well-known file-card tab interface.
|
||||
|
||||
Widgets are shown in the browser by either their \e name (such
|
||||
as "Button emergency_btn" in the example), or by their \e type
|
||||
and \e label (such as "Double_Window "My Main Window"").
|
||||
|
||||
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).
|
||||
|
||||
Nodes are moved within their group using
|
||||
`F2` and `F3`. They can be grouped and ungrouped with `F7` and `F8`, and
|
||||
relocated by selecting them and using cut, copy, and paste.
|
||||
|
||||
Every line in the browser has the same basic format. The level of indentation
|
||||
reflects the depth of a node within the tree.
|
||||
|
||||
The triangle appears only in front of nodes that can have children. If it is
|
||||
white, the group has no children. If it is black, there is at least one child.
|
||||
If the triangle points to the right, the children are hidden in the tree view.
|
||||
Click the triangle to reveal all children.
|
||||
|
||||
The icon to the right is a small representation of the base type of the node.
|
||||
Widgets are gray, windows have a blue title bar, and functional nodes are
|
||||
green. If the widget is static or private, a padlock icon will appear in the
|
||||
bottom right corner of the type icon.
|
||||
|
||||
The content of text fields depends on the node type. If a comment is set, it
|
||||
appears in green over the text. Widgets combine their type (bold black) and
|
||||
label text (red), or their C++ name in black (not bold).
|
||||
|
||||
All colors and font styles can be customized in the User tab of the
|
||||
Settings panel.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section main_menu_items The Main Menu
|
||||
|
||||
The "New" menu of the main menu bar is duplicated as a pop-up menu on any
|
||||
layout editor window. The shortcuts for all the menu items work in any
|
||||
window. The menu items are:
|
||||
|
||||
__File > New (Ctrl+n)__: Close the current project and start a new, empty project.
|
||||
|
||||
__File > Open... (Ctrl+o)__: Discard the current editing session and read in a
|
||||
different `.fl` project file. You are asked for confirmation if you have
|
||||
changed the current file.
|
||||
|
||||
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!
|
||||
|
||||
__File > Insert... (Ctrl+i)__: Insert 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.
|
||||
|
||||
__File > Save (Ctrl+s)__: Write the current data to the `.fl` file. If the
|
||||
file is unnamed then FLUID will ask for a filename.
|
||||
|
||||
__File > Save As... (Ctrl+Shift+S)__: Ask for a new filename and
|
||||
save the file.
|
||||
|
||||
__File > Save A Copy...__: Save a copy of the `.fl` data to a different file.
|
||||
|
||||
__File > Revert...__: Revert the `.fl` data to the previously saved state.
|
||||
|
||||
__File > New From Template...__: 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.
|
||||
|
||||
__File > Save As Template...__: Save the current project as a starting point
|
||||
for future projects.
|
||||
|
||||
__File > Print... (Ctrl-P)__: Generate a printout containing all currently
|
||||
open windows within your project.
|
||||
|
||||
__File > Write Code (Ctrl+Shift+C)__: Write the GUI layout as a `.cxx` and
|
||||
`.h` file. These are exactly the same as the files you get when you run
|
||||
FLUID with the `-c` switch.
|
||||
|
||||
The output file names are the same as the `.fl` file, with the leading directory
|
||||
and trailing ".fl" stripped, and ".h" or ".cxx" appended.
|
||||
|
||||
__File > Write Strings (Ctrl+Shift+W)__: Write a message file for all of the
|
||||
text labels and tooltips defined in the current file.
|
||||
|
||||
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 setting_i18n "Internationalization Mode".
|
||||
|
||||
__File > Quit (Ctrl+q)__: Exit FLUID. You are asked for confirmation if you
|
||||
have changed the current file.
|
||||
|
||||
__Edit > Undo (Ctrl+z)__ and __Redo (Shift+Ctrl+z)__: FLUID saves the project
|
||||
state for undo and redo operations after every major change.
|
||||
|
||||
__Edit > Cut (Ctrl+x)__: Delete the selected widgets and all of their children.
|
||||
These are saved to a "clipboard" file and can be pasted back into any
|
||||
FLUID window.
|
||||
|
||||
__Edit > Copy (Ctrl+c)__: Copy the selected widgets and all of their children
|
||||
to the "clipboard" file.
|
||||
|
||||
__Edit > Paste (Ctrl+v)__: Paste the widgets from the clipboard file.
|
||||
|
||||
If the widget is a window, it is added to whatever function
|
||||
is selected, or contained in the current selection.
|
||||
|
||||
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.
|
||||
|
||||
To avoid confusion, it is best to select exactly one widget
|
||||
before doing a paste.
|
||||
|
||||
Cut/paste is the only way to change the parent of a
|
||||
widget.
|
||||
|
||||
__Edit > Duplicate (Ctrl-u)__: Duplicate all currently selected widgets and
|
||||
insert the duplicates after the last selected widget.
|
||||
|
||||
__Edit > Delete__: Delete all selected widgets.
|
||||
|
||||
__Edit > Select All (Ctrl+a)__: Select all widgets in the same group as the
|
||||
current selection.
|
||||
|
||||
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.
|
||||
|
||||
__Edit > Properties... (F1 or double click)__: Display the current widget in
|
||||
the widgets panel. If the widget is a window and it is not visible then the
|
||||
window is shown instead.
|
||||
|
||||
__Edit > Sort__: Sort 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.
|
||||
|
||||
__Edit > Earlier (F2)__: Move 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.
|
||||
|
||||
__Edit > Later (F3)__: Move all of the selected widgets one later in order
|
||||
among the children of their parent (if possible).
|
||||
|
||||
__Edit > Group (F7)__: Create a new Fl_Group and make all the currently
|
||||
selected widgets children of it.
|
||||
|
||||
__Edit > Ungroup (F8)__: Delete the parent group if all the children of a
|
||||
group are selected.
|
||||
|
||||
__Edit > Show or Hide Overlays (Ctrl+Shift+O)__: Toggle 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.
|
||||
|
||||
__Edit > Show or Hide Guides (Ctrl+Shift+G)__: Guides can be used to arrange a
|
||||
widget layout easily and consistently. They indicate preferred widget
|
||||
positions and sizes with user definable margins, grids, and gap sizes. See
|
||||
the "Layout" tab in the "Settings" dialog, \ref setting_layout.
|
||||
|
||||
This menu item enables and disables guides and the snapping action when dragging
|
||||
widgets and their borders.
|
||||
|
||||
__Edit > Show or Hide Restricted (Ctrl+Shift+R)__: The behavior of overlapping
|
||||
widgets in FLTK is undefined. By activating this button, a hatch pattern is
|
||||
shown, highlighting areas where restricted or undefined behavior may occur.
|
||||
|
||||
__Edit > Show or Hide Widget Bin (Alt+B)__: 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.
|
||||
|
||||
__Edit > Show or Hide Code View (Alt+C)__: Shows or hide
|
||||
the source code preview window. Any changes to the layout or code in the layout
|
||||
editor can be previewed and verified immediately in the Code View window.
|
||||
|
||||
__Edit > Settings... (Alt+p)__: Open the application and project settings
|
||||
dialog: \ref page_setting_dialog
|
||||
|
||||
__New > Code > Function__: Create 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.
|
||||
|
||||
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 ).
|
||||
|
||||
It is possible to make the <tt>.cxx</tt> 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.
|
||||
|
||||
You can change the function name by double-clicking on the
|
||||
function.
|
||||
|
||||
\see \ref functional_function
|
||||
|
||||
__New > Group > Window__: Create 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 480x320. You can resize it to
|
||||
whatever size you require.
|
||||
|
||||
The widget panel will also appear and is described later in
|
||||
this chapter.
|
||||
|
||||
__New > ...__: 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.
|
||||
|
||||
When you create the widget you will get the widget's control
|
||||
panel, which is described later in this chapter.
|
||||
|
||||
__Layout > Align > ...__: Align all selected widgets to the first widget in
|
||||
the selection.
|
||||
|
||||
__Layout > Space Evenly > ...__: Space all selected widgets evenly inside the
|
||||
selected space. Widgets will be sorted from first to last.
|
||||
|
||||
__Layout > Make Same Size > ...__: Make all selected widgets the same size as
|
||||
the first selected widget.
|
||||
|
||||
__Layout > Center in Group > ...__: Center all selected widgets relative to
|
||||
their parent widget
|
||||
|
||||
__Layout > Grid and Size Settings... (Ctrl+g)__: Display the grid settings
|
||||
panel. See \ref setting_layout .
|
||||
|
||||
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 windows, gaps
|
||||
between widget, and/or 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 included layout suites. `FLTK` was used to design FLUID and
|
||||
other included apps, and `Grid` is a more rigid grid layout. Users can add
|
||||
more suites, import and export them, and include them into their `.fl`
|
||||
project files.
|
||||
|
||||
__Shell > Customize... (Alt+x)__: Displays the shell command settings panel.
|
||||
Shell commands are commonly used to run a 'make' script to compile the FLUID
|
||||
output. See \ref setting_shell .
|
||||
|
||||
__Help > About FLUID__: Pops up a panel showing the version of FLUID.
|
||||
|
||||
*/
|
338
fluid/documentation/src/page_setting_dialog.dox
Normal file
@ -0,0 +1,338 @@
|
||||
/**
|
||||
|
||||
\page page_setting_dialog Settings Dialog
|
||||
|
||||
\tableofcontents
|
||||
|
||||
<img src="w_settings.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings.png "Settings Dialog" width=7cm
|
||||
|
||||
The *Settings* dialog combines application preferences
|
||||
and project settings in a compact set of six tabs.
|
||||
|
||||
The *General* tab contains a collection of application wide settings. They are
|
||||
stored as user preferences.
|
||||
|
||||
The *Project* tab holds settings for the current project. They are saved with
|
||||
the `.fl` file.
|
||||
|
||||
The *Layout* tab manages databases of preferred widget alignment. These
|
||||
preferences can be saved per user, or as part of the project, or exported for
|
||||
use in other projects.
|
||||
|
||||
The *Shell* tab manages a database of quick access shell commands and scripts.
|
||||
Shell commands can be saved as a user preference and also as part of the
|
||||
`.fl` project file.
|
||||
|
||||
The *Locale* tab sets the method of internationalizing texts in the project,
|
||||
commonly used for labels and tooltips.
|
||||
|
||||
The *User* tab manages customization of fonts and colors in the widget browser.
|
||||
These settings are stored as user preferences.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_general Application Settings
|
||||
|
||||
<img src="w_settings_general_tab.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings_general_tab.png "General Settings Tab" width=7cm
|
||||
|
||||
__Scheme__:
|
||||
|
||||
Select one of the graphics schemes built into FLTK. It's helpful
|
||||
to verify the look of various schemes for an application design.
|
||||
|
||||
__Options__:
|
||||
|
||||
Various options to make life as a developer more convenient.
|
||||
|
||||
__Recent Files__:
|
||||
|
||||
FLUID keeps track of recently opened files.
|
||||
|
||||
__External Editor__:
|
||||
|
||||
Users that don't like the built-in FLUID code editor can enter a shell command
|
||||
here that opens the content of Code nodes in an external editor. FLUID does
|
||||
its best to pick up on changed content or when the editor is closed.
|
||||
|
||||
__Overlays__:
|
||||
|
||||
The *Position Guides* are little red arrows that indicate if snap points are
|
||||
found. See the *Layout* tab for details. *Restricted Areas* are areas where
|
||||
widgets from within the same group overlap. They are visible in the project
|
||||
window as a diagonally hashed pattern. *Ghosted Group Outlines* show faint
|
||||
frames around groups that would otherwise be invisible in the project window.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_project Project Settings
|
||||
|
||||
<img src="w_settings_project_tab.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings_project_tab.png "Project Settings Tab" width=7cm
|
||||
|
||||
__Header File__, __Code File__:
|
||||
|
||||
These fields are used to build the file path and name of the generated header
|
||||
and source file. If one field is empty the value defaults to `.h` and `.cxx`
|
||||
respectively. If a name starts with a `.`, FLUID assumes that the rest of the
|
||||
text is a file extension. The code file name is then generated by replacing
|
||||
the extension of the `.fl` project file name.
|
||||
|
||||
\todo Document the exact way the source and header file paths are calculated
|
||||
for interactive FLUID, and for FLUID launched from the command line.
|
||||
|
||||
__Include Header from Code__:
|
||||
|
||||
If checked, the statement to include the header file is automatically
|
||||
generated in one of the first lines of the source file.
|
||||
|
||||
__Menu shortcuts use FL_COMMAND__:
|
||||
|
||||
Setting this option will replace FL_CTRL and FL_META as a modifier for
|
||||
shortcuts with the platform aware modifiers FL_COMMAND and FL_CONTROL, making
|
||||
shortcuts more portable between macOS and Windows/Linux.
|
||||
|
||||
__allow Unicode__:
|
||||
|
||||
If unchecked, Unicode characters in strings are escaped. If checked, the Unicode
|
||||
character is stored in the source code in UTF-8 encoding.
|
||||
|
||||
__avoid early include__:
|
||||
|
||||
FLUID by default includes `<FL/Fl.H>` early in the header file. If this option
|
||||
is checked, users can include other files before including the FL header. The
|
||||
user must then include `<FL/Fl.H>` later using a Declaration node.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_layout Layout Preferences
|
||||
|
||||
<img src="w_settings_layout_tab.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings_layout_tab.png "Layout Settings Tab" width=7cm
|
||||
|
||||
Layouts are a collection of hints that help when interactively positioning and
|
||||
resizing widgets in the project window. Layouts come in a set of three for
|
||||
the application window, for dialog boxes, and for toolboxes.
|
||||
|
||||
__Layout__:
|
||||
|
||||
The layout pulldown menu lets users choose from a list of existing layouts.
|
||||
The plus button creates a new set of layouts based on the currently selected
|
||||
layout.
|
||||
The pulldown menu has items to rename, load, and save layouts. It can also
|
||||
change the location where the layout is stored. The FLUID beaker is for
|
||||
layouts that are predefined in FLUID, the portrait icon stores as user
|
||||
preference, the document
|
||||
icon stores the layout in the `.fl` file, and the disk icon lets users store
|
||||
layout in external files.
|
||||
|
||||
__Window Margin and Grid__:
|
||||
|
||||
Snap widget position to that margin in relation to the window. The grid
|
||||
snaps widgets to fixed intervals.
|
||||
|
||||
__Group Margin and Grid__:
|
||||
|
||||
Snap widget position to that margin in relation to the group. The grid
|
||||
snaps widgets to fixed intervals relative to the top left of the group.
|
||||
|
||||
__Tabs Margin__:
|
||||
|
||||
Snap the tab inside `Fl_Tabs` to the tab border and the offset given in
|
||||
Margins.
|
||||
|
||||
__Widget Minimum, Increment, and Gap__:
|
||||
|
||||
_Minimum_ sets the minimal width of a widget. _Increment_ is the size multiplier
|
||||
added to the _Minimum_ value. _Gap_ is the preferred distance to other widgets
|
||||
in the same group.
|
||||
|
||||
__Label Font__, __Text Font__:
|
||||
|
||||
The preferred label and text font and size for new widgets.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_shell Shell Commands
|
||||
|
||||
<img src="w_settings_shell_tab.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings_shell_tab.png "Shell Settings Tab" width=7cm
|
||||
|
||||
__Shell Command List__:
|
||||
|
||||
A list of all currently available shell commands. The portrait symbol in front
|
||||
of the name indicates that the script is stored in the user preferences. The
|
||||
document symbol saves them within the `.fl` project file.
|
||||
|
||||
`[+]` adds a fresh new script to the list, `[++]` duplicates the currently
|
||||
selected script. `[DEL]` deletes it, and `[v]` offers import and export
|
||||
functionality. The `[T]` button shows the terminal window, and finally the
|
||||
`[Run]` button runs the selected shell script.
|
||||
|
||||
Selecting a shell script will fill in the bottom half of the dialog.
|
||||
|
||||
__Name__:
|
||||
|
||||
This is the name of the script as it appears in the Shell Command List.
|
||||
|
||||
__Menu Label__:
|
||||
|
||||
Shell scripts that match the *Condition* flag are also available for quick
|
||||
access in the *Shell* menu in the main window and via shortcut key
|
||||
combinations. This is the text that is used for the menu entry.
|
||||
|
||||
__Shortcut__:
|
||||
|
||||
Assign a keyboard shortcut to this shell script for even faster access. FLUID
|
||||
does not check if a shortcut is already used elsewhere. Try to avoid
|
||||
collisions, especially when the script is part of a project file.
|
||||
|
||||
__Store__:
|
||||
|
||||
Choose where to store the settings of this shell script, either in the user
|
||||
preferences or as part of the `.fl` project file.
|
||||
|
||||
__Condition__:
|
||||
|
||||
Shell scripts can be quite different for different platforms hosting FLUID.
|
||||
This choice limits scripts to specific platforms. Multiple scripts can have
|
||||
the same shortcut if they have different conditions.
|
||||
|
||||
__Shell Script__:
|
||||
|
||||
This is a text field for the shell script. The `[v]` pulldown menu has a list
|
||||
of variables that are replaced with the corresponding value before running
|
||||
the script. The zoom button gives access to a much larger shell script editor.
|
||||
|
||||
The options below are a list of actions that can be executed before running
|
||||
the script.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_i18n Internationalization
|
||||
|
||||
The *Locale* tab can be used to configure optional internationalization.
|
||||
FLUID supports GNU `gettext` and POSIX `catgets`.
|
||||
|
||||
FLUID supports internationalization (I18N for short) of label
|
||||
strings and tooltips used by widgets. The GNU gettext option also
|
||||
supports deferred translation of statically initialized menu item
|
||||
labels. The setting panel (`Alt+p`) provides access
|
||||
to the I18N options.
|
||||
|
||||
\image html w_settings_i18n_gnu.png
|
||||
\image latex w_settings_i18n_gnu.png "I18N With GNU gettext" width=7cm
|
||||
|
||||
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 GNU gettext option adds some preprocessor code to the source file:
|
||||
```
|
||||
#include <libintl.h>
|
||||
#ifndef gettext_noop
|
||||
# define gettext_noop(text) text
|
||||
#endif
|
||||
```
|
||||
and the gettext call around strings in the source code:
|
||||
```
|
||||
new Fl_Button(50, 50, 54, 40, "Button");
|
||||
// ->
|
||||
new Fl_Button(50, 50, 54, 40, gettext("Button"));
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
__Include__: controls the header file to include for
|
||||
I18N; by default this is \b <libintl.h>, the
|
||||
standard I18N file for GNU gettext.
|
||||
|
||||
__Conditional__: If this 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.
|
||||
|
||||
__Function__: controls the function (or macro) that will retrieve the localized
|
||||
message; by default the \p gettext function will be called.
|
||||
|
||||
__Static Function__: 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 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)
|
||||
|
||||
\image html w_settings_i18n_psx.png
|
||||
\image latex w_settings_i18n_psx.png "I18N With POSIX catgets" width=7cm
|
||||
|
||||
The "POSIX catgets" method uses the POSIX catgets function to
|
||||
retrieve a numbered message from a message catalog before
|
||||
calling the widget constructor.
|
||||
|
||||
FLUID's code support for POSIX catgets allows you to use a
|
||||
global message file for all interfaces or a file specific to
|
||||
each <tt>.fl</tt> file; you still need to call
|
||||
\p setlocale() to select the appropriate language.
|
||||
|
||||
This option adds some preprocessor code to the source file:
|
||||
```
|
||||
#include <nl_types.h>
|
||||
// Initialize I18N stuff now for menus...
|
||||
#include <locale.h>
|
||||
static char *_locale = setlocale(LC_MESSAGES, "");
|
||||
static nl_catd _catalog = catopen("", 0);
|
||||
```
|
||||
and the catgets call around strings in the source code:
|
||||
```
|
||||
new Fl_Button(50, 50, 54, 40, "Button");
|
||||
// ->
|
||||
new Fl_Button(50, 50, 54, 40, catgets(_catalog,1,6,"Button"));
|
||||
```
|
||||
|
||||
__Include__: controls the header file to include for
|
||||
I18N; by default this is \b <nl_types.h>, the
|
||||
standard I18N file for POSIX catgets.
|
||||
|
||||
__Conditional__: include the header file only if this preprocessor macro is
|
||||
defined.
|
||||
|
||||
__Catalog__: 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
|
||||
<tt>.fl</tt> file.
|
||||
|
||||
__Set__: controls the set number in the catalog file.
|
||||
The default set is 1 and rarely needs to be changed.
|
||||
|
||||
<!-- ---------------------------------------------------------------------- -->
|
||||
\section setting_user User Interface Preferences
|
||||
|
||||
<img src="w_settings_user_tab.png" align="left" hspace="10" vspace="10" />
|
||||
\image latex w_settings_user_tab.png "User Settings Tab" width=7cm
|
||||
|
||||
This tab lets users change the font and color of text in the widget browser.
|
||||
The settings are stored in the user preferences.
|
||||
|
||||
All changes are directly visible in the widget browser.
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
*/
|