import FrameWork import Wbase, Wcontrols from Carbon import Ctl, Controls, Qd from types import * import Wapplication _arrowright = Qd.GetPicture(472) _arrowdown = Qd.GetPicture(473) class PopupControl(Wcontrols.ControlWidget): def __init__(self, possize, items=None, callback=None): if items is None: items = [] procID = Controls.popupMenuProc|Controls.popupFixedWidth|Controls.useWFont Wcontrols.ControlWidget.__init__(self, possize, "", procID, callback, 0, 0, 0) self._items = items[:] def set(self, value): self._control.SetControlValue(value+1) def get(self): return self._control.GetControlValue() - 1 def open(self): self.menu = menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1) for i in range(len(self._items)): item = self._items[i] if type(item) == StringType: menuitemtext = object = item elif type(item) == TupleType and len(item) == 2: menuitemtext, object = item self._items[i] = object else: raise Wbase.WidgetsError, "illegal itemlist for popup menu" menuitem = FrameWork.MenuItem(menu, menuitemtext, None, None) self._calcbounds() self._control = Ctl.NewControl(self._parentwindow.wid, self._bounds, self._title, 1, self._value, self.menu.id, self._max, self._procID, 0) self.SetPort() self.enable(self._enabled) def close(self): self.menu.delete() return Wcontrols.ControlWidget.close(self) def click(self, point, modifiers): if not self._enabled: return part = self._control.TrackControl(point, -1) if part: if self._callback: Wbase.CallbackCall(self._callback, 0, self._items[self.get()]) class PopupWidget(Wbase.ClickableWidget): """Simple title-less popup widget. Should be 16x16 pixels. Builds the menu items on the fly, good for dynamic popup menus.""" def __init__(self, possize, items=None, callback=None): Wbase.ClickableWidget.__init__(self, possize) if items is None: items = [] self._items = items self._itemsdict = {} self._callback = callback self._enabled = 1 def close(self): Wbase.ClickableWidget.close(self) self._items = None self._itemsdict = {} def draw(self, visRgn = None): if self._visible: Qd.FrameRect(self._bounds) Qd.EraseRect(Qd.InsetRect(self._bounds, 1, 1)) l, t, r, b = self._bounds l = l + 2 t = t + 3 pictframe = (l, t, l + 10, t + 10) Qd.DrawPicture(_arrowright, pictframe) def click(self, point, modifiers): if not self._enabled: return self.menu = FrameWork.Menu(self._parentwindow.parent.menubar, 'Foo', -1) self._additems(self._items, self.menu) self.SetPort() l, t, r, b = self._bounds l, t = Qd.LocalToGlobal((l+1, t+1)) Wbase.SetCursor("arrow") self.menu.menu.EnableMenuItem(0) reply = self.menu.menu.PopUpMenuSelect(t, l, 1) if reply: id = (reply & 0xffff0000) >> 16 item = reply & 0xffff self._menu_callback(id, item) self._emptymenu() def set(self, items): self._items = items def get(self): return self._items def _additems(self, items, menu): from FrameWork import SubMenu, MenuItem menu_id = menu.id for item in items: if item == "-": menu.addseparator() continue elif type(item) == ListType: submenu = SubMenu(menu, item[0]) self._additems(item[1:], submenu) continue elif type(item) == StringType: menuitemtext = object = item elif type(item) == TupleType and len(item) == 2: menuitemtext, object = item else: raise Wbase.WidgetsError, "illegal itemlist for popup menu" if menuitemtext[:1] == '\0': check = ord(menuitemtext[1]) menuitemtext = menuitemtext[2:] else: check = 0 menuitem = MenuItem(menu, menuitemtext, None, None) if check: menuitem.check(1) self._itemsdict[(menu_id, menuitem.item)] = object def _emptymenu(self): menus = self._parentwindow.parent.menubar.menus for id, item in self._itemsdict.keys(): if menus.has_key(id): self.menu = menus[id] self.menu.delete() self._itemsdict = {} def _menu_callback(self, id, item): thing = self._itemsdict[(id, item)] if callable(thing): thing() elif self._callback: Wbase.CallbackCall(self._callback, 0, thing) class PopupMenu(PopupWidget): """Simple title-less popup widget. Should be 16x16 pixels. Prebuilds the menu items, good for static (non changing) popup menus.""" def open(self): self._calcbounds() self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1) self._additems(self._items, self.menu) def close(self): self._emptymenu() Wbase.Widget.close(self) self._items = None self._itemsdict = {} self.menu = None def set(self, items): if self._itemsdict: self._emptymenu() self.menu = Wapplication.Menu(self._parentwindow.parent.menubar, 'Foo', -1) self._items = items self._additems(self._items, self.menu) def click(self, point, modifiers): if not self._enabled: return self.SetPort() l, t, r, b = self._bounds l, t = Qd.LocalToGlobal((l+1, t+1)) Wbase.SetCursor("arrow") self.menu.menu.EnableMenuItem(0) reply = self.menu.menu.PopUpMenuSelect(t, l, 1) if reply: id = (reply & 0xffff0000) >> 16 item = reply & 0xffff self._menu_callback(id, item) class FontMenu(PopupMenu): """A font popup menu.""" menu = None def __init__(self, possize, callback): PopupMenu.__init__(self, possize) _makefontmenu() self._callback = callback self._enabled = 1 def open(self): self._calcbounds() def close(self): del self._callback def set(self): raise Wbase.WidgetsError, "can't change font menu widget" def _menu_callback(self, id, item): fontname = self.menu.menu.GetMenuItemText(item) if self._callback: Wbase.CallbackCall(self._callback, 0, fontname) def click(self, point, modifiers): if not self._enabled: return _makefontmenu() return PopupMenu.click(self, point, modifiers) def _makefontmenu(): """helper for font menu""" if FontMenu.menu is not None: return import W FontMenu.menu = Wapplication.Menu(W.getapplication().menubar, 'Foo', -1) W.SetCursor('watch') for i in range(FontMenu.menu.menu.CountMenuItems(), 0, -1): FontMenu.menu.menu.DeleteMenuItem(i) FontMenu.menu.menu.AppendResMenu('FOND') def _getfontlist(): from Carbon import Res fontnames = [] for i in range(1, Res.CountResources('FOND') + 1): r = Res.GetIndResource('FOND', i) fontnames.append(r.GetResInfo()[2]) return fontnames