nodebar.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 » nodebar.py
#@+leo-ver=4-thin
#@+node:mork.20041022155742.1:@thin nodebar.py
"""nodebar adds buttons at the bottom of the tree canvas.

The buttons correspond to commands found in the Outline commands. It is intended
to speed up a new users ability to use the outline. Experienced users may find
value in being able to quickly execute commands they do not use very often"""

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

if g.isPython3:
    import configparser as ConfigParser
else:
    import ConfigParser

load_ok=True
try:
    import Pmw
    import weakref
    import Tkinter as Tk
    import os.path
except Exception as x:
    g.es( 'Could not load because of %s' % x )
    load_ok = False
#@nonl
#@-node:ekr.20041030084334:<< imports >>
#@nl

__version__ = ".8"
#@<<version>>
#@+node:mork.20041023091529:<<version>>
#@@nocolor
#@+at
# 
# .1 made initial icons
# .15 eliminated most of the letter icons, made them node based icons.
# .2 EKR:
#     - Fixed hang when help dialog selected.
#     - Write help string to status area on mouse over.
#     - Added test for if g.app.gui.guiName() == "tkinter"
# .25 added movement arrows.  These contrast with the move node arrows by 
# being empty and on the other side of the nodebar.  A user may be able to do 
# all the manipulations he needs of the outline at this point.  Note:  the bar 
# is of such a size we may need to add some kind of scrolling mechanism.  Not 
# sure if I like the hoist and dehoist icons yet. ????
# --tried out scrollbar idea, what a terrible idea.  The user is just going to 
# have to have a big enough screen to use it. :D
# .3 Added balloon help.  Should help new users.  Added .config file machinery
# .4 EKR: Put load_ok code in root.  Added string.atoi = int
# .5 EKR: Defined __version__
# .6 EKR:
# - Changed 'new_c' logic to 'c' logic.
# - Added init function.
# .7 EKR:
# - Removed 'start2' hook.
# - Removed haveseen dict.  It is no longer needed.
# .8 EKR: Defined images in initImages so there is no problem if the gui is 
# not Tk.
#@-at
#@nonl
#@-node:mork.20041023091529:<<version>>
#@nl
#@<<How To Configure>>
#@+node:mork.20041026092203:<<How To Configure>>
#@+at
# 
# 1rst there needs to be a config file in the plugins directory called 
# nodebar.ini
# 
# in this file there needs to be a section with this headline:
# [ nodebar ]
# 
# under this headline there needs to be these two options
# position
# usehelp
# 
# ----
# position should be set to 1 of 3 values:
# position=1
# position=2
# position=3
# 
# 1, means add the nodebar to the icon area of Leo( this is the default )
# 2, means add the nodebar underneath the tree area
# 3, means add the nodebar underneath the editor area
# 
# -----
# usehelp should be set to either 0 or 1:
# usehelp=0
# usehelp=1
# 
# 0, means do not use balloon help when the arrow goes over the nodebar( this 
# is the default )
# 1, means use the balloon help when the arrow goes over the nodebar
# 
# ------
# nodebar will create a .ini file for the user if there isn't one already.
# 
# If there are problems in the .ini file, nodebar should sail on using the 
# default values.
#@-at
#@nonl
#@-node:mork.20041026092203:<<How To Configure>>
#@nl

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

    if not load_ok: return False

    # Ok for unit test.
    if g.app.gui is None: 
        g.app.createTkGui(__file__)

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

    if ok:
        initImages()
        configureNodebar()
        leoPlugins.registerHandler(('open2',"new"),addNodeBar )
        g.plugin_signon(__name__)

    return ok
#@nonl
#@-node:ekr.20050311090939.5:init
#@+node:ekr.20070301091637:initImages
def initImages ():

    #@    << define bitmaps >>
    #@+node:ekr.20070301091637.1:<< define bitmaps >>
    clone = r'''R0lGODlhEAAQAIABAP8AAP///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAhaM
    j6nL7Q8jBDRWG8DThjvqSeJIlkgBADs='''

    copy = r'''R0lGODlhEAAQAMIEAAAAAI9pLOcxcaCclf///////////////ywAAAAAEAAQAAADLEi63P5vSLiC
    vYHiq6+wXSB8mQKcJ2GNLAssr0fCaOyB0IY/ekn9wKBwSEgAADs='''

    cut = r'''R0lGODlhEAAQAKECAAAAAKCclf///////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiaUDad7yS8cnDNYi4A0t7vNaCLTXR/ZZSBFrZMLbaIWzhLczCxTAAA7'''

    dehoist = r'''R0lGODlhEAAQAKECAAAAACMj3v/9/f/9/SH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiOUj6lrwOteivLQKi4LXCcOegJIBmIZLminklbLISIzQ9hbAAA7'''

    delete = r'''R0lGODlhEAAQAMIEAAAAAB89vKCclbq3sv///////////////yH+FUNyZWF0ZWQgd2l0aCBUaGUg
    R0lNUAAsAAAAABAAEAAAAzJIutwKELoGVp02Xmy5294zDSSlBAupMleAEhoYuahaOq4yCPswvYQe
    LyT0eYpEW8iRAAA7'''

    demote = r'''R0lGODlhEAAQAKECACMj3ucxcf///////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiiUj2nBrNniW+G4eSmulqssgAgoduYWeZ+kANPkCsBM1/abxLih70gBADs='''

    insert = r'''R0lGODlhEAAQAKECAAAAAB89vP///////ywAAAAAEAAQAAACKJRhqSvIDGJ8yjWa5MQ5BX4JwXdo
    3RiYRyeSjRqKmGZRVv3Q4M73VAEAOw=='''

    paste = r'''R0lGODlhEAAQAKECAAAAAB89vP///////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiOUH3nLktHYm9HMV92FWfPugQcgjqVBnmm5dsD7gmsbwfEZFQA7'''

    promote = r'''R0lGODlhEAAQAKECACMj3ucxcf///////yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiWUj6kX7cvcgy1CUU1ecvJ+YUGIbKSJAAlqqGQLxPI8t29650YBADs='''

    pasteclone = r'''R0lGODlhEAAQAKEDACMj3v8AAP/9/f///ywAAAAAEAAQAAACOJSPaTPgoxBzgEVDM4yZbtU91/R8
    ClkJzGqp7MK21rcG9tYedSCb7sDjwRLAGs7HsPF8khjzcigAADs='''

    hoist = r'''R0lGODlhEAAQAKECAAAAAENMzf/9/f/9/SwAAAAAEAAQAAACI5SPaRCtypp7S9rw4sVwzwQYW4ZY
    JAWhqYqE7OG+QvzSrI0WADs='''

    moveup = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAh6M
    j6nL7QDcgVDWcFfGUW3zfVPHPZHoUeq6Su4LwwUAOw=='''

    movedown = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAh+M
    j6nL7Q2inFS+EDFw2XT1eVsSHmGJdChpXesFx00BADs='''

    moveleft = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAiWM
    jwDIqd3egueFSe2lF2+oGV41fkwoZmNJJlxXvbDJSbKI1l4BADs='''

    moveright = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAiWM
    A3DLltqaSpFBWt3BFTovWeAyIiUinSNnkaf2Zagpo2x343IBADs='''

    nodeup = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAhqM
    j6nL7QDcgVBS2u5dWqfeTWA4lqYnpeqqFgA7'''

    nodedown = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAhuM
    j6nL7Q2inLTaGW49Wqa+XBD1YE8GnOrKBgUAOw=='''

    nodeleft = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAiOM
    jwDIqd3Ug0dOam/MC3JdfR0jjuRHBWjKpUbmvlIsm65WAAA7'''

    noderight = r'''R0lGODlhEAAQAIABAENMzf///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAiGM
    A3DLltrag/FMWi+WuiK9WWD4gdGYdenklUnrwqX8tQUAOw=='''

    question = r'''R0lGODlhEAAQAIABAB89vP///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAAEAAAAiCM
    DwnHrNrcgzFQGuGrMnGEfdtnjKRJpt2SsuxZqqgaFQA7'''

    sortchildren = r'''R0lGODlhEAAQAKECAAAAAB89vP/9/f/9/SwAAAAAEAAQAAACJJSPKcGt2NwzbKpqYcg68oN9ITde
    UQCkKgCeCvutsDXPk/wlBQA7'''

    sortsiblings = r'''R0lGODlhEAAQAKECAAAAAB89vP/9/f/9/SH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAAABAA
    EAAAAiWUFalxbatcS7IiZh3NE2L+fOAGXpknal4JlAIAw2Br0Fksu1YBADs='''
    #@-node:ekr.20070301091637.1:<< define bitmaps >>
    #@nl

    global clonePI ; clonePI = Tk.PhotoImage(data=clone)
    global copyPI ; copyPI = Tk.PhotoImage(data=copy)
    global cutPI ; cutPI = Tk.PhotoImage(data=cut)
    global dehoistPI ; dehoistPI = Tk.PhotoImage(data=dehoist)
    global deletePI ; deletePI = Tk.PhotoImage(data=delete)
    global demotePI ; demotePI = Tk.PhotoImage(data=demote)
    global hoistPI ; hoistPI = Tk.PhotoImage(data=hoist)
    global insertPI ; insertPI = Tk.PhotoImage(data=insert)
    global movedownPI ; movedownPI = Tk.PhotoImage(data=movedown)
    global moveleftPI ; moveleftPI = Tk.PhotoImage(data=moveleft)
    global moverightPI ; moverightPI = Tk.PhotoImage(data=moveright)
    global moveupPI ; moveupPI = Tk.PhotoImage(data=moveup)
    global nodedownPI ; nodedownPI = Tk.PhotoImage(data=nodedown)
    global nodeleftPI ; nodeleftPI = Tk.PhotoImage(data=nodeleft)
    global noderightPI ; noderightPI = Tk.PhotoImage(data=noderight)
    global nodeupPI ; nodeupPI = Tk.PhotoImage(data=nodeup)
    global pastePI ; pastePI = Tk.PhotoImage(data=paste)
    global pasteclonePI ; pasteclonePI = Tk.PhotoImage(data=pasteclone)
    global promotePI ; promotePI = Tk.PhotoImage(data=promote)
    global questionPI ; questionPI = Tk.PhotoImage(data=question)
    global sortchildrenPI ; sortchildrenPI = Tk.PhotoImage(data=sortchildren)
    global sortsiblingsPI ; sortsiblingsPI = Tk.PhotoImage(data=sortsiblings)
#@-node:ekr.20070301091637:initImages
#@+node:mork.20041026090227:determineFrame
def determineFrame( c ):
    '''Returns the area in Leo where the user wants the nodebar.  Default to are 1'''
    cpos = config[ pos ]

    if cpos == '2':
        frame = c.frame.split2Pane1
    elif cpos == '3':
        frame = c.frame.split1Pane2
    else: #Should be area 1.  If its something else we use area 1.
        frame = c.frame.iconFrame 

    return frame
#@nonl
#@-node:mork.20041026090227:determineFrame
#@+node:mork.20041022160305:addNodeBar
def addNodeBar( tag, keywords ):
    '''Add nodebar to new frame'''
    c = keywords.get( 'c' )
    if not c: return

    frame = determineFrame( c )
    if not frame: return
    mbox = Tk.Frame( frame )
    mbox.pack( side = 'bottom' , fill = 'x' )
    for z in frame.children.values():
        mbox.pack_configure( before = z )

    def goToChild( c = c ):
        pos = c.p
        if pos.hasChildren():
            c.selectPosition( pos.nthChild( 0 ) )

    bcommands = ( 
                  ( c.moveOutlineUp, nodeupPI, 'Move Node Up' ),
                  ( c.moveOutlineDown, nodedownPI , 'Move Node Down' ),
                  ( c.moveOutlineLeft, nodeleftPI , 'Move Node Left' ),
                  ( c.moveOutlineRight, noderightPI, 'Move Node Right' ),
                  ( c.clone, clonePI , 'Clone Node' ),
                  ( c.copyOutline, copyPI, 'Copy Node' ),
                  ( c.cutOutline, cutPI, 'Cut Node' ),
                  ( c.deleteOutline, deletePI, 'Delete Node' ),
                  ( c.pasteOutline, pastePI , 'Paste Node' ),
                  ( c.pasteOutlineRetainingClones, pasteclonePI, 'Paste Retaining Clones' ),
                  ( c.insertHeadline, insertPI, 'Insert Node' ),
                  ( c.demote, demotePI, 'Demote' ),
                  ( c.promote, promotePI , 'Promote' ) ,
                  ( c.hoist, hoistPI, 'Hoist'),
                  ( c.dehoist, dehoistPI, 'De-Hoist' ),
                  ( c.sortChildren, sortchildrenPI, 'Sort Children' ),
                  ( c.sortSiblings, sortsiblingsPI, 'Sort Siblings' ),
                  ( c.goToPrevSibling, moveupPI, 'Goto Previous Sibling' ),
                  ( c.goToNextSibling, movedownPI, 'Goto Next Sibling' ),
                  ( c.goToParent, moveleftPI, 'Goto Parent' ),
                  ( goToChild, moverightPI, 'Goto Child' ),
                  )
    for i, z in enumerate( bcommands ):
        add( c, mbox ,i, *z )       

    #@    << Create the help button >>
    #@+node:mork.20041026100755:<< Create the help button >>
    ques = Tk.Button( mbox, image = questionPI, 
        command = lambda c = c, items = bcommands: view_help(c,items) )    
    ques.grid( column = i + 1, row = 1 ) 

    if int( config[ help ] ):
        addBalloon( mbox, ques, "Help" )

    def callback(event,c=c ):
        c.frame.clearStatusLine()
        c.frame.putStatusLine("Open Help Dialog")

    c.bind2(ques,"<Enter>",callback, '+' )
    #@nonl
    #@-node:mork.20041026100755:<< Create the help button >>
    #@nl
#@nonl
#@-node:mork.20041022160305:addNodeBar
#@+node:mork.20041022172156:add
def add( c, frame, column, command, image, text ):
    '''Add a button to the nodebar'''
    b = Tk.Button( frame, command = command , image = image )
    b.grid( column = column , row = 1)
    if int( config[ help ] ):
        addBalloon( frame, b, text )

    def callback(event,c=c,s=text):
        c.frame.clearStatusLine()
        c.frame.putStatusLine(s)

    c.bind2(b,"<Enter>",callback, '+' )
#@nonl
#@-node:mork.20041022172156:add
#@+node:mork.20041026083725:addBalloon
balloons = {}
def addBalloon( frame, widget, text ):
    '''Help ballon is added to a frame and text is bound to a specific widget'''
    if not balloons.has_key( frame ):
        balloons[ frame ] = Pmw.Balloon( frame )


    balloon = balloons[ frame ]
    balloon.bind( widget, text )
#@nonl
#@-node:mork.20041026083725:addBalloon
#@+node:mork.20041022175619:view_help
def view_help( c, items ):
    '''Opens the Help dialog up for the user to view'''
    dialog = Pmw.Dialog( c.frame.top, title = 'Button Help' )
    sf = Pmw.ScrolledFrame( dialog.interior() )

    sf.pack()
    sfi = sf.interior()

    for z in items:
        lw = Pmw.LabeledWidget( sfi , labelpos = 'e', label_text = z[ 2 ] )
        l = Tk.Button( lw.interior() , image = z[ 1 ] )
        lw.pack()
        l.pack()

    dialog.activate()

#@-node:mork.20041022175619:view_help
#@+node:mork.20041026084314:configureNodebar
config = {}
pos = 'position'
help = 'usehelp'
config[ pos ] = '1' #The default is to put the bar in the icon area
config[ help ] = '1' #The default is to see the help buttons

def configureNodebar():
    '''nodebar reads what the config file has in it and sets global state'''
    nbar = 'nodebar'
    cparser = readConfigFile()
    if not cparser: return None
    for z in cparser.sections():
        if z.strip() == nbar:
            nbar = z
            break
    if cparser.has_section( nbar ):
        if cparser.has_option( nbar, pos ):
            p = cparser.get( nbar, pos )
            if p.isdigit():
                config[ pos ] = p
            else:
                g.es( "Bad value in nodebar.ini: %s" % p, color= 'red' )
                g.es( "Was expecting a digit", color = 'red' )
        if cparser.has_option( nbar, help ):
            p = cparser.get( nbar, help )
            if p.isdigit():
                config[ help ] = p
            else:
                g.es( "Bad value in nodebar.ini: %s" % p, color= 'red' )
                g.es( "Was expecting a digit", color = 'red' )
#@nonl
#@-node:mork.20041026084314:configureNodebar
#@+node:mork.20041026084509:readConfigFile
def readConfigFile ():

    #reads the nodebar config file in.
    pth = os.path.split(g.app.loadDir)   
    aini = pth[0]+r"/plugins/nodebar.ini"
    if not os.path.exists(aini):
        try:
            cf = file( aini, 'w' )#creates config file for user, how nice.
            data='''
[ nodebar ]
position=1
usehelp=1
            '''
            cf.write( data )
            cf.close()
            g.es( "Added nodebar.ini to plugin directory", color='blue' )
        except Exception as x:
            g.es( "Could not create nodebar.init because of : %s" % x, color='red' )
            return None
    try:
        cp = ConfigParser.ConfigParser()
        cp.read(aini)
        return cp
    except Exception as x:
        g.es( "Could not read nodebar.ini because of : %s "%x, color='red' )
        return None
#@nonl
#@-node:mork.20041026084509:readConfigFile
#@-others
#@nonl
#@-node:mork.20041022155742.1:@thin nodebar.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.