def open_menu(self, menu): # always work on a copy menu = menu[:] if (menu): menu.append(MenuItem("/__separator")) menu += self.__DISPLAY_MENU mainmenu = gtk.Menu() tree = {} for entry in menu: if (not entry.label): item = gtk.SeparatorMenuItem() elif (entry.icon): if (gtk.stock_lookup(entry.icon)): item = gtk.ImageMenuItem(entry.icon) if (entry.label): item.get_children()[0].set_text_with_mnemonic(entry.label) else: item = gtk.ImageMenuItem(entry.label) try: img = Tiling() data = vfs.read_entire_file(self.get_full_path(entry.icon)) img.set_from_data(data) img.render(16, 16, 1, 1) img.show() item.set_image(img) except: import traceback; traceback.print_exc() else: item = gtk.MenuItem(entry.label) if (entry.callback): item.connect("activate", lambda src, cb, args: cb(*args), entry.callback, entry.args) item.show() if (not entry.active): item.set_sensitive(False) menupath = "/".join(entry.path.split("/")[:-1]) if (menupath): parentitem = tree.get(menupath) if (not parentitem.get_submenu()): m = gtk.Menu() parentitem.set_submenu(m) else: m = parentitem.get_submenu() else: m = mainmenu m.append(item) tree["/".join(entry.path.split("/"))] = item mainmenu.popup(None, None, None, 0, 0)
def __init__(self, name, parent): self.__frame_widths = [Unit.ZERO] * 4 self.__images = [] ContainerTarget.__init__(self, name, parent) self.__table = gtk.Table(3, 3) self.__table.set_direction(gtk.TEXT_DIR_LTR) self.__table.show() r, g, b, a = utils.parse_color("black") for x, y in ((0, 1), (1, 0), (2, 1), (1, 2), (0, 0), (2, 0), (2, 2), (0, 2)): img = Tiling() img.set_from_color(r, g, b, a) img.show() self.__table.attach(img, x, x + 1, y, y + 1) self.__images.append(img) self.__box = gtk.HBox() self.__box.show() self.__table.attach(self.__box, 1, 2, 1, 2) self._register_property("border-uris", TYPE_LIST, self._setp_border_uris, self._getp) self._register_property("border-width", TYPE_UNIT_LIST, self._setp_border_width, self._getp) self._register_property("color", TYPE_STRING, self._setp_border_color, self._getp) self.set_prop("border-width", [Unit.Unit(2, Unit.UNIT_PX), Unit.Unit(2, Unit.UNIT_PX), Unit.Unit(2, Unit.UNIT_PX), Unit.Unit(2, Unit.UNIT_PX)]) self._setp("color", "black") # watch for geometry changes self.add_observer(self.__on_observe_size)
class GlassWindow(gtk.Window): # # Constructor. # def __init__(self, wintype = gtk.WINDOW_TOPLEVEL): # handler for transparency updates self.__update_handler = None # remember the current window position to detect movements self.__position = (0, 0) self.__size = (0, 0) # window manager self.__wm = self.__get_window_manager() gtk.Window.__init__(self, wintype) self.__layout = gtk.Fixed() self.__layout.show() gtk.Window.add(self, self.__layout) self.__background = Tiling() self.__layout.put(self.__background, 0, 0) self.__on_screen_changed (self, None) # Workaround for Ubuntu >= 11.04 # Thanks screenlets # (http://bazaar.launchpad.net/~screenlets-dev/screenlets/trunk/revision/646) try: self.set_property('has-resize-grip', False) except TypeError: pass self.set_app_paintable (True) self.__bg_watcher = BGWatcher() self.connect("configure-event", self.__on_configure) self.connect("screen-changed", self.__on_screen_changed) self.connect("expose-event", self.__on_expose_event) self.connect("composited-changed", self.__on_composited_changed) self.__is_composited = True self.__on_composited_changed (self) # # Override add method. # def add(self, widget): self.__layout.put(widget, 0, 0) # # Override resize method. # def resize(self, width, height): self.__layout.set_size_request(width, height) gobject.idle_add(gtk.Window.resize, self, width, height) # # Observer method for the background. # Connect this method to the BG watcher. # def __bg_observer(self, src, cmd): self.__update_bg() # # Updates the background for transparency. # def __update_bg(self): if (self.__update_handler): gobject.source_remove(self.__update_handler) self.__update_handler = gobject.timeout_add(100, self.__updater) else: self.__updater() def __updater(self): if (not self.window): return x, y = self.window.get_origin() width, height = self.window.get_size() if (width > 1 and height > 1): self.__capture_bg(x, y, width, height) # # Captures the background to create transparency. # def __capture_bg(self, x, y, width, height): wallpaper.get_wallpaper(self.__background, x, y, width, height) self.queue_draw() # # Reacts on expose event # def __on_expose_event (self, widget, event = None, user_data = None): cr = widget.window.cairo_create () # Fill with fully transparent white cr.set_source_rgba (1.0, 1.0, 1.0, 0.0) cr.set_operator (cairo.OPERATOR_SOURCE) cr.paint () # # Reacts on composited changed # def __on_composited_changed (self, widget): screen = self.get_screen () is_composited = gtk.ver[1] >= 10 and screen.is_composited () if self.__is_composited == is_composited: return if is_composited: self.__is_composited = True self.__background.hide () try: self.__bg_watcher.remove_observer(self.__bg_observer) except: pass else: self.__is_composited = False self.__bg_watcher.add_observer(self.__bg_observer) self.__background.show () # # Reacts on screen changed # def __on_screen_changed (self, src, old_screen): screen = self.get_screen () colormap = screen.get_rgba_colormap () if colormap == None: colormap = screen.get_rgb_colormap () self.set_colormap (colormap) # # Reacts on moving the window. # def __on_configure(self, src, event): pos = self.window.get_origin() size = self.window.get_size() if (pos != self.__position or size != self.__size): self.__position = pos self.__size = size if not self.__is_composited: self.__update_bg() # # Sets the BELOW window flag. # def _set_flag_below(self, value, tries = 0): if (not self.__wm == "Enlightenment" and not self.get_property("visible") and not tries >= 10): gobject.timeout_add(500, self._set_flag_below, value, tries + 1) if (self.window): x11.set_above(self.window, not value) x11.set_below(self.window, value) # # Sets the ABOVE window flag. # def _set_flag_above(self, value, tries = 0): if (not self.__wm == "Enlightenment" and not self.__wm.startswith("Xfwm4") and not self.get_property("visible") and not tries >= 11): gobject.timeout_add(500, self._set_flag_above, value, tries + 1) if (self.window): x11.set_below(self.window, not value) x11.set_above(self.window, value) # # Sets the STICKY window flag. # def _set_flag_sticky(self, value): if (value): self.stick() else: self.unstick() def _set_type_hint_dock(self, window, value): x11.set_type_dock(window, value) # # Sets the MANAGED window flag. # def _set_flag_managed(self, value): if (value): self.set_property("skip-taskbar-hint", 0) self.set_property("skip-pager-hint", 0) self._set_type_hint_dock(self.window, False) else: self.set_property("skip-taskbar-hint", 1) self.set_property("skip-pager-hint", 1) if (self.__wm == "Metacity"): self._set_type_hint_dock(self.window, True) # # Sets the DECORATED window flag. # def _set_flag_decorated(self, value): if (value): self.set_decorated(True) else: self.set_decorated(False) # # Returns the name of the running EWMH compliant window manager or "". # def __get_window_manager(self): name = "" win = "" # get the window where the EMWH compliant window manager tells its name root = gtk.gdk.get_default_root_window() try: ident = root.property_get("_NET_SUPPORTING_WM_CHECK", "WINDOW")[2] win = gtk.gdk.window_foreign_new(long(ident[0])) except TypeError, exc: log("Your window manager doesn't support " "_NET_SUPPORTING_WM_CHECK! Switch to a compliant WM!" "The following error occurred:\n%s" % (exc,)) if (win != None and win != ""): try: name = win.property_get("_NET_WM_NAME")[2] except TypeError, exc: log("Your window manager doesn't support _NET_WM_NAME!\n" "Switch to a EWMH compliant WM.\n" "The following error occurred:\n%s" % (exc,)) return name
class TargetImage(DisplayTarget): def __init__(self, name, parent): self.__size = (0, 0) # the original image size self.__original_size = (0, 0) # the current saturation value self.__current_saturation = 0.0 # the current opacity value self.__current_opacity = 0.0 DisplayTarget.__init__(self, name, parent) self.__widget = Tiling() self.__widget.show() self._register_property("uri", TYPE_STRING, self._setp_uri, self._getp) self._register_property("saturation", TYPE_FLOAT, self._setp_saturation, self._getp) self._register_property("scale", TYPE_FLOAT, self._setp_scale, self._getp) self._register_property("opacity", TYPE_FLOAT, self._setp_opacity, self._getp) self._register_property("image-width", TYPE_UNIT, self._setp_image_size, self._getp_image_size) self._register_property("image-height", TYPE_UNIT, self._setp_image_size, self._getp_image_size) self._setp("image-width", Unit.Unit())#-1, Unit.UNIT_PX)) self._setp("image-height", Unit.Unit())#-1, Unit.UNIT_PX)) self._setp("opacity", 1.0) self._setp("saturation", 1.0) self._setp("scale", 1.0) # watch the parent for geometry changes self.add_observer(self.__on_observe_size) def get_widget(self): return self.__widget def delete(self): DisplayTarget.delete(self) # # Observer for size. # def __on_observe_size(self, src, cmd, *args): x, y, w, h = src.get_geometry() if (cmd == src.OBS_GEOMETRY and (w.as_px(), h.as_px()) != self.__size): self.__compute_size() utils.request_call(self.__render_image) self.__size = (w.as_px(), h.as_px()) # # Loads the image from the given URI. # def __load_image(self, uri): if (not uri): return try: data = vfs.read_entire_file(uri) except: log("Couldn't read file %s.\n" % uri) return try: self.__widget.set_from_data(data) except RuntimeError, exc: log(`exc`) try: self.__original_size = self.__widget.get_size() except: log("Couldn't get width and/or height of the image.") return
class TargetGroup(ContainerTarget): def __init__(self, name, parent): # flag for ensuring that only one collapse action takes place self.__block = 0 # the maximum size values of all the children self.__max_size = (0, 0) ContainerTarget.__init__(self, name, parent) self.__layout = gtk.Layout() self.__layout.show() self.__image = Tiling() self.__image.show() self.__layout.put(self.__image, 0, 0) self._register_property("bg-uri", TYPE_STRING, self._setp_bg_uri, self._getp) self._register_property("bg-color", TYPE_STRING, self._setp_bg_color, self._getp) self.add_observer(self.__on_observe_size) def delete(self): self.__layout.remove(self.__image) del self.__image del self.__layout del self.__block del self.__max_size ContainerTarget.delete(self) def get_widget(self): return self.__layout def __on_observe_size(self, src, cmd): if (cmd == src.OBS_GEOMETRY): x, y, w, h = self.get_geometry() if (self._getp("bg-uri") or self._getp("bg-color")): ow, oh = self.__image.size_request() if ((w.as_px(), h.as_px()) != (ow, oh)): self.__image.tile(w.as_px(), h.as_px()) def new_child(self, childtype, settings, children): child = ContainerTarget.new_child(self, childtype, settings, children) if (not child.is_standalone()): x, y, w, h = child.get_geometry() self.__layout.put(child.get_widget(), x.as_px(), y.as_px()) return child def child_observer(self, src, cmd): if (cmd == src.OBS_GEOMETRY): x, y, w, h = src.get_geometry() if (src.get_widget() in self.__layout.get_children()): self.__layout.move(src.get_widget(), x.as_px(), y.as_px()) # # Sets the background color. # def __set_color(self, color): r, g, b, a = utils.parse_color(color) w, h = self.__layout.size_request() self.__image.set_from_color(r, g, b, a) self.__image.tile(w, h) # # Sets the background image. # def __set_background(self, uri): if (not uri): self.__set_color("#00000000") return from utils import vfs if (vfs.exists(uri)): try: data = vfs.read_entire_file(uri) except: return w, h = self.__layout.size_request() self.__image.set_from_data(data) self.__image.tile(w, h) # # "bg-uri" property. # def _setp_bg_uri(self, key, value): path = self._get_display().get_full_path(value) self.__set_background(path) self._setp(key, value) # # "bg-color" property. # def _setp_bg_color(self, key, value): self.__set_color(value) self._setp(key, value)
class TargetLabel(DisplayTarget): # regular expression for parsing font description strings __RE_FONT = re.compile("(?P<name>.+?)" "(?P<size>[0-9\.]+)" "(?P<unit>[a-z%]+)?$") def utf8_to_utf8(value): if (isinstance(value, unicode)): try: value = value.encode("UTF-8", "replace") except ValueError: log("Unicode -> UTF-8 convertion failed !!!") raise elif (not isinstance(value, str)): # int, float, long, list, tuple, instance value = str(value) return value def charmap_to_utf8(value): if (isinstance(value, str)): try: value = unicode(value, CHARMAP, "ignore") except LookupError: # may be it's already UTF-8 ? value = unicode(value, "UTF-8", "replace") if (isinstance(value, unicode)): try: value = value.encode("UTF-8", "replace") except ValueError: log("Unicode -> UTF-8 convertion failed !!!") raise else: # int, float, long, list, tuple, instance value = str(value) return value # # Converts the given string to UTF-8 format. # if (CHARMAP == 'UTF-8'): __utf8ify = staticmethod(utf8_to_utf8) else: __utf8ify = staticmethod(charmap_to_utf8) def __init__(self, name, parent): self.__old_value = "" self.__font_description = None self.__wrap_at = -1 self.__alignment = pango.ALIGN_LEFT self.__justify = True self.__size = (0, 0) DisplayTarget.__init__(self, name, parent) self.__widget = Tiling() self.__pango_context = self.__widget.get_pango_context() self.__pango_context.set_base_dir(pango.DIRECTION_LTR) self.__pango_layout = pango.Layout(self.__pango_context) self.__color = (0, 0, 0, 255) self.__font_description = self.__pango_context.get_font_description() self.__widget.show() # i guess a label has to accept everything printable for its value # these days self._register_property("value", TYPE_ANY, self._setp_value, self._getp) self._register_property("color", TYPE_STRING, self._setp_color, self._getp) self._register_property("font", TYPE_STRING, self._setp_font, self._getp) self._register_property("wrap-at", TYPE_UNIT, self._setp_wrap_at, self._getp) self._register_property("alignment", TYPE_STRING, self._setp_alignment, self._getp) self._register_property("justify", TYPE_BOOL, self._setp_justify, self._getp) self._setp("value", "") self._setp("color", "black") self.set_prop("font", "Sans 8") self.set_prop("wrap-at", Unit.Unit(0, Unit.UNIT_PX)) self.set_prop("alignment", "left") self.set_prop("justify", True) # watch the widget for geometry changes; we need this for percentual # font sizes self.add_observer(self.__on_observe_size) def get_widget(self): return self.__widget def __on_observe_size(self, src, cmd, *args): x, y, w, h = src.get_geometry() if (cmd == src.OBS_GEOMETRY): self.__size = (w.as_px(), h.as_px()) self.__set_justify(self.get_prop("justify")) self.__set_alignment(self.get_prop("alignment")) self.__set_wrap(self.get_prop("wrap-at")) self.__set_font(self.get_prop("font")) self.__set_value(self.get_prop("value")) # # Renders the given text. # def __render_text(self, layout): width, height = layout.get_pixel_size() # render font pmap = gtk.gdk.Pixmap(gtk.gdk.get_default_root_window(), width, height * 2) gc = pmap.new_gc() gc.set_foreground(self.__widget.get_colormap().alloc_color("black")) pmap.draw_rectangle(gc, True, 0, 0, width, height) gc.set_foreground(self.__widget.get_colormap().alloc_color("white")) pmap.draw_rectangle(gc, True, 0, height, width, height) r, g, b, a = self.__color col = "#" + ("0" + hex(r)[2:])[-2:] + \ ("0" + hex(g)[2:])[-2:] + \ ("0" + hex(b)[2:])[-2:] gc.set_foreground( gtk.gdk.get_default_root_window().get_colormap().alloc_color(col)) if (self.__alignment == pango.ALIGN_RIGHT): pmap.draw_layout(gc, width, 0, layout) pmap.draw_layout(gc, width, height, layout) elif (self.__alignment == pango.ALIGN_CENTER): pmap.draw_layout(gc, int(width / 2.0), 0, layout) pmap.draw_layout(gc, int(width / 2.0), height, layout) else: pmap.draw_layout(gc, 0, 0, layout) pmap.draw_layout(gc, 0, height, layout) # pmap.draw_layout(gc, 0, 0, layout) # pmap.draw_layout(gc, 0, height, layout) # then copy to image self.__widget.set_from_drawable(pmap, True) width, height = self.__size if (width and height): self.__widget.render(width, height, a / 255.0, 1) def __make_label(self): value = self.__old_value self.__pango_layout.set_markup(value) self.__pango_layout.set_font_description(self.__font_description) self.__pango_layout.set_alignment(self.__alignment) self.__pango_layout.set_justify(self.__justify) self.__pango_layout.set_width(self.__wrap_at * pango.SCALE) width, height = self.__pango_layout.get_pixel_size() if (width and height): self.__render_text(self.__pango_layout) self.__widget.show() else: self.__widget.hide() self.set_size(Unit.Unit(width, Unit.UNIT_PX), Unit.Unit(height, Unit.UNIT_PX)) def __set_value(self, value): value = self.__utf8ify(value) self.__old_value = value self.__make_label() def __set_font(self, font): m = TargetLabel.__RE_FONT.match(font) if (m): name = m.group("name") unit = m.group("unit") or Unit.UNIT_PT # pt is default for fonts size = m.group("size") if (size): size = float(size) if (unit == Unit.UNIT_PERCENT): height = self._get_parent().get_geometry()[3] # don't allow 0 pixels height size = max(1, height.as_pt() * (size / 100.0)) unit = Unit.UNIT_PT u = Unit.Unit(size, unit) size = u.as_pt() font = "%s %f" % (name, size) self.__font_description = pango.FontDescription(font) self.__pango_context.set_font_description(self.__font_description) #self.__widget.set_size_request(-1, -1) def __set_color(self, color): self.__color = utils.parse_color(color) def __set_wrap(self, value): width = self._get_parent().get_geometry()[2] if (width > Unit.ZERO): value.set_100_percent(width.as_px()) size = value.as_px() if (size == 0): self.__wrap_at = -1 else: self.__wrap_at = size def __set_alignment(self, value): if (value == "right"): self.__alignment = pango.ALIGN_RIGHT elif (value == "center"): self.__alignment = pango.ALIGN_CENTER else: self.__alignment = pango.ALIGN_LEFT def __set_justify(self, value): self.__justify = value # # "value" property. # def _setp_value(self, key, value): if (value != self.__old_value): self.__set_value(value) self._setp(key, value) self.__make_label() # # "font" property. # def _setp_font(self, key, value): if (value != self.get_prop("font")): self.__set_font(value) self._setp(key, value) self.__make_label() #self.__set_value(self.get_prop("value")) # # "color" property. # def _setp_color(self, key, value): self.__set_color(value) self._setp(key, value) self.__make_label() # # "wrap-at" property. # def _setp_wrap_at(self, key, value): self.__set_wrap(value) self._setp(key, value) self.__make_label() # # "alignment" property. # def _setp_alignment(self, key, value): self.__set_alignment(value) self._setp(key, value) self.__make_label() # # "justify" property. # def _setp_justify(self, key, value): self.__set_justify(value) self._setp(key, value) self.__make_label()