1 # This file is part of jack_mixer
3 # Copyright (C) 2006 Nedko Arnaudov <nedko@arnaudov.name>
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 from gi
.repository
import Gtk
19 from gi
.repository
import Gdk
20 from gi
.repository
import GObject
23 class AdjustmentdBFS(Gtk
.Adjustment
):
24 def __init__(self
, scale
, default_db
, step_inc
):
25 self
.default_value
= scale
.db_to_scale(default_db
)
28 self
.step_increment
= step_inc
29 Gtk
.Adjustment
.__init
__(self
, self
.default_value
, 0.0, 1.0, 0.02)
30 self
.connect("value-changed", self
.on_value_changed
)
31 self
.disable_value_notify
= False
34 self
.set_value(self
.get_value() + self
.step_increment
)
37 self
.set_value(self
.get_value() - self
.step_increment
)
40 self
.set_value(self
.default_value
)
42 def get_value_db(self
):
45 def set_value_db(self
, db
):
47 self
.disable_value_notify
= True
48 self
.set_value(self
.scale
.db_to_scale(db
))
49 self
.disable_value_notify
= False
50 self
.emit("volume-changed")
52 def on_value_changed(self
, adjustment
):
53 if not self
.disable_value_notify
:
54 self
.db
= self
.scale
.scale_to_db(self
.get_value())
55 self
.emit("volume-changed")
57 def set_scale(self
, scale
):
59 self
.disable_value_notify
= True
60 self
.set_value(self
.scale
.db_to_scale(self
.db
))
61 self
.disable_value_notify
= False
63 GObject
.signal_new("volume-changed", AdjustmentdBFS
,
64 GObject
.SignalFlags
.RUN_FIRST | GObject
.SignalFlags
.ACTION
, None, [])
67 class GtkSlider(Gtk
.VScale
):
68 def __init__(self
, adjustment
):
69 Gtk
.VScale
.__init
__(self
)#, adjustment)
70 self
.set_adjustment(adjustment
)
71 self
.set_draw_value(False)
72 self
.set_inverted(True)
74 # HACK: we want the behaviour you get with the middle button, so we
75 # mangle the events. Clicking with other buttons moves the slider in
76 # step increments, clicking with the middle button moves the slider
77 # to the location of the click.
78 self
.connect('button-press-event', self
.button_press_event
)
79 self
.connect('button-release-event', self
.button_release_event
)
81 def button_press_event(self
, widget
, event
):
82 print("button press", event
.button
)
86 def button_release_event(self
, widget
, event
):
91 class CustomSliderWidget(Gtk
.DrawingArea
):
92 def __init__(self
, adjustment
):
93 Gtk
.DrawingArea
.__init
__(self
)
95 self
.adjustment
= adjustment
97 self
.connect("draw", self
.on_expose
)
98 self
.connect("size_allocate", self
.on_size_allocate
)
99 adjustment
.connect("value-changed", self
.on_value_changed
)
100 self
.connect("button-press-event", self
.on_mouse
)
101 self
.connect("motion-notify-event", self
.on_mouse
)
102 self
.connect("scroll-event", self
.on_scroll
)
103 self
.set_events(Gdk
.EventMask
.BUTTON1_MOTION_MASK |
104 Gdk
.EventMask
.SCROLL_MASK | Gdk
.EventMask
.BUTTON_PRESS_MASK
)
106 def on_scroll(self
, widget
, event
):
107 delta
= self
.adjustment
.step_increment
108 value
= self
.adjustment
.get_value()
109 if event
.direction
== Gdk
.ScrollDirection
.UP
:
111 elif event
.direction
== Gdk
.ScrollDirection
.DOWN
:
117 self
.adjustment
.set_value(y
)
120 def on_mouse(self
, widget
, event
):
121 if event
.type == Gdk
.EventType
.BUTTON_PRESS
:
122 #print "mouse button %u pressed %u:%u" % (event.button, event.x, event.y)
123 if event
.button
== 1:
124 if event
.y
>= self
.slider_rail_up
and event
.y
< self
.slider_rail_up
+ self
.slider_rail_height
:
125 self
.adjustment
.set_value(1 - float(event
.y
- self
.slider_rail_up
)/float(self
.slider_rail_height
))
126 elif event
.type == Gdk
.EventType
.MOTION_NOTIFY
:
127 #print "mouse motion %u:%u" % (event.x, event.y)
128 if event
.y
< self
.slider_rail_up
:
129 y
= self
.slider_rail_up
130 elif event
.y
> self
.slider_rail_up
+ self
.slider_rail_height
:
131 y
= self
.slider_rail_up
+ self
.slider_rail_height
134 self
.adjustment
.set_value(1 - float(y
- self
.slider_rail_up
)/float(self
.slider_rail_height
))
138 def on_value_changed(self
, adjustment
):
139 self
.invalidate_all()
141 def on_expose(self
, widget
, cairo_ctx
):
147 def get_preferred_width(self
, widget
):
148 minimal_width
= natural_width
= self
.width
149 return (minimal_width
, natural_width
)
151 def get_preferred_height(self
, widget
):
152 requisition
= Gtk
.Requisition()
153 on_size_request(self
, widget
, requisition
)
154 minimal_height
= natural_heigt
= requisition
.height
155 return (minimal_height
, natural_height
)
158 def on_size_allocate(self
, widget
, allocation
):
159 self
.width
= float(allocation
.width
)
160 self
.height
= float(allocation
.height
)
163 def on_size_request(self
, widget
, requisition
):
164 #print "size-request, %u x %u" % (requisition.width, requisition.height)
165 requisition
.width
= 20
168 def invalidate_all(self
):
169 self
.queue_draw_area(0, 0, int(self
.width
), int(self
.height
))
171 def draw(self
, cairo_ctx
):
173 state
= Gtk
.StateType
.PRELIGHT
175 state
= Gtk
.StateType
.NORMAL
177 #cairo_ctx.rectangle(0, 0, self.width, self.height)
178 #cairo_ctx.set_source_color(self.style.bg[state])
179 #cairo_ctx.fill_preserve()
180 #Gdk.cairo_set_source_color(cairo_ctx,
181 # self.get_style_context().get_color(state).to_color())
184 slider_knob_width
= self
.width
* 3 / 4
185 slider_knob_height
= self
.width
* 3 / 2
186 slider_knob_height
-= slider_knob_height
% 2
187 slider_knob_height
+= 1
189 slider_x
= self
.width
/2
191 cairo_ctx
.set_line_width(1)
194 Gdk
.cairo_set_source_color(cairo_ctx
,
195 self
.get_style_context().get_color(state
).to_color())
196 self
.slider_rail_up
= slider_knob_height
/2 + (self
.width
- slider_knob_width
)/2
197 self
.slider_rail_height
= self
.height
- 2 * self
.slider_rail_up
198 cairo_ctx
.move_to(slider_x
, self
.slider_rail_up
)
199 cairo_ctx
.line_to(slider_x
, self
.slider_rail_height
+ self
.slider_rail_up
)
203 slider_y
= round(self
.slider_rail_up
+ self
.slider_rail_height
* (1 - self
.adjustment
.get_value()))
204 lg
= cairo
.LinearGradient(slider_x
-
205 float(slider_knob_width
)/2, slider_y
- slider_knob_height
/2,
206 slider_x
- float(slider_knob_width
)/2, slider_y
+
207 slider_knob_height
/2)
209 lg
.add_color_stop_rgba(0, 0.55, 0.55, 0.55, slider_alpha
)
210 lg
.add_color_stop_rgba(0.1, 0.65, 0.65, 0.65, slider_alpha
)
211 lg
.add_color_stop_rgba(0.1, 0.75, 0.75, 0.75, slider_alpha
)
212 lg
.add_color_stop_rgba(0.125, 0.75, 0.75, 0.75, slider_alpha
)
213 lg
.add_color_stop_rgba(0.125, 0.15, 0.15, 0.15, slider_alpha
)
214 lg
.add_color_stop_rgba(0.475, 0.35, 0.35, 0.35, slider_alpha
)
215 lg
.add_color_stop_rgba(0.475, 0, 0, 0, slider_alpha
)
216 lg
.add_color_stop_rgba(0.525, 0, 0, 0, slider_alpha
)
217 lg
.add_color_stop_rgba(0.525, 0.35, 0.35, 0.35, slider_alpha
)
218 lg
.add_color_stop_rgba(0.875, 0.65, 0.65, 0.65, slider_alpha
)
219 lg
.add_color_stop_rgba(0.875, 0.75, 0.75, 0.75, slider_alpha
)
220 lg
.add_color_stop_rgba(0.900, 0.75, 0.75, 0.75, slider_alpha
)
221 lg
.add_color_stop_rgba(0.900, 0.15, 0.15, 0.15, slider_alpha
)
222 lg
.add_color_stop_rgba(1.000, 0.10, 0.10, 0.10, slider_alpha
)
223 cairo_ctx
.rectangle(slider_x
- float(slider_knob_width
)/2,
224 slider_y
- slider_knob_height
/2,
225 float(slider_knob_width
),
227 Gdk
.cairo_set_source_color(cairo_ctx
,
228 self
.get_style_context().get_background_color(state
).to_color())
229 cairo_ctx
.fill_preserve()
230 cairo_ctx
.set_source(lg
)