Improve focus box drawing and documentation

Add new method
  Fl_Widget::draw_focus(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color bg)

  ... with background color for correct contrast testing (in Fl_Tabs)

Draw the focus box of the "tabs" of Fl_Tabs widgets with the correct
  boxtype and background color.

Make 'unsigned int visible_focus()' const so it can be used in 'const'
  methods.

Do not draw the focus box if the per-widget focus box option is off.
This commit is contained in:
Albrecht Schlosser
2022-01-14 17:17:09 +01:00
parent c45bf57c8f
commit ab58971bcf
4 changed files with 68 additions and 16 deletions
+23 -4
View File
@@ -169,9 +169,28 @@ protected:
void draw_box(Fl_Boxtype t, Fl_Color c) const; void draw_box(Fl_Boxtype t, Fl_Color c) const;
void draw_box(Fl_Boxtype t, int x,int y,int w,int h, Fl_Color c) const; void draw_box(Fl_Boxtype t, int x,int y,int w,int h, Fl_Color c) const;
void draw_backdrop() const; void draw_backdrop() const;
/** draws a focus rectangle around the widget */
void draw_focus() {draw_focus(box(),x(),y(),w(),h());} /** Draws a focus rectangle around the widget.
void draw_focus(Fl_Boxtype t, int x,int y,int w,int h) const; This method uses the widget's boxtype and coordinates and its
background color color().
\see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int, Fl_Color) const
*/
void draw_focus() const {
draw_focus(box(), x(), y(), w(), h(), color());
}
/** Draws a focus rectangle around the widget.
This method uses the given boxtype and coordinates and the widget's
background color color().
\see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int, Fl_Color) const
*/
void draw_focus(Fl_Boxtype t, int X, int Y, int W, int H) const {
draw_focus(t, X, Y, W, H, color());
}
// See documentation in Fl_Widget.cxx
void draw_focus(Fl_Boxtype t, int x, int y, int w, int h, Fl_Color bg) const;
void draw_label() const; void draw_label() const;
void draw_label(int, int, int, int) const; void draw_label(int, int, int, int) const;
@@ -845,7 +864,7 @@ public:
\retval 0 if this widget has no visible focus. \retval 0 if this widget has no visible focus.
\see visible_focus(int), set_visible_focus(), clear_visible_focus() \see visible_focus(int), set_visible_focus(), clear_visible_focus()
*/ */
unsigned int visible_focus() { return flags_ & VISIBLE_FOCUS; } unsigned int visible_focus() const { return flags_ & VISIBLE_FOCUS; }
/** The default callback for all widgets that don't set a callback. /** The default callback for all widgets that don't set a callback.
+6 -1
View File
@@ -299,7 +299,12 @@ inline void fl_rect(Fl_Rect r) {
fl_rect(r.x(), r.y(), r.w(), r.h()); fl_rect(r.x(), r.y(), r.w(), r.h());
} }
/** Draw a dotted rectangle, used to indicate keyboard focus on a widget. */ /** Draw a dotted rectangle, used to indicate keyboard focus on a widget.
This method draws the rectangle in the current color and independent of
the Fl::visible_focus() option. You may need to set the current color
with fl_color() before you call this.
*/
inline void fl_focus_rect(int x, int y, int w, int h) { inline void fl_focus_rect(int x, int y, int w, int h) {
fl_graphics_driver->focus_rect(x, y, w, h); fl_graphics_driver->focus_rect(x, y, w, h);
} }
+2 -2
View File
@@ -417,7 +417,7 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
o->draw_label(x1, y() + yofs, W, H - yofs, tab_align()); o->draw_label(x1, y() + yofs, W, H - yofs, tab_align());
if (Fl::focus() == this && o->visible()) if (Fl::focus() == this && o->visible())
draw_focus(box(), x1, y(), W, H); draw_focus(bt, x1, y(), W, H, bc);
fl_pop_clip(); fl_pop_clip();
} else { } else {
@@ -435,7 +435,7 @@ void Fl_Tabs::draw_tab(int x1, int x2, int W, int H, Fl_Widget* o, int what) {
o->draw_label(x1, y() + h() - H, W, H - yofs, tab_align()); o->draw_label(x1, y() + h() - H, W, H - yofs, tab_align());
if (Fl::focus() == this && o->visible()) if (Fl::focus() == this && o->visible())
draw_focus(box(), x1, y() + h() - H, W, H); draw_focus(bt, x1, y() + h() - H, W, H, bc);
fl_pop_clip(); fl_pop_clip();
} }
+37 -9
View File
@@ -182,11 +182,38 @@ Fl_Widget::~Fl_Widget() {
if (callback_ == default_callback) cleanup_readqueue(this); if (callback_ == default_callback) cleanup_readqueue(this);
} }
/** Draws a focus box for the widget at the given position and size. */ /**
Draws a focus box for the widget at the given position and size.
void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const { This method does nothing if
- the global option Fl::visible_focus() or
- the per-widget option visible_focus()
is false (off).
This means that Fl_Widget::draw_focus() or one of the more specialized
methods can be called without checking these visible focus options.
\note This method must only be called if the widget has the focus.
This is not tested internally.
The boxtype \p bt is used to calculate the inset so the focus box is drawn
inside the box borders.
The default focus box drawing color is black. The background color \p bg
is used to determine a better visible color if necessary by using
fl_contrast() with the given background color.
\param[in] bt Boxtype that needs to be considered (frame width)
\param[in] X,Y,W,H Bounding box
\param[in] bg Background color
\see Fl_Widget::draw_focus()
\see Fl_Widget::draw_focus(Fl_Boxtype, int, int, int, int) const
*/
void Fl_Widget::draw_focus(Fl_Boxtype bt, int X, int Y, int W, int H, Fl_Color bg) const {
if (!Fl::visible_focus()) return; if (!Fl::visible_focus()) return;
switch (B) { if (!visible_focus()) return;
switch (bt) {
case FL_DOWN_BOX: case FL_DOWN_BOX:
case FL_DOWN_FRAME: case FL_DOWN_FRAME:
case FL_THIN_DOWN_BOX: case FL_THIN_DOWN_BOX:
@@ -196,16 +223,17 @@ void Fl_Widget::draw_focus(Fl_Boxtype B, int X, int Y, int W, int H) const {
default: default:
break; break;
} }
X += Fl::box_dx(B); X += Fl::box_dx(bt);
Y += Fl::box_dy(B); Y += Fl::box_dy(bt);
W -= Fl::box_dw(B)+1; W -= Fl::box_dw(bt)+1;
H -= Fl::box_dh(B)+1; H -= Fl::box_dh(bt)+1;
fl_color(fl_contrast(FL_BLACK, color())); Fl_Color savecolor = fl_color();
fl_color(fl_contrast(FL_BLACK, bg));
fl_focus_rect(X, Y, W, H); fl_focus_rect(X, Y, W, H);
fl_color(savecolor);
} }
void Fl_Widget::activate() { void Fl_Widget::activate() {
if (!active()) { if (!active()) {
clear_flag(INACTIVE); clear_flag(INACTIVE);