replace ::cast_dynamic() with relevant ActionManager::get_*_action() calls
[ardour.git] / gtk2_ardour / speaker_dialog.cc
index e265b2ed1b234b88f1b24954e158ecf0f24d8ade..00495a8000dfb9866f2fd952ee7a6a9380d389b9 100644 (file)
@@ -24,7 +24,7 @@
 #include "speaker_dialog.h"
 #include "gui_thread.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace ARDOUR;
 using namespace PBD;
@@ -33,30 +33,30 @@ using namespace Gtk;
 using namespace Gtkmm2ext;
 
 SpeakerDialog::SpeakerDialog ()
-        : ArdourDialog (_("Speaker Configuration"))
-        , aspect_frame ("", 0.5, 0.5, 1.0, false)
-        , azimuth_adjustment (0, 0.0, 360.0, 10.0, 1.0)
-        , azimuth_spinner (azimuth_adjustment)
-        , add_speaker_button (_("Add Speaker"))
+       : ArdourWindow (_("Speaker Configuration"))
+       , aspect_frame ("", 0.5, 0.5, 1.5, false)
+       , azimuth_adjustment (0, 0.0, 360.0, 10.0, 1.0)
+       , azimuth_spinner (azimuth_adjustment)
+       , add_speaker_button (_("Add Speaker"))
        , remove_speaker_button (_("Remove Speaker"))
        /* initialize to 0 so that set_selected works below */
        , selected_index (0)
        , ignore_speaker_position_change (false)
        , ignore_azimuth_change (false)
 {
-        side_vbox.set_homogeneous (false);
-        side_vbox.set_border_width (6);
-        side_vbox.set_spacing (6);
-        side_vbox.pack_start (add_speaker_button, false, false);
+       side_vbox.set_homogeneous (false);
+       side_vbox.set_border_width (6);
+       side_vbox.set_spacing (6);
+       side_vbox.pack_start (add_speaker_button, false, false);
 
-        aspect_frame.set_size_request (200, 200);
-        aspect_frame.set_shadow_type (SHADOW_NONE);
-        aspect_frame.add (darea);
+       aspect_frame.set_size_request (300, 200);
+       aspect_frame.set_shadow_type (SHADOW_NONE);
+       aspect_frame.add (darea);
 
-        hbox.set_spacing (6);
-        hbox.set_border_width (6);
-        hbox.pack_start (aspect_frame, true, true);
-        hbox.pack_start (side_vbox, true, true);
+       hbox.set_spacing (6);
+       hbox.set_border_width (6);
+       hbox.pack_start (aspect_frame, true, true);
+       hbox.pack_start (side_vbox, false, false);
 
        HBox* current_speaker_hbox = manage (new HBox);
        current_speaker_hbox->set_spacing (4);
@@ -64,23 +64,25 @@ SpeakerDialog::SpeakerDialog ()
        current_speaker_hbox->pack_start (azimuth_spinner, true, true);
        current_speaker_hbox->pack_start (remove_speaker_button, true, true);
 
-        get_vbox()->pack_start (hbox);
-        get_vbox()->pack_start (*current_speaker_hbox, true, true);
-        get_vbox()->show_all ();
+       VBox* vbox = manage (new VBox);
+       vbox->pack_start (hbox);
+       vbox->pack_start (*current_speaker_hbox, true, true);
+       vbox->show_all ();
+       add (*vbox);
 
-        darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
+       darea.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
 
-        darea.signal_size_allocate().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_size_allocate));
-        darea.signal_expose_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_expose_event));
-        darea.signal_button_press_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_button_press_event));
-        darea.signal_button_release_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_button_release_event));
-        darea.signal_motion_notify_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_motion_notify_event));
+       darea.signal_size_allocate().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_size_allocate));
+       darea.signal_expose_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_expose_event));
+       darea.signal_button_press_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_button_press_event));
+       darea.signal_button_release_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_button_release_event));
+       darea.signal_motion_notify_event().connect (sigc::mem_fun (*this, &SpeakerDialog::darea_motion_notify_event));
 
        add_speaker_button.signal_clicked().connect (sigc::mem_fun (*this, &SpeakerDialog::add_speaker));
        remove_speaker_button.signal_clicked().connect (sigc::mem_fun (*this, &SpeakerDialog::remove_speaker));
        azimuth_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &SpeakerDialog::azimuth_changed));
 
-        drag_index = -1;
+       drag_index = -1;
 
        /* selected index initialised to 0 above; this will set `no selection' and
           sensitize widgets accordingly.
@@ -89,15 +91,15 @@ SpeakerDialog::SpeakerDialog ()
 }
 
 void
-SpeakerDialog::set_speakers (boost::shared_ptr<Speakers> s) 
+SpeakerDialog::set_speakers (boost::shared_ptr<Speakers> s)
 {
-        _speakers = s;
+       _speakers = s;
 }
 
 boost::shared_ptr<Speakers>
 SpeakerDialog::get_speakers () const
 {
-        return _speakers.lock ();
+       return _speakers.lock ();
 }
 
 bool
@@ -116,7 +118,7 @@ SpeakerDialog::darea_expose_event (GdkEventExpose* event)
        cairo_set_line_width (cr, 1.0);
 
        cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
-        cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 1.0);
+       cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 1.0);
        cairo_fill_preserve (cr);
        cairo_clip (cr);
 
@@ -130,7 +132,7 @@ SpeakerDialog::darea_expose_event (GdkEventExpose* event)
        cairo_stroke (cr);
 
        /* vertical line of "crosshairs" */
-       
+
        cairo_move_to (cr, width/2+0.5, 0.5);
        cairo_line_to (cr, width/2+0.5, height+0.5);
        cairo_stroke (cr);
@@ -140,59 +142,69 @@ SpeakerDialog::darea_expose_event (GdkEventExpose* event)
        cairo_arc (cr, width/2, height/2, height/2, 0, 2.0 * M_PI);
        cairo_stroke (cr);
 
-        float arc_radius;
-        
-        cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-        
-        if (height < 100) {
-                cairo_set_font_size (cr, 10);
-                arc_radius = 2.0;
-        } else {
-                cairo_set_font_size (cr, 16);
-                arc_radius = 4.0;
-        }
-
-        int n = 0;
-        for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i) {
-                
-                Speaker& s (*i);
-                CartesianVector c (s.coords());
-                
-                cart_to_gtk (c);
-                
-                x = (gint) floor (c.x);
-                y = (gint) floor (c.y);
-                
-                /* XXX need to shift circles so that they are centered on the circle */
-                
-                cairo_arc (cr, x, y, arc_radius, 0, 2.0 * M_PI);
+       float arc_radius;
+
+       cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+
+       if (height < 100) {
+               cairo_set_font_size (cr, 10);
+               arc_radius = 2.0;
+       } else {
+               cairo_set_font_size (cr, 16);
+               arc_radius = 4.0;
+       }
+
+       int n = 0;
+       for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i) {
+
+               Speaker& s (*i);
+               CartesianVector c (s.coords());
+
+               cart_to_gtk (c);
+
+               /* We have already moved our plotting origin to x_origin, y_origin,
+                  so compensate for that.
+               */
+               c.x -= x_origin;
+               c.y -= y_origin;
+
+               x = (gint) floor (c.x);
+               y = (gint) floor (c.y);
+
+               /* XXX need to shift circles so that they are centered on the circle */
+
+               cairo_arc (cr, x, y, arc_radius, 0, 2.0 * M_PI);
                if (selected_index == n) {
                        cairo_set_source_rgb (cr, 0.8, 0.8, 0.2);
                } else {
                        cairo_set_source_rgb (cr, 0.8, 0.2, 0.1);
                }
-                cairo_close_path (cr);
-                cairo_fill (cr);
-                
-                cairo_move_to (cr, x + 6, y + 6);
-                
-                char buf[256];
-                snprintf (buf, sizeof (buf), "%d:%d", n+1, (int) lrint (s.angles().azi));
-                cairo_show_text (cr, buf);
-                ++n;
-        }
-
-        cairo_destroy (cr);
+               cairo_close_path (cr);
+               cairo_fill (cr);
+
+               cairo_move_to (cr, x + 6, y + 6);
+
+               char buf[256];
+               if (n == selected_index) {
+                       snprintf (buf, sizeof (buf), "%d:%d", n+1, (int) lrint (s.angles().azi));
+               } else {
+                       snprintf (buf, sizeof (buf), "%d", n + 1);
+               }
+               cairo_show_text (cr, buf);
+               ++n;
+       }
+
+       cairo_destroy (cr);
 
        return true;
-        
+
 }
 
 void
 SpeakerDialog::cart_to_gtk (CartesianVector& c) const
 {
        /* "c" uses a coordinate space that is:
-            
+
           center = 0.0
           dimension = 2.0 * 2.0
           so max values along each axis are -1..+1
@@ -205,8 +217,8 @@ SpeakerDialog::cart_to_gtk (CartesianVector& c) const
           0,height
        */
 
-       c.x = (width / 2) * (c.x + 1);
-       c.y = (height / 2) * (1 - c.y);
+       c.x = (width / 2) * (c.x + 1) + x_origin;
+       c.y = (height / 2) * (1 - c.y) + y_origin;
 
        /* XXX z-axis not handled - 2D for now */
 }
@@ -214,8 +226,8 @@ SpeakerDialog::cart_to_gtk (CartesianVector& c) const
 void
 SpeakerDialog::gtk_to_cart (CartesianVector& c) const
 {
-       c.x = (c.x / (width / 2.0)) - 1.0;
-       c.y = -((c.y / (height / 2.0)) - 1.0);
+       c.x = ((c.x - x_origin) / (width / 2.0)) - 1.0;
+       c.y = -(((c.y - y_origin) / (height / 2.0)) - 1.0);
 
        /* XXX z-axis not handled - 2D for now */
 }
@@ -225,7 +237,7 @@ SpeakerDialog::clamp_to_circle (double& x, double& y)
 {
        double azi, ele;
        double z = 0.0;
-        double l;
+       double l;
 
        PBD::cartesian_to_spherical (x, y, z, azi, ele, l);
        PBD::spherical_to_cartesian (azi, ele, 1.0, x, y, z);
@@ -237,12 +249,19 @@ SpeakerDialog::darea_size_allocate (Gtk::Allocation& alloc)
        width = alloc.get_width();
        height = alloc.get_height();
 
+       /* The allocation will (should) be rectangualar, but make the basic
+          drawing square; space to the right of the square is for over-hanging
+          text labels.
+       */
+       width = height;
+
        if (height > 100) {
                width -= 20;
                height -= 20;
        }
 
-       x_origin = (alloc.get_width() - width) / 2;
+       /* Put the x origin to the left of the rectangular allocation */
+       x_origin = (alloc.get_width() - width) / 3;
        y_origin = (alloc.get_height() - height) / 2;
 }
 
@@ -253,14 +272,14 @@ SpeakerDialog::darea_button_press_event (GdkEventButton *ev)
        if (!speakers) {
                return false;
        }
-       
+
        GdkModifierType state;
 
        if (ev->type == GDK_2BUTTON_PRESS && ev->button == 1) {
                return false;
        }
 
-        drag_index = -1;
+       drag_index = -1;
 
        switch (ev->button) {
        case 1:
@@ -300,7 +319,7 @@ SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
        if (!speakers) {
                return false;
        }
-       
+
        gint x, y;
        GdkModifierType state;
        bool ret = false;
@@ -312,7 +331,7 @@ SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
                state = (GdkModifierType) ev->state;
 
                if (Keyboard::modifier_state_contains (state, Keyboard::TertiaryModifier)) {
-                        
+
                        for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i) {
                                /* XXX DO SOMETHING TO SET SPEAKER BACK TO "normal" */
                        }
@@ -331,21 +350,21 @@ SpeakerDialog::darea_button_release_event (GdkEventButton *ev)
                y = (int) floor (ev->y);
                state = (GdkModifierType) ev->state;
 
-                ret = handle_motion (x, y, state);
+               ret = handle_motion (x, y, state);
                break;
 
        case 3:
                break;
 
        }
-        
-        drag_index = -1;
+
+       drag_index = -1;
 
        return ret;
 }
 
 int
-SpeakerDialog::find_closest_object (gdouble x, gdouble y) 
+SpeakerDialog::find_closest_object (gdouble x, gdouble y)
 {
        boost::shared_ptr<Speakers> speakers = _speakers.lock ();
        if (!speakers) {
@@ -355,13 +374,13 @@ SpeakerDialog::find_closest_object (gdouble x, gdouble y)
        float distance;
        float best_distance = FLT_MAX;
        int n = 0;
-        int which = -1;
+       int which = -1;
 
        for (vector<Speaker>::iterator i = speakers->speakers().begin(); i != speakers->speakers().end(); ++i, ++n) {
 
                Speaker& candidate (*i);
                CartesianVector c;
-        
+
                candidate.angles().cartesian (c);
                cart_to_gtk (c);
 
@@ -375,11 +394,11 @@ SpeakerDialog::find_closest_object (gdouble x, gdouble y)
                }
        }
 
-       if (best_distance > 20) { // arbitrary 
-                return -1;
+       if (best_distance > 20) { // arbitrary
+               return -1;
        }
 
-        return which;
+       return which;
 }
 
 bool
@@ -430,7 +449,7 @@ SpeakerDialog::handle_motion (gint evx, gint evy, GdkModifierType state)
        if (state & GDK_BUTTON1_MASK && !(state & GDK_BUTTON2_MASK)) {
                CartesianVector c;
                bool need_move = false;
-                Speaker& moving (speakers->speakers()[drag_index]);
+               Speaker& moving (speakers->speakers()[drag_index]);
 
                moving.angles().cartesian (c);
                cart_to_gtk (c);
@@ -449,18 +468,18 @@ SpeakerDialog::handle_motion (gint evx, gint evy, GdkModifierType state)
                        /* position actual signal on circle */
 
                        clamp_to_circle (cp.x, cp.y);
-                        
+
                        /* generate an angular representation and set drag target (GUI) position */
 
-                        AngularVector a;
+                       AngularVector a;
 
                        cp.angular (a);
 
-                        moving.move (a);
+                       moving.move (a);
 
                        queue_draw ();
                }
-       } 
+       }
 
        return true;
 }
@@ -472,7 +491,7 @@ SpeakerDialog::add_speaker ()
        if (!speakers) {
                return;
        }
-       
+
        speakers->add_speaker (PBD::AngularVector (0, 0, 0));
        queue_draw ();
 }
@@ -484,7 +503,7 @@ SpeakerDialog::set_selected (int i)
        if (!speakers) {
                return;
        }
-       
+
        if (i == selected_index) {
                return;
        }
@@ -493,10 +512,10 @@ SpeakerDialog::set_selected (int i)
        queue_draw ();
 
        selected_speaker_connection.disconnect ();
-       
+
        azimuth_spinner.set_sensitive (selected_index != -1);
        remove_speaker_button.set_sensitive (selected_index != -1);
-       
+
        if (selected_index != -1) {
                azimuth_adjustment.set_value (speakers->speakers()[selected_index].angles().azi);
                speakers->speakers()[selected_index].PositionChanged.connect (
@@ -520,7 +539,7 @@ SpeakerDialog::azimuth_changed ()
        if (ignore_azimuth_change) {
                return;
        }
-       
+
        ignore_speaker_position_change = true;
        speakers->move_speaker (speakers->speakers()[selected_index].id, PBD::AngularVector (azimuth_adjustment.get_value (), 0, 0));
        ignore_speaker_position_change = false;
@@ -535,20 +554,20 @@ SpeakerDialog::speaker_position_changed ()
        if (!speakers) {
                return;
        }
-       
+
        assert (selected_index != -1);
 
        if (ignore_speaker_position_change) {
                return;
        }
-       
+
        ignore_azimuth_change = true;
        azimuth_adjustment.set_value (speakers->speakers()[selected_index].angles().azi);
        ignore_azimuth_change = false;
 
        queue_draw ();
 }
-                                          
+
 void
 SpeakerDialog::remove_speaker ()
 {
@@ -556,11 +575,11 @@ SpeakerDialog::remove_speaker ()
        if (!speakers) {
                return;
        }
-       
+
        assert (selected_index != -1);
 
        speakers->remove_speaker (speakers->speakers()[selected_index].id);
        set_selected (-1);
-       
+
        queue_draw ();
 }