Fix Fl_Input_Choice vs Fl_Choice drawing issues (#978)

Differences in size of arrows and overall look varies
with different schemes applied for issue raised by Philip Rose
first on fltk.general:

Subject: Discrepancy between Fl_Choice and Fl_Input_Choice
This commit is contained in:
Greg Ercolano 2024-06-26 15:40:41 -07:00
parent fe4c94b4dc
commit 5c7ba51be3
3 changed files with 87 additions and 14 deletions

View File

@ -72,7 +72,7 @@ protected:
/** See inp_x() for info. */
virtual int inp_y() const { return(y() + Fl::box_dy(box())); }
/** See inp_x() for info. */
virtual int inp_w() const { return(w() - Fl::box_dw(box()) - 20); }
virtual int inp_w() const { return(w() - Fl::box_dw(box()) - menu_w()); }
/** See inp_x() for info. */
virtual int inp_h() const { return(h() - Fl::box_dh(box())); }
@ -81,13 +81,15 @@ protected:
These can be overridden by a subclass to redefine positioning.
See code example in the Description for subclassing details.
*/
virtual int menu_x() const { return(x() + w() - 20 - Fl::box_dx(box())); }
virtual int menu_x() const { return x() + w() - menu_w() - Fl::box_dx(box()); }
/** See menu_x() for info. */
virtual int menu_y() const { return(y() + Fl::box_dy(box())); }
virtual int menu_y() const { return y() + Fl::box_dy(box()); }
/** See menu_x() for info. */
virtual int menu_w() const { return(20); }
virtual int menu_w() const { return 20; }
/** See menu_x() for info. */
virtual int menu_h() const { return(h() - Fl::box_dh(box())); }
virtual int menu_h() const { return h() - Fl::box_dh(box()); }
void draw() FL_OVERRIDE;
public:

View File

@ -125,7 +125,6 @@
*/
/** Constructor for private menu button. */
Fl_Input_Choice::InputMenuButton::InputMenuButton(int x,int y,int w,int h,const char*l)
:Fl_Menu_Button(x,y,w,h,l)
{
@ -133,14 +132,22 @@ Fl_Input_Choice::InputMenuButton::InputMenuButton(int x,int y,int w,int h,const
}
/** Draws the private menu button. */
void Fl_Input_Choice::InputMenuButton::draw() {
draw_box();
Fl_Color arrow_color = parent()->active_r() ? parent()->labelcolor() : fl_inactive(parent()->labelcolor());
Fl_Rect ab(this);
ab.inset(1);
fl_draw_arrow(ab, FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color);
if (Fl::focus() == this) draw_focus();
if (!box()) return;
// Draw box for default scheme only
// For all other schemes, let parent group's box show through
//
if (!Fl::scheme())
draw_box(pressed_menu_button_ == this ? fl_down(box()) : box(), color());
if (Fl::focus() == this) {
int woff = Fl::scheme() ? 2 : 1; // helps center focus box
draw_focus(FL_UP_BOX, x(), y(), w()+woff, h(), color());
}
// draw the arrow (choice button)
Fl_Color arrow_color = active_r() ? labelcolor() : fl_inactive(labelcolor());
fl_draw_arrow(Fl_Rect(x(), y(), w(), h()), FL_ARROW_CHOICE, FL_ORIENT_NONE, arrow_color);
}
// Make pulldown menu appear under entire width of widget
@ -251,7 +258,7 @@ void Fl_Input_Choice::inp_cb(Fl_Widget*, void *data) {
Inherited destructor destroys the widget and any values associated with it.
*/
Fl_Input_Choice::Fl_Input_Choice (int X, int Y, int W, int H, const char *L)
Fl_Input_Choice::Fl_Input_Choice(int X, int Y, int W, int H, const char *L)
: Fl_Group(X,Y,W,H,L) {
Fl_Group::box(FL_DOWN_BOX);
align(FL_ALIGN_LEFT); // default like Fl_Input
@ -337,3 +344,63 @@ int Fl_Input_Choice::update_menubutton() {
}
return 0; // not found
}
void Fl_Input_Choice::draw() {
// This is copied from Fl_Choice::draw() and customized
Fl_Boxtype btype = Fl::scheme() ? FL_UP_BOX // non-default uses up box
: FL_DOWN_BOX; // default scheme uses down box
int dx = Fl::box_dx(btype);
int dy = Fl::box_dy(btype);
// 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)
//
Fl_Color box_color = color();
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());
}
// Draw the widget box
draw_box(btype, box_color);
// Draw menu button
draw_child(*menu_);
// Draw vertical divider lines for: gtk+, gleam, oxy
//
// Scheme: Box or divider line
// ----------------------------------------
// Default (None): Arrow box (FL_UP_BOX)
// gtk+, gleam, oxy: Divider line
// else: Nothing - Fl_Group::box() shows through
//
int woff = 0;
if (Fl::is_scheme("gtk+") ||
Fl::is_scheme("gleam") ||
Fl::is_scheme("oxy")) {
// draw the vertical divider line
int x1 = menu_x() - dx;
int y1 = y() + dy;
int y2 = y() + h() - dy;
fl_color(fl_darker(color()));
fl_yxline(x1+0, y1, y2);
fl_color(fl_lighter(color()));
fl_yxline(x1+1, y1, y2);
woff = 2; // prevent Fl_Input from overdrawing divider
}
// Draw the input field
fl_push_clip(inp_x(), inp_y(), inp_w() - woff, inp_h());
draw_child(*inp_);
fl_pop_clip();
// Widget's label
draw_label();
}

View File

@ -18,6 +18,7 @@
#include <FL/Fl_Button.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Scheme_Choice.H>
#include <FL/Fl_Terminal.H>
#define TERMINAL_HEIGHT 120
@ -53,6 +54,9 @@ int main(int argc, char **argv) {
in.add("three");
in.value(1);
// Interactive control of scheme
Fl_Scheme_Choice sch(100, 120, 140, 25, "Scheme");
Fl_Button onoff(40,150,200,28,"Activate/Deactivate");
onoff.callback(buttcb, (void*)&in);