FLUID: Adds options to draw ghosted outlines.

This commit is contained in:
Matthias Melcher 2023-11-01 17:22:31 +01:00
parent 5f836377a0
commit aaaf0a0537
14 changed files with 221 additions and 218 deletions

View File

@ -95,11 +95,21 @@ endif (WIN32)
source_group("Header Files" FILES ${HEADERFILES})
# make a group in the IDE for easy access to documentation files
set ( DOC_FILES
Doxyfile
documentation/src/index.dox
documentation/src/code.dox
documentation/src/app_settings.dox
)
source_group("Documentation" FILES ${DOC_FILES})
# Build a local object library to avoid compiling all source files
# for all fluid targets (fluid, fluid-cmd, fluid-shared). This
# library includes everything except the main program (fluid.cxx).
add_library (fluid-lib OBJECT EXCLUDE_FROM_ALL ${CPPFILES} ${HEADERFILES})
add_library (fluid-lib OBJECT EXCLUDE_FROM_ALL ${CPPFILES} ${HEADERFILES} ${DOC_FILES})
# Build fluid with all its variants (fluid-cmd, fluid-shared) ...

View File

@ -49,6 +49,25 @@ void Fl_Grid_Proxy::resize(int X, int Y, int W, int H) {
redraw();
}
/**
Override draw() to make groups with no box or flat box background visible.
*/
void Fl_Grid_Proxy::draw() {
if (show_ghosted_outline) {
if (!box()) {
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
Fl_Grid::draw();
} else if (box() == FL_FLAT_BOX && parent() && parent()->color() == color()) {
Fl_Grid::draw();
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
} else {
Fl_Grid::draw();
}
} else {
Fl_Grid::draw();
}
}
Fl_Grid_Type::Fl_Grid_Type() {
}

View File

@ -28,6 +28,7 @@ class Fl_Grid_Proxy : public Fl_Grid {
public:
Fl_Grid_Proxy(int X,int Y,int W,int H) : Fl_Grid(X,Y,W,H) {}
void resize(int,int,int,int) FL_OVERRIDE;
void draw() FL_OVERRIDE;
};
class Fl_Grid_Type : public Fl_Group_Type

View File

@ -44,7 +44,6 @@ Fl_Group_Type Fl_Group_type; // the "factory"
/**
Override group's resize behavior to do nothing to children by default.
\param[in] X, Y, W, H new size
*/
void Fl_Group_Proxy::resize(int X, int Y, int W, int H) {
@ -56,6 +55,28 @@ void Fl_Group_Proxy::resize(int X, int Y, int W, int H) {
redraw();
}
/**
Override draw() to make groups with no box or flat box background visible.
*/
void Fl_Group_Proxy::draw() {
if (show_ghosted_outline) {
// it would be nice to check if the parent is Fl_Tabs, because the parent
// would then draw the outline... .
if (!box()) {
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
Fl_Group::draw();
} else if (box() == FL_FLAT_BOX && parent() && parent()->color() == color()) {
Fl_Group::draw();
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
} else {
Fl_Group::draw();
}
} else {
Fl_Group::draw();
}
}
/**
\brief Enlarge the group size, so all children fit within.
*/
@ -252,6 +273,25 @@ void Fl_Flex_Proxy::resize(int X, int Y, int W, int H) {
redraw();
}
/**
Override draw() to make groups with no box or flat box background visible.
*/
void Fl_Flex_Proxy::draw() {
if (show_ghosted_outline) {
if (!box()) {
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
Fl_Flex::draw();
} else if (box() == FL_FLAT_BOX && parent() && parent()->color() == color()) {
Fl_Flex::draw();
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
} else {
Fl_Flex::draw();
}
} else {
Fl_Flex::draw();
}
}
Fl_Widget *Fl_Flex_Type::enter_live_mode(int) {
Fl_Flex *grp = new Fl_Flex(o->x(), o->y(), o->w(), o->h());
propagate_live_mode(grp);
@ -598,6 +638,25 @@ void Fl_Tabs_Proxy::resize(int X, int Y, int W, int H) {
redraw();
}
/**
Override draw() to make groups with no box or flat box background visible.
*/
void Fl_Tabs_Proxy::draw() {
if (show_ghosted_outline) {
if (!box()) {
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
Fl_Tabs::draw();
} else if (box() == FL_FLAT_BOX && parent() && parent()->color() == color()) {
Fl_Tabs::draw();
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
} else {
Fl_Tabs::draw();
}
} else {
Fl_Tabs::draw();
}
}
// This is called when user clicks on a widget in the window. See
// if it is a tab title, and adjust visibility and return new selection:
// If none, return o unchanged:
@ -691,3 +750,23 @@ void Fl_Wizard_Proxy::resize(int X, int Y, int W, int H) {
}
redraw();
}
/**
Override draw() to make groups with no box or flat box background visible.
*/
void Fl_Wizard_Proxy::draw() {
if (show_ghosted_outline) {
if (!box()) {
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
Fl_Wizard::draw();
} else if (box() == FL_FLAT_BOX && parent() && parent()->color() == color()) {
Fl_Wizard::draw();
fl_rect(x(), y(), w(), h(), Fl::box_color(fl_color_average(FL_FOREGROUND_COLOR, color(), .1f)));
} else {
Fl_Wizard::draw();
}
} else {
Fl_Wizard::draw();
}
}

View File

@ -41,6 +41,7 @@ class Fl_Group_Proxy : public Fl_Group {
public:
Fl_Group_Proxy(int X,int Y,int W,int H) : Fl_Group(X, Y, W, H) { Fl_Group::current(0); }
void resize(int x, int y, int w, int h) FL_OVERRIDE;
void draw() FL_OVERRIDE;
};
class Fl_Group_Type : public Fl_Widget_Type
@ -94,6 +95,7 @@ class Fl_Flex_Proxy : public Fl_Flex {
public:
Fl_Flex_Proxy(int X,int Y,int W,int H) : Fl_Flex(X, Y, W, H) { Fl_Group::current(0); }
void resize(int x, int y, int w, int h) FL_OVERRIDE;
void draw() FL_OVERRIDE;
};
class Fl_Flex_Type : public Fl_Group_Type
@ -155,6 +157,7 @@ class Fl_Tabs_Proxy : public Fl_Tabs {
public:
Fl_Tabs_Proxy(int X,int Y,int W,int H) : Fl_Tabs(X,Y,W,H) {}
void resize(int,int,int,int) FL_OVERRIDE;
void draw() FL_OVERRIDE;
};
class Fl_Tabs_Type : public Fl_Group_Type
@ -215,6 +218,7 @@ class Fl_Wizard_Proxy : public Fl_Wizard {
public:
Fl_Wizard_Proxy(int X,int Y,int W,int H) : Fl_Wizard(X,Y,W,H) {}
void resize(int,int,int,int) FL_OVERRIDE;
void draw() FL_OVERRIDE;
};
extern const char wizard_type_name[];

View File

@ -795,6 +795,20 @@ void toggle_restricted(Fl_Widget *,void *) {
}
}
/**
\brief User changes settings to show low contrast groups with a ghosted outline.
*/
void toggle_ghosted_outline_cb(Fl_Check_Button *,void *) {
show_ghosted_outline = !show_ghosted_outline;
fluid_prefs.set("show_ghosted_outline", show_ghosted_outline);
for (Fl_Type *o=Fl_Type::first; o; o=o->next) {
if (o->is_a(ID_Window)) {
Fl_Widget_Type* w = (Fl_Widget_Type*)o;
((Overlay_Window*)(w->o))->redraw();
}
}
}
/**
\brief User changes settings to show overlapping and out of bounds widgets.
This is called from the check button in the Settings dialog.

View File

@ -266,6 +266,8 @@ Fl_Check_Button *guides_button=(Fl_Check_Button *)0;
Fl_Check_Button *restricted_button=(Fl_Check_Button *)0;
Fl_Check_Button *ghosted_outline_button=(Fl_Check_Button *)0;
Fl_Group *w_settings_project_tab=(Fl_Group *)0;
static void cb_w_settings_project_tab(Fl_Group* o, void* v) {
@ -2263,6 +2265,14 @@ ps");
restricted_button->callback((Fl_Callback*)toggle_restricted_cb);
o->value(show_restricted);
} // Fl_Check_Button* restricted_button
{ Fl_Check_Button* o = ghosted_outline_button = new Fl_Check_Button(120, 340, 200, 20, "Show Low Contrast Groups Ghosted");
ghosted_outline_button->tooltip("groups with no box type or flat boxtypes without contrast will be rendered wi\
th a dim outline in the editing window only");
ghosted_outline_button->down_box(FL_DOWN_BOX);
ghosted_outline_button->labelsize(11);
ghosted_outline_button->callback((Fl_Callback*)toggle_ghosted_outline_cb);
o->value(show_ghosted_outline);
} // Fl_Check_Button* ghosted_outline_button
{ Fl_Box* o = new Fl_Box(120, 530, 200, 10);
o->hide();
Fl_Group::current()->resizable(o);

View File

@ -145,7 +145,7 @@ script_input->linenumber_width(60);
script_input->linenumber_size(script_input->Fl_Text_Display::textsize());} {}
}
Function {make_settings_window()} {open selected
Function {make_settings_window()} {open
} {
Fl_Window settings_window {
label {FLUID Settings} open
@ -280,6 +280,12 @@ Examples:
tooltip {show overlapping and out of bounds areas, show unfilled areas in Fl_Pack groups} xywh {120 320 200 20} down_box DOWN_BOX labelsize 11
code0 {o->value(show_restricted);}
}
Fl_Check_Button ghosted_outline_button {
label {Show Low Contrast Groups Ghosted}
callback toggle_ghosted_outline_cb selected
tooltip {groups with no box type or flat boxtypes without contrast will be rendered with a dim outline in the editing window only} xywh {120 340 200 20} down_box DOWN_BOX labelsize 11
code0 {o->value(show_ghosted_outline);}
}
Fl_Box {} {
xywh {120 530 200 10} hide resizable
}

View File

@ -67,6 +67,8 @@ extern void toggle_guides_cb(Fl_Check_Button*, void*);
extern Fl_Check_Button *guides_button;
extern void toggle_restricted_cb(Fl_Check_Button*, void*);
extern Fl_Check_Button *restricted_button;
extern void toggle_ghosted_outline_cb(Fl_Check_Button*, void*);
extern Fl_Check_Button *ghosted_outline_button;
extern Fl_Group *w_settings_project_tab;
extern Fl_Input *header_file_input;
extern Fl_Input *code_file_input;

View File

@ -2,205 +2,49 @@
/**
\page codeNodes Code Nodes
\page appSettings Fluid Application Settings
\tableofcontents
\tableofcontents
\section function Functions and Methods
\section schemes Schemes
![](flFunction.png) Functions
Write me... .
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.
\section options Options
## Parents ##
Write me... .
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.
\section external_editor External Editor
## Children ##
Write me... .
Function nodes can contain code nodes and widget trees. The topmost node of a
widget tree must be a window.
If the function node has no children, only a forward declaration will be
created in the header, but no source code will be generated.
\section overlays Overlay
\image html flFunctionDialog.png "Function/Method Properties"
\image latex flFunctionDialog.png "Function/Method Properties"
## Show positioning guides ##
## Declaring a Function ##
When enabled, FLUID will use the existing Layout settings to propose widget
positions and dimensions that align with other widgets within the project.
It displays red indicator guides on the scene to illustrate the widget's
relationship with its neighboring elements. If you drag the widgets with the
mouse, they will automatically align with these preferred positions.
A function node at the top level or inside a declaration block generates a C
or C++ function.
## Show restricted areas ##
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();
}
```
When selected, FLUID will display a hash pattern when widgets overlap with
other widgets within the same group or extend beyond the boundaries of their
parent group. Widgets that are invisible will not trigger this effect.
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 omited.
This is used to reference functions in other modules.
```
// .h
void make_window();
```
## Ghosting low contrast groups ##
If the function contains one or more Code nodes, an implementation will also 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
}
```
Occasionally, newly created groups can be inconspicuous during the editing
process when their background matches that of the parent and no visible
box is drawn. However, if you enable the "Show Low Contrast Groups Ghosted"
option, groups that lack a box type or have a flat box type with the same
color as the parent will be displayed with a faint outline
in the editing window.
If the function contains a widget, a pointer to the first widget
will be created. The default return type will match the type of the
first widget, and a pointer to the widget will be returned.
```
// .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 declare the function `static` in the
source file. No prototype will be generated in the header.
```
// .cxx
static Fl_Window* make_window() { ...
```
If the *C* option is checked, the function will be declared as a plain C
function in the header file.
The options *local* and *C* together are not supported.
```
// .h
extern "C" { void my_plain_c_function(); }
```
## 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 on 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
&#42;/
Fl_Window* make_window() {
```
Fluid recognizes default values in the argument list and geneartes 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 code C Source Code
![](flCode.png) Code
...write me.
### Parents ###
...write me.
### Children ###
...write me.
\section codeblock Code Block
\section declaration Declaration
\section declarationblock Declaration Block
\section class Classes
\section widgetclass Widget Class
\section comment Comments
\section inlineddata Inlined Data
During live resizing and after project compilation, all groups will be
rendered as originally designed, without the ghosted outline.
*/

View File

@ -4,8 +4,7 @@
\page codeNodes Code Nodes
Overview of code nodes.
\tableofcontents
\section function Functions and Methods
@ -15,12 +14,14 @@ 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 ###
## 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 ###
## Children ##
Function nodes can contain code nodes and widget trees. The topmost node of a
widget tree must be a window.
If the function node has no children, only a forward declaration will be
@ -39,8 +40,8 @@ If the *Name* field is left empty, Fluid will generate a typical 'main()' functi
```
// .cxx
int main(int argc, char **argv) {
/* code generated by children */
w->show(argc, argv); /* <-- code generated if function has a child widget */
// code generated by children
w->show(argc, argv); // <-- code generated if function has a child widget
Fl::run();
}
```
@ -59,7 +60,7 @@ overrides the default type.
```
// .cxx
void make_window() {
/* code generated by children */
// code generated by children
}
```
@ -75,9 +76,8 @@ Fl_Window* make_window();
// .cxx
Fl_Window* make_window() {
Fl_Window* w;
/* code generated by children:
* w = new Fl_Window(...)
*/
// code generated by children:
// w = new Fl_Window(...)
return w;
}
```
@ -136,7 +136,7 @@ public:
// .cxx
Fl_Double_Window* UserInterface::make_window() {
Fl_Double_Window* w;
/* code generated by children */
// code generated by children
return w;
}
```
@ -155,13 +155,13 @@ is no text after the keyword.
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 ahead of thefunction.
in the source file before the function.
```
// .cxx
/*
My multilen comment
will be here
*/
//
// My multilen comment will be here... .
// Fluid may actually use C style comment markers.
//
Fl_Window* make_window() {
```
@ -179,6 +179,14 @@ creates an inlined function in the header file.
...write me.
### Parents ###
...write me.
### Children ###
...write me.
\section codeblock Code Block
\section declaration Declaration

View File

@ -2,25 +2,25 @@
/**
\mainpage Fluid User Manual and Developer Overview
\mainpage Fluid User Manual
\subpage function
\subpage codeNodes
\subpage code
- \ref function
- \ref code
- \ref codeblock
- \ref declaration
- \ref declarationblock
- \ref class
- \ref widgetclass
- \ref comment
- \ref inlineddata
\subpage codeblock
\subpage appSettings
\subpage declaration
\subpage declarationblock
\subpage class
\subpage widgetclass
\subpage comment
\subpage inlineddata
- \ref schemes
- \ref options
- \ref overlays
*/

View File

@ -85,6 +85,10 @@ int show_guides = 1;
/// within an Fl_Tile that are not covered by children.
int show_restricted = 1;
/// Show a ghosted outline for groups that have very little contrast.
/// This makes groups with NO_BOX or FLAT_BOX better editable.
int show_ghosted_outline = 1;
/// Show widget comments in the browser, saved in app preferences.
int show_comments = 1;
@ -1855,6 +1859,7 @@ void make_main_window() {
if (!batch_mode) {
fluid_prefs.get("show_guides", show_guides, 1);
fluid_prefs.get("show_restricted", show_restricted, 1);
fluid_prefs.get("show_ghosted_outline", show_ghosted_outline, 0);
fluid_prefs.get("show_comments", show_comments, 1);
make_shell_window();
}

View File

@ -60,6 +60,7 @@ extern Fl_Window *main_window;
extern int show_guides;
extern int show_restricted;
extern int show_ghosted_outline;
extern int show_comments;
extern int G_use_external_editor;