more tweaks/fixes for region layer editor
[ardour.git] / gtk2_ardour / editor.cc
index 133e34b8a8bb6dfe65fd0942d8d9806f09d88902..c78ea9540e59772f7bd6d6e7524fe96567f2d506 100644 (file)
@@ -82,6 +82,7 @@
 #include "sfdb_ui.h"
 #include "rhythm_ferret.h"
 #include "actions.h"
+#include "region_layering_order_editor.h"
 
 #ifdef FFT_ANALYSIS
 #include "analysis_window.h"
@@ -196,6 +197,27 @@ DragInfo::clear_copied_locations ()
        copied_locations.clear ();
 }
 
+#ifdef GTKOSX
+static void
+pane_size_watcher (Paned* pane)
+{
+       /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
+          it is no longer accessible. so stop that. this doesn't happen on X11,
+          just the quartz backend.
+          
+          ugh.
+       */
+
+       int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 25;
+
+       gint pos = pane->get_position ();
+
+       if (pos > max_width_of_lhs) {
+               pane->set_position (max_width_of_lhs);
+       }
+}
+#endif
+
 Editor::Editor ()
        : 
          /* time display buttons */
@@ -346,6 +368,7 @@ Editor::Editor ()
        _dragging_hscrollbar = false;
        select_new_marker = false;
        rhythm_ferret = 0;
+       layering_order_editor = 0;
        allow_vertical_scroll = false;
        no_save_visual = false;
        need_resize_line = false;
@@ -722,6 +745,10 @@ Editor::Editor ()
        edit_pane.pack2 (the_notebook, false, true);
        
        edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
+#ifdef GTKOSX
+       Glib::PropertyProxy<int> proxy = edit_pane.property_position();
+       proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
+#endif
 
        top_hbox.pack_start (toolbar_frame, true, true);
 
@@ -1635,21 +1662,21 @@ Editor::build_track_region_context_menu (nframes64_t frame)
                boost::shared_ptr<Playlist> pl;
                
                if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
-                       Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed()));
+
+                       nframes64_t frame_pos = (nframes64_t) floor ((double)frame * ds->speed());
+                       uint32_t regions_at = pl->count_regions_at (frame_pos);
 
                        if (selection->regions.size() > 1) {
                                // there's already a multiple selection: just add a 
                                // single region context menu that will act on all 
                                // selected regions
                                boost::shared_ptr<Region> dummy_region; // = NULL               
-                               add_region_context_items (atv->audio_view(), dummy_region, edit_items);                 
+                               add_region_context_items (atv->audio_view(), dummy_region, edit_items, frame_pos, regions_at > 1);
                        } else {
-                               for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-                                       add_region_context_items (atv->audio_view(), (*i), edit_items);
-                               }
+                               // Find the topmost region and make the context menu for it
+                               boost::shared_ptr<Region> top_region = pl->top_region_at (frame_pos);
+                               add_region_context_items (atv->audio_view(), top_region, edit_items, frame_pos, regions_at > 1);
                        }
-
-                       delete regions;
                }
        }
 
@@ -1674,7 +1701,6 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
 
                if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) {
 
-                       Playlist::RegionList* regions = pl->regions_at (frame);
                        AudioPlaylist::Crossfades xfades;
 
                        apl->crossfades_at (frame, xfades);
@@ -1685,18 +1711,20 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
                                add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
                        }
 
-                       if (selection->regions.size() > 1) {
-                               // there's already a multiple selection: just add a 
-                               // single region context menu that will act on all 
-                               // selected regions
-                               boost::shared_ptr<Region> dummy_region; // = NULL               
-                               add_region_context_items (atv->audio_view(), dummy_region, edit_items);                 
-                       } else {
-                               for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
-                                       add_region_context_items (atv->audio_view(), (*i), edit_items);
-                               }
+                       nframes64_t frame_pos = (nframes64_t) floor ((double)frame * ds->speed());
+                       uint32_t regions_at = pl->count_regions_at (frame_pos);
+
+                       if (selection->regions.size() > 1) {
+                               // there's already a multiple selection: just add a
+                               // single region context menu that will act on all
+                               // selected regions
+                               boost::shared_ptr<Region> dummy_region; // = NULL
+                               add_region_context_items (atv->audio_view(), dummy_region, edit_items, frame_pos, regions_at > 1); // OR frame ???
+                       } else {
+                               // Find the topmost region and make the context menu for it
+                               boost::shared_ptr<Region> top_region = pl->top_region_at (frame_pos);
+                               add_region_context_items (atv->audio_view(), top_region, edit_items, frame_pos, regions_at > 1);  // OR frame ???
                        }
-                       delete regions;
                }
        }
 
@@ -1817,7 +1845,8 @@ Editor::xfade_edit_right_region ()
 }
 
 void
-Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items)
+Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items, 
+                                 nframes64_t position, bool multiple_region_at_position)
 {
        using namespace Menu_Helpers;
        Gtk::MenuItem* foo_item;
@@ -1843,13 +1872,16 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
                );
 
                items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
-               items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+               items.push_back (MenuElem (_("Region Editor"), mem_fun(*this, &Editor::edit_region)));
        }
 
        items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
        items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
        items.push_back (SeparatorElem());
        items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
+       if (_edit_point == EditAtMouse) {
+               items.back ().set_sensitive (false);
+       }
        items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
        items.push_back (SeparatorElem());
 
@@ -2040,6 +2072,9 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
        }
        
        edit_items.push_back (MenuElem (menu_item_name, *region_menu));
+       if (multiple_region_at_position && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
+               edit_items.push_back (MenuElem (_("Choose top region"), (bind (mem_fun(*this, &Editor::change_region_layering_order), position))));
+       }
        edit_items.push_back (SeparatorElem());
 }
 
@@ -3043,7 +3078,9 @@ Editor::setup_toolbar ()
        edit_point_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_point_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point"));
 
-       snap_box.pack_start (edit_point_clock, false, false);
+       if (Profile->get_sae()) {
+               snap_box.pack_start (edit_point_clock, false, false);
+       }
        snap_box.pack_start (snap_mode_selector, false, false);
        snap_box.pack_start (snap_type_selector, false, false);
        snap_box.pack_start (edit_point_selector, false, false);
@@ -5078,3 +5115,40 @@ Editor::idle_resize ()
        resize_idle_id = -1;
        return false;
 }
+
+void
+Editor::change_region_layering_order (nframes64_t position)
+{
+       if (clicked_regionview == 0) {
+                if (layering_order_editor) {
+                        layering_order_editor->hide ();
+                }
+               return;
+       }
+
+       AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
+
+       if (atv == 0) {
+               return;
+       }
+
+       boost::shared_ptr<Diskstream> ds;
+       boost::shared_ptr<Playlist> pl;
+
+       if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+               
+               if (layering_order_editor == 0) {
+                       layering_order_editor = new RegionLayeringOrderEditor(*this);
+               }
+               layering_order_editor->set_context (atv->name(), session, pl, position);
+               layering_order_editor->maybe_present ();
+       }
+}
+
+void
+Editor::update_region_layering_order_editor (nframes64_t frame)
+{
+       if (layering_order_editor && layering_order_editor->is_visible ()) {
+               change_region_layering_order (frame);
+       }
+}