FLUID: Fixes issues when pasting widget into Fl_Flex #809

* new virtual function layout_widget() to inform parents after
all children were added
This commit is contained in:
Matthias Melcher 2023-10-27 18:31:14 +02:00
parent aab6afd32c
commit 4b5985eb49
9 changed files with 59 additions and 43 deletions

View File

@ -48,15 +48,6 @@ void igroup::resize(int X, int Y, int W, int H) {
redraw();
}
/**
Create and add a new Group node.
\param[in] strategy add after current or as last child
\return new Group node
*/
Fl_Type *Fl_Group_Type::make(Strategy strategy) {
return Fl_Widget_Type::make(strategy);
}
/**
\brief Enlarge the group size, so all children fit within.
*/
@ -102,6 +93,7 @@ void group_cb(Fl_Widget *, void *) {
t = nxt;
}
fix_group_size(n);
n->layout_widget();
widget_browser->rebuild();
undo_resume();
set_modflag(1);
@ -241,7 +233,6 @@ 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());
propagate_live_mode(grp);
suspend_auto_layout = 0;
Fl_Flex *d = grp, *s =(Fl_Flex*)o;
int nc = s->children(), nd = d->children();
if (nc>nd) nc = nd;
@ -320,20 +311,20 @@ void Fl_Flex_Type::read_property(Fd_Project_Reader &f, const char *c)
void Fl_Flex_Type::postprocess_read()
{
if (fixedSizeTupleSize==0) return;
Fl_Flex* flex = (Fl_Flex*)o;
for (int i=0; i<fixedSizeTupleSize; i++) {
int ix = fixedSizeTuple[2*i];
int size = fixedSizeTuple[2*i+1];
if (ix>=0 && ix<flex->children()) {
Fl_Widget *ci = flex->child(ix);
flex->fixed(ci, size);
if (fixedSizeTupleSize>0) {
for (int i=0; i<fixedSizeTupleSize; i++) {
int ix = fixedSizeTuple[2*i];
int size = fixedSizeTuple[2*i+1];
if (ix>=0 && ix<flex->children()) {
Fl_Widget *ci = flex->child(ix);
flex->fixed(ci, size);
}
}
fixedSizeTupleSize = 0;
delete[] fixedSizeTuple;
fixedSizeTuple = NULL;
}
fixedSizeTupleSize = 0;
delete[] fixedSizeTuple;
fixedSizeTuple = NULL;
flex->layout();
suspend_auto_layout = 0;
}
@ -355,22 +346,27 @@ void Fl_Flex_Type::write_code2(Fd_Code_Writer& f) {
Fl_Group_Type::write_code2(f);
}
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::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)->fixed(((Fl_Widget_Type*)a)->o, 0);
Fl_Group_Type::remove_child(a);
// ((Fl_Flex*)o)->layout();
layout_widget();
}
void Fl_Flex_Type::layout_widget() {
((Fl_Flex*)o)->layout();
}

View File

@ -46,7 +46,6 @@ public:
Fl_Widget *widget(int X,int Y,int W,int H) FL_OVERRIDE {
igroup *g = new igroup(X,Y,W,H); Fl_Group::current(0); return g;}
Fl_Widget_Type *_make() FL_OVERRIDE {return new Fl_Group_Type();}
Fl_Type *make(Strategy strategy) FL_OVERRIDE;
void write_code1(Fd_Code_Writer& f) FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
@ -106,9 +105,10 @@ public:
void copy_properties() FL_OVERRIDE;
void postprocess_read() FL_OVERRIDE;
void write_code2(Fd_Code_Writer& f) FL_OVERRIDE;
void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
// void add_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
// void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
void remove_child(Fl_Type*) FL_OVERRIDE;
void layout_widget() FL_OVERRIDE;
void change_subtype_to(int n);
static int parent_is_flex(Fl_Type*);
static int size(Fl_Type*, char fixed_only=0);

View File

@ -190,6 +190,7 @@ void earlier_cb(Fl_Widget*,void*) {
if (g && g->level == f->level && !g->selected) {
if (!mod) undo_checkpoint();
f->move_before(g);
if (f->parent) f->parent->layout_widget();
mod = 1;
}
}
@ -214,6 +215,7 @@ void later_cb(Fl_Widget*,void*) {
if (g && g->level == f->level && !g->selected) {
if (!mod) undo_checkpoint();
g->move_before(f);
if (f->parent) f->parent->layout_widget();
mod = 1;
}
}

View File

@ -195,6 +195,13 @@ public:
virtual void move_child(Fl_Type*, Fl_Type* beforethis) { }
virtual void remove_child(Fl_Type*) { }
/** Give widgets a change to arrange their children after all children were add.
If adding individual children, this is called immediately, but if children
are read via a project file, we wait until all children are read and then
lay out the group.
*/
virtual void layout_widget() { }
static Fl_Type *current; // most recently picked object
static Fl_Type *current_dnd;

View File

@ -268,6 +268,7 @@ Fl_Type *sort(Fl_Type *parent) {
}
if (g != f) f->move_before(g);
}
parent->layout_widget();
}
////////////////////////////////////////////////////////////////

View File

@ -147,7 +147,7 @@ script_input->linenumber_size(script_input->Fl_Text_Display::textsize());} {uid
}
}
Function {make_settings_window()} {uid 40199 open
Function {make_settings_window()} {uid 40199 open selected
} {
Fl_Window settings_window {uid 25753
label {FLUID Settings} open
@ -219,7 +219,7 @@ fluid_prefs.set("show_tooltips", tooltips_button->value());}
label {Show Comments in Browser}
callback {show_comments = show_comments_button->value();
fluid_prefs.set("show_comments", show_comments);
redraw_browser();} selected
redraw_browser();}
xywh {120 195 200 20} down_box DOWN_BOX labelsize 11
code1 {fluid_prefs.get("show_comments", show_comments, 1);}
code2 {show_comments_button->value(show_comments);}

View File

@ -1195,7 +1195,7 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) {
wt->ideal_size(w, h);
if ((t->parent && t->parent->is_a(ID_Flex))) {
// Do not resize or layout the widget. Flex will need the widget size.
t->parent->layout_widget();
} else if ( wt->is_a(ID_Group)
&& wt->parent
&& wt->parent->is_a(ID_Tabs)

View File

@ -217,18 +217,21 @@ int Fd_Project_Reader::read_quoted() { // read whatever character is after
If this is the first call, also read the global settings for this design.
\param[in] p parent node or NULL
\param[in] paste if set, merge into existing design, else replace design
\param[in] merge if set, merge into existing design, else replace design
\param[in] strategy add nodes after current or as last child
\param[in] skip_options this is set if the options were already found in
a previous call, and there is no need to waste time searching for them.
\return the last type that was created
*/
void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options) {
Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) {
Fl_Type::current = p;
Fl_Type *last_child_read = NULL;
for (;;) {
const char *c = read_word();
REUSE_C:
if (!c) {
if (p && !paste) read_error("Missing '}'");
if (p && !merge)
read_error("Missing '}'");
break;
}
@ -258,7 +261,7 @@ void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy,
Fl_Type *t = add_new_widget_from_file("class", kAddAsLastChild);
t->name(read_word());
Fl_Type::current = p = t;
paste = 1; // stops "missing }" error
merge = 1; // stops "missing }" error
continue;
}
@ -355,6 +358,7 @@ void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy,
read_error("Unknown word \"%s\"", c);
continue;
}
last_child_read = t;
// After reading the first widget, we no longer need to look for options
skip_options = 1;
@ -387,12 +391,18 @@ void Fd_Project_Reader::read_children(Fl_Type *p, int paste, Strategy strategy,
}
read_children(t, 0, strategy, skip_options);
t->postprocess_read();
t->layout_widget();
}
Fl_Type::current = p;
CONTINUE:;
}
if (merge && last_child_read && last_child_read->parent) {
last_child_read->parent->postprocess_read();
last_child_read->parent->layout_widget();
}
return last_child_read;
}
/** \brief Read a .fl project file.

View File

@ -55,7 +55,7 @@ public:
int close_read();
const char *filename_name();
int read_quoted();
void read_children(Fl_Type *p, int paste, Strategy strategy, char skip_options=0);
Fl_Type *read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options=0);
int read_project(const char *, int merge, Strategy strategy=kAddAsLastChild);
void read_error(const char *format, ...);
const char *read_word(int wantbrace = 0);