summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Fl_Choice.cxx93
-rw-r--r--src/Fl_Counter.cxx155
-rw-r--r--src/Fl_Menu.cxx3
-rw-r--r--src/Fl_Menu_Button.cxx3
-rw-r--r--src/Fl_Scrollbar.cxx83
-rw-r--r--src/Fl_Spinner.cxx32
-rw-r--r--src/Makefile1
-rw-r--r--src/fl_boxtype.cxx4
-rw-r--r--src/fl_draw.cxx7
-rw-r--r--src/fl_draw_arrow.cxx256
11 files changed, 486 insertions, 152 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b8b773d53..a912dc5c3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -136,6 +136,7 @@ set (CPPFILES
fl_curve.cxx
fl_diamond_box.cxx
fl_draw.cxx
+ fl_draw_arrow.cxx
fl_draw_pixmap.cxx
fl_encoding_latin1.cxx
fl_encoding_mac_roman.cxx
diff --git a/src/Fl_Choice.cxx b/src/Fl_Choice.cxx
index 20b374442..c23010c07 100644
--- a/src/Fl_Choice.cxx
+++ b/src/Fl_Choice.cxx
@@ -1,7 +1,7 @@
//
// Choice widget for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -22,6 +22,11 @@
// Emulates the Forms choice widget. This is almost exactly the same
// as an Fl_Menu_Button. The only difference is the appearance of the
// button: it draws the text of the current pick and a down-arrow.
+// The exact layout and the type of arrow can vary by FLTK scheme.
+
+// FIXME: all such variations should be implemented in the "scheme code",
+// hopefully in a future class derived from a base class Fl_Scheme or similar.
+// Albrecht
void Fl_Choice::draw() {
Fl_Boxtype btype = Fl::scheme() ? FL_UP_BOX // non-default uses up box
@@ -32,70 +37,74 @@ void Fl_Choice::draw() {
// Arrow area
int H = h() - 2 * dy;
int W = Fl::is_scheme("gtk+") ? 20 : // gtk+ -- fixed size
- Fl::is_scheme("gleam") ? 20 : // gleam -- fixed size
- Fl::is_scheme("plastic") ? ((H > 20) ? 20 : H) // plastic: shrink if H<20
- : ((H > 20) ? 20 : H); // default: shrink if H<20
+ Fl::is_scheme("gleam") ? 20 // gleam -- fixed size
+ : ((H > 20) ? 20 : H); // else: shrink if H<20
int X = x() + w() - W - dx;
int Y = y() + dy;
- // Arrow object
- int w1 = (W - 4) / 3; if (w1 < 1) w1 = 1;
- int x1 = X + (W - 2 * w1 - 1) / 2;
- int y1 = Y + (H - w1 - 1) / 2;
+ Fl_Rect ab(X, Y, W, H); // arrow box
+ int active = active_r();
+ Fl_Color arrow_color = active ? labelcolor() : fl_inactive(labelcolor());
+ Fl_Color box_color = color();
+
+ // From "original" code: modify the box color *only* for the default scheme.
+ // This is weird (why?). I believe we should either make sure that the text
+ // color contrasts well when the text is rendered *or* we should do this for
+ // *all* schemes. Anyway, adapting the old code... (Albrecht)
+
+ if (!Fl::scheme()) { // default scheme only, see comment above
+ if (fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) == textcolor())
+ box_color = FL_BACKGROUND2_COLOR;
+ else
+ box_color = fl_lighter(color());
+ }
- if (Fl::scheme()) {
- // NON-DEFAULT SCHEME
+ // Draw the widget box
- // Draw widget box
- draw_box(btype, color());
+ draw_box(btype, box_color);
- // Draw arrow area
- fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
- if (Fl::is_scheme("plastic")) {
- // Show larger up/down arrows...
- fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3);
- fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1);
- } else {
- // Show smaller up/down arrows with a divider...
- x1 = x() + w() - 13 - dx;
- y1 = y() + h() / 2;
- fl_polygon(x1, y1 - 2, x1 + 3, y1 - 5, x1 + 6, y1 - 2);
- fl_polygon(x1, y1 + 2, x1 + 3, y1 + 5, x1 + 6, y1 + 2);
+ // Arrow box or horizontal divider line, depending on the current scheme
+
+ // Scheme: Box or divider line
+ // ----------------------------------------
+ // Default (None): Arrow box (FL_UP_BOX)
+ // gtk+, gleam: Divider line
+ // else: Nothing (!)
+
+ if (Fl::scheme()) {
+ if (Fl::is_scheme("gtk+") ||
+ Fl::is_scheme("gleam")) {
+ // draw the divider
+ int x1 = x() + w() - 20 - dx;
+ int y1 = y() + h() / 2;
fl_color(fl_darker(color()));
- fl_yxline(x1 - 7, y1 - 8, y1 + 8);
+ fl_yxline(x1, y1 - 8, y1 + 8);
fl_color(fl_lighter(color()));
- fl_yxline(x1 - 6, y1 - 8, y1 + 8);
- }
- } else {
- // DEFAULT SCHEME
-
- // Draw widget box
- if (fl_contrast(textcolor(), FL_BACKGROUND2_COLOR) == textcolor()) {
- draw_box(btype, FL_BACKGROUND2_COLOR);
- } else {
- draw_box(btype, fl_lighter(color()));
+ fl_yxline(x1 + 1, y1 - 8, y1 + 8);
}
-
- // Draw arrow area
- draw_box(FL_UP_BOX,X,Y,W,H,color());
- fl_color(active_r() ? labelcolor() : fl_inactive(labelcolor()));
- fl_polygon(x1, y1, x1 + w1, y1 + w1, x1 + 2 * w1, y1);
+ } else { // Default scheme ("None")
+ // Draw arrow box
+ draw_box(FL_UP_BOX, X, Y, W, H, color());
+ ab.inset(FL_UP_BOX);
}
+ // Draw choice arrow(s)
+ fl_draw_arrow(ab, FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color);
+
W += 2 * dx;
// Draw menu item's label
if (mvalue()) {
Fl_Menu_Item m = *mvalue();
- if (active_r()) m.activate(); else m.deactivate();
+ if (active) m.activate(); else m.deactivate();
// Clip
int xx = x() + dx, yy = y() + dy + 1, ww = w() - W, hh = H - 2;
fl_push_clip(xx, yy, ww, hh);
- if ( Fl::scheme()) {
+ if (Fl::scheme()) {
Fl_Label l;
l.value = m.text;
l.image = 0;
diff --git a/src/Fl_Counter.cxx b/src/Fl_Counter.cxx
index ed856c208..9a9b4bbfc 100644
--- a/src/Fl_Counter.cxx
+++ b/src/Fl_Counter.cxx
@@ -19,67 +19,118 @@
#include <FL/Fl_Simple_Counter.H>
#include <FL/fl_draw.H>
-void Fl_Counter::draw() {
- int i; Fl_Boxtype boxtype[5];
- Fl_Color selcolor;
-
- boxtype[0] = box();
- if (boxtype[0] == FL_UP_BOX) boxtype[0] = FL_DOWN_BOX;
- if (boxtype[0] == FL_THIN_UP_BOX) boxtype[0] = FL_THIN_DOWN_BOX;
- for (i=1; i<5; i++)
- if (mouseobj == i)
- boxtype[i] = fl_down(box());
- else
- boxtype[i] = box();
+// This struct describes the four arrow boxes
+struct arrow_box {
+ int width;
+ Fl_Arrow_Type arrow_type;
+ Fl_Boxtype boxtype;
+ Fl_Orientation orientation;
+ arrow_box() { // constructor
+ width = 0;
+ boxtype = FL_NO_BOX;
+ orientation = FL_ORIENT_RIGHT;
+ arrow_type = FL_ARROW_SINGLE;
+ }
+};
- int xx[5], ww[5];
- if (type() == FL_NORMAL_COUNTER) {
- int W = w()*15/100;
- xx[1] = x(); ww[1] = W;
- xx[2] = x()+1*W; ww[2] = W;
- xx[0] = x()+2*W; ww[0] = w()-4*W;
- xx[3] = x()+w()-2*W; ww[3] = W;
- xx[4] = x()+w()-1*W; ww[4] = W;
+/**
+ Compute sizes (widths) of arrow boxes.
+
+ This method computes the two sizes of the arrow boxes of Fl_Counter.
+ You can override it in a subclass if you want to draw fancy arrows
+ or change the layout. However, the basic layout is fixed and can't
+ be changed w/o overriding the draw() and handle() methods.
+
+ Basic layout:
+ \code
+ +------+-----+-------------+-----+------+
+ | << | < | value | > | >> |
+ +------+-----+-------------+-----+------+
+ \endcode
+
+ The returned value \p w2 should be zero if the counter type() is FL_SIMPLE_COUNTER.
+
+ \param[out] w1 width of single arrow box
+ \param[out] w2 width of double arrow box
+*/
+void Fl_Counter::arrow_widths(int &w1, int &w2) {
+ if (type() == FL_SIMPLE_COUNTER) {
+ w1 = w() * 20/100;
+ w2 = 0;
} else {
- int W = w()*20/100;
- xx[1] = 0; ww[1] = 0;
- xx[2] = x(); ww[2] = W;
- xx[0] = x()+W; ww[0] = w()-2*W;
- xx[3] = x()+w()-1*W; ww[3] = W;
- xx[4] = 0; ww[4] = 0;
+ w1 = w() * 13/100;
+ w2 = w() * 17/100;
}
+ // limit arrow box sizes to reserve more space for the text box
+ if (w1 > 18) w1 = 18;
+ if (w2 > 24) w2 = 24;
+}
+
+void Fl_Counter::draw() {
+ struct arrow_box ab[4];
+
+ // text box setup
+ Fl_Boxtype tbt = box();
+ if (tbt == FL_UP_BOX) tbt = FL_DOWN_BOX;
+ if (tbt == FL_THIN_UP_BOX) tbt = FL_THIN_DOWN_BOX;
- draw_box(boxtype[0], xx[0], y(), ww[0], h(), FL_BACKGROUND2_COLOR);
+ // array boxes
+ for (int i = 0; i < 4; i++) {
+ if (mouseobj_ == i + 1)
+ ab[i].boxtype = fl_down(box());
+ else
+ ab[i].boxtype = box();
+ }
+
+ ab[0].arrow_type = ab[3].arrow_type = FL_ARROW_DOUBLE; // first and last arrow
+ ab[0].orientation = ab[1].orientation = FL_ORIENT_LEFT; // left arrows
+
+ int w1 = 0, w2 = 0;
+ arrow_widths(w1, w2);
+ if (type() == FL_SIMPLE_COUNTER)
+ w2 = 0;
+
+ ab[0].width = ab[3].width = w2; // double arrows
+ ab[1].width = ab[2].width = w1; // single arrows
+
+ int tw = w() - 2 * (w1 + w2); // text box width
+ int tx = x() + w1 + w2; // text box position
+
+ // printf("w() = %3d, w1 = %3d, w2 = %3d, tw = %3d\n", w(), w1, w2, tw);
+
+ // always draw text box and text
+ draw_box(tbt, tx, y(), tw, h(), FL_BACKGROUND2_COLOR);
fl_font(textfont(), textsize());
fl_color(active_r() ? textcolor() : fl_inactive(textcolor()));
char str[128]; format(str);
- fl_draw(str, xx[0], y(), ww[0], h(), FL_ALIGN_CENTER);
- if (Fl::focus() == this) draw_focus(boxtype[0], xx[0], y(), ww[0], h());
+ fl_draw(str, tx, y(), tw, h(), FL_ALIGN_CENTER);
+ if (Fl::focus() == this) draw_focus(tbt, tx, y(), tw, h());
if (!(damage()&FL_DAMAGE_ALL)) return; // only need to redraw text
+ Fl_Color arrow_color;
if (active_r())
- selcolor = labelcolor();
+ arrow_color = labelcolor();
else
- selcolor = fl_inactive(labelcolor());
+ arrow_color = fl_inactive(labelcolor());
- if (type() == FL_NORMAL_COUNTER) {
- draw_box(boxtype[1], xx[1], y(), ww[1], h(), color());
- fl_draw_symbol("@-4<<", xx[1], y(), ww[1], h(), selcolor);
- }
- draw_box(boxtype[2], xx[2], y(), ww[2], h(), color());
- fl_draw_symbol("@-4<", xx[2], y(), ww[2], h(), selcolor);
- draw_box(boxtype[3], xx[3], y(), ww[3], h(), color());
- fl_draw_symbol("@-4>", xx[3], y(), ww[3], h(), selcolor);
- if (type() == FL_NORMAL_COUNTER) {
- draw_box(boxtype[4], xx[4], y(), ww[4], h(), color());
- fl_draw_symbol("@-4>>", xx[4], y(), ww[4], h(), selcolor);
+ // draw arrow boxes
+ int xo = x();
+ for (int i = 0; i < 4; i++) {
+ if (ab[i].width > 0) {
+ draw_box(ab[i].boxtype, xo, y(), ab[i].width, h(), color());
+ Fl_Rect bb(xo, y(), ab[i].width, h(), ab[i].boxtype);
+ fl_draw_arrow(bb, ab[i].arrow_type, ab[i].orientation, arrow_color);
+ xo += ab[i].width;
+ }
+ if (i == 1) xo += tw;
}
-}
+
+} // draw()
void Fl_Counter::increment_cb() {
- if (!mouseobj) return;
+ if (!mouseobj_) return;
double v = value();
- switch (mouseobj) {
+ switch (mouseobj_) {
case 1: v -= lstep_; break;
case 2: v = increment(v, -1); break;
case 3: v = increment(v, 1); break;
@@ -95,7 +146,7 @@ void Fl_Counter::repeat_callback(void* v) {
Fl_Counter* b = (Fl_Counter*)v;
int buttons = Fl::event_state() & FL_BUTTONS; // any mouse button pressed
int focus = (Fl::focus() == b); // the widget has focus
- if (b->mouseobj && buttons && focus) {
+ if (b->mouseobj_ && buttons && focus) {
Fl::add_timeout(REPEAT, repeat_callback, b);
b->increment_cb();
}
@@ -120,9 +171,9 @@ int Fl_Counter::handle(int event) {
int i;
switch (event) {
case FL_RELEASE:
- if (mouseobj) {
+ if (mouseobj_) {
Fl::remove_timeout(repeat_callback, this);
- mouseobj = 0;
+ mouseobj_ = 0;
redraw();
}
handle_release();
@@ -135,9 +186,9 @@ int Fl_Counter::handle(int event) {
}
case FL_DRAG:
i = calc_mouseobj();
- if (i != mouseobj) {
+ if (i != mouseobj_) {
Fl::remove_timeout(repeat_callback, this);
- mouseobj = (uchar)i;
+ mouseobj_ = (uchar)i;
if (i > 0)
Fl::add_timeout(INITIALREPEAT, repeat_callback, this);
Fl_Widget_Tracker wp(this);
@@ -159,7 +210,7 @@ int Fl_Counter::handle(int event) {
}
// break not required because of switch...
case FL_UNFOCUS :
- mouseobj = 0;
+ mouseobj_ = 0;
/* FALLTHROUGH */
case FL_FOCUS :
if (Fl::visible_focus()) {
@@ -195,7 +246,7 @@ Fl_Counter::Fl_Counter(int X, int Y, int W, int H, const char* L)
bounds(-1000000.0, 1000000.0);
Fl_Valuator::step(1, 10);
lstep_ = 1.0;
- mouseobj = 0;
+ mouseobj_ = 0;
textfont_ = FL_HELVETICA;
textsize_ = FL_NORMAL_SIZE;
textcolor_ = FL_FOREGROUND_COLOR;
diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx
index 20eabaf41..06a7e9278 100644
--- a/src/Fl_Menu.cxx
+++ b/src/Fl_Menu.cxx
@@ -1,7 +1,7 @@
//
// Menu code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -496,6 +496,7 @@ void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) {
int sz = (hh-7)&-2;
int y1 = yy+(hh-sz)/2;
int x1 = xx+ww-sz-3;
+ // FIXME_ARROW: use fl_draw_arrow()
fl_polygon(x1+2, y1, x1+2, y1+sz, x1+sz/2+2, y1+sz/2);
} else if (m->shortcut_) {
Fl_Font f = m->labelsize_ || m->labelfont_ ? (Fl_Font)m->labelfont_ :
diff --git a/src/Fl_Menu_Button.cxx b/src/Fl_Menu_Button.cxx
index 5b69ea703..dadbaf55c 100644
--- a/src/Fl_Menu_Button.cxx
+++ b/src/Fl_Menu_Button.cxx
@@ -1,7 +1,7 @@
//
// Menu button widget for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2019 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -31,6 +31,7 @@ void Fl_Menu_Button::draw() {
draw_label(x()+Fl::box_dx(box()), y(), X-x()+2, h());
if (Fl::focus() == this) draw_focus();
// ** if (box() == FL_FLAT_BOX) return; // for XForms compatibility
+ // FIXME_ARROW: use fl_draw_arrow()
fl_color(active_r() ? FL_DARK3 : fl_inactive(FL_DARK3));
fl_line(X+H/2, Y+H, X, Y, X+H, Y);
fl_color(active_r() ? FL_LIGHT3 : fl_inactive(FL_LIGHT3));
diff --git a/src/Fl_Scrollbar.cxx b/src/Fl_Scrollbar.cxx
index 64071dbe2..d8d42ce80 100644
--- a/src/Fl_Scrollbar.cxx
+++ b/src/Fl_Scrollbar.cxx
@@ -1,7 +1,7 @@
//
// Scroll bar widget for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2015 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -196,61 +196,56 @@ int Fl_Scrollbar::handle(int event) {
}
void Fl_Scrollbar::draw() {
- if (damage()&FL_DAMAGE_ALL) draw_box();
- int X = x()+Fl::box_dx(box());
- int Y = y()+Fl::box_dy(box());
- int W = w()-Fl::box_dw(box());
- int H = h()-Fl::box_dh(box());
+ if (damage() & FL_DAMAGE_ALL) draw_box();
+ int X = x() + Fl::box_dx(box());
+ int Y = y() + Fl::box_dy(box());
+ int W = w() - Fl::box_dw(box());
+ int H = h() - Fl::box_dh(box());
+ Fl_Rect ab; // arrow box
+
+ int inset = 3;
+ if (W < 8 || H < 8)
+ inset = 2;
+
if (horizontal()) {
- if (W < 3*H) {Fl_Slider::draw(X,Y,W,H); return;}
- Fl_Slider::draw(X+H,Y,W-2*H,H);
+ if (W < 3*H) {
+ Fl_Slider::draw(X, Y, W, H);
+ return;
+ }
+ Fl_Slider::draw(X+H, Y, W-2*H, H);
if (damage()&FL_DAMAGE_ALL) {
draw_box((pushed_==1) ? fl_down(slider()) : slider(),
X, Y, H, H, selection_color());
draw_box((pushed_==2) ? fl_down(slider()) : slider(),
X+W-H, Y, H, H, selection_color());
- if (active_r())
- fl_color(labelcolor());
- else
- fl_color(fl_inactive(labelcolor()));
- int w1 = (H-4)/3; if (w1 < 1) w1 = 1;
- int x1 = X+(H-w1-1)/2;
- int yy1 = Y+(H-2*w1-1)/2;
- if (Fl::is_scheme("gtk+")) {
- fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1-1, yy1+w1, x1+w1, yy1);
- x1 += (W-H);
- fl_polygon(x1, yy1, x1+1, yy1+w1, x1, yy1+2*w1, x1+w1, yy1+w1);
- } else {
- fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1);
- x1 += (W-H);
- fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1);
- }
+
+ Fl_Color arrowcolor = active_r() ? labelcolor() : fl_inactive(labelcolor());
+ ab = Fl_Rect(X, Y, H, H);
+ ab.inset(inset);
+ fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_LEFT, arrowcolor); // left arrow
+ ab = Fl_Rect(X+W-H, Y, H, H);
+ ab.inset(inset);
+ fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_RIGHT, arrowcolor); // right arrow
}
} else { // vertical
- if (H < 3*W) {Fl_Slider::draw(X,Y,W,H); return;}
- Fl_Slider::draw(X,Y+W,W,H-2*W);
- if (damage()&FL_DAMAGE_ALL) {
+ if (H < 3*W) {
+ Fl_Slider::draw(X, Y, W, H);
+ return;
+ }
+ Fl_Slider::draw(X, Y+W, W, H-2*W);
+ if (damage() & FL_DAMAGE_ALL) {
draw_box((pushed_==1) ? fl_down(slider()) : slider(),
X, Y, W, W, selection_color());
draw_box((pushed_==2) ? fl_down(slider()) : slider(),
X, Y+H-W, W, W, selection_color());
- if (active_r())
- fl_color(labelcolor());
- else
- fl_color(fl_inactive(labelcolor()));
- int w1 = (W-4)/3; if (w1 < 1) w1 = 1;
- int x1 = X+(W-2*w1-1)/2;
- int yy1 = Y+(W-w1-1)/2;
- if (Fl::is_scheme("gtk+")) {
- fl_polygon(x1, yy1+w1, x1+w1, yy1+w1-1, x1+2*w1, yy1+w1, x1+w1, yy1);
- yy1 += H-W;
- fl_polygon(x1, yy1, x1+w1, yy1+1, x1+w1, yy1+w1);
- fl_polygon(x1+w1, yy1+1, x1+2*w1, yy1, x1+w1, yy1+w1);
- } else {
- fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1);
- yy1 += H-W;
- fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1);
- }
+
+ Fl_Color arrowcolor = active_r() ? labelcolor() : fl_inactive(labelcolor());
+ ab = Fl_Rect(X, Y, W, W);
+ ab.inset(inset);
+ fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_UP, arrowcolor); // up arrow
+ ab = Fl_Rect(X, Y+H-W, W, W);
+ ab.inset(inset);
+ fl_draw_arrow(ab, FL_ARROW_SINGLE, FL_ORIENT_DOWN, arrowcolor); // down arrow
}
}
}
diff --git a/src/Fl_Spinner.cxx b/src/Fl_Spinner.cxx
index 51657d87b..a298d189e 100644
--- a/src/Fl_Spinner.cxx
+++ b/src/Fl_Spinner.cxx
@@ -1,7 +1,7 @@
//
// Spinner widget for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2017 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <FL/Fl_Spinner.H>
+#include <FL/Fl_Rect.H>
+#include <FL/fl_draw.H>
/*
This widget is a combination of the input widget and repeat buttons.
@@ -91,9 +93,6 @@ void Fl_Spinner::update() {
input_.value(s);
}
-#define FL_UP_ARROW_TX "@-42<"
-#define FL_DOWN_ARROW_TX "@-42>"
-
/**
Creates a new Fl_Spinner widget using the given position, size,
and label string.
@@ -104,9 +103,8 @@ void Fl_Spinner::update() {
Fl_Spinner::Fl_Spinner(int X, int Y, int W, int H, const char *L)
: Fl_Group(X, Y, W, H, L),
input_(X, Y, W - H / 2 - 2, H),
- up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2, FL_UP_ARROW_TX),
- down_button_(X + W - H / 2 - 2, Y + H - H / 2,
- H / 2 + 2, H / 2, FL_DOWN_ARROW_TX)
+ up_button_(X + W - H / 2 - 2, Y, H / 2 + 2, H / 2),
+ down_button_(X + W - H / 2 - 2, Y + H - H / 2, H / 2 + 2, H / 2)
{
end();
@@ -129,6 +127,26 @@ Fl_Spinner::Fl_Spinner(int X, int Y, int W, int H, const char *L)
down_button_.callback((Fl_Callback *)sb_cb, this);
}
+void Fl_Spinner::draw() {
+
+ // draw the box and the input widget
+
+ draw_box();
+ ((Fl_Widget&)input_).draw();
+
+ // draw the buttons and the up and down arrows as their "labels"
+
+ ((Fl_Widget&)up_button_).draw();
+ Fl_Rect up(up_button_);
+ up.inset(up_button_.box());
+ fl_draw_arrow(up, FL_ARROW_SINGLE, FL_ORIENT_UP, labelcolor());
+
+ ((Fl_Widget&)down_button_).draw();
+ Fl_Rect down(down_button_);
+ down.inset(down_button_.box());
+ fl_draw_arrow(down, FL_ARROW_SINGLE, FL_ORIENT_DOWN, labelcolor());
+}
+
int Fl_Spinner::handle(int event) {
switch (event) {
diff --git a/src/Makefile b/src/Makefile
index 0964f7b00..388f69b23 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -139,6 +139,7 @@ CPPFILES = \
fl_curve.cxx \
fl_diamond_box.cxx \
fl_draw.cxx \
+ fl_draw_arrow.cxx \
fl_draw_pixmap.cxx \
fl_encoding_latin1.cxx \
fl_encoding_mac_roman.cxx \
diff --git a/src/fl_boxtype.cxx b/src/fl_boxtype.cxx
index ae60727f1..920205b07 100644
--- a/src/fl_boxtype.cxx
+++ b/src/fl_boxtype.cxx
@@ -1,7 +1,7 @@
//
// Box drawing code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -415,7 +415,7 @@ Fl_Box_Draw_F *Fl::get_boxtype(Fl_Boxtype t) {
}
/** Sets the function to call to draw a specific boxtype. */
void Fl::set_boxtype(Fl_Boxtype t, Fl_Box_Draw_F* f,
- uchar a, uchar b, uchar c, uchar d) {
+ uchar a, uchar b, uchar c, uchar d) {
fl_box_table[t].f = f;
fl_box_table[t].set = 1;
fl_box_table[t].dx = a;
diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx
index 2f91243a2..468d03251 100644
--- a/src/fl_draw.cxx
+++ b/src/fl_draw.cxx
@@ -1,7 +1,7 @@
//
// Label drawing code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2020 by Bill Spitzak and others.
+// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -249,8 +249,9 @@ void fl_draw(
if (str) {
int desc = fl_descent();
for (p=str; ; ypos += height) {
- if (lines>1) e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen,
- width, align&FL_ALIGN_WRAP, draw_symbols);
+ if (lines>1)
+ e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen,
+ width, align&FL_ALIGN_WRAP, draw_symbols);
else e = "";
if (width > symoffset) symoffset = (int)(width + 0.5);
diff --git a/src/fl_draw_arrow.cxx b/src/fl_draw_arrow.cxx
new file mode 100644
index 000000000..2aef43889
--- /dev/null
+++ b/src/fl_draw_arrow.cxx
@@ -0,0 +1,256 @@
+//
+// Arrow drawing code for the Fast Light Tool Kit (FLTK).
+//
+// Copyright 1998-2022 by Bill Spitzak and others.
+//
+// This library is free software. Distribution and use rights are outlined in
+// the file "COPYING" which should have been included with this file. If this
+// file is missing or damaged, see the license at:
+//
+// https://www.fltk.org/COPYING.php
+//
+// Please see the following page on how to report bugs and issues:
+//
+// https://www.fltk.org/bugs.php
+//
+
+// These functions implement drawing of all "arrow like" GUI elements in scrollbars,
+// choice widgets, menus, etc.
+
+// Implementation of fl_draw_arrow(...) dependent on the active FLTK Scheme.
+
+#include <FL/Fl.H>
+#include <FL/fl_draw.H>
+#include <FL/fl_utf8.h>
+
+#ifndef DEBUG_ARROW
+#define DEBUG_ARROW (0) // 0 = off, 1 = green background, 2 = red frame, 3 = both
+#endif
+
+void debug_arrow(Fl_Rect r) {
+
+#if (DEBUG_ARROW & 1)
+ fl_color(fl_lighter(FL_GREEN));
+ fl_rectf(r);
+#endif
+
+#if (DEBUG_ARROW & 2)
+ fl_color(FL_RED);
+ fl_line_style(FL_SOLID, 1); // work around X11 bug with default line width 0
+ fl_rect(r);
+ fl_line_style(FL_SOLID, 0); // reset line style
+#endif
+
+} // debug_arrow
+
+// Calculate the applicable arrow size.
+// Imagine an arrow pointing to the right side:
+// - the calculated size s is the width of the arrow,
+// - the height of the arrow is 2 * s.
+// The calculation takes into account that we need one pixel padding at
+// all sides and that the available space doesn't need to be a square,
+// i.e. it's possible that r.w() != r.h().
+
+static int arrow_size(Fl_Rect r, Fl_Orientation o, int num = 1) {
+
+ int s, d1, d2;
+
+ switch(o) {
+ case FL_ORIENT_LEFT:
+ case FL_ORIENT_RIGHT:
+ d1 = (r.w() - 2) / num;
+ d2 = (r.h() - 2) / 2;
+ break;
+ default: // up or down arrow
+ d1 = (r.h() - 2) / num;
+ d2 = (r.w() - 2) / 2;
+ break;
+ }
+ s = d1 < d2 ? d1 : d2;
+ if (s < 2) s = 2;
+ else if (s > 6) s = 6;
+ return s;
+}
+
+// Draw a "Single Arrow" in an arbitrary direction (0°, 90°, 180°, 270°).
+// This is the basic arrow drawing function for all "standard" widgets.
+// It is used in Fl_Scrollbars and similar and in all combinations, for
+// instance when "Double Arrows" or other combinations are needed.
+
+static int fl_draw_arrow_single(Fl_Rect r, Fl_Orientation o, Fl_Color col, int d = -1) {
+
+ int x1, y1;
+
+ x1 = r.x();
+ y1 = r.y();
+ if (d < 0)
+ d = arrow_size(r, o);
+
+ fl_color(col);
+
+ switch(o) {
+
+ case FL_ORIENT_LEFT:
+ x1 += (r.w()-d)/2 - 1;
+ y1 += r.h()/2;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1, x1+d, y1-d, x1+d-1, y1, x1+d, y1+d);
+ else
+ fl_polygon(x1, y1, x1+d, y1-d, x1+d, y1+d);
+ return 1;
+
+ case FL_ORIENT_RIGHT:
+ x1 += (r.w()-d)/2;
+ y1 += r.h()/2;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1-d, x1+1, y1, x1, y1+d, x1+d, y1);
+ else
+ fl_polygon(x1, y1-d, x1, y1+d, x1+d, y1);
+ return 1;
+
+ case FL_ORIENT_UP:
+ x1 += r.w()/2;
+ y1 += (r.h()-d)/2 - 1;
+ if (Fl::is_scheme("gtk+"))
+ fl_polygon(x1, y1, x1+d, y1+d, x1, y1+d-1, x1-d, y1+d);
+ else
+ fl_polygon(x1, y1, x1+d, y1+d, x1-d, y1+d);
+ return 1;
+
+ case FL_ORIENT_DOWN:
+ x1 += r.w()/2-d;
+ y1 += (r.h()-d)/2;
+ if (Fl::is_scheme("gtk+")) {
+ fl_polygon(x1, y1, x1+d, y1+1, x1+d, y1+d);
+ fl_polygon(x1+d, y1+1, x1+2*d, y1, x1+d, y1+d);
+ } else {
+ fl_polygon(x1, y1, x1+d, y1+d, x1+2*d, y1);
+ }
+ return 1;
+
+ default: // orientation not handled: return error
+ return 0;
+ }
+ return 0;
+} // fl_draw_arrow_single()
+
+
+// Draw a "Double Arrow" in an arbitrary direction (0°, 90°, 180°, 270°).
+// This is the basic arrow drawing function for all "standard" widgets.
+// It is used in Fl_Scrollbars and similar and in all combinations, for
+// instance when "Double Arrows" or other combinations are needed.
+
+static int fl_draw_arrow_double(Fl_Rect r, Fl_Orientation o, Fl_Color col) {
+
+ int d = arrow_size(r, o, 2);
+ int x1 = r.x();
+ int y1 = r.y();
+ int da = (d+1)/2;
+
+ switch(o) {
+
+ case FL_ORIENT_LEFT:
+ case FL_ORIENT_RIGHT:
+ r.x(x1 - da);
+ fl_draw_arrow_single(r, o, col, d);
+ r.x(x1 + da);
+ return fl_draw_arrow_single(r, o, col, d);
+
+ case FL_ORIENT_UP:
+ case FL_ORIENT_DOWN:
+ r.y(y1 - da);
+ fl_draw_arrow_single(r, o, col, d);
+ r.y(y1 + da);
+ return fl_draw_arrow_single(r, o, col, d);
+
+ default: // orientation not handled: return error
+ return 0;
+ }
+ return 0;
+} // fl_draw_arrow_double()
+
+
+// Draw a "Choice Arrow". The direction and type is determined by the scheme.
+
+static int fl_draw_arrow_choice(Fl_Rect r, Fl_Color col) {
+
+ int w1 = (r.w() - 4) / 3; if (w1 < 1) w1 = 1;
+ int x1 = r.x() + (r.w() - 2 * w1 - 1) / 2;
+ int y1 = r.y() + (r.h() - w1 - 1) / 2;
+
+ if (Fl::is_scheme("gtk+") ||
+ Fl::is_scheme("gleam")) {
+ // Show smaller up/down arrows ...
+ int x1 = r.x() + (r.w() - 6)/2;
+ int y1 = r.y() + r.h() / 2;
+ fl_color(col);
+ fl_polygon(x1, y1 - 2, x1 + 3, y1 - 5, x1 + 6, y1 - 2);
+ fl_polygon(x1, y1 + 2, x1 + 3, y1 + 5, x1 + 6, y1 + 2);
+ return 1;
+ }
+ else if (Fl::is_scheme("plastic")) {
+ // Show larger up/down arrows...
+ fl_color(col);
+ fl_polygon(x1, y1 + 3, x1 + w1, y1 + w1 + 3, x1 + 2 * w1, y1 + 3);
+ fl_polygon(x1, y1 + 1, x1 + w1, y1 - w1 + 1, x1 + 2 * w1, y1 + 1);
+ return 1;
+ }
+ else { // none, default // single down arrow
+ return fl_draw_arrow_single(r, FL_ORIENT_DOWN, col);
+ }
+ return 0;
+} // fl_draw_arrow_double()
+
+
+/**
+ Draw an "arrow like" GUI element for the selected scheme.
+
+ In the future this function should be integrated in Fl_Scheme
+ as a virtual method, i.e. it would call a method like ...
+ \code
+ Fl_Scheme::current()->draw_arrow(r, t, o, col);
+ \endcode
+
+ \param[in] r bounding box
+ \param[in] t arrow type
+ \param[in] o orientation
+ \param[in] col arrow color
+*/
+
+void fl_draw_arrow(Fl_Rect r, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) {
+
+ int ret = 0;
+ debug_arrow(r);
+
+ // implementation of all arrow types
+
+ switch(t) {
+ case FL_ARROW_SINGLE:
+ ret = fl_draw_arrow_single(r, o, col);
+ break;
+
+ case FL_ARROW_DOUBLE:
+ ret = fl_draw_arrow_double(r, o, col);
+ break;
+
+ case FL_ARROW_CHOICE:
+ ret = fl_draw_arrow_choice(r, col);
+ break;
+
+ default: // unknown arrow type
+ ret = 0;
+ break;
+ }
+
+ // draw an error flag (red rectangle with cross) if not successful
+
+ if (!ret) {
+ fl_color(FL_RED);
+ fl_rectf(r);
+ fl_color(FL_BLACK);
+ fl_rect(r);
+ fl_line(r.x(), r.y(), r.r(), r.b());
+ fl_line(r.x(), r.b(), r.r(), r.y());
+ }
+
+} // fl_draw_arrow()