~openerp-groupes/openobject-server/6.0-fix-setup-windows

« back to all changes in this revision

Viewing changes to bin/reportlab/graphics/widgets/eventcal.py

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#see license.txt for license details
 
2
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/widgets/eventcal.py
 
3
# Event Calendar widget
 
4
# author: Andy Robinson
 
5
"""This file is a
 
6
"""
 
7
__version__=''' $Id$ '''
 
8
 
 
9
from reportlab.lib import colors
 
10
from reportlab.lib.validators import *
 
11
from reportlab.lib.attrmap import *
 
12
from reportlab.graphics.shapes import Line, Rect, Polygon, Drawing, Group, String, Circle, Wedge
 
13
from reportlab.graphics.charts.textlabels import Label
 
14
from reportlab.graphics.widgetbase import Widget
 
15
from reportlab.graphics import renderPDF
 
16
 
 
17
 
 
18
 
 
19
 
 
20
class EventCalendar(Widget):
 
21
    def __init__(self):
 
22
        self.x = 0
 
23
        self.y = 0
 
24
        self.width = 300
 
25
        self.height = 150
 
26
        self.timeColWidth = None  # if declared, use it; otherwise auto-size.
 
27
        self.trackRowHeight = 20
 
28
        self.data = []  # list of Event objects
 
29
        self.trackNames = None
 
30
 
 
31
        self.startTime = None  #displays ALL data on day if not set
 
32
        self.endTime = None    # displays ALL data on day if not set
 
33
        self.day = 0
 
34
 
 
35
 
 
36
        # we will keep any internal geometry variables
 
37
        # here.  These are computed by computeSize(),
 
38
        # which is the first thing done when drawing.
 
39
        self._talksVisible = []  # subset of data which will get plotted, cache
 
40
        self._startTime = None
 
41
        self._endTime = None
 
42
        self._trackCount = 0
 
43
        self._colWidths = []
 
44
        self._colLeftEdges = []  # left edge of each column
 
45
 
 
46
    def computeSize(self):
 
47
        "Called at start of draw.  Sets various column widths"
 
48
        self._talksVisible = self.getRelevantTalks(self.data)
 
49
        self._trackCount = len(self.getAllTracks())
 
50
        self.computeStartAndEndTimes()
 
51
        self._colLeftEdges = [self.x]
 
52
        if self.timeColWidth is None:
 
53
            w = self.width / (1 + self._trackCount)
 
54
            self._colWidths = [w] * (1+ self._trackCount)
 
55
            for i in range(self._trackCount):
 
56
                self._colLeftEdges.append(self._colLeftEdges[-1] + w)
 
57
        else:
 
58
            self._colWidths = [self.timeColWidth]
 
59
            w = (self.width - self.timeColWidth) / self._trackCount
 
60
            for i in range(self._trackCount):
 
61
                self._colWidths.append(w)
 
62
                self._colLeftEdges.append(self._colLeftEdges[-1] + w)
 
63
 
 
64
 
 
65
 
 
66
    def computeStartAndEndTimes(self):
 
67
        "Work out first and last times to display"
 
68
        if self.startTime:
 
69
            self._startTime = self.startTime
 
70
        else:
 
71
            for (title, speaker, trackId, day, start, duration) in self._talksVisible:
 
72
 
 
73
                if self._startTime is None: #first one
 
74
                    self._startTime = start
 
75
                else:
 
76
                    if start < self._startTime:
 
77
                        self._startTime = start
 
78
 
 
79
        if self.endTime:
 
80
            self._endTime = self.endTime
 
81
        else:
 
82
            for (title, speaker, trackId, day, start, duration) in self._talksVisible:
 
83
                if self._endTime is None: #first one
 
84
                    self._endTime = start + duration
 
85
                else:
 
86
                    if start + duration > self._endTime:
 
87
                        self._endTime = start + duration
 
88
 
 
89
 
 
90
 
 
91
 
 
92
    def getAllTracks(self):
 
93
        tracks = []
 
94
        for (title, speaker, trackId, day, hours, duration) in self.data:
 
95
            if trackId is not None:
 
96
                if trackId not in tracks:
 
97
                    tracks.append(trackId)
 
98
        tracks.sort()
 
99
        return tracks
 
100
 
 
101
    def getRelevantTalks(self, talkList):
 
102
        "Scans for tracks actually used"
 
103
        used = []
 
104
        for talk in talkList:
 
105
            (title, speaker, trackId, day, hours, duration) = talk
 
106
            assert trackId <> 0, "trackId must be None or 1,2,3... zero not allowed!"
 
107
            if day == self.day:
 
108
                if (((self.startTime is None) or ((hours + duration) >= self.startTime))
 
109
                and ((self.endTime is None) or (hours <= self.endTime))):
 
110
                    used.append(talk)
 
111
        return used
 
112
 
 
113
    def scaleTime(self, theTime):
 
114
        "Return y-value corresponding to times given"
 
115
        axisHeight = self.height - self.trackRowHeight
 
116
        # compute fraction between 0 and 1, 0 is at start of period
 
117
        proportionUp = ((theTime - self._startTime) / (self._endTime - self._startTime))
 
118
        y = self.y + axisHeight - (axisHeight * proportionUp)
 
119
        return y
 
120
 
 
121
 
 
122
    def getTalkRect(self, startTime, duration, trackId, text):
 
123
        "Return shapes for a specific talk"
 
124
        g = Group()
 
125
        y_bottom = self.scaleTime(startTime + duration)
 
126
        y_top = self.scaleTime(startTime)
 
127
        y_height = y_top - y_bottom
 
128
 
 
129
        if trackId is None:
 
130
            #spans all columns
 
131
            x = self._colLeftEdges[1]
 
132
            width = self.width - self._colWidths[0]
 
133
        else:
 
134
            #trackId is 1-based and these arrays have the margin info in column
 
135
            #zero, so no need to add 1
 
136
            x = self._colLeftEdges[trackId]
 
137
            width = self._colWidths[trackId]
 
138
 
 
139
        lab = Label()
 
140
        lab.setText(text)
 
141
        lab.setOrigin(x + 0.5*width, y_bottom+0.5*y_height)
 
142
        lab.boxAnchor = 'c'
 
143
        lab.width = width
 
144
        lab.height = y_height
 
145
        lab.fontSize = 6
 
146
 
 
147
        r = Rect(x, y_bottom, width, y_height, fillColor=colors.cyan)
 
148
        g.add(r)
 
149
        g.add(lab)
 
150
 
 
151
        #now for a label
 
152
        # would expect to color-code and add text
 
153
        return g
 
154
 
 
155
    def draw(self):
 
156
        self.computeSize()
 
157
        g = Group()
 
158
 
 
159
        # time column
 
160
        g.add(Rect(self.x, self.y, self._colWidths[0], self.height - self.trackRowHeight, fillColor=colors.cornsilk))
 
161
 
 
162
        # track headers
 
163
        x = self.x + self._colWidths[0]
 
164
        y = self.y + self.height - self.trackRowHeight
 
165
        for trk in range(self._trackCount):
 
166
            wid = self._colWidths[trk+1]
 
167
            r = Rect(x, y, wid, self.trackRowHeight, fillColor=colors.yellow)
 
168
            s = String(x + 0.5*wid, y, 'Track %d' % trk, align='middle')
 
169
            g.add(r)
 
170
            g.add(s)
 
171
            x = x + wid
 
172
 
 
173
        for talk in self._talksVisible:
 
174
            (title, speaker, trackId, day, start, duration) = talk
 
175
            r = self.getTalkRect(start, duration, trackId, title + '\n' + speaker)
 
176
            g.add(r)
 
177
 
 
178
 
 
179
        return g
 
180
 
 
181
 
 
182
 
 
183
 
 
184
def test():
 
185
    "Make a conference event for day 1 of UP Python 2003"
 
186
 
 
187
 
 
188
    d = Drawing(400,200)
 
189
 
 
190
    cal = EventCalendar()
 
191
    cal.x = 50
 
192
    cal.y = 25
 
193
    cal.data = [
 
194
        # these might be better as objects instead of tuples, since I
 
195
        # predict a large number of "optionsl" variables to affect
 
196
        # formatting in future.
 
197
 
 
198
        #title, speaker, track id, day, start time (hrs), duration (hrs)
 
199
        # track ID is 1-based not zero-based!
 
200
        ('Keynote: Why design another programming language?',  'Guido van Rossum', None, 1, 9.0, 1.0),
 
201
 
 
202
        ('Siena Web Service Architecture', 'Marc-Andre Lemburg', 1, 1, 10.5, 1.5),
 
203
        ('Extreme Programming in Python', 'Chris Withers', 2, 1, 10.5, 1.5),
 
204
        ('Pattern Experiences in C++', 'Mark Radford', 3, 1, 10.5, 1.5),
 
205
        ('What is the Type of std::toupper()', 'Gabriel Dos Reis', 4, 1, 10.5, 1.5),
 
206
        ('Linguistic Variables: Clear Thinking with Fuzzy Logic ', 'Walter Banks', 5, 1, 10.5, 1.5),
 
207
 
 
208
        ('lunch, short presentations, vendor presentations', '', None, 1, 12.0, 2.0),
 
209
 
 
210
        ("CORBA? Isn't that obsolete", 'Duncan Grisby', 1, 1, 14.0, 1.5),
 
211
        ("Python Design Patterns", 'Duncan Booth', 2, 1, 14.0, 1.5),
 
212
        ("Inside Security Checks and Safe Exceptions", 'Brandon Bray', 3, 1, 14.0, 1.5),
 
213
        ("Studying at a Distance", 'Panel Discussion, Panel to include Alan Lenton & Francis Glassborow', 4, 1, 14.0, 1.5),
 
214
        ("Coding Standards - Given the ANSI C Standard why do I still need a coding Standard", 'Randy Marques', 5, 1, 14.0, 1.5),
 
215
 
 
216
        ("RESTful Python", 'Hamish Lawson', 1, 1, 16.0, 1.5),
 
217
        ("Parsing made easier - a radical old idea", 'Andrew Koenig', 2, 1, 16.0, 1.5),
 
218
        ("C++ & Multimethods", 'Julian Smith', 3, 1, 16.0, 1.5),
 
219
        ("C++ Threading", 'Kevlin Henney', 4, 1, 16.0, 1.5),
 
220
        ("The Organisation Strikes Back", 'Alan Griffiths & Sarah Lees', 5, 1, 16.0, 1.5),
 
221
 
 
222
        ('Birds of a Feather meeting', '', None, 1, 17.5, 2.0),
 
223
 
 
224
        ('Keynote: In the Spirit of C',  'Greg Colvin', None, 2, 9.0, 1.0),
 
225
 
 
226
        ('The Infinite Filing Cabinet - object storage in Python', 'Jacob Hallen', 1, 2, 10.5, 1.5),
 
227
        ('Introduction to Python and Jython for C++ and Java Programmers', 'Alex Martelli', 2, 2, 10.5, 1.5),
 
228
        ('Template metaprogramming in Haskell', 'Simon Peyton Jones', 3, 2, 10.5, 1.5),
 
229
        ('Plenty People Programming: C++ Programming in a Group, Workshop with a difference', 'Nico Josuttis', 4, 2, 10.5, 1.5),
 
230
        ('Design and Implementation of the Boost Graph Library', 'Jeremy Siek', 5, 2, 10.5, 1.5),
 
231
 
 
232
        ('lunch, short presentations, vendor presentations', '', None, 2, 12.0, 2.0),
 
233
 
 
234
        ("Building GUI Applications with PythonCard and PyCrust", 'Andy Todd', 1, 2, 14.0, 1.5),
 
235
        ("Integrating Python, C and C++", 'Duncan Booth', 2, 2, 14.0, 1.5),
 
236
        ("Secrets and Pitfalls of Templates", 'Nicolai Josuttis & David Vandevoorde', 3, 2, 14.0, 1.5),
 
237
        ("Being a Mentor", 'Panel Discussion, Panel to include Alan Lenton & Francis Glassborow', 4, 2, 14.0, 1.5),
 
238
        ("The Embedded C Extensions to C", 'Willem Wakker', 5, 2, 14.0, 1.5),
 
239
 
 
240
        ("Lightning Talks", 'Paul Brian', 1, 2, 16.0, 1.5),
 
241
        ("Scripting Java Applications with Jython", 'Anthony Eden', 2, 2, 16.0, 1.5),
 
242
        ("Metaprogramming and the Boost Metaprogramming Library", 'David Abrahams', 3, 2, 16.0, 1.5),
 
243
        ("A Common Vendor ABI for C++ -- GCC's why, what and not", 'Nathan Sidwell & Gabriel Dos Reis', 4, 2, 16.0, 1.5),
 
244
        ("The Timing and Cost of Choices", 'Hubert Matthews', 5, 2, 16.0, 1.5),
 
245
 
 
246
        ('Birds of a Feather meeting', '', None, 2, 17.5, 2.0),
 
247
 
 
248
        ('Keynote: The Cost of C &amp; C++ Compatibility', 'Andy Koenig', None, 3, 9.0, 1.0),
 
249
 
 
250
        ('Prying Eyes: Generic Observer Implementations in C++', 'Andrei Alexandrescu', 1, 2, 10.5, 1.5),
 
251
        ('The Roadmap to Generative Programming With C++', 'Ulrich Eisenecker', 2, 2, 10.5, 1.5),
 
252
        ('Design Patterns in C++ and C# for the Common Language Runtime', 'Brandon Bray', 3, 2, 10.5, 1.5),
 
253
        ('Extreme Hour (XH): (workshop) - Jutta Eckstein and Nico Josuttis', 'Jutta Ecstein', 4, 2, 10.5, 1.5),
 
254
        ('The Lambda Library : Unnamed Functions for C++', 'Jaako Jarvi', 5, 2, 10.5, 1.5),
 
255
 
 
256
        ('lunch, short presentations, vendor presentations', '', None, 3, 12.0, 2.0),
 
257
 
 
258
        ('Reflective Metaprogramming', 'Daveed Vandevoorde', 1, 3, 14.0, 1.5),
 
259
        ('Advanced Template Issues and Solutions (double session)', 'Herb Sutter',2, 3, 14.0, 3),
 
260
        ('Concurrent Programming in Java (double session)', 'Angelika Langer', 3, 3, 14.0, 3),
 
261
        ('What can MISRA-C (2nd Edition) do for us?', 'Chris Hills', 4, 3, 14.0, 1.5),
 
262
        ('C++ Metaprogramming Concepts and Results', 'Walter E Brown', 5, 3, 14.0, 1.5),
 
263
 
 
264
        ('Binding C++ to Python with the Boost Python Library', 'David Abrahams', 1, 3, 16.0, 1.5),
 
265
        ('Using Aspect Oriented Programming for Enterprise Application Integration', 'Arno Schmidmeier', 4, 3, 16.0, 1.5),
 
266
        ('Defective C++', 'Marc Paterno', 5, 3, 16.0, 1.5),
 
267
 
 
268
        ("Speakers' Banquet & Birds of a Feather meeting", '', None, 3, 17.5, 2.0),
 
269
 
 
270
        ('Keynote: The Internet, Software and Computers - A Report Card', 'Alan Lenton',  None, 4, 9.0, 1.0),
 
271
 
 
272
        ('Multi-Platform Software Development; Lessons from the Boost libraries', 'Beman Dawes', 1, 5, 10.5, 1.5),
 
273
        ('The Stability of the C++ ABI', 'Steve Clamage', 2, 5, 10.5, 1.5),
 
274
        ('Generic Build Support - A Pragmatic Approach to the Software Build Process', 'Randy Marques', 3, 5, 10.5, 1.5),
 
275
        ('How to Handle Project Managers: a survival guide', 'Barb Byro',  4, 5, 10.5, 1.5),
 
276
 
 
277
        ('lunch, ACCU AGM', '', None, 5, 12.0, 2.0),
 
278
 
 
279
        ('Sauce: An OO recursive descent parser; its design and implementation.', 'Jon Jagger', 1, 5, 14.0, 1.5),
 
280
        ('GNIRTS ESAC REWOL -  Bringing the UNIX filters to the C++ iostream library.', 'JC van Winkel', 2, 5, 14.0, 1.5),
 
281
        ('Pattern Writing: Live and Direct', 'Frank Buschmann & Kevlin Henney',  3, 5, 14.0, 3.0),
 
282
        ('The Future of Programming Languages - A Goldfish Bowl', 'Francis Glassborow and friends',  3, 5, 14.0, 1.5),
 
283
 
 
284
        ('Honey, I Shrunk the Threads: Compile-time checked multithreaded transactions in C++', 'Andrei Alexandrescu', 1, 5, 16.0, 1.5),
 
285
        ('Fun and Functionality with Functors', 'Lois Goldthwaite', 2, 5, 16.0, 1.5),
 
286
        ('Agile Enough?', 'Alan Griffiths', 4, 5, 16.0, 1.5),
 
287
        ("Conference Closure: A brief plenary session", '', None, 5, 17.5, 0.5),
 
288
 
 
289
        ]
 
290
 
 
291
    #return cal
 
292
    cal.day = 1
 
293
 
 
294
    d.add(cal)
 
295
 
 
296
 
 
297
    for format in ['pdf']:#,'gif','png']:
 
298
        out = d.asString(format)
 
299
        open('eventcal.%s' % format, 'wb').write(out)
 
300
        print 'saved eventcal.%s' % format
 
301
 
 
302
if __name__=='__main__':
 
303
    test()