Move mouse cursor stuff out of Editor into its own class.
[ardour.git] / gtk2_ardour / editor.cc
index b50acd52533bac680d02c82cd699c866b9b74b1d..d19f5f6424d35edac0a1cc6dada990465bf230b8 100644 (file)
@@ -19,7 +19,6 @@
 
 /* Note: public Editor methods are documented in public_editor.h */
 
-#define __STDC_LIMIT_MACROS 1
 #include <stdint.h>
 #include <unistd.h>
 #include <cstdlib>
 #include "editor_snapshots.h"
 #include "editor_summary.h"
 #include "region_layering_order_editor.h"
+#include "mouse_cursors.h"
+#include "editor_cursors.h"
 
 #include "i18n.h"
 
@@ -137,8 +138,6 @@ using Gtkmm2ext::Keyboard;
 
 const double Editor::timebar_height = 15.0;
 
-#include "editor_xpms"
-
 static const gchar *_snap_type_strings[] = {
        N_("CD Frames"),
        N_("Timecode Frames"),
@@ -208,32 +207,6 @@ static const gchar *_rb_opt_strings[] = {
 };
 #endif
 
-/* Soundfile  drag-n-drop */
-
-Gdk::Cursor* Editor::cross_hair_cursor = 0;
-Gdk::Cursor* Editor::selector_cursor = 0;
-Gdk::Cursor* Editor::trimmer_cursor = 0;
-Gdk::Cursor* Editor::left_side_trim_cursor = 0;
-Gdk::Cursor* Editor::right_side_trim_cursor = 0;
-Gdk::Cursor* Editor::fade_in_cursor = 0;
-Gdk::Cursor* Editor::fade_out_cursor = 0;
-Gdk::Cursor* Editor::grabber_cursor = 0;
-Gdk::Cursor* Editor::grabber_note_cursor = 0;
-Gdk::Cursor* Editor::grabber_edit_point_cursor = 0;
-Gdk::Cursor* Editor::zoom_in_cursor = 0;
-Gdk::Cursor* Editor::zoom_out_cursor = 0;
-Gdk::Cursor* Editor::time_fx_cursor = 0;
-Gdk::Cursor* Editor::fader_cursor = 0;
-Gdk::Cursor* Editor::speaker_cursor = 0;
-Gdk::Cursor* Editor::midi_pencil_cursor = 0;
-Gdk::Cursor* Editor::midi_select_cursor = 0;
-Gdk::Cursor* Editor::midi_resize_cursor = 0;
-Gdk::Cursor* Editor::midi_erase_cursor = 0;
-Gdk::Cursor* Editor::wait_cursor = 0;
-Gdk::Cursor* Editor::timebar_cursor = 0;
-Gdk::Cursor* Editor::transparent_cursor = 0;
-Gdk::Cursor* Editor::up_down_cursor = 0;
-
 void
 show_me_the_size (Requisition* r, const char* what)
 {
@@ -506,7 +479,7 @@ Editor::Editor ()
        controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
        controls_layout_size_request_connection = controls_layout.signal_size_request().connect (sigc::mem_fun (*this, &Editor::controls_layout_size_request));
 
-       build_cursors ();
+       _cursors = new MouseCursors;
 
        ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas());
        ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(),
@@ -736,8 +709,12 @@ Editor::Editor ()
        TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), ui_bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
 
        _ignore_region_action = false;
+       _last_region_menu_was_main = false;
        _popup_region_menu_item = 0;
 
+       _show_marker_lines = false;
+       _over_region_trim_target = false;
+
        constructed = true;
        instant_save ();
 
@@ -810,7 +787,7 @@ Editor::set_entered_regionview (RegionView* rv)
                entered_regionview->entered (internal_editing ());
        }
 
-       if (!_all_region_actions_sensitized) {
+       if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
                /* This RegionView entry might have changed what region actions
                   are allowed, so sensitize them all in case a key is pressed.
                */
@@ -1207,111 +1184,19 @@ void
 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
 {
        if (a->get_name() == "RegionMenu") {
-               /* When the region menu is opened, we setup the actions so that they look right
-                  in the menu.
+               /* When the main menu's region menu is opened, we setup the actions so that they look right
+                  in the menu.  I can't find a way of getting a signal when this menu is subsequently closed,
+                  so we resensitize all region actions when the entered regionview or the region selection
+                  changes.  HOWEVER we can't always resensitize on entered_regionview change because that
+                  happens after the region context menu is opened.  So we set a flag here, too.
+
+                  What a carry on :(
                */
                sensitize_the_right_region_actions ();
+               _last_region_menu_was_main = true;
        }
 }
 
-void
-Editor::build_cursors ()
-{
-       using namespace Gdk;
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> zoom_in_cursor_pixbuf (::get_icon ("zoom_in_cursor"));
-               zoom_in_cursor = new Gdk::Cursor (Gdk::Display::get_default(), zoom_in_cursor_pixbuf, 5, 5);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> zoom_out_cursor_pixbuf (::get_icon ("zoom_out_cursor"));
-               zoom_out_cursor = new Gdk::Cursor (Gdk::Display::get_default(), zoom_out_cursor_pixbuf, 5, 5);
-       }
-       
-       Gdk::Color fbg ("#ffffff" );
-       Gdk::Color ffg  ("#000000" );
-
-       {
-               RefPtr<Bitmap> source, mask;
-
-               source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
-               mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
-               fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
-       }
-
-       {
-               RefPtr<Bitmap> source, mask;
-               source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
-               mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
-               speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
-       }
-
-       {
-               RefPtr<Bitmap> bits;
-               char pix[4] = { 0, 0, 0, 0 };
-               bits = Bitmap::create (pix, 2, 2);
-               Gdk::Color c;
-               transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
-       }
-
-       {
-               RefPtr<Bitmap> bits;
-               char pix[4] = { 0, 0, 0, 0 };
-               bits = Bitmap::create (pix, 2, 2);
-               Gdk::Color c;
-               transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> grabber_pixbuf (::get_icon ("grabber"));
-               grabber_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_pixbuf, 5, 0);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> grabber_note_pixbuf (::get_icon ("grabber_note"));
-               grabber_note_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_note_pixbuf, 5, 10);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> grabber_edit_point_pixbuf (::get_icon ("grabber_edit_point"));
-               grabber_edit_point_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_edit_point_pixbuf, 5, 17);
-       }
-
-       cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
-       trimmer_cursor =  new Gdk::Cursor (SB_H_DOUBLE_ARROW);
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("trim_left_cursor"));
-               left_side_trim_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 5, 11);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("trim_right_cursor"));
-               right_side_trim_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 23, 11);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("fade_in_cursor"));
-               fade_in_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 0, 40);
-       }
-
-       {
-               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("fade_out_cursor"));
-               fade_out_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 27, 40);
-       }
-
-       selector_cursor = new Gdk::Cursor (XTERM);
-       time_fx_cursor = new Gdk::Cursor (SIZING);
-       wait_cursor = new Gdk::Cursor  (WATCH);
-       timebar_cursor = new Gdk::Cursor(LEFT_PTR);
-       midi_pencil_cursor = new Gdk::Cursor (PENCIL);
-       midi_select_cursor = new Gdk::Cursor (CENTER_PTR);
-       midi_resize_cursor = new Gdk::Cursor (SIZING);
-       midi_erase_cursor = new Gdk::Cursor (DRAPED_BOX);
-       up_down_cursor = new Gdk::Cursor (Gdk::SB_V_DOUBLE_ARROW);
-}
-
 /** Pop up a context menu for when the user clicks on a fade in or fade out */
 void
 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
@@ -1470,10 +1355,10 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
 }
 
 void
-Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, framepos_t frame)
+Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
 {
        using namespace Menu_Helpers;
-       Menu* (Editor::*build_menu_function)(framepos_t);
+       Menu* (Editor::*build_menu_function)();
        Menu *menu;
 
        switch (item_type) {
@@ -1514,7 +1399,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
                return;
        }
 
-       menu = (this->*build_menu_function)(frame);
+       menu = (this->*build_menu_function)();
        menu->set_name ("ArdourContextMenu");
 
        /* now handle specific situations */
@@ -1586,11 +1471,18 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
                clicked_routeview->build_underlay_menu(menu);
        }
 
+       /* When the region menu is opened, we setup the actions so that they look right
+          in the menu.
+       */
+       sensitize_the_right_region_actions ();
+       _last_region_menu_was_main = false;
+
+       menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
        menu->popup (button, time);
 }
 
 Menu*
-Editor::build_track_context_menu (framepos_t)
+Editor::build_track_context_menu ()
 {
        using namespace Menu_Helpers;
 
@@ -1602,7 +1494,7 @@ Editor::build_track_context_menu (framepos_t)
 }
 
 Menu*
-Editor::build_track_bus_context_menu (framepos_t)
+Editor::build_track_bus_context_menu ()
 {
        using namespace Menu_Helpers;
 
@@ -1614,7 +1506,7 @@ Editor::build_track_bus_context_menu (framepos_t)
 }
 
 Menu*
-Editor::build_track_region_context_menu (framepos_t frame)
+Editor::build_track_region_context_menu ()
 {
        using namespace Menu_Helpers;
        MenuList& edit_items  = track_region_context_menu.items();
@@ -1636,7 +1528,7 @@ Editor::build_track_region_context_menu (framepos_t frame)
                   mode and so offering region context is somewhat confusing.
                */
                if ((tr = rtv->track()) && ((pl = tr->playlist())) && !internal_editing()) {
-                        framepos_t framepos = (framepos_t) floor ((double)frame * tr->speed());
+                        framepos_t const framepos = (framepos_t) floor ((double) get_preferred_edit_position() * tr->speed());
                         uint32_t regions_at = pl->count_regions_at (framepos);
                         add_region_context_items (edit_items, regions_at > 1);
                }
@@ -1648,7 +1540,7 @@ Editor::build_track_region_context_menu (framepos_t frame)
 }
 
 Menu*
-Editor::build_track_crossfade_context_menu (framepos_t frame)
+Editor::build_track_crossfade_context_menu ()
 {
        using namespace Menu_Helpers;
        MenuList& edit_items  = track_crossfade_context_menu.items();
@@ -1665,7 +1557,7 @@ Editor::build_track_crossfade_context_menu (framepos_t frame)
 
                        AudioPlaylist::Crossfades xfades;
 
-                       apl->crossfades_at (frame, xfades);
+                       apl->crossfades_at (get_preferred_edit_position (), xfades);
 
                        bool many = xfades.size() > 1;
 
@@ -1673,7 +1565,7 @@ Editor::build_track_crossfade_context_menu (framepos_t frame)
                                add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
                        }
 
-                       framepos_t framepos = (framepos_t) floor ((double)frame * tr->speed());
+                       framepos_t framepos = (framepos_t) floor ((double) get_preferred_edit_position() * tr->speed());
                        uint32_t regions_at = pl->count_regions_at (framepos);
                         add_region_context_items (edit_items, regions_at > 1);
                }
@@ -1721,7 +1613,7 @@ Editor::analyze_range_selection()
 }
 
 Menu*
-Editor::build_track_selection_context_menu (framepos_t)
+Editor::build_track_selection_context_menu ()
 {
        using namespace Menu_Helpers;
        MenuList& edit_items  = track_selection_context_menu.items();
@@ -1827,7 +1719,7 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, bool multi
 
        edit_items.push_back (*_popup_region_menu_item);
        if (multiple_regions_at_position && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
-               edit_items.push_back (action_menu_item ("choose-top-region"));
+               edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region")->create_menu_item ()));
        }
        edit_items.push_back (SeparatorElem());
 }
@@ -2328,38 +2220,45 @@ Editor::set_state (const XMLNode& node, int /*version*/)
        if ((prop = node.property ("show-editor-mixer"))) {
 
                Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
-               if (act) {
-
-                       Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-                       bool yn = string_is_affirmative (prop->value());
-
-                       /* do it twice to force the change */
+               assert (act);
 
-                       tact->set_active (!yn);
-                       tact->set_active (yn);
-               }
+               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+               bool yn = string_is_affirmative (prop->value());
+               
+               /* do it twice to force the change */
+               
+               tact->set_active (!yn);
+               tact->set_active (yn);
        }
 
        if ((prop = node.property ("show-editor-list"))) {
 
                Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
-               assert(act);
-               if (act) {
-
-                       Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-                       bool yn = string_is_affirmative (prop->value());
+               assert (act);
 
-                       /* do it twice to force the change */
-
-                       tact->set_active (!yn);
-                       tact->set_active (yn);
-               }
+               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+               bool yn = string_is_affirmative (prop->value());
+               
+               /* do it twice to force the change */
+               
+               tact->set_active (!yn);
+               tact->set_active (yn);
        }
 
        if ((prop = node.property (X_("editor-list-page")))) {
                the_notebook.set_current_page (atoi (prop->value ()));
        }
 
+       if ((prop = node.property (X_("show-marker-lines")))) {
+               Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
+               assert (act);
+               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
+               bool yn = string_is_affirmative (prop->value ());
+
+               tact->set_active (!yn);
+               tact->set_active (yn);
+       }
+
        XMLNodeList children = node.children ();
        for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
                selection->set_state (**i, Stateful::current_state_version);
@@ -2452,6 +2351,8 @@ Editor::get_state ()
        snprintf (buf, sizeof (buf), "%d", the_notebook.get_current_page ());
        node->add_property (X_("editor-list-page"), buf);
 
+       node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
+
        node->add_child_nocopy (selection->get_state ());
        node->add_child_nocopy (_regions->get_state ());
        
@@ -4068,6 +3969,7 @@ Editor::maximise_editing_space ()
                _tools_tearoff->set_visible (true);
                _zoom_tearoff->set_visible (true);
        }
+
 }
 
 void
@@ -4352,6 +4254,8 @@ Editor::post_zoom ()
        refresh_location_display();
        _summary->set_overlays_dirty ();
 
+       update_marker_labels ();
+
        instant_save ();
 }
 
@@ -5480,5 +5384,9 @@ Editor::setup_fade_images ()
 Gtk::MenuItem&
 Editor::action_menu_item (std::string const & name)
 {
-       return *manage (editor_actions->get_action(name)->create_menu_item ());
+       Glib::RefPtr<Action> a = editor_actions->get_action (name);
+       assert (a);
+       
+       return *manage (a->create_menu_item ());
 }
+