def calculate_cell_data(self): width = self.get_allocation().width height = self.get_allocation().height x, y = self.grid_origin grid_height = height - y - PADDING_BOTTOM num_weeks = number_of_weeks(self.date.year, self.date.month) cell_height = grid_height / float(num_weeks) cell_width = (width - PADDING_LEFT - PADDING_RIGHT) / 7.0 monthdates = iter_month_dates(self.date.year, self.date.month) y2 = y for row in range(num_weeks): x2 = x for column in range(7): d = self.cells[column][row] d['x'] = int(x2) d['y'] = int(y2) d['width'] = int(cell_width) d['height'] = int(cell_height) d['date'] = monthdates.next() if not 'selected' in d: d['selected'] = False x2 += cell_width y2 += cell_height
def button_press_cb(self, widget, event): x, y = event.x, event.y should_redraw = False num_weeks = number_of_weeks(self.date.year, self.date.month) for column in range(7): for row in range(num_weeks): c_x = self.cells[column][row]['x'] c_y = self.cells[column][row]['y'] c_w = self.cells[column][row]['width'] c_h = self.cells[column][row]['height'] if (in_rect(x, y, c_x, c_y, c_w, c_h)): self.cells[column][row]['selected'] = True self.emit('day-selected', self.cells[column][row]['date']) should_redraw = True else: self.cells[column][row]['selected'] = False if should_redraw: self.queue_draw()
def draw(self, widget, ctx): width = self.get_allocation().width height = self.get_allocation().height ctx.set_operator(cairo.OPERATOR_OVER) # clear background ctx.set_source_rgb(255, 255, 255) ctx.rectangle(0, 0, width, height) ctx.fill() cell_width = (width - PADDING_LEFT - PADDING_RIGHT) / 7.0 # Draw weekdays ctx.set_source_rgba(*COLOR_GREY) ctx.select_font_face(*FONT_NORMAL) ctx.set_font_size(FONT_SIZE_WEEKDAY) y = PADDING_TOP for i, weekday in enumerate(calendar.Calendar().iterweekdays()): dayname = calendar.day_name[weekday] _, _, t_width, t_height = get_text_extents(ctx, dayname) x = i * cell_width + cell_width/2 - t_width/2 y = max(y, t_height + PADDING_TOP) ctx.move_to(x, y) ctx.show_text(dayname) if self.grid_origin != (PADDING_LEFT, y + PADDING): self.grid_origin = (PADDING_LEFT, y + PADDING) self.calculate_cell_data() else: self.grid_origin = (PADDING_LEFT, y + PADDING) num_weeks = number_of_weeks(self.date.year, self.date.month) for column in range(7): for row in range(num_weeks): x = self.cells[column][row]['x'] y = self.cells[column][row]['y'] cell_width = self.cells[column][row]['width'] cell_height = self.cells[column][row]['height'] date = self.cells[column][row]['date'] events = self.cells[column][row]['events'] selected = self.cells[column][row]['selected'] if date.month != self.date.month: # Draw the day grey, it sucks! ctx.set_source_rgba(0, 0, 0, 0.05) ctx.rectangle(x, y, cell_width+1, cell_height+1) ctx.fill() if selected: ctx.set_source_rgba(0, 0, 0.5, 0.1) ctx.rectangle(x, y, cell_width+1, cell_height+1) ctx.fill() # Draw the day into the right upper corner ctx.set_source_rgba(*COLOR_GREY) ctx.select_font_face(*FONT_NORMAL) ctx.set_font_size(FONT_SIZE_DAY) _, _, t_width, t_height = get_text_extents(ctx, str(date.day)) x2 = x + cell_width - t_width - PADDING_DAY y2 = y + t_height + PADDING_DAY ctx.move_to(x2, y2) ctx.show_text(str(date.day)) # Draw events for event, pos in events: ctx.set_source_rgb(*event.color) y3 = int(y2 + PADDING_EVENT + pos * (EVENT_HEIGHT + PADDING_EVENT)) if (event.start.as_date == date.as_date and event.end.as_date == date.as_date): roundedrect(ctx, x+PADDING_START, y3, cell_width-(PADDING_START+PADDING_END), EVENT_HEIGHT, 8) elif event.start.as_date == date.as_date: roundedrect(ctx, x+PADDING_START, y3, cell_width-(PADDING_START-1), EVENT_HEIGHT, 8, right=False) elif event.end.as_date == date.as_date: roundedrect(ctx, x, y3, cell_width-PADDING_END, EVENT_HEIGHT, 8, left=False) else: ctx.rectangle(x, y3, cell_width+1, EVENT_HEIGHT) ctx.fill() # Draw grid def draw_line(ctx, x1, y1, x2, y2): ctx.set_source_rgba(.8, .8, .8, 1) ctx.set_line_width(1) ctx.move_to(int(x1) + .5, int(y1) + .5) ctx.line_to(int(x2) + .5, int(y2) + .5) ctx.stroke() for column in range(7): for row in range(num_weeks): x = self.cells[column][row]['x'] y = self.cells[column][row]['y'] # Draw horizontal line if column == 0: draw_line(ctx, x, y, width - PADDING_RIGHT, y) # Draw vertical line if row == 0: draw_line(ctx, x, y, x, height - PADDING_BOTTOM) # Draw rightmost line if row == 0 and column == 6: x2 = int(x + cell_width) draw_line(ctx, x2, y, x2, height - PADDING_BOTTOM) # Draw bottom line if column == 0: y = int(y + cell_height) draw_line(ctx, x, y, width - PADDING_RIGHT, y) # Draw event titles ctx.select_font_face(*FONT_NORMAL) ctx.set_font_size(FONT_SIZE_DAY) ctx.set_source_rgb(0, 0, 0) for column in range(7): for row in range(num_weeks): x = self.cells[column][row]['x'] y = self.cells[column][row]['y'] cell_width = self.cells[column][row]['width'] date = self.cells[column][row]['date'] events = self.cells[column][row]['events'] t_height = get_text_extents(ctx, str(date.day))[3] y2 = y + t_height + PADDING_DAY for event, pos in events: y3 = int(y2 + PADDING_EVENT + pos * (EVENT_HEIGHT + PADDING_EVENT)) if date == event.start.as_date or date.first_day_of_week: space = calculate_remaining_space(event, date, cell_width) title = event.title t_width = get_text_extents(ctx, title)[2] while t_width > space and len(title) > 1: title = title[:-1] t_width = get_text_extents(ctx, title)[2] ctx.move_to(x + PADDING_TITLE_LEFT, y3 + 11) ctx.show_text(title)