Package dtk :: Package ui :: Module tab_window

Source Code for Module dtk.ui.tab_window

  1  #! /usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (C) 2011 ~ 2012 Deepin, Inc. 
  5  #               2011 ~ 2012 Wang Yong 
  6  #  
  7  # Author:     Wang Yong <lazycat.manatee@gmail.com> 
  8  # Maintainer: Wang Yong <lazycat.manatee@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 box import EventBox 
 24  from button import Button 
 25  from constant import DEFAULT_FONT_SIZE 
 26  from dialog import DialogBox, DIALOG_MASK_TAB_PAGE 
 27  from draw import draw_text 
 28  from scrolled_window import ScrolledWindow 
 29  from skin_config import skin_config 
 30  from theme import ui_theme 
 31  from locales import _ 
 32  import gobject 
 33  import gtk 
 34  from utils import (container_remove_all, get_content_size,  
 35                     color_hex_to_cairo, alpha_color_hex_to_cairo,  
 36                     cairo_disable_antialias, is_in_rect, cairo_state,  
 37                     get_window_shadow_size) 
 38   
39 -class TabBox(gtk.VBox):
40 ''' 41 Tab box. 42 43 @undocumented: press_tab_title_box 44 @undocumented: expose_tab_title_box 45 @undocumented: expose_tab_content_align 46 @undocumented: expose_tab_content_box 47 ''' 48
49 - def __init__(self):
50 ''' 51 Initialize TabBox class. 52 ''' 53 # Init. 54 gtk.VBox.__init__(self) 55 self.tab_height = 29 56 self.tab_padding_x = 19 57 self.tab_padding_y = 9 58 self.tab_select_bg_color = ui_theme.get_color("tab_select_bg") 59 self.tab_select_frame_color = ui_theme.get_color("tab_select_frame") 60 self.tab_unselect_bg_color = ui_theme.get_color("tab_unselect_bg") 61 self.tab_unselect_frame_color = ui_theme.get_color("tab_unselect_bg") 62 63 self.tab_title_box = EventBox() 64 self.tab_title_box.set_size_request(-1, self.tab_height) 65 self.tab_title_align = gtk.Alignment() 66 self.tab_title_align.set(0.0, 0.0, 1.0, 1.0) 67 self.tab_title_align.set_padding(0, 0, 0, 0) 68 self.tab_title_align.add(self.tab_title_box) 69 self.tab_content_align = gtk.Alignment() 70 self.tab_content_align.set(0.0, 0.0, 1.0, 1.0) 71 self.tab_content_align.set_padding(0, 1, 0, 0) 72 self.tab_content_scrolled_window = ScrolledWindow() 73 self.tab_content_align.add(self.tab_content_scrolled_window) 74 self.tab_content_box = gtk.VBox() 75 self.tab_content_scrolled_window.add_child(self.tab_content_box) 76 77 self.tab_items = [] 78 self.tab_title_widths = [] 79 self.tab_index = -1 80 81 self.pack_start(self.tab_title_align, False, False) 82 self.pack_start(self.tab_content_align, True, True) 83 84 self.tab_title_box.connect("button-press-event", self.press_tab_title_box) 85 self.tab_title_box.connect("expose-event", self.expose_tab_title_box) 86 self.tab_content_align.connect("expose-event", self.expose_tab_content_align) 87 self.tab_content_box.connect("expose-event", self.expose_tab_content_box)
88
89 - def add_items(self, items, default_index=0):
90 ''' 91 Add items. 92 93 @param items: A list of tab item, tab item format: (tab_name, tab_widget) 94 @param default_index: Initialize index, default is 0. 95 ''' 96 self.tab_items += items 97 98 for item in items: 99 self.tab_title_widths.append(get_content_size(item[0], DEFAULT_FONT_SIZE)[0] + self.tab_padding_x * 2) 100 101 self.switch_content(default_index)
102
103 - def switch_content(self, index):
104 ''' 105 Switch content with given index. 106 107 @param index: Tab index. 108 ''' 109 if self.tab_index != index: 110 self.tab_index = index 111 widget = self.tab_items[index][1] 112 113 container_remove_all(self.tab_content_box) 114 self.tab_content_box.add(widget) 115 self.tab_title_box.queue_draw() 116 self.tab_content_box.queue_draw() 117 118 self.show_all()
119
120 - def press_tab_title_box(self, widget, event):
121 ''' 122 Internal callback for `button-press-event` signal. 123 ''' 124 for (index, item) in enumerate(self.tab_items): 125 if is_in_rect((event.x, event.y), 126 (sum(self.tab_title_widths[0:index]), 127 0, 128 self.tab_title_widths[index], 129 self.tab_height)): 130 self.switch_content(index) 131 break
132
133 - def expose_tab_title_box(self, widget, event):
134 ''' 135 Internal callback for `expose-event` signal. 136 ''' 137 cr = widget.window.cairo_create() 138 rect = widget.allocation 139 140 # Draw title unselect tab. 141 tab_title_width = sum(self.tab_title_widths) 142 143 with cairo_state(cr): 144 with cairo_disable_antialias(cr): 145 cr.rectangle(rect.x, 146 rect.y, 147 sum(self.tab_title_widths[0:self.tab_index]), 148 self.tab_height) 149 cr.rectangle(rect.x + sum(self.tab_title_widths[0:min(self.tab_index + 1, len(self.tab_items))]) + 1, 150 rect.y, 151 sum(self.tab_title_widths) - sum(self.tab_title_widths[0:min(self.tab_index + 1, len(self.tab_items))]), 152 self.tab_height) 153 cr.clip() 154 155 cr.set_source_rgba(*alpha_color_hex_to_cairo((self.tab_unselect_bg_color.get_color(), 0.7))) 156 cr.rectangle(rect.x + 1, rect.y + 1, tab_title_width, self.tab_height) 157 cr.fill() 158 159 cr.set_line_width(1) 160 cr.set_source_rgba(*alpha_color_hex_to_cairo((self.tab_unselect_frame_color.get_color(), 1.0))) 161 cr.rectangle(rect.x + 1, rect.y + 1, tab_title_width, self.tab_height) 162 cr.stroke() 163 164 for (index, width) in enumerate(self.tab_title_widths[:-1]): 165 cr.set_source_rgba(*alpha_color_hex_to_cairo((self.tab_unselect_frame_color.get_color(), 1.0))) 166 cr.rectangle(rect.x + 1 + sum(self.tab_title_widths[0:index]) + width, 167 rect.y + 1, 168 1, 169 self.tab_height) 170 cr.fill() 171 172 cr.set_source_rgb(*color_hex_to_cairo(self.tab_select_frame_color.get_color())) 173 cr.rectangle(rect.x, 174 rect.y + rect.height - 1, 175 sum(self.tab_title_widths[0:self.tab_index]), 176 1) 177 cr.fill() 178 179 cr.set_source_rgb(*color_hex_to_cairo(self.tab_select_frame_color.get_color())) 180 cr.rectangle(rect.x + 1 + sum(self.tab_title_widths[0:self.tab_index]), 181 rect.y + rect.height - 1, 182 rect.width - sum(self.tab_title_widths[0:self.tab_index]), 183 1) 184 cr.fill() 185 186 for (index, item) in enumerate(self.tab_items): 187 # Draw title background. 188 title = item[0] 189 190 # Draw title tab. 191 with cairo_disable_antialias(cr): 192 if index == self.tab_index: 193 # Draw title select tab. 194 cr.set_source_rgba(*alpha_color_hex_to_cairo((self.tab_select_bg_color.get_color(), 0.93))) 195 if index == 0: 196 cr.rectangle(rect.x + sum(self.tab_title_widths[0:index]), 197 rect.y + 1, 198 self.tab_title_widths[index] + 1, 199 self.tab_height) 200 else: 201 cr.rectangle(rect.x + 1 + sum(self.tab_title_widths[0:index]), 202 rect.y + 1, 203 self.tab_title_widths[index], 204 self.tab_height) 205 cr.fill() 206 207 if index == 0: 208 cr.rectangle(rect.x, 209 rect.y, 210 rect.width, 211 self.tab_height) 212 cr.clip() 213 214 cr.set_line_width(1) 215 cr.set_source_rgb(*color_hex_to_cairo(self.tab_select_frame_color.get_color())) 216 if index == 0: 217 cr.rectangle(rect.x + sum(self.tab_title_widths[0:index]), 218 rect.y + 1, 219 self.tab_title_widths[index] + 2, 220 self.tab_height) 221 else: 222 cr.rectangle(rect.x + 1 + sum(self.tab_title_widths[0:index]), 223 rect.y + 1, 224 self.tab_title_widths[index] + 1, 225 self.tab_height) 226 cr.stroke() 227 228 draw_text(cr, title, 229 rect.x + sum(self.tab_title_widths[0:index]) + self.tab_padding_x, 230 rect.y + self.tab_padding_y, 231 self.tab_title_widths[index] - self.tab_padding_x * 2, 232 self.tab_height - self.tab_padding_y * 2, 233 )
234
235 - def expose_tab_content_align(self, widget, event):
236 ''' 237 Internal function to `expose-event` signal. 238 ''' 239 cr = widget.window.cairo_create() 240 rect = widget.allocation 241 242 with cairo_disable_antialias(cr): 243 cr.set_source_rgb(*color_hex_to_cairo(self.tab_select_frame_color.get_color())) 244 cr.rectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2) 245 cr.stroke()
246
247 - def expose_tab_content_box(self, widget, event):
248 ''' 249 Internal function to `expose-event` signal. 250 ''' 251 cr = widget.window.cairo_create() 252 rect = widget.allocation 253 254 # Draw background. 255 toplevel = widget.get_toplevel() 256 coordinate = widget.translate_coordinates(toplevel, rect.x, rect.y) 257 (offset_x, offset_y) = coordinate 258 259 with cairo_state(cr): 260 cr.translate(-offset_x, -offset_y) 261 cr.rectangle(offset_x, offset_y, rect.width, rect.height) 262 cr.clip() 263 264 (shadow_x, shadow_y) = get_window_shadow_size(self.get_toplevel()) 265 skin_config.render_background(cr, self, rect.x + shadow_x, rect.y + shadow_y) 266 267 # Draw mask. 268 cr.set_source_rgba(*alpha_color_hex_to_cairo((self.tab_select_bg_color.get_color(), 0.93))) 269 cr.rectangle(rect.x, rect.y, rect.width, rect.height) 270 cr.fill()
271 272 gobject.type_register(TabBox) 273
274 -class TabWindow(DialogBox):
275 ''' 276 Tab window. 277 278 @undocumented: click_confirm_button 279 @undocumented: click_cancel_button 280 ''' 281
282 - def __init__(self, title, items, 283 confirm_callback=None, 284 cancel_callback=None, 285 window_width=458, 286 window_height=472):
287 ''' 288 Initialize TabWindow clas. 289 290 @param title: Tab window title. 291 @param items: A list of tab item, tab item format: (tab_name, tab_widget) 292 @param confirm_callback: Callback when user click ok button. 293 @param cancel_callback: Callback when user click cancel button. 294 @param window_width: Default window width. 295 @param window_height: Default window height. 296 ''' 297 DialogBox.__init__(self, 298 title, 299 window_width, 300 window_height, 301 mask_type=DIALOG_MASK_TAB_PAGE) 302 self.confirm_callback = confirm_callback 303 self.cancel_callback = cancel_callback 304 305 self.window_box = gtk.VBox() 306 307 self.tab_window_width = window_width 308 self.tab_window_height = window_height 309 self.tab_box = TabBox() 310 self.tab_box.add_items(items) 311 self.tab_align = gtk.Alignment() 312 self.tab_align.set(0.5, 0.5, 1.0, 1.0) 313 self.tab_align.set_padding(8, 0, 0, 0) 314 self.tab_align.add(self.tab_box) 315 316 self.confirm_button = Button(_("OK")) 317 self.cancel_button = Button(_("Cancel")) 318 319 self.window_box.pack_start(self.tab_align, True, True) 320 321 self.confirm_button.connect("clicked", lambda w: self.click_confirm_button()) 322 self.cancel_button.connect("clicked", lambda w: self.click_cancel_button()) 323 self.connect("destroy", lambda w: self.destroy()) 324 325 self.body_box.pack_start(self.window_box, True, True) 326 self.right_button_box.set_buttons([self.confirm_button, self.cancel_button])
327
328 - def click_confirm_button(self):
329 ''' 330 Internal function to response when user click confirm button. 331 ''' 332 if self.confirm_callback != None: 333 self.confirm_callback() 334 335 self.destroy()
336
337 - def click_cancel_button(self):
338 ''' 339 Internal function to response when user click cancel button. 340 ''' 341 if self.cancel_callback != None: 342 self.cancel_callback() 343 344 self.destroy()
345 346 gobject.type_register(TabWindow) 347