diff options
| author | Matthias Melcher <github@matthiasm.com> | 2024-09-14 01:10:35 +0200 |
|---|---|---|
| committer | Matthias Melcher <github@matthiasm.com> | 2024-09-14 01:10:41 +0200 |
| commit | e7f1247552fbb9d056d4c68eb51564a504df3161 (patch) | |
| tree | cbaa15d7d58359d0fd59e86711881179ad34e134 /fluid | |
| parent | bb917628ffa8ffc6cafc79da80344c8c9c653969 (diff) | |
FLUID: type node placement in scene graph revised
- fixes copy/paste operation that would place pasted types wrong
- improves paste into folded and unfolded groups
- improves duplication of multiple types
- much improved placement of types that don;t fit at the
requested position
- some more testing will follow in the next days
Diffstat (limited to 'fluid')
| -rw-r--r-- | fluid/Fl_Function_Type.cxx | 88 | ||||
| -rw-r--r-- | fluid/Fl_Menu_Type.cxx | 21 | ||||
| -rw-r--r-- | fluid/Fl_Type.cxx | 278 | ||||
| -rw-r--r-- | fluid/Fl_Type.h | 12 | ||||
| -rw-r--r-- | fluid/Fl_Widget_Type.cxx | 23 | ||||
| -rw-r--r-- | fluid/Fl_Window_Type.cxx | 22 | ||||
| -rw-r--r-- | fluid/factory.cxx | 8 | ||||
| -rw-r--r-- | fluid/file.cxx | 14 | ||||
| -rw-r--r-- | fluid/fluid.cxx | 18 | ||||
| -rw-r--r-- | fluid/fluid.h | 2 | ||||
| -rw-r--r-- | fluid/widget_browser.cxx | 16 |
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; |
