#@+leo-ver=4-thin
#@+node:bobjack.20080424190315.2:@thin toolbar.py
#@@language python
#@@tabwidth -4
#@<< docstring >>
#@+node:bobjack.20080424190906.12:<< docstring >>
#@@nocolor
"""
A plugin that enhances Leo's iconBar and script buttons.
=======================================================
**see test/testToolbar.leo for demo's and howto's **
**see test/testAtPopup.leo for examples of enhanced buttons.**
This plugin provides:
multiple iconBars each of which automatically collapse and
expand so that all the buttons are always visible.
drag and drop of buttons within and between iconBars.
enhancements to Leo's buttons and @button settings to allow
icons, menus, tooltips and text and background colors to be set
in @button settings and scripts.
.. contents::
enhanced script button and @button nodes
----------------------------------------
If the toolbar.py plugin is enabled then a comment block can be added at the top
of the body of the @button node. (If toolbar.py is not enabled then these
comment blocks will of course simply be ignored.)
The header will also be honoured if script-button is used to convert a node
to a button.
Within this block you may include lines starting with @btn to set extra
parameters for the button created.
eg 1::
@
@btn fg = yellow
@btn bg = red
@btn menu = my-button-menu
@c
The created button would have yellow text on a red background and when the right
mouse button is clicked on it a popup menu will appear (if rClick.py is
enabled).
eg 2::
@
@btn icon = Tango/16x16/actions/add.png
@btn menu = my-button-menu
@btn bg =
@btn tooltip = My First Icon Button
@c
Here the button will only have an icon, not text. It still has a right click
menu. The line after the 'bg =' is left blank to suppress any default background
colors, without setting our own color.
Icons in buttons requires the Python Imaging Library to be installed on your computer.
The line containing the single @ must not be preceded by any other line except
blank lines.
toolbars
--------
A 'toolbar' is a collection of 'iconbars'. At the moment only one toolbar is
availiable and it appears in the place where the leo's traditional iconbar appears.
Future plans include allowing toolbars to be placed anywhere, including in dialogs,
orientated vertically as well as horizontally. It will then be possible to drag and
drop iconbars within and between toolbars.
iconbars
--------
Each iconbar is assigned a name, the default iconBar is called 'iconbar'. A
dictionary mapping names to iconBar objects is kept in *c.frame.iconBars* and
the default iconBar is also in *c.frame.iconBar*
Any widget may be added to an iconBar but:
All widgets must have c.frame.top as the parent.
Widgets can not be packed into the bars directly, they must be added
through c.frame.addIconWidget or through <bar>.addWidget
This will break some plugins. If it breaks a plugin you are using report this
on the mailing list and it will be fixed.
If widget.leoShow exists and is set to False then the widget will still be in
the list in its assigned packing order but it will not be seen. Any change to
widget.leoShow must be followed by a call to bar.repackButtons() before the
change will be seen.
Some convenience methods are available in c.frame, all of which can have
barName=<name of bar>. If no barName is supplied 'iconbar' will be used.
createIconBar(barName='iconbar'):
If an iconBar with barName already exists it will be returned, otherwise
a new iconBar will be created, packed and returned.
addIconButton(\*args, \**keys):
creates and packs and returns an icon button. This is equivalent
to c.frame.addIconWidget(c.frame.getIconButton(\*args, \**keys)
barName: 'iconbar' may be in keys.
getIconButton(\*args, \**keys):
creates and returns an icon button but does not pack it. Any barName
will be ignored.
getIconWidgetFrame(\*args, \**keys):
creates an enhanced Tk.Frame widget properly parented and with
a few methods which make it easier to use than a straight Tk.Frame.
args and keys are the same as for Tk.Frame except without the first
(parent) arg which is not used as the Frame will always have c.frame.top
as the parent as required by all widgets to be packed in an iconBar.
addIconWidget(widget, barName='iconbar', index=None):
Adds any widget or button to the named iconBar in the position indicated
by index. If barName does not exist it is created.
This method delegates to c.frame.iconBars[barName].addWidget
The method is used to add buttons as well as other widgets because
'addIconButton' is already taken and has a different meaning.
The iconBars themselves have the following public methods.
getButton(\*args, \**keys)
same as c.frame.getIconButton
getWidgetFrame(\*args, \**keys)
same as c.frame.getWidgetFrame
add(\*args, \**keys)
same as c.frame.addIconButton
repackButtons(buttons=None)
if buttons is None then the current list of buttons is repacked,
otherwise it must be a list of buttons or other widgets to pack
addWidget(widget, index=None, repack=True)
Adds a widget to the list of widgets to be packed in this iconBar.
repack is True by default causing repackButtons() to be called after
adding the widget. If repack is set to False the script must call
repackButtons() itself. Setting repack to False is useful if you
want to add several widgets, you can then call repackButtons() just
once.
If index is None or invalid the widget will be packed at the end
of the iconBar.
removeWidget(widget, repack=True)
removes the widget from the list and optionally repacks the iconBar.
show(show=True)
Makes the toolbar visible if it is not already visible or vice versa
if show is False.
hide()
Makes the toolbar invisible if it was not already invisible.
The iconbars also have the following public properties.
bar.buttons
This provides a shallow *copy* of the list of buttons/widgets contained
in the iconBar. Changing this list has no effect on the iconBar.
Using 'bar.buttons = <list of widgets>' is allowed and is the same as::
bar.repackButtons(<list of widgets>)
Commands of the following kind are allowed::
bar.buttons = bar.buttons[1:]
but the following will not work as expected::
bar.buttons[1:]
bar.visible
tells if the bar is visible or not.
'bar visible = True (or False)' show (or hides) the toolbar.
'bar.visible = not bar.visible' toggles the visibility of the toolbar
compound iconBar widgets and drag handles.
------------------------------------------
Compound widgets can be constructed using a Tkinter.Frame widget and packing
buttons (obtained eg from c.frame.getButton) and other components into it,
finally packing the frame into the iconBar using c.frame.addIconWidget or
bar.addWidget.
The following methods::
c.frame.getIconWidgetFrame(\*args, \*keys) and
bar.getWidgetFram(\*args, \*keys)
return a Tk.Frame widget parented on c.frame.top and with a few extra
methods to make more advanced use easier.
See the compound widgets and drag handles howto in test/testToolbar.leo
"""
#@-node:bobjack.20080424190906.12:<< docstring >>
#@nl
__version__ = "0.14" # EKR
__plugin_name__ = 'Toolbar Manager'
__plugin_id__ = 'Toolbar'
controllers = {}
#@<< version history >>
#@+node:bobjack.20080424190906.13:<< version history >>
#@+at
# 0.1 bobjack:
# - initial version
# 0.2 bobjack:
# - add toolbar-delete-button for use in button menus
# - introduced onPreCreate module method
# 0.3 bobjack:
# - added support for tooltips in @buttons
# - fixed parameter bleed bug
# O.4 bobjack:
# - added support for multiple toolbars
# 0.5 bobjack:
# - added toolbars overflow to other toolbars if they are
# not wide enough to contain their buttons.
# 0.6 bobjack:
# - refactoring
# - make toolbar area collapse when no iconBars are visible
# - add toggle-iconbar minibuffer / rClick menu command
# - remove dependency on rClick
# - add drag drop in iconBars
# 0.7 bobjack:
# - add support for leoDragHandle and leoDragMaster
# 0.8 bobjack:
# - convert to use c.universallCallback via registerCommands( ...
# wrap=True)
# - separate out icon and script button code and make these first class
# objects
# 0.9 bobjack:
# - convert to use class based commands
# 0.10 bobjack:
# - attempt to improve docstring
# - add ToolbarIconWidgetFrame and convenience methods to make
# creating compound widgets for the iconbars easier.
# 0.11 bobjack:
# - use baseclasses in rclickPluginBaseClasses
# 0.12 EKR: add 'font' to list of allowed keys so that font settings are
# honored.
# 0.13 EKR: added support for @args list.
# 0.14 EKR: import tkGui as needed.
#@-at
#@-node:bobjack.20080424190906.13:<< version history >>
#@nl
#@<< todo >>
#@+node:bobjack.20080424190906.14:<< todo >>
#@+at
#
# Use a more efficent repack algorithm to reduce flicker. The current method
# is
# simple and safe. I have tried to optimize repack but keep running into
# special cases and instability.
#@-at
#@nonl
#@-node:bobjack.20080424190906.14:<< todo >>
#@nl
#@<< imports >>
#@+node:bobjack.20080424190906.15:<< imports >>
import leo.core.leoGlobals as g
import leo.core.leoPlugins as leoPlugins
import leo.plugins.tkGui as tkGui
leoTkinterFrame = tkGui.leoTkinterFrame
leoTkinterTreeTab = tkGui.leoTkinterTreeTab
# import re
# import sys
# import os
Tk = g.importExtension('Tkinter',pluginName=__name__,verbose=True,required=True)
Pmw = g.importExtension("Pmw",pluginName=__name__,verbose=True,required=True)
# try:
# from PIL import Image
# from PIL import ImageTk
# except ImportError:
# Image = ImageTk = None
#mod_scripting = g.importExtension('mod_scripting',pluginName=__name__,verbose=True,required=True)
from leo.plugins import mod_scripting
from leo.plugins import rClickBasePluginClasses
#@-node:bobjack.20080424190906.15:<< imports >>
#@nl
#@<< required ivars >>
#@+node:bobjack.20080424195922.85:<< required ivars >>
#@+at
# This is a list of ivars that the pluginController must have and the type of
# objects they are allowed to contain.
#
# (ivar, type)
#
# where type may be a tuple and False indicates any type will do
#
# The list is used by unit tests.
#@-at
#@@c
requiredIvars = (
('commandList', (list, tuple)),
('commandPrefix', g.choose(g.isPython3,str,basestring)),
('grabWidget', False)
)
#@-node:bobjack.20080424195922.85:<< required ivars >>
#@nl
allowedButtonConfigItems = ('image', 'bg', 'fg', 'font','justify', 'padx', 'pady', 'relief', 'text', 'command', 'state')
iconBasePath = g.os_path_join(g.app.leoDir, 'Icons')
#@+others
#@+node:bobjack.20080424190906.6:Module-level
#@+node:bobjack.20080424190906.7:init
def init ():
"""Initialize and register plugin."""
global old
if not Tk:
return False
if g.app.unitTesting:
return False
if g.app.gui is None:
g.app.createTkGui(__file__)
ok = g.app.gui.guiName() == "tkinter"
if ok:
r = leoPlugins.registerHandler
r('before-create-leo-frame',onPreCreate)
r('after-create-leo-frame', onCreate)
r('close-frame', onClose)
tkGui.leoTkinterFrame = ToolbarTkinterFrame
g.plugin_signon(__name__)
return ok
#@-node:bobjack.20080424190906.7:init
#@+node:bobjack.20080424195922.11:onPreCreate
def onPreCreate (tag, keys):
"""Replace iconBarClass with our own."""
c = keys.get('c')
if not (c and c.exists) or hasattr(c.frame, 'toolbarClass'):
return
g.app.gui.ScriptingControllerClass = ToolbarScriptingController
c.frame.iconBarClass = ToolbarTkIconBarClass
c.frame.toolbarClass = ToolbarTkToolbarClass
tkGui.leoTkinterTreeTab = ToolbarTkinterTreeTab
c.frame.iconBars= {}
c.frame.toolbar = None
#@-node:bobjack.20080424195922.11:onPreCreate
#@+node:bobjack.20080426190702.6:onCreate
def onCreate (tag, keys):
"""Handle creation and initialization of the pluginController.
Make sure the pluginController is created only once.
"""
c = keys.get('c')
if not (c and c.exists):
return
controller = controllers.get(c)
if not controller:
controllers[c] = controller = pluginController(c)
controller.onCreate()
c.theToolbarController = controller
#@-node:bobjack.20080426190702.6:onCreate
#@+node:bobjack.20080424195922.10:onClose
def onClose (tag, keys):
"""Tell controller to clean up then destroy it."""
c = keys.get('c')
if not (c and c.exists):
return
controller = controllers.get(c)
try:
del controllers[c]
except KeyError:
pass
if not controller:
return
try:
controller.onClose()
finally:
controller = None
#@-node:bobjack.20080424195922.10:onClose
#@+node:bobjack.20080501055450.5:class ToolbarTkinterTreeTab
class ToolbarTkinterTreeTab (leoTkinterTreeTab):
'''A class representing a tabbed outline pane drawn with Tkinter.'''
#@ @+others
#@+node:bobjack.20080501055450.8:tt.createControl
def createControl (self):
"Create and pack the Chapter Selector control."""
tt = self ; c = tt.c
# Create the main container.
tt.frame = Tk.Frame(c.frame.top)
# Create the chapter menu.
self.chapterVar = var = Tk.StringVar()
var.set('main')
tt.chapterMenu = menu = Pmw.OptionMenu(tt.frame,
labelpos = 'w', label_text = 'chapter',
menubutton_textvariable = var,
items = [],
command = tt.selectTab,
)
menu.pack(side='left',padx=5)
tt.frame.leoDragHandle = menu.component('label')
c.frame.iconBar.addWidget(tt.frame)
#@-node:bobjack.20080501055450.8:tt.createControl
#@-others
#@nonl
#@-node:bobjack.20080501055450.5:class ToolbarTkinterTreeTab
#@+node:bobjack.20080428114659.2:class ToolbarTkinterFrame
class ToolbarTkinterFrame(leoTkinterFrame, object):
#@ @+others
#@+node:bobjack.20080429153129.29:Icon area convenience methods
#@+node:bobjack.20080429153129.30:addIconButton
def addIconButton (self,*args,**keys):
"""Create and add an icon button to the named toolbar.
keys['barName'] gives the name of the iconBar to be uses if it is present
outherwise 'iconbar' is used.
If the iconBar does not exist it will be created.
All arguments and keywords except 'barName' will be passed to iconBar.add.
"""
if 'barName' in keys:
barName = keys['barName']
del keys['barName']
else:
barName = 'iconbar'
bar = self.createIconBar(barName)
if bar:
return bar.add(*args, **keys)
#@-node:bobjack.20080429153129.30:addIconButton
#@+node:bobjack.20080503151427.2:getIconButton
def getIconButton (self,*args,**keys):
"""Create an icon button but do not add it to a toolbar.
If keys['barName'] is present it is removed from but import
otherwise ignored.
"""
if 'barName' in keys:
barName = keys['barName']
del keys['barName']
bar = self.createIconBar('iconbar')
if bar:
return bar.getButton(*args,**keys)
createIconButton = getIconButton
#@-node:bobjack.20080503151427.2:getIconButton
#@+node:bobjack.20080501055450.16:addIconWidget
def addIconWidget (self, widget, barName='iconbar', index=None):
"""Adds a button or other widget to the named toolbar."""
bar = self.createIconBar(barName)
if bar:
return bar.addWidget(widget, index=index)
#@-node:bobjack.20080501055450.16:addIconWidget
#@+node:bobjack.20080429153129.31:clearIconBar
def clearIconBar (self, barName='iconbar'):
"""This removes all widgets from thenamediconbarcallstheirdeletemethod.CreatedisplayanewiconBar. import
If the iconbar exists it will returned.
Otherwise a new iconBar will be created, shown and returned.
"""
toolbar = self.createToolbar()
frame = toolbar.toolbarFrame
if not barName in self.iconBars:
bar = self.iconBarClass(
self.c, frame, barName=barName, slaveMaster=slaveMaster
)
if not slaveMaster:
self.iconBars[barName] = bar
else:
bar = self.iconBars[barName]
if barName == 'iconbar':
self.iconBar = bar
return bar
#@-node:bobjack.20080429153129.32:createIconBar
#@+node:bobjack.20080429153129.33:getIconBar
getIconBar = createIconBar
#@nonl
#@-node:bobjack.20080429153129.33:getIconBar
#@+node:bobjack.20080429153129.34:getIconBarObject
getIconBarObject = getIconBar
#@nonl
#@-node:bobjack.20080429153129.34:getIconBarObject
#@+node:bobjack.20080429153129.35:hideIconBar
def hideIconBar (self, barName='iconbar'):
"""Remove an iconBar from thedisplay.ReturnasubclassofTk.Frame. import
The frame is parented on c.frame.top and set up for packing
into an iconBar. It may be used to hold several buttons or
other widgets which are then treat as a single item
"""
if 'barName' in keys:
del keys['barName']
bar = self.getIconBar('iconbar')
if bar:
return bar.getWidgetFrame(*args,**keys)
#@-node:bobjack.20080612150456.3:getIconWidgetFrame
#@-node:bobjack.20080429153129.29:Icon area convenience methods
#@+node:bobjack.20080502134903.8:Properties
#@+node:bobjack.20080502134903.9:iconFrame
def getIconFrame(self):
try:
return self.iconBar.iconFrame
except Exception:
pass
def setIconFrame(self, value):
pass
iconFrame = property(getIconFrame, setIconFrame)
#@-node:bobjack.20080502134903.9:iconFrame
#@+node:bobjack.20080616103714.6:toolbarFrame
def getToolbarFrame(self):
try:
return self.toolBar.toolbarFrame
except Exception:
pass
toolbarFrame = property(getToolbarFrame)
#@nonl
#@-node:bobjack.20080616103714.6:toolbarFrame
#@-node:bobjack.20080502134903.8:Properties
#@+node:bobjack.20080428114659.5:createToolbar
def createToolbar(self):
"""Create and pack the frame that contains all the toolbars.
If the frame already exists return it or create, pack and return
a new frame.
"""
c = self.c
# Rewrite to keepy pylint happy.
if hasattr(self,'toolbar'):
toolbar = getattr(self,'toolbar')
else:
toolbar = None
# try:
# toolbar = self.toolbar
# except AttributeError:
# toolbar = None
if toolbar:
return toolbar
self.toolbar = w = ToolbarTkToolbarClass(c, self.outerFrame, toolbarName='toolbar')
self.dummyToolbarFrame = Tk.Frame(w.toolbarFrame, height='1p')
w.toolbarFrame.pack(fill='x')
return self.toolbar
#@-node:bobjack.20080428114659.5:createToolbar
#@-others
#@-node:bobjack.20080428114659.2:class ToolbarTkinterFrame
#@+node:bobjack.20080506182829.14:class ToolbarIconWidgetFrame
class ToolbarIconWidgetFrame(Tk.Frame, object):
"""A subclass of Tk.Frame that is parented on c.frame.top.
"""
#@ @+others
#@+node:bobjack.20080506182829.15:__init__
def __init__(self, c, *args, **keys):
self.c = c
Tk.Frame.__init__(self, c.frame.top, *args, **keys)
self.deleteOnRightClick = False
#@-node:bobjack.20080506182829.15:__init__
#@+node:bobjack.20080612150456.4:detachWidget
def detachWidget(self):
"""Remove this widget from itscontainingiconBar.Deletethegivenbutton. import
This method does not actually delete the widget, override the method
in a derived class to do that.
"""
self.detachWidget()
#@-node:bobjack.20080612150456.5:deleteButton
#@-others
#@-node:bobjack.20080506182829.14:class ToolbarIconWidgetFrame
#@+node:bobjack.20080506182829.16:class ToolbarIconButton
class ToolbarIconButton(Tk.Button, object):
"""
text
command
shortcut
statusLine, balloon, balloonText, tooltip
bg, fg
menu,
imagefile, image, icon
command
font
item_data
"""
#@ @+others
#@+node:bobjack.20080506182829.24:__init__
def __init__(self, c, cnf={}, **keys ):
"""Create an iconBar button.
cnf must be a dictionary if it is supplied at all.
"""
if 0:
g.pr('ToolbarIconButton.__init__')
g.pr('\t', cnf)
g.pr('\t', keys)
self.c = c
self.deleteOnRightClick = False
self.balloonEnabled = False
self.balloon = None
self.keys = keys = self.mergeConfigSources(cnf, keys)
#@ << setup menu >>
#@+node:bobjack.20080507053105.4:<< setup menu >>
if 'menu' in keys:
self.context_menu = keys['menu']
del keys['menu']
#@nonl
#@-node:bobjack.20080507053105.4:<< setup menu >>
#@nl
#@ << setup statusLine >>
#@+node:bobjack.20080507053105.5:<< setup statusLine >>
value = ''
for key in ('statusLine', 'balloonText', 'balloon', 'tooltip'):
if key in keys:
s = keys[key]
if s:
value = s
del keys[key]
self.statusLine = value
if self.balloonEnabled and self.statusLine:
self.createBalloon()
#@-node:bobjack.20080507053105.5:<< setup statusLine >>
#@nl
#@ << setup image and relief >>
#@+node:bobjack.20080506182829.31:<< setup image and relief >>
imagefile = keys.get('imagefile')
image = keys.get('image')
icon = keys.get('icon')
# for key in ('imagefile', 'image', 'icon'):
# try:
# del keys[key]
# except KeyError:
# pass
if icon:
imagefile = icon
if not image and imagefile:
image = baseClasses.getImage(imagefile)
if image:
keys['image'] = image
keys['bd'] = 0
if 'bg' not in keys:
# get background of toolbar FIXME:
pass
keys['relief'] = 'flat'
keys['image'] = image
else:
keys['relief'] = 'groove'
#@-node:bobjack.20080506182829.31:<< setup image and relief >>
#@nl
#@ << setup command >>
#@+node:bobjack.20080506182829.32:<< setup command >>
command = keys.get('command')
# Rewrite to keep pylint happy.
# if command and isinstance(command, basestring):
if command and g.isString(command):
def commandCallback(c=self.c, command=command):
c.executeMinibufferCommand(command)
elif command:
commandCallback = command
else:
def commandCallback():
g.pr("command for widget %s" % self)
# commandCallback = command
# if not command:
# def commandCallback():
# g.pr("command for widget %s" % self)
# elif isinstance(command, basestring):
# def commandCallback(c=self.c, command=command):
# c.executeMinibufferCommand(command)
keys['command'] = commandCallback
#@-node:bobjack.20080506182829.32:<< setup command >>
#@nl
#@ << setup font >>
#@+node:bobjack.20080506182829.33:<< setup font >>
if not hasattr(self, 'font'):
self.font = None
self.font = (
keys.get('font') or
self.font or
self.c.config.getFontFromParams(
"button_text_font_family", "button_text_font_size",
"button_text_font_slant", "button_text_font_weight",
))
keys['font'] = self.font
#@-node:bobjack.20080506182829.33:<< setup font >>
#@nl
if 'bg' in keys and not keys['bg']:
del keys['bg']
kws = self.getButtonConfig(keys)
Tk.Button.__init__(self, c.frame.top, **kws)
c.bind(self,'<Button-3>', self.onRightClick)
#@-node:bobjack.20080506182829.24:__init__
#@+node:bobjack.20080507175534.2:attachWidget
def attachWidget(self, bar='iconbar', index=None, createBar=True, showBar=True):
"""Attatach a widget to a bar.
index:
where to place the widget in the bar
bar:
The bar may be an iconbar object or the name of an iconBar.
createBar:
If bar is a sring and no bar with that name exists, then if this
is True a new bar will be created.
showBar:
If the bar has been created then it will be shown if showBar == True
"""
pass
#@+at
# # TODO: not ready yet
#
# try:
# oldbar = self.leoIconBar
# except:
# oldbar = None
#
# if oldbar:
# oldbar.removeWidget(self)
#
# if isinstance(bar, basestring):
# bar = bar
# bar.addWidget(self)
#
#@-at
#@@c
#@-node:bobjack.20080507175534.2:attachWidget
#@+node:bobjack.20080507175534.3:createBalloon (gui-dependent)
def createBalloon (self, delay=100):
'Create a balloon for a widget.'
if not self.balloon:
self.balloon = Pmw.Balloon(self, initwait=delay)
self.balloon.bind(self, self.statusLine)
#@-node:bobjack.20080507175534.3:createBalloon (gui-dependent)
#@+node:bobjack.20080507053105.7:detachWidget
def detachWidget(self):
try:
bar = self.leoIconBar
except:
bar = None
if bar:
self.leoIconBar.removeWidget(self)
removeWidget = detachWidget
#@-node:bobjack.20080507053105.7:detachWidget
#@+node:bobjack.20080508051801.5:getButtonConfig
def getButtonConfig(self, keys=None):
"""Select keys and values to pass on to Tk.Button."""
if keys is None:
keys = self.keys
haveKeys = set(keys.keys())
allowedKeys = set(allowedButtonConfigItems)
sendkeys = [ k for k in haveKeys & allowedKeys]
kws = {}
for k in sendkeys:
# if isinstance(k,unicode):
# k = k.encode()
if g.isUnicode(k):
k = g.toEncodedString(k)
kws[k] = keys[k]
return kws
#@-node:bobjack.20080508051801.5:getButtonConfig
#@+node:bobjack.20080507053105.9:mergeConfigSources
def mergeConfigSources(self, cnf, keys):
"""Merge and prioritize config sources.
config sources are dictionaries cnf, keys and keys['item_data']
Priority cnf < keys < item_data.
"""
if 0:
g.trace()
g.pr('\t', cnf)
g.pr('\t', keys)
if cnf:
for key, value in keys.iteritems():
cnf[key] = value
keys = keys = cnf
if 'item_data' in keys:
data = keys['item_data']
del keys['item_data']
else:
data = {}
self.item_data = data
if data:
for key, value in data.iteritems():
keys[key] = value
return keys
#@-node:bobjack.20080507053105.9:mergeConfigSources
#@+node:bobjack.20080507053105.6:onRightClick
def onRightClick(self, event):
# if the button has a context menu, handle it and return
if g.doHook('rclick-popup',
c=self.c, event=event,
button=self,
):
return
# otherwise, see if there a containing widget has a menu.
if hasattr(event.widget, 'leoDragMaster'):
dragMaster = event.widget.leoDragMaster
if hasattr(dragMaster, 'context_menu'):
if g.doHook('rclick-popup',
c=self.c, event=event,
button=dragMaster,
context_menu=dragMaster.context_menu
):
return
else:
dragMaster = self
try:
if dragMaster.deleteOnRightClick:
dragMaster.deleteButton()
except AttributeError:
pass
#@-node:bobjack.20080507053105.6:onRightClick
#@+node:bobjack.20080508051801.6:deleteButton
def deleteButton(self, event=None):
"""Delete the given button.
This method does not actually delete the button, override the method
in derived classes to do that.
"""
self.detachWidget()
#@-node:bobjack.20080508051801.6:deleteButton
#@+node:bobjack.20080508051801.7:setCommand
def setCommand(self, command):
# Rewrite to keep pylint happy.
# if command and isinstance(command, basestring):
if command and g.isString(command):
def commandCallback(event,command=command):
self.c.executeMinibufferCommand(command)
elif command:
commandCallback = command
else:
def commandCallback():
g.pr("command for widget %s" % self)
# commandCallback = command
# if not command:
# def commandCallback():
# g.pr("command for widget %s" % self)
# if isinstance(command, basestring):
# def commandCallback(event, command=command):
# return self.c.executeMinibufferCommand(command)
self.config(command=commandCallback)
#@-node:bobjack.20080508051801.7:setCommand
#@-others
#@-node:bobjack.20080506182829.16:class ToolbarIconButton
#@+node:bobjack.20080506182829.18:class ToolbarScriptButton
class ToolbarScriptButton(ToolbarIconButton):
#@ @+others
#@+node:bobjack.20080506182829.19:__init__
def __init__(self, c, cnf={}, **keys):
self.c = c
k = c.k
keys = self.mergeConfigSources(cnf, keys)
text = keys.get('text')
#@ << command name >>
#@+node:bobjack.20080507053105.11:<< command name >>
self.commandName = commandName = self.cleanButtonText(text).lower()
#@nonl
#@-node:bobjack.20080507053105.11:<< command name >>
#@nl
#@ << truncate text >>
#@+node:bobjack.20080507053105.10:<< truncate text >>
self.truncatedText = truncatedText = self.truncateButtonText(commandName)
keys['text'] = truncatedText
#@-node:bobjack.20080507053105.10:<< truncate text >>
#@nl
#@ << register commands >>
#@+node:bobjack.20080507053105.12:<< register commands >>
deleteCommandName= 'delete-%s-button' % commandName
k.registerCommand(deleteCommandName, shortcut=None,
func=self.deleteButton, pane='button', verbose=False
)
shortcut = keys.get('shortcut')
k.registerCommand( commandName,
shortcut=shortcut,
func=lambda event: self.invoke(),
pane='button',
verbose=shortcut,
)
#@nonl
#@-node:bobjack.20080507053105.12:<< register commands >>
#@nl
ToolbarIconButton.__init__(self, c, keys)
self.deleteOnRightClick = True
self.baloonEnabled = True
self.createBalloon()
#@-node:bobjack.20080506182829.19:__init__
#@+node:bobjack.20080507053105.13:Properties
#@+node:bobjack.20080507175534.4:baloonEnabled
#@-node:bobjack.20080507175534.4:baloonEnabled
#@+node:bobjack.20080507053105.15:maxButtonSize
def getMaxButtonSize(self):
return self.c.theScriptingController.maxButtonSize
maxButtonSize = property(getMaxButtonSize)
#@-node:bobjack.20080507053105.15:maxButtonSize
#@+node:bobjack.20080507053105.14:scriptingController
def getScriptingController(self):
return self.c.theScriptingController
scriptingController = property(getScriptingController)
#@-node:bobjack.20080507053105.14:scriptingController
#@-node:bobjack.20080507053105.13:Properties
#@+node:bobjack.20080506182829.36:cleanButtonText
def cleanButtonText (self,s):
'''Clean the text following @button or @command so that it is a valid name of a minibuffer command.'''
import string
# Strip @...@button.
while s.startswith('@'):
s = s[1:]
if g.match_word(s,0,'button'):
s = s[6:]
for tag in ('@key','@args'):
i = s.find(tag)
if i != -1:
s = s[:i].strip()
if 1: # Not great, but spaces, etc. interfere with tab completion.
chars = g.toUnicode(string.letters + string.digits)
aList = [g.choose(ch in chars,ch,'-') for ch in g.toUnicode(s)]
s = ''.join(aList)
s = s.replace('--','-')
while s.startswith('-'):
s = s[1:]
while s.endswith('-'):
s = s[:-1]
return s
#@-node:bobjack.20080506182829.36:cleanButtonText
#@+node:bobjack.20080506182829.37:truncateButtonText
def truncateButtonText (self,s, size=0):
if not size:
size = self.maxButtonSize
size = max(size, 1)
s = s[:size]
if s.endswith('-'):
s = s[:-1]
return s.strip()
#@-node:bobjack.20080506182829.37:truncateButtonText
#@+node:bobjack.20080426064755.77:deleteButton
def deleteButton(self, event=None):
"""Delete the given button.
This is called from callbacksitacallback. import
"""
super(self.__class__, self).deleteButton(event)
self.scriptingController.deleteButton(self)
#@nonl
#@-node:bobjack.20080426064755.77:deleteButton
#@-others
#@-node:bobjack.20080506182829.18:class ToolbarScriptButton
#@+node:bobjack.20080506182829.20:class ToolbarAddScriptButton
class ToolbarAddScriptButton(ToolbarScriptButton):
#@ @+others
#@+node:bobjack.20080506182829.21:__init__
def __init__(self, c, *args, **kw):
super(ToolbarAddScriptButton, self).__init__(c, *args, **kw)
#@-node:bobjack.20080506182829.21:__init__
#@-others
#@-node:bobjack.20080506182829.20:class ToolbarAddScriptButton
#@+node:bobjack.20080425135232.6:class ToolbarScriptingController
scripting = mod_scripting.scriptingController
class ToolbarScriptingController(mod_scripting.scriptingController, object):
#@ @+others
#@+node:bobjack.20080506182829.12:createAtButtonFromSettingHelper & callback (ToolbarScriptingController)
def createAtButtonFromSettingHelper (self,h,script,statusLine,shortcut,bg='LightSteelBlue2'):
'''Create a button from an @button node.
- Calls createIconButton to do all standard button creation tasks.
- Binds button presses to a callback that executes the script.
'''
c = self.c
k = c.k
buttonText = self.cleanButtonText(h)
args = self.getArgs(h)
g.trace('h',h,'args',args)
data = self.getItemData(script)
if data and 'tooltip' in data:
statusLine = data['tooltip']
# We must define the callback *after* defining b,
# so set both command and shortcut to None here.
b = self.createIconButton(
text=h,
command=None,
shortcut=None,
statusLine=statusLine,
bg=bg,
item_data=data,
)
if not b:
return None
# Now that b is defined we can define the callback.
# Yes, the callback *does* use b (to delete b if requested by the script).
def atSettingButtonCallback (
event=None,
self=self,
args=args,
b=b,
script=script,
buttonText=buttonText
):
self.executeScriptFromSettingButton (args,b,script,buttonText)
self.iconBar.setCommandForButton(b,atSettingButtonCallback)
# At last we can define the command and use the shortcut.
k.registerCommand(buttonText.lower(),
shortcut=shortcut,func=atSettingButtonCallback,
pane='button',verbose=False)
return b
#@+node:bobjack.20080506182829.13:executeScriptFromSettingButton (ToolbarScriptingController)
def executeScriptFromSettingButton (self,args,b,script,buttonText):
'''Called from callbacks to execute the script in node p.'''
c = self.c
if c.disableCommandsMessage:
g.es(c.disableCommandsMessage,color='blue')
else:
g.app.scriptDict = {}
c.executeScript(script=script,silent=True)
# Remove the button if the script asks to be removed.
if g.app.scriptDict.get('removeMe'):
g.es("Removing '%s' button at its request" % buttonText)
b.deleteButton()
if 0: # Do *not* set focus here: the script may have changed the focus.
c.frame.bodyWantsFocus()
#@nonl
#@-node:bobjack.20080506182829.13:executeScriptFromSettingButton (ToolbarScriptingController)
#@-node:bobjack.20080506182829.12:createAtButtonFromSettingHelper & callback (ToolbarScriptingController)
#@+node:bobjack.20080508051801.2:createAtButtonHelper & callback (ToolbarScriptingController)
def createAtButtonHelper (self,p,h,statusLine,shortcut,bg='LightSteelBlue1',verbose=True):
'''Create a button from an @button node.
- Calls createIconButton to do all standard button creation tasks.
- Binds button presses to a callback that executes the script in node p.
'''
c = self.c ; k = c.k
item_data = self.getItemData(p.b)
buttonText = self.cleanButtonText(h)
args = self.getArgs(h)
b = self.createIconButton(
text=h,
command=None,
shortcut=None,
statusLine=statusLine,
bg=bg,
item_data=item_data
)
if not b:
return None
def atButtonCallback (
event=None,
self=self,
args=args,
p=p.copy(),
b=b,
buttonText=buttonText
):
self.executeScriptFromButton (p,args,b,buttonText)
b.setCommand(atButtonCallback)
# At last we can define the command and use the shortcut.
k.registerCommand(buttonText.lower(),
shortcut=shortcut,func=atButtonCallback,
pane='button',verbose=verbose)
return b
#@+node:bobjack.20080508051801.3:executeScriptFromButton (ToolbarScriptingController)
def executeScriptFromButton (self,p,args,b,buttonText):
'''Called from callbacks to execute the script in node p.'''
c = self.c
if c.disableCommandsMessage:
g.es(c.disableCommandsMessage,color='blue')
else:
g.app.scriptDict = {}
c.executeScript(args=args,p=p,silent=True)
# Remove the button if the script asks to be removed.
if g.app.scriptDict.get('removeMe'):
g.es("Removing '%s' button at its request" % buttonText)
b.deleteButton()
if 0: # Do *not* set focus here: the script may have changed the focus.
c.frame.bodyWantsFocus()
#@nonl
#@-node:bobjack.20080508051801.3:executeScriptFromButton (ToolbarScriptingController)
#@-node:bobjack.20080508051801.2:createAtButtonHelper & callback (ToolbarScriptingController)
#@+node:bobjack.20080425135232.10:getItemData
def getItemData(self, script):
item_data = {}
script = [ line.strip() for line in script.strip().splitlines() ]
if not (script and script[0] == '@'):
return {}
while script:
line = script.pop(0)
if line == '@c':
break
if not (line.startswith('@btn ') and '=' in line):
continue
key, value = line.split('=', 1)
key, value = key[4:].strip(), value.strip()
item_data[key] = value
return item_data
#@-node:bobjack.20080425135232.10:getItemData
#@+node:bobjack.20080428114659.18:getIconBar
def getIconBar(self):
return self.c.frame.iconBar
def setIconBar(self,*args, **kw):
pass
iconBar = property(getIconBar, setIconBar)
#@-node:bobjack.20080428114659.18:getIconBar
#@+node:bobjack.20080430160907.2:createIconButton
def createIconButton (self,text,command,shortcut,statusLine,bg, **keys):
'''Create an icon button. All icon buttons get created using this utility.
- Creates the actual button and its balloon.
- Adds the button to buttonsDict.
- Registers command with the shortcut.
- Creates x amd delete-x-button commands, where x is the cleaned button name.
- Binds a right-click in the button to a callback that deletes the button.'''
c = self.c ; k = c.k
cnf = {}
for k, v in (
('text', text),
('command', command),
('shortcut', shortcut),
('statusLine', statusLine),
('bg', bg)
):
cnf[k] = v
b = ToolbarScriptButton(c, cnf, **keys)
self.buttonsDict[b] = b.truncatedText
self.iconBar.addWidget(b)
return b
#@-node:bobjack.20080430160907.2:createIconButton
#@+node:bobjack.20080428114659.12:createScriptButtonIconButton 'script-button' & callback
def createScriptButtonIconButton (self, barName='iconbar'):
'''Create the 'script-button' button and the script-button command.'''
c = self.c
frame = c.frame
b = self.createIconButton(
text='script-button',
command = None,
shortcut=None,
statusLine='Make script button from selected node',
bg="#ffffcc",
)
def addScriptButtonCallback(event=None, self=self, b=b):
val = self.addScriptButtonCommand(event, b)
# Careful: func may destroy c.
if c.exists: c.outerUpdate()
return val
b.configure(command=addScriptButtonCallback)
#@+node:bobjack.20080428114659.13:addScriptButtonCommand
def addScriptButtonCommand (self,event=None, b=None):
"""Convert the node into a script button and add it to an iconBar.
b is the add-script-button that was clicked and the new script button
will be added to the same iconBar.
"""
c = self.c
frame = c.frame
p = c.p
h = p.h
buttonText = self.getButtonText(h)
shortcut = self.getShortcut(h)
statusLine = "Run Script: %s" % buttonText
if shortcut:
statusLine = statusLine + "\@key=" + shortcut
oldIconBar = frame.iconBar
try:
frame.iconBar = b.leoIconBar
b = self.createAtButtonHelper(
p, h, statusLine, shortcut, bg='MistyRose1', verbose=True
)
finally:
frame.iconBar = oldIconBar
c.frame.bodyWantsFocus()
#@-node:bobjack.20080428114659.13:addScriptButtonCommand
#@-node:bobjack.20080428114659.12:createScriptButtonIconButton 'script-button' & callback
#@-others
#@-node:bobjack.20080425135232.6:class ToolbarScriptingController
#@+node:bobjack.20080426064755.66:class ToolbarTkIconBarClass
iconbar = leoTkinterFrame.tkIconBarClass
class ToolbarTkIconBarClass(iconbar, object):
'''A class representing an iconBar.'''
iconBasePath = g.os_path_join(g.app.leoDir, 'Icons')
barConfigCount = 0
#@ @+others
#@+node:bobjack.20080428114659.6:__init__
def __init__(self, c, parentFrame, barName='iconBar', slaveMaster=None):
"""Initialize an iconBar."""
self.c = c
self.barName = barName
self.parentFrame = parentFrame
self.inConfigure = False
self.slaveMaster = slaveMaster
self.slaveBar = None
self.buttonCount = 0
self.font = None
self.inConfigure = False
self.widgets_per_row = 20 # Used by tkGui.py
if not slaveMaster :
#@ << define master iconBar stuff >>
#@+node:bobjack.20080502134903.2:<< define master iconBar stuff >>
# These are only valid for the first iconBar in a group of slaves.
self._outerFrame = None # control var for outerFrame property
self._buttons = [] # control var for buttons list
self.maxSlaves = 15
self.nSlaves = 1
# The frame which will contain all slave iconBars
self._outerFrame = w = Tk.Frame(
self.parentFrame,
height="5m", bd=2, relief="groove"
)
w.leoIconBar = self
#@-node:bobjack.20080502134903.2:<< define master iconBar stuff >>
#@nl
# Create the frame to hold buttons assigned to this slave bar.
self.iconFrame = self.top = w = Tk.Frame(
self.parentFrame,
height="5m",relief="flat",
)
w.leoIconBar = self
c.bind(w,'<Button-3>', self.onRightClick)
if not slaveMaster:
c.bind(w,'<Configure>', self.onConfigure)
self.show()
w.update_idletasks()
#@-node:bobjack.20080428114659.6:__init__
#@+node:bobjack.20080508125414.5:Event Handlers
#@+node:bobjack.20080428114659.9:onRightClick
def onRightClick(self, event):
"""Respond to a right click on any of the components of the iconbar.
The first bar in a set of slave bars is sent with the hook,
the actual slave bar can be found in event.widget.
"""
#g.trace()
w = event.widget
w = self.getDragMaster(w)
try:
flag = w.leoIconBar
except AttributeError:
flag = False
if flag:
self.c.theToolbarController.grabWidget = w
g.doHook('rclick-popup', c=self.c, event=event,
context_menu='iconbar-menu', bar=self.barHead
)
#@-node:bobjack.20080428114659.9:onRightClick
#@+node:bobjack.20080503090121.5:onPress
def onPress(self, e):
w = e.widget
w = self.getDragMaster(w)
try:
flag = w.leoIconBar
except AttributeError:
flag = False
if flag:
self.c.theToolbarController.grabWidget = w
try:
w.balloon._leave(e)
except Exception:
pass
#@-node:bobjack.20080503090121.5:onPress
#@+node:bobjack.20080503090121.6:onRelease
def onRelease(self, e):
try:
c = self.c
controller = c.theToolbarController
target = e.widget.winfo_containing(e.x_root, e.y_root)
try:
target = self.getDragMaster(target)
tBar = target.leoIconBar
except:
tBar = None
if tBar:
source = controller.grabWidget
if source and source is not target:
sBar = source.leoIconBar
if sBar.c is tBar.c:
sBar.removeWidget(source)
try:
index = tBar.buttons.index(target)
except:
index = None
tBar.addWidget(source, index)
finally:
controller.grabWidget = None
#@-node:bobjack.20080503090121.6:onRelease
#@+node:bobjack.20080429153129.16:onConfigure
def onConfigure(self, event=None):
#g.trace(self.configCount(), self.barHead.barName)
self.repackButtons()
self.configCount(1)
#return True
#@-node:bobjack.20080429153129.16:onConfigure
#@+node:bobjack.20080620224131.2:configCount
def configCount(self, i=0):
ToolbarTkIconBarClass.barConfigCount += i
return ToolbarTkIconBarClass.barConfigCount
#@-node:bobjack.20080620224131.2:configCount
#@+node:bobjack.20080506182829.2:getDragMaster
def getDragMaster(self, w):
if hasattr(w, 'leoDragMaster'):
w = w.leoDragMaster
return w
#@-node:bobjack.20080506182829.2:getDragMaster
#@-node:bobjack.20080508125414.5:Event Handlers
#@+node:bobjack.20080430160907.4:Properties
#@+node:bobjack.20080430160907.5:outerFrame
def getOuterFrame(self):
"""Get the frame that contains this bar and its companion slaves."""
return self.barHead._outerFrame
def setOuterFrame(self, value):
self.barHead._outerFrame = value
outerFrame = property(getOuterFrame, setOuterFrame)
#@-node:bobjack.20080430160907.5:outerFrame
#@+node:bobjack.20080430064145.4:barHead
def getBarHead(self):
"""Get the first bar for the list of bars of which this bar is a member."""
bar = self
while bar.slaveMaster:
bar = bar.slaveMaster
return bar
barHead = property(getBarHead)
#@-node:bobjack.20080430064145.4:barHead
#@+node:bobjack.20080501113939.2:slaveBars
def getSlaveBars(self):
"""Get a list of slave iconBars packed in this toolbar."""
return [ bar.leoIconBar for bar in self.outerFrame.pack_slaves()]
slaveBars = property(getSlaveBars)
#@nonl
#@-node:bobjack.20080501113939.2:slaveBars
#@+node:bobjack.20080502134903.7:slaveBarFrames
def getSlaveBarFrames(self):
"""Get a list of slave iconBar frames packed in this toolbar."""
return [ bar for bar in self.outerFrame.pack_slaves()]
slaveBarFrames = property(getSlaveBarFrames)
#@nonl
#@-node:bobjack.20080502134903.7:slaveBarFrames
#@+node:bobjack.20080501055450.2:slaveButtons
def getSlaveButtons(self):
"""Get a list of widgets packed in this iconBar."""
return [ btn for btn in self.iconFrame.pack_slaves()]
slaveButtons = property(getSlaveButtons)
#@-node:bobjack.20080501055450.2:slaveButtons
#@+node:bobjack.20080501113939.3:allSlaveButtons
def getAllSlaveButtons(self, shrink=False):
"""Make a list of all widgets packed in this set of toolbars."""
buttons = []
bar = self.barHead
while bar:
buttons += [ btn for btn in bar.iconFrame.pack_slaves()]
bar = bar.slaveBar
return buttons
allSlaveButtons = property(getAllSlaveButtons)
#@-node:bobjack.20080501113939.3:allSlaveButtons
#@+node:bobjack.20080501125812.5:buttons
def getButtons(self):
"""Get the list of widgets that may appear in this toolbar."""
return self.barHead._buttons[:]
def setButtons(self, lst):
"""Set a new list of widgets to be displayed in this toolbar."""
self.repackButtons(lst)
return
buttons = property(getButtons, setButtons)
#@-node:bobjack.20080501125812.5:buttons
#@+node:bobjack.20080501181134.5:visible
def getVisible(self):
"""Is the toolbar, of which this iconBar is a slave, packed."""
barHead = self.barHead
return barHead._outerFrame in barHead.parentFrame.pack_slaves()
def setVisible(self, show):
if show:
self.show()
else:
self.hide()
visible = property(getVisible, setVisible)
#@-node:bobjack.20080501181134.5:visible
#@-node:bobjack.20080430160907.4:Properties
#@+node:bobjack.20080504034903.9:updateButtons
def updateButtons(self, buttons, repack=True):
"""Update the iconBars button list to match buttons.
Buttons no longer needed are removed, new buttons are added.
"""
old = set(self.barHead._buttons)
new = set(buttons)
unchanged = old & new
remove = old - new
add = new -old
for btn in remove:
self.removeWidget(btn, repack=False)
for btn in add:
self.addWidget(btn, repack=False)
self.barHead._buttons = buttons[:]
if repack:
self.repackButtons()
#@-node:bobjack.20080504034903.9:updateButtons
#@+node:bobjack.20080507083323.4:repackButtons
def repackButtons(self, buttons=None):
bar = self.barHead
if bar.inConfigure:
return
if buttons is not None:
self.updateButtons(buttons, repack=False)
try:
bar.doRepackButtons()
finally:
bar.inConfigure = False
#@+node:bobjack.20080430160907.12:doRepackButtons
def doRepackButtons(self, trace=None):
"""Repack all the buttons in this toolbar.
New slave iconBars will be created if needed to make sure all buttons are
visible. Empty slaves will be hidden but not removed.
"""
barHead = self.barHead
barHead.inConfigure = True
orphans = barHead._buttons[:]
#@ << unpack all buttons >>
#@+node:bobjack.20080501181134.2:<< unpack all buttons >>
bar = barHead
while bar and bar.buttonCount:
# Rewrite to keep pylint happy.
# [ btn.pack_forget() for btn in bar.iconFrame.pack_slaves()]
for z in bar.iconFrame.pack_slaves():
z.pack_forget()
bar.buttonCount = 0
bar = bar.slaveBar
#@-node:bobjack.20080501181134.2:<< unpack all buttons >>
#@nl
bar = barHead
bars = bar.slaveBars
#@ << repack all widgets >>
#@+node:bobjack.20080502134903.4:<< repack all widgets >>
while bar and orphans:
orphans = bar.repackHelper(orphans)
if bar not in bars and (bar.buttonCount or not bar.slaveMaster):
bar.packSlaveBar()
bar = bar.slaveBar
#@nonl
#@-node:bobjack.20080502134903.4:<< repack all widgets >>
#@nl
#@ << hide empty slave bars >>
#@+node:bobjack.20080502134903.5:<< hide empty slave bars >>
while bar :
if bar in bars:
bar.unpackSlaveBar()
bar = bar.slaveBar
#@-node:bobjack.20080502134903.5:<< hide empty slave bars >>
#@nl
#@+node:bobjack.20080429153129.24:repackHelper
def repackHelper(self, orphans):
"""Pack as many 'orphan' buttons into this bar as possible
Return a list of orphans that could not be packed.
"""
iconFrame = self.iconFrame
req = iconFrame.winfo_reqwidth
actual = iconFrame.winfo_width
while orphans:
#@ << pack widgets until full >>
#@+node:bobjack.20080502134903.6:<< pack widgets until full >>
widget = orphans[0]
try:
show = widget.leoShow
except Exception:
widget.leoShow = show = True
if show:
widget.pack(in_=iconFrame, side="left")
iconFrame.update_idletasks()
if req() > actual():
#widget.pack_forget()
break
self.buttonCount += 1
orphans.pop(0)
#@-node:bobjack.20080502134903.6:<< pack widgets until full >>
#@nl
if len(orphans) and not self.buttonCount:
# we must pack at least one widget even if its too big
widget = orphans.pop(0)
widget.pack(in_=iconFrame, side="left")
self.buttonCount = 1
if not self.slaveBar and orphans:
self.slaveBar = self.createSlaveBar()
return orphans
#@-node:bobjack.20080429153129.24:repackHelper
#@+node:bobjack.20080430064145.3:createSlaveBar
def createSlaveBar(self):
"""Create a slave iconBar for this bar and home as many orphans as possible.
It is an error to call this if the bar already has a slaveBar.
"""
assert not self.slaveBar, 'Already have a slaveBar.'
barHead = self.barHead
if not barHead.nSlaves < barHead.maxSlaves:
return
barHead.nSlaves +=1
barName = self.uniqueSlaveName()
self.slaveBar = slaveBar = self.c.frame.createIconBar(
barName, slaveMaster=self
)
return slaveBar
#@-node:bobjack.20080430064145.3:createSlaveBar
#@-node:bobjack.20080430160907.12:doRepackButtons
#@-node:bobjack.20080507083323.4:repackButtons
#@+node:bobjack.20080503151427.3:add
def add(self,*args,**keys):
"""Create and pack an iconBar button."""
return self.addWidget(self.getButton(*args, **keys))
#@-node:bobjack.20080503151427.3:add
#@+node:bobjack.20080430160907.11:addWidget
def addWidget(self, widget, index=None, repack=True):
"""Add a widget to the iconBar.
The widget must have c.frame.top as it parent.
If the widget is already attached to an iconBar it will
first be removed
"""
try:
c = self.c
#@ << remove from current bar >>
#@+node:bobjack.20080508125414.13:<< remove from current bar >>
try:
bar = widget.leoIconBar
except:
bar = None
if bar:
bar.removeWidget(widget, repack=False)
#@nonl
#@-node:bobjack.20080508125414.13:<< remove from current bar >>
#@nl
barHead = self.barHead
buttons = barHead._buttons
#@ << validate index >>
#@+node:bobjack.20080508125414.12:<< validate index >>
if index is not None:
try:
idx = int(index)
except:
idx = None
if idx is None:
if index in buttons:
idx = buttons.index(index)
index = idx
if index is None: g.es('Icon Bar index out of range')
#@-node:bobjack.20080508125414.12:<< validate index >>
#@nl
#@ << bind widget and drag handles >>
#@+node:bobjack.20080506090043.2:<< bind widget and drag handles >>
c.bind(widget,'<ButtonPress-1>', barHead.onPress)
c.bind(widget,'<ButtonRelease-1>', barHead.onRelease)
try:
drag = widget.leoDragHandle
except AttributeError:
drag = None
if drag:
if not isinstance(drag, (tuple, list)):
drag = (drag,)
for dw in drag:
dw.leoDragMaster = widget
c.bind(dw,'<ButtonPress-1>', barHead.onPress )
c.bind(dw,'<ButtonRelease-1>', barHead.onRelease)
widget.c = self.c
widget.leoIconBar = barHead
#@-node:bobjack.20080506090043.2:<< bind widget and drag handles >>
#@nl
if index is not None:
try:
buttons.insert(index, widget)
except IndexError:
index = None
if index is None:
buttons.append(widget)
if repack:
self.repackButtons()
finally:
return widget
#@-node:bobjack.20080430160907.11:addWidget
#@+node:bobjack.20080501181134.3:removeWidget
def removeWidget(self, widget, repack=True):
"""Remove widget from thelistofmangedwidgetsrepackthebuttons.DeleteallthewidgetsthetheiconbarCreateaniconBarbutton.ShowtheiconbarbyrepackingitHidetheiconbarbyunpackingitReturnauniquenameaslaveBarofthisiconBar.AthatwrapsatoolbarframewhichholdsacollectionoficonBars.Baseallcommandsdefinedthetoolbar.pyplugin.Apercommandercontrollerprovidingatoolbarmanager.Createamenutoshowhiddentoolbars.Createamenutohidevisibletoolbars.Createamenutotogglevisibilityoftoolbars.MinibuffercommandtotogglethevisibilityofaniconBar.Commandtodeleteatoolbarbutton. import
For use only in rClick menus attached to toolbar buttons.
"""
#@ @+others
#@-others
def doCommand(self, keywords):
#g.trace(self.__class__.__name__)
if self.minibufferPhaseError():
return
try:
keywords['button'].deleteButton()
except Exception as e:
g.es_error('failed to delete button')
g.es_exception()
#@-node:bobjack.20080426190702.3:toolbar-delete-button
#@+node:bobjack.20080428114659.11:toolbar-add-iconbar
class addIconbarCommandClass(toolbarCommandClass):
"""Command to add a new iconBar."""
#@ @+others
#@+node:bobjack.20080429153129.21:uniqueBarName
def uniqueBarName(self, prefix):
iconBars = self.c.frame.iconBars
if not prefix in iconBars:
return prefix
for i in range(1,100):
barName = '%s.%s' %(prefix, i)
if barName not in iconBars:
return barName
#@-node:bobjack.20080429153129.21:uniqueBarName
#@-others
def doCommand(self, keywords):
c = self.c
frame = c.frame
try:
bar = keywords['bar']
barName = bar.barName
except KeyError:
barName = 'iconbar'
newbarName = self.uniqueBarName(barName)
frame.createIconBar(newbarName)
#@-node:bobjack.20080428114659.11:toolbar-add-iconbar
#@+node:bobjack.20080428114659.16:toolbar-hide-iconbar
class hideIconbarCommandClass(toolbarCommandClass):
"""Minibuffer command to hide an iconBar."""
#@ @+others
#@-others
def doCommand(self, keywords):
c = self.c
frame = c.frame
try:
bar = keywords['bar']
except KeyError:
bar = frame.iconBars['iconbar']
bar.hide()
#@-node:bobjack.20080428114659.16:toolbar-hide-iconbar
#@+node:bobjack.20080428114659.17:toolbar-add-script-button
class addScriptButtonCommandClass(toolbarCommandClass):
"""Add a script-button to the selected iconBar.
This command is for use in in iconBar rClick menus, the script-button will
be added to the bar that recieved the click.
It may also be used as a minibufer command, in which case a script-button
will be added to the default 'iconbar'.
"""
#@ @+others
#@-others
def doCommand(self, keywords):
c = self.c
frame = c.frame
iconBars = frame.iconBars
try:
bar = keywords['bar']
barName = bar.barName
except KeyError:
bar = iconBars['iconbar']
barName = 'iconbar'
oldIconBar = frame.iconBar
try:
frame.iconBar = bar
sm = c.theScriptingController
sm.createScriptButtonIconButton(barName)
finally:
frame.iconBar = oldIconBar
#@-node:bobjack.20080428114659.17:toolbar-add-script-button
#@-node:bobjack.20080426190702.2:Invocation Commands
#@+node:bobjack.20080429153129.28:Utility
#@-node:bobjack.20080429153129.28:Utility
#@-others
#@-node:bobjack.20080424195922.12:class pluginController
#@-others
#@-node:bobjack.20080424190315.2:@thin toolbar.py
#@-leo
|