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.
23 #include "ardour/panner.h"
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 ()
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 */
59 points
[1].x
= triangle_size
;
63 points
[2].y
= triangle_size
;
65 gdk_draw_polygon (win
->gobj(), gc
->gobj(), true, points
, 3);
69 points
[0].x
= (darea
.get_width()/2 - triangle_size
);
72 points
[1].x
= (darea
.get_width()/2 + triangle_size
);
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);
82 points
[0].x
= (darea
.get_width() - triangle_size
);
85 points
[1].x
= darea
.get_width();
88 points
[2].x
= darea
.get_width();
89 points
[2].y
= triangle_size
;
91 gdk_draw_polygon (win
->gobj(), gc
->gobj(), true, points
, 3);
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
);
114 PannerBar::button_release (GdkEventButton
* ev
)
116 bool const r
= BarController::button_release (ev
);
118 /* get rid of any `C' labels that may exist */
124 PannerBar::entry_input (double *new_value
)
126 Entry
* e
= dynamic_cast<Entry
*> (&spinner
);
127 string
const text
= e
->get_text ();
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
])) {
139 } else if (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);
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])) {
164 PannerBar::entry_output ()
166 Entry
* e
= dynamic_cast<Entry
*> (&spinner
);
167 e
->set_text (value_as_string (spinner
.get_adjustment()->get_value()));
172 PannerBar::value_as_string (double v
) const
174 if (ARDOUR::Panner::equivalent (v
, 0.5)) {
176 } else if (ARDOUR::Panner::equivalent (v
, 0)) {
178 } else if (ARDOUR::Panner::equivalent (v
, 1)) {
180 } else if (v
< 0.5) {
182 s
<< fixed
<< setprecision (0) << _("L") << ((0.5 - v
) * 200) << "%";
184 } else if (v
> 0.5) {
186 s
<< fixed
<< setprecision (0) << _("R") << ((v
-0.5) * 200) << "%";
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 */
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 ();
217 x
= (darea
.get_width() - 4 - ext
.get_width() / Pango::SCALE
);
223 return value_as_string (value
);