Package dtk :: Package ui :: Module spin

Source Code for Module dtk.ui.spin

  1  #! /usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (C) 2011 ~ 2012 Deepin, Inc. 
  5  #               2011 ~ 2012 Hou Shaohui 
  6  #  
  7  # Author:     Hou Shaohui <houshao55@gmail.com> 
  8  # Maintainer: Hou Shaohui <houshao55@gmail.com> 
  9  #  
 10  # This program is free software: you can redistribute it and/or modify 
 11  # it under the terms of the GNU General Public License as published by 
 12  # the Free Software Foundation, either version 3 of the License, or 
 13  # any later version. 
 14  #  
 15  # This program is distributed in the hope that it will be useful, 
 16  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  # GNU General Public License for more details. 
 19  #  
 20  # You should have received a copy of the GNU General Public License 
 21  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 22   
 23  from button import DisableButton 
 24  from entry import Entry 
 25  from theme import ui_theme 
 26  import gobject 
 27  import gtk 
 28  from utils import (alpha_color_hex_to_cairo, cairo_disable_antialias, 
 29                     color_hex_to_cairo, 
 30                     propagate_expose, is_float, remove_timeout_id) 
 31   
 32   
33 -class SpinBox(gtk.VBox):
34 ''' 35 SpinBox. 36 37 @undocumented: set_sensitive 38 @undocumented: size_change_cb 39 @undocumented: press_increase_button 40 @undocumented: press_decrease_button 41 @undocumented: handle_key_release 42 @undocumented: stop_update_value 43 @undocumented: increase_value 44 @undocumented: decrease_value 45 @undocumented: adjust_value 46 @undocumented: update 47 @undocumented: update_and_emit 48 @undocumented: expose_spin_bg 49 @undocumented: create_simple_button 50 ''' 51 52 __gsignals__ = { 53 "value-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,)), 54 "key-release" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,)), 55 } 56
57 - def __init__(self, 58 value=0, 59 lower=0, 60 upper=100, 61 step=10, 62 default_width=55):
63 ''' 64 Initialize SpinBox class. 65 66 @param value: Initialize value, default is 0. 67 @param lower: Lower value, default is 0. 68 @param upper: Upper value, default is 100. 69 @param step: Step value, default is 10. 70 @param default_width: Default with, default is 55 pixel. 71 ''' 72 gtk.VBox.__init__(self) 73 self.current_value = value 74 self.lower_value = lower 75 self.upper_value = upper 76 self.step_value = step 77 self.update_delay = 100 # milliseconds 78 self.increase_value_id = None 79 self.decrease_value_id = None 80 81 # Init. 82 self.default_width = default_width 83 self.default_height = 22 84 self.arrow_button_width = 19 85 self.background_color = ui_theme.get_alpha_color("text_entry_background") 86 self.acme_color = ui_theme.get_alpha_color("text_entry_acme") 87 self.point_color = ui_theme.get_alpha_color("text_entry_point") 88 self.frame_point_color = ui_theme.get_alpha_color("text_entry_frame_point") 89 self.frame_color = ui_theme.get_alpha_color("text_entry_frame") 90 91 # Widget. 92 arrow_up_button = self.create_simple_button("up", self.press_increase_button) 93 arrow_down_button = self.create_simple_button("down", self.press_decrease_button) 94 button_box = gtk.VBox() 95 button_box.pack_start(arrow_up_button, False, False) 96 button_box.pack_start(arrow_down_button, False, False) 97 self.value_entry = Entry(str(value)) 98 self.value_entry.check_text = is_float 99 100 self.main_align = gtk.Alignment() 101 self.main_align.set(0.5, 0.5, 0, 0) 102 hbox = gtk.HBox() 103 hbox.pack_start(self.value_entry, False, False) 104 hbox.pack_start(button_box, False, False) 105 hbox_align = gtk.Alignment() 106 hbox_align.set(0.5, 0.5, 1.0, 1.0) 107 hbox_align.set_padding(0, 1, 0, 0) 108 hbox_align.add(hbox) 109 self.main_align.add(hbox_align) 110 self.pack_start(self.main_align, False, False) 111 112 # Signals. 113 self.connect("size-allocate", self.size_change_cb) 114 self.main_align.connect("expose-event", self.expose_spin_bg)
115
116 - def set_sensitive(self, sensitive):
117 ''' 118 Internal function to wrap `set_sensitive`. 119 ''' 120 super(SpinBox, self).set_sensitive(sensitive) 121 self.value_entry.set_sensitive(sensitive)
122
123 - def get_value(self):
124 ''' 125 Get current value. 126 127 @return: Return current value. 128 ''' 129 return self.current_value
130
131 - def set_value(self, value):
132 ''' 133 Set value with given value. 134 135 @param value: New value. 136 ''' 137 new_value = self.adjust_value(value) 138 if new_value != self.current_value: 139 self.update_and_emit(new_value)
140
141 - def value_changed(self):
142 ''' 143 Emit `value-changed` signal. 144 ''' 145 self.emit("value-changed", self.current_value) 146
147 - def get_lower(self):
148 ''' 149 Get minimum value. 150 ''' 151 return self.lower_value 152
153 - def set_lower(self, value):
154 ''' 155 Set lower with given value. 156 157 @param value: New lower value. 158 ''' 159 self.lower_value = value
160
161 - def get_upper(self):
162 ''' 163 Get upper value. 164 ''' 165 return self.upper_value 166
167 - def set_upper(self, value):
168 ''' 169 Set upper with given value. 170 171 @param value: New upper value. 172 ''' 173 self.upper_value = value
174
175 - def get_step(self):
176 ''' 177 Get step. 178 ''' 179 return self.step_value
180
181 - def set_step(self, value):
182 ''' 183 Set step with given value. 184 185 @param value: New step value. 186 ''' 187 self.set_step = value
188
189 - def size_change_cb(self, widget, rect):
190 ''' 191 Internal callback for `size-allocate` signal. 192 ''' 193 if rect.width > self.default_width: 194 self.default_width = rect.width 195 196 self.set_size_request(self.default_width, self.default_height) 197 self.value_entry.set_size_request(self.default_width - self.arrow_button_width, self.default_height - 2) 198
199 - def press_increase_button(self, widget, event):
200 ''' 201 Internal callback when user press increase arrow. 202 ''' 203 self.stop_update_value() 204 205 self.increase_value() 206 207 self.increase_value_id = gtk.timeout_add(self.update_delay, self.increase_value)
208
209 - def press_decrease_button(self, widget, event):
210 ''' 211 Internal callback when user press decrease arrow. 212 ''' 213 self.stop_update_value() 214 215 self.decrease_value() 216 217 self.decrease_value_id = gtk.timeout_add(self.update_delay, self.decrease_value)
218
219 - def handle_key_release(self, widget, event):
220 ''' 221 Internal callback for `key-release-event` signal. 222 ''' 223 self.stop_update_value() 224 225 self.emit("key-release", self.current_value)
226
227 - def stop_update_value(self):
228 ''' 229 Internal function to stop update value. 230 ''' 231 for timeout_id in [self.increase_value_id, self.decrease_value_id]: 232 remove_timeout_id(timeout_id)
233
234 - def increase_value(self):
235 ''' 236 Internal function to increase valule. 237 ''' 238 new_value = self.current_value + self.step_value 239 if new_value > self.upper_value: 240 new_value = self.upper_value 241 if new_value != self.current_value: 242 self.update_and_emit(new_value) 243 244 return True 245
246 - def decrease_value(self):
247 ''' 248 Internal function to decrease valule. 249 ''' 250 new_value = self.current_value - self.step_value 251 if new_value < self.lower_value: 252 new_value = self.lower_value 253 if new_value != self.current_value: 254 self.update_and_emit(new_value) 255 256 return True 257
258 - def adjust_value(self, value):
259 ''' 260 Internal function to adjust value. 261 ''' 262 if not isinstance(value, int): 263 return self.current_value 264 else: 265 if value < self.lower_value: 266 return self.lower_value 267 elif value > self.upper_value: 268 return self.upper_value 269 else: 270 return value 271
272 - def update(self, new_value):
273 ''' 274 Internal function to update value, just use when need avoid emit signal recursively. 275 ''' 276 self.current_value = new_value 277 self.value_entry.set_text(str(self.current_value))
278
279 - def update_and_emit(self, new_value):
280 ''' 281 Internal function to update new value and emit `value-changed` signal. 282 ''' 283 self.current_value = new_value 284 self.value_entry.set_text(str(self.current_value)) 285 self.emit("value-changed", self.current_value) 286
287 - def expose_spin_bg(self, widget, event):
288 ''' 289 Internal callback for `expose-event` signal. 290 ''' 291 # Init. 292 cr = widget.window.cairo_create() 293 rect = widget.allocation 294 x, y, w, h = rect.x, rect.y, rect.width, rect.height 295 296 # Draw frame. 297 with cairo_disable_antialias(cr): 298 cr.set_line_width(1) 299 if widget.state == gtk.STATE_INSENSITIVE: 300 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_frame").get_color())) 301 else: 302 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color())) 303 cr.rectangle(rect.x, rect.y, rect.width, rect.height) 304 cr.stroke() 305 306 if widget.state == gtk.STATE_INSENSITIVE: 307 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("disable_background").get_color(), 0.9))) 308 else: 309 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9))) 310 cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1) 311 cr.fill() 312 313 propagate_expose(widget, event) 314 315 return False 316
317 - def create_simple_button(self, name, callback=None):
318 ''' 319 Internal function to create simple button. 320 ''' 321 button = DisableButton( 322 (ui_theme.get_pixbuf("spin/spin_arrow_%s_normal.png" % name), 323 ui_theme.get_pixbuf("spin/spin_arrow_%s_hover.png" % name), 324 ui_theme.get_pixbuf("spin/spin_arrow_%s_press.png" % name), 325 ui_theme.get_pixbuf("spin/spin_arrow_%s_disable.png" % name)), 326 ) 327 if callback: 328 button.connect("button-press-event", callback) 329 button.connect("button-release-event", self.handle_key_release) 330 return button 331 332 gobject.type_register(SpinBox) 333