1.1 --- a/macros/EventAggregator.py Mon Dec 20 01:18:48 2010 +0100
1.2 +++ b/macros/EventAggregator.py Sun Jan 16 03:10:14 2011 +0100
1.3 @@ -2,7 +2,7 @@
1.4 """
1.5 MoinMoin - EventAggregator Macro
1.6
1.7 - @copyright: 2008, 2009, 2010 by Paul Boddie <paul@boddie.org.uk>
1.8 + @copyright: 2008, 2009, 2010, 2011 by Paul Boddie <paul@boddie.org.uk>
1.9 @copyright: 2000-2004 Juergen Hermann <jh@web.de>,
1.10 2005-2008 MoinMoin:ThomasWaldmann.
1.11 @license: GNU GPL (v2 or later), see COPYING.txt for details.
1.12 @@ -37,7 +37,7 @@
1.13 'mode' parameters are used to configure the links employed by the view.
1.14
1.15 The 'name_usage' parameter controls how names are shown on calendar mode
1.16 - events.
1.17 + events, such as how often labels are repeated.
1.18 """
1.19
1.20 self.page = page
1.21 @@ -191,9 +191,11 @@
1.22
1.23 # Pop-up descriptions of the downloadable calendars.
1.24
1.25 + get_label = self.mode == "day" and self.getFullDateLabel or self.getFullMonthLabel
1.26 +
1.27 calendar_period = "%s - %s" % (
1.28 - self.getFullMonthLabel(self.calendar_start),
1.29 - self.getFullMonthLabel(self.calendar_end)
1.30 + get_label(self.calendar_start),
1.31 + get_label(self.calendar_end)
1.32 )
1.33 raw_calendar_period = "%s - %s" % (self.raw_calendar_start, self.raw_calendar_end)
1.34
1.35 @@ -386,6 +388,59 @@
1.36
1.37 return "".join(output)
1.38
1.39 + # Common layout methods.
1.40 +
1.41 + def getEventStyle(self, colour_seed):
1.42 +
1.43 + "Generate colour style information using the given 'colour_seed'."
1.44 +
1.45 + bg = getColour(colour_seed)
1.46 + fg = getBlackOrWhite(bg)
1.47 + return "background-color: rgb(%d, %d, %d); color: rgb(%d, %d, %d);" % (bg + fg)
1.48 +
1.49 + def writeEventSummaryBox(self, event):
1.50 +
1.51 + "Return an event summary box linking to the given 'event'."
1.52 +
1.53 + page = self.page
1.54 + request = page.request
1.55 + fmt = page.formatter
1.56 +
1.57 + output = []
1.58 +
1.59 + event_page = event.getPage()
1.60 + event_details = event.getDetails()
1.61 + event_summary = event.getSummary(self.parent_name)
1.62 +
1.63 + is_ambiguous = event_details["start"].ambiguous() or event_details["end"].ambiguous()
1.64 + style = self.getEventStyle(event_summary)
1.65 +
1.66 + # The event box contains the summary, alongside
1.67 + # other elements.
1.68 +
1.69 + output.append(fmt.div(on=1, css_class="event-summary-box"))
1.70 + output.append(fmt.div(on=1, css_class="event-summary", style=style))
1.71 +
1.72 + if is_ambiguous:
1.73 + output.append(fmt.icon("/!\\"))
1.74 +
1.75 + output.append(event_page.linkToPage(request, event_summary))
1.76 + output.append(fmt.div(on=0))
1.77 +
1.78 + # Add a pop-up element for long summaries.
1.79 +
1.80 + output.append(fmt.div(on=1, css_class="event-summary-popup", style=style))
1.81 +
1.82 + if is_ambiguous:
1.83 + output.append(fmt.icon("/!\\"))
1.84 +
1.85 + output.append(event_page.linkToPage(request, event_summary))
1.86 + output.append(fmt.div(on=0))
1.87 +
1.88 + output.append(fmt.div(on=0))
1.89 +
1.90 + return "".join(output)
1.91 +
1.92 # Calendar layout methods.
1.93
1.94 def writeMonthTableHeading(self, year_month):
1.95 @@ -554,13 +609,8 @@
1.96 starts_today = event_details["start"] == date
1.97 ends_today = event_details["end"] == date
1.98 event_summary = event.getSummary(self.parent_name)
1.99 - is_ambiguous = event_details["start"].ambiguous() or event_details["end"].ambiguous()
1.100
1.101 - # Generate a colour for the event.
1.102 -
1.103 - bg = getColour(event_summary)
1.104 - fg = getBlackOrWhite(bg)
1.105 - style = ("background-color: rgb(%d, %d, %d); color: rgb(%d, %d, %d);" % (bg + fg))
1.106 + style = self.getEventStyle(event_summary)
1.107
1.108 # Determine if the event name should be shown.
1.109
1.110 @@ -676,34 +726,9 @@
1.111 # Output the event.
1.112
1.113 if starts_today and ends_today or not hide_text:
1.114 -
1.115 - # The event box contains the summary, alongside
1.116 - # other elements.
1.117 -
1.118 - output.append(fmt.div(on=1, css_class="event-summary-box"))
1.119 - output.append(fmt.div(on=1, css_class="event-summary", style=style))
1.120 -
1.121 - if is_ambiguous:
1.122 - output.append(fmt.icon("/!\\"))
1.123 -
1.124 - output.append(event_page.linkToPage(request, event_summary))
1.125 - output.append(fmt.div(on=0))
1.126 + output.append(self.writeEventSummaryBox(event))
1.127
1.128 - # Add a pop-up element for long summaries.
1.129 -
1.130 - output.append(fmt.div(on=1, css_class="event-summary-popup", style=style))
1.131 -
1.132 - if is_ambiguous:
1.133 - output.append(fmt.icon("/!\\"))
1.134 -
1.135 - output.append(event_page.linkToPage(request, event_summary))
1.136 - output.append(fmt.div(on=0))
1.137 -
1.138 - output.append(fmt.div(on=0))
1.139 -
1.140 - # Output end of day content.
1.141 -
1.142 - output.append(fmt.div(on=0))
1.143 + output.append(fmt.table_cell(on=0))
1.144
1.145 # Output end of day gap.
1.146
1.147 @@ -711,10 +736,6 @@
1.148 output.append(fmt.table_cell(on=1, attrs={"class" : "event-day-end-gap"}))
1.149 output.append(fmt.table_cell(on=0))
1.150
1.151 - # End of day.
1.152 -
1.153 - output.append(fmt.table_cell(on=0))
1.154 -
1.155 # End of set.
1.156
1.157 output.append(fmt.table_row(on=0))
1.158 @@ -744,7 +765,7 @@
1.159
1.160 # Day layout methods.
1.161
1.162 - def writeDayHeading(self, date):
1.163 + def writeDayHeading(self, date, colspan=1):
1.164 page = self.page
1.165 request = page.request
1.166 fmt = page.formatter
1.167 @@ -754,7 +775,7 @@
1.168 output = []
1.169 output.append(fmt.table_row(on=1))
1.170
1.171 - output.append(fmt.table_cell(on=1, attrs={"class" : "event-weekday-heading"}))
1.172 + output.append(fmt.table_cell(on=1, attrs={"class" : "event-weekday-heading", "colspan" : str(colspan)}))
1.173 output.append(fmt.text(full_date_label))
1.174 output.append(fmt.table_cell(on=0))
1.175
1.176 @@ -787,33 +808,118 @@
1.177 # determine whether it provides content for each period.
1.178
1.179 scale = EventAggregatorSupport.getCoverageScale(full_coverage)
1.180 + period = None
1.181
1.182 for period in scale:
1.183 - start = period.start
1.184 +
1.185 + # Ignore timespans before this day.
1.186 +
1.187 + if not date in period:
1.188 + continue
1.189 +
1.190 + # Write an empty heading for the start of the day where the first
1.191 + # applicable timespan starts before this day.
1.192
1.193 - output.append(fmt.table_row(on=1))
1.194 - output.append(fmt.table_cell(on=1, attrs={"class" : "event-weekday-heading"}))
1.195 - output.append(fmt.text(str(start)))
1.196 - output.append(fmt.table_cell(on=0))
1.197 + if period.start < date:
1.198 + output.append(fmt.table_row(on=1))
1.199 + output.append(self.writeDayScaleHeading(""))
1.200 +
1.201 + # Otherwise, write a heading describing the time.
1.202 +
1.203 + else:
1.204 + output.append(fmt.table_row(on=1))
1.205 + output.append(self.writeDayScaleHeading(str(period.start)))
1.206
1.207 # Visit each slot corresponding to a location (or no location).
1.208
1.209 - #for location in locations:
1.210 + for location in locations:
1.211
1.212 - # # Visit each coverage span, presenting the events in the span.
1.213 + # Visit each coverage span, presenting the events in the span.
1.214 +
1.215 + for events in day_slots[location]:
1.216
1.217 - # for events in day_slots[location]:
1.218 + # Add a spacer.
1.219 +
1.220 + output.append(self.writeDaySpacer())
1.221
1.222 - # # Output each set.
1.223 + # Output each set's contribution to this period.
1.224
1.225 - # output.append(self.writeDaySlot(day, events))
1.226 + output.append(self.writeDaySlot(period, events))
1.227
1.228 output.append(fmt.table_row(on=0))
1.229
1.230 + # Write a final time heading if the last period ends in the current day.
1.231 +
1.232 + if period is not None:
1.233 + if period.end == date:
1.234 + output.append(fmt.table_row(on=1))
1.235 + output.append(self.writeDayScaleHeading(str(period.end)))
1.236 +
1.237 + for location in locations:
1.238 + for events in day_slots[location]:
1.239 + output.append(self.writeDaySpacer())
1.240 + output.append(self.writeEmptyDaySlot())
1.241 +
1.242 + output.append(fmt.table_row(on=0))
1.243 +
1.244 + return "".join(output)
1.245 +
1.246 + def writeDayScaleHeading(self, heading):
1.247 + page = self.page
1.248 + fmt = page.formatter
1.249 +
1.250 + output = []
1.251 + output.append(fmt.table_cell(on=1, attrs={"class" : "event-scale-heading"}))
1.252 + output.append(fmt.text(heading))
1.253 + output.append(fmt.table_cell(on=0))
1.254 +
1.255 return "".join(output)
1.256
1.257 - def writeDaySlot(self, date, events):
1.258 - pass
1.259 + def writeDaySlot(self, period, events):
1.260 + page = self.page
1.261 + fmt = page.formatter
1.262 +
1.263 + output = []
1.264 +
1.265 + for event in events:
1.266 + if period not in event:
1.267 + continue
1.268 +
1.269 + event_summary = event.getSummary(self.parent_name)
1.270 + style = self.getEventStyle(event_summary)
1.271 +
1.272 + output.append(fmt.table_cell(on=1, attrs={
1.273 + "class" : "event-timespan-content event-timespan-busy",
1.274 + "style" : style}))
1.275 + output.append(self.writeEventSummaryBox(event))
1.276 + output.append(fmt.table_cell(on=0))
1.277 + break
1.278 +
1.279 + else:
1.280 + output.append(self.writeEmptyDaySlot())
1.281 +
1.282 + return "".join(output)
1.283 +
1.284 + def writeEmptyDaySlot(self):
1.285 + page = self.page
1.286 + fmt = page.formatter
1.287 +
1.288 + output = []
1.289 +
1.290 + output.append(fmt.table_cell(on=1,
1.291 + attrs={"class" : "event-timespan-content event-timespan-empty"}))
1.292 + output.append(fmt.table_cell(on=0))
1.293 +
1.294 + return "".join(output)
1.295 +
1.296 + def writeDaySpacer(self):
1.297 + page = self.page
1.298 + fmt = page.formatter
1.299 +
1.300 + output = []
1.301 + output.append(fmt.table_cell(on=1, attrs={"class" : "event-timespan-spacer"}))
1.302 + output.append(fmt.table_cell(on=0))
1.303 + return "".join(output)
1.304
1.305 # HTML-related functions.
1.306
1.307 @@ -925,6 +1031,8 @@
1.308
1.309 mode = EventAggregatorSupport.getQualifiedParameter(request, calendar_name, "mode", mode or "calendar")
1.310
1.311 + # Different modes require different levels of precision.
1.312 +
1.313 if mode == "day":
1.314 get_date = EventAggregatorSupport.getParameterDate
1.315 get_form_date = EventAggregatorSupport.getFormDate
1.316 @@ -1215,7 +1323,12 @@
1.317 full_coverage, day_slots = EventAggregatorSupport.getCoverage(
1.318 date, date, shown_events.get(date, []))
1.319
1.320 - output.append(view.writeDayHeading(date))
1.321 + # Work out how many columns the day title will need.
1.322 + # Includer spacers before each event column.
1.323 +
1.324 + colspan = sum(map(len, day_slots.values())) * 2 + 1
1.325 +
1.326 + output.append(view.writeDayHeading(date, colspan))
1.327
1.328 # Either generate empty days...
1.329