#!/usr/bin/env python
#
# $Id: AnimatedFolder.py,v 1.4 2001/11/21 11:37:19 doughellmann Exp $
#
# Copyright 2001 Doug Hellmann.
#
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Doug
# Hellmann not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
"""A folder icon which can be used by the TreeNavigator.
"""
__rcs_info__ = {
#
# Creation Information
#
'module_name' : '$RCSfile: AnimatedFolder.py,v $',
'rcs_id' : '$Id: AnimatedFolder.py,v 1.4 2001/11/21 11:37:19 doughellmann Exp $',
'creator' : 'Doug Hellmann <doug@hellfly.net>',
'project' : 'PmwContribD',
'created' : 'Sun, 01-Apr-2001 13:50:37 EDT',
#
# Current Information
#
'author' : '$Author: doughellmann $',
'version' : '$Revision: 1.4 $',
'date' : '$Date: 2001/11/21 11:37:19 $',
}
#
# Import system modules
#
import Tkinter
import Pmw
import sys, os, string
import Canvas
import math
#
# Import Local modules
#
import colormath
import AnimatedIcon
#
# Module
#
class FileFolder(AnimatedIcon.AnimatedIcon):
"A folder icon which can be used by the TreeNavigator."
def createImage(self):
"Create the image for the icon."
# Set polygon input defaults
self.default_tab_width = self.width / 2
#self.default_tab_height = 2
self.default_tab_height = self.height / 20
#self.lean_angle = math.pi / 6
self.lean_angle = math.pi / 16
self.tangent = math.tan(self.lean_angle)
self.cosine = math.cos(self.lean_angle)
self.mainOutline = None
self.state = 'closed'
self.shadowOutline = Canvas.Polygon(
self.canvas,
self.shadowClosedCoords(),
outline='black',
fill='black',
)
self.shadowOutline.addtag(self.uniqueName)
self.canvas_objects.append(self.shadowOutline)
self.mainOutline = Canvas.Polygon(
self.canvas,
self.outlineClosedCoords(),
outline=self.outline,
fill=self.foreground,
)
self.mainOutline.addtag(self.uniqueName)
self.canvas_objects.append(self.mainOutline)
self.frontFlap = Canvas.Polygon(
self.canvas,
self.frontFlapClosedCoords(),
fill=self.foreground,
outline='black',
)
self.frontFlap.addtag(self.uniqueName)
self.canvas_objects.append(self.frontFlap)
# Store the previous coordinates where
self.previous_coords = (self.ulx, self.uly)
return
def getUL(self):
"Returns the upper left corner coordinates."
if self.mainOutline:
bbox = self.mainOutline.bbox()
ulx=bbox[0][0] + 2
uly=bbox[0][1] + 2
else:
ulx=self.ulx
uly=self.uly
return (ulx, uly)
def outlineClosedCoords(self):
"Returns coordinates of the outline when in closed state."
ulx, uly = self.getUL()
width = self.width
height = self.height - 1
tab_height = self.default_tab_height
tab_width = self.default_tab_width
top_left = (ulx,uly+tab_height)
tab_top_left = (ulx+tab_height, uly)
tab_top_right = (ulx+tab_width-tab_height,uly)
tab_bottom_right = (ulx+tab_width,uly+tab_height)
folder_top_right = (ulx+width,uly+tab_height)
folder_bottom_right = (ulx+width,uly+height)
folder_bottom_left = (ulx,uly+height)
return (
top_left,
tab_top_left,
tab_top_right,
tab_bottom_right,
folder_top_right,
folder_bottom_right,
folder_bottom_left,
)
def shadowClosedCoords(self):
"Returns shadow coordinates when in closed state."
ulx, uly = self.getUL()
ulx = ulx + 1
uly = uly + 1
width = self.width
height = self.height
tab_height = self.default_tab_height
tab_width = self.default_tab_width
top_left = (ulx,uly+tab_height)
tab_top_left = (ulx+tab_height, uly)
tab_top_right = (ulx+tab_width-tab_height,uly)
tab_bottom_right = (ulx+tab_width,uly+tab_height)
folder_top_right = (ulx+width,uly+tab_height)
folder_bottom_right = (ulx+width,uly+height)
folder_bottom_left = (ulx,uly+height)
return (
top_left,
tab_top_left,
tab_top_right,
tab_bottom_right,
folder_top_right,
folder_bottom_right,
folder_bottom_left,
)
def frontFlapClosedCoords(self):
"Returns front flap coordinates when in closed state."
ulx, uly = self.getUL()
width = self.width
height = self.height - 1
tab_height = self.default_tab_height
tab_width = self.default_tab_width
panel_offset_x = 0
panel_offset_y = 2
top_left = (ulx+panel_offset_x,uly+(2*tab_height)+panel_offset_y)
middle_bottom = (ulx+tab_width-tab_height, uly+(2*tab_height)+panel_offset_y)
middle_top = (ulx+tab_width, uly+tab_height+panel_offset_y)
top_right = (ulx+width, uly+tab_height+panel_offset_y)
bottom_right = (ulx+width, uly+height)
bottom_left = (ulx+panel_offset_x, uly+height)
return (
top_left,
middle_bottom,
middle_top,
top_right,
bottom_right,
bottom_left,
)
def outlineOpenCoords(self):
"Returns outline coordinates when in open state."
ulx, uly = self.getUL()
#width = self.width
height = self.height - 1
tab_height = self.default_tab_height
tab_width = self.default_tab_width
tab_bottom_offset = self.tangent * tab_height
folder_front_lower_offset = (height/4)
folder_right_offset = self.tangent * folder_front_lower_offset
folder_bottom_left_offset = self.tangent * height
width = self.width - folder_bottom_left_offset
top_left = (ulx,uly+tab_height)
tab_top_left = (ulx+tab_height, uly)
tab_top_right = (ulx+tab_width-(2*tab_bottom_offset),uly)
tab_bottom_right = (ulx+tab_width+tab_bottom_offset,uly+tab_height)
folder_top_right = (ulx+width,uly+tab_height)
folder_bottom_right = (ulx+folder_bottom_left_offset+width, uly+height)
folder_bottom_left = (ulx+folder_bottom_left_offset, uly+height)
return (
top_left,
tab_top_left,
tab_top_right,
tab_bottom_right,
folder_top_right,
folder_bottom_right,
folder_bottom_left,
)
def shadowOpenCoords(self):
"Returns shadow coordinates when in open state."
ulx, uly = self.getUL()
#width = self.width
height = self.height
tab_height = self.default_tab_height
tab_width = self.default_tab_width
tab_bottom_offset = self.tangent * tab_height
folder_front_lower_offset = (height/4)
folder_right_offset = self.tangent * folder_front_lower_offset
folder_bottom_left_offset = self.tangent * height
width = self.width - folder_bottom_left_offset
top_left = (ulx,uly+tab_height)
tab_top_left = (ulx+tab_height, uly)
tab_top_right = (ulx+tab_width-(2*tab_bottom_offset),uly)
tab_bottom_right = (ulx+tab_width+tab_bottom_offset,uly+tab_height)
folder_top_right = (ulx+width,uly+tab_height)
folder_bottom_right = (ulx+folder_bottom_left_offset+width, uly+height)
folder_bottom_left = (ulx+folder_bottom_left_offset, uly+height)
return (
top_left,
tab_top_left,
tab_top_right,
tab_bottom_right,
folder_top_right,
folder_bottom_right,
folder_bottom_left,
)
def frontFlapOpenCoords(self):
"Returns front flap coordinates when in open state."
ulx, uly = self.getUL()
height = self.height - 1
tab_height = self.default_tab_height
tab_width = self.default_tab_width
tab_bottom_offset = self.tangent * tab_height
folder_front_lower_offset = (height/6)
folder_right_offset = self.tangent * folder_front_lower_offset
folder_bottom_left_offset = self.tangent * height
flap_left_offset = self.tangent * (height - (2*tab_height))
width = self.width - folder_bottom_left_offset
folder_top_left = (ulx+folder_bottom_left_offset+flap_left_offset,
uly+(2*tab_height)+folder_front_lower_offset)
middle_bottom = (ulx+folder_bottom_left_offset+tab_width-tab_height,
uly+(2*tab_height)+folder_front_lower_offset)
middle_top = (ulx+folder_bottom_left_offset+tab_width,
uly+tab_height+folder_front_lower_offset)
folder_top_right = (ulx+folder_bottom_left_offset+flap_left_offset+width,
uly+tab_height+folder_front_lower_offset)
folder_bottom_right = (ulx+width+folder_bottom_left_offset, uly+height)
folder_bottom_left = (ulx+folder_bottom_left_offset, uly+height)
return (
folder_top_left,
middle_bottom,
middle_top,
folder_top_right,
folder_bottom_right,
folder_bottom_left,
)
def drawClosed(self):
"Draw in closed state."
self.shadowOutline.coords( self.shadowClosedCoords() )
self.mainOutline.coords( self.outlineClosedCoords() )
self.frontFlap.coords( self.frontFlapClosedCoords() )
self.frontFlap['fill']=self.foreground
return
def drawOpen(self):
"Draw in open state."
colors = colormath.computeColorTriplet(self.canvas, self.foreground)
self.shadowOutline.coords( self.shadowOpenCoords() )
self.mainOutline.coords( self.outlineOpenCoords() )
self.frontFlap.coords( self.frontFlapOpenCoords() )
self.frontFlap['fill']=colors[2]
return
def redraw(self):
"Redraw in current state."
if self.state == 'closed':
self.drawClosed()
elif self.state == 'open':
self.drawOpen()
else:
self.drawClosed()
return
def set_geometry(self, width=None, height=None):
"""Set the width and height of the icon.
The aspect ratio defined for the icon is respected.
Arguments
'width' -- New width value.
'height' -- New height value
"""
# Set polygon input defaults
if width != None:
self.default_tab_width = width / 2
if height != None:
self.default_tab_height = 2
AnimatedIcon.AnimatedIcon.set_geometry(self,
width=width,
height=height)
return
def get_state(self):
"Returns the current state."
return self.state
def set_state(self, new_state):
"Sets the current state and redraws."
self.state = new_state
self.redraw()
return
def clickCB(self, event):
"Called when user clicks on icon."
self.previous_coords = (event.x_root, event.y_root)
AnimatedIcon.AnimatedIcon.clickCB(self, event)
return
class AnimatedFolder(FileFolder):
"A FileFolder which changes states when clicked."
def clickCB(self, event):
"Called when user clicks on icon."
if self.state == 'closed':
self.set_state('open')
else:
self.set_state('closed')
FileFolder.clickCB(self, event)
return
class DoubleClickFolder(AnimatedFolder):
"A FileFolder which calls callback when double clicked."
def __init__(self, canvas,
name=None,
ulx=0, uly=0,
foreground='AntiqueWhite',
lightshadow='tan3',
darkshadow='tan1',
outline='black',
allowMotion=0,
width=25,
height=20,
):
AnimatedFolder.__init__(self, canvas,
name=name,
ulx=ulx, uly=uly,
foreground=foreground,
lightshadow=lightshadow,
darkshadow=darkshadow,
outline=outline,
allowMotion=allowMotion,
width=width,
height=height,
defaultSequence='<Double-1>',
command=self.callback)
def callback(self, event):
pass
if __name__ == '__main__':
import GuiAppD
class DrawTest(GuiAppD.GuiAppD):
appname = 'Test animating folder'
def createInterface(self):
self.scrolledCanvas = self.createcomponent('canvas', (), None,
Pmw.ScrolledCanvas,
(self.interior(),),
canvas_background='white'
)
self.scrolledCanvas.pack(
side=Tkinter.TOP,
expand=Tkinter.YES,
fill=Tkinter.BOTH
)
self.canvas = self.scrolledCanvas.component('canvas')
self.button_down = None
self.contents = []
ulx = 150
uly = 100
item1 = AnimatedFolder(self.canvas, name='item1', ulx=ulx, uly=uly,
command=self.clicked,
width=110,
height=85)
item1.set_state('open')
item1.bind('<Enter>', self.enterCB)
item2 = AnimatedFolder(self.canvas, ulx=ulx*2, uly=uly+2,
command=self.clicked,
allowMotion=1,
)
return
def clicked(self, icon, event):
print 'clicked on %s!' % icon
pass
def enterCB(self, event):
print 'entered item1'
pass
DrawTest().run()
|