Fix Mixbus action fc83d044f8 & 65bda27d4 rebase ordering
[ardour.git] / gtk2_ardour / stripable_treemodel.cc
1 /* Copyright (C) 2017 Paul Davis
2  *   based on gtkmm example Copyright (C) 2002 gtkmm development team
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 version 2
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17
18 #include <iostream>
19
20 #include "ardour/session.h"
21 #include "ardour/types.h"
22
23 #include "axis_provider.h"
24 #include "stripable_treemodel.h"
25
26 using namespace ARDOUR;
27
28 StripableTreeModel::Glue::Glue (boost::shared_ptr<Stripable> s)
29         : stripable (s)
30 {
31 }
32
33 StripableTreeModel::StripableTreeModel (AxisViewProvider& avp)
34         : Glib::ObjectBase( typeid(StripableTreeModel) ) //register a custom GType.
35         , Glib::Object() //The custom GType is actually registered here.
36         , axis_view_provider (avp)
37 {
38         n_columns = columns.size();
39 }
40
41 void
42 StripableTreeModel::set_session (Session& s)
43 {
44         _session = &s;
45 }
46
47 StripableTreeModel::~StripableTreeModel()
48 {
49 }
50
51 Glib::RefPtr<StripableTreeModel>
52 StripableTreeModel::create (AxisViewProvider& avp)
53 {
54         return Glib::RefPtr<StripableTreeModel> (new StripableTreeModel (avp));
55 }
56
57 Gtk::TreeModelFlags
58 StripableTreeModel::get_flags_vfunc() const
59 {
60         return Gtk::TREE_MODEL_LIST_ONLY;
61 }
62
63 int
64 StripableTreeModel::get_n_columns_vfunc() const
65 {
66         return n_columns;
67 }
68
69 GType
70 StripableTreeModel::get_column_type_vfunc (int index) const
71 {
72         if (index <= n_columns) {
73                 return columns.types()[index];
74         }
75         return 0;
76 }
77
78 void
79 StripableTreeModel::get_value_vfunc (const TreeModel::iterator& iter, int column, Glib::ValueBase& value) const
80 {
81         if (!_session) {
82                 return;
83         }
84
85         if (column > n_columns) {
86                 return;
87         }
88
89         const Glue* glue = (const Glue*)iter.gobj()->user_data;
90         boost::shared_ptr<Stripable> iter_stripable = glue->stripable.lock();
91
92         if (!iter_stripable) {
93                 return;
94         }
95
96         switch (column) {
97         case 0:
98                 return text_value (iter_stripable, value);
99         }
100 }
101
102 void
103 StripableTreeModel::text_value (boost::shared_ptr<Stripable> stripable, Glib::ValueBase& value) const
104 {
105         StringColumn::ValueType val;
106         val.set (stripable->name());
107         value = val;
108 }
109
110 bool
111 StripableTreeModel::iter_next_vfunc (const iterator& iter, iterator& iter_next) const
112 {
113         if (!_session) {
114                 return false;
115         }
116
117         const Glue* glue = (const Glue*)iter.gobj()->user_data;
118         boost::shared_ptr<Stripable> iter_stripable = glue->stripable.lock();
119
120         if (!iter_stripable) {
121                 return false;
122         }
123
124         //initialize the next iterator:
125         iter_next = iterator();
126
127         StripableList sl;
128         _session->get_stripables (sl);
129         if (sl.empty()) {
130                 return false;
131         }
132         sl.sort (Stripable::Sorter());
133
134         for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
135
136                 if (*s == iter_stripable) {
137                         ++s;
138                         if (s != sl.end()) {
139                                 Glue* new_glue = new Glue (iter_stripable);
140                                 iter_next.gobj()->user_data = (void*)new_glue;
141                                 remember_glue_item (new_glue);
142                                 return true; //success
143                         }
144                         break;
145                 }
146         }
147
148         return false; //There is no next row.
149 }
150
151 bool
152 StripableTreeModel::iter_children_vfunc(const iterator& parent, iterator& iter) const
153 {
154         return false;
155 }
156
157 bool
158 StripableTreeModel::iter_has_child_vfunc(const iterator& iter) const
159 {
160         return false;
161 }
162
163 int
164 StripableTreeModel::iter_n_children_vfunc(const iterator& iter) const
165 {
166         return 0;
167 }
168
169 int
170 StripableTreeModel::iter_n_root_children_vfunc() const
171 {
172         if (_session) {
173                 StripableList sl;
174                 _session->get_stripables (sl);
175                 return sl.size();
176         }
177         return 0;
178 }
179
180 bool
181 StripableTreeModel::iter_nth_child_vfunc(const iterator& parent, int /* n */, iterator& iter) const
182 {
183         iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
184         return false; //There are no children.
185 }
186
187 bool
188 StripableTreeModel::iter_nth_root_child_vfunc(int n, iterator& iter) const
189 {
190         iter = iterator(); //clear the input parameter.
191         if (!_session) {
192                 return false;
193         }
194
195         StripableList sl;
196         _session->get_stripables (sl);
197
198         if (sl.empty()) {
199                 return false;
200         }
201
202         sl.sort (Stripable::Sorter());
203
204         StripableList::const_iterator s;
205
206         for (s = sl.begin(); s != sl.end() && n > 0; ++s, --n);
207
208         if (s != sl.end()) {
209                 Glue* new_glue = new Glue (*s);
210                 iter.gobj()->user_data = new_glue;
211                 remember_glue_item (new_glue);
212                 return true;
213         }
214
215         return false; //There are no children.
216 }
217
218 bool
219 StripableTreeModel::iter_parent_vfunc(const iterator& child, iterator& iter) const
220 {
221         iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
222         return false; //There are no children, so no parents.
223 }
224
225 Gtk::TreeModel::Path
226 StripableTreeModel::get_path_vfunc(const iterator& /* iter */) const
227 {
228         //TODO:
229         return Path();
230 }
231
232 bool
233 StripableTreeModel::get_iter_vfunc (const Path& path, iterator& iter) const
234 {
235         unsigned sz = path.size();
236
237         if (!sz || sz > 1) {
238                 /* path must refer to something, but not children since we
239                    don't do children.
240                 */
241                 iter = iterator(); //Set is as invalid, as the TreeModel documentation says that it should be.
242                 return false;
243         }
244
245         return iter_nth_root_child_vfunc (path[0], iter);
246 }
247
248 bool
249 StripableTreeModel::iter_is_valid(const iterator& iter) const
250 {
251         const Glue* glue = (const Glue*)iter.gobj()->user_data;
252
253         if (!glue->stripable.lock()) {
254                 return false;
255         }
256
257         return Gtk::TreeModel::iter_is_valid(iter);
258 }
259
260 void
261 StripableTreeModel::remember_glue_item (Glue* item) const
262 {
263         glue_list.insert (item);
264 }