FLUID: Fixes grouping and ungrouping, #1056

- grouping a bunch of widgets will now create the new
  group in the expected place
- also add grouping and ungrouping of menu items
- ungrouping now also works with only a few items
  selected instead all items, moving the selection before
  the group
This commit is contained in:
Matthias Melcher 2024-08-31 19:08:12 +02:00
parent 1da9438a1c
commit c8b8eb4b84
3 changed files with 127 additions and 29 deletions

View File

@ -89,59 +89,95 @@ void fix_group_size(Fl_Type *tt) {
t->o->resize(X,Y,R-X,B-Y); t->o->resize(X,Y,R-X,B-Y);
} }
extern void group_selected_menuitems();
void group_cb(Fl_Widget *, void *) { void group_cb(Fl_Widget *, void *) {
// Find the current widget: if (!Fl_Type::current) {
Fl_Type *qq = Fl_Type::current; fl_message("No widgets selected.");
while (qq && !qq->is_true_widget()) qq = qq->parent; return;
if (!qq || qq->level < 1 || (qq->level == 1 && qq->is_a(ID_Widget_Class))) { }
fl_message("Please select widgets to group"); if (!Fl_Type::current->is_widget()) {
fl_message("Only widgets and menu items can be grouped.");
return;
}
if (Fl_Type::current->is_a(ID::ID_Menu_Item)) {
group_selected_menuitems();
return;
}
// The group will be created in the parent group of the current widget
Fl_Type *qq = Fl_Type::current->parent;
Fl_Widget_Type *q = static_cast<Fl_Widget_Type*>(Fl_Type::current);
while (qq && !qq->is_a(ID::ID_Group)) {
qq = qq->parent;
}
if (!qq) {
fl_message("Can't create a new group here.");
return; return;
} }
undo_checkpoint(); undo_checkpoint();
undo_suspend(); undo_suspend();
Fl_Widget_Type* q = (Fl_Widget_Type*)qq; Fl_Type::current = qq;
force_parent = 1;
Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make(kAddAsLastChild)); Fl_Group_Type *n = (Fl_Group_Type*)(Fl_Group_type.make(kAddAsLastChild));
n->move_before(q); n->move_before(q);
n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h()); n->o->resize(q->o->x(),q->o->y(),q->o->w(),q->o->h());
for (Fl_Type *t = Fl_Type::first; t;) { for (Fl_Type *t = qq->next; t && (t->level > qq->level);) {
if (t->level != n->level || t == n || !t->selected) { if (t->level != n->level || t == n || !t->selected) {
t = t->next; continue;} t = t->next;
continue;
}
Fl_Type *nxt = t->remove(); Fl_Type *nxt = t->remove();
t->add(n, kAddAsLastChild); t->add(n, kAddAsLastChild);
t = nxt; t = nxt;
} }
fix_group_size(n); fix_group_size(n);
Fl_Type::current = q;
n->layout_widget(); n->layout_widget();
widget_browser->rebuild(); widget_browser->rebuild();
undo_resume(); undo_resume();
set_modflag(1); set_modflag(1);
} }
extern void ungroup_selected_menuitems();
void ungroup_cb(Fl_Widget *, void *) { void ungroup_cb(Fl_Widget *, void *) {
// Find the group: if (!Fl_Type::current) {
Fl_Type *q = Fl_Type::current; fl_message("No widgets selected.");
while (q && !q->is_true_widget()) q = q->parent;
if (q) q = q->parent;
if (!q || q->level < 1 || (q->level == 1 && q->is_a(ID_Widget_Class))) {
fl_message("Please select widgets in a group");
return; return;
} }
Fl_Type* n; if (!Fl_Type::current->is_widget()) {
for (n = q->next; n && n->level > q->level; n = n->next) { fl_message("Only widgets and menu items can be ungrouped.");
if (n->level == q->level+1 && !n->selected) {
fl_message("Please select all widgets in group");
return; return;
} }
if (Fl_Type::current->is_a(ID::ID_Menu_Item)) {
ungroup_selected_menuitems();
return;
}
Fl_Widget_Type *q = static_cast<Fl_Widget_Type*>(Fl_Type::current);
int q_level = q->level;
Fl_Type *qq = Fl_Type::current->parent;
while (qq && !qq->is_true_widget()) qq = qq->parent;
if (!qq || !qq->is_a(ID_Group)) {
fl_message("Only menu widgets inside a group can be ungrouped.");
return;
} }
undo_checkpoint(); undo_checkpoint();
undo_suspend(); undo_suspend();
for (n = q->next; n && n->level > q->level;) { Fl_Type::current = qq;
Fl_Type *nxt = n->remove(); for (Fl_Type *t = qq->next; t && (t->level > qq->level);) {
n->insert(q); if (t->level != q_level || !t->selected) {
n = nxt; t = t->next;
continue;
} }
delete q; Fl_Type *nxt = t->remove();
t->insert(qq);
t = nxt;
}
if (!qq->next || (qq->next->level <= qq->level)) {
qq->remove();
delete qq; // qq has no children that need to be delete
}
Fl_Type::current = q;
widget_browser->rebuild(); widget_browser->rebuild();
undo_resume(); undo_resume();
set_modflag(1); set_modflag(1);

View File

@ -29,6 +29,8 @@
#include "Fluid_Image.h" #include "Fluid_Image.h"
#include "custom_widgets.h" #include "custom_widgets.h"
#include "mergeback.h" #include "mergeback.h"
#include "undo.h"
#include "widget_browser.h"
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/fl_message.H> #include <FL/fl_message.H>
@ -175,6 +177,65 @@ Fl_Type *Fl_Menu_Item_Type::make(Strategy strategy) {
return t; return t;
} }
void group_selected_menuitems() {
// The group will be created in the parent group of the current menuitem
Fl_Type *qq = Fl_Type::current->parent;
Fl_Widget_Type *q = static_cast<Fl_Widget_Type*>(Fl_Type::current);
if (!qq || !(qq->is_a(ID_Menu_Manager_) || qq->is_a(ID_Submenu))) {
fl_message("Can't create a new group here.");
return;
}
undo_checkpoint();
undo_suspend();
submenuflag = 1;
Fl_Widget_Type *n = (Fl_Widget_Type*)(q->make(kAddAfterCurrent));
submenuflag = 0;
for (Fl_Type *t = qq->next; t && (t->level > qq->level);) {
if (t->level != n->level || t == n || !t->selected) {
t = t->next;
continue;
}
Fl_Type *nxt = t->remove();
t->add(n, kAddAsLastChild);
t = nxt;
}
widget_browser->rebuild();
undo_resume();
set_modflag(1);
}
void ungroup_selected_menuitems() {
// Find the submenu
Fl_Type *qq = Fl_Type::current->parent;
Fl_Widget_Type *q = static_cast<Fl_Widget_Type*>(Fl_Type::current);
int q_level = q->level;
if (!qq || !qq->is_a(ID_Submenu)) {
fl_message("Only menu items inside a submenu can be ungrouped.");
return;
}
undo_checkpoint();
undo_suspend();
Fl_Type::current = qq;
for (Fl_Type *t = qq->next; t && (t->level > qq->level);) {
if (t->level != q_level || !t->selected) {
t = t->next;
continue;
}
Fl_Type *nxt = t->remove();
t->insert(qq);
t = nxt;
}
if (!qq->next || (qq->next->level <= qq->level)) {
qq->remove();
delete qq; // qq has no children that need to be delete
}
Fl_Type::current = q;
widget_browser->rebuild();
undo_resume();
set_modflag(1);
}
/** /**
Create and add a new Checkbox Menu Item node. Create and add a new Checkbox Menu Item node.
\param[in] strategy add after current or as last child \param[in] strategy add after current or as last child

View File

@ -257,10 +257,11 @@ __Edit > Later (F3)__: Move all of the selected widgets one later in order
among the children of their parent (if possible). among the children of their parent (if possible).
__Edit > Group (F7)__: Create a new Fl_Group and make all the currently __Edit > Group (F7)__: Create a new Fl_Group and make all the currently
selected widgets children of it. selected widgets children of that group.
__Edit > Ungroup (F8)__: Delete the parent group if all the children of a __Edit > Ungroup (F8)__: Move the selected children of a group out of the
group are selected. group and up one level in the hierarchy. If all children of a group are
selected and moved, the remaining empty group is deleted.
__Edit > Show or Hide Overlays (Ctrl+Shift+O)__: Toggle the display of the __Edit > Show or Hide Overlays (Ctrl+Shift+O)__: Toggle the display of the
red overlays off, without changing the selection. This makes it easier to see red overlays off, without changing the selection. This makes it easier to see