1.1 --- a/macros/EventAggregator.py Fri Oct 22 22:06:18 2010 +0200
1.2 +++ b/macros/EventAggregator.py Sat Oct 23 01:35:47 2010 +0200
1.3 @@ -24,7 +24,7 @@
1.4
1.5 def __init__(self, page, calendar_name, raw_calendar_start, raw_calendar_end,
1.6 calendar_start, calendar_end, first, last, category_names, template_name,
1.7 - parent_name, mode):
1.8 + parent_name, mode, name_usage):
1.9
1.10 """
1.11 Initialise the view with the current 'page', a 'calendar_name' (which
1.12 @@ -35,6 +35,9 @@
1.13
1.14 The additional 'category_names', 'template_name', 'parent_name' and
1.15 'mode' parameters are used to configure the links employed by the view.
1.16 +
1.17 + The 'name_usage' parameter controls how names are shown on calendar mode
1.18 + events.
1.19 """
1.20
1.21 self.page = page
1.22 @@ -46,6 +49,7 @@
1.23 self.template_name = template_name
1.24 self.parent_name = parent_name
1.25 self.mode = mode
1.26 + self.name_usage = name_usage
1.27
1.28 self.category_name_parameters = "&".join([("category=%s" % name) for name in category_names])
1.29
1.30 @@ -375,6 +379,330 @@
1.31
1.32 return "".join(output)
1.33
1.34 + # Calendar layout methods.
1.35 +
1.36 + def writeDayNumbers(self, first_day, number_of_days, month, busy_dates):
1.37 + page = self.page
1.38 + fmt = page.formatter
1.39 +
1.40 + output = []
1.41 + output.append(fmt.table_row(on=1))
1.42 +
1.43 + for weekday in range(0, 7):
1.44 + day = first_day + weekday
1.45 + date = month.as_date(day)
1.46 +
1.47 + # Output out-of-month days.
1.48 +
1.49 + if day < 1 or day > number_of_days:
1.50 + output.append(fmt.table_cell(on=1,
1.51 + attrs={"class" : "event-day-heading event-day-excluded", "colspan" : "3"}))
1.52 + output.append(fmt.table_cell(on=0))
1.53 +
1.54 + # Output normal days.
1.55 +
1.56 + else:
1.57 + if date in busy_dates:
1.58 + output.append(fmt.table_cell(on=1,
1.59 + attrs={"class" : "event-day-heading event-day-busy", "colspan" : "3"}))
1.60 + else:
1.61 + output.append(fmt.table_cell(on=1,
1.62 + attrs={"class" : "event-day-heading event-day-empty", "colspan" : "3"}))
1.63 +
1.64 + # Output the day number, making a link to a new event
1.65 + # action.
1.66 +
1.67 + output.append(self.writeDayNumberLinked(date))
1.68 +
1.69 + # End of day.
1.70 +
1.71 + output.append(fmt.table_cell(on=0))
1.72 +
1.73 + # End of day numbers.
1.74 +
1.75 + output.append(fmt.table_row(on=0))
1.76 + return "".join(output)
1.77 +
1.78 + def writeEmptyWeek(self, first_day, number_of_days):
1.79 + page = self.page
1.80 + fmt = page.formatter
1.81 +
1.82 + output = []
1.83 + output.append(fmt.table_row(on=1))
1.84 +
1.85 + for weekday in range(0, 7):
1.86 + day = first_day + weekday
1.87 +
1.88 + # Output out-of-month days.
1.89 +
1.90 + if day < 1 or day > number_of_days:
1.91 + output.append(fmt.table_cell(on=1,
1.92 + attrs={"class" : "event-day-content event-day-excluded", "colspan" : "3"}))
1.93 + output.append(fmt.table_cell(on=0))
1.94 +
1.95 + # Output empty days.
1.96 +
1.97 + else:
1.98 + output.append(fmt.table_cell(on=1,
1.99 + attrs={"class" : "event-day-content event-day-empty", "colspan" : "3"}))
1.100 +
1.101 + output.append(fmt.table_row(on=0))
1.102 + return "".join(output)
1.103 +
1.104 + def writeWeekSlots(self, first_day, number_of_days, month, week_end, week_slots):
1.105 + output = []
1.106 +
1.107 + locations = week_slots.keys()
1.108 + locations.sort(EventAggregatorSupport.sort_none_first)
1.109 +
1.110 + # Visit each slot corresponding to a location (or no location).
1.111 +
1.112 + for location in locations:
1.113 +
1.114 + # Visit each coverage span, presenting the events in the span.
1.115 +
1.116 + for coverage, events in week_slots[location]:
1.117 +
1.118 + # Output each set.
1.119 +
1.120 + output.append(self.writeWeekSlot(first_day, number_of_days, month, week_end, coverage, events))
1.121 +
1.122 + # Add a spacer.
1.123 +
1.124 + output.append(self.writeSpacer(first_day, number_of_days))
1.125 +
1.126 + return "".join(output)
1.127 +
1.128 + def writeWeekSlot(self, first_day, number_of_days, month, week_end, coverage, events):
1.129 + page = self.page
1.130 + request = page.request
1.131 + fmt = page.formatter
1.132 +
1.133 + output = []
1.134 + output.append(fmt.table_row(on=1))
1.135 +
1.136 + # Then, output day details.
1.137 +
1.138 + for weekday in range(0, 7):
1.139 + day = first_day + weekday
1.140 + date = month.as_date(day)
1.141 +
1.142 + # Skip out-of-month days.
1.143 +
1.144 + if day < 1 or day > number_of_days:
1.145 + output.append(fmt.table_cell(on=1,
1.146 + attrs={"class" : "event-day-content event-day-excluded", "colspan" : "3"}))
1.147 + output.append(fmt.table_cell(on=0))
1.148 + continue
1.149 +
1.150 + # Output the day.
1.151 +
1.152 + if date not in coverage:
1.153 + output.append(fmt.table_cell(on=1,
1.154 + attrs={"class" : "event-day-content event-day-empty", "colspan" : "3"}))
1.155 +
1.156 + # Get event details for the current day.
1.157 +
1.158 + for event in events:
1.159 + event_page = event.getPage()
1.160 + event_details = event.getDetails()
1.161 +
1.162 + if not (event_details["start"] <= date <= event_details["end"]):
1.163 + continue
1.164 +
1.165 + # Get basic properties of the event.
1.166 +
1.167 + starts_today = event_details["start"] == date
1.168 + ends_today = event_details["end"] == date
1.169 + event_summary = event.getSummary(self.parent_name)
1.170 + is_ambiguous = event_details["start"].ambiguous() or event_details["end"].ambiguous()
1.171 +
1.172 + # Generate a colour for the event.
1.173 +
1.174 + bg = getColour(event_summary)
1.175 + fg = getBlackOrWhite(bg)
1.176 + style = ("background-color: rgb(%d, %d, %d); color: rgb(%d, %d, %d);" % (bg + fg))
1.177 +
1.178 + # Determine if the event name should be shown.
1.179 +
1.180 + start_of_period = starts_today or weekday == 0 or day == 1
1.181 +
1.182 + if self.name_usage == "daily" or start_of_period:
1.183 + hide_text = 0
1.184 + else:
1.185 + hide_text = 1
1.186 +
1.187 + # Output start of day gap and determine whether
1.188 + # any event content should be explicitly output
1.189 + # for this day.
1.190 +
1.191 + if starts_today:
1.192 +
1.193 + # Single day events...
1.194 +
1.195 + if ends_today:
1.196 + colspan = 3
1.197 + event_day_type = "event-day-single"
1.198 +
1.199 + # Events starting today...
1.200 +
1.201 + else:
1.202 + output.append(fmt.table_cell(on=1, attrs={"class" : "event-day-start-gap"}))
1.203 + output.append(fmt.table_cell(on=0))
1.204 +
1.205 + # Calculate the span of this cell.
1.206 + # Events whose names appear on every day...
1.207 +
1.208 + if self.name_usage == "daily":
1.209 + colspan = 2
1.210 + event_day_type = "event-day-starting"
1.211 +
1.212 + # Events whose names appear once per week...
1.213 +
1.214 + else:
1.215 + if event_details["end"] <= week_end:
1.216 + event_length = event_details["end"].day() - day + 1
1.217 + colspan = (event_length - 2) * 3 + 4
1.218 + else:
1.219 + event_length = week_end.day() - day + 1
1.220 + colspan = (event_length - 1) * 3 + 2
1.221 +
1.222 + event_day_type = "event-day-multiple"
1.223 +
1.224 + # Events continuing from a previous week...
1.225 +
1.226 + elif start_of_period:
1.227 +
1.228 + # End of continuing event...
1.229 +
1.230 + if ends_today:
1.231 + colspan = 2
1.232 + event_day_type = "event-day-ending"
1.233 +
1.234 + # Events continuing for at least one more day...
1.235 +
1.236 + else:
1.237 +
1.238 + # Calculate the span of this cell.
1.239 + # Events whose names appear on every day...
1.240 +
1.241 + if self.name_usage == "daily":
1.242 + colspan = 3
1.243 + event_day_type = "event-day-full"
1.244 +
1.245 + # Events whose names appear once per week...
1.246 +
1.247 + else:
1.248 + if event_details["end"] <= week_end:
1.249 + event_length = event_details["end"].day() - day + 1
1.250 + colspan = (event_length - 1) * 3 + 2
1.251 + else:
1.252 + event_length = week_end.day() - day + 1
1.253 + colspan = event_length * 3
1.254 +
1.255 + event_day_type = "event-day-multiple"
1.256 +
1.257 + # Continuing events whose names appear on every day...
1.258 +
1.259 + elif self.name_usage == "daily":
1.260 + if ends_today:
1.261 + colspan = 2
1.262 + event_day_type = "event-day-ending"
1.263 + else:
1.264 + colspan = 3
1.265 + event_day_type = "event-day-full"
1.266 +
1.267 + # Continuing events whose names appear once per week...
1.268 +
1.269 + else:
1.270 + colspan = None
1.271 +
1.272 + # Output the main content only if it is not
1.273 + # continuing from a previous day.
1.274 +
1.275 + if colspan is not None:
1.276 +
1.277 + # Colour the cell for continuing events.
1.278 +
1.279 + attrs={
1.280 + "class" : "event-day-content event-day-busy %s" % event_day_type,
1.281 + "colspan" : str(colspan)
1.282 + }
1.283 +
1.284 + if not (starts_today and ends_today):
1.285 + attrs["style"] = style
1.286 +
1.287 + output.append(fmt.table_cell(on=1, attrs=attrs))
1.288 +
1.289 + # Output the event.
1.290 +
1.291 + if starts_today and ends_today or not hide_text:
1.292 +
1.293 + # The event box contains the summary, alongside
1.294 + # other elements.
1.295 +
1.296 + output.append(fmt.div(on=1, css_class="event-summary-box"))
1.297 + output.append(fmt.div(on=1, css_class="event-summary", style=style))
1.298 +
1.299 + if is_ambiguous:
1.300 + output.append(fmt.icon("/!\\"))
1.301 +
1.302 + output.append(event_page.linkToPage(request, event_summary))
1.303 + output.append(fmt.div(on=0))
1.304 +
1.305 + # Add a pop-up element for long summaries.
1.306 +
1.307 + output.append(fmt.div(on=1, css_class="event-summary-popup", style=style))
1.308 +
1.309 + if is_ambiguous:
1.310 + output.append(fmt.icon("/!\\"))
1.311 +
1.312 + output.append(event_page.linkToPage(request, event_summary))
1.313 + output.append(fmt.div(on=0))
1.314 +
1.315 + output.append(fmt.div(on=0))
1.316 +
1.317 + # Output end of day content.
1.318 +
1.319 + output.append(fmt.div(on=0))
1.320 +
1.321 + # Output end of day gap.
1.322 +
1.323 + if ends_today and not starts_today:
1.324 + output.append(fmt.table_cell(on=1, attrs={"class" : "event-day-end-gap"}))
1.325 + output.append(fmt.table_cell(on=0))
1.326 +
1.327 + # End of day.
1.328 +
1.329 + output.append(fmt.table_cell(on=0))
1.330 +
1.331 + # End of set.
1.332 +
1.333 + output.append(fmt.table_row(on=0))
1.334 + return "".join(output)
1.335 +
1.336 + def writeSpacer(self, first_day, number_of_days):
1.337 + page = self.page
1.338 + fmt = page.formatter
1.339 +
1.340 + output = []
1.341 + output.append(fmt.table_row(on=1))
1.342 +
1.343 + for weekday in range(0, 7):
1.344 + day = first_day + weekday
1.345 + css_classes = "event-day-spacer"
1.346 +
1.347 + # Skip out-of-month days.
1.348 +
1.349 + if day < 1 or day > number_of_days:
1.350 + css_classes += " event-day-excluded"
1.351 +
1.352 + output.append(fmt.table_cell(on=1, attrs={"class" : css_classes, "colspan" : "3"}))
1.353 + output.append(fmt.table_cell(on=0))
1.354 +
1.355 + output.append(fmt.table_row(on=0))
1.356 + return "".join(output)
1.357 +
1.358 # HTML-related functions.
1.359
1.360 def getColour(s):
1.361 @@ -498,7 +826,7 @@
1.362 # Define a view of the calendar, retaining useful navigational information.
1.363
1.364 view = View(page, calendar_name, raw_calendar_start, raw_calendar_end, calendar_start, calendar_end,
1.365 - first, last, category_names, template_name, parent_name, mode)
1.366 + first, last, category_names, template_name, parent_name, mode, name_usage)
1.367
1.368 # Make a calendar.
1.369
1.370 @@ -660,299 +988,17 @@
1.371
1.372 # Output a week, starting with the day numbers.
1.373
1.374 - output.append(fmt.table_row(on=1))
1.375 -
1.376 - for weekday in range(0, 7):
1.377 - day = first_day + weekday
1.378 - date = month.as_date(day)
1.379 -
1.380 - # Output out-of-month days.
1.381 -
1.382 - if day < 1 or day > number_of_days:
1.383 - output.append(fmt.table_cell(on=1,
1.384 - attrs={"class" : "event-day-heading event-day-excluded", "colspan" : "3"}))
1.385 - output.append(fmt.table_cell(on=0))
1.386 -
1.387 - # Output normal days.
1.388 -
1.389 - else:
1.390 - if date in full_coverage:
1.391 - output.append(fmt.table_cell(on=1,
1.392 - attrs={"class" : "event-day-heading event-day-busy", "colspan" : "3"}))
1.393 - else:
1.394 - output.append(fmt.table_cell(on=1,
1.395 - attrs={"class" : "event-day-heading event-day-empty", "colspan" : "3"}))
1.396 -
1.397 - # Output the day number, making a link to a new event
1.398 - # action.
1.399 -
1.400 - output.append(view.writeDayNumberLinked(date))
1.401 -
1.402 - # End of day.
1.403 -
1.404 - output.append(fmt.table_cell(on=0))
1.405 -
1.406 - # End of day numbers.
1.407 -
1.408 - output.append(fmt.table_row(on=0))
1.409 + output.append(view.writeDayNumbers(first_day, number_of_days, month, full_coverage))
1.410
1.411 # Either generate empty days...
1.412
1.413 if not week_slots:
1.414 - output.append(fmt.table_row(on=1))
1.415 -
1.416 - for weekday in range(0, 7):
1.417 - day = first_day + weekday
1.418 -
1.419 - # Output out-of-month days.
1.420 + output.append(view.writeEmptyWeek(first_day, number_of_days))
1.421
1.422 - if day < 1 or day > number_of_days:
1.423 - output.append(fmt.table_cell(on=1,
1.424 - attrs={"class" : "event-day-content event-day-excluded", "colspan" : "3"}))
1.425 - output.append(fmt.table_cell(on=0))
1.426 -
1.427 - # Output empty days.
1.428 -
1.429 - else:
1.430 - output.append(fmt.table_cell(on=1,
1.431 - attrs={"class" : "event-day-content event-day-empty", "colspan" : "3"}))
1.432 -
1.433 - output.append(fmt.table_row(on=0))
1.434 -
1.435 - # Or visit each set of scheduled events...
1.436 + # Or generate each set of scheduled events...
1.437
1.438 else:
1.439 - locations = week_slots.keys()
1.440 - locations.sort(EventAggregatorSupport.sort_none_first)
1.441 -
1.442 - # Visit each slot corresponding to a location (or no location).
1.443 -
1.444 - for location in locations:
1.445 -
1.446 - # Visit each coverage span, presenting the events in the span.
1.447 -
1.448 - for coverage, events in week_slots[location]:
1.449 -
1.450 - # Output each set.
1.451 -
1.452 - output.append(fmt.table_row(on=1))
1.453 -
1.454 - # Then, output day details.
1.455 -
1.456 - for weekday in range(0, 7):
1.457 - day = first_day + weekday
1.458 - date = month.as_date(day)
1.459 -
1.460 - # Skip out-of-month days.
1.461 -
1.462 - if day < 1 or day > number_of_days:
1.463 - output.append(fmt.table_cell(on=1,
1.464 - attrs={"class" : "event-day-content event-day-excluded", "colspan" : "3"}))
1.465 - output.append(fmt.table_cell(on=0))
1.466 - continue
1.467 -
1.468 - # Output the day.
1.469 -
1.470 - if date not in coverage:
1.471 - output.append(fmt.table_cell(on=1,
1.472 - attrs={"class" : "event-day-content event-day-empty", "colspan" : "3"}))
1.473 -
1.474 - # Get event details for the current day.
1.475 -
1.476 - for event in events:
1.477 - event_page = event.getPage()
1.478 - event_details = event.getDetails()
1.479 -
1.480 - if not (event_details["start"] <= date <= event_details["end"]):
1.481 - continue
1.482 -
1.483 - # Get basic properties of the event.
1.484 -
1.485 - starts_today = event_details["start"] == date
1.486 - ends_today = event_details["end"] == date
1.487 - event_summary = event.getSummary(parent_name)
1.488 - is_ambiguous = event_details["start"].ambiguous() or event_details["end"].ambiguous()
1.489 -
1.490 - # Generate a colour for the event.
1.491 -
1.492 - bg = getColour(event_summary)
1.493 - fg = getBlackOrWhite(bg)
1.494 - style = ("background-color: rgb(%d, %d, %d); color: rgb(%d, %d, %d);" % (bg + fg))
1.495 -
1.496 - # Determine if the event name should be shown.
1.497 -
1.498 - start_of_period = starts_today or weekday == 0 or day == 1
1.499 -
1.500 - if name_usage == "daily" or start_of_period:
1.501 - hide_text = 0
1.502 - else:
1.503 - hide_text = 1
1.504 -
1.505 - # Output start of day gap and determine whether
1.506 - # any event content should be explicitly output
1.507 - # for this day.
1.508 -
1.509 - if starts_today:
1.510 -
1.511 - # Single day events...
1.512 -
1.513 - if ends_today:
1.514 - colspan = 3
1.515 - event_day_type = "event-day-single"
1.516 -
1.517 - # Events starting today...
1.518 -
1.519 - else:
1.520 - output.append(fmt.table_cell(on=1, attrs={"class" : "event-day-start-gap"}))
1.521 - output.append(fmt.table_cell(on=0))
1.522 -
1.523 - # Calculate the span of this cell.
1.524 - # Events whose names appear on every day...
1.525 -
1.526 - if name_usage == "daily":
1.527 - colspan = 2
1.528 - event_day_type = "event-day-starting"
1.529 -
1.530 - # Events whose names appear once per week...
1.531 -
1.532 - else:
1.533 - if event_details["end"] <= week_end:
1.534 - event_length = event_details["end"].day() - day + 1
1.535 - colspan = (event_length - 2) * 3 + 4
1.536 - else:
1.537 - event_length = week_end.day() - day + 1
1.538 - colspan = (event_length - 1) * 3 + 2
1.539 -
1.540 - event_day_type = "event-day-multiple"
1.541 -
1.542 - # Events continuing from a previous week...
1.543 -
1.544 - elif start_of_period:
1.545 -
1.546 - # End of continuing event...
1.547 -
1.548 - if ends_today:
1.549 - colspan = 2
1.550 - event_day_type = "event-day-ending"
1.551 -
1.552 - # Events continuing for at least one more day...
1.553 -
1.554 - else:
1.555 -
1.556 - # Calculate the span of this cell.
1.557 - # Events whose names appear on every day...
1.558 -
1.559 - if name_usage == "daily":
1.560 - colspan = 3
1.561 - event_day_type = "event-day-full"
1.562 -
1.563 - # Events whose names appear once per week...
1.564 -
1.565 - else:
1.566 - if event_details["end"] <= week_end:
1.567 - event_length = event_details["end"].day() - day + 1
1.568 - colspan = (event_length - 1) * 3 + 2
1.569 - else:
1.570 - event_length = week_end.day() - day + 1
1.571 - colspan = event_length * 3
1.572 -
1.573 - event_day_type = "event-day-multiple"
1.574 -
1.575 - # Continuing events whose names appear on every day...
1.576 -
1.577 - elif name_usage == "daily":
1.578 - if ends_today:
1.579 - colspan = 2
1.580 - event_day_type = "event-day-ending"
1.581 - else:
1.582 - colspan = 3
1.583 - event_day_type = "event-day-full"
1.584 -
1.585 - # Continuing events whose names appear once per week...
1.586 -
1.587 - else:
1.588 - colspan = None
1.589 -
1.590 - # Output the main content only if it is not
1.591 - # continuing from a previous day.
1.592 -
1.593 - if colspan is not None:
1.594 -
1.595 - # Colour the cell for continuing events.
1.596 -
1.597 - attrs={
1.598 - "class" : "event-day-content event-day-busy %s" % event_day_type,
1.599 - "colspan" : str(colspan)
1.600 - }
1.601 -
1.602 - if not (starts_today and ends_today):
1.603 - attrs["style"] = style
1.604 -
1.605 - output.append(fmt.table_cell(on=1, attrs=attrs))
1.606 -
1.607 - # Output the event.
1.608 -
1.609 - if starts_today and ends_today or not hide_text:
1.610 -
1.611 - # The event box contains the summary, alongside
1.612 - # other elements.
1.613 -
1.614 - output.append(fmt.div(on=1, css_class="event-summary-box"))
1.615 - output.append(fmt.div(on=1, css_class="event-summary", style=style))
1.616 -
1.617 - if is_ambiguous:
1.618 - output.append(fmt.icon("/!\\"))
1.619 -
1.620 - output.append(event_page.linkToPage(request, event_summary))
1.621 - output.append(fmt.div(on=0))
1.622 -
1.623 - # Add a pop-up element for long summaries.
1.624 -
1.625 - output.append(fmt.div(on=1, css_class="event-summary-popup", style=style))
1.626 -
1.627 - if is_ambiguous:
1.628 - output.append(fmt.icon("/!\\"))
1.629 -
1.630 - output.append(event_page.linkToPage(request, event_summary))
1.631 - output.append(fmt.div(on=0))
1.632 -
1.633 - output.append(fmt.div(on=0))
1.634 -
1.635 - # Output end of day content.
1.636 -
1.637 - output.append(fmt.div(on=0))
1.638 -
1.639 - # Output end of day gap.
1.640 -
1.641 - if ends_today and not starts_today:
1.642 - output.append(fmt.table_cell(on=1, attrs={"class" : "event-day-end-gap"}))
1.643 - output.append(fmt.table_cell(on=0))
1.644 -
1.645 - # End of day.
1.646 -
1.647 - output.append(fmt.table_cell(on=0))
1.648 -
1.649 - # End of set.
1.650 -
1.651 - output.append(fmt.table_row(on=0))
1.652 -
1.653 - # Add a spacer.
1.654 -
1.655 - output.append(fmt.table_row(on=1))
1.656 -
1.657 - for weekday in range(0, 7):
1.658 - day = first_day + weekday
1.659 - css_classes = "event-day-spacer"
1.660 -
1.661 - # Skip out-of-month days.
1.662 -
1.663 - if day < 1 or day > number_of_days:
1.664 - css_classes += " event-day-excluded"
1.665 -
1.666 - output.append(fmt.table_cell(on=1, attrs={"class" : css_classes, "colspan" : "3"}))
1.667 - output.append(fmt.table_cell(on=0))
1.668 -
1.669 - output.append(fmt.table_row(on=0))
1.670 + output.append(view.writeWeekSlots(first_day, number_of_days, month, week_end, week_slots))
1.671
1.672 # Process the next week...
1.673