Zoom session when the mouse pointer is moved up and down during a playhead drag.
[ardour2.git] / gtk2_ardour / export_multiplicator.cc
blobba5a2a667d298bb354bfefd1d7cc2f94e66891ca
1 /* This file is not used at the moment. It includes code related to export a
2 * multiplication graph system that can be used together with the code in
3 * libs/ardour/export_multiplication.cc and libs/ardour/ardour/export_multiplication.h
4 * - Sakari Bergen 6.8.2008 -
5 */
7 /*
8 Copyright (C) 2008 Paul Davis
9 Author: Sakari Bergen
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "export_multiplicator.h"
29 #include <cassert>
31 #include "pbd/compose.h"
33 #include "i18n.h"
35 using namespace ARDOUR;
36 using namespace PBD;
38 #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
40 ExportMultiplicator::ExportMultiplicator () :
41 graph (0)
43 add (table);
46 ExportMultiplicator::~ExportMultiplicator ()
49 void
50 ExportMultiplicator::set_manager (boost::shared_ptr<ARDOUR::ExportProfileManager> _manager)
52 manager = _manager;
53 manager->GraphChanged.connect (sigc::mem_fun (*this, &ExportMultiplicator::redraw));
55 redraw();
58 void
59 ExportMultiplicator::redraw ()
61 if (!manager) { return; }
63 graph = &manager->get_graph();
65 /* Empty table */
67 table.foreach (sigc::mem_fun (table, &Gtk::Table::remove));
68 widget_map.clear();
70 /* Calculate table dimensions */
72 uint32_t max_width = 0;
73 GraphLevel max_level = NoLevel;
75 if (graph->timespans.size() > max_width) {
76 max_width = graph->timespans.size();
77 max_level = Timespans;
80 if (graph->channel_configs.size() > max_width) {
81 max_width = graph->channel_configs.size();
82 max_level = ChannelConfigs;
85 if (graph->formats.size() > max_width) {
86 max_width = graph->formats.size();
87 max_level = Formats;
90 if (graph->filenames.size() > max_width) {
91 max_width = graph->filenames.size();
92 max_level = Filenames;
95 table.resize (4, max_width);
97 std::cout << "Table width: " << max_width << std::endl;
99 /* Fill table */
101 for (list<ExportProfileManager::TimespanNodePtr>::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) {
102 draw_timespan (*it, get_bounds (it->get(), Timespans, max_level));
105 for (list<ExportProfileManager::ChannelConfigNodePtr>::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) {
106 draw_channel_config (*it, get_bounds (it->get(), ChannelConfigs, max_level));
109 for (list<ExportProfileManager::FormatNodePtr>::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) {
110 draw_format (*it, get_bounds (it->get(), Formats, max_level));
113 for (list<ExportProfileManager::FilenameNodePtr>::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) {
114 draw_filename (*it, get_bounds (it->get(), Filenames, max_level));
117 show_all_children ();
120 std::pair<uint32_t, uint32_t>
121 ExportMultiplicator::get_bounds (ARDOUR::ExportProfileManager::GraphNode * node, GraphLevel current_level, GraphLevel max_level) const
123 assert (current_level != NoLevel && max_level != NoLevel && graph);
125 uint32_t left_bound = 0;
126 uint32_t right_bound = 0;
128 bool left_bound_found = false;
130 bool (ExportProfileManager::GraphNode::*relation_func) (ExportProfileManager::GraphNode const *) const;
131 if (max_level < current_level) {
132 std::cout << "using 'is_ancestor_of'" << std::endl;
133 relation_func = &ExportProfileManager::GraphNode::is_ancestor_of;
134 } else if (max_level > current_level) {
135 std::cout << "using 'is_descendant_of'" << std::endl;
136 relation_func = &ExportProfileManager::GraphNode::is_descendant_of;
137 } else {
138 std::cout << "using 'equals'" << std::endl;
139 relation_func = &ExportProfileManager::GraphNode::equals;
142 switch (max_level) {
143 case Timespans:
144 for (list<ExportProfileManager::TimespanNodePtr>::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) {
145 if (CALL_MEMBER_FN(**it, relation_func) (node)) {
146 left_bound_found = true;
147 } else if (!left_bound_found) {
148 ++left_bound;
151 if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
152 break;
153 } else {
154 ++right_bound;
157 break;
159 case ChannelConfigs:
160 for (list<ExportProfileManager::ChannelConfigNodePtr>::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) {
161 if (CALL_MEMBER_FN(**it, relation_func) (node)) {
162 left_bound_found = true;
163 } else if (!left_bound_found) {
164 ++left_bound;
167 if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
168 break;
169 } else {
170 ++right_bound;
173 break;
175 case Formats:
176 for (list<ExportProfileManager::FormatNodePtr>::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) {
177 if (CALL_MEMBER_FN(**it, relation_func) (node)) {
178 left_bound_found = true;
179 } else if (!left_bound_found) {
180 ++left_bound;
183 if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
184 break;
185 } else {
186 ++right_bound;
189 break;
191 case Filenames:
192 for (list<ExportProfileManager::FilenameNodePtr>::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) {
193 if (CALL_MEMBER_FN(**it, relation_func) (node)) {
194 std::cout << "filename relation check returned true" << std::endl;
195 left_bound_found = true;
196 } else if (!left_bound_found) {
197 std::cout << "filename relation check returned false" << std::endl;
198 ++left_bound;
201 if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) {
202 break;
203 } else {
204 ++right_bound;
207 break;
209 case NoLevel:
210 // Not reached !
211 break;
214 return std::pair<uint32_t, uint32_t> (left_bound, right_bound);
217 void
218 ExportMultiplicator::draw_timespan (ARDOUR::ExportProfileManager::TimespanNodePtr node, std::pair<uint32_t, uint32_t> bounds)
220 ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Timespan %1", node->id()), manager, node.get()));
221 get_hbox (TablePosition (bounds.first, bounds.second, Timespans))->pack_end (*button, true, true);
224 void
225 ExportMultiplicator::draw_channel_config (ARDOUR::ExportProfileManager::ChannelConfigNodePtr node, std::pair<uint32_t, uint32_t> bounds)
227 ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Channel config %1", node->id()), manager, node.get()));
228 get_hbox (TablePosition (bounds.first, bounds.second, ChannelConfigs))->pack_end (*button, true, true);
231 void
232 ExportMultiplicator::draw_format (ARDOUR::ExportProfileManager::FormatNodePtr node, std::pair<uint32_t, uint32_t> bounds)
234 ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Format %1", node->id()), manager, node.get()));
235 get_hbox (TablePosition (bounds.first, bounds.second, Formats))->pack_end (*button, true, true);
238 void
239 ExportMultiplicator::draw_filename (ARDOUR::ExportProfileManager::FilenameNodePtr node, std::pair<uint32_t, uint32_t> bounds)
241 ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Filename %1", node->id()), manager, node.get()));
242 get_hbox (TablePosition (bounds.first, bounds.second, Filenames))->pack_end (*button, true, true);
245 boost::shared_ptr<Gtk::HBox>
246 ExportMultiplicator::get_hbox (TablePosition position)
248 WidgetMap::iterator it = widget_map.find (position);
249 if (it != widget_map.end()) { return it->second; }
251 boost::shared_ptr<Gtk::HBox> widget = widget_map.insert (WidgetPair (position, boost::shared_ptr<Gtk::HBox> (new Gtk::HBox ()))).first->second;
252 table.attach (*widget, position.left, position.right, position.row - 1, position.row);
254 return widget;
257 ExportMultiplicator::ButtonWidget::ButtonWidget (std::string name, boost::shared_ptr<ExportProfileManager> m, ExportProfileManager::GraphNode * node) :
258 label (name),
259 node (node),
260 split_position (0.5)
262 manager = m;
264 menu_actions = Gtk::ActionGroup::create();
265 menu_actions->add (Gtk::Action::create ("Split", _("_Split here")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::split));
266 menu_actions->add (Gtk::Action::create ("Remove", _("_Remove")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::remove));
268 ui_manager = Gtk::UIManager::create();
269 ui_manager->insert_action_group (menu_actions);
271 std::string ui_info =
272 "<ui>"
273 " <popup name='PopupMenu'>"
274 " <menuitem action='Split'/>"
275 " <menuitem action='Remove'/>"
276 " </popup>"
277 "</ui>";
279 ui_manager->add_ui_from_string (ui_info);
280 menu = dynamic_cast<Gtk::Menu*> (ui_manager->get_widget ("/PopupMenu"));
282 add_events (Gdk::BUTTON_PRESS_MASK);
283 signal_button_press_event ().connect (sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::on_button_press_event));
285 modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000"));
286 set_border_width (1);
287 vbox.pack_start (label, true, true, 4);
288 add (vbox);
291 bool
292 ExportMultiplicator::ButtonWidget::on_button_press_event (GdkEventButton* event)
294 if(event->type != GDK_BUTTON_PRESS) { return false; }
295 if (event->button == 1) {
296 node->select (!node->selected ());
298 if (node->selected ()) {
299 unset_bg (Gtk::STATE_NORMAL);
300 modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#194756"));
301 } else {
302 unset_bg (Gtk::STATE_NORMAL);
303 modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000"));
306 return true;
308 } else if (event->button == 3) {
309 int x, y;
310 get_pointer (x, y);
311 split_position = (float) x / get_width();
313 menu->popup (event->button, event->time);
314 return true;
317 return false;
320 void
321 ExportMultiplicator::ButtonWidget::split ()
323 manager->split_node (node, split_position);
326 void
327 ExportMultiplicator::ButtonWidget::remove ()
329 manager->remove_node (node);