Add close buttons for individual tabs in Fl_Tabs (#628)
Add close buttons for Fl_Tabs Introducing callback reasons FLUID shows all FL_WHEN_... options Adding Fl_Tabs overflow types Improved test/tabs to show new features
This commit is contained in:
parent
4d1a508c7e
commit
8826dca106
@ -51,6 +51,7 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2022
|
||||
- New Fl_ICO_Image class to read Windows .ico icon files.
|
||||
- New classes Fl_SVG_File_Surface and Fl_EPS_File_Surface to save any FLTK
|
||||
graphics to SVG or EPS files, respectively.
|
||||
- Fl_Tabs now supports close buttons for individual tabs.
|
||||
- Windows platform: added support for using a manifest to set the
|
||||
application's level of DPI awareness (issue #309).
|
||||
- class Fl_Native_File_Chooser on the X11/Wayland platform relies on external
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Enumerations for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
||||
// 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
|
||||
@ -415,22 +415,51 @@ enum Fl_Event { // events
|
||||
/*@{*/
|
||||
/** These constants determine when a callback is performed.
|
||||
|
||||
\see Fl_Widget::when();
|
||||
\todo doxygen comments for values are incomplete and maybe wrong or unclear
|
||||
Fl_When is a bit field. Some values are merely shorcuts for common bit
|
||||
combinations. New flags may be added in the future, so it's important to
|
||||
mask the required bit when reading via \p when().
|
||||
|
||||
\note Some widgets may not fully suppoert \p FL_WHEN_... flags.
|
||||
|
||||
\see Fl_Widget::when(), Fl::callback_reason(), Fl_Callback_Reason, Fl_Widget::do_callback()
|
||||
*/
|
||||
enum Fl_When { // Fl_Widget::when():
|
||||
FL_WHEN_NEVER = 0, ///< Never call the callback
|
||||
FL_WHEN_CHANGED = 1, ///< Do the callback only when the widget value changes
|
||||
FL_WHEN_NOT_CHANGED = 2, ///< Do the callback whenever the user interacts with the widget
|
||||
FL_WHEN_RELEASE = 4, ///< Do the callback when the button or key is released and the value changes
|
||||
FL_WHEN_RELEASE_ALWAYS = 6, ///< Do the callback when the button or key is released, even if the value doesn't change
|
||||
FL_WHEN_ENTER_KEY = 8, ///< Do the callback when the user presses the ENTER key and the value changes
|
||||
FL_WHEN_ENTER_KEY_ALWAYS =10, ///< Do the callback when the user presses the ENTER key, even if the value doesn't change
|
||||
FL_WHEN_ENTER_KEY_CHANGED =11 ///< = (FL_WHEN_ENTER_KEY | FL_WHEN_CHANGED | FL_WHEN_NOT_CHANGED)
|
||||
FL_WHEN_NEVER = 0, ///< Never call the callback
|
||||
FL_WHEN_CHANGED = 1, ///< Do the callback only when the widget value changes
|
||||
FL_WHEN_NOT_CHANGED = 2, ///< Do the callback whenever the user interacts with the widget
|
||||
FL_WHEN_RELEASE = 4, ///< Do the callback when the button or key is released and the value changes
|
||||
FL_WHEN_RELEASE_ALWAYS = 6, ///< Do the callback when the button or key is released, even if the value doesn't change
|
||||
FL_WHEN_ENTER_KEY = 8, ///< Do the callback when the user presses the ENTER key and the value changes
|
||||
FL_WHEN_ENTER_KEY_ALWAYS = 10, ///< Do the callback when the user presses the ENTER key, even if the value doesn't change
|
||||
FL_WHEN_ENTER_KEY_CHANGED = 11, ///< Do callbacks whether the value changed or not, and when the ENTER key is pressed
|
||||
FL_WHEN_CLOSED = 16 ///< Do the callback when a child of Fl_Tabs is closed
|
||||
};
|
||||
|
||||
/*@}*/ // group: When Conditions
|
||||
|
||||
|
||||
/** \name Callback Reasons */
|
||||
/*@{*/
|
||||
/** These constants describe why a callback is performed.
|
||||
|
||||
\see Fl::callback_reason(), Fl_Widget::when(), Fl_When
|
||||
*/
|
||||
enum Fl_Callback_Reason {
|
||||
FL_REASON_UNKNOWN=0, ///< unknown or unset reason
|
||||
FL_REASON_SELECTED, ///< an item was selected
|
||||
FL_REASON_DESELECTED, ///< an item was de-selected
|
||||
FL_REASON_RESELECTED, ///< an item was re-selected (double-clicked).
|
||||
FL_REASON_OPENED, ///< an item was opened
|
||||
FL_REASON_CLOSED, ///< an item was closed
|
||||
FL_REASON_DRAGGED, ///< an item was dragged into a new place
|
||||
FL_REASON_CANCELLED, ///< a dialog was cancelled
|
||||
FL_REASON_CHANGED, ///< the value of the widget was modified
|
||||
FL_REASON_GOT_FOCUS, ///< a widget received focus
|
||||
FL_REASON_LOST_FOCUS, ///< a widget lost focus
|
||||
FL_REASON_RELEASED, ///< the mouse button was released
|
||||
};
|
||||
/*@}*/ // group: Callback Reasons
|
||||
|
||||
|
||||
/** \name Mouse and Keyboard Events
|
||||
|
||||
This and the following constants define the non-ASCII keys on the
|
||||
|
2
FL/Fl.H
2
FL/Fl.H
@ -202,6 +202,7 @@ public: // should be private!
|
||||
static void *e_clipboard_data;
|
||||
static const char *e_clipboard_type;
|
||||
static Fl_Event_Dispatch e_dispatch;
|
||||
static Fl_Callback_Reason callback_reason_;
|
||||
static Fl_Widget* belowmouse_;
|
||||
static Fl_Widget* pushed_;
|
||||
static Fl_Widget* focus_;
|
||||
@ -847,6 +848,7 @@ public:
|
||||
static void remove_system_handler(Fl_System_Handler h);
|
||||
static void event_dispatch(Fl_Event_Dispatch d);
|
||||
static Fl_Event_Dispatch event_dispatch();
|
||||
static Fl_Callback_Reason callback_reason();
|
||||
/** @} */
|
||||
|
||||
/** \defgroup fl_clipboard Selection & Clipboard functions
|
||||
|
@ -53,6 +53,12 @@
|
||||
accessing image data or doing stat() on a file or doing some
|
||||
other slow operation.
|
||||
|
||||
Callbacks are called when the value changes with \p FL_REASON_CHANGED.
|
||||
If \p FL_WHEN_RELEASE is set, callbacks are called when the mouse button is
|
||||
released with \p FL_REASON_CHANGED or \p FL_REASON_RESELECTED if the selection
|
||||
did not change. If \p FL_WHEN_ENTER_KEY is set, callbacks are also called when
|
||||
key presses or double clicks change the selection.
|
||||
|
||||
Keyboard navigation of browser items
|
||||
------------------------------------
|
||||
|
||||
|
@ -65,10 +65,15 @@ class Fl_Widget_Tracker;
|
||||
being \c FL_WHEN_RELEASE:
|
||||
\li \c 0: The callback is not done, instead changed() is turned on.
|
||||
\li \c FL_WHEN_RELEASE: The callback is done after the user successfully
|
||||
clicks the button, or when a shortcut is typed.
|
||||
clicks the button, or when a shortcut is typed. The reason is
|
||||
\p FL_REASON_RELEASED.
|
||||
\li \c FL_WHEN_CHANGED: The callback is done each time the value() changes
|
||||
(when the user pushes and releases the button, and as the mouse is
|
||||
dragged around in and out of the button).
|
||||
dragged around in and out of the button). The reason is set to
|
||||
\p FL_REASON_CHANGED
|
||||
\li \c FL_WHEN_NOT_CHANGED: The callback is done when the mouse button is
|
||||
released, but the value did not changed. The reason is set to
|
||||
\p FL_REASON_SELECTED
|
||||
*/
|
||||
|
||||
class FL_EXPORT Fl_Button : public Fl_Widget {
|
||||
|
@ -104,6 +104,9 @@ public:
|
||||
available colors, leaving you no space to exactly represent the color the
|
||||
user picks! You can however use fl_rectf() to fill a region with a simulated
|
||||
color using dithering.
|
||||
|
||||
Callback reasons can be \c FL_REASON_DRAGGED, \c FL_REASON_CHANGED, or
|
||||
\c FL_REASON_RESELECTED.
|
||||
*/
|
||||
/** @} */
|
||||
class FL_EXPORT Fl_Color_Chooser : public Fl_Group {
|
||||
|
@ -47,6 +47,11 @@ class Fl_Rect;
|
||||
\endcode
|
||||
..and this will trigger proper scheduling of the widget's removal
|
||||
from its parent group.
|
||||
|
||||
If used as a child of \p Fl_Tabs, setting \p when(FL_WHEN_CLOSED) will
|
||||
enable the Close button in the corresponding tab. If the user clicks the
|
||||
Close button, the callback of this group will be called with the callback
|
||||
reason \p FL_REASON_CLOSED.
|
||||
*/
|
||||
class FL_EXPORT Fl_Group : public Fl_Widget {
|
||||
|
||||
|
@ -200,7 +200,7 @@ protected:
|
||||
int handletext(int e, int, int, int, int);
|
||||
|
||||
/* Check the when() field and do a callback if indicated. */
|
||||
void maybe_do_callback();
|
||||
void maybe_do_callback(Fl_Callback_Reason reason = FL_REASON_UNKNOWN);
|
||||
|
||||
/** \internal Horizontal offset of text to left edge of widget. */
|
||||
int xscroll() const {return xscroll_;}
|
||||
|
@ -390,14 +390,14 @@ struct FL_EXPORT Fl_Menu_Item {
|
||||
The callback is called with the stored user_data() as its second argument.
|
||||
You must first check that callback() is non-zero before calling this.
|
||||
*/
|
||||
void do_callback(Fl_Widget* o) const {callback_(o, user_data_);}
|
||||
void do_callback(Fl_Widget* o) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, user_data_);}
|
||||
|
||||
/**
|
||||
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
|
||||
This call overrides the callback's second argument with the given value \p arg.
|
||||
You must first check that callback() is non-zero before calling this.
|
||||
*/
|
||||
void do_callback(Fl_Widget* o,void* arg) const {callback_(o, arg);}
|
||||
void do_callback(Fl_Widget* o,void* arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, arg);}
|
||||
|
||||
/**
|
||||
Calls the Fl_Menu_Item item's callback, and provides the Fl_Widget argument.
|
||||
@ -406,7 +406,7 @@ struct FL_EXPORT Fl_Menu_Item {
|
||||
the callback.
|
||||
You must first check that callback() is non-zero before calling this.
|
||||
*/
|
||||
void do_callback(Fl_Widget* o,long arg) const {callback_(o, (void*)(fl_intptr_t)arg);}
|
||||
void do_callback(Fl_Widget* o,long arg) const {Fl::callback_reason_=FL_REASON_SELECTED; callback_(o, (void*)(fl_intptr_t)arg);}
|
||||
|
||||
/** Back compatibility only.
|
||||
\deprecated
|
||||
|
60
FL/Fl_Tabs.H
60
FL/Fl_Tabs.H
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Tab header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2017 by Bill Spitzak and others.
|
||||
// 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
|
||||
@ -22,10 +22,15 @@
|
||||
|
||||
#include "Fl_Group.H"
|
||||
|
||||
struct Fl_Menu_Item;
|
||||
|
||||
/**
|
||||
The Fl_Tabs widget is the "file card tabs"
|
||||
interface that allows you to put lots and lots of buttons and
|
||||
switches in a panel, as popularized by many toolkits.
|
||||
The Fl_Tabs widget is a container widget that displays a set of tabs, with
|
||||
each tab representing a different child widget. The user can select a tab by
|
||||
clicking on it, and the corresponding child widget will be displayed.
|
||||
The Fl_Tabs widget is useful for organizing a large number of controls or
|
||||
other widgets into a compact space, allowing the user to switch between
|
||||
different sets of controls as needed.
|
||||
|
||||
\image html tabs.png
|
||||
\image latex tabs.png "Fl_Tabs" width=8cm
|
||||
@ -46,8 +51,8 @@
|
||||
children (there should be some space between the children and
|
||||
the edge of the Fl_Tabs), and the tabs may be placed
|
||||
"inverted" on the bottom - this is determined by which
|
||||
gap is larger. It is easiest to lay this out in fluid, using the
|
||||
fluid browser to select each child group and resize them until
|
||||
gap is larger. It is easiest to lay this out in FLUID, using the
|
||||
FLUID browser to select each child group and resize them until
|
||||
the tabs look the way you want them to.
|
||||
|
||||
The background area behind and to the right of the tabs is
|
||||
@ -157,6 +162,19 @@
|
||||
\image html tabs_uniform.png "Fl_Tabs with uniform colors"
|
||||
\image latex tabs_uniform.png "Fl_Tabs with uniform colors" width=8cm
|
||||
|
||||
\b Close \b Button \b on \b Tabs
|
||||
|
||||
The Fl_Tabs widget allows you to specify that a child widget should display
|
||||
a close button in its tab. If the \ref FL_WHEN_CLOSED flag is set for the
|
||||
child widget, an "X" symbol will be displayed to the left of the label text
|
||||
in the tab. When the close button is clicked, the child widget's callback
|
||||
function will be called with the \ref FL_REASON_CLOSED argument. It is then
|
||||
the responsibility of the child widget to remove itself from the
|
||||
Fl_Tabs container.
|
||||
|
||||
Tabs that are in a compressed state will not display a close button until
|
||||
they are fully expanded.
|
||||
|
||||
\b Resizing \b Caveats
|
||||
|
||||
When Fl_Tabs is resized vertically, the default behavior scales the
|
||||
@ -197,6 +215,7 @@
|
||||
-# \ref FL_WHEN_NOT_CHANGED can happen if someone clicks on an already selected tab,
|
||||
or if a keyboard navigation attempt results in no change to the tabs,
|
||||
such as using the arrow keys while at the left or right end of the tabs.
|
||||
-# \ref Fl::callback_reason() returns FL_REASON_SELECTED or FL_REASON_RESELECTED
|
||||
*/
|
||||
class FL_EXPORT Fl_Tabs : public Fl_Group {
|
||||
|
||||
@ -204,16 +223,31 @@ class FL_EXPORT Fl_Tabs : public Fl_Group {
|
||||
|
||||
protected:
|
||||
|
||||
int overflow_type;
|
||||
int tab_offset;
|
||||
int *tab_pos; // array of x-offsets of tabs per child + 1
|
||||
int *tab_width; // array of widths of tabs per child + 1
|
||||
int *tab_flags; // array of tab flag of tabs per child + 1
|
||||
int tab_count; // array size
|
||||
Fl_Align tab_align_; // tab label alignment
|
||||
int has_overflow_menu;
|
||||
Fl_Menu_Item* overflow_menu;
|
||||
|
||||
void check_overflow_menu();
|
||||
void handle_overflow_menu();
|
||||
void draw_overflow_menu_button();
|
||||
|
||||
int on_insert(Fl_Widget*, int) FL_OVERRIDE;
|
||||
int on_move(int, int) FL_OVERRIDE;
|
||||
void on_remove(int) FL_OVERRIDE;
|
||||
void resize(int, int, int, int) FL_OVERRIDE;
|
||||
|
||||
virtual void redraw_tabs();
|
||||
virtual int tab_positions(); // allocate and calculate tab positions
|
||||
virtual void clear_tab_positions();
|
||||
virtual void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int sel=0);
|
||||
virtual void draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int flags, int sel);
|
||||
virtual int tab_height();
|
||||
virtual int hit_close(Fl_Widget *o, int event_x, int event_y);
|
||||
|
||||
void draw() FL_OVERRIDE;
|
||||
|
||||
@ -225,6 +259,7 @@ public:
|
||||
int handle(int) FL_OVERRIDE;
|
||||
Fl_Widget *value();
|
||||
int value(Fl_Widget *);
|
||||
|
||||
/**
|
||||
Returns the tab group for the tab the user has currently down-clicked on
|
||||
and remains over until FL_RELEASE. Otherwise, returns NULL.
|
||||
@ -256,12 +291,23 @@ public:
|
||||
recommended alignment to show the icon left of the text.
|
||||
*/
|
||||
void tab_align(Fl_Align a) {tab_align_ = a;}
|
||||
|
||||
/**
|
||||
Gets the tab label alignment.
|
||||
|
||||
\see tab_align(Fl_Align)
|
||||
*/
|
||||
Fl_Align tab_align() const {return tab_align_;}
|
||||
|
||||
enum {
|
||||
OVERFLOW_COMPRESS = 0,
|
||||
OVERFLOW_CLIP,
|
||||
OVERFLOW_PULLDOWN,
|
||||
OVERFLOW_DRAG,
|
||||
};
|
||||
|
||||
void handle_overflow(int ov);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -113,7 +113,7 @@ class FL_EXPORT Fl_Text_Editor : public Fl_Text_Display {
|
||||
|
||||
protected:
|
||||
int handle_key();
|
||||
void maybe_do_callback();
|
||||
void maybe_do_callback(Fl_Callback_Reason reason = FL_REASON_CHANGED);
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
int insert_mode_;
|
||||
|
14
FL/Fl_Tree.H
14
FL/Fl_Tree.H
@ -273,14 +273,14 @@
|
||||
/// The reason the callback was invoked.
|
||||
///
|
||||
enum Fl_Tree_Reason {
|
||||
FL_TREE_REASON_NONE=0, ///< unknown reason
|
||||
FL_TREE_REASON_SELECTED, ///< an item was selected
|
||||
FL_TREE_REASON_DESELECTED, ///< an item was de-selected
|
||||
FL_TREE_REASON_RESELECTED, ///< an item was re-selected (double-clicked).
|
||||
FL_TREE_REASON_NONE = FL_REASON_UNKNOWN, ///< unknown reason
|
||||
FL_TREE_REASON_SELECTED = FL_REASON_SELECTED, ///< an item was selected
|
||||
FL_TREE_REASON_DESELECTED = FL_REASON_DESELECTED, ///< an item was de-selected
|
||||
FL_TREE_REASON_RESELECTED = FL_REASON_RESELECTED, ///< an item was re-selected (double-clicked).
|
||||
///< See ::Fl_Tree_Item_Reselect_Mode to enable this.
|
||||
FL_TREE_REASON_OPENED, ///< an item was opened
|
||||
FL_TREE_REASON_CLOSED, ///< an item was closed
|
||||
FL_TREE_REASON_DRAGGED ///< an item was dragged into a new place
|
||||
FL_TREE_REASON_OPENED = FL_REASON_OPENED, ///< an item was opened
|
||||
FL_TREE_REASON_CLOSED = FL_REASON_CLOSED, ///< an item was closed
|
||||
FL_TREE_REASON_DRAGGED = FL_REASON_DRAGGED ///< an item was dragged into a new place
|
||||
};
|
||||
|
||||
class FL_EXPORT Fl_Tree : public Fl_Group {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Widget header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2020 by Bill Spitzak and others.
|
||||
// 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
|
||||
@ -707,7 +707,7 @@ public:
|
||||
FL_WHEN_RELEASE.
|
||||
|
||||
\return set of flags
|
||||
\see when(uchar)
|
||||
\see when(uchar), Fl_When, do_callback(), Fl::callback_reason()
|
||||
*/
|
||||
Fl_When when() const {return (Fl_When)when_;}
|
||||
|
||||
@ -733,6 +733,11 @@ public:
|
||||
a newline for a Fl_Multiline_Input) - this changes the behavior.
|
||||
\li FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED: The Enter key will do the
|
||||
callback even if the text has not changed. Useful for command fields.
|
||||
\li \ref FL_WHEN_CLOSED : If the user requests that the widget is closed,
|
||||
the callback is called with \ref FL_REASON_CLOSED. The \ref Fl_Tabs
|
||||
widget checks this flag on its children to determine whether to display
|
||||
a close button on the tab of that widget.
|
||||
|
||||
Fl_Widget::when() is a set of bitflags used by subclasses of
|
||||
Fl_Widget to decide when to do the callback.
|
||||
|
||||
@ -741,6 +746,7 @@ public:
|
||||
class so that you can scan a panel and do_callback() on all the ones
|
||||
that don't do their own callbacks in response to an "OK" button.
|
||||
\param[in] i set of flags
|
||||
\see Fl_When, do_callback(), Fl::callback_reason()
|
||||
*/
|
||||
void when(uchar i) {when_ = i;}
|
||||
|
||||
@ -962,7 +968,7 @@ public:
|
||||
\see callback()
|
||||
\see do_callback(Fl_Widget *widget, void *data)
|
||||
*/
|
||||
void do_callback() {do_callback(this, user_data_);}
|
||||
void do_callback(Fl_Callback_Reason reason=FL_REASON_UNKNOWN) {do_callback(this, user_data_, reason);}
|
||||
|
||||
/** Calls the widget callback function with arbitrary arguments.
|
||||
\param[in] widget call the callback with \p widget as the first argument
|
||||
@ -970,13 +976,11 @@ public:
|
||||
\see callback()
|
||||
\see do_callback(Fl_Widget *widget, void *data)
|
||||
*/
|
||||
void do_callback(Fl_Widget *widget, long arg) {
|
||||
do_callback(widget, (void*)(fl_intptr_t)arg);
|
||||
void do_callback(Fl_Widget *widget, long arg, Fl_Callback_Reason reason=FL_REASON_UNKNOWN) {
|
||||
do_callback(widget, (void*)(fl_intptr_t)arg, reason);
|
||||
}
|
||||
|
||||
// Causes a widget to invoke its callback function with arbitrary arguments.
|
||||
// Documentation and implementation in Fl_Widget.cxx
|
||||
void do_callback(Fl_Widget *widget, void *arg = 0);
|
||||
void do_callback(Fl_Widget *widget, void *arg = 0, Fl_Callback_Reason reason=FL_REASON_UNKNOWN);
|
||||
|
||||
/* Internal use only. */
|
||||
int test_shortcut();
|
||||
|
@ -48,6 +48,9 @@ class Fl_Double_Window;
|
||||
The window's callback is done if the user tries to close a window
|
||||
using the window manager and Fl::modal() is zero or equal to the
|
||||
window. Fl_Window has a default callback that calls Fl_Window::hide().
|
||||
Callback reasons can be \p FL_REASON_CANCELLED if the Escape key was pressed,
|
||||
or \p FL_REASON_CLOSED when the close button is clicked. \p FL_WHEN_...
|
||||
flags are ignored.
|
||||
*/
|
||||
class FL_EXPORT Fl_Window : public Fl_Group {
|
||||
friend int Fl::arg(int argc, char **argv, int &i);
|
||||
|
21
FL/names.h
21
FL/names.h
@ -110,6 +110,27 @@ const char * const fl_fontnames[] =
|
||||
"FL_ZAPF_DINGBATS",
|
||||
};
|
||||
|
||||
/**
|
||||
This is an array of callback reason names you can use to convert font numbers into names.
|
||||
|
||||
The array gets defined inline wherever your '\#include <FL/names.h>' appears.
|
||||
*/
|
||||
const char * const fl_callback_reason_names[] =
|
||||
{
|
||||
"FL_REASON_UNKNOWN",
|
||||
"FL_REASON_SELECTED",
|
||||
"FL_REASON_DESELECTED",
|
||||
"FL_REASON_RESELECTED",
|
||||
"FL_REASON_OPENED",
|
||||
"FL_REASON_CLOSED",
|
||||
"FL_REASON_DRAGGED",
|
||||
"FL_REASON_CANCELLED",
|
||||
"FL_REASON_CHANGED",
|
||||
"FL_REASON_GOT_FOCUS",
|
||||
"FL_REASON_LOST_FOCUS",
|
||||
"FL_REASON_RELEASED",
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* FL_NAMES_H */
|
||||
|
@ -197,7 +197,7 @@ int CodeEditor::auto_indent(int, CodeEditor* e) {
|
||||
}
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
|
||||
free(text);
|
||||
|
||||
|
@ -1110,12 +1110,20 @@ void down_box_cb(Fl_Choice* i, void *v) {
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Fl_Menu_Item whenmenu[] = {
|
||||
// set individual bits
|
||||
{"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED, FL_MENU_TOGGLE},
|
||||
{"FL_WHEN_NOT_CHANGED",0,0,(void*)FL_WHEN_NOT_CHANGED, FL_MENU_TOGGLE},
|
||||
{"FL_WHEN_RELEASE",0,0,(void*)FL_WHEN_RELEASE, FL_MENU_TOGGLE},
|
||||
{"FL_WHEN_ENTER_KEY",0,0,(void*)FL_WHEN_ENTER_KEY, FL_MENU_TOGGLE},
|
||||
{"FL_WHEN_CLOSED",0,0,(void*)FL_WHEN_CLOSED, FL_MENU_TOGGLE|FL_MENU_DIVIDER},
|
||||
// set bit combinations
|
||||
{"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER},
|
||||
{"FL_WHEN_RELEASE_ALWAYS",0,0,(void*)FL_WHEN_RELEASE_ALWAYS},
|
||||
{"FL_WHEN_ENTER_KEY_ALWAYS",0,0,(void*)FL_WHEN_ENTER_KEY_ALWAYS},
|
||||
{"FL_WHEN_ENTER_KEY_CHANGED",0,0,(void*)FL_WHEN_ENTER_KEY_CHANGED},
|
||||
{0}};
|
||||
|
||||
|
||||
static Fl_Menu_Item whensymbolmenu[] = {
|
||||
/* 0 */ {"FL_WHEN_NEVER",0,0,(void*)FL_WHEN_NEVER},
|
||||
/* 1 */ {"FL_WHEN_CHANGED",0,0,(void*)FL_WHEN_CHANGED},
|
||||
@ -1136,23 +1144,48 @@ static Fl_Menu_Item whensymbolmenu[] = {
|
||||
{0}
|
||||
};
|
||||
|
||||
// Return a text string representing the Fl_When value n
|
||||
const char* when_symbol_name(int n) {
|
||||
static char sym[128];
|
||||
if (n == FL_WHEN_CLOSED) {
|
||||
strcpy(sym, "FL_WHEN_CLOSED");
|
||||
} else {
|
||||
strcpy(sym, whensymbolmenu[n&15].label());
|
||||
if (n & FL_WHEN_CLOSED)
|
||||
strcat(sym, " | FL_WHEN_CLOSED");
|
||||
}
|
||||
return sym;
|
||||
}
|
||||
|
||||
// Set the check marks in the "when()" menu according to the Fl_When value n
|
||||
void set_whenmenu(int n) {
|
||||
if (n&FL_WHEN_CHANGED) whenmenu[0].set(); else whenmenu[0].clear();
|
||||
if (n&FL_WHEN_NOT_CHANGED) whenmenu[1].set(); else whenmenu[1].clear();
|
||||
if (n&FL_WHEN_RELEASE) whenmenu[2].set(); else whenmenu[2].clear();
|
||||
if (n&FL_WHEN_ENTER_KEY) whenmenu[3].set(); else whenmenu[3].clear();
|
||||
if (n&FL_WHEN_CLOSED) whenmenu[4].set(); else whenmenu[4].clear();
|
||||
}
|
||||
|
||||
void when_cb(Fl_Menu_Button* i, void *v) {
|
||||
if (v == LOAD) {
|
||||
if (current_widget->is_menu_item()) {i->deactivate(); return;} else i->activate();
|
||||
int n = current_widget->o->when() & 15;
|
||||
if (n&1) whenmenu[0].set(); else whenmenu[0].clear();
|
||||
if (n&2) whenmenu[1].set(); else whenmenu[1].clear();
|
||||
if (n&4) whenmenu[2].set(); else whenmenu[2].clear();
|
||||
if (n&8) whenmenu[3].set(); else whenmenu[3].clear();
|
||||
w_when_box->label(whensymbolmenu[n].label());
|
||||
int n = current_widget->o->when();
|
||||
set_whenmenu(n);
|
||||
w_when_box->copy_label(when_symbol_name(n));
|
||||
} else {
|
||||
int mod = 0;
|
||||
int n = 0;
|
||||
if (whenmenu[0].value()) n |= 1;
|
||||
if (whenmenu[1].value()) n |= 2;
|
||||
if (whenmenu[2].value()) n |= 4;
|
||||
if (whenmenu[3].value()) n |= 8;
|
||||
w_when_box->label(whensymbolmenu[n].label());
|
||||
if (i->mvalue() && ((i->mvalue()->flags & FL_MENU_TOGGLE) == 0) ) {
|
||||
n = (int)i->mvalue()->argument();
|
||||
set_whenmenu(n);
|
||||
} else {
|
||||
if (whenmenu[0].value()) n |= FL_WHEN_CHANGED;
|
||||
if (whenmenu[1].value()) n |= FL_WHEN_NOT_CHANGED;
|
||||
if (whenmenu[2].value()) n |= FL_WHEN_RELEASE;
|
||||
if (whenmenu[3].value()) n |= FL_WHEN_ENTER_KEY;
|
||||
if (whenmenu[4].value()) n |= FL_WHEN_CLOSED;
|
||||
}
|
||||
w_when_box->copy_label(when_symbol_name(n));
|
||||
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
|
||||
if (o->selected && o->is_widget()) {
|
||||
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
|
||||
@ -3074,8 +3107,7 @@ void Fl_Widget_Type::write_widget_code() {
|
||||
if (ww==FL_WHEN_NOT_CHANGED)
|
||||
ww = FL_WHEN_NEVER;
|
||||
if (ww != tplate->when() || subclass())
|
||||
write_c("%s%s->when(%s);\n", indent(), var,
|
||||
item_name(whensymbolmenu, ww));
|
||||
write_c("%s%s->when(%s);\n", indent(), var, when_symbol_name(ww));
|
||||
if (!o->visible() && o->parent())
|
||||
write_c("%s%s->hide();\n", indent(), var);
|
||||
if (!o->active())
|
||||
@ -3552,6 +3584,7 @@ void Fl_Widget_Type::copy_properties() {
|
||||
w->labelsize(o->labelsize());
|
||||
w->labelcolor(o->labelcolor());
|
||||
w->align(o->align());
|
||||
w->when(o->when());
|
||||
|
||||
// copy all attributes specific to widgets derived from Fl_Button
|
||||
if (is_button()) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Widget type code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// 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
|
||||
@ -86,9 +86,10 @@ int Shortcut_Button::handle(int e) {
|
||||
}
|
||||
|
||||
/** \class Widget_Bin_Button
|
||||
A button for the widget bin that allows the user to drag widgets into a window.
|
||||
Dragging and dropping a new widget makes it easy for the user to position
|
||||
a widget inside a window or group.
|
||||
The Widget_Bin_Button button is a button that can be used in the widget bin to
|
||||
allow the user to drag and drop widgets into a window or group. This feature
|
||||
makes it easy for the user to position a widget at a specific location within
|
||||
the window or group.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -124,8 +125,9 @@ int Widget_Bin_Button::handle(int inEvent)
|
||||
}
|
||||
|
||||
/** \class Widget_Bin_Window_Button
|
||||
This button is used by the widget bin to create new windows by drag'n'drop.
|
||||
The new window will be created wherever the user drops it on the desktop.
|
||||
The Widget_Bin_Window_Button button is used in the widget bin to create new
|
||||
windows by dragging and dropping. When the button is dragged and dropped onto
|
||||
the desktop, a new window will be created at the drop location.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -179,9 +181,10 @@ int Widget_Bin_Window_Button::handle(int inEvent)
|
||||
}
|
||||
|
||||
/** \class Fluid_Coord_Input
|
||||
An Input field for widget coordinates and sizes.
|
||||
This widget adds basic math capability to the text input field and a number
|
||||
of variables that can be used in the formula.
|
||||
The Fluid_Coord_Input widget is an input field for entering widget coordinates
|
||||
and sizes. It includes basic math capabilities and allows the use of variables
|
||||
in formulas. This widget is useful for specifying precise positions and
|
||||
dimensions for widgets in a graphical user interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -298,10 +301,15 @@ int Fluid_Coord_Input::eval(uchar *&s, int prio) const {
|
||||
|
||||
/**
|
||||
Evaluate a formula into an integer.
|
||||
The interpreter understands unary plus and minus, basic integer math
|
||||
(+, -, *, /), brackets, and can handle a user defined list of variables
|
||||
by name. There is no error checking. We assume that the formula is
|
||||
entered correctly.
|
||||
|
||||
The Fluid_Coord_Input widget includes a formula interpreter that allows you
|
||||
to evaluate a string containing a mathematical formula and obtain the result
|
||||
as an integer. The interpreter supports unary plus and minus, basic integer
|
||||
math operations (such as addition, subtraction, multiplication, and division),
|
||||
and brackets. It also allows you to define a list of variables by name and use
|
||||
them in the formula. The interpreter does not perform error checking, so it is
|
||||
assumed that the formula is entered correctly.
|
||||
|
||||
\param s formula as a C string
|
||||
\return the calculated value
|
||||
*/
|
||||
|
15
src/Fl.cxx
15
src/Fl.cxx
@ -69,6 +69,7 @@ const char *Fl::e_clipboard_type = "";
|
||||
void *Fl::e_clipboard_data = NULL;
|
||||
|
||||
Fl_Event_Dispatch Fl::e_dispatch = 0;
|
||||
Fl_Callback_Reason Fl::callback_reason_ = FL_REASON_UNKNOWN;
|
||||
|
||||
unsigned char Fl::options_[] = { 0, 0 };
|
||||
unsigned char Fl::options_read_ = 0;
|
||||
@ -1173,6 +1174,14 @@ static int send_event(int event, Fl_Widget* to, Fl_Window* window) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Give the reason for calling a callback.
|
||||
\return the reason for the current callback
|
||||
\see Fl_Widget::when(), Fl_Widget::do_callback(), Fl_Widget::callback()
|
||||
*/
|
||||
Fl_Callback_Reason Fl::callback_reason() {
|
||||
return callback_reason_;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Set a new event dispatch function.
|
||||
@ -1258,6 +1267,8 @@ int Fl::handle(int e, Fl_Window* window)
|
||||
another dispatch function. In that case, the user dispatch function must
|
||||
decide when to call Fl::handle_(int, Fl_Window*)
|
||||
|
||||
Callbacks can set \p FL_REASON_CLOSED and \p FL_REASON_CANCELLED.
|
||||
|
||||
\param e the event type (Fl::event_number() is not yet set)
|
||||
\param window the window that caused this event
|
||||
\return 0 if the event was not handled
|
||||
@ -1275,7 +1286,7 @@ int Fl::handle_(int e, Fl_Window* window)
|
||||
|
||||
case FL_CLOSE:
|
||||
if ( grab() || (modal() && window != modal()) ) return 0;
|
||||
wi->do_callback();
|
||||
wi->do_callback(FL_REASON_CLOSED);
|
||||
return 1;
|
||||
|
||||
case FL_SHOW:
|
||||
@ -1425,7 +1436,7 @@ int Fl::handle_(int e, Fl_Window* window)
|
||||
// make Escape key close windows:
|
||||
if (event_key()==FL_Escape) {
|
||||
wi = modal(); if (!wi) wi = window;
|
||||
wi->do_callback();
|
||||
wi->do_callback(FL_REASON_CANCELLED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -630,7 +630,7 @@ int Fl_Browser_::select(void* item, int val, int docallbacks) {
|
||||
}
|
||||
if (docallbacks) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -733,7 +733,7 @@ int Fl_Browser_::handle(int event) {
|
||||
if (wp.deleted()) return 1;
|
||||
if (when() & FL_WHEN_ENTER_KEY) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
case ' ':
|
||||
@ -807,7 +807,7 @@ J1:
|
||||
if (wp.deleted()) return 1;
|
||||
if (change && (when() & FL_WHEN_CHANGED)) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
} else {
|
||||
@ -821,7 +821,7 @@ J1:
|
||||
if (wp.deleted()) return 1;
|
||||
if (change && (when() & FL_WHEN_CHANGED)) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
}
|
||||
@ -859,7 +859,7 @@ J1:
|
||||
if (wp.deleted()) return 1;
|
||||
if (change && (when() & FL_WHEN_CHANGED)) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
}
|
||||
@ -897,7 +897,7 @@ J1:
|
||||
change |= change_t;
|
||||
if (change_t && (when() & FL_WHEN_CHANGED)) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
}
|
||||
@ -922,16 +922,16 @@ J1:
|
||||
}
|
||||
if (change) {
|
||||
set_changed();
|
||||
if (when() & FL_WHEN_RELEASE) do_callback();
|
||||
if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_CHANGED);
|
||||
} else {
|
||||
if (when() & FL_WHEN_NOT_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
if (wp.deleted()) return 1;
|
||||
|
||||
// double click calls the callback: (like Enter Key)
|
||||
if (Fl::event_clicks() && (when() & FL_WHEN_ENTER_KEY)) {
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
case FL_FOCUS:
|
||||
|
@ -100,12 +100,12 @@ int Fl_Button::handle(int event) {
|
||||
value_ = newval;
|
||||
set_changed();
|
||||
redraw();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;
|
||||
case FL_RELEASE:
|
||||
if (value_ == oldval) {
|
||||
if (when() & FL_WHEN_NOT_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_NOT_CHANGED) do_callback(FL_REASON_SELECTED);
|
||||
return 1;
|
||||
}
|
||||
set_changed();
|
||||
@ -116,11 +116,11 @@ int Fl_Button::handle(int event) {
|
||||
set_changed();
|
||||
if (when() & FL_WHEN_CHANGED) {
|
||||
Fl_Widget_Tracker wp(this);
|
||||
do_callback();
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
}
|
||||
if (when() & FL_WHEN_RELEASE) do_callback();
|
||||
if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
|
||||
return 1;
|
||||
case FL_SHORTCUT:
|
||||
if (!(shortcut() ?
|
||||
@ -150,16 +150,16 @@ int Fl_Button::handle(int event) {
|
||||
if (type() == FL_RADIO_BUTTON) {
|
||||
if (!value_) {
|
||||
setonly();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
} else if (type() == FL_TOGGLE_BUTTON) {
|
||||
value(!value());
|
||||
if (when() & FL_WHEN_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
} else {
|
||||
simulate_key_action();
|
||||
}
|
||||
if (wp.deleted()) return 1;
|
||||
if (when() & FL_WHEN_RELEASE) do_callback();
|
||||
if (when() & FL_WHEN_RELEASE) do_callback(FL_REASON_RELEASED);
|
||||
return 1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
@ -206,6 +206,11 @@ void Fl_Button::key_release_timeout(void *d)
|
||||
|
||||
Derived classes may handle this differently.
|
||||
|
||||
A button may reequest callbacks with \p whne() \p FL_WHEN_CHANGED,
|
||||
\p FL_WHEN_NOT_CHANGED, and \p FL_WHEN_RELEASE, triggering the callback
|
||||
reasons \p FL_REASON_CHANGED, \p FL_REASON_SELECTED,
|
||||
and \p FL_REASON_DESELECTED.
|
||||
|
||||
\param[in] X, Y, W, H position and size of the widget
|
||||
\param[in] L widget label, default is no label
|
||||
*/
|
||||
|
@ -220,7 +220,7 @@ int Flcc_HueBox::handle(int e) {
|
||||
if (fabs(H-ih) < 3*6.0/w()) H = ih;
|
||||
if (fabs(S-is) < 3*1.0/h()) S = is;
|
||||
if (Fl::event_state(FL_CTRL)) H = ih;
|
||||
if (c->hsv(H, S, c->value())) c->do_callback();
|
||||
if (c->hsv(H, S, c->value())) c->do_callback(FL_REASON_DRAGGED);
|
||||
} return 1;
|
||||
case FL_FOCUS : /* FALLTHROUGH */
|
||||
case FL_UNFOCUS :
|
||||
@ -292,7 +292,7 @@ int Flcc_HueBox::handle_key(int key) {
|
||||
Xf = (double)X/(double)w1;
|
||||
Yf = (double)Y/(double)h1;
|
||||
tohs(Xf, Yf, H, S);
|
||||
if (c->hsv(H, S, c->value())) c->do_callback();
|
||||
if (c->hsv(H, S, c->value())) c->do_callback(FL_REASON_CHANGED);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -347,7 +347,7 @@ int Flcc_ValueBox::handle(int e) {
|
||||
double Yf;
|
||||
Yf = 1-(Fl::event_y()-y()-Fl::box_dy(box()))/double(h()-Fl::box_dh(box()));
|
||||
if (fabs(Yf-iv)<(3*1.0/h())) Yf = iv;
|
||||
if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback();
|
||||
if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(FL_REASON_DRAGGED);
|
||||
} return 1;
|
||||
case FL_FOCUS : /* FALLTHROUGH */
|
||||
case FL_UNFOCUS :
|
||||
@ -418,7 +418,7 @@ int Flcc_ValueBox::handle_key(int key) {
|
||||
|
||||
double Yf;
|
||||
Yf = 1-((double)Y/(double)h1);
|
||||
if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback();
|
||||
if (c->hsv(c->hue(),c->saturation(),Yf)) c->do_callback(FL_REASON_CHANGED);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -432,7 +432,7 @@ void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) {
|
||||
double G = c->gvalue.value();
|
||||
double B = c->bvalue.value();
|
||||
if (c->mode() == M_HSV) {
|
||||
if (c->hsv(R,G,B)) c->do_callback();
|
||||
if (c->hsv(R,G,B)) c->do_callback(FL_REASON_CHANGED);
|
||||
return;
|
||||
}
|
||||
if (c->mode() != M_RGB) {
|
||||
@ -440,7 +440,7 @@ void Fl_Color_Chooser::rgb_cb(Fl_Widget* o, void*) {
|
||||
G = G/255;
|
||||
B = B/255;
|
||||
}
|
||||
if (c->rgb(R,G,B)) c->do_callback();
|
||||
if (c->rgb(R,G,B)) c->do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
|
||||
void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) {
|
||||
@ -455,7 +455,7 @@ void Fl_Color_Chooser::mode_cb(Fl_Widget* o, void*) {
|
||||
void Fl_Color_Chooser::mode(int newMode)
|
||||
{
|
||||
choice.value(newMode);
|
||||
choice.do_callback();
|
||||
choice.do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
|
||||
// Small local helper function:
|
||||
|
@ -269,7 +269,7 @@ Fl_File_Input::handle_button(int event) // I - Event
|
||||
|
||||
// Then do the callbacks, if necessary...
|
||||
set_changed();
|
||||
if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback();
|
||||
if (when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE) ) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -3553,7 +3553,7 @@ Fl_Help_View::topline(int top) // I - Top line number
|
||||
|
||||
scrollbar_.value(topline_, h() - scrollsize, 0, size_);
|
||||
|
||||
do_callback();
|
||||
do_callback(FL_REASON_DRAGGED);
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
@ -577,7 +577,7 @@ int Fl_Input::handle(int event) {
|
||||
|
||||
// For output widgets, do the callback so the app knows the user
|
||||
// did something with the mouse...
|
||||
if (readonly()) do_callback();
|
||||
if (readonly()) do_callback(FL_REASON_RELEASED);
|
||||
|
||||
return 1;
|
||||
|
||||
|
@ -942,7 +942,7 @@ int Fl_Input_::replace(int b, int e, const char* text, int ilen) {
|
||||
mark_ = position_ = undo_->undoat;
|
||||
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -989,7 +989,7 @@ int Fl_Input_::undo() {
|
||||
while (b1 > 0 && index(b1)!='\n') b1--;
|
||||
minimal_update(b1);
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1013,9 +1013,9 @@ int Fl_Input_::copy_cuts() {
|
||||
/** \internal
|
||||
Checks the when() field and does a callback if indicated.
|
||||
*/
|
||||
void Fl_Input_::maybe_do_callback() {
|
||||
void Fl_Input_::maybe_do_callback(Fl_Callback_Reason reason) {
|
||||
if (changed() || (when()&FL_WHEN_NOT_CHANGED)) {
|
||||
do_callback();
|
||||
do_callback(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1055,7 +1055,7 @@ int Fl_Input_::handletext(int event, int X, int Y, int W, int H) {
|
||||
case FL_HIDE:
|
||||
fl_reset_spot();
|
||||
if (!readonly() && (when() & FL_WHEN_RELEASE))
|
||||
maybe_do_callback();
|
||||
maybe_do_callback(FL_REASON_LOST_FOCUS);
|
||||
return 1;
|
||||
|
||||
case FL_PUSH:
|
||||
|
@ -205,7 +205,7 @@ void Fl_Input_Choice::menu_cb(Fl_Widget*, void *data) {
|
||||
{
|
||||
o->Fl_Widget::clear_changed();
|
||||
if (o->when() & FL_WHEN_NOT_CHANGED)
|
||||
o->do_callback();
|
||||
o->do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -213,7 +213,7 @@ void Fl_Input_Choice::menu_cb(Fl_Widget*, void *data) {
|
||||
o->inp_->set_changed();
|
||||
o->Fl_Widget::set_changed();
|
||||
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
|
||||
o->do_callback();
|
||||
o->do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
|
||||
if (wp.deleted()) return;
|
||||
@ -233,11 +233,11 @@ void Fl_Input_Choice::inp_cb(Fl_Widget*, void *data) {
|
||||
if (o->inp_->changed()) {
|
||||
o->Fl_Widget::set_changed();
|
||||
if (o->when() & (FL_WHEN_CHANGED|FL_WHEN_RELEASE))
|
||||
o->do_callback();
|
||||
o->do_callback(FL_REASON_CHANGED);
|
||||
} else {
|
||||
o->Fl_Widget::clear_changed();
|
||||
if (o->when() & FL_WHEN_NOT_CHANGED)
|
||||
o->do_callback();
|
||||
o->do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
|
||||
if (wp.deleted()) return;
|
||||
|
@ -99,8 +99,12 @@ int Fl_Positioner::handle(int event, int X, int Y, int W, int H) {
|
||||
if (!(when() & FL_WHEN_CHANGED ||
|
||||
(when() & FL_WHEN_RELEASE && event == FL_RELEASE))) return 1;
|
||||
if (changed() || when()&FL_WHEN_NOT_CHANGED) {
|
||||
if (event == FL_RELEASE) clear_changed();
|
||||
do_callback();
|
||||
Fl_Callback_Reason reason = changed() ? FL_REASON_CHANGED : FL_REASON_SELECTED;
|
||||
if (event == FL_RELEASE) {
|
||||
clear_changed();
|
||||
reason = FL_REASON_RELEASED;
|
||||
}
|
||||
do_callback(reason);
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
|
@ -23,7 +23,7 @@
|
||||
void Fl_Repeat_Button::repeat_callback(void *v) {
|
||||
Fl_Button *b = (Fl_Button*)v;
|
||||
Fl::add_timeout(REPEAT,repeat_callback,b);
|
||||
b->do_callback();
|
||||
b->do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
|
||||
int Fl_Repeat_Button::handle(int event) {
|
||||
@ -43,7 +43,7 @@ int Fl_Repeat_Button::handle(int event) {
|
||||
if (value(newval)) {
|
||||
if (newval) {
|
||||
Fl::add_timeout(INITIALREPEAT,repeat_callback,this);
|
||||
do_callback();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
} else {
|
||||
Fl::remove_timeout(repeat_callback,this);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ int Fl_Return_Button::handle(int event) {
|
||||
if (event == FL_SHORTCUT &&
|
||||
(Fl::event_key() == FL_Enter || Fl::event_key() == FL_KP_Enter)) {
|
||||
simulate_key_action();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
return 1;
|
||||
} else
|
||||
return Fl_Button::handle(event);
|
||||
|
@ -188,7 +188,7 @@ int Fl_Scrollbar::handle(int event) {
|
||||
Fl_Slider::value(v);
|
||||
value_damage();
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_DRAGGED);
|
||||
}
|
||||
return 1;}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ void Fl_Spinner::sb_cb(Fl_Widget *w, Fl_Spinner *sb) {
|
||||
}
|
||||
|
||||
sb->set_changed();
|
||||
sb->do_callback();
|
||||
sb->do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
|
||||
void Fl_Spinner::update() {
|
||||
@ -154,10 +154,10 @@ int Fl_Spinner::handle(int event) {
|
||||
case FL_KEYDOWN:
|
||||
case FL_SHORTCUT:
|
||||
if (Fl::event_key() == FL_Up) {
|
||||
up_button_.do_callback();
|
||||
up_button_.do_callback(FL_REASON_DRAGGED);
|
||||
return 1;
|
||||
} else if (Fl::event_key() == FL_Down) {
|
||||
down_button_.do_callback();
|
||||
down_button_.do_callback(FL_REASON_DRAGGED);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
397
src/Fl_Tabs.cxx
397
src/Fl_Tabs.cxx
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Tab widget for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// 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
|
||||
@ -24,6 +24,7 @@
|
||||
#include <FL/Fl_Tabs.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl_Tooltip.H>
|
||||
#include <FL/Fl_Menu_Item.H>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -31,6 +32,41 @@
|
||||
#define BORDER 2
|
||||
#define EXTRASPACE 10
|
||||
#define SELECTION_BORDER 5
|
||||
#define EXTRAGAP 2
|
||||
|
||||
|
||||
/** Make sure that we redraw all tabs when new children are added. */
|
||||
int Fl_Tabs::on_insert(Fl_Widget* candidate, int index) {
|
||||
redraw_tabs();
|
||||
damage(FL_DAMAGE_EXPOSE);
|
||||
return Fl_Group::on_insert(candidate, index);
|
||||
}
|
||||
|
||||
/** Make sure that we redraw all tabs when children are moved. */
|
||||
int Fl_Tabs::on_move(int a, int b) {
|
||||
redraw_tabs();
|
||||
damage(FL_DAMAGE_EXPOSE);
|
||||
return Fl_Group::on_move(a, b);
|
||||
}
|
||||
|
||||
/** Make sure that we redraw all tabs when new children are removed. */
|
||||
void Fl_Tabs::on_remove(int index) {
|
||||
redraw_tabs();
|
||||
damage(FL_DAMAGE_EXPOSE|FL_DAMAGE_ALL);
|
||||
if (child(index)->visible()) {
|
||||
if (index+1<children())
|
||||
value(child(index+1));
|
||||
else if (index>0)
|
||||
value(child(index-1));
|
||||
}
|
||||
Fl_Group::on_remove(index);
|
||||
}
|
||||
|
||||
/** Make sure that we redraw all tabs when the widget size changes. */
|
||||
void Fl_Tabs::resize(int X, int Y, int W, int H) {
|
||||
damage(FL_DAMAGE_EXPOSE);
|
||||
Fl_Group::resize(X, Y, W, H);
|
||||
}
|
||||
|
||||
// Return the left edges of each tab (plus a fake left edge for a tab
|
||||
// past the right-hand one). These positions are actually of the left
|
||||
@ -47,6 +83,7 @@ int Fl_Tabs::tab_positions() {
|
||||
if (nc) {
|
||||
tab_pos = (int*)malloc((nc+1)*sizeof(int));
|
||||
tab_width = (int*)malloc((nc)*sizeof(int));
|
||||
tab_flags = (int*)malloc((nc)*sizeof(int));
|
||||
}
|
||||
tab_count = nc;
|
||||
}
|
||||
@ -73,33 +110,45 @@ int Fl_Tabs::tab_positions() {
|
||||
o->labeltype(ot);
|
||||
o->align(oa);
|
||||
|
||||
if (o->when() & FL_WHEN_CLOSED)
|
||||
wt += labelsize()/2 + EXTRAGAP;
|
||||
|
||||
tab_width[i] = wt + EXTRASPACE;
|
||||
tab_pos[i+1] = tab_pos[i] + tab_width[i] + BORDER;
|
||||
tab_flags[i] = 0;
|
||||
}
|
||||
fl_draw_shortcut = prev_draw_shortcut;
|
||||
|
||||
int r = w();
|
||||
if (tab_pos[i] <= r) return selected;
|
||||
// uh oh, they are too big:
|
||||
// pack them against right edge:
|
||||
tab_pos[i] = r;
|
||||
for (i = nc; i--;) {
|
||||
int l = r-tab_width[i];
|
||||
if (tab_pos[i+1] < l) l = tab_pos[i+1];
|
||||
if (tab_pos[i] <= l) break;
|
||||
tab_pos[i] = l;
|
||||
r -= EXTRASPACE;
|
||||
}
|
||||
// pack them against left edge and truncate width if they still don't fit:
|
||||
for (i = 0; i<nc; i++) {
|
||||
if (tab_pos[i] >= i*EXTRASPACE) break;
|
||||
tab_pos[i] = i*EXTRASPACE;
|
||||
int W = w()-1-EXTRASPACE*(nc-i) - tab_pos[i];
|
||||
if (tab_width[i] > W) tab_width[i] = W;
|
||||
}
|
||||
// adjust edges according to visiblity:
|
||||
for (i = nc; i > selected; i--) {
|
||||
tab_pos[i] = tab_pos[i-1] + tab_width[i-1];
|
||||
|
||||
if (overflow_type == OVERFLOW_COMPRESS) {
|
||||
// uh oh, they are too big:
|
||||
// pack them against right edge:
|
||||
tab_pos[i] = r;
|
||||
for (i = nc; i--;) {
|
||||
int l = r-tab_width[i];
|
||||
if (tab_pos[i+1] < l) l = tab_pos[i+1];
|
||||
if (tab_pos[i] <= l) break;
|
||||
tab_pos[i] = l;
|
||||
tab_flags[i] |= 1;
|
||||
r -= EXTRASPACE;
|
||||
}
|
||||
// pack them against left edge and truncate width if they still don't fit:
|
||||
for (i = 0; i<nc; i++) {
|
||||
if (tab_pos[i] >= i*EXTRASPACE) break;
|
||||
tab_pos[i] = i*EXTRASPACE;
|
||||
tab_flags[i] |= 1;
|
||||
int W = w()-1-EXTRASPACE*(nc-i) - tab_pos[i];
|
||||
if (tab_width[i] > W) tab_width[i] = W;
|
||||
}
|
||||
// adjust edges according to visiblity:
|
||||
for (i = nc; i > selected; i--) {
|
||||
tab_pos[i] = tab_pos[i-1] + tab_width[i-1];
|
||||
}
|
||||
if ((selected > 0) && (tab_pos[selected-1]+tab_width[selected-1]>tab_pos[selected]))
|
||||
tab_flags[selected] |= 1;
|
||||
tab_flags[selected] &= ~1;
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
@ -121,12 +170,15 @@ int Fl_Tabs::tab_height() {
|
||||
else return (H <= 0) ? 0 : H;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the widget of the tab the user clicked on at \p event_x / \p event_y.
|
||||
This is used for event handling (clicks) and by fluid to pick tabs.
|
||||
/** Return a pointer to the child widget with a tab at the given coordinates.
|
||||
|
||||
\returns The child widget of the tab the user clicked on, or<br>
|
||||
0 if there are no children or if the event is outside of the tabs area.
|
||||
The Fl_Tabs::which() method returns a pointer to the child widget of the
|
||||
Fl_Tabs container that corresponds to the tab at the given event coordinates.
|
||||
If the event coordinates are outside the area of the tabs or if the Fl_Tabs
|
||||
container has no children, the method returns NULL.
|
||||
|
||||
\param event_x, event_y event coordinates
|
||||
\returns pointer to the selected child widget, or NULL
|
||||
*/
|
||||
Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
|
||||
if (children() == 0) return 0;
|
||||
@ -141,7 +193,7 @@ Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
|
||||
const int nc = children();
|
||||
tab_positions();
|
||||
for (int i=0; i<nc; i++) {
|
||||
if (event_x < x()+tab_pos[i+1]) {
|
||||
if (event_x < x()+tab_pos[i+1]+tab_offset) {
|
||||
ret = child(i);
|
||||
break;
|
||||
}
|
||||
@ -149,6 +201,92 @@ Fl_Widget *Fl_Tabs::which(int event_x, int event_y) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Check whether the coordinates fall within the "close" button area of the tab.
|
||||
|
||||
The Fl_Tabs::hit_close() method checks whether the given event coordinates
|
||||
fall within the area of the "close" button on the tab of the specified
|
||||
child widget. This method should be called after the Fl_Tabs::which() method,
|
||||
which updates a lookup table used to determine the width of each tab.
|
||||
|
||||
\param o check the tab of this widget
|
||||
\param event_x, event_y event coordinatese
|
||||
\return 1 if we hit the close button, and 0 otherwie
|
||||
*/
|
||||
int Fl_Tabs::hit_close(Fl_Widget *o, int event_x, int event_y) {
|
||||
(void)event_y;
|
||||
for (int i=0; i<children(); i++) {
|
||||
if (child(i)==o) {
|
||||
// never hit the "close" button on a compressed tab unless it's the active one
|
||||
if (tab_flags[i] & 1)
|
||||
return 0;
|
||||
// did we hit the area of teh "x"?
|
||||
int tab_x = tab_pos[i] + tab_offset + x();
|
||||
return ( (event_x >= tab_x)
|
||||
&& (event_x < tab_x + (labelsize()+EXTRASPACE+EXTRAGAP)/2) );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fl_Tabs::check_overflow_menu() {
|
||||
int nc = children();
|
||||
int H = tab_height(); if (H < 0) H = -H;
|
||||
if (tab_pos[nc] > w()-H) {
|
||||
has_overflow_menu = 1;
|
||||
} else {
|
||||
has_overflow_menu = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Tabs::handle_overflow_menu() {
|
||||
int nc = children();
|
||||
int H = tab_height(); if (H < 0) H = -H;
|
||||
int vc; // number of visible children
|
||||
|
||||
// count visibel children
|
||||
for (vc = 0; vc < nc; vc++) {
|
||||
if (tab_pos[vc+1] > w()-H) break;
|
||||
}
|
||||
if (vc == nc) return; // children are visible
|
||||
|
||||
// create a menu with invisible children
|
||||
int i, n = nc - vc;
|
||||
overflow_menu = new Fl_Menu_Item[n+1];
|
||||
memset(overflow_menu, 0, sizeof(Fl_Menu_Item)*(n+1));
|
||||
for (i = 0; i < n; i++) {
|
||||
overflow_menu[i].label(child(vc+i)->label());
|
||||
overflow_menu[i].user_data(child(vc+i));
|
||||
}
|
||||
overflow_menu[i].label(NULL);
|
||||
|
||||
// show the menu and handle the selection
|
||||
const Fl_Menu_Item *m = overflow_menu->popup(x()+w()-H, (tab_height()>0)?(y()+H):(y()+h()));
|
||||
if (m)
|
||||
value((Fl_Widget*)m->user_data());
|
||||
|
||||
// delete the menu until we need it next time
|
||||
if (overflow_menu) {
|
||||
delete[] overflow_menu;
|
||||
overflow_menu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Tabs::draw_overflow_menu_button() {
|
||||
int H = tab_height();
|
||||
int X, Y;
|
||||
if (H > 0) {
|
||||
X = x() + w() - H;
|
||||
Y = y();
|
||||
} else {
|
||||
H = -H;
|
||||
X = x() + w() - H;
|
||||
Y = y() + h() - H;
|
||||
}
|
||||
fl_draw_box(box(), X, Y, H, H, color());
|
||||
Fl_Rect r(X, Y, H, H);
|
||||
fl_draw_arrow(r, FL_ARROW_CHOICE, FL_ORIENT_NONE, fl_contrast(FL_BLACK, color()));
|
||||
}
|
||||
|
||||
void Fl_Tabs::redraw_tabs()
|
||||
{
|
||||
int H = tab_height();
|
||||
@ -162,31 +300,73 @@ void Fl_Tabs::redraw_tabs()
|
||||
}
|
||||
|
||||
int Fl_Tabs::handle(int event) {
|
||||
|
||||
static int initial_x = 0;
|
||||
static int initial_tab_offset = 0;
|
||||
static int forward_motion_to_group = 0;
|
||||
Fl_Widget *o;
|
||||
int i;
|
||||
|
||||
switch (event) {
|
||||
|
||||
case FL_PUSH:
|
||||
initial_x = Fl::event_x();
|
||||
initial_tab_offset = tab_offset;
|
||||
forward_motion_to_group = 0;
|
||||
{
|
||||
int H = tab_height();
|
||||
if (H >= 0) {
|
||||
if (Fl::event_y() > y()+H) return Fl_Group::handle(event);
|
||||
if (Fl::event_y() > y()+H) {
|
||||
forward_motion_to_group = 1;
|
||||
return Fl_Group::handle(event);
|
||||
}
|
||||
} else {
|
||||
if (Fl::event_y() < y()+h()+H) return Fl_Group::handle(event);
|
||||
if (Fl::event_y() < y()+h()+H) {
|
||||
forward_motion_to_group = 1;
|
||||
return Fl_Group::handle(event);
|
||||
}
|
||||
H = - H;
|
||||
}
|
||||
if (has_overflow_menu && Fl::event_x() > x()+w()-H) {
|
||||
handle_overflow_menu();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case FL_DRAG:
|
||||
case FL_RELEASE:
|
||||
if (forward_motion_to_group) {
|
||||
return Fl_Group::handle(event);
|
||||
}
|
||||
o = which(Fl::event_x(), Fl::event_y());
|
||||
if (overflow_type == OVERFLOW_DRAG) {
|
||||
if (tab_pos[children()] < w() && tab_offset == 0) {
|
||||
// fall through
|
||||
} else if (!Fl::event_is_click()) {
|
||||
tab_offset = initial_tab_offset + Fl::event_x() - initial_x;
|
||||
if (tab_offset > 0) {
|
||||
initial_tab_offset -= tab_offset;
|
||||
tab_offset = 0;
|
||||
} else {
|
||||
int dw = tab_pos[children()] + tab_offset - w();
|
||||
if (dw < -20) {
|
||||
initial_tab_offset -= dw+20;
|
||||
tab_offset -= dw+20;
|
||||
}
|
||||
}
|
||||
damage(FL_DAMAGE_EXPOSE|FL_DAMAGE_SCROLL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (event == FL_RELEASE) {
|
||||
push(0);
|
||||
if (o && Fl::visible_focus() && Fl::focus()!=this) {
|
||||
Fl::focus(this);
|
||||
redraw_tabs();
|
||||
}
|
||||
if (o && (o->when() & FL_WHEN_CLOSED) && hit_close(o, Fl::event_x(), Fl::event_y())) {
|
||||
o->do_callback(FL_REASON_CLOSED);
|
||||
return 1; // o may be deleted at this point
|
||||
}
|
||||
if (o && // Released on a tab and..
|
||||
(value(o) || // tab changed value or..
|
||||
(when()&(FL_WHEN_NOT_CHANGED)) // ..no change but WHEN_NOT_CHANGED set,
|
||||
@ -194,7 +374,7 @@ int Fl_Tabs::handle(int event) {
|
||||
) {
|
||||
Fl_Widget_Tracker wp(o);
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
if (wp.deleted()) return 1;
|
||||
}
|
||||
Fl_Tooltip::current(o);
|
||||
@ -240,16 +420,16 @@ int Fl_Tabs::handle(int event) {
|
||||
if (child(i)->visible()) break;
|
||||
value(child(i - 1));
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
return 1;
|
||||
case FL_Right:
|
||||
if (!children()) return 0;
|
||||
if (child(children() - 1)->visible()) return 0;
|
||||
for (i = 0; i < children(); i ++)
|
||||
for (i = 0; i < children()-1; i++)
|
||||
if (child(i)->visible()) break;
|
||||
value(child(i + 1));
|
||||
set_changed();
|
||||
do_callback();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
return 1;
|
||||
case FL_Down:
|
||||
redraw();
|
||||
@ -264,8 +444,12 @@ int Fl_Tabs::handle(int event) {
|
||||
if (c->test_shortcut(c->label())) {
|
||||
char sc = !c->visible();
|
||||
value(c);
|
||||
if (sc) set_changed();
|
||||
do_callback();
|
||||
if (sc) {
|
||||
set_changed();
|
||||
do_callback(FL_REASON_SELECTED);
|
||||
} else {
|
||||
do_callback(FL_REASON_RESELECTED);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -300,10 +484,15 @@ int Fl_Tabs::push(Fl_Widget *o) {
|
||||
/**
|
||||
Gets the currently visible widget/tab.
|
||||
|
||||
The value() is the first visible child (or the last child if none
|
||||
are visible) and this also hides any other children.
|
||||
This allows the tabs to be deleted, moved to other groups, and
|
||||
show()/hide() called without it screwing up.
|
||||
The Fl_Tabs::value() method returns a pointer to the currently visible child
|
||||
widget of the Fl_Tabs container. The visible child is the first child that
|
||||
is currently being displayed, or the last child if none of the children are
|
||||
being displayed.
|
||||
|
||||
If child widgets have been added, moved, or deleted, this method ensures that
|
||||
only one tab is visible at a time.
|
||||
|
||||
\return a pointer to the currently visible child
|
||||
*/
|
||||
Fl_Widget* Fl_Tabs::value() {
|
||||
Fl_Widget* v = 0;
|
||||
@ -317,12 +506,17 @@ Fl_Widget* Fl_Tabs::value() {
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the widget to become the current visible widget/tab.
|
||||
Setting the value hides all other children, and makes this one
|
||||
visible, if it is really a child.
|
||||
\returns 1 if there was a change (new value different from previous),<BR>
|
||||
0 if there was no change (new value already set)
|
||||
/** Sets the widget to become the current visible widget/tab.
|
||||
|
||||
The Fl_Tabs::value() method allows you to set a particular child widget of
|
||||
the Fl_Tabs container to be the currently visible widget. If the specified
|
||||
widget is a child of the Fl_Tabs container, it will be made visible and all
|
||||
other children will be hidden. The method returns 1 if the value was changed,
|
||||
and 0 if the specified value was already set.
|
||||
|
||||
\param[in] newvalue a poiner to a child widget
|
||||
\return 1 if a different tab was chosen
|
||||
\return 0 if there was no change (new value already set)
|
||||
*/
|
||||
int Fl_Tabs::value(Fl_Widget *newvalue) {
|
||||
Fl_Widget*const* a = array();
|
||||
@ -344,12 +538,18 @@ enum {LEFT, RIGHT, SELECTED};
|
||||
void Fl_Tabs::draw() {
|
||||
Fl_Widget *v = value();
|
||||
int H = tab_height();
|
||||
int ty, th;
|
||||
if (H >= 0) {
|
||||
ty = y(); th = H;
|
||||
} else {
|
||||
ty = y() + h() + H; th = -H;
|
||||
}
|
||||
Fl_Color c = v ? v->color() : color();
|
||||
|
||||
if (damage() & FL_DAMAGE_ALL) { // redraw the entire thing:
|
||||
Fl_Color c = v ? v->color() : color();
|
||||
|
||||
if (damage() & FL_DAMAGE_ALL) { // redraw the children
|
||||
draw_box(box(), x(), y()+(H>=0?H:0), w(), h()-(H>=0?H:-H), c);
|
||||
|
||||
}
|
||||
if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) {
|
||||
if (selection_color() != c) {
|
||||
// Draw the top or bottom SELECTION_BORDER lines of the tab pane in the
|
||||
// selection color so that the user knows which tab is selected...
|
||||
@ -358,33 +558,60 @@ void Fl_Tabs::draw() {
|
||||
draw_box(box(), x(), clip_y, w(), SELECTION_BORDER, selection_color());
|
||||
fl_pop_clip();
|
||||
}
|
||||
}
|
||||
if (damage() & FL_DAMAGE_ALL) { // redraw the children
|
||||
if (v) draw_child(*v);
|
||||
} else { // redraw the child
|
||||
if (v) update_child(*v);
|
||||
}
|
||||
if (damage() & FL_DAMAGE_EXPOSE) { // redraw the tab bar background
|
||||
if (parent()) {
|
||||
Fl_Widget *p = parent();
|
||||
fl_push_clip(x(), ty, w(), th);
|
||||
if (p->as_window())
|
||||
fl_draw_box(p->box(), 0, 0, p->w(), p->h(), p->color());
|
||||
else
|
||||
fl_draw_box(p->box(), p->x(), p->y(), p->w(), p->h(), p->color());
|
||||
fl_pop_clip();
|
||||
} else {
|
||||
fl_rectf(x(), ty, w(), th, color());
|
||||
}
|
||||
}
|
||||
if (damage() & (FL_DAMAGE_SCROLL|FL_DAMAGE_ALL)) {
|
||||
const int nc = children();
|
||||
int selected = tab_positions();
|
||||
int i;
|
||||
if (H>0)
|
||||
fl_push_clip(x(), ty, w(), th+BORDER);
|
||||
else
|
||||
fl_push_clip(x(), ty-BORDER, w(), th+BORDER);
|
||||
Fl_Widget*const* a = array();
|
||||
for (i=0; i<selected; i++)
|
||||
draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
|
||||
tab_width[i], H, a[i], LEFT);
|
||||
tab_width[i], H, a[i], tab_flags[i], LEFT);
|
||||
for (i=nc-1; i > selected; i--)
|
||||
draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
|
||||
tab_width[i], H, a[i], RIGHT);
|
||||
tab_width[i], H, a[i], tab_flags[i], RIGHT);
|
||||
if (v) {
|
||||
i = selected;
|
||||
draw_tab(x()+tab_pos[i], x()+tab_pos[i+1],
|
||||
tab_width[i], H, a[i], SELECTED);
|
||||
tab_width[i], H, a[i], tab_flags[i], SELECTED);
|
||||
}
|
||||
if (overflow_type == OVERFLOW_PULLDOWN)
|
||||
check_overflow_menu();
|
||||
if (has_overflow_menu)
|
||||
draw_overflow_menu_button();
|
||||
fl_pop_clip();
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
|
||||
void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int flags, int what) {
|
||||
x1 += tab_offset;
|
||||
x2 += tab_offset;
|
||||
int sel = (what == SELECTED);
|
||||
int dh = Fl::box_dh(box());
|
||||
int dy = Fl::box_dy(box());
|
||||
int wc = 0; // width of "close" button if drawn, or 0
|
||||
char prev_draw_shortcut = fl_draw_shortcut;
|
||||
fl_draw_shortcut = 1;
|
||||
|
||||
@ -414,8 +641,18 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
|
||||
|
||||
// Draw the label using the current color...
|
||||
o->labelcolor(sel ? labelcolor() : o->labelcolor());
|
||||
o->draw_label(x1, y() + yofs, W, H - yofs, tab_align());
|
||||
|
||||
// Draw the "close" button if requested
|
||||
if ( (o->when() & FL_WHEN_CLOSED) && !(flags & 1) ) {
|
||||
int sz = labelsize()/2, sy = (H - sz)/2;
|
||||
fl_draw_symbol("@3+", x1 + EXTRASPACE/2, y() + yofs/2 + sy, sz, sz, o->labelcolor());
|
||||
wc = sz + EXTRAGAP;
|
||||
}
|
||||
|
||||
// Draw the label text
|
||||
o->draw_label(x1 + wc, y() + yofs, W - wc, H - yofs, tab_align());
|
||||
|
||||
// Draw the focus box
|
||||
if (Fl::focus() == this && o->visible())
|
||||
draw_focus(bt, x1, y(), W, H, bc);
|
||||
|
||||
@ -432,8 +669,18 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
|
||||
|
||||
// Draw the label using the current color...
|
||||
o->labelcolor(sel ? labelcolor() : o->labelcolor());
|
||||
o->draw_label(x1, y() + h() - H, W, H - yofs, tab_align());
|
||||
|
||||
// Draw the "close" button if requested
|
||||
if ( (o->when() & FL_WHEN_CLOSED) && (x1+W < x2) ) {
|
||||
int sz = labelsize()/2, sy = (H - sz)/2;
|
||||
fl_draw_symbol("@3+", x1 + EXTRASPACE/2, y() + h() - H -yofs/2 + sy, sz, sz, o->labelcolor());
|
||||
wc = sz + EXTRAGAP;
|
||||
}
|
||||
|
||||
// Draw the label text
|
||||
o->draw_label(x1 + wc, y() + h() - H, W - wc, H - yofs, tab_align());
|
||||
|
||||
// Draw the focus box
|
||||
if (Fl::focus() == this && o->visible())
|
||||
draw_focus(bt, x1, y() + h() - H, W, H, bc);
|
||||
|
||||
@ -472,14 +719,21 @@ Fl_Tabs::Fl_Tabs(int X, int Y, int W, int H, const char *L) :
|
||||
{
|
||||
box(FL_THIN_UP_BOX);
|
||||
push_ = 0;
|
||||
overflow_type = OVERFLOW_COMPRESS;
|
||||
tab_offset = 0;
|
||||
tab_pos = 0;
|
||||
tab_width = 0;
|
||||
tab_flags = NULL;
|
||||
tab_count = 0;
|
||||
tab_align_ = FL_ALIGN_CENTER;
|
||||
has_overflow_menu = 0;
|
||||
overflow_menu = NULL;
|
||||
}
|
||||
|
||||
Fl_Tabs::~Fl_Tabs() {
|
||||
clear_tab_positions();
|
||||
if (overflow_menu)
|
||||
delete[] overflow_menu;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -548,4 +802,35 @@ void Fl_Tabs::clear_tab_positions() {
|
||||
free(tab_width);
|
||||
tab_width = 0;
|
||||
}
|
||||
if (tab_flags){
|
||||
free(tab_flags);
|
||||
tab_flags = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Set a method to handle an overflowing tab bar.
|
||||
|
||||
The Fl_Tabs widget allows you to specify how to handle the situation where
|
||||
there are more tabs than can be displayed at once. The available options are:
|
||||
|
||||
- \c OVERFLOW_COMPRESS: Tabs will be compressed and overlaid on top of each other.
|
||||
- \c OVERFLOW_CLIP: Only the first tabs that fit will be displayed.
|
||||
- \c OVERFLOW_PULLDOWN: Tabs that do not fit will be placed in a pull-down menu.
|
||||
- \c OVERFLOW_DRAG: The tab bar can be dragged horizontally to reveal additional tabs.
|
||||
|
||||
You can set the desired behavior using the overflow() method.
|
||||
|
||||
\param ov overflow type
|
||||
*/
|
||||
void Fl_Tabs::handle_overflow(int ov) {
|
||||
overflow_type = ov;
|
||||
tab_offset = 0;
|
||||
has_overflow_menu = 0;
|
||||
if (overflow_menu) {
|
||||
delete[] overflow_menu;
|
||||
overflow_menu = NULL;
|
||||
}
|
||||
damage(FL_DAMAGE_EXPOSE|FL_DAMAGE_ALL);
|
||||
redraw();
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,7 @@ int Fl_Text_Editor::kf_default(int c, Fl_Text_Editor* e) {
|
||||
else e->overstrike(s);
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -268,7 +268,7 @@ int Fl_Text_Editor::kf_backspace(int, Fl_Text_Editor* e) {
|
||||
kill_selection(e);
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ int Fl_Text_Editor::kf_enter(int, Fl_Text_Editor* e) {
|
||||
e->insert("\n");
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -544,7 +544,7 @@ int Fl_Text_Editor::kf_delete(int, Fl_Text_Editor* e) {
|
||||
kill_selection(e);
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -567,7 +567,7 @@ int Fl_Text_Editor::kf_cut(int c, Fl_Text_Editor* e) {
|
||||
kf_copy(c, e);
|
||||
kill_selection(e);
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -580,7 +580,7 @@ int Fl_Text_Editor::kf_paste(int, Fl_Text_Editor* e) {
|
||||
Fl::paste(*e, 1);
|
||||
e->show_insert_position();
|
||||
e->set_changed();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback();
|
||||
if (e->when()&FL_WHEN_CHANGED) e->do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -636,7 +636,7 @@ int Fl_Text_Editor::handle_key() {
|
||||
}
|
||||
show_insert_position();
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -651,10 +651,11 @@ int Fl_Text_Editor::handle_key() {
|
||||
}
|
||||
|
||||
/** does or does not a callback according to changed() and when() settings */
|
||||
void Fl_Text_Editor::maybe_do_callback() {
|
||||
void Fl_Text_Editor::maybe_do_callback(Fl_Callback_Reason reason) {
|
||||
// printf("Fl_Text_Editor::maybe_do_callback()\n");
|
||||
// printf("changed()=%d, when()=%x\n", changed(), when());
|
||||
if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
|
||||
if (changed() || (when()&FL_WHEN_NOT_CHANGED))
|
||||
do_callback(reason);
|
||||
}
|
||||
|
||||
int Fl_Text_Editor::handle(int event) {
|
||||
@ -679,7 +680,7 @@ int Fl_Text_Editor::handle(int event) {
|
||||
if (buffer()->selected()) redraw(); // Redraw selections...
|
||||
// FALLTHROUGH
|
||||
case FL_HIDE:
|
||||
if (when() & FL_WHEN_RELEASE) maybe_do_callback();
|
||||
if (when() & FL_WHEN_RELEASE) maybe_do_callback(FL_REASON_LOST_FOCUS);
|
||||
return 1;
|
||||
|
||||
case FL_KEYBOARD:
|
||||
@ -697,7 +698,7 @@ int Fl_Text_Editor::handle(int event) {
|
||||
else overstrike(Fl::event_text());
|
||||
show_insert_position();
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
|
||||
case FL_ENTER:
|
||||
@ -719,7 +720,7 @@ int Fl_Text_Editor::handle(int event) {
|
||||
Fl::paste(*this, 0);
|
||||
Fl::focus(this);
|
||||
set_changed();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback();
|
||||
if (when()&FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
@ -269,8 +269,12 @@ int Fl_Tile::handle(int event) {
|
||||
} else
|
||||
newy = sy;
|
||||
position(sx,sy,newx,newy);
|
||||
if (event == FL_DRAG) set_changed();
|
||||
do_callback();
|
||||
if (event == FL_DRAG) {
|
||||
set_changed();
|
||||
do_callback(FL_REASON_DRAGGED);
|
||||
} else {
|
||||
do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
return 1;}
|
||||
|
||||
}
|
||||
|
@ -2571,7 +2571,7 @@ int Fl_Tree::is_hscroll_visible() const {
|
||||
void Fl_Tree::do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) {
|
||||
callback_reason(reason);
|
||||
callback_item(item);
|
||||
do_callback((Fl_Widget*)this, user_data());
|
||||
do_callback((Fl_Widget*)this, user_data(), (Fl_Callback_Reason)reason);
|
||||
}
|
||||
|
||||
/// Sets the item that was changed for this callback.
|
||||
|
@ -101,7 +101,7 @@ void Fl_Valuator::handle_drag(double v) {
|
||||
value_ = v;
|
||||
value_damage();
|
||||
set_changed();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback();
|
||||
if (when() & FL_WHEN_CHANGED) do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
}
|
||||
/** Called after an FL_WHEN_RELEASE event is received and before the callback. */
|
||||
@ -113,7 +113,7 @@ void Fl_Valuator::handle_release() {
|
||||
clear_changed();
|
||||
// now do the callback only if slider in new position or always is on:
|
||||
if (value_ != previous_value_ || when() & FL_WHEN_NOT_CHANGED) {
|
||||
do_callback();
|
||||
do_callback(FL_REASON_RELEASED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ void Fl_Value_Input::input_cb(Fl_Widget*, void* v) {
|
||||
if (nv != t.value() || t.when() & FL_WHEN_NOT_CHANGED) {
|
||||
t.set_value(nv);
|
||||
t.set_changed();
|
||||
if (t.when()) t.do_callback();
|
||||
if (t.when()) t.do_callback(FL_REASON_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,28 +365,33 @@ void Fl_Widget::bind_deimage(Fl_Image* img) {
|
||||
|
||||
/** Calls the widget callback function with arbitrary arguments.
|
||||
|
||||
All overloads of do_callback() call this method.
|
||||
It does nothing if the widget's callback() is NULL.
|
||||
It clears the widget's \e changed flag \b after the callback was
|
||||
called unless the callback is the default callback. Hence it is not
|
||||
necessary to call clear_changed() after calling do_callback()
|
||||
in your own widget's handle() method.
|
||||
All overloads of do_callback() call this method.
|
||||
It does nothing if the widget's callback() is NULL.
|
||||
It clears the widget's \e changed flag \b after the callback was
|
||||
called unless the callback is the default callback. Hence it is not
|
||||
necessary to call clear_changed() after calling do_callback()
|
||||
in your own widget's handle() method.
|
||||
|
||||
\note It is legal to delete the widget in the callback (i.e. in user code),
|
||||
but you must not access the widget in the handle() method after
|
||||
calling do_callback() if the widget was deleted in the callback.
|
||||
We recommend to use Fl_Widget_Tracker to check whether the widget
|
||||
was deleted in the callback.
|
||||
A \p reason must be set for widgets if different actions can trigger
|
||||
the same callback.
|
||||
|
||||
\param[in] widget call the callback with \p widget as the first argument
|
||||
\param[in] arg use \p arg as the user data (second) argument
|
||||
\note It is legal to delete the widget in the callback (i.e. in user code),
|
||||
but you must not access the widget in the handle() method after
|
||||
calling do_callback() if the widget was deleted in the callback.
|
||||
We recommend to use Fl_Widget_Tracker to check whether the widget
|
||||
was deleted in the callback.
|
||||
|
||||
\see default_callback()
|
||||
\see callback()
|
||||
\see class Fl_Widget_Tracker
|
||||
*/
|
||||
\param[in] widget call the callback with \p widget as the first argument
|
||||
\param[in] arg use \p arg as the user data (second) argument
|
||||
\param[in] reason for calling this callback
|
||||
|
||||
void Fl_Widget::do_callback(Fl_Widget *widget, void *arg) {
|
||||
\see default_callback()
|
||||
\see callback()
|
||||
\see class Fl_Widget_Tracker
|
||||
\see Fl::callback_reason()
|
||||
*/
|
||||
void Fl_Widget::do_callback(Fl_Widget *widget, void *arg, Fl_Callback_Reason reason) {
|
||||
Fl::callback_reason_ = reason;
|
||||
if (!callback_) return;
|
||||
Fl_Widget_Tracker wp(this);
|
||||
callback_(widget, arg);
|
||||
|
@ -168,7 +168,11 @@ int main(int argc, char **argv) {
|
||||
browser->callback(b_cb);
|
||||
if (!browser->load(fname)) {
|
||||
fl_message("Can't load '%s'\n%s\n", fname, strerror(errno));
|
||||
exit(1);
|
||||
browser->add("This is a test of how the browser draws lines.");
|
||||
browser->add("This is a second line.");
|
||||
browser->add("This is a third.");
|
||||
browser->add("@bBold text");
|
||||
browser->add("@iItalic text");
|
||||
}
|
||||
browser->position(0);
|
||||
|
||||
|
75
test/tabs.fl
75
test/tabs.fl
@ -5,19 +5,21 @@ code_name {.cxx}
|
||||
Function {} {open
|
||||
} {
|
||||
Fl_Window foo_window {
|
||||
label {Comparison of Fl_Tab (left) vs. Fl_Wizard (right)} open selected
|
||||
xywh {516 38 660 400} type Double hide resizable
|
||||
label {Comparison of Fl_Tab (left) vs. Fl_Wizard (right)} open
|
||||
xywh {330 402 660 400} type Double resizable visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
label {class Fl_Tabs}
|
||||
xywh {95 0 130 35} labeltype ENGRAVED_LABEL labelfont 1
|
||||
}
|
||||
Fl_Tabs {} {open
|
||||
Fl_Tabs tabs_group {open
|
||||
tooltip {the various index cards test different aspects of the Fl_Tabs widget} xywh {10 35 315 260} selection_color 4 labelcolor 7 resizable
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label {Label&1}
|
||||
tooltip {this tab tests correct keyboard navigation between text input fields} xywh {10 60 315 235} selection_color 1 resizable
|
||||
callback {if (Fl::callback_reason()==FL_REASON_CLOSED)
|
||||
o->parent()->remove(o);} selected
|
||||
tooltip {this tab tests correct keyboard navigation between text input fields} xywh {10 60 315 235} selection_color 1 when 16 hide resizable
|
||||
} {
|
||||
Fl_Input {} {
|
||||
label {input:}
|
||||
@ -35,7 +37,9 @@ Function {} {open
|
||||
}
|
||||
Fl_Group {} {
|
||||
label {tab&2}
|
||||
tooltip {tab2 tests among other things the cooperation of modal windows and tabs} xywh {10 60 315 235} selection_color 2 hide
|
||||
callback {if (Fl::callback_reason()==FL_REASON_CLOSED)
|
||||
o->parent()->remove(o);} selected
|
||||
tooltip {tab2 tests among other things the cooperation of modal windows and tabs} xywh {10 60 315 235} selection_color 2 when 16 hide
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label button1
|
||||
@ -61,7 +65,9 @@ Function {} {open
|
||||
}
|
||||
Fl_Group {} {
|
||||
label {tab&3}
|
||||
tooltip {tab3 checks for correct keyboard navigation} xywh {10 60 315 235} selection_color 3 hide
|
||||
callback {if (Fl::callback_reason()==FL_REASON_CLOSED)
|
||||
o->parent()->remove(o);} selected
|
||||
tooltip {tab3 checks for correct keyboard navigation} xywh {10 60 315 235} selection_color 3 when 16 hide
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label button2
|
||||
@ -78,7 +84,9 @@ Function {} {open
|
||||
}
|
||||
Fl_Group {} {
|
||||
label {&tab4}
|
||||
tooltip {this tab shows the issue of indicating a selected tab if the tab layouts are very similar} xywh {10 60 315 235} selection_color 5 labeltype ENGRAVED_LABEL labelfont 2 hide
|
||||
callback {if (Fl::callback_reason()==FL_REASON_CLOSED)
|
||||
o->parent()->remove(o);} selected
|
||||
tooltip {this tab shows the issue of indicating a selected tab if the tab layouts are very similar} xywh {10 60 315 235} selection_color 5 labeltype ENGRAVED_LABEL labelfont 2 when 16 hide
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label button2
|
||||
@ -94,8 +102,8 @@ Function {} {open
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label {@fileprint &print}
|
||||
tooltip {tab5 verifies if visibility requests are handled correctly} xywh {10 60 315 235} hide
|
||||
label {@fileprint &print} selected
|
||||
tooltip {tab5 verifies if visibility requests are handled correctly} xywh {10 60 315 235}
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label button2
|
||||
@ -265,12 +273,53 @@ wWizard->value(wWizard->child(last));}
|
||||
tooltip {go to last page [End]} xywh {510 305 30 25} shortcut 0xff57
|
||||
}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {inputA:}
|
||||
xywh {60 310 130 25}
|
||||
Fl_Button {} {
|
||||
label {add tab}
|
||||
callback {static int n = 6;
|
||||
int X = tabs_group->x(), Y = tabs_group->y()+25;
|
||||
int W = tabs_group->w(), H = tabs_group->h()-25;
|
||||
Fl_Group::current(NULL);
|
||||
char buf[64];
|
||||
snprintf(buf, 62, "tab%d", n);
|
||||
Fl_Group* new_tab = new Fl_Group(X, Y, W, H);
|
||||
new_tab->copy_label(buf);
|
||||
new_tab->when(FL_WHEN_CLOSED);
|
||||
new_tab->callback((Fl_Callback*)cb_tab);
|
||||
snprintf(buf, 62, "Empty tab %d.", n);
|
||||
Fl_Box* box = new Fl_Box(X+5, Y+5, W-10, H-10);
|
||||
box->copy_label(buf);
|
||||
box->align(Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE));
|
||||
tabs_group->add(new_tab);
|
||||
n++;}
|
||||
tooltip {Add more tabs to check overflow handling.} xywh {60 309 70 25}
|
||||
}
|
||||
Fl_Choice {} {
|
||||
label {overflow:} open
|
||||
tooltip {Change how Fl_Tabs handles more tabs than fit into the tabs space.} xywh {212 309 95 25} down_box BORDER_BOX
|
||||
} {
|
||||
MenuItem {} {
|
||||
label compress
|
||||
callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_COMPRESS);}
|
||||
xywh {0 0 31 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
label clip
|
||||
callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_CLIP);}
|
||||
xywh {0 0 31 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
label pulldown
|
||||
callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_PULLDOWN);}
|
||||
xywh {0 0 31 20}
|
||||
}
|
||||
MenuItem {} {
|
||||
label drag
|
||||
callback {tabs_group->handle_overflow(Fl_Tabs::OVERFLOW_DRAG);}
|
||||
xywh {0 0 31 20}
|
||||
}
|
||||
}
|
||||
Fl_Input {} {
|
||||
label {inputB:}
|
||||
label {input:}
|
||||
xywh {60 345 250 25}
|
||||
}
|
||||
Fl_Button {} {
|
||||
|
Loading…
Reference in New Issue
Block a user