Fix various tooltip markup (ampersand) entity-escape:
[ardour.git] / libs / canvas / grid.cc
index 323cdbf1ad9ee2bba89ad1cb4bf999bddae7ad23..e46a184e42ce19dd3a5d6e4be29da8a849a36960 100644 (file)
@@ -30,38 +30,44 @@ using std::endl;
 
 Grid::Grid (Canvas* canvas)
        : Item (canvas)
-       , spacing (0)
+       , row_spacing (0)
+       , col_spacing (0)
        , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
        , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
        , homogenous (false)
 {
-       self = new Rectangle (this);
-       self->set_outline (false);
-       self->set_fill (false);
+       bg = new Rectangle (this);
+       bg->set_outline (false);
+       bg->set_fill (false);
+       bg->hide ();
 }
 
 Grid::Grid (Item* parent)
        : Item (parent)
-       , spacing (0)
+       , row_spacing (0)
+       , col_spacing (0)
        , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
        , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
        , homogenous (false)
 {
-       self = new Rectangle (this);
-       self->set_outline (false);
-       self->set_fill (false);
+       bg = new Rectangle (this);
+       bg->set_outline (false);
+       bg->set_fill (false);
+       bg->hide ();
 }
 
 Grid::Grid (Item* parent, Duple const & p)
        : Item (parent, p)
-       , spacing (0)
+       , row_spacing (0)
+       , col_spacing (0)
        , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
        , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
        , homogenous (true)
 {
-       self = new Rectangle (this);
-       self->set_outline (false);
-       self->set_fill (false);
+       bg = new Rectangle (this);
+       bg->set_outline (false);
+       bg->set_fill (false);
+       bg->hide ();
 }
 
 void
@@ -91,19 +97,25 @@ Grid::compute_bounding_box () const
        if (_bounding_box) {
                Rect r = _bounding_box;
 
-               _bounding_box = r.expand (outline_width() + top_margin,
-                                         outline_width() + right_margin,
-                                         outline_width() + bottom_margin,
-                                         outline_width() + left_margin);
+               _bounding_box = r.expand (outline_width() + top_margin + top_padding,
+                                         outline_width() + right_margin + right_padding,
+                                         outline_width() + bottom_margin + bottom_padding,
+                                         outline_width() + left_margin + left_padding);
        }
 
        _bounding_box_dirty = false;
 }
 
 void
-Grid::set_spacing (double s)
+Grid::set_row_spacing (double s)
 {
-       spacing = s;
+       row_spacing = s;
+}
+
+void
+Grid::set_col_spacing (double s)
+{
+       col_spacing = s;
 }
 
 void
@@ -147,14 +159,14 @@ Grid::set_margin (double t, double r, double b, double l)
 }
 
 void
-Grid::reset_self ()
+Grid::reset_bg ()
 {
        if (_bounding_box_dirty) {
                compute_bounding_box ();
        }
 
        if (!_bounding_box) {
-               self->hide ();
+               bg->hide ();
                return;
        }
 
@@ -162,7 +174,7 @@ Grid::reset_self ()
 
        /* XXX need to shrink by margin */
 
-       self->set (r);
+       bg->set (r);
 }
 
 void
@@ -172,34 +184,35 @@ Grid::reposition_children ()
        uint32_t max_col = 0;
 
        /* since we encourage dynamic and essentially random placement of
-        * children, begin by determining the maximum row and column given
+        * children, begin by determining the maximum row and column extents given
         * our current set of children and placements.
         */
 
        for (CoordsByItem::const_iterator c = coords_by_item.begin(); c != coords_by_item.end(); ++c) {
-               max_col = max (max_col, (uint32_t) c->second.x);
-               max_row = max (max_row, (uint32_t) c->second.y);
+               if (collapse_on_hide && !c->second.item->visible()) {
+                       continue;
+               }
+               max_col = max (max_col, (uint32_t) (c->second.x + c->second.col_span));
+               max_row = max (max_row, (uint32_t) (c->second.y + c->second.row_span));
        }
 
-       max_row++;
-       max_col++;
-
        /* Now compute the width of the widest child for each column, and the
-        * height of the tallest child for each row.
+        * height of the tallest child for each row. Store the results in
+        * row_dimens and col_dimens, making sure they are suitably sized first.
         */
 
        vector<double> row_dimens;
        vector<double> col_dimens;
 
-       row_dimens.assign (max_row, 0);
-       col_dimens.assign (max_col, 0);
+       row_dimens.assign (max_row + 1, 0);
+       col_dimens.assign (max_col + 1, 0);
 
-       Rect uniform_size;
+       Rect uniform_cell_size;
 
        if (homogenous) {
                for (std::list<Item*>::iterator i = _items.begin(); i != _items.end(); ++i) {
 
-                       if (*i == self) {
+                       if (*i == bg || (collapse_on_hide && !(*i)->visible())) {
                                continue;
                        }
 
@@ -208,31 +221,42 @@ Grid::reposition_children ()
                        if (!bb) {
                                continue;
                        }
-                       cerr << "\tbb for " << (*i)->whatami() << " is " << bb << endl;
-                       uniform_size.y1 = max (uniform_size.y1, bb.height());
-                       uniform_size.x1 = max (uniform_size.x1, bb.width());
+
+                       CoordsByItem::const_iterator c = coords_by_item.find (*i);
+
+                       uniform_cell_size.x1 = max (uniform_cell_size.x1, (bb.width()/c->second.col_span));
+                       uniform_cell_size.y1 = max (uniform_cell_size.y1, (bb.height()/c->second.row_span));
+               }
+
+               for (uint32_t n = 0; n < max_col; ++n) {
+                       col_dimens[n] = uniform_cell_size.width();
                }
 
-               cerr << "Uniform size will be " << uniform_size << endl;
+               for (uint32_t n = 0; n < max_row; ++n) {
+                       row_dimens[n] = uniform_cell_size.height();
+               }
 
                for (std::list<Item*>::iterator i = _items.begin(); i != _items.end(); ++i) {
-                       if (*i == self) {
-                               /* self-rect is not a normal child */
+
+                       if (*i == bg || (collapse_on_hide && !(*i)->visible())) {
+                               /* bg rect is not a normal child */
                                continue;
                        }
-                       (*i)->size_allocate (uniform_size);
-                       for (uint32_t n = 0; n < max_col; ++n) {
-                               col_dimens[n] = uniform_size.width();
-                       }
-                       for (uint32_t n = 0; n < max_row; ++n) {
-                               row_dimens[n] = uniform_size.height();
-                       }
+
+                       CoordsByItem::const_iterator c = coords_by_item.find (*i);
+
+                       Rect r = uniform_cell_size;
+                       r.x1 *= c->second.col_span;
+                       r.y1 *= c->second.row_span;
+
+                       (*i)->size_allocate (r);
                }
+
        } else {
                for (std::list<Item*>::iterator i = _items.begin(); i != _items.end(); ++i) {
 
-                       if (*i == self) {
-                               /* self-rect is not a normal child */
+                       if (*i == bg || (collapse_on_hide && !(*i)->visible())) {
+                               /* bg rect is not a normal child */
                                continue;
                        }
 
@@ -244,38 +268,48 @@ Grid::reposition_children ()
 
                        CoordsByItem::const_iterator c = coords_by_item.find (*i);
 
-                       row_dimens[c->second.y] = max (row_dimens[c->second.y], bb.height());
-                       col_dimens[c->second.x] = max (col_dimens[c->second.x]  , bb.width());
-               }
-       }
+                       const double per_col_width = bb.width() / c->second.col_span;
+                       const double per_row_height = bb.height() / c->second.row_span;
 
-       /* now sum the row and column widths, so that row_dimens is transformed
-        * into the y coordinate of the upper left of each row, and col_dimens
-        * is transformed into the x coordinate of the left edge of each
-        * column.
-        */
+                       /* set the width of each column spanned by this item
+                        */
 
-       double current_top_edge = top_margin;
-
-       for (uint32_t n = 0; n < max_row; ++n) {
-               if (row_dimens[n]) {
-                       /* height defined for this row */
-                       const double h = row_dimens[n]; /* save height */
-                       row_dimens[n] = current_top_edge;
-                       cerr << "row[" << n << "] @ " << row_dimens[n] << endl;
-                       current_top_edge = current_top_edge + h + top_padding + bottom_padding;
+                       for (int n = 0; n < (int) c->second.col_span; ++n) {
+                               col_dimens[c->second.x + n] = max (col_dimens[c->second.x + n], per_col_width);
+                       }
+                       for (int n = 0; n < (int) c->second.row_span; ++n) {
+                               row_dimens[c->second.y + n] = max (row_dimens[c->second.y + n], per_row_height);
+                       }
                }
        }
 
-       double current_right_edge = left_margin;
+       /* now progressively sum the row and column widths, once we're done:
+        *
+        * col_dimens: transformed into the x coordinate of the left edge of each column.
+        *
+        * row_dimens: transformed into the y coordinate of the upper left of each row,
+        *
+        */
+
+       double current_right_edge = left_margin + left_padding;
 
        for (uint32_t n = 0; n < max_col; ++n) {
                if (col_dimens[n]) {
                        /* a width was defined for this column */
                        const double w = col_dimens[n]; /* save width of this column */
                        col_dimens[n] = current_right_edge;
-                       cerr << "col[" << n << "] @ " << col_dimens[n] << endl;
-                       current_right_edge = current_right_edge + w + left_padding + right_padding;
+                       current_right_edge = current_right_edge + w + col_spacing;
+               }
+       }
+
+       double current_top_edge = top_margin + top_padding;
+
+       for (uint32_t n = 0; n < max_row; ++n) {
+               if (row_dimens[n]) {
+                       /* height defined for this row */
+                       const double h = row_dimens[n]; /* save height */
+                       row_dimens[n] = current_top_edge;
+                       current_top_edge = current_top_edge + h + row_spacing;
                }
        }
 
@@ -290,21 +324,31 @@ Grid::reposition_children ()
                        continue;
                }
 
+               /* do this even for hidden items - it will be corrected when
+                * they become visible again.
+                */
+
                (*i)->set_position (Duple (col_dimens[c->second.x], row_dimens[c->second.y]));
-               cerr << "place " << (*i)->whatami() << " @ " << c->second.x << ", " << c->second.y << " at "
-                    << Duple (col_dimens[c->second.x], row_dimens[c->second.y])
-                    << endl;
        }
 
        _bounding_box_dirty = true;
-       reset_self ();
+       reset_bg ();
 }
 
 void
-Grid::place (Item* i, Duple at)
+Grid::place (Item* i, double x, double y, double col_span, double row_span)
 {
+       ChildInfo ci;
+
        add (i);
-       coords_by_item.insert (std::make_pair (i, at));
+
+       ci.item = i;
+       ci.x = x;
+       ci.y = y;
+       ci.col_span = max (1.0, col_span);
+       ci.row_span = max (1.0, row_span);
+
+       coords_by_item.insert (std::make_pair (i, ci));
        reposition_children ();
 }