io_selector.cc done, connection_editor in progress but skipped
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 1 Nov 2005 00:56:09 +0000 (00:56 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 1 Nov 2005 00:56:09 +0000 (00:56 +0000)
git-svn-id: svn://localhost/trunk/ardour2@76 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/SConscript
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/connection_editor.cc
gtk2_ardour/connection_editor.h
gtk2_ardour/editor.h
gtk2_ardour/editor_edit_groups.cc
gtk2_ardour/io_selector.cc
gtk2_ardour/io_selector.h
gtk2_ardour/redirect_box.cc
gtk2_ardour/redirect_box.h

index 79259421e8ebc5c5884175949dac5db80c5c0ff7..d55b151e7204e246fecfc7cd3fbfc06be85d5898 100644 (file)
@@ -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)
 
index f8a460f778348fafa77c4743c81d62da37b24449..e4155682fe9aefb1f666f6e7bdd5f637c050d835 100644 (file)
@@ -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]);
        
 
index 56c7435cc3cc138b5e767fc77008db6103c79410..0b67ac8477f028d63783d9b20b389c2f46d455c8 100644 (file)
@@ -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;
 }
-       
-       
index 69b6b835777354924a8518387176a103373d2bac..1d6dd7d7fc098629eb8a98ef91e4fd69e083a025 100644 (file)
@@ -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);
index de945c4ad11444b339642e46f1f823e45c8b128d..43812439c4c84ebd88be65f1305cb08a6623b8a9 100644 (file)
@@ -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 */
index 9e3df176f8fb5a08ff41dbd0888eea6fa4c6ebac..2153a2f90eaaed3537a1078b23a9103dd9218628 100644 (file)
@@ -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;
index ae2a63e20278eb5cdc6656ac8c02839c535e70ee..9aec5be3190245bda5e7feb50fb5c27ae3694592 100644 (file)
@@ -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 ();
 }
 
 
index abc902ba4c1c4a1968e5ad5e9212edb45259f3ce..5d7e2589219709ba4e2964d72afe46be9190ddfc 100644 (file)
@@ -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:
        
index b6ea4560d664d77e00463d7ef04c75c733ccda03..c32f341cc682d5ca6f3a475b130d9cd8e8a861b1 100644 (file)
@@ -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,
@@ -137,6 +134,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 ();
index 55769cd4e1008604c94d1470d2de6709da44fa56..278c423df48cc31a5d1a40c18d97bec8ede6a8de 100644 (file)
 #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;