Source code for wxpyNautilus.etc.bookshelf

import re
import wx

from mwx.utilus import TreeList
from mwx.framework import CtrlInterface
from mwx.nutshell import EditorBook
from mwx.graphman import Layer


[docs]class ItemData: """Item data for TreeListCtrl """ def __init__(self, tree, buffer): self.tree = tree self.buffer = buffer self._itemId = None #: reference <TreeItemId>
[docs]class EditorTreeCtrl(wx.TreeCtrl, CtrlInterface, TreeList): """TreeList control Construct treectrl in the order of tree:list. """ def __init__(self, parent, *args, **kwargs): wx.TreeCtrl.__init__(self, parent, *args, **kwargs) CtrlInterface.__init__(self) TreeList.__init__(self) self.Font = wx.Font(9, wx.DEFAULT, wx.NORMAL, wx.NORMAL) self.parent = parent self.target = None self.context = { # DNA<EditorTreeCtrl> None : { 'buffer_new' : [ None, self.on_buffer_new ], 'buffer_saved' : [ None, ], 'buffer_loaded' : [ None, ], 'buffer_deleted' : [ None, self.on_buffer_deleted ], 'buffer_activated' : [ None, self.on_buffer_selected ], 'buffer_inactivated' : [ None, ], 'buffer_caption_reset' : [ None, self.on_buffer_caption ], 'buffer_filename_reset' : [ None, self.on_buffer_filename ], }, } self.Bind(wx.EVT_TREE_ITEM_GETTOOLTIP, self.OnItemTooltip) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged) self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy) @self.handler.bind('tab pressed') @self.handler.bind('enter pressed') def enter(v): data = self.GetItemData(self.Selection) if data: data.buffer.SetFocus() @self.handler.bind('delete pressed') def delete(v): data = self.GetItemData(self.Selection) if data: buf = data.buffer buf.parent.delete_buffer(buf) # -> focus moves self.SetFocus() @self.handler.bind('*button* pressed') @self.handler.bind('*button* released') def dispatch(v): """Fork mouse events to the parent.""" self.parent.handler(self.handler.current_event, v) v.Skip()
[docs] def OnDestroy(self, evt): if evt.EventObject is self: self.unwatch() evt.Skip()
## -------------------------------- ## TreeList/Ctrl wrapper interface ## --------------------------------
[docs] def reset(self, clear=True): """Build tree control. All items will be rebuilt after clear if specified. """ try: self.Freeze() wnd = wx.Window.FindFocus() # original focus if clear: self.DeleteAllItems() self.AddRoot(self.Name) for branch in self: self._set_item(self.RootItem, *branch) finally: if wnd: wnd.SetFocus() # restore focus self.Thaw()
def _get_item(self, root, key): """Returns the first item [root/key] found. Note: Items with the same name are not supported. """ item, cookie = self.GetFirstChild(root) while item: caption = self.GetItemText(item) caption = re.sub(r"^\W+\s+(.*)", r"\1", caption) if key == caption: return item item, cookie = self.GetNextChild(root, cookie) def _set_item(self, root, key, *values): """Set the item [root/key] with values recursively. """ item = self._get_item(root, key) or self.AppendItem(root, key) branches = next((x for x in values if isinstance(x, (tuple, list))), []) rest = [x for x in values if x not in branches] if rest: ## Take the first element assuming it's client data. ## Set the item client data. (override as needed) self.SetItemData(item, *rest) for branch in branches: self._set_item(item, *branch)
[docs] def SetItemData(self, item, data, *rest): """Sets the item client data. (override)""" try: data._itemId = item wx.TreeCtrl.SetItemData(self, item, data) except AttributeError: pass
## -------------------------------- ## Actions for bookshelf interfaces ## --------------------------------
[docs] def watch(self, target): self.unwatch() self.target = target if self.target: for editor in self.target.get_pages(EditorBook): editor.handler.append(self.context) self[editor.Name] = [[buf.name, ItemData(self, buf)] for buf in editor.all_buffers] self.reset()
[docs] def unwatch(self): if self.target: for editor in self.target.get_pages(EditorBook): editor.handler.remove(self.context) self.clear() self.reset() self.target = None
[docs] def on_buffer_new(self, buf): self[f"{buf.parent.Name}/{buf.name}"] = ItemData(self, buf) self.reset(clear=0)
[docs] def on_buffer_deleted(self, buf): del self[f"{buf.parent.Name}/{buf.name}"] self.reset()
[docs] def on_buffer_selected(self, buf): data = self[f"{buf.parent.Name}/{buf.name}"] if data: self.SelectItem(data._itemId)
[docs] def on_buffer_caption(self, buf): data = self[f"{buf.parent.Name}/{buf.name}"] if data: self.SetItemText(data._itemId, buf.caption)
[docs] def on_buffer_filename(self, buf): for key, data in self.items(): # <-- old key if data.buffer is buf: self.SetItemText(data._itemId, buf.name) for item in self[buf.parent.Name]: if item[1] is data: item[0] = buf.name # --> new key break break
[docs] def OnSelChanged(self, evt): if self and self.HasFocus(): data = self.GetItemData(evt.Item) if data: data.buffer.SetFocus() self.SetFocus() evt.Skip()
[docs] def OnItemTooltip(self, evt): data = self.GetItemData(evt.Item) if data: evt.SetToolTip(data.buffer.filename) evt.Skip()
[docs]class Plugin(Layer):
[docs] def Init(self): self.tree = EditorTreeCtrl(self, style=wx.TR_DEFAULT_STYLE ## | wx.TR_HIDE_ROOT ## | wx.TR_FULL_ROW_HIGHLIGHT ## | wx.TR_NO_LINES ) self.tree.watch(self.parent.shellframe.ghost) self.layout( (self.tree,), expand=2, border=0, vspacing=0 )
[docs] def Destroy(self): try: self.tree.unwatch() finally: return Layer.Destroy(self)
if __name__ == "__main__": from wxpyNautilus import Frame app = wx.App() frm = Frame(None) frm.load_plug(Plugin, show=1, dock=5) frm.Show() app.MainLoop()