nav_buttons.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 » nav_buttons.py
#@+leo-ver=4-thin
#@+node:edream.110203113231.758:@thin nav_buttons.py
#@<< docstring >>
#@+node:bob.20080103150617:<< docstring >>
"""
Add navigation buttons to icon bar
==================================

This plugin adds buttons to the icon bar that:

    - allow the selected position to be moved between recently visited positions

    - pops up a dialog which shows recently visited positions and allows them
      to be selected.

    - pops up a dialog which shows currently marked nodes and allows them to be
      selected

In addition, the marks button and the previous/next arrow buttons have right 
click menus that pop up in response to right clicks from the mouse.


Commands
--------

    show-recent-sections-dialog

    show-marks-dialog

rClick menu generator commands
------------------------------

    These minibuffer commands are for use in rClick and @popup menus. To include
    the menus generated by these commands:

        In @popup menus use '@item *' in the headline and the name of the
        command as the first line of the body.

        In rClick menu tables use ('*', <command-name>)

    nav-marks-menu:

        creates menu items for each marked headline that will select that headline
        when invoked.

    nav-prev-menu:

        creates menu items for each previously visited node that will select
        that headline when invoked. The items are created in the same order as
        the headlines would be visited by pressing the left arrow icon.

    nav-next-menu:

        creates menu items for each each next to be visited node that will
        select that headline when invoked. The items are created in the same
        order they would be visited by pressing the right arrow icon.

    Typical usage for these commands would be:

        @menu prev
            @item *    body = nav-prev-menu
"""

#@+at 
#@nonl
# disabled last part of the docstring.
# 
# 
# Gui Support
# -----------
# 
# This plugin supplies the gui components for the tkinter gui.
# 
# Any non-tkinter gui's wishing to support this plugin should supply:
# 
#     a marksDialog class          as g.app.gui.marksDialog
#     a recentSectionsDialog class as g.app.gui.recentSectionsDialog
# 
# Obviously these classes should mimic the behavior of the Tk classes for
# the relevant gui.
# 
# The dialogs will be automatically detected by the plugin and used if 
# supplied.
#@-at
#@-node:bob.20080103150617:<< docstring >>
#@nl

#@@language python
#@@tabwidth -4

#@<< imports >>
#@+node:ekr.20050219114353:<< imports >>
import leo.core.leoGlobals as g
import leo.core.leoPlugins as leoPlugins

if g.app.gui.guiName() == 'tkinter':

    import leo.plugins.tkGui as tkGui
    leoTkinterDialog = tkGui.leoTkinterDialog
    tkinterListBoxDialog = tkGui.tkinterListBoxDialog

    try:
        import Tkinter as Tk
    except ImportError:
        Tk = None
else:
    class tkinterListBoxDialog: pass
    Tk = None

import os
#@-node:ekr.20050219114353:<< imports >>
#@nl
__version__ = "1.15" # EKR: Don't touch this code without my permission!
#@<< version history >>
#@+node:ekr.20050219114353.1:<< version history >>
#@@killcolor
#@+at
# 
# 1.3 EKR:
# - Rewritten to use:
#     - init and onCreate functions.
#     - Common imageClass.
#     - per-commander dialogs.
#     - positions rather than vnodes.
# - Fixed numerous bugs.
# - The code is _much_ simpler than before.
# - Added marksInitiallyVisible and recentInitiallyVisible config
# constants.
# 1.4 EKR: 2 bug fixes
# - Allways fill the box when clicking on the 'Recent' button.
# - Use keywords.get('c') NOT self.c in hook handlers.  They may not be the 
# same!
# - This is actually a bug in leoPlugins.registerHandler, but it can't be
# fixed because there is no way to associate commanders with hook handlers.
# 1.5 EKR: Fixed crasher in tkinterListBoxDialog.go().
# updateMarks must set positionList ivar in the base class.
# 1.6 EKR: Use c.nodeHistory methods instead of raw ivars of the commander.
# 1.7 plumloco: Modified to be gui-independant.
# 1.8 EKR:
# - Added show-marks-dialog and show-recent-sections-dialog commands.
# - Select an item initially.
# - Added bindings for up and down arrows.
# 1.9 bobjack:
# - Fixed hook bugs.
#     - added module level hook dispatchers and a guard so that hooks
#       only get registered once.  Hooks handlers for non existent
#       commanders as the references in the hook list were keeping
#       these alive.
#     - changed mark hooks from open2, new2 to after-create-leo-frame
#       as open2 and new2 do not work
#     - removed open2 and new2 from recent hooks ditto.
# 1.10 bobjack:
# - Added rClick menus to left and right nav buttons
# - Added rClick menu to Marks button
# - Limited menu lengths to 30 items.
# 1.11 bobjack:
# - Added some docstrings.
# - Moved hook registration to init.
# 1.12 bobjack:
#     - bind prev and next buttons together if Tk and toolbar plugin enabled
# 1.13 EKR: Reverted to organization used in Leo 4.4.5, while retaining latest 
# code.
# 1.14 EKR: Added guards for c.nodeHistory.
# 1.15 EKR: Import from tkGui as needed.
#@-at
#@nonl
#@-node:ekr.20050219114353.1:<< version history >>
#@nl

marksInitiallyVisible = False
recentInitiallyVisible = False

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

    if Tk is None: return False

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

    ok = g.app.gui.guiName() == "tkinter"

    if ok:
        leoPlugins.registerHandler('after-create-leo-frame',onCreate)
        g.plugin_signon(__name__)

    return ok
#@-node:ekr.20050219114353.2:init
#@+node:ekr.20050219115116:onCreate
def onCreate (tag,keywords):

    # Not ok for unit testing: can't use unitTestGui.
    if g.app.unitTesting or g.app.gui.guiName() != 'tkinter':
        return

    c = keywords.get("c")
    r = leoPlugins.registerHandler

    images = imageClass()

    # Create the marks dialog and hooks.
    marks = marksDialog(c,images)
    marks.updateMarks()
    r(('set-mark','clear-mark'),marks.updateMarks)

    # Create the recent nodes dialog.
    recent = recentSectionsDialog(c,images)
    recent.updateRecent()
    r('select2',recent.updateRecent)
#@-node:ekr.20050219115116:onCreate
#@+node:ekr.20050219115859:class imageClass
class imageClass:

    """An image manager class."""

    #@    @+others
    #@+node:ekr.20050219115859.1:ctor
    def __init__ (self):

        """Load the images needed for the module."""

        if not Tk:
            return

        self.path = g.os_path_join(g.app.loadDir,'..','Icons')

        # Create images and set ivars.
        for ivar,icon in (
            ('lt_nav_disabled_image','lt_arrow_disabled.gif'),
            ('lt_nav_enabled_image', 'lt_arrow_enabled.gif'),
            ('rt_nav_disabled_image','rt_arrow_disabled.gif'),
            ('rt_nav_enabled_image', 'rt_arrow_enabled.gif'),
        ):
            image = self.createImage(icon)
            setattr(self,ivar,image)
    #@-node:ekr.20050219115859.1:ctor
    #@+node:ekr.20050219115859.2:createImage
    def createImage (self,iconName):

        """Load a single image from a file."""

        path = os.path.normpath(os.path.join(self.path,iconName))

        try:
            image = Tk.PhotoImage(master=g.app.root,file=path)
        except:
            g.es("can not load icon: %s" % iconName)
            image = None

        return image
    #@-node:ekr.20050219115859.2:createImage
    #@-others
#@-node:ekr.20050219115859:class imageClass
#@+node:edream.110203113231.775:class marksDialog (listBoxDialog)
class marksDialog (tkinterListBoxDialog):

    """A class to create the marks dialog."""

    #@    @+others
    #@+node:edream.110203113231.776: marksDialog.__init__
    def __init__ (self,c,images):

        """Create a Marks listbox dialog."""

        self.c = c
        self.images = images

        self.label = None
        self.title = 'Marks for %s' % g.shortFileName(c.mFileName) # c.frame.title

        # Init the base class and call self.createFrame.
        tkinterListBoxDialog.__init__(self,c,self.title,self.label)

        # Create the show-marks-dialog command.
        self.addCommand()


        if not marksInitiallyVisible:
            self.top.withdraw()

        self.addButtons()

        # Create the marks menu generator commands.
        self.addGeneratorCommands()

        c.bind(self.top,"<Up>",self.up)
        c.bind(self.top,"<Down>",self.down)
    #@-node:edream.110203113231.776: marksDialog.__init__
    #@+node:ekr.20050219131752:addButtons
    def addButtons (self):

        """Add extra buttons to the dialog."""

        c = self.c ; images = self.images

        def marksButtonCallback(*args,**keys):
            self.top.deiconify()
            # No call to c.outerUpdate is needed here.

        self.marks_button = btn = c.frame.addIconButton(
            text="Marks",command=marksButtonCallback)

        c.bind(btn,'<Button-3>', self.rClickMarks)
    #@-node:ekr.20050219131752:addButtons
    #@+node:bobjack.20080411192347.2:rClickMarks
    def rClickMarks(self, event):

        """Show a popup menu to select a mark."""

        c = self.c

        menu_table = [('*', 'nav-marks-menu')]   

        g.doHook('rclick-popup', c=c, event=event, context_menu=menu_table)
    #@-node:bobjack.20080411192347.2:rClickMarks
    #@+node:ekr.20080311065442.2:addCommand
    def addCommand (self):

        '''Create the show-marks-dialog command.'''

        c = self.c

        # The event arg is required to keep a unit test happy.
        def showMarksDialogCallback(event,*args,**keys):
            self.top.deiconify()

        c.k.registerCommand('show-marks-dialog',
            shortcut=None,func=showMarksDialogCallback)
    #@-node:ekr.20080311065442.2:addCommand
    #@+node:bobjack.20080411192347.8:addGeneratorCommands
    def addGeneratorCommands(self):

        """Register rClick minibuffer generator commands."""

        c = self.c

        for command in (
            'nav-marks-menu',
        ):    
            cb = getGeneratorCallback(self, c, command)
            c.k.registerCommand(command, shortcut=None, func=cb)
    #@+node:bobjack.20080411192347.9:nav_marks_menu
    def nav_marks_menu(self, keywords):

        """Generate marks menu and prepend to menu_table."""

        c = self.c

        menu_table = []
        tnodeList = []
        for p in c.all_positions():
            if p.isMarked() and p.v not in tnodeList:
                tnodeList.append(p.v)
                cb = lambda event, keywords, p=p.copy(): self.gotoNode(p)
                menu_table.append((p.h.strip(), cb))

        keywords['rc_menu_table'][:0] = menu_table

    #@-node:bobjack.20080411192347.9:nav_marks_menu
    #@+node:bobjack.20080411192347.3:gotoNode
    def gotoNode(self, p):

        """Select node `p`."""

        c = self.c

        if c.contractVisitedNodes:
           p.contract()

        c.treeSelectHelper(p)
    #@-node:bobjack.20080411192347.3:gotoNode
    #@-node:bobjack.20080411192347.8:addGeneratorCommands
    #@+node:edream.110203113231.777:createFrame
    def createFrame(self):

        """Create the frame for a Marks listbox dialog."""

        tkinterListBoxDialog.createFrame(self)

        f = Tk.Frame(self.outerFrame)
        f.pack()

        self.addStdButtons(f)
    #@nonl
    #@-node:edream.110203113231.777:createFrame
    #@+node:ekr.20080311065442.3:down/up
    def down (self,event):

        """Handle clicks on the dialogs 'down' button."""

        # Work around an old Python bug.  Convert strings to ints.
        items = self.box.curselection()
        try: items = map(int, items)
        except ValueError: pass

        if items:
            n = items[0]
            if n + 1 < len(self.positionList):
                self.box.selection_clear(n)
                self.box.selection_set(n+1)
        else:
            self.box.selection_set(0)

    def up (self,event):

        """Handle clicks on the dialogs 'up' button."""

        # Work around an old Python bug.  Convert strings to ints.
        items = self.box.curselection()
        try: items = map(int, items)
        except ValueError: pass

        if items: n = items[0]
        else:     n = 0
        self.box.selection_clear(n)
        self.box.selection_set(max(0,n-1))
    #@-node:ekr.20080311065442.3:down/up
    #@+node:edream.110203113231.779:updateMarks
    def updateMarks(self,tag=None,keywords=None):

        '''Recreate the Marks listbox. A hook handler.'''

        # It is safe to use self.c as the module level dispatcher
        # ensures we only get events from our own controller.
        c = self.c

        self.box.delete(0,"end")

        # Bug fix 5/12/05: Set self.positionList for use by tkinterListBoxDialog.go().
        i = 0 ; self.positionList = [] ; tnodeList = []

        for p in c.all_positions():
            if p.isMarked() and p.v not in tnodeList:
                self.box.insert(i,p.h.strip())
                tnodeList.append(p.v)
                self.positionList.append(p.copy())
                i += 1

        self.box.selection_set(max(0,len(self.positionList)-1))
    #@-node:edream.110203113231.779:updateMarks
    #@-others
#@nonl
#@-node:edream.110203113231.775:class marksDialog (listBoxDialog)
#@+node:edream.110203113231.780:class recentSectionsDialog (tkinterListBoxDialog)
class recentSectionsDialog (tkinterListBoxDialog):

    """A class to create the recent sections dialog"""

    #@    @+others
    #@+node:edream.110203113231.781:__init__  recentSectionsDialog
    def __init__ (self,c,images):

        """Create a Recent Sections listbox dialog."""

        self.c = c
        self.images = images
        self.label = None
        self.title = "Recent nodes for %s" % g.shortFileName(c.mFileName)
        self.lt_nav_button = self.rt_nav_button = None # Created by createFrame.

        # Create the show-recent-sections-dialog command.
        self.addCommand()

        # Add 'Recent' button to icon bar.
        self.addIconBarButtons()

        # Init the base class. (calls createFrame)
        # N.B.  The base class contains positionList ivar.
        tkinterListBoxDialog.__init__(self,c,self.title,self.label)

        self.fillbox() # Must be done initially.

        if not recentInitiallyVisible:
            self.top.withdraw()

        self.updateButtons()

        self.addGeneratorCommands()

        c.bind(self.top,"<Up>",self.up)
        c.bind(self.top,"<Down>",self.down)
    #@-node:edream.110203113231.781:__init__  recentSectionsDialog
    #@+node:ekr.20080311065442.1:addCommand
    def addCommand (self):

        '''Create the show-recent-sections-dialog command.'''

        c = self.c

        # The event arg is required to keep a unit test happy.
        def recentSectionsCommandCallback(event,*args,**keys):
            self.fillbox(forceUpdate=True)
            self.top.deiconify()

        c.k.registerCommand('show-recent-sections-dialog',
            shortcut=None,func=recentSectionsCommandCallback)
    #@-node:ekr.20080311065442.1:addCommand
    #@+node:bobjack.20080411192347.5:addGeneratorCommands
    def addGeneratorCommands(self):

        """Register rClick minibuffer generator commands."""

        c = self.c

        for command in (
            'nav-prev-menu',
            'nav-next-menu',
            'nav-recent-menu',
        ):

            cb = getGeneratorCallback(self, c, command)
            c.k.registerCommand(command, shortcut=None, func=cb)
    #@+node:bobjack.20080411192347.7:nav_prev_menu
    def nav_prev_menu(self, keywords):

        """Handler for minibuffer command nav-prev-menu."""

        c = self.c

        h = c.nodeHistory
        if not h: return

        menu_table = []

        if h.beadPointer > -1:
            count = 0
            for p, ch in h.beadList[:h.beadPointer]:
                cb = lambda event, keywords, count=count: self.gotoNode(count)
                menu_table[:0] = [(p.h, cb)]
                count += 1

        keywords['rc_menu_table'][:0] = menu_table

    #@-node:bobjack.20080411192347.7:nav_prev_menu
    #@+node:bobjack.20080411192347.11:nav_next_menu
    def nav_next_menu(self, keywords):

        """Handler for minibuffer command nav-next-menu."""

        c = self.c

        h = c.nodeHistory
        if not h: return

        menu_table = []

        if h.beadPointer + 1 < len(h.beadList):
            count = h.beadPointer + 1
            for p, ch in h.beadList[h.beadPointer+1:]:
                cb = lambda event, keywords, count=count: self.gotoNode(count)
                menu_table.append((p.h, cb))
                count += 1

        keywords['rc_menu_table'][:0] = menu_table
    #@-node:bobjack.20080411192347.11:nav_next_menu
    #@+node:bobjack.20080411162443.4:gotoNode
    def gotoNode(self, ptr):

        '''Goto the node in the beadList indexed by ptr.'''

        c = self.c
        h = self.c.nodeHistory
        if not h: return

        p, chapter = h.beadList[ptr]
        h.beadPointer = ptr
        h.selectChapter(chapter)

        if c.contractVisitedNodes:
            g.trace('contracting node')
            p.contract()

        c.treeSelectHelper(p)
    #@-node:bobjack.20080411162443.4:gotoNode
    #@-node:bobjack.20080411192347.5:addGeneratorCommands
    #@+node:edream.110203113231.782:addFrameButtons
    def addFrameButtons (self):

        """Add buttons to the listbox dialog."""

        self.buttonFrame = f = Tk.Frame(self.outerFrame)
        f.pack()

        row1 = Tk.Frame(f)
        row1.pack()

        # Create the back and forward buttons, cloning the images & commands of the already existing buttons.
        image   = self.lt_nav_iconFrame_button.cget("image")
        command = self.lt_nav_iconFrame_button.cget("command")

        self.lt_nav_button = b = Tk.Button(row1,image=image,command=command)
        b.pack(side="left",pady=2,padx=5)

        image   = self.rt_nav_iconFrame_button.cget("image")
        command = self.rt_nav_iconFrame_button.cget("command")

        self.rt_nav_button = b = Tk.Button(row1,image=image,command=command)
        b.pack(side="left",pady=2,padx=5)

        row2 = Tk.Frame(f)
        row2.pack()
        self.addStdButtons(row2)

        row3 = Tk.Frame(f)
        row3.pack()

        self.clear_button = b =  Tk.Button(row3,text="Clear All",
            width=6,command=self.clearAll)
        b.pack(side="left",pady=2,padx=5)

        self.delete_button = b =  Tk.Button(row3,text="Delete",
            width=6,command=self.deleteEntry)
        b.pack(side="left",pady=2,padx=5)
    #@-node:edream.110203113231.782:addFrameButtons
    #@+node:ekr.20050219131336:addIconBarButtons
    def addIconBarButtons (self):

        """Create buttons and add them to the icon bar."""

        c = self.c ; images = self.images

        # Add 'Recent' button to icon bar.
        def recentButtonCallback(*args,**keys):
            self.fillbox(forceUpdate=True)
            self.top.deiconify()
            # No call to c.outerUpdate is needed here.

        self.sections_button = btn = c.frame.addIconButton(
            text="Recent",command=recentButtonCallback)

        #c.bind(btn,'<Button-3>', self.rClickRecent)

        # Add left and right arrows to icon bar.
        self.lt_nav_disabled_image = images.lt_nav_disabled_image
        self.lt_nav_enabled_image  = images.lt_nav_enabled_image
        self.rt_nav_disabled_image = images.rt_nav_disabled_image
        self.rt_nav_enabled_image  = images.rt_nav_enabled_image

        useTkFrame = g.app.gui.guiName() == 'tkinter' and hasattr(c.frame, 'getIconButton')

        if useTkFrame:
            getButton = c.frame.getIconButton
            self.nav_button_frame = bf = Tk.Frame(self.c.frame.top)
        else:
            getButton = c.frame.addIconButton

        self.lt_nav_iconFrame_button = btnl = getButton(
            image=self.lt_nav_disabled_image,
            command=c.goPrevVisitedNode)

        c.bind(btnl,'<Button-3>', self.rClickLeft)

        self.rt_nav_iconFrame_button = btnr = getButton(
            image=self.rt_nav_disabled_image,
            command=c.goNextVisitedNode)

        c.bind(btnr,'<Button-3>', self.rClickRight)

        if useTkFrame:

            for btn in (btnl, btnr):
                btn.pack(in_=bf, side='left')

            bf.leoDragHandle = (btnl, btnr)
            self.c.frame.addIconWidget(bf)

        # Don't dim the button when it is inactive.
        for b in (self.lt_nav_iconFrame_button,self.rt_nav_iconFrame_button):
            fg = b.cget("foreground")
            b.configure(disabledforeground=fg)

        # Package these buttons for the recentSectionsDialog class in leoTkinterDialog.py
        self.nav_buttons = (self.lt_nav_iconFrame_button, self.rt_nav_iconFrame_button)
    #@-node:ekr.20050219131336:addIconBarButtons
    #@+node:bobjack.20080411162443.2:rClickLeft
    def rClickLeft(self, event):

        """Show a popup menu to choose a previously visited node."""

        c = self.c

        menu = [('*', 'nav-prev-menu')]
        g.doHook('rclick-popup', c=c, event=event, context_menu=menu)
    #@-node:bobjack.20080411162443.2:rClickLeft
    #@+node:bobjack.20080411162443.3:rClickRight
    def rClickRight(self,event):

        """Show a popup menu to choose a previously visited node."""

        c = self.c

        menu = [('*', 'nav-next-menu')]
        g.doHook('rclick-popup', c=c, event=event, context_menu=menu)

    #@-node:bobjack.20080411162443.3:rClickRight
    #@+node:bobjack.20080413153103.3:rClickRecent

    #@+at
    # def rClickRecent(self,event):
    # 
    #     """Show a popup menu to choose a previously visited node."""
    # 
    #     c = self.c
    # 
    #     menu = [
    #         (' Prev ', ''),
    #         ('*', 'nav-prev-menu'),
    #         ('|', ''),
    #         (' Next ', ''),
    #         ('*', 'nav-next-menu'),
    #     ]
    #     g.doHook('rclick-popup', c=c, event=event, context_menu=menu)
    #@-at
    #@nonl
    #@-node:bobjack.20080413153103.3:rClickRecent
    #@+node:edream.110203113231.783:clearAll
    def clearAll (self,event=None):

        """Handle clicks in the "Delete" button of the Recent Sections listbox dialog."""

        c = self.c

        self.positionList = []
        if c.nodeHistory:
            c.nodeHistory.clear()
        self.fillbox()
        self.updateButtons()

    #@-node:edream.110203113231.783:clearAll
    #@+node:edream.110203113231.784:createFrame
    def createFrame(self):

        """Create the frame of a Recent Sections listbox dialog."""

        tkinterListBoxDialog.createFrame(self)
        self.addFrameButtons()
    #@nonl
    #@-node:edream.110203113231.784:createFrame
    #@+node:edream.110203113231.785:deleteEntry
    def deleteEntry (self,event=None):

        """Handle clicks in the "Delete" button of a Recent Sections listbox dialog."""

        c = self.c ; box = self.box

        # Work around an old Python bug.  Convert strings to ints.
        items = box.curselection()
        try:
            items = map(int, items)
        except ValueError: pass

        if items:
            n = items[0]
            p = self.positionList[n]
            del self.positionList[n]
            c.nodeHistory.remove(p)
            self.fillbox()
            self.updateButtons()
    #@nonl
    #@-node:edream.110203113231.785:deleteEntry
    #@+node:edream.110203113231.786:destroy
    def destroy (self,event=None):

        """Hide a Recent Sections listbox dialog and mark it inactive.

        This is an escape from possible performance penalties"""

        # This is enough to disable fillbox.
        self.top.withdraw()
    #@-node:edream.110203113231.786:destroy
    #@+node:ekr.20080311065442.4:down/up
    def down (self,event):

        """Handle clicks on the dialogs 'down' button."""

        # Work around an old Python bug.  Convert strings to ints.
        items = self.box.curselection()
        try: items = map(int, items)
        except ValueError: pass

        if items:
            n = items[0]
            if n + 1 < len(self.positionList):
                self.box.selection_clear(n)
                self.box.selection_set(n+1)
        else:
            self.box.selection_set(0)

    def up (self,event):

        """Handle clicks on the dialogs 'up' button."""

        # Work around an old Python bug.  Convert strings to ints.
        items = self.box.curselection()
        try: items = map(int, items)
        except ValueError: pass

        if items: n = items[0]
        else:     n = 0
        self.box.selection_clear(n)
        self.box.selection_set(max(0,n-1))
    #@-node:ekr.20080311065442.4:down/up
    #@+node:edream.110203113231.787:fillbox
    def fillbox(self,forceUpdate=False):

        """Update the Recent Sections listbox."""

        # Only fill the box if the dialog is visible.
        # This is an important protection against bad performance.
        if not forceUpdate and self.top.state() != "normal":
            return

        c = self.c
        if not c.nodeHistory: return

        self.box.delete(0,"end")
        self.positionList = []
        i = 0
        for data in c.nodeHistory.beadList:
            p,theChapter = data
            self.box.insert(i,p.h.strip())
            self.positionList.append(p.copy())
            i += 1

        n = len(c.nodeHistory.beadList)
        p = c.nodeHistory.beadPointer
        self.box.selection_set(max(0,(min(p,n-1))))
    #@-node:edream.110203113231.787:fillbox
    #@+node:ekr.20050219122657:updateButtons
    def updateButtons (self):

        """Update nav buttons to reflect current state."""

        c = self.c
        if not hasattr(c,'nodeHistory') or not c.nodeHistory: return

        for b,b2,enabled_image,disabled_image,cond in (
            (
                self.lt_nav_button,self.lt_nav_iconFrame_button,
                self.lt_nav_enabled_image,self.lt_nav_disabled_image,
                c.nodeHistory.canGoToPrevVisited()),
            (
                self.rt_nav_button,self.rt_nav_iconFrame_button,
                self.rt_nav_enabled_image,self.rt_nav_disabled_image,
                c.nodeHistory.canGoToNextVisited()),
        ):
            # Disabled state makes the icon look bad.
            image = g.choose(cond,enabled_image,disabled_image)
            b.configure(image=image,state='normal')
            b2.configure(image=image,state='normal')
    #@-node:ekr.20050219122657:updateButtons
    #@+node:ekr.20050219162434:updateRecent
    def updateRecent(self,tag=None,keywords=None):

        """Recreate the Recent listbox. A hook handler"""

        # It is safe to use self.c as the module level dispatcher
        # ensures we only get events from our own controller.

        c = self.c

        self.fillbox(forceUpdate=False)
        self.updateButtons()
    #@-node:ekr.20050219162434:updateRecent
    #@-others
#@nonl
#@-node:edream.110203113231.780:class recentSectionsDialog (tkinterListBoxDialog)
#@+node:bobjack.20080412173602.2:getGeneratorCallback
def getGeneratorCallback(obj, c, command):

    """Convert a call to  rClick generator command to a method call on `obj`.

    The method call will be on `obj` , the method name will be calculated from
    `command` by replacing all '-' with '_'.

    The method will be supplied with keyword arguments from theContextMenuController
    and it's return value will be put in same.

    Maybe put this in rClick ???
    """

    def cb(event, obj=obj, c=c, command=command):
        cm = c.theContextMenuController
        method = getattr(obj, command.replace('-','_'))
        cm.mb_retval = method(cm.mb_keywords)

    return cb
#@-node:bobjack.20080412173602.2:getGeneratorCallback
#@-others
#@nonl
#@-node:edream.110203113231.758:@thin nav_buttons.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.