Add Fl_Flex widget from Karsten Pedersen (issue #255)

This work is based on the repository and latest commit:
  https://github.com/osen/FL_Flex.git

  commit 36e4ed75a00daac825b87e81295818b4650991f5
  Author: Karsten Pedersen <...>
  Date:   Fri Apr 23 12:06:16 2021 +0000

    Added Fltk (LGPL) license.

This widget is similar to Fl_Pack and supports either one row or one
column of widgets but has some more features. Test and demo programs
are included:

  test/flex_login.cxx: simple "login window" demo program
  test/flex_demo.cxx:  slightly more complex demo program

The original demo programs can still be compiled and built with
the new widget provided you '#include <FL/Fl_Flex.H>'.
Backwards compatible methods are included (except debug()).

The original widget has been modified to match FLTK standards and
enhanced in several ways, including:

- support box frames
- add HORIZONTAL and VERTICAL enum values (as in Fl_Pack)
- add horizontal() method (as in Fl_Pack)
- use type() rather than internal 'direction' variable
- add standard widget constructor (x, y, w, h, label)
- add margin and gap accessors rather than hard coding constants
- improve test and demo programs
- add documentation
- replace <vector> with array as required by FLTK CMP
- rename camelCase method names, keeping old names for compatibility:
  - change 'setSize(Fl_Widget*, int)'   to 'set_size(Fl_Widget*, int)'
  - change 'bool isSetSize(Fl_Widget*)' to 'int set_size(Fl_Widget*)'
- remove debug() method
- add a way to "unset" fixed size: set_size(Fl_Widget *, 0)
- add layout() method to force recalculation of children
- unify resizeRow() and resizeCol() methods to avoid code duplication
- improve widget size calculation.
This commit is contained in:
Albrecht Schlosser 2022-07-28 18:26:07 +02:00
parent de8e6de25b
commit f37aca15e9
11 changed files with 848 additions and 0 deletions

161
FL/Fl_Flex.H Normal file
View File

@ -0,0 +1,161 @@
//
// Fl_Flex widget header file for the Fast Light Tool Kit (FLTK).
//
// Copyright 2020 by Karsten Pedersen
// Copyright 2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#ifndef Fl_Flex_H
#define Fl_Flex_H
#include <FL/Fl_Group.H>
class FL_EXPORT Fl_Flex : public Fl_Group {
int margin_;
int gap_;
int set_size_size_;
int set_size_alloc_;
Fl_Widget **set_size_;
public:
enum { // values for type(int)
VERTICAL = 0, ///< vertical layout (one column)
HORIZONTAL = 1, ///< horizontal layout (one row)
COLUMN = 0, ///< alias for VERTICAL
ROW = 1 ///< alias for HORIZONTAL
};
// FLTK standard constructor
Fl_Flex(int X, int Y, int W, int H, const char *L = 0);
// original Fl_Flex constructors:
// backwards compatible if direction *names* { ROW | COLUMN } are used
Fl_Flex(int direction);
Fl_Flex(int w, int h, int direction);
Fl_Flex(int x, int y, int w, int h, int direction);
virtual ~Fl_Flex();
virtual void end();
virtual void resize(int x, int y, int w, int h);
void set_size(Fl_Widget *w, int size);
int set_size(Fl_Widget *w);
protected:
void init(int t = VERTICAL);
int alloc_size(int size);
public:
/** Return the margin size of the widget.
\return margin size.
*/
int margin() { return margin_; }
/** Set the margin and optionally the gap size of the widget.
This method can be used to set both the margin and the gap size.
If you don't use the second parameter \p g or supply a negative value
the gap size is not changed.
The margin is some free space inside the widget border \b around all child
widgets. It has the same size at all four edges of the Fl_Flex widget.
The gap size \p g is some free space \b between child widgets.
\param[in] m margin size, must be \>= 0
\param[in] g gap size, must be \>= 0, or will be ignored (if negative)
\see gap(int)
*/
void margin(int m, int g = -1) {
margin_ = m < 0 ? 0 : m;
if (g >= 0)
gap_ = g;
}
/** Return the gap size of the widget.
\return gap size between all child widgets.
*/
int gap() { return gap_; }
/**
Set the gap size of the widget.
The gap size is some free space \b between child widgets.
The size must be \>= 0. Negative values are clamped to 0.
\param[in] g gap size
*/
void gap(int g) {
gap_ = g < 0 ? 0 : g;
}
/** Returns non-zero (true) if Fl_Flex alignment is horizontal (row mode).
\returns non-zero if Fl_Flex alignment is horizontal
\retval 1 if type() == Fl_Flex::HORIZONTAL
\retval 0 if type() == Fl_Flex::VERTICAL
See class Fl_Flex documentation for details.
*/
int horizontal() const {
return type() == Fl_Flex::HORIZONTAL ? 1 : 0;
}
/**
Calculates the layout of the widget and redraws it.
If you change widgets in the Fl_Flex container you should call this method
to force recalculation of child widget sizes and positions. This can be
useful (necessary) if you hide(), show(), add() or remove() children.
This method also calls redraw() on the Fl_Flex widget.
*/
void layout() {
resize(x(), y(), w(), h());
redraw();
}
#if (1)
// Additional methods for backwards compatibility with "original" Fl_Flex widget
/**
Deprecated.
\deprecated Please use set_size(Fl_Widget *) instead.
*/
bool isSetSize(Fl_Widget *w) {
return (bool)set_size(w);
}
/**
Set the horizontal or vertical size of a child widget.
\deprecated Please use set_size(Fl_Widget *, int) instead.
*/
void setSize(Fl_Widget *w, int size) {
set_size(w, size);
}
#endif
};
#endif // Fl_Flex_H

View File

@ -39,6 +39,7 @@ set (CPPFILES
Fl_File_Chooser2.cxx
Fl_File_Icon.cxx
Fl_File_Input.cxx
Fl_Flex.cxx
Fl_Graphics_Driver.cxx
Fl_Group.cxx
Fl_Help_View.cxx

332
src/Fl_Flex.cxx Normal file
View File

@ -0,0 +1,332 @@
//
// Fl_Flex widget implementation for the Fast Light Tool Kit (FLTK).
//
// Copyright 2020 by Karsten Pedersen
// Copyright 2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#include <FL/Fl_Flex.H>
#include <stdlib.h>
/**
Construct a new Fl_Flex widget with the given position, size, and label.
Fl_Flex is a container (layout) widget that provides flexible positioning
of its children either in one row or in one column. Fl_Flex containers can
be nested so you can create flexible layouts with multiple columns and rows.
Fl_Flex is designed to be as simple as possible. You can set particular
widget sizes or let Fl_Flex position and size the widgets to fit the container.
You can set the margin \b around all children at the inner side the box frame
(if any). This margin has the same size on top, bottom, and both sides.
The default margin size is 3.
You can set the gap size \b between all children. The gap size is the same between
all children. This is similar to the 'spacing' of Fl_Pack.
The default gap size is 3.
Fl_Flex can either consist of a single row, i.e. type() = Fl_Flex::HORIZONTAL,
or a single column, i.e. type() = Fl_Flex::VERTICAL. The default value is
\p VERTICAL for consistency with Fl_Pack but you can use \p type() to assign
a row (\p HORIZONTAL) layout.
If type() == Fl_Flex::HORIZONTAL widgets are resized horizontally to fit in
the container and their height is the full Fl_Flex height minus border size
and margin. You can set a fixed widget width by using set_size().
If type() == Fl_Flex::VERTICAL the above description applies equivalently
to the row layout, i.e. widget heights can be set etc.
Alternate constructors let you specify the layout as Fl_Flex::HORIZONTAL or
Fl_Flex::VERTICAL directly. Fl_Flex::ROW is an alias of Fl_Flex::HORIZONTAL
and Fl_Flex::COLUMN is an alias of Fl_Flex::VERTICAL.
\note Please use the names (enum) rather than numerical values for
the type() argument and the \p direction parameter of the alternate
constructors. These constructors are backwards compatible with older
versions of Fl_Flex.
\param[in] X,Y position
\param[in] W,H size (width and height)
\param[in] L label (optional)
\see Fl_Flex::Fl_Flex(int direction)
\see Fl_Flex::Fl_Flex(int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L)
*/
Fl_Flex::Fl_Flex(int X, int Y, int W, int H, const char *L)
: Fl_Group(X, Y, W, H, L) {
init();
}
// special Fl_Flex constructors w/o label (backwards compatible with original Fl_Flex widget)
/**
Construct a new Fl_Flex object specifying its layout.
Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL
(aka Fl_Flex::COLUMN) as the \p direction argument.
This constructor sets the position and size to (0, 0, 0, 0) which is suitable
for nested Fl_Flex widgets. Use one of the other constructors to set the
desired position and size as well.
\param[in] direction horizontal (row) or vertical (column) layout
\see Fl_Flex::Fl_Flex(int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L)
*/
Fl_Flex::Fl_Flex(int direction)
: Fl_Group(0, 0, 0, 0, 0) {
init(direction);
}
/**
Construct a new Fl_Flex object specifying its layout and size.
Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL
(aka Fl_Flex::COLUMN) as the \p direction argument.
This constructor sets the position to (x = 0, y = 0) which is suitable
for nested Fl_Flex widgets. Use one of the other constructors to set the
desired position as well.
\param[in] w,h widget size
\param[in] direction horizontal (row) or vertical (column) layout
\see Fl_Flex::Fl_Flex(int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L)
*/
Fl_Flex::Fl_Flex(int w, int h, int direction)
: Fl_Group(0, 0, w, h, 0) {
init(direction);
}
/**
Construct a new Fl_Flex object specifying its layout, position, and size.
Use Fl_Flex::HORIZONTAL (aka Fl_Flex::ROW) or Fl_Flex::VERTICAL
(aka Fl_Flex::COLUMN) as the \p direction argument.
This constructor sets the position and size of the widget which is suitable
for outer Fl_Flex widgets but does not set a widget label.
Use Fl_Widget::label() to set one if required.
\param[in] x,y widget position
\param[in] w,h widget size
\param[in] direction horizontal (row) or vertical (column) layout
\see Fl_Flex::Fl_Flex(int direction)
\see Fl_Flex::Fl_Flex(int w, int h, int direction)
\see Fl_Flex::Fl_Flex(int x, int y, int w, int h, const char *L)
*/
Fl_Flex::Fl_Flex(int x, int y, int w, int h, int direction)
: Fl_Group(x, y, w, h, 0) {
init(direction);
}
void Fl_Flex::init(int t) {
gap_ = 3; // default gap size
margin_ = 3; // default margin size
set_size_ = 0; // array of fixed size widgets
set_size_size_ = 0; // number of fixed size widgets
set_size_alloc_ = 0; // allocated size of array of fixed size widgets
type(HORIZONTAL);
if (t == VERTICAL)
type(VERTICAL);
}
Fl_Flex::~Fl_Flex() {
if (set_size_)
free(set_size_);
}
void Fl_Flex::resize(int x, int y, int w, int h) {
Fl_Widget::resize(x, y, w, h);
int cc = children();
int dx = Fl::box_dx(box());
int dy = Fl::box_dy(box());
int dw = Fl::box_dw(box());
int dh = Fl::box_dh(box());
// Calculate total space minus gaps
int gaps = cc > 1 ? cc - 1 : 0;
int hori = horizontal();
int space = (hori ? w - dw : h - dh) - 2 * margin_;
// set x and y (start) position, calculate widget sizes
int xp = x + dx + margin_;
int yp = y + dy + margin_;
int hh = h - dh - margin_ * 2; // if horizontal: constant height of widgets
int vw = w - dw - margin_ * 2; // if vertical: constant width of widgets
int fw = cc; // number of flexible widgets
// Precalculate remaining space that can be distributed
for (int i = 0; i < cc; i++) {
Fl_Widget *c = child(i);
if (c->visible()) {
if (set_size(c)) {
space -= (hori ? c->w() : c->h());
fw--;
}
} else { // hidden widget
fw--;
gaps--;
}
}
if (gaps > 0)
space -= gaps * gap_;
// Set children to shared width/height of remaining space
int sp = 0; // width or height of flexible widget
int rem = 0; // remainder (to be distributed evenly)
if (fw > 0) {
sp = space / fw;
rem = space % fw;
if (rem) // adjust space for first 'rem' widgets
sp++;
}
for (int i = 0; i < cc; i++) {
Fl_Widget *c = child(i);
if (!c->visible())
continue;
if (hori) {
if (set_size(c)) {
c->resize(xp, yp, c->w(), hh);
} else {
c->resize(xp, yp, sp, hh);
if (--rem == 0) sp--;
}
xp += c->w() + gap_;
} else {
if (set_size(c)) {
c->resize(xp, yp, vw, c->h());
} else {
c->resize(xp, yp, vw, sp);
if (--rem == 0) sp--;
}
yp += c->h() + gap_;
}
}
} // resize()
/**
Ends automatic child addition and resizes all children.
This calculates the layout depending on all children and whether
they have been assigned fix sizes or not.
*/
void Fl_Flex::end() {
Fl_Group::end();
resize(x(), y(), w(), h());
}
/**
Set the horizontal or vertical size of a child widget.
This sets either the width or height of a child widget, depending on the
type() of the Fl_Flex container (Fl_Flex::HORIZONTAL or Fl_Flex::VERTICAL).
The other dimension is set to the full width or height of the Fl_Flex widget.
This can be used to set a fixed widget width or height of children
of Fl_Flex so they are not resized dynamically.
If \p size is 0 (zero) or negative the widget size is reset to flexible size.
\param[in] w widget to be affected
\param[in] size width (Fl_Flex::HORIZONTAL) or height (Fl_Flex::VERTICAL)
*/
void Fl_Flex::set_size(Fl_Widget *w, int size) {
if (size <= 0)
size = 0;
w->resize(0, 0, size, size);
int idx = -1;
for (int i = 0; i < set_size_size_; i++) {
if (set_size_[i] == w) {
idx = i;
break;
}
}
// remove from array ?
if (size == 0 && idx >= 0) {
for (int i = idx; i < set_size_size_ - 2; i++) {
set_size_[i] = set_size_[i+1];
}
set_size_size_--;
return;
}
// add to array of fixed size widgets
if (set_size_size_ == set_size_alloc_) {
set_size_alloc_ = alloc_size(set_size_alloc_);
set_size_ = (Fl_Widget **)realloc(set_size_, set_size_alloc_ * sizeof(Fl_Widget *));
}
set_size_[set_size_size_] = w;
set_size_size_++;
}
/**
Return whether the given widget has a fixed size or resizes dynamically.
\param[in] w widget
\return whether the widget has a fixed size
\retval 1 the widget has a fixed size
\retval 0 the widget resizes dynamically
*/
int Fl_Flex::set_size(Fl_Widget *w) {
for (int i = 0; i < set_size_size_; i++) {
if (w == set_size_[i]) {
return 1;
}
}
return 0;
}
/**
Return new size to be allocated for array of fixed size widgets.
This method is called when the array of fixed size widgets needs to be
expanded. The current \p size is provided (size can be 0). The default
method adds 8 to the current size.
This can be used in derived classes to change the allocation strategy.
Note that this method only \p queries the new size which shall be allocated
but does not allocate the memory.
\param[in] size current size
\return int new size (to be allocated)
*/
int Fl_Flex::alloc_size(int size) {
return size + 8;
}

View File

@ -42,6 +42,7 @@ CPPFILES = \
Fl_File_Chooser2.cxx \
Fl_File_Icon.cxx \
Fl_File_Input.cxx \
Fl_Flex.cxx \
Fl_Graphics_Driver.cxx \
Fl_Group.cxx \
Fl_Help_View.cxx \

View File

@ -1828,6 +1828,8 @@ Fl_File_Input.o: ../FL/Fl_Window.H
Fl_File_Input.o: ../FL/platform_types.h
Fl_File_Input.o: flstring.h
Fl_File_Input.o: Fl_System_Driver.H
Fl_Flex.o: ../FL/Fl_Flex.H
Fl_Flex.o: ../FL/Fl_Group.H
fl_font.o: ../config.h
fl_font.o: ../FL/Enumerations.H
fl_font.o: ../FL/Fl.H

2
test/.gitignore vendored
View File

@ -41,6 +41,8 @@ doublebuffer
editor
fast_slow
file_chooser
flex_demo
flex_login
fltk-versions
fonts
forms

View File

@ -81,6 +81,8 @@ CREATE_EXAMPLE (doublebuffer doublebuffer.cxx fltk)
CREATE_EXAMPLE (editor "editor.cxx;editor.plist" fltk)
CREATE_EXAMPLE (fast_slow fast_slow.fl fltk)
CREATE_EXAMPLE (file_chooser file_chooser.cxx "fltk_images;fltk")
CREATE_EXAMPLE (flex_demo flex_demo.cxx fltk)
CREATE_EXAMPLE (flex_login flex_login.cxx fltk)
CREATE_EXAMPLE (fltk-versions fltk-versions.cxx fltk)
CREATE_EXAMPLE (fonts fonts.cxx fltk)
CREATE_EXAMPLE (forms forms.cxx "fltk_forms;fltk")

View File

@ -74,6 +74,8 @@ CPPFILES =\
editor.cxx \
fast_slow.cxx \
file_chooser.cxx \
flex_demo.cxx \
flex_login.cxx \
fltk-versions.cxx \
fonts.cxx \
forms.cxx \
@ -163,6 +165,8 @@ ALL = \
editor$(EXEEXT) \
fast_slow$(EXEEXT) \
file_chooser$(EXEEXT) \
flex_demo$(EXEEXT) \
flex_login$(EXEEXT) \
fltk-versions$(EXEEXT) \
fonts$(EXEEXT) \
forms$(EXEEXT) \
@ -420,6 +424,10 @@ file_chooser$(EXEEXT): file_chooser.o $(IMGLIBNAME)
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) file_chooser.o -o $@ $(LINKFLTKIMG) $(LDLIBS)
$(OSX_ONLY) ../fltk-config --post $@
flex_demo$(EXEEXT): flex_demo.o
flex_login$(EXEEXT): flex_login.o
fltk-versions$(EXEEXT): fltk-versions.o
fonts$(EXEEXT): fonts.o

168
test/flex_demo.cxx Normal file
View File

@ -0,0 +1,168 @@
//
// Fl_Flex demo program for the Fast Light Tool Kit (FLTK).
//
// Copyright 2020 by Karsten Pedersen
// Copyright 2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#define DEBUG_GROUP (0)
void debug_group(Fl_Group *g) {
#if (DEBUG_GROUP)
printf("\nFl_Group (%p) has %d children:\n", g, g->children());
for (int i = 0; i < g->children(); i++) {
Fl_Widget *c = g->child(i);
printf(" child %2d: hidden = %-5s, (x,y,w,h) = (%3d, %3d, %3d, %3d), label = '%s'\n",
i, c->visible() ? "false" : "true", c->x(), c->y(), c->w(), c->h(),
c->label() ? c->label() : "(null)");
}
#endif
} // debug_group
Fl_Button *createButton(const char *caption) {
Fl_Button *rtn = new Fl_Button(0, 0, 120, 30, caption);
rtn->color(fl_rgb_color(225, 225, 225));
return rtn;
}
void toggle_cb(Fl_Widget *w, void *v) {
static Fl_Box *b = 0;
Fl_Widget *o = (Fl_Widget *)v;
Fl_Flex *flex = (Fl_Flex *)o->parent();
if (o->visible()) {
o->hide();
w->label("show OK button");
flex->child(1)->hide(); // hide Box
} else {
o->show();
w->label("hide OK button");
flex->child(1)->show(); // show Box
}
flex->layout();
debug_group(flex);
// Yet another test: modify the first (top) Fl_Flex widget
flex = (Fl_Flex *)(flex->parent()->child(0));
Fl_Group::current(0);
if (!b) {
b = new Fl_Box(0, 0, 0, 0, "Box3");
flex->insert(*b, flex->children() - 1);
} else {
delete b;
b = 0;
}
flex->layout();
debug_group(flex);
}
Fl_Flex *createRow() {
Fl_Flex *row = new Fl_Flex(Fl_Flex::ROW);
{
Fl_Button *toggle = createButton("hide OK button");
toggle->tooltip("hide() or show() OK button");
Fl_Box *box2 = new Fl_Box(0, 0, 120, 10, "Box2");
Fl_Button * okay = createButton("OK");
new Fl_Input(0, 0, 120, 10, "");
toggle->callback(toggle_cb, okay);
Fl_Flex *col2 = new Fl_Flex(Fl_Flex::COLUMN);
{
createButton("Top2");
createButton("Bottom2");
col2->end();
col2->margin(0, 5);
col2->box(FL_FLAT_BOX);
col2->color(fl_rgb_color(255, 128, 128));
}
row->set_size(box2, 50);
row->set_size(col2, 100);
row->end();
// TEST
row->box(FL_DOWN_BOX);
row->color(FL_GREEN);
}
return row;
}
int main(int argc, char **argv) {
Fl_Window *window = new Fl_Double_Window(100, 100, "Simple GUI Example");
{
Fl_Flex *col = new Fl_Flex(5, 5, 90, 90, Fl_Flex::COLUMN);
{
Fl_Flex *row = new Fl_Flex(Fl_Flex::ROW);
row->color(FL_YELLOW);
row->box(FL_FLAT_BOX);
{
createButton("Cancel");
new Fl_Box(0, 0, 120, 10, "Box1");
createButton("OK");
new Fl_Input(0, 0, 120, 10, "");
Fl_Flex *col1 = new Fl_Flex(Fl_Flex::COLUMN);
{
createButton("Top1");
createButton("Bottom1");
col1->end();
col1->box(FL_FLAT_BOX);
col1->color(fl_rgb_color(255, 128, 128));
col1->margin(5, 5);
}
row->end();
}
col->set_size(createRow(), 90);
createButton("Something1");
row = new Fl_Flex(Fl_Flex::ROW);
{
Fl_Button *cancel = createButton("Cancel");
Fl_Button *ok = createButton("OK");
new Fl_Input(0, 0, 120, 10, "");
row->set_size(cancel, 100);
row->set_size(ok, 100);
row->end();
}
createButton("Something2");
col->set_size(row, 30);
col->margin(0, 6);
col->end();
}
window->resizable(col);
window->color(fl_rgb_color(160, 180, 240));
window->box(FL_FLAT_BOX);
window->end();
}
window->size_range(550, 330);
window->resize(0, 0, 640, 480);
window->show(argc, argv);
int ret = Fl::run();
delete window;
return ret;
}

131
test/flex_login.cxx Normal file
View File

@ -0,0 +1,131 @@
//
// Fl_Flex demo program for the Fast Light Tool Kit (FLTK).
//
// Copyright 2020 by Karsten Pedersen
// Copyright 2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
Fl_Button *createButton(const char *caption) {
Fl_Button *rtn = new Fl_Button(0, 0, 100, 25, caption);
rtn->color(fl_rgb_color(225, 225, 225));
return rtn;
}
void buttonsPanel(Fl_Flex *parent) {
new Fl_Box(0, 0, 0, 0, "");
Fl_Box *w = new Fl_Box(0, 0, 0, 0, "Welcome to Flex Login");
Fl_Flex *urow = new Fl_Flex(Fl_Flex::ROW);
{
Fl_Box *b = new Fl_Box(0, 0, 0, 0, "Username:");
b->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT);
Fl_Input *username = new Fl_Input(0, 0, 0, 0, "");
urow->set_size(username, 180);
urow->end();
}
Fl_Flex *prow = new Fl_Flex(Fl_Flex::ROW);
{
Fl_Box *b = new Fl_Box(0, 0, 0, 0, "Password:");
b->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT);
Fl_Input *password = new Fl_Input(0, 0, 0, 0, "");
prow->set_size(password, 180);
prow->end();
}
Fl_Box *pad = new Fl_Box(0, 0, 0, 0, "");
Fl_Flex *brow = new Fl_Flex(Fl_Flex::ROW);
{
new Fl_Box(0, 0, 0, 0, "");
Fl_Button *reg = createButton("Register");
Fl_Button *login = createButton("Login");
brow->set_size(reg, 80);
brow->set_size(login, 80);
brow->gap(20);
brow->end();
}
Fl_Box *b = new Fl_Box(0, 0, 0, 0, "");
parent->set_size(w, 60);
parent->set_size(urow, 30);
parent->set_size(prow, 30);
parent->set_size(pad, 1);
parent->set_size(brow, 30);
parent->set_size(b, 30);
}
void middlePanel(Fl_Flex *parent) {
new Fl_Box(0, 0, 0, 0, "");
Fl_Box *box = new Fl_Box(0, 0, 0, 0, "Image");
box->box(FL_BORDER_BOX);
box->color(fl_rgb_color(0, 200, 0));
Fl_Box *spacer = new Fl_Box(0, 0, 0, 0, "");
Fl_Flex *bp = new Fl_Flex(Fl_Flex::COLUMN);
buttonsPanel(bp);
bp->end();
new Fl_Box(0, 0, 0, 0, "");
parent->set_size(box, 200);
parent->set_size(spacer, 10);
parent->set_size(bp, 300);
}
void mainPanel(Fl_Flex *parent) {
new Fl_Box(0, 0, 0, 0, "");
Fl_Flex *mp = new Fl_Flex(Fl_Flex::ROW);
middlePanel(mp);
mp->end();
new Fl_Box(0, 0, 0, 0, "");
parent->set_size(mp, 200);
}
int main(int argc, char **argv) {
Fl_Window *window = new Fl_Double_Window(100, 100, "Simple GUI Example");
{
Fl_Flex *col = new Fl_Flex(5, 5, 90, 90, Fl_Flex::COLUMN);
mainPanel(col);
col->end();
window->resizable(col);
window->color(fl_rgb_color(250, 250, 250));
window->end();
}
window->resize(0, 0, 640, 480);
window->size_range(550, 250);
window->show(argc, argv);
int ret = Fl::run();
delete window;
return ret;
}

View File

@ -857,6 +857,46 @@ file_chooser.o: ../FL/Fl_Valuator.H
file_chooser.o: ../FL/Fl_Widget.H
file_chooser.o: ../FL/Fl_Window.H
file_chooser.o: ../FL/platform_types.h
flex_demo.o: ../FL/Enumerations.H
flex_demo.o: ../FL/Fl.H
flex_demo.o: ../FL/Fl_Bitmap.H
flex_demo.o: ../FL/Fl_Box.H
flex_demo.o: ../FL/Fl_Button.H
flex_demo.o: ../FL/Fl_Cairo.H
flex_demo.o: ../FL/fl_casts.H
flex_demo.o: ../FL/fl_config.h
flex_demo.o: ../FL/Fl_Double_Window.H
flex_demo.o: ../FL/Fl_Export.H
flex_demo.o: ../FL/Fl_Flex.H
flex_demo.o: ../FL/Fl_Group.H
flex_demo.o: ../FL/Fl_Image.H
flex_demo.o: ../FL/Fl_Input.H
flex_demo.o: ../FL/Fl_Input_.H
flex_demo.o: ../FL/fl_types.h
flex_demo.o: ../FL/fl_utf8.h
flex_demo.o: ../FL/Fl_Widget.H
flex_demo.o: ../FL/Fl_Window.H
flex_demo.o: ../FL/platform_types.h
flex_login.o: ../FL/Enumerations.H
flex_login.o: ../FL/Fl.H
flex_login.o: ../FL/Fl_Bitmap.H
flex_login.o: ../FL/Fl_Box.H
flex_login.o: ../FL/Fl_Button.H
flex_login.o: ../FL/Fl_Cairo.H
flex_login.o: ../FL/fl_casts.H
flex_login.o: ../FL/fl_config.h
flex_login.o: ../FL/Fl_Double_Window.H
flex_login.o: ../FL/Fl_Export.H
flex_login.o: ../FL/Fl_Flex.H
flex_login.o: ../FL/Fl_Group.H
flex_login.o: ../FL/Fl_Image.H
flex_login.o: ../FL/Fl_Input.H
flex_login.o: ../FL/Fl_Input_.H
flex_login.o: ../FL/fl_types.h
flex_login.o: ../FL/fl_utf8.h
flex_login.o: ../FL/Fl_Widget.H
flex_login.o: ../FL/Fl_Window.H
flex_login.o: ../FL/platform_types.h
fltk-versions.o: ../FL/Enumerations.H
fltk-versions.o: ../FL/Fl.H
fltk-versions.o: ../FL/fl_ask.H