Made the local file name safe for windows
[pyTivo.git] / Cheetah / Tools / SiteHierarchy.py
blobd4a92e1e7a450e4128074b8f0449e000ad719e7c
1 #!/usr/bin/env python
2 # $Id: SiteHierarchy.py,v 1.1 2001/10/11 03:25:54 tavis_rudd Exp $
3 """Create menus and crumbs from a site hierarchy.
5 You define the site hierarchy as lists/tuples. Each location in the hierarchy
6 is a (url, description) tuple. Each list has the base URL/text in the 0
7 position, and all the children coming after it. Any child can be a list,
8 representing further depth to the hierarchy. See the end of the file for an
9 example hierarchy.
11 Use Hierarchy(contents, currentURL), where contents is this hierarchy, and
12 currentURL is the position you are currently in. The menubar and crumbs methods
13 give you the HTML output.
15 There are methods you can override to customize the HTML output.
17 Meta-Data
18 ================================================================================
19 Author: Ian Bicking <ianb@colorstudy.com>
20 Version: $Revision: 1.1 $
21 Start Date: 2001/07/23
22 Last Revision Date: $Date: 2001/10/11 03:25:54 $
23 """
24 __author__ = "Ian Bicking <ianb@colorstudy.com>"
25 __version__ = "$Revision: 1.1 $"[11:-2]
27 ##################################################
28 ## DEPENDENCIES
29 import string
30 try:
31 from cStringIO import StringIO
32 except ImportError:
33 from StringIO import StringIO
36 ##################################################
37 ## GLOBALS & CONSTANTS
39 True, False = (1==1), (0==1)
41 ##################################################
42 ## CLASSES
44 class Hierarchy:
45 def __init__(self, hierarchy, currentURL, prefix='', menuCSSClass=None,
46 crumbCSSClass=None):
47 """
48 hierarchy is described above, currentURL should be somewhere in
49 the hierarchy. prefix will be added before all of the URLs (to
50 help mitigate the problems with absolute URLs), and if given,
51 cssClass will be used for both links *and* nonlinks.
52 """
54 self._contents = hierarchy
55 self._currentURL = currentURL
56 if menuCSSClass:
57 self._menuCSSClass = ' class="%s"' % menuCSSClass
58 else:
59 self._menuCSSClass = ''
60 if crumbCSSClass:
61 self._crumbCSSClass = ' class="%s"' % crumbCSSClass
62 else:
63 self._crumbCSSClass = ''
64 self._prefix=prefix
67 ## Main output methods
69 def menuList(self, menuCSSClass=None):
70 """An indented menu list"""
71 if menuCSSClass:
72 self._menuCSSClass = ' class="%s"' % menuCSSClass
74 stream = StringIO()
75 for item in self._contents[1:]:
76 self._menubarRecurse(item, 0, stream)
77 return stream.getvalue()
79 def crumbs(self, crumbCSSClass=None):
80 """The home>where>you>are crumbs"""
81 if crumbCSSClass:
82 self._crumbCSSClass = ' class="%s"' % crumbCSSClass
84 path = []
85 pos = self._contents
86 while 1:
87 ## This is not the fastest algorithm, I'm afraid.
88 ## But it probably won't be for a huge hierarchy anyway.
89 foundAny = False
90 path.append(pos[0])
91 for item in pos[1:]:
92 if self._inContents(item):
93 if type(item) is type(()):
94 path.append(item)
95 break
96 else:
97 pos = item
98 foundAny = True
99 break
100 if not foundAny:
101 break
102 if len(path) == 1:
103 return self.emptyCrumb()
104 return string.join(map(lambda x, self=self: self.crumbLink(x[0], x[1]),
105 path), self.crumbSeperator()) + \
106 self.crumbTerminator()
108 ## Methods to control the Aesthetics
109 # - override these methods for your own look
111 def menuLink(self, url, text, indent):
112 if url == self._currentURL or self._prefix + url == self._currentURL:
113 return '%s<B%s>%s</B> <BR>\n' % ('&nbsp;'*2*indent,
114 self._menuCSSClass, text)
115 else:
116 return '%s<A HREF="%s%s"%s>%s</A> <BR>\n' % \
117 ('&nbsp;'*2*indent, self._prefix, url,
118 self._menuCSSClass, text)
120 def crumbLink(self, url, text):
121 if url == self._currentURL or self._prefix + url == self._currentURL:
122 return '<B%s>%s</B>' % (text, self._crumbCSSClass)
123 else:
124 return '<A HREF="%s%s"%s>%s</A>' % \
125 (self._prefix, url, self._crumbCSSClass, text)
127 def crumbSeperator(self):
128 return '&nbsp;&gt;&nbsp;'
130 def crumbTerminator(self):
131 return ''
133 def emptyCrumb(self):
134 """When you are at the homepage"""
135 return ''
137 ## internal methods
139 def _menubarRecurse(self, contents, indent, stream):
140 if type(contents) is type(()):
141 url, text = contents
142 rest = []
143 else:
144 url, text = contents[0]
145 rest = contents[1:]
146 stream.write(self.menuLink(url, text, indent))
147 if self._inContents(contents):
148 for item in rest:
149 self._menubarRecurse(item, indent+1, stream)
151 def _inContents(self, contents):
152 if type(contents) is type(()):
153 return self._currentURL == contents[0]
154 for item in contents:
155 if self._inContents(item):
156 return True
157 return False
159 ##################################################
160 ## from the command line
162 if __name__ == '__main__':
163 hierarchy = [('/', 'home'),
164 ('/about', 'About Us'),
165 [('/services', 'Services'),
166 [('/services/products', 'Products'),
167 ('/services/products/widget', 'The Widget'),
168 ('/services/products/wedge', 'The Wedge'),
169 ('/services/products/thimble', 'The Thimble'),
171 ('/services/prices', 'Prices'),
173 ('/contact', 'Contact Us'),
176 for url in ['/', '/services', '/services/products/widget', '/contact']:
177 print '<p>', '='*50
178 print '<br> %s: <br>\n' % url
179 n = Hierarchy(hierarchy, url, menuCSSClass='menu', crumbCSSClass='crumb',
180 prefix='/here')
181 print n.menuList()
182 print '<p>', '-'*50
183 print n.crumbs()