/* This file is not used at the moment. It includes code related to export a * multiplication graph system that can be used together with the code in * libs/ardour/export_multiplication.cc and libs/ardour/ardour/export_multiplication.h * - Sakari Bergen 6.8.2008 - */ /* Copyright (C) 2008 Paul Davis Author: Sakari Bergen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "export_multiplicator.h" #include #include "pbd/compose.h" #include "i18n.h" using namespace ARDOUR; using namespace PBD; #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) ExportMultiplicator::ExportMultiplicator () : graph (0) { add (table); } ExportMultiplicator::~ExportMultiplicator () {} void ExportMultiplicator::set_manager (boost::shared_ptr _manager) { manager = _manager; manager->GraphChanged.connect (sigc::mem_fun (*this, &ExportMultiplicator::redraw)); redraw(); } void ExportMultiplicator::redraw () { if (!manager) { return; } graph = &manager->get_graph(); /* Empty table */ table.foreach (sigc::mem_fun (table, &Gtk::Table::remove)); widget_map.clear(); /* Calculate table dimensions */ uint32_t max_width = 0; GraphLevel max_level = NoLevel; if (graph->timespans.size() > max_width) { max_width = graph->timespans.size(); max_level = Timespans; } if (graph->channel_configs.size() > max_width) { max_width = graph->channel_configs.size(); max_level = ChannelConfigs; } if (graph->formats.size() > max_width) { max_width = graph->formats.size(); max_level = Formats; } if (graph->filenames.size() > max_width) { max_width = graph->filenames.size(); max_level = Filenames; } table.resize (4, max_width); std::cout << "Table width: " << max_width << std::endl; /* Fill table */ for (list::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) { draw_timespan (*it, get_bounds (it->get(), Timespans, max_level)); } for (list::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) { draw_channel_config (*it, get_bounds (it->get(), ChannelConfigs, max_level)); } for (list::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) { draw_format (*it, get_bounds (it->get(), Formats, max_level)); } for (list::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) { draw_filename (*it, get_bounds (it->get(), Filenames, max_level)); } show_all_children (); } std::pair ExportMultiplicator::get_bounds (ARDOUR::ExportProfileManager::GraphNode * node, GraphLevel current_level, GraphLevel max_level) const { assert (current_level != NoLevel && max_level != NoLevel && graph); uint32_t left_bound = 0; uint32_t right_bound = 0; bool left_bound_found = false; bool (ExportProfileManager::GraphNode::*relation_func) (ExportProfileManager::GraphNode const *) const; if (max_level < current_level) { std::cout << "using 'is_ancestor_of'" << std::endl; relation_func = &ExportProfileManager::GraphNode::is_ancestor_of; } else if (max_level > current_level) { std::cout << "using 'is_descendant_of'" << std::endl; relation_func = &ExportProfileManager::GraphNode::is_descendant_of; } else { std::cout << "using 'equals'" << std::endl; relation_func = &ExportProfileManager::GraphNode::equals; } switch (max_level) { case Timespans: for (list::const_iterator it = graph->timespans.begin(); it != graph->timespans.end(); ++it) { if (CALL_MEMBER_FN(**it, relation_func) (node)) { left_bound_found = true; } else if (!left_bound_found) { ++left_bound; } if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) { break; } else { ++right_bound; } } break; case ChannelConfigs: for (list::const_iterator it = graph->channel_configs.begin(); it != graph->channel_configs.end(); ++it) { if (CALL_MEMBER_FN(**it, relation_func) (node)) { left_bound_found = true; } else if (!left_bound_found) { ++left_bound; } if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) { break; } else { ++right_bound; } } break; case Formats: for (list::const_iterator it = graph->formats.begin(); it != graph->formats.end(); ++it) { if (CALL_MEMBER_FN(**it, relation_func) (node)) { left_bound_found = true; } else if (!left_bound_found) { ++left_bound; } if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) { break; } else { ++right_bound; } } break; case Filenames: for (list::const_iterator it = graph->filenames.begin(); it != graph->filenames.end(); ++it) { if (CALL_MEMBER_FN(**it, relation_func) (node)) { std::cout << "filename relation check returned true" << std::endl; left_bound_found = true; } else if (!left_bound_found) { std::cout << "filename relation check returned false" << std::endl; ++left_bound; } if (left_bound_found && !CALL_MEMBER_FN(**it, relation_func) (node)) { break; } else { ++right_bound; } } break; case NoLevel: // Not reached ! break; } return std::pair (left_bound, right_bound); } void ExportMultiplicator::draw_timespan (ARDOUR::ExportProfileManager::TimespanNodePtr node, std::pair bounds) { ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Timespan %1", node->id()), manager, node.get())); get_hbox (TablePosition (bounds.first, bounds.second, Timespans))->pack_end (*button, true, true); } void ExportMultiplicator::draw_channel_config (ARDOUR::ExportProfileManager::ChannelConfigNodePtr node, std::pair bounds) { ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Channel config %1", node->id()), manager, node.get())); get_hbox (TablePosition (bounds.first, bounds.second, ChannelConfigs))->pack_end (*button, true, true); } void ExportMultiplicator::draw_format (ARDOUR::ExportProfileManager::FormatNodePtr node, std::pair bounds) { ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Format %1", node->id()), manager, node.get())); get_hbox (TablePosition (bounds.first, bounds.second, Formats))->pack_end (*button, true, true); } void ExportMultiplicator::draw_filename (ARDOUR::ExportProfileManager::FilenameNodePtr node, std::pair bounds) { ButtonWidget * button = Gtk::manage (new ButtonWidget (string_compose ("Filename %1", node->id()), manager, node.get())); get_hbox (TablePosition (bounds.first, bounds.second, Filenames))->pack_end (*button, true, true); } boost::shared_ptr ExportMultiplicator::get_hbox (TablePosition position) { WidgetMap::iterator it = widget_map.find (position); if (it != widget_map.end()) { return it->second; } boost::shared_ptr widget = widget_map.insert (WidgetPair (position, boost::shared_ptr (new Gtk::HBox ()))).first->second; table.attach (*widget, position.left, position.right, position.row - 1, position.row); return widget; } ExportMultiplicator::ButtonWidget::ButtonWidget (std::string name, boost::shared_ptr m, ExportProfileManager::GraphNode * node) : label (name), node (node), split_position (0.5) { manager = m; menu_actions = Gtk::ActionGroup::create(); menu_actions->add (Gtk::Action::create ("Split", _("_Split here")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::split)); menu_actions->add (Gtk::Action::create ("Remove", _("_Remove")), sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::remove)); ui_manager = Gtk::UIManager::create(); ui_manager->insert_action_group (menu_actions); std::string ui_info = "" " " " " " " " " ""; ui_manager->add_ui_from_string (ui_info); menu = dynamic_cast (ui_manager->get_widget ("/PopupMenu")); add_events (Gdk::BUTTON_PRESS_MASK); signal_button_press_event ().connect (sigc::mem_fun (*this, &ExportMultiplicator::ButtonWidget::on_button_press_event)); modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000")); set_border_width (1); vbox.pack_start (label, true, true, 4); add (vbox); } bool ExportMultiplicator::ButtonWidget::on_button_press_event (GdkEventButton* event) { if(event->type != GDK_BUTTON_PRESS) { return false; } if (event->button == 1) { node->select (!node->selected ()); if (node->selected ()) { unset_bg (Gtk::STATE_NORMAL); modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#194756")); } else { unset_bg (Gtk::STATE_NORMAL); modify_bg (Gtk::STATE_NORMAL, Gdk::Color ("#0000")); } return true; } else if (event->button == 3) { int x, y; get_pointer (x, y); split_position = (float) x / get_width(); menu->popup (event->button, event->time); return true; } return false; } void ExportMultiplicator::ButtonWidget::split () { manager->split_node (node, split_position); } void ExportMultiplicator::ButtonWidget::remove () { manager->remove_node (node); }