initial skeleton for a Grid canvas item
[ardour.git] / libs / canvas / grid.cc
1 /*
2     Copyright (C) 2018 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <algorithm>
20
21 #include "canvas/grid.h"
22 #include "canvas/rectangle.h"
23
24 using namespace ArdourCanvas;
25
26 Grid::Grid (Canvas* canvas)
27         : Item (canvas)
28         , spacing (0)
29         , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
30         , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
31         , homogenous (false)
32 {
33         self = new Rectangle (this);
34         self->set_outline (false);
35         self->set_fill (false);
36 }
37
38 Grid::Grid (Item* parent)
39         : Item (parent)
40         , spacing (0)
41         , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
42         , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
43         , homogenous (false)
44 {
45         self = new Rectangle (this);
46         self->set_outline (false);
47         self->set_fill (false);
48 }
49
50 Grid::Grid (Item* parent, Duple const & p)
51         : Item (parent, p)
52         , spacing (0)
53         , top_padding (0), right_padding (0), bottom_padding (0), left_padding (0)
54         , top_margin (0), right_margin (0), bottom_margin (0), left_margin (0)
55         , homogenous (false)
56 {
57         self = new Rectangle (this);
58         self->set_outline (false);
59         self->set_fill (false);
60 }
61
62 void
63 Grid::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
64 {
65         Item::render_children (area, context);
66 }
67
68 void
69 Grid::compute_bounding_box () const
70 {
71         _bounding_box = boost::none;
72
73         if (_items.empty()) {
74                 _bounding_box_dirty = false;
75                 return;
76         }
77
78         add_child_bounding_boxes (!collapse_on_hide);
79
80         if (_bounding_box) {
81                 Rect r = _bounding_box.get();
82
83                 _bounding_box = r.expand (top_padding + outline_width() + top_margin,
84                                           right_padding + outline_width() + right_margin,
85                                           bottom_padding + outline_width() + bottom_margin,
86                                           left_padding + outline_width() + left_margin);
87         }
88
89         _bounding_box_dirty = false;
90 }
91
92 void
93 Grid::set_spacing (double s)
94 {
95         spacing = s;
96 }
97
98 void
99 Grid::set_padding (double t, double r, double b, double l)
100 {
101         double last = t;
102
103         top_padding = t;
104
105         if (r >= 0) {
106                 last = r;
107         }
108         right_padding = last;
109         if (b >= 0) {
110                 last = b;
111         }
112         bottom_padding = last;
113         if (l >= 0) {
114                 last = l;
115         }
116         left_padding = last;
117 }
118
119 void
120 Grid::set_margin (double t, double r, double b, double l)
121 {
122         double last = t;
123         top_margin = t;
124         if (r >= 0) {
125                 last = r;
126         }
127         right_margin = last;
128         if (b >= 0) {
129                 last = b;
130         }
131         bottom_margin = last;
132         if (l >= 0) {
133                 last = l;
134         }
135         left_margin = last;
136 }
137
138 void
139 Grid::reset_self ()
140 {
141         if (_bounding_box_dirty) {
142                 compute_bounding_box ();
143         }
144
145         if (!_bounding_box) {
146                 self->hide ();
147                 return;
148         }
149
150         Rect r (_bounding_box.get());
151
152         /* XXX need to shrink by margin */
153
154         self->set (r);
155 }
156
157 void
158 Grid::reposition_children ()
159 {
160         Duple previous_edge (0, 0);
161         Distance largest_width = 0;
162         Distance largest_height = 0;
163
164         if (homogenous) {
165
166                 for (std::list<Item*>::iterator i = _items.begin(); ++i != _items.end(); ++i) {
167                         boost::optional<Rect> bb = (*i)->bounding_box();
168                         if (bb) {
169                                 largest_height = std::max (largest_height, bb.get().height());
170                                 largest_width = std::max (largest_width, bb.get().width());
171                         }
172                 }
173         }
174
175         for (std::list<Item*>::iterator i = _items.begin(); ++i != _items.end(); ++i) {
176
177         }
178
179         _bounding_box_dirty = true;
180         reset_self ();
181 }
182
183 void
184 Grid::place (Item* i, Duple at)
185 {
186
187 }
188
189 void
190 Grid::child_changed ()
191 {
192         /* catch visibility and size changes */
193
194         Item::child_changed ();
195         reposition_children ();
196 }
197
198 void
199 Grid::set_collapse_on_hide (bool yn)
200 {
201         if (collapse_on_hide != yn) {
202                 collapse_on_hide = yn;
203                 reposition_children ();
204         }
205 }