mirror of https://github.com/fltk/fltk
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
This commit is contained in:
parent
bb917628ff
commit
e7f1247552
|
@ -206,12 +206,17 @@ Fl_Function_Type::~Fl_Function_Type() {
|
||||||
\return the new node
|
\return the new node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Function_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Function_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_decl_block()) p = p->parent;
|
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();
|
Fl_Function_Type *o = new Fl_Function_Type();
|
||||||
o->name("make_window()");
|
o->name("make_window()");
|
||||||
o->return_type = 0;
|
o->return_type = 0;
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
o->public_ = 1;
|
o->public_ = 1;
|
||||||
o->cdecl_ = 0;
|
o->cdecl_ = 0;
|
||||||
|
@ -590,15 +595,20 @@ Fl_Code_Type::Fl_Code_Type() :
|
||||||
\return new Code node
|
\return new Code node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Code_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Code_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_code_block()) p = p->parent;
|
if (p && (strategy == kAddAfterCurrent)) p = p->parent;
|
||||||
|
while (p && !p->is_code_block()) {
|
||||||
|
anchor = p;
|
||||||
|
strategy = kAddAfterCurrent;
|
||||||
|
p = p->parent;
|
||||||
|
}
|
||||||
if (!p) {
|
if (!p) {
|
||||||
fl_message("Please select a function");
|
fl_message("Please select a function");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Fl_Code_Type *o = new Fl_Code_Type();
|
Fl_Code_Type *o = new Fl_Code_Type();
|
||||||
o->name("printf(\"Hello, World!\\n\");");
|
o->name("printf(\"Hello, World!\\n\");");
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -752,8 +762,13 @@ Fl_CodeBlock_Type::~Fl_CodeBlock_Type() {
|
||||||
\return new CodeBlock
|
\return new CodeBlock
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
|
Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_code_block()) p = p->parent;
|
if (p && (strategy == kAddAfterCurrent)) p = p->parent;
|
||||||
|
while (p && !p->is_code_block()) {
|
||||||
|
anchor = p;
|
||||||
|
strategy = kAddAfterCurrent;
|
||||||
|
p = p->parent;
|
||||||
|
}
|
||||||
if (!p) {
|
if (!p) {
|
||||||
fl_message("Please select a function");
|
fl_message("Please select a function");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -761,7 +776,7 @@ Fl_Type *Fl_CodeBlock_Type::make(Strategy strategy) {
|
||||||
Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
|
Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type();
|
||||||
o->name("if (test())");
|
o->name("if (test())");
|
||||||
o->after = 0;
|
o->after = 0;
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -888,13 +903,18 @@ int Fl_Decl_Type::is_public() const
|
||||||
\return new Declaration node
|
\return new Declaration node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Decl_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Decl_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_decl_block()) p = p->parent;
|
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();
|
Fl_Decl_Type *o = new Fl_Decl_Type();
|
||||||
o->public_ = 0;
|
o->public_ = 0;
|
||||||
o->static_ = 1;
|
o->static_ = 1;
|
||||||
o->name("int x;");
|
o->name("int x;");
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -1110,15 +1130,20 @@ Fl_Data_Type::~Fl_Data_Type() {
|
||||||
\return new inline data node
|
\return new inline data node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Data_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Data_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_decl_block()) p = p->parent;
|
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();
|
Fl_Data_Type *o = new Fl_Data_Type();
|
||||||
o->public_ = 1;
|
o->public_ = 1;
|
||||||
o->static_ = 1;
|
o->static_ = 1;
|
||||||
o->filename_ = 0;
|
o->filename_ = 0;
|
||||||
o->text_mode_ = 0;
|
o->text_mode_ = 0;
|
||||||
o->name("myInlineData");
|
o->name("myInlineData");
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -1448,13 +1473,18 @@ int Fl_DeclBlock_Type::is_public() const {
|
||||||
\return new Declaration Block node
|
\return new Declaration Block node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) {
|
Fl_Type *Fl_DeclBlock_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_decl_block()) p = p->parent;
|
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();
|
Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type();
|
||||||
o->name("#if 1");
|
o->name("#if 1");
|
||||||
o->write_map_ = CODE_IN_SOURCE;
|
o->write_map_ = CODE_IN_SOURCE;
|
||||||
o->after = fl_strdup("#endif");
|
o->after = fl_strdup("#endif");
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -1675,14 +1705,19 @@ Fl_Comment_Type::Fl_Comment_Type() :
|
||||||
\return new Comment node
|
\return new Comment node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Comment_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Comment_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_code_block()) p = p->parent;
|
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();
|
Fl_Comment_Type *o = new Fl_Comment_Type();
|
||||||
o->in_c_ = 1;
|
o->in_c_ = 1;
|
||||||
o->in_h_ = 1;
|
o->in_h_ = 1;
|
||||||
o->style_ = 0;
|
o->style_ = 0;
|
||||||
o->name("my comment");
|
o->name("my comment");
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
@ -1949,14 +1984,19 @@ void Fl_Class_Type::prefix(const char*p) {
|
||||||
\return new Class node
|
\return new Class node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Class_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Class_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && !p->is_decl_block()) p = p->parent;
|
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();
|
Fl_Class_Type *o = new Fl_Class_Type();
|
||||||
o->name("UserInterface");
|
o->name("UserInterface");
|
||||||
o->class_prefix = NULL;
|
o->class_prefix = NULL;
|
||||||
o->subclass_of = NULL;
|
o->subclass_of = NULL;
|
||||||
o->public_ = 1;
|
o->public_ = 1;
|
||||||
o->add(p, strategy);
|
o->add(anchor, strategy);
|
||||||
o->factory = this;
|
o->factory = this;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,15 +160,16 @@ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) {
|
||||||
\return new Menu Item node
|
\return new Menu Item node
|
||||||
*/
|
*/
|
||||||
Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) {
|
Fl_Type* Fl_Menu_Item_Type::make(int flags, Strategy strategy) {
|
||||||
// Find the current menu item:
|
// Find a good insert position based on the current marked node
|
||||||
Fl_Type* q = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
Fl_Type* p = q;
|
if (p && (strategy == kAddAfterCurrent)) p = p->parent;
|
||||||
if (p) {
|
while (p && !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) {
|
||||||
if ( (force_parent && q->is_a(ID_Menu_Item)) || !q->can_have_children()) p = p->parent;
|
anchor = p;
|
||||||
|
strategy = kAddAfterCurrent;
|
||||||
|
p = p->parent;
|
||||||
}
|
}
|
||||||
force_parent = 0;
|
if (!p) {
|
||||||
if (!p || !(p->is_a(ID_Menu_Manager_) || p->is_a(ID_Submenu))) {
|
fl_message("Please select a menu widget or a menu item");
|
||||||
fl_message("Please select a menu to add to");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!o) {
|
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 = new Fl_Button(0,0,100,20);
|
||||||
t->o->type(flags);
|
t->o->type(flags);
|
||||||
t->factory = this;
|
t->factory = this;
|
||||||
t->add(p, strategy);
|
t->add(anchor, strategy);
|
||||||
if (!reading_file) {
|
if (!reading_file) {
|
||||||
if (flags==FL_SUBMENU) {
|
if (flags==FL_SUBMENU) {
|
||||||
t->label("submenu");
|
t->label("submenu");
|
||||||
|
|
|
@ -130,6 +130,143 @@ Fl_Type *in_this_only; // set if menu popped-up in window
|
||||||
|
|
||||||
// ---- various functions
|
// ---- 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 *) {
|
void select_all_cb(Fl_Widget *,void *) {
|
||||||
Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
|
Fl_Type *p = Fl_Type::current ? Fl_Type::current->parent : 0;
|
||||||
if (in_this_only) {
|
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) {
|
void update_visibility_flag(Fl_Type *p) {
|
||||||
Fl_Type *t = p;
|
Fl_Type *t = p;
|
||||||
for (;;) {
|
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;
|
else t->visible = 1;
|
||||||
t = t->next;
|
t = t->next;
|
||||||
if (!t || t->level <= p->level) break;
|
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] p insert \c this tree as a child of \c p
|
||||||
\param[in] strategy is kAddAsLastChild or kAddAfterCurrent
|
\param[in] strategy is kAddAsLastChild or kAddAfterCurrent
|
||||||
*/
|
*/
|
||||||
void Fl_Type::add(Fl_Type *p, Strategy strategy) {
|
void Fl_Type::add(Fl_Type *anchor, Strategy strategy) {
|
||||||
if (p && parent == p) return;
|
#if 0
|
||||||
undo_checkpoint();
|
#ifndef NDEBUG
|
||||||
parent = p;
|
// print_project_tree();
|
||||||
// 'this' is not in the Widget_Browser, so we must run the linked list to find the last entry
|
// 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;
|
Fl_Type *end = this;
|
||||||
while (end->next) end = end->next;
|
while (end->next) end = end->next;
|
||||||
// run the list again to set the future node levels
|
|
||||||
Fl_Type *q; // insert 'this' before q
|
// Everything is prepared, now insert ourself in front of the target node
|
||||||
int newlevel;
|
undo_checkpoint();
|
||||||
if (p) {
|
|
||||||
// find the last node that is a child or grandchild of p
|
// Walk the tree to update parent pointers and levels
|
||||||
for (q = p->next; q && q->level > p->level; q = q->next) {/*empty*/}
|
int source_level = level;
|
||||||
newlevel = p->level+1;
|
for (Fl_Type *t = this; t; t = t->next) {
|
||||||
} else {
|
t->level += (target_level-source_level);
|
||||||
q = 0;
|
if (t->level == target_level)
|
||||||
newlevel = 0;
|
t->parent = target_parent;
|
||||||
}
|
}
|
||||||
for (Fl_Type *t = this->next; t; t = t->next) t->level += (newlevel-level);
|
|
||||||
level = newlevel;
|
// Now link ourselves and our children before 'target', or last, if 'target' is NULL
|
||||||
// now link 'this' and its children before 'q', or last, if 'q' is NULL
|
if (target) {
|
||||||
if (q) {
|
prev = target->prev;
|
||||||
prev = q->prev;
|
target->prev = end;
|
||||||
prev->next = this;
|
end->next = target;
|
||||||
q->prev = end;
|
|
||||||
end->next = q;
|
|
||||||
} else if (first) {
|
|
||||||
prev = last;
|
|
||||||
prev->next = this;
|
|
||||||
end->next = 0;
|
|
||||||
last = end;
|
|
||||||
} else {
|
} else {
|
||||||
first = this;
|
prev = Fl_Type::last;
|
||||||
last = end;
|
end->next = NULL;
|
||||||
prev = end->next = 0;
|
Fl_Type::last = end;
|
||||||
}
|
}
|
||||||
|
if (prev) {
|
||||||
|
prev->next = this;
|
||||||
|
} else {
|
||||||
|
Fl_Type::first = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
{ // make sure that we have no duplicate uid's
|
{ // make sure that we have no duplicate uid's
|
||||||
Fl_Type *tp = this;
|
Fl_Type *tp = this;
|
||||||
do {
|
do {
|
||||||
|
@ -513,28 +693,24 @@ void Fl_Type::add(Fl_Type *p, Strategy strategy) {
|
||||||
tp = tp->next;
|
tp = tp->next;
|
||||||
} while (tp!=end && tp!=NULL);
|
} while (tp!=end && tp!=NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// tell this that it was added, so it can update itself
|
// Give the widgets in our tree a chance to update themselves
|
||||||
if (p) p->add_child(this,0);
|
for (Fl_Type *t = this; t && t!=end->next; t = t->next) {
|
||||||
open_ = 1;
|
if (target_parent && (t->level == target_level))
|
||||||
update_visibility_flag(this);
|
target_parent->add_child(t, 0);
|
||||||
set_modflag(1);
|
update_visibility_flag(t);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_modflag(1);
|
||||||
widget_browser->redraw();
|
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");
|
||||||
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");
|
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"))
|
else if (!strcmp(c,"comment"))
|
||||||
comment(f.read_word());
|
comment(f.read_word());
|
||||||
else if (!strcmp(c,"open"))
|
else if (!strcmp(c,"open"))
|
||||||
open_ = 1;
|
folded_ = 0;
|
||||||
else if (!strcmp(c,"selected"))
|
else if (!strcmp(c,"selected"))
|
||||||
select(this,1);
|
select(this,1);
|
||||||
else if (!strcmp(c,"parent_properties"))
|
else if (!strcmp(c,"parent_properties"))
|
||||||
|
|
|
@ -46,7 +46,8 @@ class Fd_Project_Writer;
|
||||||
int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy)
|
int Fd_Project_Reader::read_project(const char *filename, int merge, Strategy strategy)
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
kAddAsLastChild = 0,
|
kAddAsFirstChild = 0,
|
||||||
|
kAddAsLastChild,
|
||||||
kAddAfterCurrent
|
kAddAfterCurrent
|
||||||
} Strategy;
|
} Strategy;
|
||||||
|
|
||||||
|
@ -92,6 +93,13 @@ void select_none_cb(Fl_Widget *,void *);
|
||||||
void earlier_cb(Fl_Widget*,void*);
|
void earlier_cb(Fl_Widget*,void*);
|
||||||
void later_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.
|
\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
|
(see `haderror`). It seems that this is often confused with new_selected
|
||||||
which seems to hold the true and visible selection state. */
|
which seems to hold the true and visible selection state. */
|
||||||
char selected; // copied here by selection_changed()
|
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
|
char visible; // true if all parents are open
|
||||||
int level; // number of parents over this
|
int level; // number of parents over this
|
||||||
static Fl_Type *first, *last;
|
static Fl_Type *first, *last;
|
||||||
|
|
|
@ -87,19 +87,20 @@ Fl_Widget_Type::ideal_size(int &w, int &h) {
|
||||||
\return new node
|
\return new node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Widget_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Widget_Type::make(Strategy strategy) {
|
||||||
// Find the current widget, or widget to copy:
|
Fl_Type *anchor = Fl_Type::current, *pp = anchor;
|
||||||
Fl_Type *qq = Fl_Type::current;
|
if (pp && (strategy == kAddAfterCurrent)) pp = pp->parent;
|
||||||
while (qq && (!qq->is_true_widget() || !qq->can_have_children())) qq = qq->parent;
|
while (pp && !pp->is_a(ID_Group)) {
|
||||||
if (!qq) {
|
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");
|
fl_message("Please select a group widget or window");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Fl_Widget_Type* q = (Fl_Widget_Type*)qq;
|
|
||||||
// find the parent widget:
|
Fl_Widget_Type* p = (Fl_Widget_Type*)pp;
|
||||||
Fl_Widget_Type* p = q;
|
Fl_Widget_Type* q = (Fl_Widget_Type*)anchor;
|
||||||
if ((force_parent || !p->is_a(ID_Group)) && p->parent && p->parent->is_widget())
|
|
||||||
p = (Fl_Widget_Type*)(p->parent);
|
|
||||||
force_parent = 0;
|
|
||||||
|
|
||||||
// Figure out a border between widget and window:
|
// 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;
|
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:
|
// Put it in the parent:
|
||||||
// ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add())
|
// ((Fl_Group *)(p->o))->add(t->o); (done by Fl_Type::add())
|
||||||
// add to browser:
|
// add to browser:
|
||||||
t->add(p, strategy);
|
t->add(anchor, strategy);
|
||||||
t->redraw();
|
t->redraw();
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,8 +227,13 @@ int Overlay_Window::handle(int e) {
|
||||||
\return new node
|
\return new node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Window_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Window_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && (!p->is_code_block() || p->is_a(ID_Widget_Class))) p = p->parent;
|
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) {
|
if (!p) {
|
||||||
fl_message("Please select a function");
|
fl_message("Please select a function");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -245,7 +250,7 @@ Fl_Type *Fl_Window_Type::make(Strategy strategy) {
|
||||||
w->size_range(10, 10);
|
w->size_range(10, 10);
|
||||||
w->window = myo;
|
w->window = myo;
|
||||||
myo->o = w;
|
myo->o = w;
|
||||||
myo->add(p, strategy);
|
myo->add(anchor, strategy);
|
||||||
myo->modal = 0;
|
myo->modal = 0;
|
||||||
myo->non_modal = 0;
|
myo->non_modal = 0;
|
||||||
return myo;
|
return myo;
|
||||||
|
@ -1363,8 +1368,13 @@ Fl_Widget_Class_Type *current_widget_class = 0;
|
||||||
\return new node
|
\return new node
|
||||||
*/
|
*/
|
||||||
Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
|
Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
|
||||||
Fl_Type *p = Fl_Type::current;
|
Fl_Type *anchor = Fl_Type::current, *p = anchor;
|
||||||
while (p && (!p->is_decl_block() || (p->is_widget() && p->is_class()))) p = p->parent;
|
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();
|
Fl_Widget_Class_Type *myo = new Fl_Widget_Class_Type();
|
||||||
myo->name("UserInterface");
|
myo->name("UserInterface");
|
||||||
|
|
||||||
|
@ -1379,7 +1389,7 @@ Fl_Type *Fl_Widget_Class_Type::make(Strategy strategy) {
|
||||||
w->size_range(10, 10);
|
w->size_range(10, 10);
|
||||||
w->window = myo;
|
w->window = myo;
|
||||||
myo->o = w;
|
myo->o = w;
|
||||||
myo->add(p, strategy);
|
myo->add(anchor, strategy);
|
||||||
myo->modal = 0;
|
myo->modal = 0;
|
||||||
myo->non_modal = 0;
|
myo->non_modal = 0;
|
||||||
myo->wc_relative = 0;
|
myo->wc_relative = 0;
|
||||||
|
|
|
@ -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) {
|
static void cbf(Fl_Widget *, void *v) {
|
||||||
Fl_Type *t = NULL;
|
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);
|
t = ((Fl_Type*)v)->make(kAddAsLastChild);
|
||||||
else
|
else
|
||||||
t = ((Fl_Type*)v)->make(kAddAfterCurrent);
|
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) {
|
static void cb(Fl_Widget *, void *v) {
|
||||||
Fl_Type *t = NULL;
|
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);
|
t = add_new_widget_from_user((Fl_Type*)v, kAddAsLastChild);
|
||||||
else
|
else
|
||||||
t = add_new_widget_from_user((Fl_Type*)v, kAddAfterCurrent);
|
t = add_new_widget_from_user((Fl_Type*)v, kAddAfterCurrent);
|
||||||
|
|
|
@ -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 *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strategy, char skip_options) {
|
||||||
Fl_Type::current = p;
|
Fl_Type::current = p;
|
||||||
Fl_Type *last_child_read = NULL;
|
Fl_Type *last_child_read = NULL;
|
||||||
|
Fl_Type *t = NULL;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const char *c = read_word();
|
const char *c = read_word();
|
||||||
REUSE_C:
|
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) {
|
if (!t) {
|
||||||
read_error("Unknown word \"%s\"", c);
|
read_error("Unknown word \"%s\"", c);
|
||||||
continue;
|
continue;
|
||||||
|
@ -377,7 +378,7 @@ Fl_Type *Fd_Project_Reader::read_children(Fl_Type *p, int merge, Strategy strate
|
||||||
goto REUSE_C;
|
goto REUSE_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->open_ = 0;
|
t->folded_ = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const char *cc = read_word();
|
const char *cc = read_word();
|
||||||
if (!cc || !strcmp(cc,"}")) break;
|
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());
|
read_error("Missing child list for %s\n",t->title());
|
||||||
goto REUSE_C;
|
goto REUSE_C;
|
||||||
}
|
}
|
||||||
read_children(t, 0, strategy, skip_options);
|
read_children(t, 0, kAddAsLastChild, skip_options);
|
||||||
t->postprocess_read();
|
t->postprocess_read();
|
||||||
// FIXME: this has no business in the file reader!
|
// FIXME: this has no business in the file reader!
|
||||||
// TODO: this is called whenever something is pasted from the top level into a grid
|
// 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();
|
t->layout_widget();
|
||||||
}
|
}
|
||||||
|
if (strategy == kAddAfterCurrent) {
|
||||||
Fl_Type::current = p;
|
Fl_Type::current = t;
|
||||||
|
} else {
|
||||||
|
Fl_Type::current = p;
|
||||||
|
}
|
||||||
|
|
||||||
CONTINUE:;
|
CONTINUE:;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,11 +106,6 @@ int G_debug = 0;
|
||||||
char G_external_editor_command[512];
|
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.
|
/// This is set to create different labels when creating new widgets.
|
||||||
/// \todo Details unclear.
|
/// \todo Details unclear.
|
||||||
int reading_file = 0;
|
int reading_file = 0;
|
||||||
|
@ -1411,13 +1406,16 @@ void delete_cb(Fl_Widget *, void *) {
|
||||||
User chose to paste the widgets from the cut buffer.
|
User chose to paste the widgets from the cut buffer.
|
||||||
*/
|
*/
|
||||||
void paste_cb(Fl_Widget*, void*) {
|
void paste_cb(Fl_Widget*, void*) {
|
||||||
//if (ipasteoffset) force_parent = 1;
|
|
||||||
pasteoffset = ipasteoffset;
|
pasteoffset = ipasteoffset;
|
||||||
undo_checkpoint();
|
undo_checkpoint();
|
||||||
undo_suspend();
|
undo_suspend();
|
||||||
Strategy strategy = kAddAfterCurrent;
|
Strategy strategy = kAddAfterCurrent;
|
||||||
if (Fl_Type::current && Fl_Type::current->is_a(ID_Group))
|
if (Fl_Type::current && Fl_Type::current->is_a(ID_Group)) {
|
||||||
strategy = kAddAsLastChild;
|
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)) {
|
if (!read_file(cutfname(), 1, strategy)) {
|
||||||
widget_browser->rebuild();
|
widget_browser->rebuild();
|
||||||
fl_message("Can't read %s: %s", cutfname(), strerror(errno));
|
fl_message("Can't read %s: %s", cutfname(), strerror(errno));
|
||||||
|
@ -1427,7 +1425,6 @@ void paste_cb(Fl_Widget*, void*) {
|
||||||
widget_browser->rebuild();
|
widget_browser->rebuild();
|
||||||
pasteoffset = 0;
|
pasteoffset = 0;
|
||||||
ipasteoffset += 10;
|
ipasteoffset += 10;
|
||||||
force_parent = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1447,7 +1444,6 @@ void duplicate_cb(Fl_Widget*, void*) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pasteoffset = 0;
|
pasteoffset = 0;
|
||||||
force_parent = 1;
|
|
||||||
|
|
||||||
undo_checkpoint();
|
undo_checkpoint();
|
||||||
undo_suspend();
|
undo_suspend();
|
||||||
|
@ -1458,8 +1454,6 @@ void duplicate_cb(Fl_Widget*, void*) {
|
||||||
widget_browser->display(Fl_Type::current);
|
widget_browser->display(Fl_Type::current);
|
||||||
widget_browser->rebuild();
|
widget_browser->rebuild();
|
||||||
undo_resume();
|
undo_resume();
|
||||||
|
|
||||||
force_parent = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -51,8 +51,6 @@ typedef enum {
|
||||||
|
|
||||||
// ---- global variables
|
// ---- global variables
|
||||||
|
|
||||||
extern int force_parent;
|
|
||||||
|
|
||||||
extern Fl_Preferences fluid_prefs;
|
extern Fl_Preferences fluid_prefs;
|
||||||
extern Fl_Menu_Item Main_Menu[];
|
extern Fl_Menu_Item Main_Menu[];
|
||||||
extern Fl_Menu_Bar *main_menubar;
|
extern Fl_Menu_Bar *main_menubar;
|
||||||
|
|
|
@ -120,8 +120,8 @@ void reveal_in_browser(Fl_Type *t) {
|
||||||
Fl_Type *p = t->parent;
|
Fl_Type *p = t->parent;
|
||||||
if (p) {
|
if (p) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!p->open_)
|
if (p->folded_)
|
||||||
p->open_ = 1;
|
p->folded_ = 0;
|
||||||
if (!p->parent) break;
|
if (!p->parent) break;
|
||||||
p = p->parent;
|
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()) {
|
if (l->can_have_children()) {
|
||||||
X = X - 18 - 13;
|
X = X - 18 - 13;
|
||||||
if (!l->next || l->next->level <= l->level) {
|
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
|
// an outlined triangle to the right indicates closed item, no children
|
||||||
fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
|
fl_loop(X,Y+7,X+5,Y+12,X+10,Y+7);
|
||||||
} else {
|
} 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);
|
fl_loop(X+2,Y+2,X+7,Y+7,X+2,Y+12);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (l->open_!=(l==pushedtitle)) {
|
if (l->folded_==(l==pushedtitle)) {
|
||||||
// a filled triangle to the right indicates closed item, with children
|
// a filled triangle to the right indicates closed item, with children
|
||||||
fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
|
fl_polygon(X,Y+7,X+5,Y+12,X+10,Y+7);
|
||||||
} else {
|
} else {
|
||||||
|
@ -538,15 +538,15 @@ int Widget_Browser::handle(int e) {
|
||||||
l = pushedtitle;
|
l = pushedtitle;
|
||||||
title = pushedtitle = 0;
|
title = pushedtitle = 0;
|
||||||
if (l) {
|
if (l) {
|
||||||
if (l->open_) {
|
if (!l->folded_) {
|
||||||
l->open_ = 0;
|
l->folded_ = 1;
|
||||||
for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
|
for (Fl_Type*k = l->next; k&&k->level>l->level; k = k->next)
|
||||||
k->visible = 0;
|
k->visible = 0;
|
||||||
} else {
|
} else {
|
||||||
l->open_ = 1;
|
l->folded_ = 0;
|
||||||
for (Fl_Type*k=l->next; k&&k->level>l->level;) {
|
for (Fl_Type*k=l->next; k&&k->level>l->level;) {
|
||||||
k->visible = 1;
|
k->visible = 1;
|
||||||
if (k->can_have_children() && !k->open_) {
|
if (k->can_have_children() && k->folded_) {
|
||||||
Fl_Type *j;
|
Fl_Type *j;
|
||||||
for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/}
|
for (j = k->next; j && j->level>k->level; j = j->next) {/*empty*/}
|
||||||
k = j;
|
k = j;
|
||||||
|
|
Loading…
Reference in New Issue