Adding horiizonatl and vertical label margin

- sizeof(Fl_Widget) not increased
- label positions can be adjusted
- try it out in test/label app
- full support in FLUD
This commit is contained in:
Matthias Melcher 2024-08-27 15:13:32 +02:00
parent 5879e7fae7
commit ec05f78d98
12 changed files with 235 additions and 32 deletions

View File

@ -63,6 +63,10 @@ struct FL_EXPORT Fl_Label {
Fl_Align align_;
/** type of label. \see Fl_Labeltype */
uchar type;
/** Spacing between label and the horizontally aligned side of the widget. */
signed char h_margin_;
/** Spacing between label and the vertically aligned side of the widget. */
signed char v_margin_;
/** Spacing between an image and the label text */
uchar spacing;
@ -698,6 +702,26 @@ public:
*/
int label_image_spacing() { return label_.spacing; }
/** Set the spacing between the label and the horizontal edge of the widget.
\param[in] px gap in pixels
*/
void horizontal_label_margin(int px) { label_.h_margin_ = (signed char)px; }
/** Get the spacing between the label and the horizontal edge of the widget.
\return px gap in pixels
*/
int horizontal_label_margin() { return label_.h_margin_; }
/** Set the spacing between the label and the vertical edge of the widget.
\param[in] px gap in pixels
*/
void vertical_label_margin(int px) { label_.v_margin_ = (signed char)px; }
/** Get the spacing between the label and the vertical edge of the widget.
\return px gap in pixels
*/
int vertical_label_margin() { return label_.v_margin_; }
/** Gets the current tooltip text.
\return a pointer to the tooltip text or NULL
\see tooltip(const char*), copy_tooltip(const char*)

View File

@ -1985,8 +1985,66 @@ void image_spacing_cb(Fl_Value_Input* i, void* v) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
if (q->o->label_image_spacing() != s) {
q->o->label_image_spacing(s);
if (q->o->parent())
q->o->parent()->damage(FL_DAMAGE_EXPOSE); // outside labels
if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window())
q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels
q->o->redraw();
mod = 1;
}
}
}
if (mod) set_modflag(1);
}
}
void h_label_margin_cb(Fl_Value_Input* i, void* v) {
int s;
if (v == LOAD) {
if (!current_widget->is_true_widget()) {
i->deactivate();
i->value(0);
} else {
i->activate();
i->value(((Fl_Widget_Type*)current_widget)->o->horizontal_label_margin());
}
} else {
int mod = 0;
s = int(i->value());
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_true_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
if (q->o->horizontal_label_margin() != s) {
q->o->horizontal_label_margin(s);
if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window())
q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels
q->o->redraw();
mod = 1;
}
}
}
if (mod) set_modflag(1);
}
}
void v_label_margin_cb(Fl_Value_Input* i, void* v) {
int s;
if (v == LOAD) {
if (!current_widget->is_true_widget()) {
i->deactivate();
i->value(0);
} else {
i->activate();
i->value(((Fl_Widget_Type*)current_widget)->o->vertical_label_margin());
}
} else {
int mod = 0;
s = int(i->value());
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_true_widget()) {
Fl_Widget_Type* q = (Fl_Widget_Type*)o;
if (q->o->vertical_label_margin() != s) {
q->o->vertical_label_margin(s);
if (!(q->o->align() & FL_ALIGN_INSIDE) && q->o->window())
q->o->window()->damage(FL_DAMAGE_EXPOSE); // outside labels
q->o->redraw();
mod = 1;
}
@ -3218,6 +3276,12 @@ void Fl_Widget_Type::write_widget_code(Fd_Code_Writer& f) {
f.write_c("%s%s->labelsize(%d);\n", f.indent(), var, o->labelsize());
if (o->labelcolor() != tplate->labelcolor() || subclass())
write_color(f, "labelcolor", o->labelcolor());
if (o->horizontal_label_margin() != tplate->horizontal_label_margin())
f.write_c("%s%s->horizontal_label_margin(%d);\n", f.indent(), var, o->horizontal_label_margin());
if (o->vertical_label_margin() != tplate->vertical_label_margin())
f.write_c("%s%s->vertical_label_margin(%d);\n", f.indent(), var, o->vertical_label_margin());
if (o->label_image_spacing() != tplate->label_image_spacing())
f.write_c("%s%s->label_image_spacing(%d);\n", f.indent(), var, o->label_image_spacing());
if (is_a(ID_Valuator_)) {
Fl_Valuator* v = (Fl_Valuator*)o;
Fl_Valuator* t = (Fl_Valuator*)(tplate);
@ -3397,6 +3461,10 @@ void Fl_Widget_Type::write_properties(Fd_Project_Writer &f) {
f.write_string("labelcolor %d", o->labelcolor());
if (o->align()!=tplate->align())
f.write_string("align %d", o->align());
if (o->horizontal_label_margin()!=tplate->horizontal_label_margin())
f.write_string("h_label_margin %d", o->horizontal_label_margin());
if (o->vertical_label_margin()!=tplate->vertical_label_margin())
f.write_string("v_label_margin %d", o->vertical_label_margin());
if (o->label_image_spacing()!=tplate->label_image_spacing())
f.write_string("image_spacing %d", o->label_image_spacing());
if (o->when() != tplate->when())
@ -3568,6 +3636,10 @@ void Fl_Widget_Type::read_property(Fd_Project_Reader &f, const char *c) {
if (sscanf(f.read_word(),"%d",&x) == 1) o->labelcolor(x);
} else if (!strcmp(c,"align")) {
if (sscanf(f.read_word(),"%d",&x) == 1) o->align(x);
} else if (!strcmp(c,"h_label_margin")) {
if (sscanf(f.read_word(),"%d",&x) == 1) o->horizontal_label_margin(x);
} else if (!strcmp(c,"v_label_margin")) {
if (sscanf(f.read_word(),"%d",&x) == 1) o->vertical_label_margin(x);
} else if (!strcmp(c,"image_spacing")) {
if (sscanf(f.read_word(),"%d",&x) == 1) o->label_image_spacing(x);
} else if (!strcmp(c,"when")) {

View File

@ -468,6 +468,8 @@ Type "Fl_Widget" <word> : C++ variable name
"labelsize" <word> : integer
"labelcolor" <word> : integer, color index
"align" <word> : integer, see Fl_Align
"h_label_margin" <word> : integer, horizontal label margin
"v_label_margin" <word> : integer, vertical label margin
"image_spacing" <word> : integer, see Fl_Widget::label_image_spacing()
"when" <word> : integer, see Fl_When
"minimum" <word> : (is_valuator(), is_spinner()) double

View File

@ -1664,23 +1664,54 @@ Fl_Double_Window* make_widget_panel() {
} // Fl_Menu_Button* o
wp_style_text->end();
} // Fl_Group* wp_style_text
{ Fl_Value_Input* o = new Fl_Value_Input(99, 140, 49, 20, "Image Spacing:");
o->tooltip("Gap between label image and text in pixels");
{ Fl_Group* o = new Fl_Group(99, 150, 242, 20, "Label Margin:");
o->labelfont(1);
o->labelsize(11);
o->maximum(100);
o->step(1);
o->value(14);
o->textsize(11);
o->callback((Fl_Callback*)image_spacing_cb);
} // Fl_Value_Input* o
{ Fl_Light_Button* o = new Fl_Light_Button(99, 165, 90, 20, "Compact");
o->callback((Fl_Callback*)propagate_load);
o->align(Fl_Align(FL_ALIGN_LEFT));
{ Fl_Value_Input* o = new Fl_Value_Input(99, 150, 55, 20, "Horizontal:");
o->tooltip("Spacing between label and the horizontally aligned side of the widget.");
o->labelsize(11);
o->minimum(-127);
o->maximum(128);
o->step(1);
o->textsize(11);
o->callback((Fl_Callback*)h_label_margin_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(159, 150, 55, 20, "Vertical:");
o->tooltip("Spacing between label and the vertically aligned side of the widget.");
o->labelsize(11);
o->minimum(-127);
o->maximum(127);
o->step(1);
o->textsize(11);
o->callback((Fl_Callback*)v_label_margin_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(219, 150, 55, 20, "Text to Image:");
o->tooltip("Gap between label image and text in pixels");
o->labelsize(11);
o->maximum(255);
o->step(1);
o->textsize(11);
o->callback((Fl_Callback*)image_spacing_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Box* o = new Fl_Box(281, 150, 60, 20);
o->labelsize(11);
o->hide();
Fl_Group::current()->resizable(o);
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Light_Button* o = new Fl_Light_Button(99, 175, 90, 20, "Compact");
o->tooltip("use compact box types for closely set buttons");
o->selection_color((Fl_Color)1);
o->labelsize(11);
o->callback((Fl_Callback*)compact_cb);
} // Fl_Light_Button* o
{ Fl_Box* o = new Fl_Box(195, 195, 40, 40);
{ Fl_Box* o = new Fl_Box(195, 205, 40, 40);
o->labelsize(11);
Fl_Group::current()->resizable(o);
} // Fl_Box* o

View File

@ -935,18 +935,37 @@ Use Ctrl-J for newlines.} xywh {95 285 310 20} labelfont 1 labelsize 11 textsize
code1 {o->menu(colormenu);}
} {}
}
Fl_Value_Input {} {
label {Image Spacing:}
callback image_spacing_cb
tooltip {Gap between label image and text in pixels} xywh {99 140 49 20} labelfont 1 labelsize 11 maximum 100 step 1 value 14 textsize 11
Fl_Group {} {
label {Label Margin:}
callback propagate_load open
xywh {99 150 242 20} labelfont 1 labelsize 11 align 4
} {
Fl_Value_Input {} {
label {Horizontal:}
callback h_label_margin_cb
tooltip {Spacing between label and the horizontally aligned side of the widget.} xywh {99 150 55 20} labelsize 11 align 5 minimum -127 maximum 128 step 1 textsize 11
}
Fl_Value_Input {} {
label {Vertical:}
callback v_label_margin_cb
tooltip {Spacing between label and the vertically aligned side of the widget.} xywh {159 150 55 20} labelsize 11 align 5 minimum -127 maximum 127 step 1 textsize 11
}
Fl_Value_Input {} {
label {Text to Image:}
callback image_spacing_cb
tooltip {Gap between label image and text in pixels} xywh {219 150 55 20} labelsize 11 align 5 maximum 255 step 1 textsize 11
}
Fl_Box {} {
xywh {281 150 60 20} labelsize 11 hide resizable
}
}
Fl_Light_Button {} {
label Compact
callback compact_cb
tooltip {use compact box types for closely set buttons} xywh {99 165 90 20} selection_color 1 labelsize 11
tooltip {use compact box types for closely set buttons} xywh {99 175 90 20} selection_color 1 labelsize 11
}
Fl_Box {} {
xywh {195 195 40 40} labelsize 11 resizable
xywh {195 205 40 40} labelsize 11 resizable
}
}
Fl_Group wp_cpp_tab {

View File

@ -144,6 +144,8 @@ extern void textsize_cb(Fl_Value_Input*, void*);
extern void textcolor_cb(Fl_Button*, void*);
extern Fl_Button *w_textcolor;
extern void textcolor_menu_cb(Fl_Menu_Button*, void*);
extern void h_label_margin_cb(Fl_Value_Input*, void*);
extern void v_label_margin_cb(Fl_Value_Input*, void*);
extern void image_spacing_cb(Fl_Value_Input*, void*);
extern void compact_cb(Fl_Light_Button*, void*);
extern Fl_Group *wp_cpp_tab;

View File

@ -113,7 +113,7 @@ void Fl_Choice::draw() {
l.font = m.labelsize_ || m.labelfont_ ? m.labelfont_ : textfont();
l.size = m.labelsize_ ? m.labelsize_ : textsize();
l.color= m.labelcolor_ ? m.labelcolor_ : textcolor();
l.spacing = 0;
l.h_margin_ = l.v_margin_ = l.spacing = 0;
if (!m.active()) l.color = fl_inactive((Fl_Color)l.color);
fl_draw_shortcut = 2; // hack value to make '&' disappear
l.draw(xx+3, yy, ww>6 ? ww-6 : 0, hh, FL_ALIGN_LEFT);

View File

@ -261,7 +261,7 @@ int Fl_Menu_Item::measure(int* hp, const Fl_Menu_* m) const {
l.font = labelsize_ || labelfont_ ? labelfont_ : (m ? m->textfont() : FL_HELVETICA);
l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE;
l.color = FL_FOREGROUND_COLOR; // this makes no difference?
l.spacing = 0;
l.h_margin_ = l.v_margin_ = l.spacing = 0;
fl_draw_shortcut = 1;
int w = 0; int h = 0;
l.measure(w, hp ? *hp : h);
@ -281,7 +281,7 @@ void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m,
l.font = labelsize_ || labelfont_ ? labelfont_ : (m ? m->textfont() : FL_HELVETICA);
l.size = labelsize_ ? labelsize_ : m ? m->textsize() : FL_NORMAL_SIZE;
l.color = labelcolor_ ? labelcolor_ : m ? m->textcolor() : int(FL_FOREGROUND_COLOR);
l.spacing = 0;
l.h_margin_ = l.v_margin_ = l.spacing = 0;
if (!active()) l.color = fl_inactive((Fl_Color)l.color);
if (selected) {
Fl_Color r = m ? m->selection_color() : FL_SELECTION_COLOR;

View File

@ -118,6 +118,7 @@ Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) {
label_.size = FL_NORMAL_SIZE;
label_.color = FL_FOREGROUND_COLOR;
label_.align_ = FL_ALIGN_CENTER;
label_.h_margin_ = label_.v_margin_ = 0;
label_.spacing = 0;
tooltip_ = 0;
callback_ = default_callback;

View File

@ -526,7 +526,7 @@ void Fl_Window::draw_backdrop() {
l1.image = image();
if (!active_r() && l1.image && l1.deimage) l1.image = l1.deimage;
l1.type = labeltype();
l1.spacing = 0;
l1.h_margin_ = l1.v_margin_ = l1.spacing = 0;
l1.draw(0,0,w(),h(),align());
}
}

View File

@ -82,6 +82,29 @@ void Fl::set_labeltype(Fl_Labeltype t,Fl_Label_Draw_F* f,Fl_Label_Measure_F*m)
/** Draws a label with arbitrary alignment in an arbitrary box. */
void Fl_Label::draw(int X, int Y, int W, int H, Fl_Align align) const {
if (!value && !image) return;
const Fl_Align FL_ALIGN_CENTER = 0x0000;
const Fl_Align FL_ALIGN_TOP = 0x0001;
const Fl_Align FL_ALIGN_BOTTOM = 0x0002;
const Fl_Align FL_ALIGN_LEFT = 0x0004;
const Fl_Align FL_ALIGN_RIGHT = 0x0008;
const Fl_Align FL_ALIGN_TOP_LEFT = FL_ALIGN_TOP | FL_ALIGN_LEFT;
const Fl_Align FL_ALIGN_TOP_RIGHT = FL_ALIGN_TOP | FL_ALIGN_RIGHT;
const Fl_Align FL_ALIGN_BOTTOM_LEFT = FL_ALIGN_BOTTOM | FL_ALIGN_LEFT;
const Fl_Align FL_ALIGN_BOTTOM_RIGHT = FL_ALIGN_BOTTOM | FL_ALIGN_RIGHT;
const Fl_Align FL_ALIGN_LEFT_TOP = 0x0007;
const Fl_Align FL_ALIGN_RIGHT_TOP = 0x000b;
const Fl_Align FL_ALIGN_LEFT_BOTTOM = 0x000d;
const Fl_Align FL_ALIGN_RIGHT_BOTTOM = 0x000e;
switch (align&(FL_ALIGN_TOP|FL_ALIGN_BOTTOM)) {
case 0: Y += v_margin_; H -= 2*v_margin_; break;
case FL_ALIGN_TOP: Y += v_margin_; H -= v_margin_; break;
case FL_ALIGN_BOTTOM: H -= v_margin_; break;
}
switch (align&(FL_ALIGN_LEFT|FL_ALIGN_RIGHT)) {
case 0: X += h_margin_; W -= 2*h_margin_; break;
case FL_ALIGN_LEFT: X += h_margin_; W -= h_margin_; break;
case FL_ALIGN_RIGHT: W -= h_margin_; break;
}
table[type](this, X, Y, W, H, align);
}
/**
@ -95,6 +118,7 @@ void Fl_Label::measure(int& W, int& H) const {
return;
}
// if (W > 0) W -= h_margin_;
Fl_Label_Measure_F* f = ::measure[type]; if (!f) f = fl_normal_measure;
f(this, W, H);
}

View File

@ -32,7 +32,7 @@ Fl_Box *text;
Fl_Input *input;
Fl_Hor_Value_Slider *fonts;
Fl_Hor_Value_Slider *sizes;
Fl_Hor_Value_Slider *spacing;
Fl_Hor_Value_Slider *h_margin, *v_margin, *img_spacing;
Fl_Double_Window *window;
Fl_Pixmap *img;
@ -65,8 +65,18 @@ void font_cb(Fl_Widget *,void *) {
window->redraw();
}
void h_margin_cb(Fl_Widget *,void *) {
text->horizontal_label_margin(int(h_margin->value()));
window->redraw();
}
void v_margin_cb(Fl_Widget *,void *) {
text->vertical_label_margin(int(v_margin->value()));
window->redraw();
}
void spacing_cb(Fl_Widget *,void *) {
text->label_image_spacing(int(spacing->value()));
text->label_image_spacing(int(img_spacing->value()));
window->redraw();
}
@ -120,9 +130,9 @@ Fl_Menu_Item choices[] = {
int main(int argc, char **argv) {
img = new Fl_Pixmap(blast_xpm);
window = new Fl_Double_Window(440,445);
window = new Fl_Double_Window(440,495);
input = new Fl_Input(70,400,350,25,"Label:");
input = new Fl_Input(70,435,350,25,"Label:");
input->static_value("The quick brown fox jumped over the lazy dog.");
input->when(FL_WHEN_CHANGED);
input->callback(input_cb);
@ -142,12 +152,30 @@ int main(int argc, char **argv) {
fonts->value(0);
fonts->callback(font_cb);
spacing=new Fl_Hor_Value_Slider(70,375,350,25,"Spacing:");
spacing->align(FL_ALIGN_LEFT);
spacing->bounds(0,100);
spacing->step(1);
spacing->value(0);
spacing->callback(spacing_cb);
Fl_Box *margin = new Fl_Box(0, 380, 70, 25, "Margins");
margin->box(FL_FLAT_BOX);
margin->align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE);
h_margin = new Fl_Hor_Value_Slider(70+50,380,125,25,"Hor:");
h_margin->align(FL_ALIGN_LEFT);
h_margin->bounds(-25,25);
h_margin->step(1);
h_margin->value(0);
h_margin->callback(h_margin_cb);
v_margin = new Fl_Hor_Value_Slider(70+175+50,380,125,25,"Vert:");
v_margin->align(FL_ALIGN_LEFT);
v_margin->bounds(-25,25);
v_margin->step(1);
v_margin->value(0);
v_margin->callback(v_margin_cb);
img_spacing = new Fl_Hor_Value_Slider(70+50,405,125,25,"Image:");
img_spacing->align(FL_ALIGN_LEFT);
img_spacing->bounds(0,50);
img_spacing->step(1);
img_spacing->value(0);
img_spacing->callback(spacing_cb);
Fl_Group *g = new Fl_Group(70,275,350,50);
imageb = new Fl_Toggle_Button(70,275,50,25,"image");