Adds compact buttons feature to create keypads.
See test/buttons for an example.
This commit is contained in:
parent
502fa72eb4
commit
5e8adebac2
@ -51,7 +51,11 @@ 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_Button now supports a compact flag that visually groups closely set
|
||||
buttons into keypads.
|
||||
- Fl_Tabs now supports close buttons for individual tabs.
|
||||
- Fl_Tabs now support four different modes for handling an
|
||||
overflowing number of 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
|
||||
|
@ -79,6 +79,7 @@ class FL_EXPORT Fl_Button : public Fl_Widget {
|
||||
char value_;
|
||||
char oldval;
|
||||
uchar down_box_;
|
||||
uchar compact_;
|
||||
|
||||
protected:
|
||||
|
||||
@ -167,6 +168,14 @@ public:
|
||||
|
||||
/// (for backwards compatibility)
|
||||
void down_color(unsigned c) {selection_color(c);}
|
||||
|
||||
// handle flag for compact buttons, documentation in source code
|
||||
void compact(uchar v);
|
||||
|
||||
/// Return true if buttons are rendered as compact buttons.
|
||||
/// \return 0 if compact mode is off, 1 if it is on
|
||||
/// \see compact(bool)
|
||||
uchar compact() { return compact_; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "Fl_Button_Type.h"
|
||||
|
||||
#include "Fd_Snap_Action.h"
|
||||
#include "file.h"
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
@ -34,6 +35,9 @@
|
||||
#include <FL/Fl_Repeat_Button.H>
|
||||
#include <FL/Fl_Round_Button.H>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
// ---- Button Types --------------------------------------------------- MARK: -
|
||||
|
||||
@ -61,6 +65,30 @@ Fl_Widget *Fl_Button_Type::widget(int x, int y, int w, int h) {
|
||||
return new Fl_Button(x, y, w, h, "Button");
|
||||
}
|
||||
|
||||
void Fl_Button_Type::write_properties(Fd_Project_Writer &f) {
|
||||
Fl_Widget_Type::write_properties(f);
|
||||
Fl_Button *btn = (Fl_Button*)o;
|
||||
if (btn->compact()) {
|
||||
f.write_string("compact");
|
||||
f.write_string("%d", btn->compact());
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Button_Type::read_property(Fd_Project_Reader &f, const char *c) {
|
||||
Fl_Button *btn = (Fl_Button*)o;
|
||||
if (!strcmp(c, "compact")) {
|
||||
btn->compact((uchar)atol(f.read_word()));
|
||||
} else {
|
||||
Fl_Widget_Type::read_property(f, c);
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Button_Type::copy_properties() {
|
||||
Fl_Widget_Type::copy_properties();
|
||||
Fl_Button *s = (Fl_Button*)o, *d = (Fl_Button*)live_widget;
|
||||
d->compact(s->compact());
|
||||
}
|
||||
|
||||
Fl_Button_Type Fl_Button_type;
|
||||
|
||||
|
||||
|
@ -35,6 +35,10 @@ public:
|
||||
int is_button() const FL_OVERRIDE { return 1; }
|
||||
ID id() const FL_OVERRIDE { return ID_Button; }
|
||||
bool is_a(ID inID) const FL_OVERRIDE { return (inID==ID_Button) ? true : super::is_a(inID); }
|
||||
void write_properties(Fd_Project_Writer &f) FL_OVERRIDE;
|
||||
void read_property(Fd_Project_Reader &f, const char *) FL_OVERRIDE;
|
||||
void copy_properties() FL_OVERRIDE;
|
||||
|
||||
};
|
||||
|
||||
extern Fl_Button_Type Fl_Button_type;
|
||||
|
@ -1081,6 +1081,39 @@ void down_box_cb(Fl_Choice* i, void *v) {
|
||||
}
|
||||
}
|
||||
|
||||
void compact_cb(Fl_Light_Button* i, void* v) {
|
||||
if (v == LOAD) {
|
||||
uchar n;
|
||||
if (current_widget->is_a(Fl_Type::ID_Button)) {
|
||||
n = ((Fl_Button*)(current_widget->o))->compact();
|
||||
i->value(n);
|
||||
i->show();
|
||||
} else {
|
||||
i->hide();
|
||||
}
|
||||
} else {
|
||||
int mod = 0;
|
||||
uchar n = (uchar)i->value();
|
||||
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
|
||||
if (o->selected && o->is_a(Fl_Type::ID_Button)) {
|
||||
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
|
||||
uchar v = ((Fl_Button*)(q->o))->compact();
|
||||
if (n != v) {
|
||||
if (!mod) {
|
||||
mod = 1;
|
||||
undo_checkpoint();
|
||||
}
|
||||
((Fl_Button*)(q->o))->compact(n);
|
||||
q->redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mod) set_modflag(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Fl_Menu_Item whenmenu[] = {
|
||||
@ -3039,6 +3072,7 @@ void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) {
|
||||
if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var,
|
||||
boxname(b->down_box()));
|
||||
if (b->value()) f.write_c("%s%s->value(1);\n", f.indent(), var);
|
||||
if (b->compact()) f.write_c("%s%s->compact(%d);\n", f.indent(), var, b->compact());
|
||||
} else if (is_a(Fl_Type::ID_Input_Choice)) {
|
||||
Fl_Input_Choice* b = (Fl_Input_Choice*)o;
|
||||
if (b->down_box()) f.write_c("%s%s->down_box(FL_%s);\n", f.indent(), var,
|
||||
|
@ -1239,18 +1239,21 @@ ped using octal notation `\\0123`. If this option is checked, Fluid will write\
|
||||
{ preset_choice[0] = new Fl_Button(85, 107, 78, 20, "Application");
|
||||
preset_choice[0]->type(102);
|
||||
preset_choice[0]->value(1);
|
||||
preset_choice[0]->compact(1);
|
||||
preset_choice[0]->selection_color(FL_DARK2);
|
||||
preset_choice[0]->labelsize(11);
|
||||
preset_choice[0]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(0));
|
||||
} // Fl_Button* preset_choice[0]
|
||||
{ preset_choice[1] = new Fl_Button(163, 107, 79, 20, "Dialog");
|
||||
preset_choice[1]->type(102);
|
||||
preset_choice[1]->compact(1);
|
||||
preset_choice[1]->selection_color(FL_DARK2);
|
||||
preset_choice[1]->labelsize(11);
|
||||
preset_choice[1]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(1));
|
||||
} // Fl_Button* preset_choice[1]
|
||||
{ preset_choice[2] = new Fl_Button(242, 107, 78, 20, "Toolbox");
|
||||
preset_choice[2]->type(102);
|
||||
preset_choice[2]->compact(1);
|
||||
preset_choice[2]->selection_color(FL_DARK2);
|
||||
preset_choice[2]->labelsize(11);
|
||||
preset_choice[2]->callback((Fl_Callback*)edit_layout_preset_cb, (void*)(2));
|
||||
|
@ -107,7 +107,7 @@ decl {void scheme_cb(Fl_Scheme_Choice *, void *);} {public local
|
||||
Function {make_settings_window()} {open
|
||||
} {
|
||||
Fl_Window settings_window {
|
||||
label {FLUID Settings} open selected
|
||||
label {FLUID Settings} open
|
||||
xywh {423 204 340 580} type Double align 80 non_modal visible
|
||||
} {
|
||||
Fl_Tabs w_settings_tabs {
|
||||
@ -115,7 +115,7 @@ Function {make_settings_window()} {open
|
||||
xywh {10 10 320 530} selection_color 12 labelsize 11 labelcolor 255
|
||||
} {
|
||||
Fl_Group {} {
|
||||
label General open
|
||||
label General open selected
|
||||
image {icons/general_64.png} compress_image 1 xywh {10 60 320 480} labelsize 11
|
||||
code0 {o->image()->scale(36, 24);}
|
||||
} {
|
||||
@ -471,19 +471,19 @@ g_layout_list.update_dialogs();}
|
||||
label Application
|
||||
user_data 0 user_data_type long
|
||||
callback edit_layout_preset_cb
|
||||
xywh {85 107 78 20} type Radio value 1 selection_color 45 labelsize 11
|
||||
xywh {85 107 78 20} type Radio value 1 selection_color 45 labelsize 11 compact 1
|
||||
}
|
||||
Fl_Button {preset_choice[1]} {
|
||||
label Dialog
|
||||
user_data 1 user_data_type long
|
||||
callback edit_layout_preset_cb
|
||||
xywh {163 107 79 20} type Radio selection_color 45 labelsize 11
|
||||
xywh {163 107 79 20} type Radio selection_color 45 labelsize 11 compact 1
|
||||
}
|
||||
Fl_Button {preset_choice[2]} {
|
||||
label Toolbox
|
||||
user_data 2 user_data_type long
|
||||
callback edit_layout_preset_cb
|
||||
xywh {242 107 78 20} type Radio selection_color 45 labelsize 11
|
||||
xywh {242 107 78 20} type Radio selection_color 45 labelsize 11 compact 1
|
||||
}
|
||||
}
|
||||
Fl_Box {} {
|
||||
|
@ -803,10 +803,16 @@ sized to fit the container.");
|
||||
} // Fl_Menu_Button* o
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ Fl_Box* o = new Fl_Box(95, 140, 300, 40);
|
||||
{ Fl_Box* o = new Fl_Box(95, 165, 300, 40);
|
||||
o->labelsize(11);
|
||||
Fl_Group::current()->resizable(o);
|
||||
} // Fl_Box* o
|
||||
{ Fl_Light_Button* o = new Fl_Light_Button(95, 140, 90, 20, "Compact");
|
||||
o->tooltip("use compact box types for closely set buttons");
|
||||
o->selection_color((Fl_Color)1);
|
||||
o->labelsize(11);
|
||||
o->callback((Fl_Callback*)compact_cb);
|
||||
} // Fl_Light_Button* o
|
||||
o->end();
|
||||
} // Fl_Group* o
|
||||
{ Fl_Group* o = new Fl_Group(10, 30, 400, 330, "C++");
|
||||
|
@ -655,7 +655,12 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize
|
||||
} {}
|
||||
}
|
||||
Fl_Box {} {
|
||||
xywh {95 140 300 40} labelsize 11 resizable
|
||||
xywh {95 165 300 40} labelsize 11 resizable
|
||||
}
|
||||
Fl_Light_Button {} {
|
||||
label Compact
|
||||
callback compact_cb
|
||||
tooltip {use compact box types for closely set buttons} xywh {95 140 90 20} selection_color 1 labelsize 11
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
|
@ -113,6 +113,7 @@ extern void textsize_cb(Fl_Value_Input*, void*);
|
||||
extern void textcolor_cb(Fl_Button*, void*);
|
||||
extern Fl_Button *w_textcolor;
|
||||
extern void textcolor_menu_cb(Fl_Menu_Button*, void*);
|
||||
extern void compact_cb(Fl_Light_Button*, void*);
|
||||
extern void subclass_cb(Fl_Input*, void*);
|
||||
extern void subtype_cb(Fl_Choice*, void*);
|
||||
extern void name_cb(Fl_Input*, void*);
|
||||
|
@ -1143,12 +1143,12 @@ void fl_throw_focus(Fl_Widget *o) {
|
||||
// the inactive widget and all inactive parent groups.
|
||||
//
|
||||
// This is used to send FL_SHORTCUT events to the Fl::belowmouse() widget
|
||||
// in case the target widget itself is inactive_r(). In this case the event
|
||||
// in case the target widget itself is !active_r(). In this case the event
|
||||
// is sent to the first active_r() parent.
|
||||
//
|
||||
// This prevents sending events to inactive widgets that might get the
|
||||
// input focus otherwise. The search is fast and light and avoids calling
|
||||
// inactive_r() multiple times.
|
||||
// !active_r() multiple times.
|
||||
// See STR #3216.
|
||||
//
|
||||
// Returns: first active_r() widget "above" the widget wi or NULL if
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include <FL/Fl_Radio_Button.H>
|
||||
#include <FL/Fl_Toggle_Button.H>
|
||||
@ -67,7 +68,29 @@ void Fl_Button::setonly() { // set this radio button on, turn others off
|
||||
void Fl_Button::draw() {
|
||||
if (type() == FL_HIDDEN_BUTTON) return;
|
||||
Fl_Color col = value() ? selection_color() : color();
|
||||
draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
|
||||
Fl_Boxtype bt = value() ? (down_box()?down_box():fl_down(box())) : box();
|
||||
if (compact_ && parent()) {
|
||||
Fl_Widget *p = parent();
|
||||
int px, py, pw = p->w(), ph = p->h();
|
||||
if (p->as_window()) { px = 0; py = 0; } else { px = p->x(); py = p->y(); }
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
draw_box(bt, px, py, pw, ph, col);
|
||||
fl_pop_clip();
|
||||
const int hh = 5, ww = 5;
|
||||
Fl_Color divider_color = fl_gray_ramp(FL_NUM_GRAY/3);
|
||||
if (!active_r())
|
||||
divider_color = fl_inactive(divider_color);
|
||||
if (x()+w() != px+pw) {
|
||||
fl_color(divider_color);
|
||||
fl_yxline(x()+w()-1, y()+hh, y()+h()-1-hh);
|
||||
}
|
||||
if (y()+h() != py+ph) {
|
||||
fl_color(divider_color);
|
||||
fl_xyline(x()+ww, y()+h()-1, x()+w()-1-ww);
|
||||
}
|
||||
} else {
|
||||
draw_box(bt, col);
|
||||
}
|
||||
draw_backdrop();
|
||||
if (labeltype() == FL_NORMAL_LABEL && value()) {
|
||||
Fl_Color c = labelcolor();
|
||||
@ -215,11 +238,14 @@ void Fl_Button::key_release_timeout(void *d)
|
||||
\param[in] L widget label, default is no label
|
||||
*/
|
||||
Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *L)
|
||||
: Fl_Widget(X,Y,W,H,L) {
|
||||
: Fl_Widget(X,Y,W,H,L),
|
||||
shortcut_(0),
|
||||
value_(0),
|
||||
oldval(0),
|
||||
down_box_(FL_NO_BOX),
|
||||
compact_(0)
|
||||
{
|
||||
box(FL_UP_BOX);
|
||||
down_box(FL_NO_BOX);
|
||||
value_ = oldval = 0;
|
||||
shortcut_ = 0;
|
||||
set_flag(SHORTCUT_LABEL);
|
||||
}
|
||||
|
||||
@ -249,3 +275,23 @@ Fl_Toggle_Button::Fl_Toggle_Button(int X,int Y,int W,int H,const char *L)
|
||||
{
|
||||
type(FL_TOGGLE_BUTTON);
|
||||
}
|
||||
|
||||
/**
|
||||
Decide if buttons should be rendered in compact mode.
|
||||
|
||||
\image html compact_buttons_gtk.png "compact button keypad using GTK+ Scheme"
|
||||
\image latex compact_buttons_gtk.png "compact button keypad using GTK+ Scheme" width=4cm
|
||||
|
||||
\image html compact_buttons_gleam.png "compact buttons in Gleam"
|
||||
\image latex compact_buttons_gleam.png "compact buttons in Gleam" width=4cm
|
||||
|
||||
In compact mode, the button's surrounding border is altered to visually signal
|
||||
that multiple buttons are functionally linked together. To ensure the correct
|
||||
rendering of buttons in compact mode, all buttons must be part of the same
|
||||
group, positioned close to each other, and aligned with the edges of the
|
||||
group. Any button outlines not in contact with the parent group's outline
|
||||
will be displayed as separators.
|
||||
|
||||
\param[in] v switch compact mode on (1) or off (0)
|
||||
*/
|
||||
void Fl_Button::compact(uchar v) { compact_ = v; }
|
||||
|
@ -64,7 +64,7 @@ const uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'
|
||||
Gets the drawing color to be used for the background of a box.
|
||||
|
||||
This method is only useful inside box drawing code. It returns the
|
||||
color to be used, either fl_inactive(c) if the widget is inactive_r()
|
||||
color to be used, either fl_inactive(c) if the widget is !active_r()
|
||||
or \p c otherwise.
|
||||
*/
|
||||
Fl_Color Fl::box_color(Fl_Color c) {
|
||||
@ -84,7 +84,7 @@ Fl_Color Fl::box_color(Fl_Color c) {
|
||||
This method is only useful inside box drawing code. Whenever a box is
|
||||
drawn with one of the standard box drawing methods, a static variable
|
||||
is set depending on the widget's current state - if the widget is
|
||||
inactive_r() then the internal variable is false (0), otherwise it
|
||||
!active_r() then the internal variable is false (0), otherwise it
|
||||
is true (1). This is faster than calling Fl_Widget::active_r()
|
||||
because the state is cached.
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <FL/Fl_Scheme_Choice.H>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Fl_Window *window = new Fl_Window(320, 170);
|
||||
Fl_Window *window = new Fl_Window(420, 170);
|
||||
Fl_Button *b1 = new Fl_Button(10, 10, 130, 30, "Fl_Button");
|
||||
b1->tooltip("Fl_Button");
|
||||
Fl_Button *b2 = new Fl_Return_Button(150, 10, 160, 30, "Fl_Return_Button");
|
||||
@ -39,6 +39,25 @@ int main(int argc, char **argv) {
|
||||
Fl_Button *b6 = new Fl_Check_Button(150, 90, 160, 30, "Fl_Check_Button");
|
||||
b6->tooltip("Fl_Check_Button");
|
||||
|
||||
Fl_Group *keypad = new Fl_Group(320, 10, 90, 120);
|
||||
Fl_Button *kp[11];
|
||||
kp[7] = new Fl_Button(320, 10, 30, 30, "7");
|
||||
kp[8] = new Fl_Button(350, 10, 30, 30, "8");
|
||||
kp[9] = new Fl_Button(380, 10, 30, 30, "9");
|
||||
kp[4] = new Fl_Button(320, 40, 30, 30, "4");
|
||||
kp[5] = new Fl_Button(350, 40, 30, 30, "5");
|
||||
kp[6] = new Fl_Button(380, 40, 30, 30, "6");
|
||||
kp[1] = new Fl_Button(320, 70, 30, 30, "1");
|
||||
kp[2] = new Fl_Button(350, 70, 30, 30, "2");
|
||||
kp[3] = new Fl_Button(380, 70, 30, 30, "3");
|
||||
kp[0] = new Fl_Button(320, 100, 60, 30, "0");
|
||||
kp[10] = new Fl_Button(380, 100, 30, 30, ".");
|
||||
for (int i=0; i<11; i++) {
|
||||
kp[i]->compact(1);
|
||||
kp[i]->selection_color(FL_SELECTION_COLOR);
|
||||
}
|
||||
keypad->end();
|
||||
|
||||
// Add a scheme choice widget for easier testing. Position the widget at
|
||||
// the right window border so the menu popup doesn't cover the check boxes etc.
|
||||
Fl_Scheme_Choice *scheme_choice = new Fl_Scheme_Choice(180, 130, 130, 30, "Active FLTK Scheme:");
|
||||
|
@ -13,44 +13,52 @@ Function {} {open
|
||||
xywh {462 303 420 369} type Double resizable visible
|
||||
} {
|
||||
Fl_Group the_group {
|
||||
label {activate()/deactivate() called on this Fl_Group} open selected
|
||||
label {activate()/deactivate() called on this Fl_Group} open
|
||||
xywh {25 25 375 295} box ENGRAVED_FRAME align 17 resizable
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label button
|
||||
xywh {50 50 105 25}
|
||||
xywh {50 50 105 20}
|
||||
}
|
||||
Fl_Light_Button {} {
|
||||
label {light button}
|
||||
xywh {50 80 105 25} value 1 align 16
|
||||
xywh {50 75 105 20} value 1 align 16
|
||||
}
|
||||
Fl_Group {} {open
|
||||
xywh {50 100 105 20}
|
||||
} {
|
||||
Fl_Button {} {
|
||||
label On selected
|
||||
xywh {50 100 52 20} type Radio value 1 compact 1
|
||||
}
|
||||
Fl_Button {} {
|
||||
label Off selected
|
||||
xywh {102 100 53 20} type Radio compact 1
|
||||
}
|
||||
}
|
||||
Fl_Group {} {
|
||||
label {Child group} open
|
||||
xywh {50 130 105 125} box DOWN_FRAME
|
||||
xywh {50 150 105 105} box DOWN_FRAME
|
||||
} {
|
||||
Fl_Check_Button {} {
|
||||
label red
|
||||
xywh {54 172 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 1 labelcolor 1
|
||||
xywh {54 192 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 1 labelcolor 1
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label green
|
||||
xywh {54 192 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 2 labelcolor 2
|
||||
xywh {54 212 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 2 labelcolor 2
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label blue
|
||||
xywh {54 212 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 4 labelcolor 4
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label white
|
||||
xywh {54 232 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 55 labelcolor 55
|
||||
xywh {54 232 97 20} type Radio down_box DIAMOND_DOWN_BOX selection_color 4 labelcolor 4
|
||||
}
|
||||
Fl_Check_Button {} {
|
||||
label check
|
||||
xywh {54 132 97 20} down_box DOWN_BOX
|
||||
xywh {54 152 97 20} down_box DOWN_BOX
|
||||
}
|
||||
Fl_Round_Button {} {
|
||||
label round
|
||||
xywh {54 152 97 20} down_box ROUND_DOWN_BOX
|
||||
xywh {54 172 97 20} down_box ROUND_DOWN_BOX
|
||||
}
|
||||
}
|
||||
Fl_Slider {} {
|
||||
|
Loading…
Reference in New Issue
Block a user