summaryrefslogtreecommitdiff
path: root/fluid
diff options
context:
space:
mode:
Diffstat (limited to 'fluid')
-rw-r--r--fluid/Fl_Function_Type.cxx88
-rw-r--r--fluid/Fl_Menu_Type.cxx21
-rw-r--r--fluid/Fl_Type.cxx278
-rw-r--r--fluid/Fl_Type.h12
-rw-r--r--fluid/Fl_Widget_Type.cxx23
-rw-r--r--fluid/Fl_Window_Type.cxx22
-rw-r--r--fluid/factory.cxx8
-rw-r--r--fluid/file.cxx14
-rw-r--r--fluid/fluid.cxx18
-rw-r--r--fluid/fluid.h2
-rw-r--r--fluid/widget_browser.cxx16
11 files changed, 367 insertions, 135 deletions
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx
index 2f26a2a68..f490c9e11 100644
--- a/fluid/Fl_Function_Type.cxx
+++ b/fluid/Fl_Function_Type.cxx
@@ -206,12 +206,17 @@ Fl_Function_Type::~Fl_Function_Type() {
\return the new node
*/
Fl_Type *Fl_Function_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_decl_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Function_Type *o = new Fl_Function_Type();
o->name("make_window()");
o->return_type = 0;
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
o->public_ = 1;
o->cdecl_ = 0;
@@ -590,15 +595,20 @@ Fl_Code_Type::Fl_Code_Type() :
\return new Code node
*/
Fl_Type *Fl_Code_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_code_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_code_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
if (!p) {
fl_message("Please select a function");
return 0;
}
Fl_Code_Type *o = new Fl_Code_Type();
o->name("printf(\"Hello, World!\\n\");");
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -752,8 +762,13 @@ Fl_CodeBlock_Type::~Fl_CodeBlock_Type() {
\return new CodeBlock
*/
Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_code_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_code_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
if (!p) {
fl_message("Please select a function");
return 0;
@@ -761,7 +776,7 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
o->name("if (test())");
o->after = 0;
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -888,13 +903,18 @@ int Fl_Decl_Type::is_public() const
\return new Declaration node
*/
Fl_Type *Fl_Decl_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_decl_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Decl_Type *o = new Fl_Decl_Type();
o->public_ = 0;
o->static_ = 1;
o->name("int x;");
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -1110,15 +1130,20 @@ Fl_Data_Type::~Fl_Data_Type() {
\return new inline data node
*/
Fl_Type *Fl_Data_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_decl_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Data_Type *o = new Fl_Data_Type();
o->public_ = 1;
o->static_ = 1;
o->filename_ = 0;
o->text_mode_ = 0;
o->name("myInlineData");
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -1448,13 +1473,18 @@ int Fl_DeclBlock_Type::is_public() const {
\return new Declaration Block node
*/
Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_decl_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
o->name("#if 1");
o->write_map_ = CODE_IN_SOURCE;
o->after = fl_strdup("#endif");
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -1675,14 +1705,19 @@ Fl_Comment_Type::Fl_Comment_Type() :
\return new Comment node
*/
Fl_Type *Fl_Comment_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_code_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_code_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Comment_Type *o = new Fl_Comment_Type();
o->in_c_ = 1;
o->in_h_ = 1;
o->style_ = 0;
o->name("my comment");
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
@@ -1949,14 +1984,19 @@ void Fl_Class_Type::prefix(const char*p) {
\return new Class node
*/
Fl_Type *Fl_Class_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && !p->is_decl_block()) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !p->is_decl_block()) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Class_Type *o = new Fl_Class_Type();
o->name("UserInterface");
o->class_prefix = NULL;
o->subclass_of = NULL;
o->public_ = 1;
- o->add(p, strategy);
+ o->add(anchor, strategy);
o->factory = this;
return o;
}
diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx
index c03516bb8..23a7868fb 100644
--- a/fluid/Fl_Menu_Type.cxx
+++ b/fluid/Fl_Menu_Type.cxx
@@ -160,15 +160,16 @@ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) {
\return new Menu Item node
*/
Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) {
- // Find the current menu item:
- Fl_Type* q = Fl_Type::current;
- Fl_Type* p = q;
- if (p) {
- if ( (force_parent && q->is_a(ID_Menu_Item)) || !q->can_have_children()) p = p->parent;
- }
- force_parent = 0;
- if (!p || !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) {
- fl_message("Please select a menu to add to");
+ // Find a good insert position based on the current marked node
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
+ if (!p) {
+ fl_message("Please select a menu widget or a menu item");
return 0;
}
if (!o) {
@@ -184,7 +185,7 @@ Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) {
t->o = new Fl_Button(0,0,100,20);
t->o->type(flags);
t->factory = this;
- t->add(p, strategy);
+ t->add(anchor, strategy);
if (!reading_file) {
if (flags==FL_SUBMENU) {
t->label("submenu");
diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx
index c4127967b..5847fbddc 100644
--- a/fluid/Fl_Type.cxx
+++ b/fluid/Fl_Type.cxx
@@ -130,6 +130,143 @@ Fl_Type *in_this_only; // set if menu popped-up in window
// ---- various functions
+#if 0
+#ifndef NDEBUG
+/**
+ Print the current project tree to stderr.
+ */
+void print_project_tree() {
+ fprintf(stderr, "---- %s --->\n", g_project.projectfile_name().c_str());
+ for (Fl_Type *t = Fl_Type::first; t; t = t->next) {
+ for (int i = t->level; i > 0; i--)
+ fprintf(stderr, ". ");
+ fprintf(stderr, "%s\n", subclassname(t));
+ }
+}
+#endif
+
+#ifndef NDEBUG
+/**
+ Check the validity of the project tree.
+
+ Write problems with the project tree to stderr.
+
+ \return true if the project tree is valid
+ */
+bool validate_project_tree() {
+ // Validate `first` and `last`
+ if (Fl_Type::first == NULL) {
+ if (Fl_Type::last == NULL) {
+ return true;
+ } else {
+ fprintf(stderr, "ERROR: `first` is NULL, but `last` is not!\n");
+ return false;
+ }
+ }
+ if (Fl_Type::last == NULL) {
+ fprintf(stderr, "ERROR: `last` is NULL, but `first` is not!\n");
+ return false;
+ }
+ // Validate the branch linkage, parent links, etc.
+ return validate_branch(Fl_Type::first);
+}
+#endif
+
+#ifndef NDEBUG
+/**
+ Check the validity of a Type branch that is not connected to the project.
+
+ Write problems with the branch to stderr.
+
+ \param[in] root the first node in a branch
+ \return true if the branch is correctly separated and valid
+ */
+bool validate_independent_branch(class Fl_Type *root) {
+ // Make sure that `first` and `last` do not point at any node in this branch
+ if (Fl_Type::first) {
+ for (Fl_Type *t = root; t; t = t->next) {
+ if (Fl_Type::first == t) {
+ fprintf(stderr, "ERROR: Branch is not independent, `first` is pointing to branch member!\n");
+ return false;
+ }
+ }
+ }
+ if (Fl_Type::last) {
+ for (Fl_Type *t = root; t; t = t->next) {
+ if (Fl_Type::last == t) {
+ fprintf(stderr, "ERROR: Branch is not independent, `last` is pointing to branch member!\n");
+ return false;
+ }
+ }
+ }
+ // Validate the branch linkage, parent links, etc.
+ return validate_branch(root);
+}
+#endif
+
+#ifndef NDEBUG
+/**
+ Check the validity of a Type branch.
+
+ Write problems with the branch to stderr.
+
+ \param[in] root the first node in a branch
+ \return true if the branch is valid
+ */
+bool validate_branch(class Fl_Type *root) {
+ // Only check real branches
+ if (!root) {
+ fprintf(stderr, "WARNING: Branch is empty!\n");
+ return false;
+ }
+ // Check relation between this and next node
+ for (Fl_Type *t = root; t; t = t->next) {
+ if (t->level < root->level) {
+ fprintf(stderr, "ERROR: Node in tree is above root level!\n");
+ return false;
+ }
+ if (t->next) {
+ // Make sure that all `next` types have the `prev` member link back
+ if (t->next->prev != t) {
+ fprintf(stderr, "ERROR: Doubly linked list broken!\n");
+ return false;
+ }
+ if (t->next->level > t->level) {
+ // Validate `level` changes
+ if (t->next->level - t->level > 1) {
+ fprintf(stderr, "ERROR: Child level increment greater than one!\n");
+ return false;
+ }
+ // Ensure that this node can actually have children
+ if (!t->can_have_children()) {
+ fprintf(stderr, "ERROR: This parent must not have children!\n");
+ return false;
+ }
+ }
+ }
+ // Validate the `parent` entry
+ for (Fl_Type *p = t->prev; ; p = p->prev) {
+ if (p == NULL) {
+ if (t->parent != NULL) {
+ fprintf(stderr, "ERROR: `parent` pointer should be NULL!\n");
+ return false;
+ }
+ break;
+ }
+ if (p->level < t->level) {
+ if (t->parent != p) {
+ fprintf(stderr, "ERROR: `parent` points to wrong parent!\n");
+ return false;
+ }
+ break;
+ }
+ }
+ }
+ return true;
+}
+#endif
+#endif
+
void select_all_cb(Fl_Widget *,void *) {
Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
if (in_this_only) {
@@ -317,7 +454,7 @@ int storestring(const char *n, const char * & p, int nostrip) {
void update_visibility_flag(Fl_Type *p) {
Fl_Type *t = p;
for (;;) {
- if (t->parent) t->visible = t->parent->visible && t->parent->open_;
+ if (t->parent) t->visible = t->parent->visible && !t->parent->folded_;
else t->visible = 1;
t = t->next;
if (!t || t->level <= p->level) break;
@@ -470,42 +607,85 @@ Fl_Group_Type *Fl_Type::group() {
\param[in] p insert \c this tree as a child of \c p
\param[in] strategy is kAddAsLastChild or kAddAfterCurrent
*/
-void Fl_Type::add(Fl_Type *p, Strategy strategy) {
- if (p && parent == p) return;
- undo_checkpoint();
- parent = p;
- // 'this' is not in the Widget_Browser, so we must run the linked list to find the last entry
+void Fl_Type::add(Fl_Type *anchor, Strategy strategy) {
+#if 0
+#ifndef NDEBUG
+ // print_project_tree();
+ // fprintf(stderr, "Validating project\n");
+ validate_project_tree();
+ // fprintf(stderr, "Validating branch\n");
+ validate_independent_branch(this);
+#endif
+#endif
+
+ Fl_Type *target = NULL; // insert self before target node, if NULL, insert last
+ Fl_Type *target_parent = NULL; // this will be the new parent for branch
+ int target_level = 0; // adjust self to this new level
+
+ // Find the node after our insertion position
+ switch (strategy) {
+ case kAddAsFirstChild:
+ if (anchor == NULL) {
+ target = Fl_Type::first;
+ } else {
+ target = anchor->next;
+ target_level = anchor->level + 1;
+ target_parent = anchor;
+ }
+ break;
+ case kAddAsLastChild:
+ if (anchor == NULL) {
+ /* empty */
+ } else {
+ for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/}
+ target_level = anchor->level + 1;
+ target_parent = anchor;
+ }
+ break;
+ case kAddAfterCurrent:
+ if (anchor == NULL) {
+ target = Fl_Type::first;
+ } else {
+ for (target = anchor->next; target && target->level > anchor->level; target = target->next) {/*empty*/}
+ target_level = anchor->level;
+ target_parent = anchor->parent;
+ }
+ break;
+ }
+
+
+ // Find the last node of our tree
Fl_Type *end = this;
while (end->next) end = end->next;
- // run the list again to set the future node levels
- Fl_Type *q; // insert 'this' before q
- int newlevel;
- if (p) {
- // find the last node that is a child or grandchild of p
- for (q = p->next; q && q->level > p->level; q = q->next) {/*empty*/}
- newlevel = p->level+1;
+
+ // Everything is prepared, now insert ourself in front of the target node
+ undo_checkpoint();
+
+ // Walk the tree to update parent pointers and levels
+ int source_level = level;
+ for (Fl_Type *t = this; t; t = t->next) {
+ t->level += (target_level-source_level);
+ if (t->level == target_level)
+ t->parent = target_parent;
+ }
+
+ // Now link ourselves and our children before 'target', or last, if 'target' is NULL
+ if (target) {
+ prev = target->prev;
+ target->prev = end;
+ end->next = target;
} else {
- q = 0;
- newlevel = 0;
+ prev = Fl_Type::last;
+ end->next = NULL;
+ Fl_Type::last = end;
}
- for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
- level = newlevel;
- // now link 'this' and its children before 'q', or last, if 'q' is NULL
- if (q) {
- prev = q->prev;
- prev->next = this;
- q->prev = end;
- end->next = q;
- } else if (first) {
- prev = last;
+ if (prev) {
prev->next = this;
- end->next = 0;
- last = end;
} else {
- first = this;
- last = end;
- prev = end->next = 0;
+ Fl_Type::first = this;
}
+
+#if 0
{ // make sure that we have no duplicate uid's
Fl_Type *tp = this;
do {
@@ -513,28 +693,24 @@ void Fl_Type::add(Fl_Type *p, Strategy strategy) {
tp = tp->next;
} while (tp!=end && tp!=NULL);
}
+#endif
- // tell this that it was added, so it can update itself
- if (p) p->add_child(this,0);
- open_ = 1;
- update_visibility_flag(this);
- set_modflag(1);
-
- if (strategy==kAddAfterCurrent && current) {
- // we have current, t is the new node, p is the parent
- // find the next child of the parent after current
- //t->add(p); // add as a last child
- Fl_Type *cc;
- for (cc = current->next; cc; cc = cc->next) {
- if (cc->level <= this->level)
- break;
- }
- if (cc && cc->level==this->level && cc!=this) {
- this->move_before(cc);
- }
- select(this, 1);
+ // Give the widgets in our tree a chance to update themselves
+ for (Fl_Type *t = this; t && t!=end->next; t = t->next) {
+ if (target_parent && (t->level == target_level))
+ target_parent->add_child(t, 0);
+ update_visibility_flag(t);
}
+
+ set_modflag(1);
widget_browser->redraw();
+
+#if 0
+#ifndef NDEBUG
+ // fprintf(stderr, "Validating project after adding branch\n");
+ validate_project_tree();
+#endif
+#endif
}
/**
@@ -757,7 +933,7 @@ void Fl_Type::write_properties(Fd_Project_Writer &f) {
f.write_word("comment");
f.write_word(comment());
}
- if (can_have_children() && open_) f.write_word("open");
+ if (can_have_children() && !folded_) f.write_word("open");
if (selected) f.write_word("selected");
}
@@ -779,7 +955,7 @@ void Fl_Type::read_property(Fd_Project_Reader &f, const char *c) {
else if (!strcmp(c,"comment"))
comment(f.read_word());
else if (!strcmp(c,"open"))
- open_ = 1;
+ folded_ = 0;
else if (!strcmp(c,"selected"))
select(this,1);
else if (!strcmp(c,"parent_properties"))
diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h
index 8d9588e13..be5e5f1a6 100644
--- a/fluid/Fl_Type.h
+++ b/fluid/Fl_Type.h
@@ -46,7 +46,8 @@ class Fd_Project_Writer;
int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy)
*/
typedef enum {
- kAddAsLastChild = 0,
+ kAddAsFirstChild = 0,
+ kAddAsLastChild,
kAddAfterCurrent
} Strategy;
@@ -92,6 +93,13 @@ void select_none_cb(Fl_Widget *,void *);
void earlier_cb(Fl_Widget*,void*);
void later_cb(Fl_Widget*,void*);
+#ifndef NDEBUG
+void print_project_tree();
+bool validate_project_tree();
+bool validate_independent_branch(class Fl_Type *root);
+bool validate_branch(class Fl_Type *root);
+#endif
+
/**
\brief This is the base class for all elements in the project tree.
@@ -150,7 +158,7 @@ public: // things that should not be public:
(see `haderror`). It seems that this is often confused with new_selected
which seems to hold the true and visible selection state. */
char selected; // copied here by selection_changed()
- char open_; // state of triangle in browser
+ char folded_; // if set, children are not shown in browser
char visible; // true if all parents are open
int level; // number of parents over this
static Fl_Type *first, *last;
diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx
index da80add7e..44b470102 100644
--- a/fluid/Fl_Widget_Type.cxx
+++ b/fluid/Fl_Widget_Type.cxx
@@ -87,19 +87,20 @@ Fl_Widget_Type::ideal_size(int &w, int &h) {
\return new node
*/
Fl_Type *Fl_Widget_Type::make(Strategy strategy) {
- // Find the current widget, or widget to copy:
- Fl_Type *qq = Fl_Type::current;
- while (qq && (!qq->is_true_widget() || !qq->can_have_children())) qq = qq->parent;
- if (!qq) {
+ Fl_Type *anchor = Fl_Type::current, *pp = anchor;
+ if (pp && (strategy == kAddAfterCurrent)) pp = pp->parent;
+ while (pp && !pp->is_a(ID_Group)) {
+ anchor = pp;
+ strategy = kAddAfterCurrent;
+ pp = pp->parent;
+ }
+ if (!pp || !pp->is_true_widget() || !anchor->is_true_widget()) {
fl_message("Please select a group widget or window");
return 0;
}
- Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
- // find the parent widget:
- Fl_Widget_Type* p = q;
- if ((force_parent || !p->is_a(ID_Group)) && p->parent && p->parent->is_widget())
- p = (Fl_Widget_Type*)(p->parent);
- force_parent = 0;
+
+ Fl_Widget_Type* p = (Fl_Widget_Type*)pp;
+ Fl_Widget_Type* q = (Fl_Widget_Type*)anchor;
// Figure out a border between widget and window:
int B = p->o->w()/2; if (p->o->h()/2 < B) B = p->o->h()/2; if (B>25) B = 25;
@@ -146,7 +147,7 @@ Fl_Type *Fl_Widget_Type::make(Strategy strategy) {
// Put it in the parent:
// ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add())
// add to browser:
- t->add(p, strategy);
+ t->add(anchor, strategy);
t->redraw();
return t;
}
diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx
index 4b4944d8e..55f66e6cf 100644
--- a/fluid/Fl_Window_Type.cxx
+++ b/fluid/Fl_Window_Type.cxx
@@ -227,8 +227,13 @@ int Overlay_Window::handle(int e) {
\return new node
*/
Fl_Type *Fl_Window_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && (!p->is_code_block() || p->is_a(ID_Widget_Class))) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && (!p->is_code_block() || p->is_a(ID_Widget_Class))) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
if (!p) {
fl_message("Please select a function");
return 0;
@@ -245,7 +250,7 @@ Fl_Type *Fl_Window_Type::make(Strategy strategy) {
w->size_range(10, 10);
w->window = myo;
myo->o = w;
- myo->add(p, strategy);
+ myo->add(anchor, strategy);
myo->modal = 0;
myo->non_modal = 0;
return myo;
@@ -1363,8 +1368,13 @@ Fl_Widget_Class_Type *current_widget_class = 0;
\return new node
*/
Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
- Fl_Type *p = Fl_Type::current;
- while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) p = p->parent;
+ Fl_Type *anchor = Fl_Type::current, *p = anchor;
+ if (p && (strategy == kAddAfterCurrent)) p = p->parent;
+ while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) {
+ anchor = p;
+ strategy = kAddAfterCurrent;
+ p = p->parent;
+ }
Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type();
myo->name("UserInterface");
@@ -1379,7 +1389,7 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
w->size_range(10, 10);
w->window = myo;
myo->o = w;
- myo->add(p, strategy);
+ myo->add(anchor, strategy);
myo->modal = 0;
myo->non_modal = 0;
myo->wc_relative = 0;
diff --git a/fluid/factory.cxx b/fluid/factory.cxx
index a4072967f..56077020c 100644
--- a/fluid/factory.cxx
+++ b/fluid/factory.cxx
@@ -1342,11 +1342,11 @@ Fl_Type *add_new_widget_from_user(const char *inName, Strategy strategy, bool an
}
/**
- Callback for all menu items.
+ Callback for all non-widget menu items.
*/
static void cbf(Fl_Widget *, void *v) {
Fl_Type *t = NULL;
- if (Fl_Type::current && Fl_Type::current->is_a(ID_Group))
+ if (Fl_Type::current && Fl_Type::current->can_have_children())
t = ((Fl_Type*)v)->make(kAddAsLastChild);
else
t = ((Fl_Type*)v)->make(kAddAfterCurrent);
@@ -1354,11 +1354,11 @@ static void cbf(Fl_Widget *, void *v) {
}
/**
- Callback for all menu items.
+ Callback for all widget menu items.
*/
static void cb(Fl_Widget *, void *v) {
Fl_Type *t = NULL;
- if (Fl_Type::current && Fl_Type::current->is_a(ID_Group))
+ if (Fl_Type::current && Fl_Type::current->can_have_children())
t = add_new_widget_from_user((Fl_Type*)v, kAddAsLastChild);
else
t = add_new_widget_from_user((Fl_Type*)v, kAddAfterCurrent);
diff --git a/fluid/file.cxx b/fluid/file.cxx
index 653746130..73b51f52c 100644
--- a/fluid/file.cxx
+++ b/fluid/file.cxx
@@ -227,6 +227,7 @@ int Fd_Project_Reader::read_quoted() { // read whatever character is after
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;
+ Fl_Type *t = NULL;
for (;;) {
const char *c = read_word();
REUSE_C:
@@ -354,7 +355,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate
}
}
{
- Fl_Type *t = add_new_widget_from_file(c, strategy);
+ t = add_new_widget_from_file(c, strategy);
if (!t) {
read_error("Unknown word \"%s\"", c);
continue;
@@ -377,7 +378,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate
goto REUSE_C;
}
- t->open_ = 0;
+ t->folded_ = 1;
for (;;) {
const char *cc = read_word();
if (!cc || !strcmp(cc,"}")) break;
@@ -390,7 +391,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate
read_error("Missing child list for %s\n",t->title());
goto REUSE_C;
}
- read_children(t, 0, strategy, skip_options);
+ read_children(t, 0, kAddAsLastChild, skip_options);
t->postprocess_read();
// FIXME: this has no business in the file reader!
// TODO: this is called whenever something is pasted from the top level into a grid
@@ -405,8 +406,11 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate
t->layout_widget();
}
-
- Fl_Type::current = p;
+ if (strategy == kAddAfterCurrent) {
+ Fl_Type::current = t;
+ } else {
+ Fl_Type::current = p;
+ }
CONTINUE:;
}
diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx
index ffd2edfee..e690c5f7e 100644
--- a/fluid/fluid.cxx
+++ b/fluid/fluid.cxx
@@ -106,11 +106,6 @@ int G_debug = 0;
char G_external_editor_command[512];
-/// If set, if the `current` node is a group, and a new group is added, it will
-/// be added as sibling to the first group instead of inside the group.
-/// \todo Needs to be verified.
-int force_parent = 0;
-
/// This is set to create different labels when creating new widgets.
/// \todo Details unclear.
int reading_file = 0;
@@ -1411,13 +1406,16 @@ void delete_cb(Fl_Widget *, void *) {
User chose to paste the widgets from the cut buffer.
*/
void paste_cb(Fl_Widget*, void*) {
- //if (ipasteoffset) force_parent = 1;
pasteoffset = ipasteoffset;
undo_checkpoint();
undo_suspend();
Strategy strategy = kAddAfterCurrent;
- if (Fl_Type::current && Fl_Type::current->is_a(ID_Group))
- strategy = kAddAsLastChild;
+ if (Fl_Type::current && Fl_Type::current->is_a(ID_Group)) {
+ Fl_Group_Type *current_group = static_cast<Fl_Group_Type*>(Fl_Type::current);
+ if (current_group->folded_ == 0) {
+ strategy = kAddAsLastChild;
+ }
+ }
if (!read_file(cutfname(), 1, strategy)) {
widget_browser->rebuild();
fl_message("Can't read %s: %s", cutfname(), strerror(errno));
@@ -1427,7 +1425,6 @@ void paste_cb(Fl_Widget*, void*) {
widget_browser->rebuild();
pasteoffset = 0;
ipasteoffset += 10;
- force_parent = 0;
}
/**
@@ -1447,7 +1444,6 @@ void duplicate_cb(Fl_Widget*, void*) {
}
pasteoffset = 0;
- force_parent = 1;
undo_checkpoint();
undo_suspend();
@@ -1458,8 +1454,6 @@ void duplicate_cb(Fl_Widget*, void*) {
widget_browser->display(Fl_Type::current);
widget_browser->rebuild();
undo_resume();
-
- force_parent = 0;
}
/**
diff --git a/fluid/fluid.h b/fluid/fluid.h
index 95f4dc4dd..2f92a6e11 100644
--- a/fluid/fluid.h
+++ b/fluid/fluid.h
@@ -51,8 +51,6 @@ typedef enum {
// ---- global variables
-extern int force_parent;
-
extern Fl_Preferences fluid_prefs;
extern Fl_Menu_Item Main_Menu[];
extern Fl_Menu_Bar *main_menubar;
diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx
index 6fd33cd62..1540c6d75 100644
--- a/fluid/widget_browser.cxx
+++ b/fluid/widget_browser.cxx
@@ -120,8 +120,8 @@ void reveal_in_browser(Fl_Type *t) {
Fl_Type *p = t->parent;
if (p) {
for (;;) {
- if (!p->open_)
- p->open_ = 1;
+ if (p->folded_)
+ p->folded_ = 0;
if (!p->parent) break;
p = p->parent;
}
@@ -340,7 +340,7 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
if (l->can_have_children()) {
X = X - 18 - 13;
if (!l->next || l->next->level <= l->level) {
- if (l->open_!=(l==pushedtitle)) {
+ if (l->folded_==(l==pushedtitle)) {
// an outlined triangle to the right indicates closed item, no children
fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
} else {
@@ -348,7 +348,7 @@ void Widget_Browser::item_draw(void *v, int X, int Y, int, int) const {
fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
}
} else {
- if (l->open_!=(l==pushedtitle)) {
+ if (l->folded_==(l==pushedtitle)) {
// a filled triangle to the right indicates closed item, with children
fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
} else {
@@ -538,15 +538,15 @@ int Widget_Browser::handle(int e) {
l = pushedtitle;
title = pushedtitle = 0;
if (l) {
- if (l->open_) {
- l->open_ = 0;
+ if (!l->folded_) {
+ l->folded_ = 1;
for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
k->visible = 0;
} else {
- l->open_ = 1;
+ l->folded_ = 0;
for (Fl_Type*k=l->next; k&&k->level>l->level;) {
k->visible = 1;
- if (k->can_have_children() && !k->open_) {
+ if (k->can_have_children() && k->folded_) {
Fl_Type *j;
for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/}
k = j;