Remove idiocy.
[ardour2.git] / gtk2_ardour / panner.cc
blob8c5524b414325c8db1b8a55a97588716d473b9c3
1 /*
2 Copyright (C) 2000-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <iostream>
21 #include <iomanip>
22 #include <cstring>
23 #include "ardour/panner.h"
24 #include "panner.h"
25 #include "i18n.h"
27 using namespace std;
28 using namespace Gtk;
30 static const int triangle_size = 5;
32 PannerBar::PannerBar (Adjustment& adj, boost::shared_ptr<PBD::Controllable> c)
33 : BarController (adj, c)
35 set_style (BarController::Line);
38 PannerBar::~PannerBar ()
42 bool
43 PannerBar::expose (GdkEventExpose* ev)
45 Glib::RefPtr<Gdk::Window> win (darea.get_window());
46 Glib::RefPtr<Gdk::GC> gc (get_style()->get_base_gc (get_state()));
48 BarController::expose (ev);
50 /* now draw triangles for left, right and center */
52 GdkPoint points[3];
54 // left
56 points[0].x = 0;
57 points[0].y = 0;
59 points[1].x = triangle_size;
60 points[1].y = 0;
62 points[2].x = 0;
63 points[2].y = triangle_size;
65 gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
67 // center
69 points[0].x = (darea.get_width()/2 - triangle_size);
70 points[0].y = 0;
72 points[1].x = (darea.get_width()/2 + triangle_size);
73 points[1].y = 0;
75 points[2].x = darea.get_width()/2;
76 points[2].y = triangle_size - 1;
78 gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
80 // right
82 points[0].x = (darea.get_width() - triangle_size);
83 points[0].y = 0;
85 points[1].x = darea.get_width();
86 points[1].y = 0;
88 points[2].x = darea.get_width();
89 points[2].y = triangle_size;
91 gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
93 return true;
96 bool
97 PannerBar::button_press (GdkEventButton* ev)
99 if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS && ev->y < 10) {
100 if (ev->x < triangle_size) {
101 adjustment.set_value (adjustment.get_lower());
102 } else if (ev->x > (darea.get_width() - triangle_size)) {
103 adjustment.set_value (adjustment.get_upper());
104 } else if (ev->x > (darea.get_width()/2 - triangle_size) &&
105 ev->x < (darea.get_width()/2 + triangle_size)) {
106 adjustment.set_value (adjustment.get_lower() + ((adjustment.get_upper() - adjustment.get_lower()) / 2.0));
110 return BarController::button_press (ev);
113 bool
114 PannerBar::button_release (GdkEventButton* ev)
116 bool const r = BarController::button_release (ev);
118 /* get rid of any `C' labels that may exist */
119 queue_draw ();
120 return r;
123 bool
124 PannerBar::entry_input (double *new_value)
126 Entry* e = dynamic_cast<Entry*> (&spinner);
127 string const text = e->get_text ();
129 string digits;
130 string letters;
132 string const L = _("L");
133 string const C = _("C");
134 string const R = _("R");
136 for (string::size_type i = 0; i < text.length(); ++i) {
137 if (isdigit (text[i])) {
138 digits += text[i];
139 } else if (text[i] != '%') {
140 letters += text[i];
144 if (letters.empty()) {
145 /* no letter specified, so take any number as a percentage where
146 * 0 is left and 100 right */
147 *new_value = digits.empty() ? 0.5 : (atoi (digits.c_str()) / 100.0);
148 } else {
149 /* letter given, so value is a percentage to the extreme
150 * (e.g. 100L is full left, 1L is slightly left */
151 if (letters[0] == L[0] || letters[0] == tolower (L[0])) {
152 *new_value = digits.empty() ? 0 : (0.5 - atoi (digits.c_str()) / 200.0);
153 } else if (letters[0] == R[0] || letters[0] == tolower (R[0])) {
154 *new_value = digits.empty() ? 1 : 0.5 + atoi (digits.c_str()) / 200.0;
155 } else if (letters[0] == C[0] || letters[0] == tolower (C[0])) {
156 *new_value = 0.5;
160 return true;
163 bool
164 PannerBar::entry_output ()
166 Entry* e = dynamic_cast<Entry*> (&spinner);
167 e->set_text (value_as_string (spinner.get_adjustment()->get_value()));
168 return true;
171 string
172 PannerBar::value_as_string (double v) const
174 if (ARDOUR::Panner::equivalent (v, 0.5)) {
175 return _("C");
176 } else if (ARDOUR::Panner::equivalent (v, 0)) {
177 return _("L");
178 } else if (ARDOUR::Panner::equivalent (v, 1)) {
179 return _("R");
180 } else if (v < 0.5) {
181 std::stringstream s;
182 s << fixed << setprecision (0) << _("L") << ((0.5 - v) * 200) << "%";
183 return s.str();
184 } else if (v > 0.5) {
185 std::stringstream s;
186 s << fixed << setprecision (0) << _("R") << ((v -0.5) * 200) << "%";
187 return s.str ();
190 return "";
193 std::string
194 PannerBar::get_label (int& x)
196 double const value = spinner.get_adjustment()->get_value ();
198 if (ARDOUR::Panner::equivalent (value, 0.5)) {
200 /* centre: only display text during a drag */
202 if (!grabbed) {
203 return "";
206 } else {
208 /* non-centre: display text on the side of the panner which has more space */
210 Glib::RefPtr<Pango::Context> p = get_pango_context ();
211 Glib::RefPtr<Pango::Layout> l = Pango::Layout::create (p);
212 l->set_text (value_as_string (value));
214 Pango::Rectangle const ext = l->get_ink_extents ();
216 if (value < 0.5) {
217 x = (darea.get_width() - 4 - ext.get_width() / Pango::SCALE);
218 } else {
219 x = 4;
223 return value_as_string (value);