diff options
-rw-r--r-- | gtk2_ardour/SConscript | 11 | ||||
-rw-r--r-- | gtk2_ardour/audio_time_axis.cc | 8 | ||||
-rw-r--r-- | gtk2_ardour/connection_editor.cc | 179 | ||||
-rw-r--r-- | gtk2_ardour/connection_editor.h | 7 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_edit_groups.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/io_selector.cc | 355 | ||||
-rw-r--r-- | gtk2_ardour/io_selector.h | 35 | ||||
-rw-r--r-- | gtk2_ardour/redirect_box.cc | 348 | ||||
-rw-r--r-- | gtk2_ardour/redirect_box.h | 40 |
10 files changed, 516 insertions, 470 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 79259421e8..d55b151e72 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -28,6 +28,7 @@ gtkardour.Merge ([ libraries['midi++2'], libraries['pbd3'], libraries['gtkmm2'], + libraries['glib2'], libraries['libgnomecanvas2'], libraries['libgnomecanvasmm'], libraries['sysmidi'], @@ -48,6 +49,10 @@ gtkardour.Merge ([ if gtkardour['VST']: gtkardour.Merge ([ libraries['fst']]) +skipped_files=Split(""" +connection_editor.cc +""") + gtkardour_files=Split(""" about.cc actions.cc @@ -75,7 +80,6 @@ canvas-simplerect.c simplerect.cc canvas-waveview.c waveview.cc -connection_editor.cc crossfade_edit.cc crossfade_view.cc curvetest.cc @@ -167,6 +171,10 @@ mtest_files=Split(""" mtest.cc """) +itest_files=Split(""" +itest.cc +""") + extra_sources = [] vst_files = [ 'vst_pluginui.cc' ] @@ -187,6 +195,7 @@ executable = 'ardour.bin' ardour = gtkardour.Program(target = executable, source = gtkardour_files + extra_sources) mtest = gtkardour.Program(target = 'mtest', source = mtest_files) +itest = gtkardour.Program(target = 'itest', source = itest_files) Default(ardour) diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc index f8a460f778..e4155682fe 100644 --- a/gtk2_ardour/audio_time_axis.cc +++ b/gtk2_ardour/audio_time_axis.cc @@ -1204,10 +1204,10 @@ AudioTimeAxisView::add_gain_automation_child () line = new AutomationGainLine ("automation gain", _session, *gain_track, - gain_track->canvas_display, - _route.gain_automation_curve(), - PublicEditor::canvas_control_point_event, - PublicEditor::canvas_line_event); + gain_track->canvas_display, + _route.gain_automation_curve(), + slot (mem_fun (ed, &PublicEditor::canvas_control_point_event)), + slot (mem_fun (ed, &PublicEditor::canvas_line_event))); line->set_line_color (color_map[cAutomationLine]); diff --git a/gtk2_ardour/connection_editor.cc b/gtk2_ardour/connection_editor.cc index 56c7435cc3..0b67ac8477 100644 --- a/gtk2_ardour/connection_editor.cc +++ b/gtk2_ardour/connection_editor.cc @@ -17,6 +17,9 @@ $Id$ */ + +#include <map> +#include <vector> #include <stdint.h> #include <gtkmm2ext/gtk_ui.h> @@ -134,15 +137,26 @@ ConnectionEditor::ConnectionEditor () right_vbox.set_border_width (5); right_vbox.pack_start (port_and_selector_box); + input_connection_model = ListStore::create (connection_columns); + output_connection_model = ListStore::create (connection_columns); + + input_connection_display.set_model (input_connection_model); + output_connection_display.set_model (output_connection_model); + + input_connection_display.append_column (_("Connections"), connection_columns.name); + output_connection_display.append_column (_("Connections"), connection_columns.name); + input_connection_display.get_selection()->set_mode(Gtk::SELECTION_SINGLE); input_connection_display.set_size_request (80, -1); input_connection_display.set_name ("ConnectionEditorConnectionList"); - input_connection_display.get_selection()->signal_changed().connect (bind (mem_fun(*this, &ConnectionEditor::connection_selection_changed), input_connection_display)); output_connection_display.get_selection()->set_mode(Gtk::SELECTION_SINGLE); output_connection_display.set_size_request (80, -1); output_connection_display.set_name ("ConnectionEditorConnectionList"); - output_connection_display.get_selection()->signal_changed().connect (bind (mem_fun(*this, &ConnectionEditor::connection_selection_changed), output_connection_display)); + + input_connection_display.get_selection()->signal_changed().connect (bind (mem_fun(*this, &ConnectionEditor::selection_changed), &input_connection_display)); + output_connection_display.get_selection()->signal_changed().connect (bind (mem_fun(*this, &ConnectionEditor::selection_changed), &output_connection_display)); + input_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); output_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); @@ -182,8 +196,9 @@ ConnectionEditor::ConnectionEditor () set_title (_("ardour: connections")); add (main_vbox); - delete_event.connect (bind (ptr_fun (just_hide_it), reinterpret_cast<Window *> (this))); - + // GTK2FIX + // signal_delete_event.connect (bind (ptr_fun (just_hide_it), reinterpret_cast<Window *> (this))); + clear_button.signal_clicked().connect (mem_fun(*this, &ConnectionEditor::clear)); add_port_button.signal_clicked().connect (mem_fun(*this, &ConnectionEditor::add_port)); new_input_connection_button.signal_clicked().connect (bind (mem_fun(*this, &ConnectionEditor::new_connection), true)); @@ -238,11 +253,11 @@ ConnectionEditor::clear () } } -gint -ConnectionEditor::on_map (GdkEventAny *ev) +void +ConnectionEditor::on_map () { refill_connection_display (); - return Window::on_map (ev); + Window::on_map (); } void @@ -253,51 +268,42 @@ ConnectionEditor::add_connection (ARDOUR::Connection *connection) if (dynamic_cast<InputConnection *> (connection)) { if (push_at_front) { - row = *(input_connection_model.prepend()); + row = *(input_connection_model->prepend()); } else { - row = *(input_connection_model.append()); + row = *(input_connection_model->append()); } - row[input_connection_columns.connection] = connection; - row[input_connection_columns.name] = connection->name(); - - } else { + if (push_at_front) { - row = *(output_connection_model.prepend()); + row = *(output_connection_model->prepend()); } else { - row = *(output_connection_model.append()); + row = *(output_connection_model->append()); } - - row[output_connection_columns.connection] = connection; - row[output_connection_columns.name] = connection->name(); } + + row[connection_columns.connection] = connection; + row[connection_columns.name] = connection->name(); } void ConnectionEditor::remove_connection (ARDOUR::Connection *connection) { - TreeModel::Children rows; TreeModel::iterator i; + Glib::RefPtr<TreeModel> model = input_connection_model; - if (dynamic_cast<InputConnection *> (connection)) { - TreeModel::Children rows = input_connection_model->children(); - for (i = rows.begin(); i != rows.end(); ++i) { - if ((*i)[input_connection_columns.connection] == connection) { - rows.erase (i); - break; - } - } - } else { - TreeModel::Children rows = output_connection_model->children(); - for (i = rows.begin(); i != rows.end(); ++i) { - if ((*i)[output_connection_columns.connection] == connection) { - rows.erase (i); + if (dynamic_cast<InputConnection *> (connection) == 0) { + model = output_connection_model; + } + + TreeModel::Children rows = model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + if ((*i)[connection_columns.connection] == connection) { + // model->erase (i); break; - } } } - } void @@ -317,18 +323,19 @@ ConnectionEditor::add_connection_and_select (ARDOUR::Connection *connection) { add_connection (connection); - if (dynamic_cast<InputConnection *> (connection)) { - input_connection_display.rows().front().select (); - } else { - output_connection_display.rows().front().select (); - } + // GTK2FIX + // if (dynamic_cast<InputConnection *> (connection)) { + // input_connection_display.rows().front().select (); + // } else { + // output_connection_display.rows().front().select (); + //} } void ConnectionEditor::refill_connection_display () { - input_connection_display.set_model (0); - output_connection_display.set_model (0); + input_connection_display.set_model (Glib::RefPtr<TreeModel>(0)); + output_connection_display.set_model (Glib::RefPtr<TreeModel>(0)); input_connection_model.clear(); output_connection_model.clear(); @@ -345,17 +352,19 @@ ConnectionEditor::refill_connection_display () } void -ConnectionEditor::connection_selection_changed (TreeView& view, Glib::RefPtr<ListStore>& model) +ConnectionEditor::selection_changed (TreeView* view) { ARDOUR::Connection *old_current = current_connection; TreeIter iter; TreeModel::Path path; Glib::RefPtr<TreeView::Selection> selection = view->get_selection(); - + Glib::RefPtr<TreeModel> model = view->get_model(); + bool input = (view == &input_connection_display); + iter = model->get_iter (path); - current_connection = (*iter)[input_connection_columns.connection]; + current_connection = (*iter)[connection_columns.connection]; if (old_current != current_connection) { config_connection.disconnect (); @@ -368,7 +377,7 @@ ConnectionEditor::connection_selection_changed (TreeView& view, Glib::RefPtr<Lis connect_connection = current_connection->ConnectionsChanged.connect (bind (mem_fun(*this, &ConnectionEditor::connections_changed), input)); } - + display_connection_state (input); display_ports (); } @@ -393,9 +402,8 @@ ConnectionEditor::display_ports () } using namespace Notebook_Helpers; - using namespace CList_Helpers; - typedef map<string,vector<pair<string,string> > > PortMap; + typedef std::map<std::string,std::vector<std::pair<std::string,std::string> > > PortMap; PortMap portmap; const char **ports; PageList& pages = notebook.pages(); @@ -403,7 +411,7 @@ ConnectionEditor::display_ports () vector<string> rowdata; bool for_input; - current_page = notebook.get_current_page_num (); + current_page = notebook.get_current_page (); pages.clear (); /* get relevant current JACK ports */ @@ -446,33 +454,35 @@ ConnectionEditor::display_ports () for (i = portmap.begin(); i != portmap.end(); ++i) { Box *client_box = manage (new VBox); - Gtk::CList *client_port_display = manage (new Gtk::CList (1)); + Gtk::CTreeView *display = manage (new Gtk::TreeView); + RefPtr<TreeModel> model = TreeModel::create (columns); ScrolledWindow *scroller = manage (new ScrolledWindow); - scroller->add (*client_port_display); - scroller->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - - client_box->pack_start (*scroller); - - client_port_display->set_selection_mode (GTK_SELECTION_BROWSE); - client_port_display->set_name ("ConnectionEditorList"); + display->set_selection_mode (GTK_SELECTION_SINGLE); + display->set_name ("ConnectionEditorList"); for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) { - rowdata.clear (); - rowdata.push_back (s->first); - client_port_display->rows().push_back (rowdata); - client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free); + Row row = model->append (); + + row[displayed_name] = s->first; + row[full_name] = s->second; } - client_port_display->columns_autosize (); - client_port_display->select_row.connect (bind (mem_fun(*this, &ConnectionEditor::port_selection_handler), client_port_display)); + display->get_selection()->signal_changed().connect (bind (mem_fun(*this, &ConnectionEditor::port_selection_handler), display)); Label *tab_label = manage (new Label); tab_label->set_name ("ConnectionEditorNotebookTab"); tab_label->set_text ((*i).first); + display->set_model (model); + + scroller->add (*client_port_display); + scroller->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + client_box->pack_start (*scroller); + pages.push_back (TabElem (*client_box, *tab_label)); } @@ -569,12 +579,14 @@ ConnectionEditor::port_selection_changed (TreeView* tview) Glib::RefPtr<TreeView::Selection> sel = tview->get_selection(); TreeModel::iterator iter = sel->get_selected(); + if (!current_connection) { + return; + } + if (iter) { TreeModel::Row row = *iter; - string other_port_name = row[port_display_columns.name]; - } else { - selected_port = -1; - } + string other_port_name = row[port_display_columns.full_name]; + if (current_connection && selected_port >= 0) { current_connection->add_connection (selected_port, other_port_name); @@ -591,7 +603,7 @@ ConnectionEditor::add_port () } void -ConnectionEditor::port_button_press_event (GdkEventButton* ev, TreeView* tview) +ConnectionEditor::connection_port_button_press_event (GdkEventButton* ev, TreeView* tview) { LockMonitor lm (port_display_lock, __LINE__, __FILE__); @@ -678,28 +690,35 @@ ConnectionEditor::delete_connection () } gint -ConnectionEditor::port_button_event (GdkEventButton *ev, CList *clist) +ConnectionEditor::port_button_event (GdkEventButton *ev, Treeview* treeview) { int row, col; + TreeIter iter; + TreeModel::Path path; + TreeViewColumn* column; + int cellx; + int celly; if (current_connection == 0) { - return FALSE; + return false; } - if (clist->get_selection_info ((int) ev->x, (int) ev->y, &row, &col) == 0) { - return FALSE; + if (!(Keyboard::is_delete_event (ev))) { + return false; } - if (!(Keyboard::is_delete_event (ev))) { - return FALSE; + if (!treeview->get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { + return false; } - string port_name = clist->cell (row, col).get_text (); - int which_port = (intptr_t) clist->get_data ("port"); - - current_connection->remove_connection (which_port, port_name); + if ((iter = treeview->get_model()->get_iter (path))) { + /* path is valid */ + + string port_name = (*iter)[columns.full_name]; + int which_port = (intptr_t) treeview->get_data ("port"); - return TRUE; + current_connection->remove_connection (which_port, port_name); + } + + return true; } - - diff --git a/gtk2_ardour/connection_editor.h b/gtk2_ardour/connection_editor.h index 69b6b83577..1d6dd7d7fc 100644 --- a/gtk2_ardour/connection_editor.h +++ b/gtk2_ardour/connection_editor.h @@ -54,7 +54,7 @@ class ConnectionEditor : public ArdourDialog { void set_session (ARDOUR::Session *); protected: - bool on_map (GdkEventAny *); + void on_map (); private: ARDOUR::Connection *current_connection; @@ -71,8 +71,7 @@ class ConnectionEditor : public ArdourDialog { Gtk::TreeModelColumn<ARDOUR::Connection*> connection; }; - ConnectionDisplayModelColumns input_connection_columns; - ConnectionDisplayModelColumns output_connection_columns; + ConnectionDisplayModelColumns connection_columns; Glib::RefPtr<Gtk::ListStore> input_connection_model; Glib::RefPtr<Gtk::ListStore> output_connection_model; @@ -145,7 +144,7 @@ class ConnectionEditor : public ArdourDialog { void cancel (); void accept (); - void port_selection_handler (gint row, gint col, GdkEvent*, Gtk::TreeView*); + void selection_changed (Gtk::TreeView* display); void add_port (); void remove_port (int which_port); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index de945c4ad1..43812439c4 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -264,7 +264,7 @@ class Editor : public PublicEditor Width editor_mixer_strip_width; void show_editor_mixer (bool yn); void set_selected_mixer_strip (TimeAxisView&); - void unselect_strip_in_display (TimeAxisView* tv); + void unselect_strip_in_display (TimeAxisView& tv); void select_strip_in_display (TimeAxisView* tv); /* nudge is initiated by transport controls owned by ARDOUR_UI */ diff --git a/gtk2_ardour/editor_edit_groups.cc b/gtk2_ardour/editor_edit_groups.cc index 9e3df176f8..2153a2f90e 100644 --- a/gtk2_ardour/editor_edit_groups.cc +++ b/gtk2_ardour/editor_edit_groups.cc @@ -119,7 +119,6 @@ Editor::edit_group_list_button_clicked () gint Editor::edit_group_list_button_press_event (GdkEventButton* ev) { - RouteGroup* group; TreeIter iter; TreeModel::Path path; diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index ae2a63e202..9aec5be319 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -44,6 +44,7 @@ using namespace std; using namespace Gtk; +using namespace Glib; using namespace sigc; using namespace ARDOUR; @@ -76,8 +77,7 @@ IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can if (can_cancel) { button_box.pack_start (cancel_button); - } - else { + } else { cancel_button.hide(); } @@ -91,7 +91,7 @@ IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can rescan_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::rescan)); set_title (title); - set_position (Gtk::WIN_POS_MOUSE); + set_position (WIN_POS_MOUSE); add (vbox); signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window *> (this))); @@ -121,12 +121,11 @@ IOSelectorWindow::accept () hide (); } - -bool -IOSelectorWindow::on_map (GdkEventAny *ev) +void +IOSelectorWindow::on_map () { _selector.redisplay (); - return Window::on_map (ev); + Window::on_map (); } /************************* @@ -173,8 +172,8 @@ IOSelector::IOSelector (Session& sess, IO& ior, bool input) port_display_scroller.set_border_width (0); port_display_scroller.set_size_request (-1, 170); port_display_scroller.add (port_box); - port_display_scroller.set_policy (Gtk::POLICY_NEVER, - Gtk::POLICY_AUTOMATIC); + port_display_scroller.set_policy (POLICY_NEVER, + POLICY_AUTOMATIC); port_button_box.set_spacing (5); port_button_box.set_border_width (5); @@ -273,7 +272,6 @@ void IOSelector::rescan () { using namespace Notebook_Helpers; - using namespace CList_Helpers; typedef std::map<string,vector<pair<string,string> > > PortMap; PortMap portmap; @@ -282,7 +280,7 @@ IOSelector::rescan () gint current_page; vector<string> rowdata; - current_page = notebook.get_current_page_num (); + current_page = notebook.get_current_page (); pages.clear (); /* get relevant current JACK ports */ @@ -293,13 +291,21 @@ IOSelector::rescan () return; } + /* get relevant current JACK ports */ + + ports = session.engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input?JackPortIsOutput:JackPortIsInput); + + if (ports == 0) { + return; + } + /* find all the client names and group their ports into a list-by-client */ for (int n = 0; ports[n]; ++n) { pair<string,vector<pair<string,string> > > newpair; pair<string,string> strpair; - std::pair<PortMap::iterator,bool> result; + pair<PortMap::iterator,bool> result; string str = ports[n]; string::size_type pos; @@ -310,12 +316,6 @@ IOSelector::rescan () newpair.first = str.substr (0, pos); portname = str.substr (pos+1); - /* this may or may not succeed at actually inserting. - we don't care, however: we just want an iterator - that gives us either the inserted element or - the existing one with the same name. - */ - result = portmap.insert (newpair); strpair.first = portname; @@ -329,37 +329,41 @@ IOSelector::rescan () for (i = portmap.begin(); i != portmap.end(); ++i) { Box *client_box = manage (new VBox); - Gtk::CList *client_port_display = manage (new Gtk::CList (1)); + TreeView *display = manage (new TreeView); + RefPtr<ListStore> model = ListStore::create (port_display_columns); ScrolledWindow *scroller = manage (new ScrolledWindow); - scroller->add (*client_port_display); - scroller->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - - client_box->pack_start (*scroller); - - client_port_display->set_selection_mode (Gtk::SELECTION_BROWSE); - client_port_display->set_name ("IOSelectorList"); + display->set_model (model); + display->append_column (X_("notvisible"), port_display_columns.displayed_name); + display->set_headers_visible (false); + display->get_selection()->set_mode (SELECTION_SINGLE); + display->set_name ("IOSelectorList"); for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) { - rowdata.clear (); - rowdata.push_back (s->first); - client_port_display->rows().push_back (rowdata); - client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free); - } + TreeModel::Row row = *(model->append ()); - client_port_display->columns_autosize (); - client_port_display->select_row.connect (bind (mem_fun(*this, &IOSelector::port_selection_handler), client_port_display)); + row[port_display_columns.displayed_name] = s->first; + row[port_display_columns.full_name] = s->second; + } + display->get_selection()->signal_changed().connect + (bind (mem_fun(*this, &IOSelector::port_selection_changed), display)); + Label *tab_label = manage (new Label); tab_label->set_name ("IOSelectorNotebookTab"); tab_label->set_text ((*i).first); + scroller->add (*display); + scroller->set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC); + + client_box->pack_start (*scroller); + pages.push_back (TabElem (*client_box, *tab_label)); } - notebook.set_page (current_page); + notebook.set_current_page (current_page); notebook.signal_show().connect (bind (mem_fun (notebook, &Notebook::set_current_page), current_page)); selector_box.show_all (); } @@ -367,9 +371,8 @@ IOSelector::rescan () void IOSelector::display_ports () { - CList *clist = 0; - CList *firstclist = 0; - CList *selected_port_list = 0; + TreeView *firsttview = 0; + TreeView *selected_port_tview = 0; { LockMonitor lm (port_display_lock, __LINE__, __FILE__); @@ -382,9 +385,9 @@ IOSelector::display_ports () limit = io.n_outputs(); } - for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ) { + for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ) { - slist<CList *>::iterator tmp; + slist<TreeView *>::iterator tmp; tmp = i; ++tmp; @@ -396,107 +399,95 @@ IOSelector::display_ports () i = tmp; } + for (uint32_t n = 0; n < limit; ++n) { - const gchar *title[1]; + + TreeView* tview; + ScrolledWindow *scroller; string really_short_name; - - if (for_input) { - port = io.input (n); - } else { - port = io.output (n); - } - + /* we know there is '/' because we put it there */ really_short_name = port->short_name(); really_short_name = really_short_name.substr (really_short_name.find ('/') + 1); - title[0] = really_short_name.c_str(); - clist = new CList (1, title); - if (!firstclist) { - firstclist = clist; + tview = manage (new TreeView()); + RefPtr<ListStore> port_model = ListStore::create (port_display_columns); + + if (!firsttview) { + firsttview = tview; } - port_displays.insert (port_displays.end(), clist); - port_box.pack_start (*clist); - - clist->set_data (_("port"), port); - - /* XXX THIS IS A DIGUSTING AND DIRTY HACK, FORCED UPON US BECAUSE - GtkCList DOESN'T PROVIDE ANY WAY TO CONNECT TO BUTTON_PRESS_EVENTS - FOR THE COLUMN TITLE BUTTON. - */ - - clist->column(0).get_widget(); // force the column title button to be created - GtkButton *b = GTK_BUTTON(clist->gobj()->column[0].button); // no API to access this - Gtk::Button *B = Glib::wrap (b); // make C++ signal handling easier. + tview->set_model (port_model); + tview->append_column (really_short_name, port_display_columns.displayed_name); + tview->get_selection()->set_mode (SELECTION_SINGLE); + tview->set_data ("port", port); + tview->set_headers_visible (true); + tview->set_name ("IOSelectorPortList"); + + scroller = manage (new ScrolledWindow); + + scroller->add (*tview); + scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC); + + port_displays.insert (port_displays.end(), tview); + port_box.pack_start (*scroller); + + scroller->set_size_request (-1, 75); + + /* now fill the clist with the current connections */ + - clist->column_titles_show (); - clist->column_titles_active (); + const char **connections = port->get_connections (); + if (connections) { + for (uint32_t c = 0; connections[c]; ++c) { + TreeModel::Row row = *(port_model->append()); + row[port_display_columns.displayed_name] = connections[c]; + } + } + if (for_input) { - + if (io.input_maximum() == 1) { selected_port = port; - selected_port_list = clist; + selected_port_tview = tview; } else { if (port == selected_port) { - selected_port_list = clist; + selected_port_tview = tview; } } - - B->signal_button_release_event().connect - (bind (mem_fun(*this, &IOSelector::port_column_button_release), clist)); } else { if (io.output_maximum() == 1) { selected_port = port; - selected_port_list = clist; + selected_port_tview = tview; } else { if (port == selected_port) { - selected_port_list = clist; + selected_port_tview = tview; } } - - B->signal_button_release_event().connect - (bind (mem_fun(*this, &IOSelector::port_column_button_release), clist)); } - clist->set_name ("IOSelectorPortList"); - clist->set_selection_mode (Gtk::SELECTION_SINGLE); - clist->set_shadow_type (Gtk::SHADOW_IN); - clist->set_size_request (-1, 75); - - /* now fill the clist with the current connections */ - - const char **connections = port->get_connections (); - - if (connections) { - - for (uint32_t c = 0; connections[c]; ++c) { - - const gchar *txt[1]; - - txt[0] = connections[c]; - - clist->rows().push_back (txt); - } + TreeViewColumn* col = tview->get_column (0); + + col->set_clickable (true); - free (connections); - } + /* handle button events on the column header and within the treeview itself */ - clist->columns_autosize (); - clist->signal_button_release_event().connect (bind (mem_fun(*this, &IOSelector::connection_click), clist)); + col->get_widget()->signal_button_release_event().connect (bind (mem_fun(*this, &IOSelector::port_column_button_release), tview)); + tview->signal_button_release_event().connect (bind (mem_fun(*this, &IOSelector::connection_button_release), tview)); } port_box.show_all (); - if (selected_port_list) { - selected_port_list->click_column(0); - selected_port_list->set_name ("IOSelectorPortListSelected"); - for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { - if (*i != selected_port_list) { + if (selected_port_tview) { + // GTK2FIX + // selected_port_tview->click_column(0); + selected_port_tview->set_name ("IOSelectorPortListSelected"); + for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + if (*i != selected_port_tview) { (*i)->set_name ("IOSelectorPortList"); (*i)->queue_draw (); } @@ -507,26 +498,30 @@ IOSelector::display_ports () } } - if (selected_port_list) { - select_clist (selected_port_list); - } else if (firstclist) { + if (selected_port_tview) { + select_treeview (selected_port_tview); + } else if (firsttview) { // select first - select_clist (firstclist); + select_treeview (firsttview); } } void -IOSelector::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *clist) +IOSelector::port_selection_changed (TreeView* treeview) { - using namespace CList_Helpers; + TreeModel::iterator i = treeview->get_selection()->get_selected(); int status; - if (selected_port == 0) { + if (!i) { return; } - string other_port_name = (char *) clist->rows()[row].get_data(); + if (selected_port == 0) { + return; + } + ustring other_port_name = (*i)[port_display_columns.full_name]; + if (for_input) { if ((status = io.connect_input (selected_port, other_port_name, this)) == 0) { Port *p = session.engine().get_port_by_name (other_port_name); @@ -537,7 +532,7 @@ IOSelector::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList } if (status == 0) { - select_next_clist (); + select_next_treeview (); } } @@ -556,15 +551,12 @@ IOSelector::add_port () if (for_input) { - try { - io.add_input_port ("", this); } catch (AudioEngine::PortRegistrationFailure& err) { - ArdourMessage msg (0, X_("noport dialog"), - _("There are no more JACK ports available.")); + ArdourMessage msg (0, X_("noport dialog"), _("There are no more JACK ports available.")); } if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) { @@ -595,8 +587,9 @@ IOSelector::add_port () void IOSelector::remove_port () { - // always remove last port uint32_t nports; + + // always remove last port if (for_input) { if ((nports = io.n_inputs()) > 0) { @@ -625,19 +618,69 @@ IOSelector::remove_port_when_idle (Port *port) } gint -IOSelector::port_column_button_release (GdkEventButton *event, CList *clist) +IOSelector::connection_button_release (GdkEventButton *ev, TreeView *treeview) { + /* this handles button release on a port name row: i.e. a connection + between the named port and the port represented by the treeview. + */ + + TreeIter iter; + TreeModel::Path path; + TreeViewColumn* column; + int cellx; + int celly; + + /* only handle button1 events here */ + + if (ev->button != 1) { + return false; + } + + if (!(Keyboard::is_delete_event (ev))) { + return false; + } + + if (!treeview->get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { + return false; + } + + if ((iter = treeview->get_model()->get_iter (path))) { + + /* path is valid */ + + ustring connected_port_name = (*iter)[port_display_columns.full_name]; + Port *port = reinterpret_cast<Port *> (treeview->get_data (_("port"))); + + if (for_input) { + Port *p = session.engine().get_port_by_name (connected_port_name); + p->disable_metering(); + io.disconnect_input (port, connected_port_name, this); + } else { + io.disconnect_output (port, connected_port_name, this); + } + } + + return true; +} + +gint +IOSelector::port_column_button_release (GdkEventButton *event, TreeView* treeview) +{ + /* this handles button release on the button at the top of a single-column + treeview (representing a port) + */ + if (Keyboard::is_delete_event (event)) { Port* port; { LockMonitor lm (port_display_lock, __LINE__, __FILE__); - port = reinterpret_cast<Port *> (clist->get_data (_("port"))); + port = static_cast<Port *> (treeview->get_data (_("port"))); if (port == selected_port) { selected_port = 0; - clist->set_name ("IOSelectorPortList"); - clist->queue_draw(); + treeview->set_name ("IOSelectorPortList"); + treeview->queue_draw(); } } @@ -645,30 +688,30 @@ IOSelector::port_column_button_release (GdkEventButton *event, CList *clist) for whom we are handling an event. not good. */ - Glib::signal_idle().connect (bind (mem_fun(*this, &IOSelector::remove_port_when_idle), port)); + signal_idle().connect (bind (mem_fun(*this, &IOSelector::remove_port_when_idle), port)); } else { - select_clist(clist); + select_treeview (treeview); } return TRUE; } void -IOSelector::select_next_clist () +IOSelector::select_next_treeview () { - slist<CList*>::iterator next; + slist<TreeView*>::iterator next; - for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + for (slist<TreeView *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { if ((*i)->get_name() == "IOSelectorPortListSelected") { ++i; if (i == port_displays.end()) { - select_clist (port_displays.front()); + select_treeview (port_displays.front()); } else { - select_clist (*i); + select_treeview (*i); } break; @@ -677,22 +720,23 @@ IOSelector::select_next_clist () } void -IOSelector::select_clist(Gtk::CList* clist) +IOSelector::select_treeview (TreeView* tview) { - /* Gack. CList's don't respond visually to a change + /* Gack. TreeView's don't respond visually to a change in their state, so rename them to force a style switch. */ + LockMonitor lm (port_display_lock, __LINE__, __FILE__); - Port* port = reinterpret_cast<Port *> (clist->get_data (_("port"))); + Port* port = reinterpret_cast<Port *> (tview->get_data (_("port"))); if (port != selected_port) { selected_port = port; - clist->set_name ("IOSelectorPortListSelected"); + tview->set_name ("IOSelectorPortListSelected"); - for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { - if (*i != clist) { + for (slist<TreeView*>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + if (*i != tview) { (*i)->set_name ("IOSelectorPortList"); (*i)->queue_draw (); } @@ -701,39 +745,6 @@ IOSelector::select_clist(Gtk::CList* clist) } } -gint -IOSelector::connection_click (GdkEventButton *ev, CList *clist) -{ - gint row, col; - - /* only handle button1 events here */ - - if (ev->button != 1) { - return FALSE; - } - - if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { - return FALSE; - } - - if (row < 0 || col < 0) { - return FALSE; - } - - Port *port = reinterpret_cast<Port *> (clist->get_data (_("port"))); - string connected_port_name = clist->cell(row,col).get_text (); - - if (for_input) { - Port *p = session.engine().get_port_by_name (connected_port_name); - p->disable_metering(); - io.disconnect_input (port, connected_port_name, this); - } else { - io.disconnect_output (port, connected_port_name, this); - } - - return TRUE; -} - void IOSelector::redisplay () { @@ -827,11 +838,11 @@ PortInsertWindow::plugin_going_away (ARDOUR::Redirect* ignored) delete_when_idle (this); } -gint -PortInsertWindow::on_map (GdkEventAny *ev) +void +PortInsertWindow::on_map () { _portinsertui.redisplay (); - return Window::on_map (ev); + Window::on_map (); } diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h index abc902ba4c..5d7e258921 100644 --- a/gtk2_ardour/io_selector.h +++ b/gtk2_ardour/io_selector.h @@ -29,7 +29,13 @@ using __gnu_cxx::slist; #endif #include <string> -#include <gtkmm.h> +#include <gtkmm/box.h> +#include <gtkmm/frame.h> +#include <gtkmm/button.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/notebook.h> +#include <gtkmm/treeview.h> +#include <gtkmm/liststore.h> #include <ardour_dialog.h> @@ -66,6 +72,21 @@ class IOSelector : public Gtk::VBox { Gtk::VBox main_box; Gtk::HBox port_and_selector_box; + /* column model */ + + struct PortDisplayModelColumns : public Gtk::TreeModel::ColumnRecord { + + PortDisplayModelColumns() { + add (displayed_name); + add (full_name); + } + + Gtk::TreeModelColumn<Glib::ustring> displayed_name; + Gtk::TreeModelColumn<Glib::ustring> full_name; + }; + + PortDisplayModelColumns port_display_columns; + /* client/port selection */ Gtk::Notebook notebook; @@ -91,7 +112,7 @@ class IOSelector : public Gtk::VBox { void rescan (); void clear_connections (); - void port_selection_changed(); + void port_selection_changed(Gtk::TreeView*); void ports_changed (ARDOUR::IOChange, void *); void name_changed (void*); @@ -101,10 +122,10 @@ class IOSelector : public Gtk::VBox { gint remove_port_when_idle (ARDOUR::Port *); gint port_column_button_release (GdkEventButton*, Gtk::TreeView*); - gint connection_click (GdkEventButton *, Gtk::TreeView*); + gint connection_button_release (GdkEventButton *, Gtk::TreeView*); - void select_clist(Gtk::TreeView*); - void select_next_clist (); + void select_treeview(Gtk::TreeView*); + void select_next_treeview (); }; class IOSelectorWindow : public ArdourDialog @@ -116,7 +137,7 @@ class IOSelectorWindow : public ArdourDialog IOSelector& selector() { return _selector; } protected: - bool on_map (GdkEventAny *); + void on_map (); private: IOSelector _selector; @@ -158,7 +179,7 @@ class PortInsertWindow : public ArdourDialog PortInsertWindow (ARDOUR::Session&, ARDOUR::PortInsert&, bool can_cancel=false); protected: - bool on_map (GdkEventAny *); + void on_map (); private: diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index b6ea4560d6..c32f341cc6 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -72,29 +72,29 @@ RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelec _session(sess), _owner_is_mixer (owner_is_mixer), _placement(pcmnt), - _plugin_selector(plugsel), - _rr_selection(rsel), - redirect_display (1) + _plugin_selector(plugsel), + _rr_selection(rsel) + //redirect_display (1) { _width = Wide; redirect_menu = 0; send_action_menu = 0; redirect_drag_in_progress = false; + model = ListStore::create(columns); + selection = redirect_display.get_selection(); + selection->set_mode (Gtk::SELECTION_MULTIPLE); + redirect_display.set_model (model); + redirect_display.append_column (NULL, columns.text); redirect_display.set_name ("MixerRedirectSelector"); - redirect_display.column_titles_active (); + redirect_display.set_headers_visible (false); redirect_display.set_reorderable (true); - redirect_display.set_button_actions (0, (GTK_BUTTON_SELECTS|GTK_BUTTON_DRAGS)); - redirect_display.set_button_actions (1, 0); - redirect_display.set_button_actions (2, 0); - redirect_display.set_button_actions (3, 0); - redirect_display.drag_begin.connect (mem_fun(*this, &RedirectBox::redirect_drag_begin)); - redirect_display.drag_end.connect (mem_fun(*this, &RedirectBox::redirect_drag_end)); redirect_display.set_size_request (-1, 48); - redirect_display.set_selection_mode (Gtk::SELECTION_MULTIPLE); - redirect_display.set_shadow_type (Gtk::SHADOW_IN); - redirect_display.row_move.connect (mem_fun(*this, &RedirectBox::redirects_reordered)); + redirect_display.add_object_drag (columns.redirect.index(), "redirects"); + redirect_display.signal_object_drop.connect (mem_fun (*this, &RedirectBox::object_drop)); + // Does this adequately replace the drag start/stop signal handlers? + model->signal_rows_reordered().connect (mem_fun (*this, &RedirectBox::redirects_reordered)); redirect_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); redirect_scroller.add (redirect_display); @@ -111,11 +111,8 @@ RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelec redirect_display.signal_button_press_event().connect (mem_fun(*this, &RedirectBox::redirect_button)); redirect_display.signal_button_release_event().connect (mem_fun(*this, &RedirectBox::redirect_button)); - redirect_display.signal_button_release_event().connect_after (ptr_fun (do_not_propagate)); - _plugin_selector.hide.connect(mem_fun(*this,&RedirectBox::disconnect_newplug)); - - redirect_display.click_column.connect (mem_fun(*this, &RedirectBox::show_redirect_menu)); - + //redirect_display.signal_button_release_event().connect_after (ptr_fun (do_not_propagate)); + //_plugin_selector.hide.connect(mem_fun(*this,&RedirectBox::disconnect_newplug)); set_stuff_from_route (); /* start off as a passthru strip. we'll correct this, if necessary, @@ -138,6 +135,14 @@ RedirectBox::~RedirectBox () } void +RedirectBox::object_drop (string type, uint32_t cnt, void** ptr) +{ + if (type != "redirects") { + return; + } +} + +void RedirectBox::set_stuff_from_route () { } @@ -145,17 +150,12 @@ RedirectBox::set_stuff_from_route () void RedirectBox::set_title (const std::string & title) { - redirect_display.column(0).set_title (title); + redirect_display.get_column(0)->set_title (title); } void RedirectBox::set_title_shown (bool flag) { - if (flag) { - redirect_display.column_titles_show(); - } else { - redirect_display.column_titles_hide(); - } } @@ -230,7 +230,7 @@ void RedirectBox::show_redirect_menu (gint arg) { if (redirect_menu == 0) { - redirect_menu = build_redirect_menu (redirect_display); + redirect_menu = build_redirect_menu (); } redirect_menu->popup (1, 0); @@ -251,19 +251,18 @@ RedirectBox::redirect_drag_end (GdkDragContext *context) gint RedirectBox::redirect_button (GdkEventButton *ev) { - gint row=-1, col=-1; Redirect *redirect; - CList *clist = &redirect_display; - - if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 1) { - redirect = 0; - } else { - redirect = reinterpret_cast<Redirect *> (clist->row (row).get_data ()); - } + TreeModel::Row row = *(redirect_display.get_selection()->get_selected()); + redirect = row[columns.redirect]; switch (ev->type) { case GDK_BUTTON_PRESS: - return FALSE; + if (ev->button == 3) { + show_redirect_menu (0); // Handle the context-click menu here as well + return TRUE; + } + else + return FALSE; case GDK_2BUTTON_PRESS: if (ev->state != 0) { @@ -273,11 +272,6 @@ RedirectBox::redirect_button (GdkEventButton *ev) break; case GDK_BUTTON_RELEASE: - if (redirect_drag_in_progress) { - // drag-n-drop reordering - return stop_signal (*clist, "button-release-event"); - } - /* continue on */ break; default: @@ -287,7 +281,7 @@ RedirectBox::redirect_button (GdkEventButton *ev) if (redirect && Keyboard::is_delete_event (ev)) { - Gtk::Main::idle.connect (bind (mem_fun(*this, &RedirectBox::idle_delete_redirect), redirect)); + Glib::signal_idle().connect (bind (mem_fun(*this, &RedirectBox::idle_delete_redirect), redirect)); return TRUE; } else if (redirect && (Keyboard::is_edit_event (ev) || ev->type == GDK_2BUTTON_PRESS)) { @@ -300,32 +294,11 @@ RedirectBox::redirect_button (GdkEventButton *ev) } else if (Keyboard::is_context_menu_event (ev)) { show_redirect_menu(0); - return stop_signal (*clist, "button-release-event"); + return TRUE; //stop_signal (*clist, "button-release-event"); } else { switch (ev->button) { case 1: - if (redirect) { - using namespace CList_Helpers; - SelectionList& sel (redirect_display.selection()); - bool selecting = true; - - for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { - if ((*i).get_row_num() == row) { - // clicked row is not selected yet, so it is - // becoming selected now - selecting = false; - break; - } - } - - if (selecting) { - RedirectSelected (redirect); // emit - } - else { - RedirectUnselected (redirect); // emit - } - } return FALSE; break; @@ -347,105 +320,112 @@ RedirectBox::redirect_button (GdkEventButton *ev) } Menu * -RedirectBox::build_redirect_menu (CList& clist) +RedirectBox::build_redirect_menu () { - using namespace Menu_Helpers; - Menu * menu = new Menu; - menu->set_name ("ArdourContextMenu"); - MenuList& items = menu->items(); - menu->set_name ("ArdourContextMenu"); + popup_act_grp = Gtk::ActionGroup::create(); /* new stuff */ - - items.push_back (MenuElem (_("New Plugin ..."), mem_fun(*this, &RedirectBox::choose_plugin))); - items.push_back (MenuElem (_("New Insert"), mem_fun(*this, &RedirectBox::choose_insert))); - items.push_back (MenuElem (_("New Send ..."), mem_fun(*this, &RedirectBox::choose_send))); - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Clear"), mem_fun(*this, &RedirectBox::clear_redirects))); - items.push_back (SeparatorElem()); + popup_act_grp->add (Gtk::Action::create("newplugin", _("New Plugin ...")), mem_fun(*this, &RedirectBox::choose_plugin)); + popup_act_grp->add (Gtk::Action::create("newinsert", _("New Insert")), mem_fun(*this, &RedirectBox::choose_insert)); + popup_act_grp->add (Gtk::Action::create("newsend", _("New Send ...")), mem_fun(*this, &RedirectBox::choose_send)); + popup_act_grp->add (Gtk::Action::create("clear", _("Clear")), mem_fun(*this, &RedirectBox::clear_redirects)); + /* standard editing stuff */ - - items.push_back (MenuElem (_("Cut"), mem_fun(*this, &RedirectBox::cut_redirects))); - selection_dependent_items.push_back (items.back()); - items.push_back (MenuElem (_("Copy"), mem_fun(*this, &RedirectBox::copy_redirects))); - selection_dependent_items.push_back (items.back()); - items.push_back (MenuElem (_("Paste"), mem_fun(*this, &RedirectBox::paste_redirects))); - redirect_paste_item = items.back(); - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RedirectBox::rename_redirects))); - - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Select all"), mem_fun(*this, &RedirectBox::select_all_redirects))); - items.push_back (MenuElem (_("Deselect all"), mem_fun(*this, &RedirectBox::deselect_all_redirects))); - -#if LATER - Menu *select_sub_menu = manage (new Menu); - MenuList& sitems = select_sub_menu->items(); - select_sub_menu->set_name ("ArdourContextMenu"); + popup_act_grp->add (Gtk::Action::create("cut", _("Cut")), mem_fun(*this, &RedirectBox::cut_redirects)); + popup_act_grp->add (Gtk::Action::create("copy", _("Copy")), mem_fun(*this, &RedirectBox::copy_redirects)); + popup_act_grp->add (Gtk::Action::create("paste", _("Paste")), mem_fun(*this, &RedirectBox::paste_redirects)); + popup_act_grp->add (Gtk::Action::create("rename", _("Rename")), mem_fun(*this, &RedirectBox::rename_redirects)); + popup_act_grp->add (Gtk::Action::create("selectall", _("Select All")), mem_fun(*this, &RedirectBox::select_all_redirects)); + popup_act_grp->add (Gtk::Action::create("deselectall", _("Deselect All")), mem_fun(*this, &RedirectBox::deselect_all_redirects)); - sitems.push_back (MenuElem (_("Plugins"))); - sitems.push_back (MenuElem (_("Inserts"))); - sitems.push_back (MenuElem (_("Sends"))); - sitems.push_back (SeparatorElem()); - - items.push_back (MenuElem (_("Select all ..."), *select_sub_menu)); -#endif /* activation */ - - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Activate"), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), - &RedirectBox::activate_redirect))); - selection_dependent_items.push_back (items.back()); - items.push_back (MenuElem (_("Deactivate"), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), - &RedirectBox::deactivate_redirect))); - selection_dependent_items.push_back (items.back()); - items.push_back (SeparatorElem()); - - items.push_back (MenuElem (_("Activate All"), bind (mem_fun(*this, &RedirectBox::all_redirects_active), true))); - items.push_back (MenuElem (_("Deactivate All"), bind (mem_fun(*this, &RedirectBox::all_redirects_active), false))); - + + popup_act_grp->add (Gtk::Action::create("activate", _("Activate")), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), &RedirectBox::activate_redirect)); + popup_act_grp->add (Gtk::Action::create("deactivate", _("Deactivate")), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), &RedirectBox::deactivate_redirect)); + popup_act_grp->add (Gtk::Action::create("activateall", _("Activate All")), bind (mem_fun(*this, &RedirectBox::all_redirects_active), true)); + popup_act_grp->add (Gtk::Action::create("deactivateall", _("Deactivate All")), bind (mem_fun(*this, &RedirectBox::all_redirects_active), false)); + /* show editors */ - - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), - &RedirectBox::edit_redirect))); - selection_dependent_items.push_back (items.back()); - - menu->signal_map_event().connect (mem_fun(*this, &RedirectBox::redirect_menu_map_handler)); - - return menu; + + popup_act_grp->add (Gtk::Action::create("edit", _("Edit")), bind (mem_fun(*this, &RedirectBox::for_selected_redirects), &RedirectBox::edit_redirect)); + + selection_dependent_items.push_back (popup_act_grp->get_action("cut")); + selection_dependent_items.push_back (popup_act_grp->get_action("copy")); + selection_dependent_items.push_back (popup_act_grp->get_action("rename")); + selection_dependent_items.push_back (popup_act_grp->get_action("activate")); + selection_dependent_items.push_back (popup_act_grp->get_action("deactivate")); + selection_dependent_items.push_back (popup_act_grp->get_action("edit")); + + popup_ui_mgr = Gtk::UIManager::create(); + popup_ui_mgr->insert_action_group(popup_act_grp); + + try + { + Glib::ustring ui_info = + "<ui>" + " <popup name='redirectmenu'>" + " <menuitem action='newplugin'/>" + " <menuitem action='newinsert'/>" + " <menuitem action='newsend'/>" + " <separator/>" + " <menuitem action='clear'/>" + " <separator/>" + " <menuitem action='cut'/>" + " <menuitem action='copy'/>" + " <menuitem action='paste'/>" + " <separator/>" + " <menuitem action='rename'/>" + " <separator/>" + " <menuitem action='selectall'/>" + " <menuitem action='deselectall'/>" + " <separator/>" + " <menuitem action='activate'/>" + " <menuitem action='deactivate'/>" + " <separator/>" + " <menuitem action='activateall'/>" + " <menuitem action='deactivateall'/>" + " <separator/>" + " <menuitem action='edit'/>" + " </popup>" + "</ui>"; + popup_ui_mgr->add_ui_from_string(ui_info); + + } catch(const Glib::Error& ex) { + std::cerr << "building menus failed: " << ex.what(); + } + + redirect_menu = dynamic_cast<Gtk::Menu*>( popup_ui_mgr->get_widget("/redirectmenu") ); + redirect_menu->signal_map_event().connect (mem_fun(*this, &RedirectBox::redirect_menu_map_handler)); + redirect_menu->set_name ("ArdourContextMenu"); + show_all_children(); + return redirect_menu; } gint RedirectBox::redirect_menu_map_handler (GdkEventAny *ev) { - using namespace Menu_Helpers; - using namespace CList_Helpers; - - Gtk::CList* clist = &redirect_display; + bool sensitive = (redirect_display.get_selection()->count_selected_rows()) ? true : false; - bool sensitive = !clist->selection().empty(); - - for (vector<MenuItem*>::iterator i = selection_dependent_items.begin(); i != selection_dependent_items.end(); ++i) { + for (vector<Glib::RefPtr<Gtk::Action> >::iterator i = selection_dependent_items.begin(); i != selection_dependent_items.end(); ++i) { (*i)->set_sensitive (sensitive); } - redirect_paste_item->set_sensitive (!_rr_selection.redirects.empty()); + popup_act_grp->get_action("paste")->set_sensitive (!_rr_selection.redirects.empty()); return FALSE; } void RedirectBox::select_all_redirects () { - redirect_display.selection().all(); + redirect_display.get_selection()->select_all(); } void RedirectBox::deselect_all_redirects () { - redirect_display.selection().clear (); + redirect_display.get_selection()->unselect_all(); } void @@ -542,8 +522,9 @@ RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io) dialog.set_modal (true); dialog.show_all (); - dialog.realize(); - dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH)); + // GTK2FIX + //dialog.realize(); + //dialog.get_window()->set_decorations (Gdk::WMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); dialog.run (); } @@ -604,8 +585,8 @@ RedirectBox::redirects_changed (void *src) { ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::redirects_changed), src)); - redirect_display.freeze (); - redirect_display.clear (); + //redirect_display.freeze (); + model.clear (); redirect_active_connections.clear (); redirect_name_connections.clear (); @@ -613,40 +594,30 @@ RedirectBox::redirects_changed (void *src) switch (_placement) { case PreFader: - build_redirect_tooltip(redirect_display, redirect_eventbox, _("Pre-fader inserts, sends & plugins:")); + build_redirect_tooltip(redirect_eventbox, _("Pre-fader inserts, sends & plugins:")); break; case PostFader: - build_redirect_tooltip(redirect_display, redirect_eventbox, _("Post-fader inserts, sends & plugins:")); + build_redirect_tooltip(redirect_eventbox, _("Post-fader inserts, sends & plugins:")); break; } - redirect_display.thaw (); + //redirect_display.thaw (); } void RedirectBox::add_redirect_to_display (Redirect *redirect) { - const gchar *rowdata[1]; - gint row; - CList *clist = 0; - if (redirect->placement() != _placement) { return; } - clist = &redirect_display; - - string rname = redirect_name (*redirect); - rowdata[0] = rname.c_str(); - clist->rows().push_back (rowdata); - row = clist->rows().size() - 1; - clist->row (row).set_data (redirect); - + Gtk::TreeModel::Row row = *(model->append()); + row[columns.text] = redirect_name (*redirect); + row[columns.redirect] = redirect; + show_redirect_active (redirect, this); - redirect_active_connections.push_back - (redirect->active_changed.connect (mem_fun(*this, &RedirectBox::show_redirect_active))); - redirect_name_connections.push_back - (redirect->name_changed.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name), redirect))); + redirect_active_connections.push_back (redirect->active_changed.connect (mem_fun(*this, &RedirectBox::show_redirect_active))); + redirect_name_connections.push_back (redirect->name_changed.connect (bind (mem_fun(*this, &RedirectBox::show_redirect_name), redirect))); } string @@ -699,14 +670,15 @@ RedirectBox::redirect_name (Redirect& redirect) } void -RedirectBox::build_redirect_tooltip (CList& clist, EventBox& box, string start) +RedirectBox::build_redirect_tooltip (EventBox& box, string start) { - CList_Helpers::RowIterator ri; string tip(start); - for (ri = clist.rows().begin(); ri != clist.rows().end(); ++ri) { + Gtk::TreeModel::Children children = model->children(); + for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { + Gtk::TreeModel::Row row = *iter; tip += '\n'; - tip += clist.cell(ri->get_row_num(), 0).get_text(); + tip += row[columns.text]; } ARDOUR_UI::instance()->tooltips().set_tip (box, tip); } @@ -724,44 +696,43 @@ RedirectBox::show_redirect_active (Redirect *redirect, void *src) { ENSURE_GUI_THREAD(bind (mem_fun(*this, &RedirectBox::show_redirect_active), redirect, src)); - CList_Helpers::RowIterator ri; - CList *clist; + Gtk::TreeModel::Children children = model->children(); + Gtk::TreeModel::Children::iterator iter = children.begin(); - if ((ri = redirect_display.rows().find_data (redirect)) == redirect_display.rows().end()) { - return; + while( iter != children.end()) + { + if ((*iter)[columns.redirect] == redirect) + break; + iter++; } - clist = &redirect_display; - - clist->cell(ri->get_row_num(), 0).set_text (redirect_name (*redirect)); + (*iter)[columns.text] = redirect_name (*redirect); if (redirect->active()) { - // ri->select (); + redirect_display.get_selection()->select (iter); } else { - // ri->unselect (); + redirect_display.get_selection()->unselect (iter); } } void -RedirectBox::redirects_reordered (gint src, gint dst) +RedirectBox::redirects_reordered (const TreeModel::Path& path,const TreeModel::iterator& iter ,int* hmm) { /* this is called before the reorder has been done, so just queue something for idle time. */ - Glib::signal_idle().connect (mem_fun(*this, &RedirectBox::compute_redirect_sort_keys)); + Glib::signal_idle().connect (mem_fun(*this, &RedirectBox::compute_redirect_sort_keys)); } gint RedirectBox::compute_redirect_sort_keys () { - CList_Helpers::RowList::iterator i; - uint32_t sort_key; + uint32_t sort_key = 0; + Gtk::TreeModel::Children children = model->children(); - sort_key = 0; - - for (i = redirect_display.rows().begin(); i != redirect_display.rows().end(); ++i) { - Redirect *redirect = reinterpret_cast<Redirect*> (i->get_data()); + for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { + Redirect *redirect = (*iter)[columns.redirect]; redirect->set_sort_key (sort_key, this); sort_key++; } @@ -798,8 +769,9 @@ outputs do not work correctly.")); dialog.set_modal (true); dialog.show_all (); - dialog.realize(); - dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH)); + // GTK2FIX + //dialog.realize(); + //dialog.get_window()->set_decorations (Gdk::WMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); dialog.run (); } @@ -1011,23 +983,19 @@ RedirectBox::deactivate_redirect (Redirect *r) void RedirectBox::get_selected_redirects (vector<Redirect*>& redirects) { - using namespace CList_Helpers; - SelectionList& sel (redirect_display.selection()); - - for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { - Redirect* redirect = reinterpret_cast<Redirect *> ((*i).get_data ()); - redirects.push_back (redirect); - } + vector<Gtk::TreeModel::Path> pathlist = redirect_display.get_selection()->get_selected_rows(); + + for (vector<Gtk::TreeModel::Path>::iterator iter = pathlist.begin(); iter != pathlist.end(); ++iter) + redirects.push_back ((*(model->get_iter(*iter)))[columns.redirect]); } void RedirectBox::for_selected_redirects (void (RedirectBox::*pmf)(Redirect*)) { - using namespace CList_Helpers; - SelectionList& sel (redirect_display.selection()); + vector<Gtk::TreeModel::Path> pathlist = redirect_display.get_selection()->get_selected_rows(); - for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { - Redirect* redirect = reinterpret_cast<Redirect *> ((*i).get_data ()); + for (vector<Gtk::TreeModel::Path>::iterator iter = pathlist.begin(); iter != pathlist.end(); ++iter) { + Redirect* redirect = (*(model->get_iter(*iter)))[columns.redirect]; (this->*pmf)(redirect); } } @@ -1073,7 +1041,7 @@ RedirectBox::clear_redirects() Gtkmm2ext::Choice prompter (prompt, choices); - prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.chosen.connect(sigc::ptr_fun(Gtk::Main::quit)); prompter.show_all (); Gtk::Main::run (); diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h index 55769cd4e1..278c423df4 100644 --- a/gtk2_ardour/redirect_box.h +++ b/gtk2_ardour/redirect_box.h @@ -24,9 +24,14 @@ #include <vector> #include <cmath> -#include <gtkmm.h> +#include <gtkmm/box.h> +#include <gtkmm/eventbox.h> +#include <gtkmm/menu.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm2ext/dndtreeview.h> #include <gtkmm2ext/auto_spin.h> #include <gtkmm2ext/click_box.h> +#include <gtkmm2ext/dndtreeview.h> #include <ardour/types.h> #include <ardour/ardour.h> @@ -91,11 +96,25 @@ class RedirectBox : public Gtk::HBox PluginSelector & _plugin_selector; RouteRedirectSelection & _rr_selection; + struct ModelColumns : public Gtk::TreeModel::ColumnRecord { + ModelColumns () { + add (text); + add (redirect); + } + Gtk::TreeModelColumn<std::string> text; + Gtk::TreeModelColumn<ARDOUR::Redirect*> redirect; + }; + + ModelColumns columns; + Glib::RefPtr<Gtk::ListStore> model; + Glib::RefPtr<Gtk::TreeSelection> selection; - Gtk::EventBox redirect_eventbox; - Gtk::HBox redirect_hpacker; - Gtk::TreeView redirect_display; - Gtk::ScrolledWindow redirect_scroller; + Gtk::EventBox redirect_eventbox; + Gtk::HBox redirect_hpacker; + Gtkmm2ext::DnDTreeView redirect_display; + Gtk::ScrolledWindow redirect_scroller; + + void object_drop (std::string type, uint32_t cnt, void**); Width _width; @@ -107,12 +126,13 @@ class RedirectBox : public Gtk::HBox void new_send (); void show_send_controls (); + Glib::RefPtr<Gtk::UIManager> popup_ui_mgr; + Glib::RefPtr<Gtk::ActionGroup> popup_act_grp; Gtk::Menu *redirect_menu; - vector<Gtk::MenuItem*> selection_dependent_items; - Gtk::MenuItem* redirect_paste_item; + vector<Glib::RefPtr<Gtk::Action> > selection_dependent_items; gint redirect_menu_map_handler (GdkEventAny *ev); - Gtk::Menu * build_redirect_menu (Gtk::TreeView&); - void build_redirect_tooltip (Gtk::TreeView&, Gtk::EventBox&, string); + Gtk::Menu * build_redirect_menu (); + void build_redirect_tooltip (Gtk::EventBox&, string); void show_redirect_menu (gint arg); void choose_send (); @@ -137,7 +157,7 @@ class RedirectBox : public Gtk::HBox void disconnect_newplug(); - void redirects_reordered (gint, gint); + void redirects_reordered (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&, int*); gint compute_redirect_sort_keys (); vector<sigc::connection> redirect_active_connections; vector<sigc::connection> redirect_name_connections; |