diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/Fl_Choice.cxx | 93 | ||||
| -rw-r--r-- | src/Fl_Counter.cxx | 155 | ||||
| -rw-r--r-- | src/Fl_Menu.cxx | 3 | ||||
| -rw-r--r-- | src/Fl_Menu_Button.cxx | 3 | ||||
| -rw-r--r-- | src/Fl_Scrollbar.cxx | 83 | ||||
| -rw-r--r-- | src/Fl_Spinner.cxx | 32 | ||||
| -rw-r--r-- | src/Makefile | 1 | ||||
| -rw-r--r-- | src/fl_boxtype.cxx | 4 | ||||
| -rw-r--r-- | src/fl_draw.cxx | 7 | ||||
| -rw-r--r-- | src/fl_draw_arrow.cxx | 256 |
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() |
