nodenavigator.py :  » Development » Leo » Leo-4.7.1-final » leo » plugins » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » Leo 
Leo » Leo 4.7.1 final » leo » plugins » nodenavigator.py
#@+leo-ver=4-thin
#@+node:ekr.20040108062655:@thin nodenavigator.py
"""Add "Recent" and "Marks" pulldown buttons to the toolbar."""

#@@language python
#@@tabwidth -4

__plugin_name__ = "Node Navigator"
__version__ = "0.15"

#@<< version history >>
#@+node:ekr.20040908093511.2:<< version history >>
#@+at
# 0.4 EKR:
# - Rewrote to handle multiple commanders correctly.
# - Created ctor, set hooks on "new" and "open2".
# - Saved marks so we don't have to rescan:  a major performance boost.
#   This was slowing down write logic considerably.
# - Added basic unit testing.
# 0.5 EKR: Use constant spacing for buttons on MacOs/darwin.
# 0.6 EKR:
# - Create a separate Navigator instance for each open window.
#     This eliminates problems when multiple windows are open.
# - Limit size of recent menu to 25 entries.
# - Limit width of entries to 40 characters.
# 0.7 EKR, following suggestions of Bernhard Mulder.
# - Fix problems with initialization:
#     - Bind onCreate to the "open2" hook.
#     - Set c = keywords.get("new_c") in onCreate.
# 0.8 EKR:
#     - Changed 'new_c' logic to 'c' logic.
#     - Added init function.
# 0.9 EKR: Make sure buttons appear in a new window.
# 0.10 EKR: Make sure self.c == keywords.get('c') in all hook handlers.
# 0.11 EKR: Disabled setting __name__ so that an entry is created for 
# nodenavigator in the Plugins menu.
# 0.13 EKR: set __plugin_name__ rather than __name__.
# 0.14 EKR: use c.nodeHistory.visitedPositions.
# 0.15 EKR: added guards for c.nodeHistory.
#@-at
#@nonl
#@-node:ekr.20040908093511.2:<< version history >>
#@nl
#@<< imports >>
#@+node:ekr.20040908094021.1:<< imports >>
import leo.core.leoGlobals as g
import leo.core.leoPlugins as leoPlugins

Tk = g.importExtension('Tkinter',pluginName=__name__,verbose=True)

import sys
#@nonl
#@-node:ekr.20040908094021.1:<< imports >>
#@nl

# Set this to 0 if the sizing of the toolbar controls doesn't look good on your platform. 
USE_FIXED_SIZES = sys.platform != "darwin"

#@+others
#@+node:ekr.20050311090939.4:init
def init ():

    ok = Tk is not None # OK for unit testing.

    if ok:
        if g.app.gui is None:
            g.app.createTkGui(__file__)

        if g.app.gui.guiName() == "tkinter":
            leoPlugins.registerHandler(('new','open2'), onCreate)
            g.plugin_signon(__name__) #"nodenavigator")

    return ok
#@nonl
#@-node:ekr.20050311090939.4:init
#@+node:ekr.20040909132810:onCreate
def onCreate(tag, keywords):

    # Not ok for unit testing: can't use unitTestGui.
    if g.app.unitTesting:
        return

    c = keywords.get("c")
    nav = Navigator(c)
    nav.addWidgets()

    leoPlugins.registerHandler("set-mark",nav.addMark)
    leoPlugins.registerHandler("clear-mark",nav.clearMark)
    leoPlugins.registerHandler("select3",nav.updateRecent)
#@nonl
#@-node:ekr.20040909132810:onCreate
#@+node:ekr.20040108062655.2:class Navigator
class Navigator:

    """A node navigation aid for Leo"""

    #@    @+others
    #@+node:ekr.20040801062218:__init__
    def __init__ (self,c):

        self.c = c
        self.inited = False
        self.markLists = {}
            # Keys are commanders, values are lists of marked tnodes.
        self.marksMenus = {}
            # Keys are commanders, values are marks menus.
        self.recentMenus = {}
            # Keys are commanders, values are recent menus.
    #@nonl
    #@-node:ekr.20040801062218:__init__
    #@+node:ekr.20040108062655.4:_getSizer
    def _getSizer(self, parent, height, width):

        """Return a sizer object to force a Tk widget to be the right size"""

        if USE_FIXED_SIZES: 
            sizer = Tk.Frame(parent,height=height,width=width) 
            sizer.pack_propagate(0) # don't shrink 
            sizer.pack(side="right") 
            return sizer 
        else: 
            return parent 
    #@nonl
    #@-node:ekr.20040108062655.4:_getSizer
    #@+node:ekr.20040108062655.6:addMark
    def addMark(self, tag, keywords):

        """Add a mark to the marks list"""

        c = keywords.get("c")
        p = keywords.get("p")
        if c != self.c or not p: return

        marks = self.markLists.get(c,[])
        if p.v in marks: return

        menu = self.marksMenus.get(c)
        if menu is None: return
        menu = menu["menu"]

        def callback(event=None,self=self,c=c,p=p.copy()):
            self.select(c,p)

        name = p.h.strip()
        c.add_command(menu,label=name[:40],command=callback)
        marks.append(p.v)

        # Unlike the recent menu, which gets recreated each time, we remember the marks.
        self.markLists[c] = marks
    #@nonl
    #@-node:ekr.20040108062655.6:addMark
    #@+node:ekr.20040108062655.3:addWidgets
    def addWidgets(self):

        """Add the widgets to the navigation bar"""

        c = self.c
        # Create the main container.
        self.frame = Tk.Frame(c.frame.iconFrame)
        if not self.frame: return
        self.frame.pack(side="left")
        # Create the two menus.
        menus = []
        for (name,side) in (("Marks","right"),("Recent","left")):
            args = [name]
            val = Tk.StringVar() 
            menu = Tk.OptionMenu(self._getSizer(self.frame,29,70),val,*args)
            val.set(name) 
            menu.pack(side=side,fill="both",expand=1)
            menus.append(menu)
        self.marksMenus[c] = menus[0]
        self.recentMenus[c] = menus[1]
        # Update the menus.
        self.updateRecent("tag",{"c":c})
        self.initMarks("tag",{"c":c})
    #@nonl
    #@-node:ekr.20040108062655.3:addWidgets
    #@+node:ekr.20040730092357:initMarks
    def initMarks(self, tag, keywords):

        """Initialize the marks list."""

        c = keywords.get("c")
        if c != self.c: return

        # Clear old marks menu
        menu = self.marksMenus.get(c)
        if menu is None: return

        menu = menu["menu"]
        menu.delete(0,"end")

        # Find all marked nodes. We only do this once!
        marks = self.markLists.get(c,[])
        for p in c.all_positions():
            if p.isMarked() and p.v not in marks:
                def callback(event=None,self=self,c=c,p=p.copy()):
                    self.select(c,p)
                name = p.h.strip()
                c.add_command(menu,label=name,command=callback)
                marks.append(p.v)
        self.markLists[c] = marks
    #@nonl
    #@-node:ekr.20040730092357:initMarks
    #@+node:ekr.20040730093250:clearMark
    def clearMark(self, tag, keywords):

        """Remove a mark to the marks list"""

        c = keywords.get("c")
        p = keywords.get("p")
        if c != self.c or not p: return

        marks = self.markLists.get(c,[])
        if not p.v in marks: return

        menu = self.marksMenus.get(c)
        if menu is None: return # This should never happen.
        menu = menu["menu"]

        name = p.h.strip()
        try:
            # 9/7/04: The headline may be in the process of being changed.
            # If so, there is no way to clear the old entry.
            menu.delete(name)
        except Tk.TclError:
            pass
        marks.remove(p.v)

        # Unlike the recent menu, which gets recreated each time, we remember the marks.
        self.markLists[c] = marks
    #@nonl
    #@-node:ekr.20040730093250:clearMark
    #@+node:ekr.20040730094103:select
    def select(self,c,p):

        """Callback that selects position p."""

        if c.positionExists(p):
            c.frame.tree.expandAllAncestors(p)
            c.selectPosition(p)
            c.redraw()
    #@nonl
    #@-node:ekr.20040730094103:select
    #@+node:ekr.20040108091136:updateRecent
    def updateRecent(self,tag,keywords):

        """Add all entries to the recent nodes list."""

        c = keywords.get("c")
        if c != self.c: return
        if not c.nodeHistory: return

        # Clear old recent menu
        menu = self.recentMenus.get(c)
        if not menu: return

        menu = menu["menu"]
        menu.delete(0,"end")

        for p in c.nodeHistory.visitedPositions()[:25]:
            if c.positionExists(p):
                def callback(event=None,self=self,c=c,p=p):
                    self.select(c,p)
                c.add_command(menu,label=p.h[:40],command=callback)
    #@nonl
    #@-node:ekr.20040108091136:updateRecent
    #@-others
#@-node:ekr.20040108062655.2:class Navigator
#@-others
#@nonl
#@-node:ekr.20040108062655:@thin nodenavigator.py
#@-leo
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.