"Fossies" - the Fresh Open Source Software Archive

Member "reportlab-3.5.23/src/reportlab/graphics/widgets/eventcal.py" (6 Nov 2017, 13224 Bytes) of package /linux/privat/reportlab-3.5.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "eventcal.py" see the Fossies "Dox" file reference documentation.

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