Package conduit :: Package gtkui :: Module MsgArea
[hide private]

Source Code for Module conduit.gtkui.MsgArea

  1  # This file is part of the Hotwire Shell user interface. 
  2  #    
  3  # Copyright (C) 2007,2008 Colin Walters <walters@verbum.org> 
  4  # 
  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; either version 2 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # This program is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the Free Software 
 17  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 18   
 19  import os, sys, re, logging, string 
 20   
 21  import gtk, gobject, pango 
 22   
 23  #from hotssh.hotlib.logutil import log_except 
 24   
 25  #_logger = logging.getLogger("hotwire.ui.MsgArea") 
 26   
 27  # This file is a Python translation of gedit/gedit/gedit-message-area.c 
 28   
29 -class MsgArea(gtk.HBox):
30 __gsignals__ = { 31 "response" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,)), 32 "close" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []) 33 } 34
35 - def __init__(self, buttons, **kwargs):
36 super(MsgArea, self).__init__(**kwargs) 37 38 self.__contents = None 39 self.__changing_style = False 40 41 self.__main_hbox = gtk.HBox(False, 16) # FIXME: use style properties 42 self.__main_hbox.show() 43 self.__main_hbox.set_border_width(8) # FIXME: use style properties 44 45 self.__action_area = gtk.HBox(True, 4); # FIXME: use style properties 46 self.__action_area.show() 47 48 #Pack the buttons into a VBox so they remain the same height and do 49 #not expand to be the same size as the Primary + Secondary text 50 vb = gtk.VBox() 51 vb.pack_end(self.__action_area, False, False) 52 53 self.__main_hbox.pack_end (vb, False, False, 0) 54 55 self.pack_start(self.__main_hbox, True, True, 0) 56 57 self.set_app_paintable(True) 58 59 self.connect("expose-event", self.__paint) 60 61 # Note that we connect to style-set on one of the internal 62 # widgets, not on the message area itself, since gtk does 63 # not deliver any further style-set signals for a widget on 64 # which the style has been forced with gtk_widget_set_style() 65 self.__main_hbox.connect("style-set", self.__on_style_set) 66 67 self.add_buttons(buttons)
68
69 - def __get_response_data(self, w, create):
70 d = w.get_data('hotwire-msg-area-data') 71 if (d is None) and create: 72 d = {'respid': None} 73 w.set_data('hotwire-msg-area-data', d) 74 return d
75
76 - def __find_button(self, respid):
77 children = self.__actionarea.get_children() 78 for child in children: 79 rd = self.__get_response_data(child, False) 80 if rd is not None and rd['respid'] == respid: 81 return child
82
83 - def __close(self):
84 cancel = self.__find_button(gtk.RESPONSE_CANCEL) 85 if cancel is None: 86 return 87 self.response(gtk.RESPONSE_CANCEL)
88
89 - def __paint(self, w, event):
90 gtk.Style.paint_flat_box(w.style, 91 w.window, 92 gtk.STATE_NORMAL, 93 gtk.SHADOW_OUT, 94 None, 95 w, 96 "tooltip", 97 w.allocation.x + 1, 98 w.allocation.y + 1, 99 w.allocation.width - 2, 100 w.allocation.height - 2) 101 102 return False
103
104 - def __on_style_set(self, w, style):
105 if self.__changing_style: 106 return 107 # This is a hack needed to use the tooltip background color 108 window = gtk.Window(gtk.WINDOW_POPUP); 109 window.set_name("gtk-tooltip") 110 window.ensure_style() 111 style = window.get_style() 112 113 self.__changing_style = True 114 self.set_style(style) 115 self.__changing_style = False 116 117 window.destroy() 118 119 self.queue_draw()
120
121 - def __get_response_for_widget(self, w):
122 rd = self.__get_response_data(w, False) 123 if rd is None: 124 return gtk.RESPONSE_NONE 125 return rd['respid']
126
127 - def __on_action_widget_activated(self, w):
128 response_id = self.__get_response_for_widget(w) 129 self.response(response_id)
130
131 - def add_action_widget(self, child, respid):
132 rd = self.__get_response_data(child, True) 133 rd['respid'] = respid 134 if not isinstance(child, gtk.Button): 135 raise ValueError("Can only pack buttons as action widgets") 136 child.connect('clicked', self.__on_action_widget_activated) 137 if respid != gtk.RESPONSE_HELP: 138 self.__action_area.pack_start(child, False, False, 0) 139 else: 140 self.__action_area.pack_end(child, False, False, 0)
141
142 - def set_contents(self, contents):
143 self.__contents = contents 144 self.__main_hbox.pack_start(contents, True, True, 0)
145 146
147 - def add_button(self, btext, respid):
148 button = gtk.Button(stock=btext) 149 button.set_focus_on_click(False) 150 button.set_flags(gtk.CAN_DEFAULT) 151 button.show() 152 self.add_action_widget(button, respid) 153 return button
154
155 - def add_buttons(self, args):
156 #_logger.debug("init buttons: %r", args) 157 for (btext, respid) in args: 158 self.add_button(btext, respid)
159
160 - def set_response_sensitive(self, respid, setting):
161 for child in self.__action_area.get_children(): 162 rd = self.__get_response_data(child, False) 163 if rd is not None and rd['respid'] == respid: 164 child.set_sensitive(setting) 165 break
166
167 - def set_default_response(self, respid):
168 for child in self.__action_area.get_children(): 169 rd = self.__get_response_data(child, False) 170 if rd is not None and rd['respid'] == respid: 171 child.grab_default() 172 break
173
174 - def response(self, respid):
175 self.emit('response', respid)
176
177 - def add_stock_button_with_text(self, text, stockid, respid):
178 b = gtk.Button(label=text) 179 b.set_focus_on_click(False) 180 img = gtk.Image() 181 img.set_from_stock(stockid, gtk.ICON_SIZE_BUTTON) 182 b.set_image(img) 183 b.show_all() 184 self.add_action_widget(b, respid) 185 return b
186
187 - def set_text_and_icon(self, stockid, primary_text, secondary_text=None):
188 hbox_content = gtk.HBox(False, 8) 189 hbox_content.show() 190 191 image = gtk.Image() 192 image.set_from_stock(stockid, gtk.ICON_SIZE_BUTTON) 193 image.show() 194 hbox_content.pack_start(image, False, False, 0) 195 image.set_alignment(0.5, 0.5) 196 197 vbox = gtk.VBox(False, 6) 198 vbox.show() 199 hbox_content.pack_start (vbox, True, True, 0) 200 201 primary_markup = "<b>%s</b>" % (primary_text,) 202 primary_label = gtk.Label(primary_markup) 203 primary_label.show() 204 vbox.pack_start(primary_label, True, True, 0) 205 primary_label.set_use_markup(True) 206 primary_label.set_line_wrap(True) 207 primary_label.set_alignment(0, 0.5) 208 primary_label.set_flags(gtk.CAN_FOCUS) 209 primary_label.set_selectable(True) 210 211 if secondary_text: 212 secondary_markup = "<small>%s</small>" % (secondary_text,) 213 secondary_label = gtk.Label(secondary_markup) 214 secondary_label.show() 215 vbox.pack_start(secondary_label, True, True, 0) 216 secondary_label.set_flags(gtk.CAN_FOCUS) 217 secondary_label.set_use_markup(True) 218 secondary_label.set_line_wrap(True) 219 secondary_label.set_selectable(True) 220 secondary_label.set_alignment(0, 0.5) 221 222 self.set_contents(hbox_content)
223
224 -class MsgAreaController(gtk.HBox):
225 - def __init__(self):
226 super(MsgAreaController, self).__init__() 227 228 self.__msgarea = None
229
230 - def _timeout(self, msgarea):
231 if msgarea == self.__msgarea: 232 self.clear()
233
234 - def clear(self):
235 if self.__msgarea is not None: 236 self.remove(self.__msgarea) 237 self.__msgarea.destroy() 238 self.__msgarea = None
239
240 - def new_from_text_and_icon(self, stockid, primary, secondary=None, buttons=[], timeout=0):
241 self.clear() 242 msgarea = self.__msgarea = MsgArea(buttons) 243 msgarea.set_text_and_icon(stockid, primary, secondary) 244 self.pack_start(msgarea, expand=True) 245 246 if timeout: 247 gobject.timeout_add(timeout*1000, self._timeout, msgarea) 248 249 return msgarea
250