Strip trailing whitespace and fix other whitespace errors (e.g. space/tab mixing...
[ardour.git] / gtk2_ardour / panner.cc
index bb9b43218426bfe33219f85527cb98bc6cac99ca..8c5524b414325c8db1b8a55a97588716d473b9c3 100644 (file)
@@ -1,22 +1,36 @@
-#include <iostream>
+/*
+    Copyright (C) 2000-2007 Paul Davis
 
-#include "panner.h"
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
 
-using namespace std;
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
 
-static const int triangle_size = 5;
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-static void
-null_label_callback (char* buf, unsigned int bufsize)
-{
-       /* no label */
+*/
 
-       buf[0] = '\0';
-}
+#include <iostream>
+#include <iomanip>
+#include <cstring>
+#include "ardour/panner.h"
+#include "panner.h"
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
 
+static const int triangle_size = 5;
 
-PannerBar::PannerBar (Gtk::Adjustment& adj, PBD::Controllable& c)
-       : BarController (adj, c, sigc::ptr_fun (null_label_callback))
+PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
+       : BarController (adj, c)
 {
        set_style (BarController::Line);
 }
@@ -38,13 +52,13 @@ PannerBar::expose (GdkEventExpose* ev)
        GdkPoint points[3];
 
        // left
-       
+
        points[0].x = 0;
        points[0].y = 0;
 
        points[1].x = triangle_size;
        points[1].y = 0;
-       
+
        points[2].x = 0;
        points[2].y = triangle_size;
 
@@ -55,23 +69,23 @@ PannerBar::expose (GdkEventExpose* ev)
        points[0].x = (darea.get_width()/2 - triangle_size);
        points[0].y = 0;
 
-       points[1].x = (darea.get_width()/2 + triangle_size) - 1;
+       points[1].x = (darea.get_width()/2 + triangle_size);
        points[1].y = 0;
-       
-       points[2].x = darea.get_width()/2 - 1;
+
+       points[2].x = darea.get_width()/2;
        points[2].y = triangle_size - 1;
 
-       gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3); 
+       gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
 
        // right
 
-       points[0].x = (darea.get_width() - triangle_size) - 1;
+       points[0].x = (darea.get_width() - triangle_size);
        points[0].y = 0;
 
-       points[1].x = darea.get_width() - 1;
+       points[1].x = darea.get_width();
        points[1].y = 0;
-       
-       points[2].x = darea.get_width() - 1;
+
+       points[2].x = darea.get_width();
        points[2].y = triangle_size;
 
        gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
@@ -99,6 +113,112 @@ PannerBar::button_press (GdkEventButton* ev)
 bool
 PannerBar::button_release (GdkEventButton* ev)
 {
-       return BarController::button_release (ev);
+       bool const r = BarController::button_release (ev);
+
+       /* get rid of any `C' labels that may exist */
+       queue_draw ();
+       return r;
 }
 
+bool
+PannerBar::entry_input (double *new_value)
+{
+       Entry* e = dynamic_cast<Entry*> (&spinner);
+       string const text = e->get_text ();
+
+       string digits;
+       string letters;
+
+       string const L = _("L");
+       string const C = _("C");
+       string const R = _("R");
+
+       for (string::size_type i = 0; i < text.length(); ++i) {
+               if (isdigit (text[i])) {
+                       digits += text[i];
+               } else if (text[i] != '%') {
+                       letters += text[i];
+               }
+       }
+
+       if (letters.empty()) {
+               /* no letter specified, so take any number as a percentage where
+                * 0 is left and 100 right */
+               *new_value = digits.empty() ? 0.5 : (atoi (digits.c_str()) / 100.0);
+       } else {
+               /* letter given, so value is a percentage to the extreme
+                * (e.g. 100L is full left, 1L is slightly left */
+               if (letters[0] == L[0] || letters[0] == tolower (L[0])) {
+                       *new_value = digits.empty() ? 0 : (0.5 - atoi (digits.c_str()) / 200.0);
+               } else if (letters[0] == R[0] || letters[0] == tolower (R[0])) {
+                       *new_value = digits.empty() ? 1 : 0.5 + atoi (digits.c_str()) / 200.0;
+               } else if (letters[0] == C[0] || letters[0] == tolower (C[0])) {
+                       *new_value = 0.5;
+               }
+       }
+
+       return true;
+}
+
+bool
+PannerBar::entry_output ()
+{
+       Entry* e = dynamic_cast<Entry*> (&spinner);
+       e->set_text (value_as_string (spinner.get_adjustment()->get_value()));
+       return true;
+}
+
+string
+PannerBar::value_as_string (double v) const
+{
+       if (ARDOUR::Panner::equivalent (v, 0.5)) {
+               return _("C");
+       } else if (ARDOUR::Panner::equivalent (v, 0)) {
+               return _("L");
+       } else if (ARDOUR::Panner::equivalent (v, 1)) {
+               return _("R");
+       } else if (v < 0.5) {
+               std::stringstream s;
+               s << fixed << setprecision (0) << _("L") << ((0.5 - v) * 200) << "%";
+               return s.str();
+       } else if (v > 0.5) {
+               std::stringstream s;
+               s << fixed << setprecision (0) << _("R") << ((v -0.5) * 200) << "%";
+               return s.str ();
+       }
+
+       return "";
+}
+
+std::string
+PannerBar::get_label (int& x)
+{
+       double const value = spinner.get_adjustment()->get_value ();
+
+       if (ARDOUR::Panner::equivalent (value, 0.5)) {
+
+               /* centre: only display text during a drag */
+
+               if (!grabbed) {
+                       return "";
+               }
+
+       } else {
+
+               /* non-centre: display text on the side of the panner which has more space */
+
+               Glib::RefPtr<Pango::Context> p = get_pango_context ();
+               Glib::RefPtr<Pango::Layout> l = Pango::Layout::create (p);
+               l->set_text (value_as_string (value));
+
+               Pango::Rectangle const ext = l->get_ink_extents ();
+
+               if (value < 0.5) {
+                       x = (darea.get_width() - 4 - ext.get_width() / Pango::SCALE);
+               } else {
+                       x = 4;
+               }
+       }
+
+       return value_as_string (value);
+}