/opt/alt/python37/lib64/python3.7/idlelib
NameSizeModeActions
Icons/-0755rm
idle_test/-0755rm
__pycache__/-0755rm
autocomplete.py89540644editdlrm
autocomplete_w.py201090644editdlrm
autoexpand.py32160644editdlrm
browser.py83140644editdlrm
calltip.py63180644editdlrm
calltip_w.py71580644editdlrm
ChangeLog563600644editdlrm
codecontext.py113260644editdlrm
colorizer.py129920644editdlrm
config-extensions.def22660644editdlrm
config-highlight.def28640644editdlrm
config-keys.def109100644editdlrm
config-main.def31680644editdlrm
config.py381730644editdlrm
configdialog.py1045240644editdlrm
config_key.py144650644editdlrm
CREDITS.txt18660644editdlrm
debugger.py191040644editdlrm
debugger_r.py121400644editdlrm
debugobj.py40550644editdlrm
debugobj_r.py10820644editdlrm
delegator.py10430644editdlrm
dynoption.py20170644editdlrm
editor.py656140644editdlrm
extend.txt36420644editdlrm
filelist.py38960644editdlrm
format.py157770644editdlrm
grep.py74790644editdlrm
help.html622140644editdlrm
help.py117340644editdlrm
help_about.py89810644editdlrm
history.py40430644editdlrm
HISTORY.txt103120644editdlrm
hyperparser.py128830644editdlrm
idle.py4540644editdlrm
idle.pyw5700644editdlrm
iomenu.py206320644editdlrm
macosx.py96620644editdlrm
mainmenu.py39180644editdlrm
multicall.py186480644editdlrm
NEWS.txt487910644editdlrm
NEWS2x.txt271720644editdlrm
outwin.py57880644editdlrm
parenmatch.py72040644editdlrm
pathbrowser.py31930644editdlrm
percolator.py31300644editdlrm
pyparse.py199470644editdlrm
pyshell.py572470755editdlrm
query.py148980644editdlrm
README.txt95990644editdlrm
redirector.py68750644editdlrm
replace.py98890644editdlrm
rpc.py211370644editdlrm
run.py202930644editdlrm
runscript.py87810644editdlrm
scrolledlist.py44650644editdlrm
search.py55660644editdlrm
searchbase.py75370644editdlrm
searchengine.py74720644editdlrm
sidebar.py135850644editdlrm
squeezer.py128400644editdlrm
stackviewer.py44540644editdlrm
statusbar.py14410644editdlrm
textview.py68130644editdlrm
TODO.txt84780644editdlrm
tooltip.py65650644editdlrm
tree.py163570644editdlrm
undo.py110460644editdlrm
window.py26160644editdlrm
zoomheight.py42030644editdlrm
zzdummy.py9610644editdlrm
__init__.py3960644editdlrm
__main__.py1590644editdlrm
Edit: /opt/alt/python37/lib64/python3.7/idlelib/tree.py (16357B)
# XXX TO DO: # - popup menu # - support partial or total redisplay # - key bindings (instead of quick-n-dirty bindings on Canvas): # - up/down arrow keys to move focus around # - ditto for page up/down, home/end # - left/right arrows to expand/collapse & move out/in # - more doc strings # - add icons for "file", "module", "class", "method"; better "python" icon # - callback for selection??? # - multiple-item selection # - tooltips # - redo geometry without magic numbers # - keep track of object ids to allow more careful cleaning # - optimize tree redraw after expand of subnode import os from tkinter import * from tkinter.ttk import Frame, Scrollbar from idlelib.config import idleConf from idlelib import zoomheight ICONDIR = "Icons" # Look for Icons subdirectory in the same directory as this module try: _icondir = os.path.join(os.path.dirname(__file__), ICONDIR) except NameError: _icondir = ICONDIR if os.path.isdir(_icondir): ICONDIR = _icondir elif not os.path.isdir(ICONDIR): raise RuntimeError("can't find icon directory (%r)" % (ICONDIR,)) def listicons(icondir=ICONDIR): """Utility to display the available icons.""" root = Tk() import glob list = glob.glob(os.path.join(icondir, "*.gif")) list.sort() images = [] row = column = 0 for file in list: name = os.path.splitext(os.path.basename(file))[0] image = PhotoImage(file=file, master=root) images.append(image) label = Label(root, image=image, bd=1, relief="raised") label.grid(row=row, column=column) label = Label(root, text=name) label.grid(row=row+1, column=column) column = column + 1 if column >= 10: row = row+2 column = 0 root.images = images def wheel_event(event, widget=None): """Handle scrollwheel event. For wheel up, event.delta = 120*n on Windows, -1*n on darwin, where n can be > 1 if one scrolls fast. Flicking the wheel generates up to maybe 20 events with n up to 10 or more 1. Macs use wheel down (delta = 1*n) to scroll up, so positive delta means to scroll up on both systems. X-11 sends Control-Button-4,5 events instead. The widget parameter is needed so browser label bindings can pass the underlying canvas. This function depends on widget.yview to not be overridden by a subclass. """ up = {EventType.MouseWheel: event.delta > 0, EventType.ButtonPress: event.num == 4} lines = -5 if up[event.type] else 5 widget = event.widget if widget is None else widget widget.yview(SCROLL, lines, 'units') return 'break' class TreeNode: def __init__(self, canvas, parent, item): self.canvas = canvas self.parent = parent self.item = item self.state = 'collapsed' self.selected = False self.children = [] self.x = self.y = None self.iconimages = {} # cache of PhotoImage instances for icons def destroy(self): for c in self.children[:]: self.children.remove(c) c.destroy() self.parent = None def geticonimage(self, name): try: return self.iconimages[name] except KeyError: pass file, ext = os.path.splitext(name) ext = ext or ".gif" fullname = os.path.join(ICONDIR, file + ext) image = PhotoImage(master=self.canvas, file=fullname) self.iconimages[name] = image return image def select(self, event=None): if self.selected: return self.deselectall() self.selected = True self.canvas.delete(self.image_id) self.drawicon() self.drawtext() def deselect(self, event=None): if not self.selected: return self.selected = False self.canvas.delete(self.image_id) self.drawicon() self.drawtext() def deselectall(self): if self.parent: self.parent.deselectall() else: self.deselecttree() def deselecttree(self): if self.selected: self.deselect() for child in self.children: child.deselecttree() def flip(self, event=None): if self.state == 'expanded': self.collapse() else: self.expand() self.item.OnDoubleClick() return "break" def expand(self, event=None): if not self.item._IsExpandable(): return if self.state != 'expanded': self.state = 'expanded' self.update() self.view() def collapse(self, event=None): if self.state != 'collapsed': self.state = 'collapsed' self.update() def view(self): top = self.y - 2 bottom = self.lastvisiblechild().y + 17 height = bottom - top visible_top = self.canvas.canvasy(0) visible_height = self.canvas.winfo_height() visible_bottom = self.canvas.canvasy(visible_height) if visible_top <= top and bottom <= visible_bottom: return x0, y0, x1, y1 = self.canvas._getints(self.canvas['scrollregion']) if top >= visible_top and height <= visible_height: fraction = top + height - visible_height else: fraction = top fraction = float(fraction) / y1 self.canvas.yview_moveto(fraction) def lastvisiblechild(self): if self.children and self.state == 'expanded': return self.children[-1].lastvisiblechild() else: return self def update(self): if self.parent: self.parent.update() else: oldcursor = self.canvas['cursor'] self.canvas['cursor'] = "watch" self.canvas.update() self.canvas.delete(ALL) # XXX could be more subtle self.draw(7, 2) x0, y0, x1, y1 = self.canvas.bbox(ALL) self.canvas.configure(scrollregion=(0, 0, x1, y1)) self.canvas['cursor'] = oldcursor def draw(self, x, y): # XXX This hard-codes too many geometry constants! dy = 20 self.x, self.y = x, y self.drawicon() self.drawtext() if self.state != 'expanded': return y + dy # draw children if not self.children: sublist = self.item._GetSubList() if not sublist: # _IsExpandable() was mistaken; that's allowed return y+17 for item in sublist: child = self.__class__(self.canvas, self, item) self.children.append(child) cx = x+20 cy = y + dy cylast = 0 for child in self.children: cylast = cy self.canvas.create_line(x+9, cy+7, cx, cy+7, fill="gray50") cy = child.draw(cx, cy) if child.item._IsExpandable(): if child.state == 'expanded': iconname = "minusnode" callback = child.collapse else: iconname = "plusnode" callback = child.expand image = self.geticonimage(iconname) id = self.canvas.create_image(x+9, cylast+7, image=image) # XXX This leaks bindings until canvas is deleted: self.canvas.tag_bind(id, "<1>", callback) self.canvas.tag_bind(id, "", lambda x: None) id = self.canvas.create_line(x+9, y+10, x+9, cylast+7, ##stipple="gray50", # XXX Seems broken in Tk 8.0.x fill="gray50") self.canvas.tag_lower(id) # XXX .lower(id) before Python 1.5.2 return cy def drawicon(self): if self.selected: imagename = (self.item.GetSelectedIconName() or self.item.GetIconName() or "openfolder") else: imagename = self.item.GetIconName() or "folder" image = self.geticonimage(imagename) id = self.canvas.create_image(self.x, self.y, anchor="nw", image=image) self.image_id = id self.canvas.tag_bind(id, "<1>", self.select) self.canvas.tag_bind(id, "", self.flip) def drawtext(self): textx = self.x+20-1 texty = self.y-4 labeltext = self.item.GetLabelText() if labeltext: id = self.canvas.create_text(textx, texty, anchor="nw", text=labeltext) self.canvas.tag_bind(id, "<1>", self.select) self.canvas.tag_bind(id, "", self.flip) x0, y0, x1, y1 = self.canvas.bbox(id) textx = max(x1, 200) + 10 text = self.item.GetText() or "" try: self.entry except AttributeError: pass else: self.edit_finish() try: self.label except AttributeError: # padding carefully selected (on Windows) to match Entry widget: self.label = Label(self.canvas, text=text, bd=0, padx=2, pady=2) theme = idleConf.CurrentTheme() if self.selected: self.label.configure(idleConf.GetHighlight(theme, 'hilite')) else: self.label.configure(idleConf.GetHighlight(theme, 'normal')) id = self.canvas.create_window(textx, texty, anchor="nw", window=self.label) self.label.bind("<1>", self.select_or_edit) self.label.bind("", self.flip) self.label.bind("", lambda e: wheel_event(e, self.canvas)) self.label.bind("", lambda e: wheel_event(e, self.canvas)) self.label.bind("", lambda e: wheel_event(e, self.canvas)) self.text_id = id def select_or_edit(self, event=None): if self.selected and self.item.IsEditable(): self.edit(event) else: self.select(event) def edit(self, event=None): self.entry = Entry(self.label, bd=0, highlightthickness=1, width=0) self.entry.insert(0, self.label['text']) self.entry.selection_range(0, END) self.entry.pack(ipadx=5) self.entry.focus_set() self.entry.bind("", self.edit_finish) self.entry.bind("", self.edit_cancel) def edit_finish(self, event=None): try: entry = self.entry del self.entry except AttributeError: return text = entry.get() entry.destroy() if text and text != self.item.GetText(): self.item.SetText(text) text = self.item.GetText() self.label['text'] = text self.drawtext() self.canvas.focus_set() def edit_cancel(self, event=None): try: entry = self.entry del self.entry except AttributeError: return entry.destroy() self.drawtext() self.canvas.focus_set() class TreeItem: """Abstract class representing tree items. Methods should typically be overridden, otherwise a default action is used. """ def __init__(self): """Constructor. Do whatever you need to do.""" def GetText(self): """Return text string to display.""" def GetLabelText(self): """Return label text string to display in front of text (if any).""" expandable = None def _IsExpandable(self): """Do not override! Called by TreeNode.""" if self.expandable is None: self.expandable = self.IsExpandable() return self.expandable def IsExpandable(self): """Return whether there are subitems.""" return 1 def _GetSubList(self): """Do not override! Called by TreeNode.""" if not self.IsExpandable(): return [] sublist = self.GetSubList() if not sublist: self.expandable = 0 return sublist def IsEditable(self): """Return whether the item's text may be edited.""" def SetText(self, text): """Change the item's text (if it is editable).""" def GetIconName(self): """Return name of icon to be displayed normally.""" def GetSelectedIconName(self): """Return name of icon to be displayed when selected.""" def GetSubList(self): """Return list of items forming sublist.""" def OnDoubleClick(self): """Called on a double-click on the item.""" # Example application class FileTreeItem(TreeItem): """Example TreeItem subclass -- browse the file system.""" def __init__(self, path): self.path = path def GetText(self): return os.path.basename(self.path) or self.path def IsEditable(self): return os.path.basename(self.path) != "" def SetText(self, text): newpath = os.path.dirname(self.path) newpath = os.path.join(newpath, text) if os.path.dirname(newpath) != os.path.dirname(self.path): return try: os.rename(self.path, newpath) self.path = newpath except OSError: pass def GetIconName(self): if not self.IsExpandable(): return "python" # XXX wish there was a "file" icon def IsExpandable(self): return os.path.isdir(self.path) def GetSubList(self): try: names = os.listdir(self.path) except OSError: return [] names.sort(key = os.path.normcase) sublist = [] for name in names: item = FileTreeItem(os.path.join(self.path, name)) sublist.append(item) return sublist # A canvas widget with scroll bars and some useful bindings class ScrolledCanvas: def __init__(self, master, **opts): if 'yscrollincrement' not in opts: opts['yscrollincrement'] = 17 self.master = master self.frame = Frame(master) self.frame.rowconfigure(0, weight=1) self.frame.columnconfigure(0, weight=1) self.canvas = Canvas(self.frame, **opts) self.canvas.grid(row=0, column=0, sticky="nsew") self.vbar = Scrollbar(self.frame, name="vbar") self.vbar.grid(row=0, column=1, sticky="nse") self.hbar = Scrollbar(self.frame, name="hbar", orient="horizontal") self.hbar.grid(row=1, column=0, sticky="ews") self.canvas['yscrollcommand'] = self.vbar.set self.vbar['command'] = self.canvas.yview self.canvas['xscrollcommand'] = self.hbar.set self.hbar['command'] = self.canvas.xview self.canvas.bind("", self.page_up) self.canvas.bind("", self.page_down) self.canvas.bind("", self.unit_up) self.canvas.bind("", self.unit_down) self.canvas.bind("", wheel_event) self.canvas.bind("", wheel_event) self.canvas.bind("", wheel_event) #if isinstance(master, Toplevel) or isinstance(master, Tk): self.canvas.bind("", self.zoom_height) self.canvas.focus_set() def page_up(self, event): self.canvas.yview_scroll(-1, "page") return "break" def page_down(self, event): self.canvas.yview_scroll(1, "page") return "break" def unit_up(self, event): self.canvas.yview_scroll(-1, "unit") return "break" def unit_down(self, event): self.canvas.yview_scroll(1, "unit") return "break" def zoom_height(self, event): zoomheight.zoom_height(self.master) return "break" def _tree_widget(parent): # htest # top = Toplevel(parent) x, y = map(int, parent.geometry().split('+')[1:]) top.geometry("+%d+%d" % (x+50, y+175)) sc = ScrolledCanvas(top, bg="white", highlightthickness=0, takefocus=1) sc.frame.pack(expand=1, fill="both", side=LEFT) item = FileTreeItem(ICONDIR) node = TreeNode(sc.canvas, None, item) node.expand() if __name__ == '__main__': from unittest import main main('idlelib.idle_test.test_tree', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_tree_widget)