X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor.cc;h=a44eba37544994c64241a983f5ecd0092d82decf;hb=a20f41ab39cc034740ccd564c1057d8737d763d5;hp=a6d651961c93c235fb9683281bc76205e043963e;hpb=010fc09da937094330db4d1cc1bdc036ffbf383c;p=ardour.git diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index a6d651961c..a44eba3754 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -193,11 +193,12 @@ Editor::on_key_press_event (GdkEventKey* ev) } /* no modifiers, propagate first */ - + if (!gtk_window_propagate_key_event (win, ev)) { return gtk_window_activate_key (win, ev); } + return true; } @@ -318,6 +319,7 @@ Editor::Editor (AudioEngine& eng) show_gain_after_trim = false; no_zoom_repos_update = false; ignore_route_list_reorder = false; + no_route_list_redisplay = false; verbose_cursor_on = true; route_removal = false; track_spacing = 0; @@ -338,8 +340,6 @@ Editor::Editor (AudioEngine& eng) new_transport_marker_menu = 0; editor_mixer_strip_width = Wide; repos_zoom_queued = false; - import_audio_item = 0; - embed_audio_item = 0; region_edit_menu_split_item = 0; temp_location = 0; region_edit_menu_split_multichannel_item = 0; @@ -364,7 +364,6 @@ Editor::Editor (AudioEngine& eng) range_marker_drag_rect = 0; marker_drag_line = 0; - mouse_mode = MouseZoom; /* force change in next call */ set_mouse_mode (MouseObject, true); frames_per_unit = 2048; /* too early to use set_frames_per_unit */ @@ -374,7 +373,7 @@ Editor::Editor (AudioEngine& eng) initialize_rulers (); initialize_canvas (); - edit_controls_vbox.set_spacing (track_spacing); + edit_controls_vbox.set_spacing (0); horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled)); vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling)); @@ -385,10 +384,10 @@ Editor::Editor (AudioEngine& eng) track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler)); time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler)); - // edit_controls_hbox.pack_start (edit_controls_vbox, true, true); controls_layout.add (edit_controls_vbox); controls_layout.set_name ("EditControlsBase"); - controls_layout.signal_size_request().connect (mem_fun(*this, &Editor::set_layout_width), false); + controls_layout.add_events (Gdk::SCROLL_MASK); + controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false); controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK); controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release)); @@ -498,9 +497,9 @@ Editor::Editor (AudioEngine& eng) zoom_out_full_button.set_name ("EditorTimeButton"); ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session")); - zoom_in_button.add (*(manage (new Gtk::Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON)))); - zoom_out_button.add (*(manage (new Gtk::Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON)))); - zoom_out_full_button.add (*(manage (new Gtk::Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON)))); + zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON)))); + zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON)))); + zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON)))); zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false)); zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true)); @@ -523,30 +522,22 @@ Editor::Editor (AudioEngine& eng) bottom_hbox.set_spacing (3); route_display_model = ListStore::create(route_display_columns); - route_list.set_model (route_display_model); - route_list.append_column (_("Tracks"), route_display_columns.text); - route_list.set_name ("TrackListDisplay"); - route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - route_list.set_reorderable (true); - - route_list.set_size_request (75,-1); - route_list.set_headers_visible (true); - route_list.set_headers_clickable (true); - - // GTK2FIX - // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered)); + route_list_display.set_model (route_display_model); + route_list_display.append_column (_("Tracks"), route_display_columns.text); + route_list_display.set_headers_visible (false); + route_list_display.set_name ("TrackListDisplay"); + route_list_display.get_selection()->set_mode (SELECTION_MULTIPLE); + route_list_display.set_reorderable (true); + route_list_display.set_size_request (75,-1); - // GTK2FIX - // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func)); + route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::route_list_reordered)); + route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func)); + route_display_model->set_sort_column (0, SORT_ASCENDING); - // GTK2FIX - //route_list.set_shadow_type (Gtk::SHADOW_IN); + route_list_scroller.add (route_list_display); + route_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); - route_list_scroller.add (route_list); - route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); - - route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed)); - route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click)); + route_list_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed)); edit_group_list_button_label.set_text (_("Edit Groups")); edit_group_list_button_label.set_name ("EditGroupTitleButton"); @@ -554,118 +545,132 @@ Editor::Editor (AudioEngine& eng) edit_group_list_button.set_name ("EditGroupTitleButton"); group_model = ListStore::create(group_columns); - edit_group_list.set_model (group_model); - edit_group_list.append_column (_("active"), group_columns.is_active); - edit_group_list.append_column (_("groupname"), group_columns.text); - edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); - edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); + edit_group_display.set_model (group_model); + edit_group_display.append_column (_("active"), group_columns.is_active); + edit_group_display.append_column (_("groupname"), group_columns.text); + edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0)); + edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); + edit_group_display.set_headers_visible (false); /* use checkbox for the active column */ - CellRendererToggle *active_cell = dynamic_cast(edit_group_list.get_column_cell_renderer (0)); + CellRendererToggle *active_cell = dynamic_cast(edit_group_display.get_column_cell_renderer (0)); active_cell->property_activatable() = true; active_cell->property_radio() = false; - edit_group_list.set_name ("MixerGroupList"); - //edit_group_list.set_shadow_type (Gtk::SHADOW_IN); - - edit_group_list.columns_autosize (); - edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - edit_group_list.set_reorderable (false); + edit_group_display.set_name ("MixerGroupList"); + edit_group_display.columns_autosize (); + edit_group_display.get_selection()->set_mode (SELECTION_MULTIPLE); + edit_group_display.set_reorderable (false); - edit_group_list.set_size_request (75, -1); - edit_group_list.set_headers_visible (true); + edit_group_display.set_size_request (75, -1); - edit_group_list_scroller.add (edit_group_list); - edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + edit_group_list_scroller.add (edit_group_display); + edit_group_list_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC); edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked)); - edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event)); - edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed)); + edit_group_display.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event)); + edit_group_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed)); TreeModel::Row row = *(group_model->append()); row[group_columns.is_active] = false; row[group_columns.text] = (_("-all-")); - edit_group_list.get_selection()->select (row); -/* GTK2FIX is set_data(0) setting the is_active to false here? - list stupid_list; + row[group_columns.routegroup] = 0; + edit_group_display.get_selection()->select (row); - stupid_list.push_back ("*"); - stupid_list.push_back (_("-all-")); - - edit_group_list.rows().push_back (stupid_list); - edit_group_list.rows().back().set_data (0); - edit_group_list.rows().back().select(); - -*/ edit_group_vbox.pack_start (edit_group_list_button, false, false); edit_group_vbox.pack_start (edit_group_list_scroller, true, true); + region_list_display.set_size_request (100, -1); + region_list_display.set_name ("RegionListDisplay"); + region_list_model = TreeStore::create (region_list_columns); - region_list_sort_model = TreeModelSort::create (region_list_model); region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter)); + region_list_model->set_sort_column (0, SORT_ASCENDING); + + region_list_display.set_model (region_list_model); + CellRendererText* renderer = manage( new CellRendererText() ); + region_list_display.append_column (_("Regions"), *renderer); + region_list_display.set_headers_visible (false); - region_list_display.set_model (region_list_sort_model); - region_list_display.append_column (_("Regions"), region_list_columns.name); + region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter)); + + TreeViewColumn* tv_col = region_list_display.get_column(0); + tv_col->add_attribute(renderer->property_text(), region_list_columns.name); + tv_col->add_attribute(renderer->property_foreground_gdk(), region_list_columns.color_); + region_list_display.set_reorderable (true); - region_list_display.set_size_request (100, -1); - region_list_display.set_data ("editor", this); - region_list_display.set_flags (Gtk::CAN_FOCUS); - region_list_display.set_name ("RegionListDisplay"); - region_list_scroller.add (region_list_display); - region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE); + region_list_display.add_object_drag (region_list_columns.region.index(), "regions"); - list region_list_target_table; + /* setup DnD handling */ + + list region_list_target_table; - region_list_target_table.push_back (TargetEntry ("STRING")); region_list_target_table.push_back (TargetEntry ("text/plain")); region_list_target_table.push_back (TargetEntry ("text/uri-list")); region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop")); + + region_list_display.add_drop_targets (region_list_target_table); + region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received)); - // GTK2FIX - // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE)); - // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received)); + region_list_scroller.add (region_list_display); + region_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press)); region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release)); - region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press)); + region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press), false); region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release)); region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed)); - // GTK2FIX - //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected)); - //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click)); + // region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0)); named_selection_scroller.add (named_selection_display); - named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); named_selection_model = TreeStore::create (named_selection_columns); named_selection_display.set_model (named_selection_model); named_selection_display.append_column (_("Chunks"), named_selection_columns.text); + named_selection_display.set_headers_visible (false); named_selection_display.set_size_request (100, -1); named_selection_display.set_name ("RegionListDisplay"); - named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE); + named_selection_display.get_selection()->set_mode (SELECTION_SINGLE); named_selection_display.set_size_request (100, -1); - named_selection_display.set_headers_visible (true); - named_selection_display.set_headers_clickable (true); - named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press)); + named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press), false); named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed)); + /* SNAPSHOTS */ + + snapshot_display_model = ListStore::create (snapshot_display_columns); + snapshot_display.set_model (snapshot_display_model); + snapshot_display.append_column (X_("snapshot"), snapshot_display_columns.visible_name); + snapshot_display.set_name ("SnapshotDisplayList"); + snapshot_display.set_size_request (75, -1); + snapshot_display.set_headers_visible (false); + snapshot_display.set_reorderable (false); + snapshot_display_scroller.add (snapshot_display); + snapshot_display_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + + snapshot_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::snapshot_display_selection_changed)); + snapshot_display.signal_button_press_event().connect (mem_fun (*this, &Editor::snapshot_display_button_press), false); + the_notebook.append_page (region_list_scroller, _("Regions")); the_notebook.append_page (route_list_scroller, _("Tracks/Busses")); + the_notebook.append_page (snapshot_display_scroller, _("Snapshots")); the_notebook.append_page (edit_group_vbox, _("Edit Groups")); the_notebook.append_page (named_selection_scroller, _("Chunks")); the_notebook.set_show_tabs (true); the_notebook.set_scrollable (true); the_notebook.popup_enable (); - TearOff *notebook_tearoff = manage (new TearOff (the_notebook)); + TearOff *notebook_tearoff = manage (new TearOff (the_notebook, true)); + notebook_tearoff->tearoff_window().set_size_request (200, 400); edit_pane.pack1 (edit_frame, true, true); edit_pane.pack2 (*notebook_tearoff, true, true); - - edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast (&edit_pane))); + + edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast (&edit_pane))); top_hbox.pack_start (toolbar_frame, true, true); @@ -681,6 +686,10 @@ Editor::Editor (AudioEngine& eng) add_accel_group (ActionManager::ui_manager->get_accel_group()); vpacker.pack_end (global_hpacker, true, true); + + /* register actions now so that set_state() can find them and set toggles/checks etc */ + + register_actions (); XMLNode* node = ARDOUR_UI::instance()->editor_settings(); set_state (*node); @@ -692,8 +701,8 @@ Editor::Editor (AudioEngine& eng) /* nudge stuff */ - nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm))))); - nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm))))); + nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm))))); + nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm))))); ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards")); ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards")); @@ -815,7 +824,6 @@ Editor::tie_vertical_scrolling () { double y1 = vertical_adjustment.get_value(); controls_layout.get_vadjustment()->set_value (y1); - playhead_cursor->set_y_axis(y1); edit_cursor->set_y_axis(y1); } @@ -983,16 +991,9 @@ void Editor::on_realize () { Window::on_realize (); - - /* Even though we're not using acceleration, we want the - labels to show up. - */ - - track_context_menu.accelerate (*this->get_toplevel()); - track_region_context_menu.accelerate (*this->get_toplevel()); + Realized (); } - void Editor::queue_session_control_changed (Session::ControlType t) { @@ -1111,7 +1112,7 @@ Editor::handle_new_duration () } void -Editor::update_title_s (stringcr_t snap_name) +Editor::update_title_s (const string & snap_name) { ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name)); @@ -1156,8 +1157,6 @@ Editor::connect_to_session (Session *t) first_action_message->hide(); } - flush_track_canvas(); - update_title (); session->going_away.connect (mem_fun(*this, &Editor::session_going_away)); @@ -1240,7 +1239,7 @@ Editor::connect_to_session (Session *t) update_punch_range_view (true); session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed)); - + session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved)); refresh_location_display (); session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location)); @@ -1253,15 +1252,13 @@ Editor::connect_to_session (Session *t) redisplay_regions (); redisplay_named_selections (); + redisplay_snapshots (); - //route_list.freeze (); GTK2FIX route_display_model->clear (); + no_route_list_redisplay = true; session->foreach_route (this, &Editor::handle_new_route); - // route_list.select_all (); - // GTK2FIX - //route_list.sort (); - route_list_reordered (); - //route_list.thaw (); + no_route_list_redisplay = false; + route_list_display.get_selection()->select_all (); for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (static_cast(*i))->set_samples_per_unit (frames_per_unit); @@ -1295,7 +1292,7 @@ Editor::connect_to_session (Session *t) TreeModel::Children rows = route_display_model->children(); TreeModel::Children::iterator i; - //route_list.freeze (); + //route_list_display.freeze (); for (i = rows.begin(); i != rows.end(); ++i) { TimeAxisView *tv = (*i)[route_display_columns.tv]; @@ -1303,13 +1300,13 @@ Editor::connect_to_session (Session *t) if ((atv = dynamic_cast(tv)) != 0) { if (atv->route().master()) { - route_list.get_selection()->unselect (i); + route_list_display.get_selection()->unselect (i); //(*i)->unselect (); } } } - //route_list.thaw (); + //route_list_display.thaw (); } } @@ -1470,11 +1467,9 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, if (!with_selection) { if (region_edit_menu_split_item) { if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) { - // GTK2FIX find the action, change its sensitivity - // region_edit_menu_split_item->set_sensitive (true); + ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true); } else { - // GTK2FIX see above - // region_edit_menu_split_item->set_sensitive (false); + ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false); } } if (region_edit_menu_split_multichannel_item) { @@ -2127,8 +2122,13 @@ Editor::set_state (const XMLNode& node) if ((prop = node.property ("follow-playhead"))) { bool yn = (prop->value() == "yes"); - _follow_playhead = !yn; - set_follow_playhead (yn); + RefPtr act = ActionManager::get_action (X_("Editor"), X_("ToggleFollowPlayhead")); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + /* do it twice to force the change */ + tact->set_active (!yn); + tact->set_active (yn); + } } if ((prop = node.property ("xfades-visible"))) { @@ -2475,10 +2475,10 @@ Editor::setup_toolbar () mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table)); mouse_mode_tearoff->set_name ("MouseModeBase"); - mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - mouse_mode_tearoff->tearoff_window())); - mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - mouse_mode_tearoff->tearoff_window(), 1)); + mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &mouse_mode_tearoff->tearoff_window())); + mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &mouse_mode_tearoff->tearoff_window(), 1)); mouse_move_button.set_name ("MouseModeButton"); mouse_select_button.set_name ("MouseModeButton"); @@ -2494,12 +2494,12 @@ Editor::setup_toolbar () ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions")); ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions")); - mouse_move_button.unset_flags (Gtk::CAN_FOCUS); - mouse_select_button.unset_flags (Gtk::CAN_FOCUS); - mouse_gain_button.unset_flags (Gtk::CAN_FOCUS); - mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS); - mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS); - mouse_audition_button.unset_flags (Gtk::CAN_FOCUS); + mouse_move_button.unset_flags (CAN_FOCUS); + mouse_select_button.unset_flags (CAN_FOCUS); + mouse_gain_button.unset_flags (CAN_FOCUS); + mouse_zoom_button.unset_flags (CAN_FOCUS); + mouse_timefx_button.unset_flags (CAN_FOCUS); + mouse_audition_button.unset_flags (CAN_FOCUS); mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange)); mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release)); @@ -2605,23 +2605,35 @@ Editor::setup_toolbar () selection_start_clock_label.set_text (_("Start:")); selection_end_clock_label.set_text (_("End:")); - edit_cursor_clock_label.set_text (_("Edit:")); + edit_cursor_clock_label.set_text (_("Edit")); + + /* the zoom in/out buttons are generally taller than the clocks, so + put all the toolbar clocks into a size group with one of the + buttons to make them all equal height. - toolbar_selection_clock_table.set_border_width (5); - toolbar_selection_clock_table.set_col_spacings (2); - toolbar_selection_clock_table.set_homogeneous (false); + this also applies to the various toolbar combos + */ -// toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0); -// toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0); - toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0); + RefPtr toolbar_clock_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL); + toolbar_clock_size_group->add_widget (zoom_out_button); + toolbar_clock_size_group->add_widget (edit_cursor_clock); + toolbar_clock_size_group->add_widget (zoom_range_clock); + toolbar_clock_size_group->add_widget (nudge_clock); + toolbar_clock_size_group->add_widget (edit_mode_selector); + toolbar_clock_size_group->add_widget (snap_type_selector); + toolbar_clock_size_group->add_widget (snap_mode_selector); + toolbar_clock_size_group->add_widget (zoom_focus_selector); -// toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0); -// toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0); - toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL); + HBox* edit_clock_hbox = manage (new HBox()); + VBox* edit_clock_vbox = manage (new VBox()); + edit_clock_hbox->pack_start (edit_cursor_clock, false, false); + + edit_clock_vbox->set_spacing (3); + edit_clock_vbox->set_border_width (3); + edit_clock_vbox->pack_start (edit_cursor_clock_label, false, false); + edit_clock_vbox->pack_start (*edit_clock_hbox, false, false); -// toolbar_clock_vbox.set_spacing (2); -// toolbar_clock_vbox.set_border_width (10); /* the editor/mixer button will be enabled at session connect */ editor_mixer_button.set_active(false); @@ -2630,7 +2642,7 @@ Editor::setup_toolbar () HBox* hbox = new HBox; hbox->pack_start (editor_mixer_button, false, false); - hbox->pack_start (toolbar_selection_clock_table, false, false); + hbox->pack_start (*edit_clock_vbox, false, false); hbox->pack_start (zoom_indicator_vbox, false, false); hbox->pack_start (zoom_focus_box, false, false); hbox->pack_start (snap_type_box, false, false); @@ -2663,10 +2675,10 @@ Editor::setup_toolbar () tools_tearoff = new TearOff (*hbox); tools_tearoff->set_name ("MouseModeBase"); - tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), - tools_tearoff->tearoff_window())); - tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), - tools_tearoff->tearoff_window(), 0)); + tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + &tools_tearoff->tearoff_window())); + tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + &tools_tearoff->tearoff_window(), 0)); toolbar_hbox.set_spacing (8); @@ -2678,7 +2690,7 @@ Editor::setup_toolbar () toolbar_base.set_name ("ToolBarBase"); toolbar_base.add (toolbar_hbox); - toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT); + toolbar_frame.set_shadow_type (SHADOW_OUT); toolbar_frame.set_name ("BaseFrame"); toolbar_frame.add (toolbar_base); } @@ -2780,130 +2792,80 @@ Editor::stop_canvas_autoscroll () int Editor::convert_drop_to_paths (vector& paths, - GdkDragContext *context, + const RefPtr& context, gint x, gint y, - GtkSelectionData *data, + const SelectionData& data, guint info, guint time) { - string spath; - char *path; - int state; - gchar *tname = gdk_atom_name (data->type); - - if (session == 0 || strcmp (tname, "text/plain") != 0) { + if (session == 0) { return -1; } - /* Parse the "uri-list" format that Nautilus provides, - where each pathname is delimited by \r\n - */ + vector uris = data.get_uris(); - path = (char *) data->data; - state = 0; + if (uris.empty()) { + + /* This is seriously fucked up. Nautilus doesn't say that its URI lists + are actually URI lists. So do it by hand. + */ - for (int n = 0; n < data->length; ++n) { + if (data.get_target() != "text/plain") { + return -1; + } + + /* Parse the "uri-list" format that Nautilus provides, + where each pathname is delimited by \r\n + */ + + const char* p = data.get_text().c_str(); + const char* q; - switch (state) { - case 0: - if (path[n] == '\r') { - state = 1; - } else { - spath += path[n]; - } - break; - case 1: - if (path[n] == '\n') { - paths.push_back (spath); - spath = ""; - state = 0; - } else { - warning << _("incorrectly formatted URI list, ignored") - << endmsg; - return -1; + while (p) + { + if (*p != '#') + { + while (g_ascii_isspace (*p)) + p++; + + q = p; + while (*q && (*q != '\n') && (*q != '\r')) + q++; + + if (q > p) + { + q--; + while (q > p && g_ascii_isspace (*q)) + q--; + + if (q > p) + { + uris.push_back (ustring (p, q - p + 1)); + } + } } - break; + p = strchr (p, '\n'); + if (p) + p++; } - } - - /* nautilus and presumably some other file managers prefix even text/plain with file:// */ - - for (vector::iterator p = paths.begin(); p != paths.end(); ++p) { - - // cerr << "dropped text was " << *p << endl; - - url_decode (*p); - // cerr << "decoded was " << *p << endl; - - if ((*p).substr (0,7) == "file://") { - (*p) = (*p).substr (7); + if (uris.empty()) { + return -1; } } - return 0; -} - -void -Editor::track_canvas_drag_data_received (GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *data, - guint info, - guint time) -{ - TimeAxisView* tvp; - AudioTimeAxisView* tv; - double cy; - vector paths; - string spath; - GdkEvent ev; - jack_nframes_t frame; - - if (convert_drop_to_paths (paths, context, x, y, data, info, time)) { - goto out; - } - - /* D-n-D coordinates are window-relative, so convert to "world" coordinates - */ - - double wx; - double wy; - - track_canvas.c2w( x, y, wx, wy); - - ev.type = GDK_BUTTON_RELEASE; - ev.button.x = wx; - ev.button.y = wy; - - frame = event_frame (&ev, 0, &cy); - - snap_to (frame); - - if ((tvp = trackview_by_y_position (cy)) == 0) { - - /* drop onto canvas background: create a new track */ - - insert_paths_as_new_tracks (paths, false); - - - } else if ((tv = dynamic_cast(tvp)) != 0) { - - /* check that its an audio track, not a bus */ - - if (tv->get_diskstream()) { - - for (vector::iterator p = paths.begin(); p != paths.end(); ++p) { - insert_sndfile_into (*p, true, tv, frame); - } + for (vector::iterator i = uris.begin(); i != uris.end(); ++i) { + if ((*i).substr (0,7) == "file://") { + string p = *i; + url_decode (p); + cerr << "adding " << p << endl; + paths.push_back (p.substr (7)); } - } - out: - gtk_drag_finish (context, TRUE, FALSE, time); + return 0; } void @@ -2981,19 +2943,6 @@ Editor::commit_reversible_command () } } -void -Editor::flush_track_canvas () -{ - /* I don't think this is necessary, and only causes more problems. - I'm commenting it out - and if the imageframe folks don't have any issues, we can take - out this method entirely - */ - - //gnome_canvas_update_now (GNOME_CANVAS(track_canvas)); - //gtk_main_iteration (); -} - void Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove) { @@ -3374,7 +3323,7 @@ Editor::duplicate_dialog (bool dup_region) win.add_button (Stock::OK, RESPONSE_ACCEPT); win.add_button (Stock::CANCEL, RESPONSE_CANCEL); - win.set_position (Gtk::WIN_POS_MOUSE); + win.set_position (WIN_POS_MOUSE); entry.set_text ("1"); set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15); @@ -3422,7 +3371,7 @@ Editor::hide_verbose_canvas_cursor () } void -Editor::set_verbose_canvas_cursor (stringcr_t txt, double x, double y) +Editor::set_verbose_canvas_cursor (const string & txt, double x, double y) { /* XXX get origin of canvas relative to root window, add x and y and check compared to gdk_screen_{width,height} @@ -3433,7 +3382,7 @@ Editor::set_verbose_canvas_cursor (stringcr_t txt, double x, double y) } void -Editor::set_verbose_canvas_cursor_text (stringcr_t txt) +Editor::set_verbose_canvas_cursor_text (const string & txt) { verbose_canvas_cursor->property_text() = txt.c_str(); } @@ -3695,7 +3644,7 @@ Editor::ensure_float (Window& win) } void -Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which) +Editor::pane_allocation_handler (Allocation &alloc, Paned* which) { /* recover or initialize pane positions. do this here rather than earlier because we don't want the positions to change the child allocations, which they seem to do. @@ -3706,7 +3655,7 @@ Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which) char buf[32]; XMLNode* node = ARDOUR_UI::instance()->editor_settings(); int width, height; - static int32_t done[4] = { 0, 0, 0, 0 }; + static int32_t done; XMLNode* geometry; if ((geometry = find_named_node (*node, "geometry")) == 0) { @@ -3717,38 +3666,37 @@ Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which) height = atoi(geometry->property("y_size")->value()); } - if (which == static_cast (&edit_pane)) { + if (which == static_cast (&edit_pane)) { - if (done[0]) { + if (done) { return; } if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) { - pos = 75; + /* initial allocation is 90% to canvas, 10% to notebook */ + pos = (int) floor (alloc.get_width() * 0.90f); snprintf (buf, sizeof(buf), "%d", pos); } else { pos = atoi (prop->value()); } - - if ((done[0] = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) { + + if ((done = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) { edit_pane.set_position (pos); } } } void -Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w) +Editor::detach_tearoff (Box* b, Window* w) { if (tools_tearoff->torn_off() && mouse_mode_tearoff->torn_off()) { top_hbox.remove (toolbar_frame); } - - ensure_float (*w); } void -Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n) +Editor::reattach_tearoff (Box* b, Window* w, int32_t n) { if (toolbar_frame.get_parent() == 0) { top_hbox.pack_end (toolbar_frame); @@ -3769,6 +3717,16 @@ Editor::set_show_measures (bool yn) } } +void +Editor::toggle_follow_playhead () +{ + RefPtr act = ActionManager::get_action (X_("Editor"), X_("ToggleFollowPlayhead")); + if (act) { + RefPtr tact = RefPtr::cast_dynamic(act); + set_follow_playhead (tact->get_active()); + } +} + void Editor::set_follow_playhead (bool yn) { @@ -3848,7 +3806,7 @@ Editor::playlist_deletion_dialog (Playlist* pl) "If deleted, audio files used by it alone by will cleaned."), pl->name())); - dialog.set_position (Gtk::WIN_POS_CENTER); + dialog.set_position (WIN_POS_CENTER); dialog.get_vbox()->pack_start (label); dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT); @@ -3927,11 +3885,87 @@ Editor::transport_punch_location() } } +bool +Editor::control_layout_scroll (GdkEventScroll* ev) +{ + switch (ev->direction) { + case GDK_SCROLL_UP: + scroll_tracks_up_line (); + return true; + break; + + case GDK_SCROLL_DOWN: + scroll_tracks_down_line (); + return true; + + default: + /* no left/right handling yet */ + break; + } + + return false; +} + void -Editor::set_layout_width(Gtk::Requisition *r) +Editor::snapshot_display_selection_changed () +{ + if (snapshot_display.get_selection()->count_selected_rows() > 0) { + + TreeModel::iterator i = snapshot_display.get_selection()->get_selected(); + + cerr << "snapshot selected\n"; + + Glib::ustring snap_name = (*i)[snapshot_display_columns.real_name]; + + cerr << "name is " << snap_name << endl; + + if (snap_name.length() == 0) { + return; + } + + if (session->snap_name() == snap_name) { + return; + } + + ARDOUR_UI::instance()->load_session(session->path(), string (snap_name)); + } +} + +bool +Editor::snapshot_display_button_press (GdkEventButton* ev) { - edit_controls_vbox.check_resize(); - int w = edit_controls_vbox.get_width(); - cerr << "set_layout_width() called w = " << w << endl; - controls_layout.set_size_request (w, -1); + return false; } + +void +Editor::redisplay_snapshots () +{ + if (session == 0) { + return; + } + + vector* states; + + if ((states = session->possible_states()) == 0) { + return; + } + + snapshot_display_model->clear (); + + for (vector::iterator i = states->begin(); i != states->end(); ++i) { + string statename = *(*i); + TreeModel::Row row = *(snapshot_display_model->append()); + row[snapshot_display_columns.visible_name] = statename; + row[snapshot_display_columns.real_name] = statename; + } + + delete states; +} + +void +Editor::session_state_saved (string snap_name) +{ + ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::session_state_saved), snap_name)); + redisplay_snapshots (); +} +