FLUID: Positioning grid cells intuitively.
User can now drag widgets from the toolbox into the grid or use the context menu to add them into the corresponding cell. If no position is indicated, now children are added at the first free cell.
This commit is contained in:
parent
ab6ef9d52f
commit
17baeceb7a
@ -311,6 +311,9 @@ public:
|
||||
void row_gap(const int *value, size_t size);
|
||||
int row_gap(int row) const;
|
||||
|
||||
int computed_col_width(int col) const;
|
||||
int computed_row_height(int row) const;
|
||||
|
||||
/**
|
||||
Enable or disable drawing of the grid helper lines for visualization.
|
||||
|
||||
|
@ -421,18 +421,62 @@ static void move_cell(Fl_Grid *grid, Fl_Widget *child, int to_row, int to_col) {
|
||||
if (new_cell) new_cell->minimum_size(w, h);
|
||||
}
|
||||
|
||||
void Fl_Grid_Type::insert_child_at(Fl_Widget *child, int x, int y) {
|
||||
Fl_Grid *grid = (Fl_Grid*)o;
|
||||
int row = -1, col = -1, ml, mt, grg, gcg;
|
||||
grid->margin(&ml, &mt, NULL, NULL);
|
||||
grid->gap(&grg, &gcg);
|
||||
int x0 = grid->x() + Fl::box_dx(grid->box()) + ml;
|
||||
int y0 = grid->y() + Fl::box_dy(grid->box()) + mt;
|
||||
|
||||
for (int r = 0; r < grid->rows(); r++) {
|
||||
if (y>y0) row = r;
|
||||
int gap = grid->row_gap(r)>=0 ? grid->row_gap(r) : grg;
|
||||
y0 += grid->computed_row_height(r);
|
||||
y0 += gap;
|
||||
}
|
||||
|
||||
for (int c = 0; c < grid->cols(); c++) {
|
||||
if (x>x0) col = c;
|
||||
int gap = grid->col_gap(c)>=0 ? grid->col_gap(c) : gcg;
|
||||
x0 += grid->computed_col_width(c);
|
||||
x0 += gap;
|
||||
}
|
||||
|
||||
move_cell(grid, child, row, col);
|
||||
}
|
||||
|
||||
/** Insert a child window into the first new cell we can find .
|
||||
|
||||
There are many other possible strategies. How about inserting to the right
|
||||
of the last added child. Also, what happens if the grid is full? Should
|
||||
we add a new row at the bottom?
|
||||
*/
|
||||
void Fl_Grid_Type::insert_child(Fl_Widget *child) {
|
||||
Fl_Grid *grid = (Fl_Grid*)o;
|
||||
if (grid->cell(child)) return;
|
||||
for (int r=0; r<grid->rows(); r++) {
|
||||
for (int c=0; c<grid->cols(); c++) {
|
||||
if (!grid->cell(r, c)) {
|
||||
move_cell(grid, child, r, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: when changing the cell location, and another cell would be overridden,
|
||||
// don't actually move the cell (hard to implement!) and activate
|
||||
// a red button "replace". If clicked, user gets the option to delete
|
||||
// the old widget, or just remove the cell, or cancel.
|
||||
// TODO: move cells by using the arrow keys?
|
||||
// TODO: move cells via drag'n'drop
|
||||
// TODO: insert cells when adding them from the menu or toolbar
|
||||
// TODO: better grid overlay?
|
||||
// TODO: grid_child_cb should move all selected cells.
|
||||
// TODO: grid_child_cb should move all selected cells, not just the current_selected.
|
||||
// TODO: buttons to add and delete rows and columns in the widget dialog
|
||||
// TODO: ways to resize rows and columns, add and delete them in the project window, pulldown menu?
|
||||
// TODO: alignment can be FL_GRID_LEFT|FL_GRID_VERTICAL?
|
||||
// TODO: we must set undo checkpoints in all callbacks!
|
||||
void grid_child_cb(Fluid_Coord_Input* i, void* v, int what) {
|
||||
static Fl_Widget *prev_widget = NULL;
|
||||
if ( !current_widget
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
void move_child(Fl_Type*, Fl_Type*) FL_OVERRIDE;
|
||||
void remove_child(Fl_Type*) FL_OVERRIDE;
|
||||
void child_resized(Fl_Widget_Type *child);
|
||||
void insert_child_at(Fl_Widget *child, int x, int y);
|
||||
void insert_child(Fl_Widget *child);
|
||||
|
||||
static class Fl_Grid *selected();
|
||||
};
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "fluid.h"
|
||||
#include "Fl_Group_Type.h"
|
||||
#include "Fl_Grid_Type.h"
|
||||
#include "Fl_Menu_Type.h"
|
||||
#include "Fd_Snap_Action.h"
|
||||
#include "pixmaps.h"
|
||||
@ -1225,6 +1226,13 @@ Fl_Type *add_new_widget_from_user(Fl_Type *inPrototype, Strategy strategy) {
|
||||
wt->o->size(w, h);
|
||||
}
|
||||
}
|
||||
if (t->parent && t->parent->is_a(ID_Grid)) {
|
||||
if (Fl_Window_Type::popupx != 0x7FFFFFFF) {
|
||||
((Fl_Grid_Type*)t->parent)->insert_child_at(((Fl_Widget_Type*)t)->o, Fl_Window_Type::popupx, Fl_Window_Type::popupy);
|
||||
} else {
|
||||
((Fl_Grid_Type*)t->parent)->insert_child(((Fl_Widget_Type*)t)->o);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t->is_a(ID_Window)) {
|
||||
int x = 0, y = 0, w = 480, h = 320;
|
||||
|
@ -1142,6 +1142,14 @@ int Fl_Grid::row_gap(int row) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fl_Grid::computed_col_width(int col) const {
|
||||
return Cols_[col].w_;
|
||||
}
|
||||
|
||||
int Fl_Grid::computed_row_height(int row) const {
|
||||
return Rows_[row].h_;
|
||||
}
|
||||
|
||||
/**
|
||||
Output layout information of this Fl_Grid to stderr.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user