| @@ -277,60 +277,88 @@ def internet_available(): | |||||||
|     return False |     return False | ||||||
|  |  | ||||||
|  |  | ||||||
| def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)): | from PIL import Image, ImageDraw | ||||||
|     """Draws a border at given coordinates. |  | ||||||
|  | def draw_dotted_line(draw, start, end, colour, thickness): | ||||||
|  |     """Draws a dotted line between start and end points using dots.""" | ||||||
|  |     delta_x = end[0] - start[0] | ||||||
|  |     delta_y = end[1] - start[1] | ||||||
|  |     distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) | ||||||
|  |     dot_spacing = 6  # Distance between dots | ||||||
|  |  | ||||||
|  |     for i in range(0, int(distance / dot_spacing), 1): | ||||||
|  |         dot_position = (start[0] + (i * dot_spacing * delta_x / distance), | ||||||
|  |                         start[1] + (i * dot_spacing * delta_y / distance)) | ||||||
|  |         # Drawing a circle at each dot position to create a dotted effect | ||||||
|  |         draw.ellipse([(dot_position[0] - thickness, dot_position[1] - thickness), | ||||||
|  |                       (dot_position[0] + thickness, dot_position[1] + thickness)], | ||||||
|  |                       fill=colour) | ||||||
|  |  | ||||||
|  | def draw_dashed_line(draw, start, end, colour, thickness): | ||||||
|  |     """Draws a dashed line between start and end points.""" | ||||||
|  |     delta_x = end[0] - start[0] | ||||||
|  |     delta_y = end[1] - start[1] | ||||||
|  |     distance = ((delta_x ** 2 + delta_y ** 2) ** 0.5) | ||||||
|  |     step_size = 10 | ||||||
|  |     gap_size = 5 | ||||||
|  |  | ||||||
|  |     for i in range(0, int(distance / (step_size + gap_size)), 1): | ||||||
|  |         segment_start = (start[0] + (i * (step_size + gap_size) * delta_x / distance), | ||||||
|  |                          start[1] + (i * (step_size + gap_size) * delta_y / distance)) | ||||||
|  |         segment_end = (segment_start[0] + (step_size * delta_x / distance), | ||||||
|  |                        segment_start[1] + (step_size * delta_y / distance)) | ||||||
|  |         draw.line((segment_start, segment_end), fill=colour, width=thickness) | ||||||
|  |  | ||||||
|  | def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1), style='solid'): | ||||||
|  |     """ | ||||||
|  |     Draws a border at given coordinates with specified styles (solid, dotted, dashed). | ||||||
|  |  | ||||||
|     Args: |     Args: | ||||||
|       - image: The image on which the border should be drawn (usually im_black or |         - image: Image on which the border should be drawn. | ||||||
|         im_colour. |         - xy: Tuple for the top-left corner of the border. | ||||||
|  |         - size: Size of the border as a tuple (width, height). | ||||||
|       - xy: Tuple representing the top-left corner of the border e.g. (32, 100) |         - radius: Radius of the corners. | ||||||
|         where 32 is the x co-ordinate and 100 is the y-coordinate. |         - thickness: Thickness of the border in pixels. | ||||||
|  |         - shrinkage: Tuple for width and height shrinkage percentages. | ||||||
|       - size: Size of the border as a tuple -> (width, height). |         - style: Style of the border ('solid', 'dotted', 'dashed'). | ||||||
|  |  | ||||||
|       - radius: Radius of the corners, where 0 = plain rectangle, 5 = round corners. |  | ||||||
|  |  | ||||||
|       - thickness: Thickness of the border in pixels. |  | ||||||
|  |  | ||||||
|       - shrinkage: A tuple containing decimals presenting a percentage of shrinking |  | ||||||
|         -> (width_shrink_percentage, height_shrink_percentage). |  | ||||||
|         e.g. (0.1, 0.2) ~ shrinks the width of border by 10%, shrinks height of |  | ||||||
|         border by 20% |  | ||||||
|     """ |     """ | ||||||
|  |  | ||||||
|     colour = 'black' |     colour = 'black' | ||||||
|  |  | ||||||
|     # size from function paramter |  | ||||||
|     width, height = int(size[0] * (1 - shrinkage[0])), int(size[1] * (1 - shrinkage[1])) |     width, height = int(size[0] * (1 - shrinkage[0])), int(size[1] * (1 - shrinkage[1])) | ||||||
|  |  | ||||||
|     # shift cursor to move rectangle to center |  | ||||||
|     offset_x, offset_y = int((size[0] - width) / 2), int((size[1] - height) / 2) |     offset_x, offset_y = int((size[0] - width) / 2), int((size[1] - height) / 2) | ||||||
|  |  | ||||||
|     x, y, diameter = xy[0] + offset_x, xy[1] + offset_y, radius * 2 |     x, y, diameter = xy[0] + offset_x, xy[1] + offset_y, radius * 2 | ||||||
|     # lenght of rectangle size |  | ||||||
|     a, b = (width - diameter), (height - diameter) |     a, b = (width - diameter), (height - diameter) | ||||||
|  |  | ||||||
|     # Set coordinates for staright lines |  | ||||||
|     p1, p2 = (x + radius, y), (x + radius + a, y) |     p1, p2 = (x + radius, y), (x + radius + a, y) | ||||||
|     p3, p4 = (x + width, y + radius), (x + width, y + radius + b) |     p3, p4 = (x + width, y + radius), (x + width, y + radius + b) | ||||||
|     p5, p6 = (p2[0], y + height), (p1[0], y + height) |     p5, p6 = (p2[0], y + height), (p1[0], y + height) | ||||||
|     p7, p8 = (x, p4[1]), (x, p3[1]) |     p7, p8 = (x, p4[1]), (x, p3[1]) | ||||||
|  |  | ||||||
|  |     draw = ImageDraw.Draw(image) | ||||||
|  |  | ||||||
|  |     # Choose the appropriate line drawing function based on style | ||||||
|  |     if style == 'solid': | ||||||
|  |         line_drawer = draw.line | ||||||
|  |     elif style == 'dotted': | ||||||
|  |         line_drawer = lambda coords, fill, width: draw_dotted_line(draw, coords[0], coords[1], fill, width) | ||||||
|  |     elif style == 'dashed': | ||||||
|  |         line_drawer = lambda coords, fill, width: draw_dashed_line(draw, coords[0], coords[1], fill, width) | ||||||
|  |     else: | ||||||
|  |         raise ValueError(f"Unknown style: {style}") | ||||||
|  |  | ||||||
|  |     # Draw lines according to the chosen style | ||||||
|  |     line_drawer((p1, p2), fill=colour, width=thickness) | ||||||
|  |     line_drawer((p3, p4), fill=colour, width=thickness) | ||||||
|  |     line_drawer((p5, p6), fill=colour, width=thickness) | ||||||
|  |     line_drawer((p7, p8), fill=colour, width=thickness) | ||||||
|  |  | ||||||
|     if radius != 0: |     if radius != 0: | ||||||
|         # Set coordinates for arcs |  | ||||||
|         c1, c2 = (x, y), (x + diameter, y + diameter) |         c1, c2 = (x, y), (x + diameter, y + diameter) | ||||||
|         c3, c4 = ((x + width) - diameter, y), (x + width, y + diameter) |         c3, c4 = ((x + width) - diameter, y), (x + width, y + diameter) | ||||||
|         c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height) |         c5, c6 = ((x + width) - diameter, (y + height) - diameter), (x + width, y + height) | ||||||
|         c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height) |         c7, c8 = (x, (y + height) - diameter), (x + diameter, y + height) | ||||||
|  |  | ||||||
|     # Draw lines and arcs, creating a square with round corners |  | ||||||
|     draw = ImageDraw.Draw(image) |  | ||||||
|     draw.line((p1, p2), fill=colour, width=thickness) |  | ||||||
|     draw.line((p3, p4), fill=colour, width=thickness) |  | ||||||
|     draw.line((p5, p6), fill=colour, width=thickness) |  | ||||||
|     draw.line((p7, p8), fill=colour, width=thickness) |  | ||||||
|  |  | ||||||
|     if radius != 0: |  | ||||||
|         draw.arc((c1, c2), 180, 270, fill=colour, width=thickness) |         draw.arc((c1, c2), 180, 270, fill=colour, width=thickness) | ||||||
|         draw.arc((c3, c4), 270, 360, fill=colour, width=thickness) |         draw.arc((c3, c4), 270, 360, fill=colour, width=thickness) | ||||||
|         draw.arc((c5, c6), 0, 90, fill=colour, width=thickness) |         draw.arc((c5, c6), 0, 90, fill=colour, width=thickness) | ||||||
|   | |||||||
| @@ -296,14 +296,27 @@ class Calendar(inkycal_module): | |||||||
|             month_events = parser.get_events(month_start, month_end, self.timezone) |             month_events = parser.get_events(month_start, month_end, self.timezone) | ||||||
|             parser.sort() |             parser.sort() | ||||||
|             self.month_events = month_events |             self.month_events = month_events | ||||||
|  |              | ||||||
|  |             # Initialize days_with_events as an empty list | ||||||
|  |             days_with_events = [] | ||||||
|  |  | ||||||
|             # find out on which days of this month events are taking place |             # Handle multi-day events by adding all days between start and end | ||||||
|             days_with_events = [ |             for event in month_events: | ||||||
|                 int(events['begin'].format('D')) for events in month_events |                 start_date = event['begin'].date() | ||||||
|             ] |                 end_date = event['end'].date() | ||||||
|  |  | ||||||
|  |                 # Convert start and end dates to arrow objects with timezone | ||||||
|  |                 start = arrow.get(event['begin'].date(), tzinfo=self.timezone) | ||||||
|  |                 end = arrow.get(event['end'].date(), tzinfo=self.timezone) | ||||||
|  |  | ||||||
|  |                 # Use arrow's range function for generating dates | ||||||
|  |                 for day in arrow.Arrow.range('day', start, end): | ||||||
|  |                     day_num = int(day.format('D'))  # get day number using arrow's format method | ||||||
|  |                     if day_num not in days_with_events: | ||||||
|  |                         days_with_events.append(day_num) | ||||||
|  |  | ||||||
|             # remove duplicates (more than one event in a single day) |             # remove duplicates (more than one event in a single day) | ||||||
|             list(set(days_with_events)).sort() |             days_with_events = sorted(set(days_with_events)) | ||||||
|             self._days_with_events = days_with_events |             self._days_with_events = days_with_events | ||||||
|  |  | ||||||
|             # Draw a border with specified parameters around days with events |             # Draw a border with specified parameters around days with events | ||||||
| @@ -355,7 +368,13 @@ class Calendar(inkycal_module): | |||||||
|                 cursor = 0 |                 cursor = 0 | ||||||
|                 for event in upcoming_events: |                 for event in upcoming_events: | ||||||
|                     if cursor < len(event_lines): |                     if cursor < len(event_lines): | ||||||
|                         the_name = event['title'] |                         event_duration = (event['end'] - event['begin']).days | ||||||
|  |                         if event_duration > 1: | ||||||
|  |                             # Format the duration using Arrow's localization | ||||||
|  |                             days_translation = arrow.get().shift(days=event_duration).humanize(only_distance=True, locale=lang) | ||||||
|  |                             the_name = f"{event['title']} ({days_translation})" | ||||||
|  |                         else: | ||||||
|  |                             the_name = event['title'] | ||||||
|                         the_date = event['begin'].format(self.date_format, locale=lang) |                         the_date = event['begin'].format(self.date_format, locale=lang) | ||||||
|                         the_time = event['begin'].format(self.time_format, locale=lang) |                         the_time = event['begin'].format(self.time_format, locale=lang) | ||||||
|                         # logger.debug(f"name:{the_name}   date:{the_date} time:{the_time}") |                         # logger.debug(f"name:{the_name}   date:{the_date} time:{the_time}") | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user