Fluid support for Fl_Flex (#523) and some Fl_Flex improvements

* Adding Fluid support for Fl_Flex, margins, and gap.

* Fluid Fl_Flex mostly working. Fixed in Fl_Flex::set_size().

* Fluid Flex live mode works, interactive dragging works

* Fluid Flex: adding check box for fixed children

* Fluid Flex: visual flexibility indicator in guides.

* Fluid Flex: bug in generated code.

* Fix formatting

* Fixing Tooltip, fixing resize issue PR #518.

* Removing unused variables.

Co-authored-by: Albrecht Schlosser <albrechts.fltk@online.de>
This commit is contained in:
Matthias Melcher 2022-11-01 13:30:05 +01:00 committed by GitHub
parent 31ec6f623a
commit 93ea93ee2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 833 additions and 48 deletions

View File

@ -34,6 +34,7 @@
#include "../src/flstring.h"
#include <stdio.h>
#include <stdlib.h>
// Override group's resize behavior to do nothing to children:
void igroup::resize(int X, int Y, int W, int H) {
@ -146,6 +147,226 @@ Fl_Menu_Item pack_type_menu[] = {
Fl_Pack_Type Fl_Pack_type; // the "factory"
void Fl_Pack_Type::copy_properties()
{
Fl_Group_Type::copy_properties();
Fl_Pack *d = (Fl_Pack*)live_widget, *s =(Fl_Pack*)o;
d->spacing(s->spacing());
}
////////////////////////////////////////////////////////////////
const char flex_type_name[] = "Fl_Flex";
Fl_Menu_Item flex_type_menu[] = {
{"HORIZONTAL", 0, 0, (void*)Fl_Flex::HORIZONTAL},
{"VERTICAL", 0, 0, (void*)Fl_Flex::VERTICAL},
{0}};
Fl_Flex_Type Fl_Flex_type; // the "factory"
Fl_Widget *Fl_Flex_Type::enter_live_mode(int) {
Fl_Flex *grp = new Fl_Flex(o->x(), o->y(), o->w(), o->h());
live_widget = grp;
copy_properties();
suspend_auto_layout = 1;
Fl_Type *n;
for (n = next; n && n->level > level; n = n->next) {
if (n->level == level+1)
n->enter_live_mode();
}
suspend_auto_layout = 0;
Fl_Flex *d = grp, *s =(Fl_Flex*)o;
int nc = s->children(), nd = d->children();
if (nc>nd) nc = nd;
for (int i=0; i<nc; i++) {
if (s->set_size(s->child(i))) {
Fl_Widget *dc = d->child(i);
d->set_size(d->child(i), s->horizontal() ? dc->w() : dc->h());
}
}
grp->end(); //this also updates the layout
return live_widget;
}
void Fl_Flex_Type::copy_properties()
{
Fl_Group_Type::copy_properties();
Fl_Flex *d = (Fl_Flex*)live_widget, *s =(Fl_Flex*)o;
int lm, tm, rm, bm;
s->margins(&lm, &tm, &rm, &bm);
d->margin(lm, tm, rm, bm);
d->gap( s->gap() );
}
void Fl_Flex_Type::write_properties()
{
Fl_Group_Type::write_properties();
Fl_Flex* f = (Fl_Flex*)o;
int lm, tm, rm, bm;
f->margins(&lm, &tm, &rm, &bm);
if (lm!=0 || tm!=0 || rm!=0 || bm!=0)
write_string("margins {%d %d %d %d}", lm, tm, rm, bm);
if (f->gap())
write_string("gap %d", f->gap());
int nSet = 0;
for (int i=0; i<f->children(); i++)
if (f->set_size(f->child(i)))
nSet++;
if (nSet) {
write_string("size_set {%d", nSet);
for (int i=0; i<f->children(); i++)
if (f->set_size(f->child(i)))
write_string(" %d", i);
write_string("}");
}
}
void Fl_Flex_Type::read_property(const char *c)
{
Fl_Flex* f = (Fl_Flex*)o;
suspend_auto_layout = 1;
if (!strcmp(c,"margins")) {
int lm, tm, rm, bm;
if (sscanf(read_word(),"%d %d %d %d",&lm,&tm,&rm,&bm) == 4)
f->margin(lm, tm, rm, bm);
} else if (!strcmp(c,"gap")) {
int g;
if (sscanf(read_word(),"%d",&g))
f->gap(g);
} else if (!strcmp(c,"size_set")) {
read_word(1); // must be '{'
const char *nStr = read_word(1); // number of indices in table
fixedSizeTableSize = atoi(nStr);
fixedSizeTable = new int[fixedSizeTableSize];
for (int i=0; i<fixedSizeTableSize; i++) {
const char *ix = read_word(1); // child at that index is fixed in size
fixedSizeTable[i] = atoi(ix);
}
read_word(1); // must be '}'
} else {
Fl_Group_Type::read_property(c);
}
}
void Fl_Flex_Type::postprocess_read()
{
if (fixedSizeTableSize==0) return;
Fl_Flex* f = (Fl_Flex*)o;
for (int i=0; i<fixedSizeTableSize; i++) {
int ix = fixedSizeTable[i];
if (ix>=0 && ix<f->children()) {
Fl_Widget *ci = f->child(ix);
f->set_size(ci, f->horizontal()?ci->w():ci->h());
}
}
fixedSizeTableSize = 0;
delete[] fixedSizeTable;
fixedSizeTable = NULL;
f->layout();
suspend_auto_layout = 0;
}
void Fl_Flex_Type::write_code2() {
const char *var = name() ? name() : "o";
Fl_Flex* f = (Fl_Flex*)o;
int lm, tm, rm, bm;
f->margins(&lm, &tm, &rm, &bm);
if (lm!=0 || tm!=0 || rm!=0 || bm!=0)
write_c("%s%s->margin(%d, %d, %d, %d);\n", indent(), var, lm, tm, rm, bm);
if (f->gap())
write_c("%s%s->gap(%d);\n", indent(), var, f->gap());
for (int i=0; i<f->children(); ++i) {
Fl_Widget *ci = f->child(i);
if (f->set_size(ci))
write_c("%s%s->set_size(%s->child(%d), %d);\n", indent(), var, var, i,
f->horizontal() ? ci->w() : ci->h());
}
Fl_Group_Type::write_code2();
}
void Fl_Flex_Type::add_child(Fl_Type* a, Fl_Type* b) {
Fl_Group_Type::add_child(a, b);
if (!suspend_auto_layout)
((Fl_Flex*)o)->layout();
}
void Fl_Flex_Type::move_child(Fl_Type* a, Fl_Type* b) {
Fl_Group_Type::move_child(a, b);
if (!suspend_auto_layout)
((Fl_Flex*)o)->layout();
}
void Fl_Flex_Type::remove_child(Fl_Type* a) {
if (a->is_widget())
((Fl_Flex*)o)->set_size(((Fl_Widget_Type*)a)->o, 0);
Fl_Group_Type::remove_child(a);
((Fl_Flex*)o)->layout();
}
// Change from HORIZONTAL to VERTICAL or back.
// Children in a horizontal Flex have already the full vertical height. If we
// just change to vertical, the accumulated hight of all children is too big.
// We need to relayout existing children.
void Fl_Flex_Type::change_subtype_to(int n) {
Fl_Flex* f = (Fl_Flex*)o;
int nc = f->children();
if (f->type()==n || nc==0) return;
int dw = Fl::box_dw(f->box());
int dh = Fl::box_dh(f->box());
int lm, tm, rm, bm;
f->margins(&lm, &tm, &rm, &bm);
int gap = f->gap();
int fw = f->w()-dw-lm-rm-(nc*gap);
if (fw<=nc) fw = nc; // avoid division by zero
int fh = f->h()-dh-tm-bm-(nc*gap);
if (fh<=nc) fh = nc; // avoid division by zero
if (f->type()==Fl_Flex::HORIZONTAL && n==Fl_Flex::VERTICAL) {
float scl = (float)fh/(float)fw;
for (int i=0; i<nc; i++) {
Fl_Widget* c = f->child(i);
c->size(f->w(), (int)(c->w()*scl));
}
} else if (f->type()==Fl_Flex::VERTICAL && n==Fl_Flex::HORIZONTAL) {
float scl = (float)fw/(float)fh;
for (int i=0; i<nc; i++) {
Fl_Widget* c = f->child(i);
c->size((int)(c->h()*scl), f->h());
}
}
f->type(n);
f->layout();
}
int Fl_Flex_Type::parent_is_flex(Fl_Type *t) {
return (t->is_widget()
&& t->parent
&& t->parent->is_flex());
}
int Fl_Flex_Type::size(Fl_Type *t, char fixed_only) {
if (!t->is_widget()) return 0;
if (!t->parent) return 0;
if (!t->parent->is_flex()) return 0;
Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent;
Fl_Flex* f = (Fl_Flex*)ft->o;
Fl_Widget *w = ((Fl_Widget_Type*)t)->o;
if (fixed_only && !f->set_size(w)) return 0;
return f->horizontal() ? w->w() : w->h();
}
int Fl_Flex_Type::is_fixed(Fl_Type *t) {
if (!t->is_widget()) return 0;
if (!t->parent) return 0;
if (!t->parent->is_flex()) return 0;
Fl_Flex_Type* ft = (Fl_Flex_Type*)t->parent;
Fl_Flex* f = (Fl_Flex*)ft->o;
Fl_Widget *w = ((Fl_Widget_Type*)t)->o;
return f->set_size(w);
}
////////////////////////////////////////////////////////////////
static const int MAX_ROWS = 14;

View File

@ -21,6 +21,7 @@
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Pack.H>
#include <FL/Fl_Flex.H>
#include <FL/Fl_Wizard.H>
void group_cb(Fl_Widget *, void *);
@ -82,6 +83,38 @@ public:
void copy_properties();
};
extern const char flex_type_name[];
extern Fl_Menu_Item flex_type_menu[];
class Fl_Flex_Type : public Fl_Group_Type {
Fl_Menu_Item *subtypes() {return flex_type_menu;}
int fixedSizeTableSize;
int *fixedSizeTable;
int suspend_auto_layout;
public:
Fl_Flex_Type() : fixedSizeTableSize(0), fixedSizeTable(NULL), suspend_auto_layout(0) { }
virtual const char *type_name() {return flex_type_name;}
virtual const char *alt_type_name() {return "fltk::FlexGroup";}
Fl_Widget_Type *_make() { return new Fl_Flex_Type(); }
Fl_Widget *widget(int X,int Y,int W,int H) {
Fl_Flex *g = new Fl_Flex(X,Y,W,H); Fl_Group::current(0); return g;}
int pixmapID() { return 56; }
void write_properties();
void read_property(const char *);
Fl_Widget *enter_live_mode(int top=0);
void copy_properties();
void postprocess_read();
void write_code2();
void add_child(Fl_Type*, Fl_Type*);
void move_child(Fl_Type*, Fl_Type*);
void remove_child(Fl_Type*);
int is_flex() const {return 1;}
void change_subtype_to(int n);
static int parent_is_flex(Fl_Type*);
static int size(Fl_Type*, char fixed_only=0);
static int is_fixed(Fl_Type*);
};
extern const char table_type_name[];
class Fl_Table_Type : public Fl_Group_Type {

View File

@ -126,6 +126,7 @@ public:
virtual void write_properties();
virtual void read_property(const char *);
virtual int read_fdesign(const char*, const char*);
virtual void postprocess_read() { }
// write code, these are called in order:
virtual void write_static(); // write static stuff to .c file
@ -155,6 +156,7 @@ public:
virtual int is_menu_item() const {return 0;}
virtual int is_menu_button() const {return 0;}
virtual int is_group() const {return 0;}
virtual int is_flex() const {return 0;}
virtual int is_window() const {return 0;}
virtual int is_code() const {return 0;}
virtual int is_code_block() const {return 0;}

View File

@ -1614,8 +1614,7 @@ void textcolor_cb(Fl_Button* i, void* v) {
void min_w_cb(Fl_Value_Input* i, void* v) {
if (v == LOAD) {
if (!current_widget->is_window()) {i->parent()->hide(); return;}
i->parent()->show();
if (!current_widget->is_window()) return;
i->value(((Fl_Window_Type*)current_widget)->sr_min_w);
} else {
int mod = 0;
@ -1717,10 +1716,6 @@ void set_max_size_cb(Fl_Button*, void* v) {
void slider_size_cb(Fl_Value_Input* i, void* v) {
if (v == LOAD) {
if (current_widget->is_window())
i->parent()->hide();
else
i->parent()->show();
if (current_widget->is_valuator()<2) {i->deactivate(); return;}
i->activate();
i->value(((Fl_Slider*)(current_widget->o))->slider_size());
@ -1876,6 +1871,271 @@ void value_cb(Fl_Value_Input* i, void* v) {
}
}
// The following three callbacks cooperate, showing only one of the groups of
// widgets that use the same space in the dialog.
void values_group_cb(Fl_Group* g, void* v) {
if (v == LOAD) {
if (current_widget->is_flex()) {
g->hide();
} else if (current_widget->is_window()) {
g->hide();
} else {
g->show();
}
propagate_load(g, v);
}
}
void flex_margin_group_cb(Fl_Group* g, void* v) {
if (v == LOAD) {
if (current_widget->is_flex()) {
g->show();
} else {
g->hide();
}
propagate_load(g, v);
}
}
void size_range_group_cb(Fl_Group* g, void* v) {
if (v == LOAD) {
if (current_widget->is_window()) {
g->show();
} else {
g->hide();
}
propagate_load(g, v);
}
}
static void flex_margin_cb(Fl_Value_Input* i, void* v,
void (*load_margin)(Fl_Flex*,Fl_Value_Input*),
int (*update_margin)(Fl_Flex*,int)) {
if (v == LOAD) {
if (current_widget->is_flex()) {
load_margin((Fl_Flex*)current_widget->o, i);
}
} else {
int mod = 0;
int new_value = (int)i->value();
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_flex()) {
Fl_Flex_Type* q = (Fl_Flex_Type*)o;
Fl_Flex* w = (Fl_Flex*)q->o;
if (update_margin(w, new_value)) {
w->layout();
mod = 1;
}
}
}
if (mod) set_modflag(1);
}
}
static void load_left_margin(Fl_Flex *w, Fl_Value_Input* i)
{
int v;
w->margins(&v, NULL, NULL, NULL);
i->value((double)v);
}
static int update_left_margin(Fl_Flex *w, int new_value)
{
int l, t, r, b;
w->margins(&l, &t, &r, &b);
if (new_value!=l) {
w->margin(new_value, t, r, b);
return 1;
} else {
return 0;
}
}
void flex_margin_left_cb(Fl_Value_Input* i, void* v) {
flex_margin_cb(i, v, load_left_margin, update_left_margin);
}
static void load_top_margin(Fl_Flex *w, Fl_Value_Input* i)
{
int v;
w->margins(NULL, &v, NULL, NULL);
i->value((double)v);
}
static int update_top_margin(Fl_Flex *w, int new_value)
{
int l, t, r, b;
w->margins(&l, &t, &r, &b);
if (new_value!=t) {
w->margin(l, new_value, r, b);
return 1;
} else {
return 0;
}
}
void flex_margin_top_cb(Fl_Value_Input* i, void* v) {
flex_margin_cb(i, v, load_top_margin, update_top_margin);
}
static void load_right_margin(Fl_Flex *w, Fl_Value_Input* i)
{
int v;
w->margins(NULL, NULL, &v, NULL);
i->value((double)v);
}
static int update_right_margin(Fl_Flex *w, int new_value)
{
int l, t, r, b;
w->margins(&l, &t, &r, &b);
if (new_value!=r) {
w->margin(l, t, new_value, b);
return 1;
} else {
return 0;
}
}
void flex_margin_right_cb(Fl_Value_Input* i, void* v) {
flex_margin_cb(i, v, load_right_margin, update_right_margin);
}
static void load_bottom_margin(Fl_Flex *w, Fl_Value_Input* i)
{
int v;
w->margins(NULL, NULL, NULL, &v);
i->value((double)v);
}
static int update_bottom_margin(Fl_Flex *w, int new_value)
{
int l, t, r, b;
w->margins(&l, &t, &r, &b);
if (new_value!=b) {
w->margin(l, t, r, new_value);
return 1;
} else {
return 0;
}
}
void flex_margin_bottom_cb(Fl_Value_Input* i, void* v) {
flex_margin_cb(i, v, load_bottom_margin, update_bottom_margin);
}
static void load_gap(Fl_Flex *w, Fl_Value_Input* i)
{
int v = w->gap();
i->value((double)v);
}
static int update_gap(Fl_Flex *w, int new_value)
{
int g = w->gap();
if (new_value!=g) {
w->gap(new_value);
return 1;
} else {
return 0;
}
}
void flex_margin_gap_cb(Fl_Value_Input* i, void* v) {
flex_margin_cb(i, v, load_gap, update_gap);
}
void position_group_cb(Fl_Group* g, void* v) {
if (v == LOAD) {
if (Fl_Flex_Type::parent_is_flex(current_widget)) {
g->hide();
} else {
g->show();
}
}
propagate_load(g, v);
}
void flex_size_group_cb(Fl_Group* g, void* v) {
if (v == LOAD) {
if (Fl_Flex_Type::parent_is_flex(current_widget)) {
g->show();
} else {
g->hide();
}
}
propagate_load(g, v);
}
void flex_size_cb(Fl_Value_Input* i, void* v) {
if (v == LOAD) {
if (Fl_Flex_Type::parent_is_flex(current_widget)) {
i->value(Fl_Flex_Type::size(current_widget));
}
} else {
int mod = 0;
int new_size = (int)i->value();
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) {
Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o;
Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o;
int was_fixed = f->set_size(w);
if (new_size==0) {
if (was_fixed) {
f->set_size(w, 0);
f->layout();
widget_flex_fixed->value(0);
mod = 1;
}
} else {
int old_size = Fl_Flex_Type::size(o);
if (old_size!=new_size || !was_fixed) {
f->set_size(w, new_size);
f->layout();
widget_flex_fixed->value(1);
mod = 1;
}
}
}
}
if (mod) set_modflag(1);
}
}
void flex_fixed_cb(Fl_Check_Button* i, void* v) {
if (v == LOAD) {
if (Fl_Flex_Type::parent_is_flex(current_widget)) {
i->value(Fl_Flex_Type::is_fixed(current_widget));
}
} else {
int mod = 0;
int new_fixed = (int)i->value();
for (Fl_Type *o = Fl_Type::first; o; o = o->next) {
if (o->selected && o->is_widget() && Fl_Flex_Type::parent_is_flex(o)) {
Fl_Widget* w = (Fl_Widget*)((Fl_Widget_Type*)o)->o;
Fl_Flex* f = (Fl_Flex*)((Fl_Flex_Type*)o->parent)->o;
int was_fixed = f->set_size(w);
if (new_fixed==0) {
if (was_fixed) {
f->set_size(w, 0);
f->layout();
mod = 1;
}
} else {
if (!was_fixed) {
f->set_size(w, Fl_Flex_Type::size(o));
f->layout();
mod = 1;
}
}
}
}
if (mod) set_modflag(1);
}
}
////////////////////////////////////////////////////////////////
// subtypes:
@ -1918,6 +2178,8 @@ void subtype_cb(Fl_Choice* i, void* v) {
if (q->subtypes()==m) {
if (q->is_spinner())
((Fl_Spinner*)q->o)->type(n);
else if (q->is_flex())
((Fl_Flex_Type*)q)->change_subtype_to(n);
else
q->o->type(n);
q->redraw();
@ -3048,9 +3310,3 @@ void Fl_Widget_Type::copy_properties() {
w->parent()->resizable(o);
}
void Fl_Pack_Type::copy_properties()
{
Fl_Group_Type::copy_properties();
Fl_Pack *d = (Fl_Pack*)live_widget, *s =(Fl_Pack*)o;
d->spacing(s->spacing());
}

View File

@ -20,6 +20,7 @@
#include "Fl_Window_Type.h"
#include "Fl_Group_Type.h"
#include "fluid.h"
#include "widget_browser.h"
#include "undo.h"
@ -54,10 +55,15 @@ inline int fl_min(int a, int b) { return (a < b ? a : b); }
// Update the XYWH values in the widget panel...
static void update_xywh() {
if (current_widget && current_widget->is_widget()) {
widget_x_input->value(((Fl_Widget_Type *)current_widget)->o->x());
widget_y_input->value(((Fl_Widget_Type *)current_widget)->o->y());
widget_w_input->value(((Fl_Widget_Type *)current_widget)->o->w());
widget_h_input->value(((Fl_Widget_Type *)current_widget)->o->h());
Fl_Widget *o = ((Fl_Widget_Type *)current_widget)->o;
widget_x_input->value(o->x());
widget_y_input->value(o->y());
widget_w_input->value(o->w());
widget_h_input->value(o->h());
if (Fl_Flex_Type::parent_is_flex(current_widget)) {
widget_flex_size->value(Fl_Flex_Type::size(current_widget));
widget_flex_fixed->value(Fl_Flex_Type::is_fixed(current_widget));
}
}
}
@ -798,7 +804,28 @@ void Fl_Window_Type::draw_overlay() {
Fl_Widget_Type* myo = (Fl_Widget_Type*)q;
int x,y,r,t;
newposition(myo,x,y,r,t);
if (!show_guides || !drag || numselected != 1) fl_rect(x,y,r-x,t-y);
if (!show_guides || !drag || numselected != 1) {
if (Fl_Flex_Type::parent_is_flex(q) && !Fl_Flex_Type::is_fixed(q)) {
if (((Fl_Flex*)((Fl_Flex_Type*)q->parent)->o)->horizontal()) {
int yh = y + (t-y)/2;
fl_begin_loop();
fl_vertex(x+2, yh); fl_vertex(x+12, yh+5); fl_vertex(x+12, yh-5);
fl_end_loop();
fl_begin_loop();
fl_vertex(r-3, yh); fl_vertex(r-13, yh+5); fl_vertex(r-13, yh-5);
fl_end_loop();
} else {
int xh = x + (r-x)/2;
fl_begin_loop();
fl_vertex(xh, y+2); fl_vertex(xh+5, y+12); fl_vertex(xh-5, y+12);
fl_end_loop();
fl_begin_loop();
fl_vertex(xh, t-3); fl_vertex(xh+5, t-13); fl_vertex(xh-5, t-13);
fl_end_loop();
}
}
fl_rect(x,y,r-x,t-y);
}
if (x < mysx) mysx = x;
if (y < mysy) mysy = y;
if (r > mysr) mysr = r;
@ -1188,13 +1215,28 @@ void Fl_Window_Type::moveallchildren()
for (i=next; i && i->level>level;) {
if (i->selected && i->is_widget() && !i->is_menu_item()) {
Fl_Widget_Type* myo = (Fl_Widget_Type*)i;
int x,y,r,t;
int x,y,r,t,ow=myo->o->w(),oh=myo->o->h();
newposition(myo,x,y,r,t);
myo->o->resize(x,y,r-x,t-y);
if (Fl_Flex_Type::parent_is_flex(myo)) {
Fl_Flex_Type* ft = (Fl_Flex_Type*)myo->parent;
Fl_Flex* f = (Fl_Flex*)ft->o;
if (f->horizontal()) {
if (myo->o->w()!=ow) {
f->set_size(myo->o, myo->o->w());
f->layout();
}
} else {
if (myo->o->h()!=oh) {
f->set_size(myo->o, myo->o->h());
f->layout();
}
}
}
// move all the children, whether selected or not:
Fl_Type* p;
for (p = myo->next; p && p->level>myo->level; p = p->next)
if (p->is_widget() && !p->is_menu_item()) {
if (p->is_widget() && !p->is_menu_item() && !myo->is_flex()) {
Fl_Widget_Type* myo2 = (Fl_Widget_Type*)p;
int X,Y,R,T;
newposition(myo2,X,Y,R,T);

View File

@ -26,6 +26,7 @@
#include "fluid.h"
#include "Fl_Window_Type.h"
#include "Fl_Group_Type.h"
#include "pixmaps.h"
#include "undo.h"
@ -35,6 +36,7 @@
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Tree.H>
#include <FL/Fl_Flex.H>
#include "../src/flstring.h"
#include <stdio.h>
@ -938,6 +940,7 @@ extern class Fl_Window_Type Fl_Window_type;
extern class Fl_Widget_Class_Type Fl_Widget_Class_type;
extern class Fl_Group_Type Fl_Group_type;
extern class Fl_Pack_Type Fl_Pack_type;
extern class Fl_Flex_Type Fl_Flex_type;
extern class Fl_Tabs_Type Fl_Tabs_type;
extern class Fl_Scroll_Type Fl_Scroll_type;
extern class Fl_Table_Type Fl_Table_type;
@ -976,6 +979,7 @@ static Fl_Type *known_types[] = {
(Fl_Type*)&Fl_Window_type,
(Fl_Type*)&Fl_Group_type,
(Fl_Type*)&Fl_Pack_type,
(Fl_Type*)&Fl_Flex_type,
(Fl_Type*)&Fl_Tabs_type,
(Fl_Type*)&Fl_Scroll_type,
(Fl_Type*)&Fl_Tile_type,
@ -1055,7 +1059,8 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) {
undo_suspend();
Fl_Type *t = ((Fl_Type*)inPrototype)->make(strategy);
if (t) {
if (t->is_widget() && !t->is_window()) {
if (t->is_widget() && !t->is_window())
{
Fl_Widget_Type *wt = (Fl_Widget_Type *)t;
// Set font sizes...
@ -1071,7 +1076,9 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) {
int w = 0, h = 0;
wt->ideal_size(w, h);
if (!strcmp(wt->type_name(), "Fl_Menu_Bar")) {
if ((t->parent && t->parent->is_flex())) {
// Do not resize or layout the widget. Flex will need the widget size.
} else if (!strcmp(wt->type_name(), "Fl_Menu_Bar")) {
// Move and resize the menubar across the top of the window...
wt->o->resize(0, 0, w, h);
} else {
@ -1143,6 +1150,7 @@ Fl_Menu_Item New_Menu[] = {
{0,0,cb,(void*)&Fl_Window_type},
{0,0,cb,(void*)&Fl_Group_type},
{0,0,cb,(void*)&Fl_Pack_type},
{0,0,cb,(void*)&Fl_Flex_type},
{0,0,cb,(void*)&Fl_Tabs_type},
{0,0,cb,(void*)&Fl_Scroll_type},
{0,0,cb,(void*)&Fl_Tile_type},

View File

@ -624,6 +624,7 @@ static void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_op
goto REUSE_C;
}
read_children(t, 0, strategy, skip_options);
t->postprocess_read();
}
Fl_Type::current = p;

View File

@ -856,6 +856,20 @@ Fl_Window* make_widgetbin() {
o->when(FL_WHEN_RELEASE);
o->image(pixmap[19]);
} // Widget_Bin_Button* o
{ Widget_Bin_Button* o = new Widget_Bin_Button(139, 46, 24, 24);
o->tooltip("Flex");
o->box(FL_THIN_UP_BOX);
o->color(FL_BACKGROUND_COLOR);
o->selection_color(FL_BACKGROUND_COLOR);
o->labeltype(FL_NORMAL_LABEL);
o->labelfont(0);
o->labelsize(14);
o->labelcolor(FL_FOREGROUND_COLOR);
o->callback((Fl_Callback*)type_make_cb, (void*)("Fl_Flex"));
o->align(Fl_Align(FL_ALIGN_CENTER));
o->when(FL_WHEN_RELEASE);
o->image(pixmap[56]);
} // Widget_Bin_Button* o
{ Widget_Bin_Button* o = new Widget_Bin_Button(89, 71, 24, 24);
o->tooltip("Tile");
o->box(FL_THIN_UP_BOX);

View File

@ -50,7 +50,7 @@ Function {use_tab_navigation(int, Fl_Text_Editor*)} {
Function {make_function_panel()} {open
} {
Fl_Window function_panel {
label {Function/Method Properties} open
label {Function/Method Properties}
xywh {540 418 343 232} type Double hide resizable modal
} {
Fl_Group {} {open
@ -537,15 +537,15 @@ else
add_new_widget_from_user(type_name, kAddAfterCurrent);} {}
}
Function {make_widgetbin()} {open selected
Function {make_widgetbin()} {open
} {
Fl_Window widgetbin_panel {
label {Widget Bin}
callback {if (Fl::event()==FL_SHORTCUT && Fl::event_key()==FL_Escape)
exit_cb((Fl_Widget*)o, v);
else
toggle_widgetbin_cb((Fl_Widget*)o, v);}
xywh {449 206 600 102} type Single align 80 hide non_modal
toggle_widgetbin_cb((Fl_Widget*)o, v);} open
xywh {449 206 600 102} type Single align 80 non_modal visible
} {
Fl_Group {} {
label Code open
@ -645,6 +645,13 @@ else
code0 {o->image(pixmap[19]);}
class Widget_Bin_Button
}
Fl_Button {} {
user_data {"Fl_Flex"}
callback type_make_cb selected
tooltip Flex xywh {139 46 24 24} box THIN_UP_BOX
code0 {o->image(pixmap[56]);}
class Widget_Bin_Button
}
Fl_Button {} {
user_data {"Fl_Tile"}
callback type_make_cb

View File

@ -77,6 +77,7 @@
#include "pixmaps/flInputChoice.xpm"
#include "pixmaps/flCheckMenuitem.xpm"
#include "pixmaps/flRadioMenuitem.xpm"
#include "pixmaps/flFlex.xpm"
Fl_Pixmap *lock_pixmap;
Fl_Pixmap *protected_pixmap;
@ -137,8 +138,9 @@ Fl_Pixmap *simple_terminal_pixmap;
Fl_Pixmap *input_choice_pixmap;
Fl_Pixmap *check_menuitem_pixmap;
Fl_Pixmap *radio_menuitem_pixmap;
Fl_Pixmap *flex_pixmap;
Fl_Pixmap *pixmap[56];
Fl_Pixmap *pixmap[57];
void loadPixmaps()
{
@ -211,5 +213,7 @@ void loadPixmaps()
pixmap[53] = input_choice_pixmap = new Fl_Pixmap(flInputChoice_xpm); input_choice_pixmap->scale(16, 16);
pixmap[54] = check_menuitem_pixmap = new Fl_Pixmap(flCheckMenuitem_xpm); check_menuitem_pixmap->scale(16, 16);
pixmap[55] = radio_menuitem_pixmap = new Fl_Pixmap(flRadioMenuitem_xpm); radio_menuitem_pixmap->scale(16, 16);
pixmap[56] = flex_pixmap = new Fl_Pixmap(flFlex_xpm); flex_pixmap->scale(16, 16);
}

View File

@ -75,6 +75,7 @@ extern Fl_Pixmap *data_pixmap;
extern Fl_Pixmap *tree_pixmap;
extern Fl_Pixmap *table_pixmap;
extern Fl_Pixmap *simple_terminal_pixmap;
extern Fl_Pixmap *flex_pixmap;
extern Fl_Pixmap *pixmap[];

45
fluid/pixmaps/flFlex.xpm Normal file
View File

@ -0,0 +1,45 @@
/* XPM */
static const char * const flFlex_xpm[] = {
/* width height ncolors chars_per_pixel */
"32 32 6 1",
/* colors */
"a c #606060",
"b c #2020ff",
"c c none",
"d c #999999",
"e c #8080ff",
"f c #000000",
/* pixels */
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"ffffffffffffffffffffffffffffffcc",
"ffffffffffffffffffffffffffffffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffffffffffffffffffffffffffffffcc",
"ffffffffffffffffffffffffffffffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffffffffffffffffffffffffffffffcc",
"ffffffffffffffffffffffffffffffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffddddddddddddddddddddddddddffcc",
"ffffffffffffffffffffffffffffffcc",
"ffffffffffffffffffffffffffffffcc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc",
"cccccccccccccccccccccccccccccccc"
};

View File

@ -60,6 +60,10 @@ Fluid_Coord_Input *widget_w_input=(Fluid_Coord_Input *)0;
Fluid_Coord_Input *widget_h_input=(Fluid_Coord_Input *)0;
Fl_Value_Input *widget_flex_size=(Fl_Value_Input *)0;
Fl_Check_Button *widget_flex_fixed=(Fl_Check_Button *)0;
Fl_Menu_Item menu_2[] = {
{"private", 0, 0, (void*)(0), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
{"public", 0, 0, (void*)(1), 0, (uchar)FL_NORMAL_LABEL, 0, 11, 0},
@ -260,8 +264,9 @@ Fl_Double_Window* make_widget_panel() {
{ Fl_Group* o = new Fl_Group(95, 150, 314, 20, "Position:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)propagate_load);
o->callback((Fl_Callback*)position_group_cb);
o->align(Fl_Align(FL_ALIGN_LEFT));
o->hide();
{ widget_x_input = new Fluid_Coord_Input(95, 150, 55, 20, "X:");
widget_x_input->tooltip("The X position of the widget.");
widget_x_input->box(FL_DOWN_BOX);
@ -329,10 +334,33 @@ ive to the origin at construction time");
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(95, 150, 314, 20, "Flex Parent:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)flex_size_group_cb);
o->align(Fl_Align(FL_ALIGN_LEFT));
{ widget_flex_size = new Fl_Value_Input(95, 150, 55, 20, "Size:");
widget_flex_size->tooltip("Fixed Width or Height for a horizontal or vertical Fl_Flex Parent.");
widget_flex_size->labelsize(11);
widget_flex_size->textsize(11);
widget_flex_size->callback((Fl_Callback*)flex_size_cb);
widget_flex_size->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* widget_flex_size
{ widget_flex_fixed = new Fl_Check_Button(155, 150, 55, 20, "fixed");
widget_flex_fixed->tooltip("If checked, the size of the widget stays fixed.");
widget_flex_fixed->down_box(FL_DOWN_BOX);
widget_flex_fixed->labelsize(11);
widget_flex_fixed->callback((Fl_Callback*)flex_fixed_cb);
} // Fl_Check_Button* widget_flex_fixed
{ Fl_Box* o = new Fl_Box(398, 150, 1, 20);
Fl_Group::current()->resizable(o);
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(95, 185, 300, 20, "Values:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)propagate_load);
o->callback((Fl_Callback*)values_group_cb);
o->align(Fl_Align(FL_ALIGN_LEFT));
{ Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Size:");
o->tooltip("The size of the slider.");
@ -375,10 +403,56 @@ ive to the origin at construction time");
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(95, 185, 300, 20, "Margins:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)flex_margin_group_cb);
o->align(Fl_Align(FL_ALIGN_LEFT));
o->hide();
{ Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Left:");
o->tooltip("Left margin in group.");
o->labelsize(11);
o->textsize(11);
o->callback((Fl_Callback*)flex_margin_left_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(155, 185, 55, 20, "Top:");
o->tooltip("Top margin in group.");
o->labelsize(11);
o->textsize(11);
o->callback((Fl_Callback*)flex_margin_top_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(215, 185, 55, 20, "Right:");
o->tooltip("Right margin in group.");
o->labelsize(11);
o->textsize(11);
o->callback((Fl_Callback*)flex_margin_right_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(275, 185, 55, 20, "Bottom:");
o->tooltip("Bottom margin in group.");
o->labelsize(11);
o->textsize(11);
o->callback((Fl_Callback*)flex_margin_bottom_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Value_Input* o = new Fl_Value_Input(335, 185, 55, 20, "Gap:");
o->tooltip("Gap between children.");
o->labelsize(11);
o->textsize(11);
o->callback((Fl_Callback*)flex_margin_gap_cb);
o->align(Fl_Align(FL_ALIGN_TOP_LEFT));
} // Fl_Value_Input* o
{ Fl_Box* o = new Fl_Box(395, 185, 0, 20);
Fl_Group::current()->resizable(o);
} // Fl_Box* o
o->end();
} // Fl_Group* o
{ Fl_Group* o = new Fl_Group(95, 185, 300, 20, "Size Range:");
o->labelfont(1);
o->labelsize(11);
o->callback((Fl_Callback*)propagate_load);
o->callback((Fl_Callback*)size_range_group_cb);
o->align(Fl_Align(FL_ALIGN_LEFT));
o->hide();
{ Fl_Value_Input* o = new Fl_Value_Input(95, 185, 55, 20, "Minimum Size:");

View File

@ -23,7 +23,7 @@ comment {//
decl {\#include "Fl_Widget_Type.h"} {private global
}
decl {\#include "Shortcut_Button.h"} {selected public global
decl {\#include "Shortcut_Button.h"} {public global
}
Function {make_widget_panel()} {
@ -31,8 +31,8 @@ Function {make_widget_panel()} {
} {
Fl_Window {} {
comment {Use a Double Window to avoid flickering.} open
xywh {500 209 420 400} type Double labelsize 11 align 80 hide resizable hotspot
code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0}
xywh {500 209 420 400} type Double labelsize 11 align 80 resizable hotspot
code0 {o->size_range(o->w(), o->h());} size_range {420 400 0 0} visible
} {
Fl_Tabs {} {
callback {propagate_load((Fl_Group *)o,v);} open
@ -258,8 +258,8 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 1 te
}
Fl_Group {} {
label {Position:}
callback propagate_load open
xywh {95 150 314 20} labelfont 1 labelsize 11 align 4
callback position_group_cb open
xywh {95 150 314 20} labelfont 1 labelsize 11 align 4 hide
} {
Fl_Input widget_x_input {
label {X:}
@ -294,9 +294,28 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 1 te
xywh {398 150 1 20} resizable
}
}
Fl_Group {} {
label {Flex Parent:}
callback flex_size_group_cb open
xywh {95 150 314 20} labelfont 1 labelsize 11 align 4
} {
Fl_Value_Input widget_flex_size {
label {Size:}
callback flex_size_cb
tooltip {Fixed Width or Height for a horizontal or vertical Fl_Flex Parent.} xywh {95 150 55 20} labelsize 11 align 5 textsize 11
}
Fl_Check_Button widget_flex_fixed {
label fixed
callback flex_fixed_cb selected
tooltip {If checked, the size of the widget stays fixed.} xywh {155 150 55 20} down_box DOWN_BOX labelsize 11
}
Fl_Box {} {
xywh {398 150 1 20} resizable
}
}
Fl_Group {} {
label {Values:}
callback propagate_load
callback values_group_cb open
xywh {95 185 300 20} labelfont 1 labelsize 11 align 4
} {
Fl_Value_Input {} {
@ -328,9 +347,43 @@ Use Ctrl-J for newlines.} xywh {95 40 190 20} labelfont 1 labelsize 11 when 1 te
xywh {395 185 0 20} resizable
}
}
Fl_Group {} {
label {Margins:}
callback flex_margin_group_cb open
xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide
} {
Fl_Value_Input {} {
label {Left:}
callback flex_margin_left_cb
tooltip {Left margin in group.} xywh {95 185 55 20} labelsize 11 align 5 textsize 11
}
Fl_Value_Input {} {
label {Top:}
callback flex_margin_top_cb
tooltip {Top margin in group.} xywh {155 185 55 20} labelsize 11 align 5 textsize 11
}
Fl_Value_Input {} {
label {Right:}
callback flex_margin_right_cb
tooltip {Right margin in group.} xywh {215 185 55 20} labelsize 11 align 5 textsize 11
}
Fl_Value_Input {} {
label {Bottom:}
callback flex_margin_bottom_cb
tooltip {Bottom margin in group.} xywh {275 185 55 20} labelsize 11 align 5 textsize 11
}
Fl_Value_Input {} {
label {Gap:}
callback flex_margin_gap_cb
tooltip {Gap between children.} xywh {335 185 55 20} labelsize 11 align 5 textsize 11
}
Fl_Box {} {
xywh {395 185 0 20} resizable
}
}
Fl_Group {} {
label {Size Range:}
callback propagate_load
callback size_range_group_cb open
xywh {95 185 300 20} labelfont 1 labelsize 11 align 4 hide
} {
Fl_Value_Input {} {

View File

@ -38,6 +38,7 @@ extern void align_cb(Fl_Button*, void*);
extern void align_text_image_cb(Fl_Choice*, void*);
extern void align_position_cb(Fl_Choice*, void*);
#include <FL/Fl_Box.H>
extern void position_group_cb(Fl_Group*, void*);
extern void x_cb(Fluid_Coord_Input*, void*);
extern Fluid_Coord_Input *widget_x_input;
extern void y_cb(Fluid_Coord_Input*, void*);
@ -48,12 +49,26 @@ extern void h_cb(Fluid_Coord_Input*, void*);
extern Fluid_Coord_Input *widget_h_input;
#include <FL/Fl_Light_Button.H>
extern void wc_relative_cb(Fl_Light_Button*, void*);
extern void flex_size_group_cb(Fl_Group*, void*);
#include <FL/Fl_Value_Input.H>
extern void flex_size_cb(Fl_Value_Input*, void*);
extern Fl_Value_Input *widget_flex_size;
#include <FL/Fl_Check_Button.H>
extern void flex_fixed_cb(Fl_Check_Button*, void*);
extern Fl_Check_Button *widget_flex_fixed;
extern void values_group_cb(Fl_Group*, void*);
extern void slider_size_cb(Fl_Value_Input*, void*);
extern void min_cb(Fl_Value_Input*, void*);
extern void max_cb(Fl_Value_Input*, void*);
extern void step_cb(Fl_Value_Input*, void*);
extern void value_cb(Fl_Value_Input*, void*);
extern void flex_margin_group_cb(Fl_Group*, void*);
extern void flex_margin_left_cb(Fl_Value_Input*, void*);
extern void flex_margin_top_cb(Fl_Value_Input*, void*);
extern void flex_margin_right_cb(Fl_Value_Input*, void*);
extern void flex_margin_bottom_cb(Fl_Value_Input*, void*);
extern void flex_margin_gap_cb(Fl_Value_Input*, void*);
extern void size_range_group_cb(Fl_Group*, void*);
extern void min_w_cb(Fl_Value_Input*, void*);
extern void min_h_cb(Fl_Value_Input*, void*);
extern void set_min_size_cb(Fl_Button*, void*);

View File

@ -236,41 +236,50 @@ void Fl_Flex::end() {
If \p size is 0 (zero) or negative the widget size is reset to flexible size.
\param[in] w widget to be affected
\param[in] child widget to be affected
\param[in] size width (Fl_Flex::HORIZONTAL) or height (Fl_Flex::VERTICAL)
*/
void Fl_Flex::set_size(Fl_Widget *w, int size) {
void Fl_Flex::set_size(Fl_Widget *child, int size) {
if (size <= 0)
size = 0;
w->resize(0, 0, size, size);
// find w in our fixed size list
int idx = -1;
for (int i = 0; i < set_size_size_; i++) {
if (set_size_[i] == w) {
if (set_size_[i] == child) {
idx = i;
break;
}
}
// remove from array ?
// remove from array, if we want the widget to be flexible, but an entry was found
if (size == 0 && idx >= 0) {
for (int i = idx; i < set_size_size_ - 2; i++) {
for (int i = idx; i < set_size_size_ - 1; i++) {
set_size_[i] = set_size_[i+1];
}
set_size_size_--;
return;
}
// if w is meant to be flexible, we are done now
if (size == 0)
return;
// add to array of fixed size widgets
if (set_size_size_ == set_size_alloc_) {
set_size_alloc_ = alloc_size(set_size_alloc_);
set_size_ = (Fl_Widget **)realloc(set_size_, set_size_alloc_ * sizeof(Fl_Widget *));
// if we have no entry yet, add to array of fixed size widgets
if (idx == -1) {
if (set_size_size_ == set_size_alloc_) {
set_size_alloc_ = alloc_size(set_size_alloc_);
set_size_ = (Fl_Widget **)realloc(set_size_, set_size_alloc_ * sizeof(Fl_Widget *));
}
set_size_[set_size_size_] = child;
set_size_size_++;
}
set_size_[set_size_size_] = w;
set_size_size_++;
// if the child size is meant to be fixed, set its new size
if (horizontal())
child->size(size, h()-margin_top_-margin_bottom_-Fl::box_dh(box()));
else
child->size(w()-margin_left_-margin_right_-Fl::box_dw(box()), size);
}
/**