def add_image(self, state, bb): """ Add image :param state: button state :param bb: bounding box """ if not state.show_img or getattr(state, "icon_base", None) == None: self.add_component(None) return c = Component(self.util) c.name = state.name + ".image" scaled = getattr(state, "scaled", False) enabled = getattr(state, "enabled", True) if not enabled: c.content = state.icon_disabled[1] c.image_filename = state.icon_disabled[0] else: if scaled: c.content = state.icon_base_scaled else: c.content = state.icon_base[1] c.image_filename = state.icon_base[0] w = c.content.get_size()[0] h = c.content.get_size()[1] c.content_x = bb.x + (bb.width - w) / 2 c.content_y = bb.y + (bb.height - h) / 2 self.add_component(c)
def add_image(self, state, bb): """ Add image :param state: button state :param bb: bounding box """ if not state.show_img: self.add_component(None) return c = Component(self.util) c.name = state.name + ".image" scaled = getattr(state, "scaled", False) if scaled: c.content = state.icon_base_scaled else: c.content = state.icon_base[1] c.image_filename = state.icon_base[0] w = c.content.get_size()[0] h = c.content.get_size()[1] c.content_x = bb.x + (bb.width - w)/2 c.content_y = bb.y + (bb.height - h)/2 self.add_component(c)
def add_page(self, page_num, page): """ Add lyrics page to the container :param page_num: lyrics page number :param page: lyrics page """ cont = Container(self.util, self.bounding_box, (0, 0, 0)) max_line_length = self.get_max_line_length(page) s = self.f.size("W") page_height = self.lines * s[1] offset_y = (self.screen_h - page_height) / 2 offset_x = (self.screen_w - max_line_length) / 2 for n, line in enumerate(page): c = Component(self.util, bgr=(0, 0, 0)) str_size = self.f.size(line) if page_num == 0 and n == 0: color = self.config[COLORS][COLOR_BRIGHT] else: color = self.config[COLORS][COLOR_CONTRAST] img = self.f.render(line, 1, color) name = GENERATED_IMAGE + str(n) c.content = (name, img) c.name = name c.image_filename = name c.content_y = offset_y + (str_size[1] * n) c.content_x = offset_x cont.add_component(c) self.add_component(cont)
def draw_tile_header(self, x, y, w, h, fcast): """ Draw tile header :param x: tile x coordinate :param y: tile y coordinate :param w: tile width :param h: tile height :param fcast: one day forecast """ height = (h / 100) * TILE_HEADER_HEIGHT comp = Component(self.util) comp.name = "tile.header." + str(x) + "." + str(y) comp.content_x = x comp.content_y = y rect = pygame.Rect(x, y, w, height) comp.content = rect comp.fgr = self.semi_transparent_color comp.bgr = self.semi_transparent_color comp.bounding_box = rect self.add_component(comp) text_color = self.util.weather_config[COLOR_BRIGHT] font_size = int((height / 100) * DAY_HEIGHT) if fcast[DAY] == UNKNOWN: d = UNKNOWN else: d = self.weather_config[fcast[DAY].lower()] c = self.util.get_text_component(d, text_color, font_size) c.name = "th." + str(x) + "." + str(y) c.content_x = x + (w - c.content.get_size()[0]) / 2 c.content_y = y + font_size / 8 self.add_component(c)
def __init__(self, util, digits, digit, bb, increment_listener, decrement_listener, name): """ Initializer :param util: utility object :param digits: clock digits 0-9 :param digit: the digit :param bb: digit bounding box :param increment_listener: increment listener :param decrement_listener: decrement listener :param name: component name """ self.util = util self.config = self.util.config EventContainer.__init__(self, util, bb) self.digits = digits self.digit = digit image = self.digits[self.digit][1] c = Component(self.util) c.name = name c.image_filename = self.digits[self.digit][0] c.content = image c.content_x = bb.x c.content_y = bb.y self.add_component(c) top = Rect(bb.x, bb.y, bb.w, bb.h / 2) self.add_area_listener((top, increment_listener)) bottom = Rect(bb.x, bb.y + (bb.h / 2) + 1, bb.w, bb.h / 2) self.add_area_listener((bottom, decrement_listener))
def add_key(self, x, y, name, key): """ Add the key indicating current focus position :param x: x coordinate :param y: y coordinate :param name: component name :param key: key image """ size = key[1].get_size() w = size[0] h = size[1] cont = Container(self.util) cont.bgr = cont.fgr = (0, 0, 0, 0) cont.name = name + ".cont" c = Component(self.util) c.name = name c.content = key[1] c.bgr = c.fgr = (0, 0, 0, 0) c.content_x = x - w / 2 c.content_y = y c.image_filename = key[0] c.bounding_box = pygame.Rect(0, 0, w, h) cont.bounding_box = pygame.Rect(c.content_x, c.content_y, w, h) cont.add_component(c) self.add_component(cont) return cont
def get_star_component(self, button): """ Prepare star icon component for marking :param button: button to mark :return: star component """ button_image_comp = button.components[1] button_image_x = button_image_comp.content_x button_image_y = button_image_comp.content_y button_image_size = button_image_comp.content.get_size() button_image_w = button_image_size[0] c = Component(self.util) bb = Rect(0, 0, self.config[SCREEN_INFO][WIDTH], self.config[SCREEN_INFO][HEIGHT]) r = 1 / 25 c.content = self.image_util.load_multi_color_svg_icon( IMAGE_STAR, bb, r) c.bgr = c.fgr = (0, 0, 255) c.name = button.state.l_name + ".fav" img_w = c.content[1].get_size()[0] c.content_x = button_image_x + button_image_w - img_w - 2 c.content_y = button_image_y + 2 return c
def get_clickable_rect(self): """ Return the list of rectangles which define the clickable areas on screen. Used for web browser. :return: list of rectangles """ c = Component(self.util) c.name = "clickable_rect" c.content = self.menu.bounding_box c.bgr = c.fgr = (0, 0, 0) c.content_x = c.content_y = 0 d = [c] return d
def add_background(self, state): """ Add button background bounding box :param state: button state """ if not state.show_bgr: self.add_component(None) return c = Component(self.util) c.name = state.name + ".bgr" c.content = state.bounding_box c.bgr = c.fgr = getattr(state, "bgr", (0, 0, 0)) c.content_x = state.bounding_box.x c.content_y = state.bounding_box.y self.add_component(c)
def add_image(self, image, x, y, rect=None): """ Create new UI component from provided image and add it to the UI container. :param image: the image object :param x: x coordinate of the image top left corner :param y: y coordinate of the image top left corner :param rect: bounding rectangle of the image """ c = Component(self.util) c.content = image c.content_x = x c.content_y = y if rect: c.bounding_box = rect self.add_component(c) return c
def draw_background(self, x, y, w, h): """ Draw background defined by input parameters :param x: x coordinate :param y: y coordinate :param w: width :param h: height """ c = Component(self.util) c.name = "today.bgr" c.content = pygame.Rect(x, y, w, h) c.content_x = x c.content_y = y c.bounding_box = c.content c.bgr = self.semi_transparent_color self.add_component(c)
def get_clickable_rect(self): """ Return the list of rectangles which define the clickable areas on screen. Used for web browser. :return: list of rectangles """ bb = self.screen_title.bounding_box x = 0 y = bb.h w = bb.width h = self.station_menu.bounding_box.height c = Component(self.util) c.name = "clickable_rect" c.content = pygame.Rect(x, y, w, h) c.bgr = c.fgr = (0, 0, 0) c.content_x = c.content_y = 0 d = [c] return d
def draw_weather(self): """ Draw weather forecast """ Container.__init__(self, self.util, self.rect, BLACK) c = Component(self.util) c.name = "forecast.bgr" c.content = self.initial_image c.content_x = 0 c.content_y = 0 c.bounding_box = self.rect self.add_component(c) widths = self.get_widths() heights = self.get_heights() self.draw_tiles(widths, heights)
def draw_separator(self, x, y, w, h): """ Draw tile separator :param x: tile x coordinate :param y: tile y coordinate :param w: tile width :param h: tile height """ height = (h / 100) * TILE_HEADER_HEIGHT comp = Component(self.util) comp.name = "sep." + str(x) + "." + str(y) rect = pygame.Rect(x + w, y + height, 1, h - height + 2) comp.content = rect comp.fgr = self.util.weather_config[COLOR_DARK_LIGHT] comp.bgr = self.util.weather_config[COLOR_DARK_LIGHT] comp.bounding_box = rect self.add_component(comp)
def add_selection(self, state, bb): if not self.selected: return border = 2 c = Component(self.util, t=border) c.name = state.name + ".selection" x = state.bounding_box.x + border / 2 y = state.bounding_box.y + border / 2 w = state.bounding_box.w - border h = state.bounding_box.h - border c.content = pygame.Rect(x, y, w, h) c.bgr = state.text_color_selected c.fgr = (0, 0, 0, 0) c.content_x = state.bounding_box.x c.content_y = state.bounding_box.y self.add_component(c)
def draw_image(self, image, x, y, container, rect, name): """ Draw background defined by input parameters :param image: image to draw :param x: x coordinate :param y: y coordinate :param container: container to which image will be added :param rect: bounding box :param name: component name """ c = Component(self) c.name = name c.content = image c.content_x = rect.x c.content_y = rect.y c.image_filename = c.name c.bounding_box = rect container.add_component(c) return c
def add_background(self, state): """ Add button background bounding box :param state: button state """ if not state.show_bgr: self.add_component(None) return c = Component(self.util) c.name = state.name + ".bgr" c.content = state.bounding_box c.bgr = c.fgr = getattr(state, "bgr", (0, 0, 0)) c.content_x = state.bounding_box.x c.content_y = state.bounding_box.y if len(self.components) > 0: self.components[0] = c else: self.add_component(c)
def get_not_found_screen(self, util): """ Set 'Lyrics not found' message in the current language :param util: utility object :return: component for lyrics not found screen """ c = Component(util, bgr=self.bgr) c.name = "base" self.lyrics_not_found_label = self.config[LABELS][LYRICS_NOT_FOUND] str_size = self.f.size(self.lyrics_not_found_label) self.label_rect = pygame.Rect(0, 0, str_size[0], str_size[1]) img = self.f.render(self.lyrics_not_found_label, 1, self.config[COLORS][COLOR_CONTRAST]) name = GENERATED_IMAGE + "not.found" c.content = (name, img) c.name = name c.image_filename = name return c
def draw_weather(self): """ Draw Today's weather """ Container.__init__(self, self.util, self.rect, BLACK) c = Component(self.util) c.name = "today" c.content = self.initial_image c.content_x = 0 c.content_y = 0 c.bounding_box = self.rect self.add_component(c) top_height = self.draw_top_background() self.draw_bottom_background() self.draw_city(top_height) self.draw_time(top_height) self.draw_code() self.draw_temp() self.draw_high_low() self.draw_details()
def draw_tile_body(self, x, y, w, h, fcast): """ Draw center part of the tile :param x: tile x coordinate :param y: tile y coordinate :param w: tile width :param h: tile height :param fcast: one day forecast """ top_height = (h / 100) * TILE_HEADER_HEIGHT y += top_height h = h - top_height + 1 comp = Component(self.util) comp.name = "tile.body" + str(x) + "." + str(y) comp.content_x = x comp.content_y = y rect = pygame.Rect(x, y, w, h) comp.content = rect comp.fgr = self.util.weather_config[COLOR_BRIGHT] comp.bgr = self.util.weather_config[COLOR_BRIGHT] comp.bounding_box = rect self.add_component(comp)
def __init__(self, items, util, bounding_box, update_parent, callback, default_selection=None): """ Initializer :param items: list of item names :param util: utility object :param bounding_box: bounding box :param update_parent: redraw parent function :param callback: menu selection callback """ Container.__init__(self, util, bounding_box, (0, 0, 0)) self.util = util self.factory = Factory(util) self.config = util.config self.update_parent = update_parent self.callback = callback self.popup = True c = Component(self.util) w = self.config[SCREEN_INFO][WIDTH] h = self.config[SCREEN_INFO][HEIGHT] c.content = pygame.Rect(0, 0, w, h) c.content_x = 0 c.content_y = 0 c.bounding_box = c.content c.bgr = (0, 0, 0, 0) c.name = "popup.overlay.bgr" c.handle_event = self.handle_outside_event self.add_component(c) c = Component(self.util) c.content = pygame.Rect(bounding_box.x, bounding_box.y, bounding_box.w, bounding_box.h - 1) c.content_x = 0 c.content_y = 0 c.bounding_box = c.content c.bgr = self.config[COLORS][COLOR_BRIGHT] c.name = "popup.bgr" self.add_component(c) self.cols = 1 self.rows = len(items) m = self.create_popup_menu_button b = pygame.Rect(bounding_box.x, bounding_box.y, bounding_box.w, bounding_box.h - 2) self.menu = Menu(util, None, b, self.rows, self.cols, create_item_method=m) layout = GridLayout(self.menu.bb) layout.set_pixel_constraints(self.rows, self.cols, 1, 1) bounding_box = layout.get_next_constraints() self.modes = self.util.load_menu(items, NAME, [], V_ALIGN_TOP, bb=bounding_box, scale=IMAGE_SCALE) if not default_selection: selection = self.modes[items[0]] else: selection = self.modes[default_selection] self.menu.set_items(self.modes, 0, self.select_item, False) self.menu.visible = False self.menu.item_selected(selection) self.add_component(self.menu) self.redraw_observer = None self.clicked = False self.visible = False
def __init__(self, util, name, time_key, digits, bb, timer_lock, clock_change_callback, change_codes): """ Initializer :param util: utility object :param name: component name :param time_key: key of the clock time in configuration :param digits: images of the clock digits 0-9 :param bb: clock bounding box :param gap: gap between hours and minutes :param icon_size: size of the button icon size :param timer_lock: lock object :param clock_change_callback: callback function :param change_codes: codes for increment and decrement for hours and minutes """ self.util = util self.name = name self.timer_lock = timer_lock self.clock_change_callback = clock_change_callback self.config = self.util.config Container.__init__(self, util) self.content = None self.clock_bb = bb self.bounding_box = bb.LEFT size = digits[0][1].get_size() self.digit_w = size[0] self.digit_h = size[1] separator = util.image_util.get_flipclock_separator(self.digit_h / 3) self.shift_x = 2 border_x = bb.RIGHT.x self.change_codes = change_codes self.change_listeners = [] r = pygame.Rect(bb.x, bb.y + 1, border_x, bb.h - 1) c = Component(self.util, r, bb=bb) c.name = name + ".bgr" c.bgr = self.config[BACKGROUND][MENU_BGR_COLOR] self.add_component(c) size = separator[1].get_size() w = size[0] h = size[1] c = Component(self.util) c.name = name + ".separator" c.content = separator separator_x = (border_x / 2) - (w / 2) separator_y = bb.y + (bb.h / 2) - (h / 2) c.content_x = separator_x c.content_y = separator_y self.add_component(c) self.time_key = time_key current_time = datetime.now().strftime("%H%M") try: self.time = self.config[TIMER][time_key] except: self.time = current_time if len(self.time.strip()) == 0: self.time = current_time with self.timer_lock: self.config[TIMER][self.time_key] = self.time h1_x = separator_x - (self.digit_w * 2) - w h1_n = name + ".h1" self.h1 = self.add_digit(digits, int(self.time[0]), h1_x, self.increment_hours, self.decrement_hours, h1_n) h2_x = separator_x - self.digit_w - w h2_n = name + ".h2" self.h2 = self.add_digit(digits, int(self.time[1]), h2_x, self.increment_hours, self.decrement_hours, h2_n) m1_x = separator_x + w * 2 m1_n = name + ".m1" self.m1 = self.add_digit(digits, int(self.time[2]), m1_x, self.increment_minutes, self.decrement_minutes, m1_n) m2_x = separator_x + self.digit_w + w * 2 m2_n = name + ".m2" self.m2 = self.add_digit(digits, int(self.time[3]), m2_x, self.increment_minutes, self.decrement_minutes, m2_n) key_height = self.digit_h self.top_image = util.image_util.get_flipclock_key( "key-top.png", key_height) self.bottom_image = util.image_util.get_flipclock_key( "key-bottom.png", key_height) self.top_image_on = util.image_util.get_flipclock_key( "key-top-on.png", key_height) self.bottom_image_on = util.image_util.get_flipclock_key( "key-bottom-on.png", key_height) y = self.clock_bb.y + (self.clock_bb.h / 2) - (self.digit_h / 2) self.h_top = self.add_key(h2_x, y, h2_n + ".top.key", self.top_image) self.m_top = self.add_key(m2_x, y, m2_n + ".top.key", self.top_image) y = self.clock_bb.y + (self.clock_bb.h / 2) - ( self.digit_h / 2) + self.digit_h - self.bottom_image[1].get_size()[1] self.h_bottom = self.add_key(h2_x, y, h2_n + ".bottom.key", self.bottom_image) self.m_bottom = self.add_key(m2_x, y, m2_n + ".bottom.key", self.bottom_image) self.selected_key = None