diff --git a/FL/fl_draw.H b/FL/fl_draw.H index 4095aab34..2ad8d81af 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -982,6 +982,10 @@ FL_EXPORT void fl_draw_arrow(Fl_Rect bb, Fl_Arrow_Type t, Fl_Orientation o, Fl_C // Draw a potentially small, filled circle FL_EXPORT void fl_draw_circle(int x, int y, int d, Fl_Color color); +// Draw the full "radio button" of a radio menu entry or radio button +// This requires scheme specific handling (particularly gtk+ scheme) +FL_EXPORT void fl_draw_radio(int x, int y, int d, Fl_Color color); + // images: /** diff --git a/src/Fl_Light_Button.cxx b/src/Fl_Light_Button.cxx index 9658be15a..98ef910e6 100644 --- a/src/Fl_Light_Button.cxx +++ b/src/Fl_Light_Button.cxx @@ -32,6 +32,16 @@ void Fl_Light_Button::draw() { Fl_Color col = value() ? (active_r() ? selection_color() : fl_inactive(selection_color())) : color(); + // determine the color of the check mark or radio button (circle) + + Fl_Color check_color = selection_color(); // default = selection color + if (Fl::is_scheme("gtk+")) + check_color = FL_SELECTION_COLOR; // exception for gtk+ + if (!active_r()) + check_color = fl_inactive(check_color); + // select a color with enough contrast + check_color = fl_contrast(check_color, FL_BACKGROUND2_COLOR); + int W = labelsize(); // check mark box size if (W > 25) W = 25; // limit box size int bx = Fl::box_dx(box()); // box frame width @@ -42,8 +52,11 @@ void Fl_Light_Button::draw() { int cy = y() + dy; // check mark box y-position int cw = 0; // check mark box width and height - if (down_box()) { - // draw other down_box() styles: + // FIXME: the *box type* of the widget determines the drawing style: + // (a) down_box() == 0: Fl_Light_Button style + // (b) down_box() != 0: other button styles + + if (down_box()) { // draw "other" button styles (b): switch (down_box()) { case FL_DOWN_BOX : case FL_UP_BOX : @@ -53,14 +66,11 @@ void Fl_Light_Button::draw() { draw_box(down_box(), cx, cy, W, W, FL_BACKGROUND2_COLOR); if (value()) { // Check mark... - if (Fl::is_scheme("gtk+")) { - col = FL_SELECTION_COLOR; - } // Calculate box position and size cx += Fl::box_dx(down_box()); cy += Fl::box_dy(down_box()); cw = W - Fl::box_dw(down_box()); - fl_draw_check(Fl_Rect(cx, cy, cw, cw), col); + fl_draw_check(Fl_Rect(cx, cy, cw, cw), check_color); } break; case _FL_ROUND_DOWN_BOX : @@ -68,27 +78,16 @@ void Fl_Light_Button::draw() { // Radio button... draw_box(down_box(), x()+dx, y()+dy, W, W, FL_BACKGROUND2_COLOR); if (value()) { + + // Draw round check mark of radio button + int tW = (W - Fl::box_dw(down_box())) / 2 + 1; if ((W - tW) & 1) tW++; // Make sure difference is even to center int tdx = dx + (W - tW) / 2; int tdy = dy + (W - tW) / 2; + fl_draw_radio(x() + tdx - 1, y() + tdy - 1, tW + 2, check_color); - if (Fl::is_scheme("gtk+")) { - fl_color(FL_SELECTION_COLOR); - tW --; - fl_pie(x() + tdx - 1, y() + tdy - 1, tW + 3, tW + 3, 0.0, 360.0); - fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.2f)); - } else { - fl_color(col); - } - - fl_draw_circle(x() + tdx, y() + tdy, tW, fl_color()); - - if (Fl::is_scheme("gtk+")) { - fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.5)); - fl_arc(x() + tdx, y() + tdy, tW + 1, tW + 1, 60.0, 180.0); - } - } + } // Radio button: if (value()) break; default : draw_box(down_box(), x()+dx, y()+dy, W, W, col); @@ -96,7 +95,7 @@ void Fl_Light_Button::draw() { } lx = dx + W + 2; } else { - // if down_box() is zero, draw light button style: + // if down_box() is zero, draw light button style (a): int hh = h()-2*dy - 2; int ww = W/2+1; int xx = dx; diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index 271bcd50b..3a3e70708 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -290,7 +290,7 @@ void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m, if (selected) { Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR; Fl_Boxtype b = m && m->down_box() ? m->down_box() : FL_FLAT_BOX; - if (fl_contrast(r,color)!=r) { // back compatibility boxtypes + if (fl_contrast(r, color) != r) { // back compatibility boxtypes if (selected == 2) { // menu title r = color; b = m ? m->box() : FL_UP_BOX; @@ -314,45 +314,26 @@ void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m, int d = (h - FL_NORMAL_SIZE + 1) / 2; int W = h - 2 * d; + Fl_Color check_color = labelcolor_; + if (Fl::is_scheme("gtk+")) + check_color = FL_SELECTION_COLOR; + check_color = fl_contrast(check_color, FL_BACKGROUND2_COLOR); + if (flags & FL_MENU_RADIO) { + fl_draw_box(FL_ROUND_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); if (value()) { int tW = (W - Fl::box_dw(FL_ROUND_DOWN_BOX)) / 2 + 1; if ((W - tW) & 1) tW++; // Make sure difference is even to center int td = (W - tW) / 2; - if (Fl::is_scheme("gtk+")) { - fl_color(FL_SELECTION_COLOR); - tW --; - fl_pie(x + td + 1, y + d + td - 1, tW + 3, tW + 3, 0.0, 360.0); - fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.2f)); - } else { - fl_color(labelcolor_); - } + fl_draw_radio(x + td + 1, y + d + td - 1, tW + 2, check_color); + } // FL_MENU_RADIO && value() - fl_draw_circle(x + td + 2, y + d + td, tW, fl_color()); + } else { // FL_MENU_TOGGLE && ! FL_MENU_RADIO - if (Fl::is_scheme("gtk+")) { - fl_color(fl_color_average(FL_WHITE, FL_SELECTION_COLOR, 0.5)); - fl_arc(x + td + 2, y + d + td, tW + 1, tW + 1, 60.0, 180.0); - } - } - } else { fl_draw_box(FL_DOWN_BOX, x+2, y+d, W, W, FL_BACKGROUND2_COLOR); if (value()) { - if (Fl::is_scheme("gtk+")) { - fl_color(FL_SELECTION_COLOR); - } else { - fl_color(labelcolor_); - } - int tx = x + 5; - int tw = W - 6; - int d1 = tw/3; - int d2 = tw-d1; - int ty = y + d + (W+d2)/2-d1-2; - for (int n = 0; n < 3; n++, ty++) { - fl_line(tx, ty, tx+d1, ty+d1); - fl_line(tx+d1, ty+d1, tx+tw-1, ty+d1-d2+1); - } + fl_draw_check(Fl_Rect(x+3, y+d+1, W-2, W-2), check_color); } } x += W + 3; diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index bfd1c67fd..b0598245f 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -594,25 +594,76 @@ void fl_draw_check(Fl_Rect bb, Fl_Color col) { /** Draw a potentially small, filled circle using a given color. - This function draws using \p color a filled circle bounded by rectangle (x, y, d, d). + This function draws a filled circle bounded by rectangle + (x, y, d, d) using color \p color - This function is the same as fl_pie(x, y, d, d, 0, 360) except with some systems - that don't draw small circles well. In that situation, the circle diameter \p d is converted - from FLTK units to pixels and this function approximates a filled circle by drawing several - filled rectangles if the converted diameter is ≤ 6 pixels. + This function is the same as fl_pie(x, y, d, d, 0, 360) except + with some systems that don't draw small circles well. In that situation, + the circle diameter \p d is converted from FLTK units to pixels and this + function approximates a filled circle by drawing several filled + rectangles if the converted diameter is ≤ 6 pixels. - \param[in] x,y coordinates of top left of the bounding box - \param[in] d diameter == width and height of the bounding box in FLTK units - \param[in] color drawing color + The current drawing color fl_color() is preserved across the call. + + \param[in] x,y coordinates of top left of the bounding box + \param[in] d diameter == width and height of the bounding box in FLTK units + \param[in] color the color used to draw the circle \since 1.4.0 */ void fl_draw_circle(int x, int y, int d, Fl_Color color) { #define DEBUG_DRAW_CIRCLE (0) // bit 1 = draw bounding box (green) -#if (DEBUG_DRAW_CIRCLE & 1) +#if (DEBUG_DRAW_CIRCLE & 0) Fl_Color current = fl_color(); - fl_rectf(x0, y0, d, d, FL_GREEN); + fl_rectf(x, y, d, d, FL_GREEN); fl_color(current); #endif fl_graphics_driver->draw_circle(x, y, d, color); } + +/** + Draw a round check mark (circle) of a radio button. + + This draws only the round "radio button mark", it does not draw the + (also typically round) box of the radio button. + + Call this only if the radio button is \c ON. + + This method draws a scheme specific "circle" with a particular light effect + if the scheme is gtk+. For all other schemes this function draws a simple, + small circle. + + The \c color must be chosen by the caller so it has enough contrast with + the background. + + The bounding box of the circle is the rectangle (x, y, d, d). + + The current drawing color fl_color() is preserved across the call. + + \param[in] x,y coordinates of top left of the bounding box + \param[in] d diameter == width and height of the bounding box in FLTK units + \param[in] color the base color used to draw the circle + + \since 1.4.0 +*/ +void fl_draw_radio(int x, int y, int d, Fl_Color color) { + + Fl_Color current = fl_color(); + +#if (0) // DEBUG: draw bounding box + fl_color(fl_lighter(FL_RED)); + fl_rectf(x, y, d, d); +#endif + + if (Fl::is_scheme("gtk+")) { + fl_color(color); + fl_pie(x, y, d, d, 0.0, 360.0); + Fl_Color icol = fl_color_average(FL_WHITE, color, 0.2f); + fl_draw_circle(x + 2, y + 2, d - 4, icol); + fl_color(fl_color_average(FL_WHITE, color, 0.5)); + fl_arc(x + 1, y + 1, d - 1, d - 1, 60.0, 180.0); + } else { + fl_draw_circle(x + 1, y + 1, d - 2, color); + } + fl_color(current); +}