def show_tooltip(self): if not self.helptext: return # recreate full tooltip since new text needs to be relayouted if self.gui is None: self.gui = load_uh_widget('tooltip.xml') else: self.gui.removeAllChildren() translated_tooltip = _(self.helptext) #HACK this looks better than splitting into several lines & joining # them. works because replace_whitespace in fill defaults to True: replaced = translated_tooltip.replace(r'\n', self.CHARS_PER_LINE*' ') replaced = replaced.replace(r'[br]', self.CHARS_PER_LINE*' ') tooltip = textwrap.fill(replaced, self.CHARS_PER_LINE) line_count = len(tooltip.splitlines()) - 1 top_image = Icon(image=self.TOP_IMAGE, position=(0, 0)) self.gui.addChild(top_image) top_x, top_y = top_image.position top_y += self.SIZE_BG_TOP for i in xrange(0, line_count): middle_image = Icon(image=self.MIDDLE_IMAGE) middle_image.position = (top_x, top_y + self.LINE_HEIGHT * i) self.gui.addChild(middle_image) bottom_image = Icon(image=self.BOTTOM_IMAGE) bottom_image.position = (top_x, top_y + self.LINE_HEIGHT * line_count) self.gui.addChild(bottom_image) label = Label(text=tooltip, position=(10, 5)) self.gui.addChild(label) self.gui.stylize('tooltip') size_y = self.SIZE_BG_TOP + self.LINE_HEIGHT * line_count + self.SIZE_BG_BOTTOM self.gui.size = (145, size_y) self.gui.show()
def show_tooltip(self): if not self.helptext: return # recreate full tooltip since new text needs to be relayouted if self.gui is None: self.gui = load_uh_widget('tooltip.xml') else: self.gui.removeAllChildren() translated_tooltip = _(self.helptext) #HACK this looks better than splitting into several lines & joining # them. works because replace_whitespace in fill defaults to True: replaced = translated_tooltip.replace(r'\n', self.CHARS_PER_LINE * ' ') replaced = replaced.replace('[br]', self.CHARS_PER_LINE * ' ') tooltip = textwrap.fill(replaced, self.CHARS_PER_LINE) line_count = len(tooltip.splitlines()) - 1 top_image = Icon(image=self.TOP_IMAGE, position=(0, 0)) self.gui.addChild(top_image) top_x, top_y = top_image.position top_y += self.SIZE_BG_TOP for i in xrange(0, line_count): middle_image = Icon(image=self.MIDDLE_IMAGE) middle_image.position = (top_x, top_y + self.LINE_HEIGHT * i) self.gui.addChild(middle_image) bottom_image = Icon(image=self.BOTTOM_IMAGE) bottom_image.position = (top_x, top_y + self.LINE_HEIGHT * line_count) self.gui.addChild(bottom_image) label = Label(text=tooltip, position=(10, 5)) self.gui.addChild(label) self.gui.stylize('tooltip') size_y = self.SIZE_BG_TOP + self.LINE_HEIGHT * line_count + self.SIZE_BG_BOTTOM self.gui.size = (145, size_y) self.gui.show()
def _draw_pretty_arrows(self, parent_container, amount, x=0, y=0, out=False): """Draws incoming or outgoing arrows for production line container.""" if amount % 2: # Add center arrow for 1, 3, 5, ... but not 2, 4, ... if out: mid_arrow = Icon(image=self.__class__.ARROWHEAD_MID) else: mid_arrow = Icon(image=self.__class__.ARROW_MID) mid_arrow.position = (x, 17 + y) parent_container.insertChild(mid_arrow, 0) for res in xrange(amount // 2): # --\ <= placed for res = 1 # --\| <= place connector <= placed for res = 0 # ---O--> <= placed above (mid_arrow) # --/| <= place connector <= placed for res = 0 # --/ <= placed for res = 1 offset = -17 + (self.ICON_HEIGHT // 2) * (2 * res + (amount % 2) + 1) if out: top_arrow = Icon(image=self.__class__.ARROWHEAD_TOP) else: top_arrow = Icon(image=self.__class__.ARROW_TOP) top_arrow.position = (x, y - offset) parent_container.insertChild(top_arrow, 0) if out: bottom_arrow = Icon(image=self.__class__.ARROWHEAD_BOTTOM) else: bottom_arrow = Icon(image=self.__class__.ARROW_BOTTOM) bottom_arrow.position = (x, y + offset) parent_container.insertChild(bottom_arrow, 0) # Place a connector image (the | in above sketch) that vertically connects # the input resource arrows. We need those if the production line has more # than three input resources. Connectors are placed in the inner loop parts. place_connectors = amount > (3 + 2 * res) if place_connectors: # the connector downwards connects top_arrows if out: down_connector = Icon(image=self.__class__.ARROWHEAD_CONNECT_DOWN) else: down_connector = Icon(image=self.__class__.ARROW_CONNECT_DOWN) down_connector.position = (98, y - offset) parent_container.insertChild(down_connector, 0) # the connector upwards connects up_arrows if out: up_connector = Icon(image=self.__class__.ARROWHEAD_CONNECT_UP) else: up_connector = Icon(image=self.__class__.ARROW_CONNECT_UP) up_connector.position = (98, y + offset) parent_container.insertChild(up_connector, 0)
def _connect_multiple_input_res_for_production(self, centered_container, container, production): """Draws incoming arrows for production line container.""" input_amount = len(production.get_consumed_resources()) if input_amount == 0: # Do not draw input arrows if there is no input return # center the production line icon_height = ImageFillStatusButton.CELL_SIZE[ 1] + ImageFillStatusButton.PADDING center_y = (icon_height // 2) * (input_amount - 1) centered_container.position = (0, center_y) if input_amount % 2: # Add center arrow for 1, 3, 5, ... but not 2, 4, ... mid_arrow = Icon(image=self.__class__.ARROW_MID) mid_arrow.position = (58, 17 + center_y) container.insertChild(mid_arrow, 0) for res in xrange(input_amount // 2): # --\ <= placed for res = 1 # --\| <= place connector <= placed for res = 0 # ---O--> <= placed above # --/| <= place connector <= placed for res = 0 # --/ <= placed for res = 1 offset = -17 + (icon_height // 2) * (2 * res + (input_amount % 2) + 1) top_arrow = Icon(image=self.__class__.ARROW_TOP) top_arrow.position = (58, center_y - offset) container.insertChild(top_arrow, 0) bottom_arrow = Icon(image=self.__class__.ARROW_BOTTOM) bottom_arrow.position = (58, center_y + offset) container.insertChild(bottom_arrow, 0) # Place a connector image (the | in above sketch) that vertically connects # the input resource arrows. We need those if the production line has more # than three input resources. Connectors are placed in the inner loop parts. place_connectors = (1 + 2 * res) < (input_amount // 2) if place_connectors: # the connector downwards connects top_arrows down_connector = Icon(image=self.__class__.ARROW_CONNECT_DOWN) down_connector.position = (98, center_y - offset) container.insertChild(down_connector, 0) # the connector upwards connects up_arrows up_connector = Icon(image=self.__class__.ARROW_CONNECT_UP) up_connector.position = (98, center_y + offset) container.insertChild(up_connector, 0)
def refresh(self): """This function is called by the TabWidget to redraw the widget.""" self._refresh_utilisation() # remove old production line data parent_container = self.widget.child_finder('production_lines') while parent_container.children: child = parent_container.children[-1] if hasattr(child, "anim"): child.anim.stop() del child.anim parent_container.removeChild( child ) # create a container for each production # sort by production line id to have a consistent (basically arbitrary) order for production in self.get_displayed_productions(): # we need to be notified of small production changes # that aren't passed through the instance production.add_change_listener(self._schedule_refresh, no_duplicates=True) gui = load_uh_widget(self.production_line_gui_xml) # fill in values to gui reflecting the current game state container = gui.findChild(name="production_line_container") self._set_resource_amounts(container, production) if production.is_paused(): container.removeChild( container.findChild(name="toggle_active_active") ) toggle_icon = container.findChild(name="toggle_active_inactive") toggle_icon.name = "toggle_active" else: container.removeChild( container.findChild(name="toggle_active_inactive") ) toggle_icon = container.findChild(name="toggle_active_active") toggle_icon.name = "toggle_active" if production.get_state() == PRODUCTION.STATES.producing: bg = Icon(image=self.__class__.BUTTON_BACKGROUND) bg.position = toggle_icon.position container.addChild(bg) container.removeChild(toggle_icon) # fix z-ordering container.addChild(toggle_icon) anim = PychanAnimation(toggle_icon, self.__class__.ACTIVE_PRODUCTION_ANIM_DIR) container.anim = anim anim.start(1.0/12, -1) # always start anew, people won't notice self._animations.append( weakref.ref( anim ) ) # fill it with input and output resources in_res_container = container.findChild(name="input_res") self._add_resource_icons(in_res_container, production.get_consumed_resources(), marker=True) out_res_container = container.findChild(name="output_res") self._add_resource_icons(out_res_container, production.get_produced_resources()) # active toggle_active button toggle_active = ToggleActive(self.instance.get_component(Producer), production) container.mapEvents({ 'toggle_active': Callback(toggle_active.execute, self.instance.session) }) # NOTE: this command causes a refresh, so we needn't change the toggle_active-button-image container.stylize('menu_black') parent_container.addChild(container) super(ProductionOverviewTab, self).refresh()
def _draw(self): """Draws the icon + bar.""" # hash buttons by creation function call # NOTE: there may be problems with multiple buttons with the same # images and helptext at the same time create_btn = Callback(ImageButton, path=self.path, helptext=self.helptext) self.button = None if self.uncached: self.button = create_btn() else: self.button = self.__widget_cache.get(create_btn, None) if self.button is None: # create button self.__widget_cache[create_btn] = self.button = create_btn() else: # disconnect button from earlier layout if self.button.parent: self.button.parent.removeChild(self.button) # can't cache the other instances, because we need multiple instances # with the same data active at the same time self.label = Label(text=self.text) self.label.position = self.text_position self.fill_bar = Icon(image="content/gui/images/tabwidget/green_line.png") fill_level = (self.button.height * self.filled) // 100 self.fill_bar.size = ((2 * self.fill_bar.size[0]) // 3, fill_level) # move fillbar down after resizing, since its origin is top aligned self.fill_bar.position = (self.button.width, self.button.height - fill_level) self.addChildren(self.button, self.fill_bar, self.label) if self.marker > 0: marker_icon = Icon(image="content/gui/icons/templates/production/marker.png") marker_level = (self.button.height * self.marker) // 100 marker_icon.position = (self.button.width - 1, self.button.height - marker_level) marker_icon.max_size = (5, 1) self.addChild(marker_icon)
def _connect_input_res(self, centered_container, container, production): """Draws incoming arrows for production line container.""" input_amount = len(production.get_consumed_resources()) if input_amount == 0: # Do not draw input arrows if there is no input return # center the production line icon_height = ImageFillStatusButton.CELL_SIZE[1] + ImageFillStatusButton.PADDING center_y = (icon_height // 2) * (input_amount - 1) centered_container.position = (0, center_y) if input_amount % 2: # Add center arrow for 1, 3, 5, ... but not 2, 4, ... mid_arrow = Icon(image=self.__class__.ARROW_MID) mid_arrow.position = (58, 17 + center_y) container.insertChild(mid_arrow, 0) for res in xrange(input_amount // 2): # --\ <= placed for res = 1 # --\| <= place connector <= placed for res = 0 # ---O--> <= placed above (mid_arrow) # --/| <= place connector <= placed for res = 0 # --/ <= placed for res = 1 offset = -17 + (icon_height // 2) * (2 * res + (input_amount % 2) + 1) top_arrow = Icon(image=self.__class__.ARROW_TOP) top_arrow.position = (58, center_y - offset) container.insertChild(top_arrow, 0) bottom_arrow = Icon(image=self.__class__.ARROW_BOTTOM) bottom_arrow.position = (58, center_y + offset) container.insertChild(bottom_arrow, 0) # Place a connector image (the | in above sketch) that vertically connects # the input resource arrows. We need those if the production line has more # than three input resources. Connectors are placed in the inner loop parts. place_connectors = (1 + 2 * res) < (input_amount // 2) if place_connectors: # the connector downwards connects top_arrows down_connector = Icon(image=self.__class__.ARROW_CONNECT_DOWN) down_connector.position = (98, center_y - offset) container.insertChild(down_connector, 0) # the connector upwards connects up_arrows up_connector = Icon(image=self.__class__.ARROW_CONNECT_UP) up_connector.position = (98, center_y + offset) container.insertChild(up_connector, 0)
def refresh(self): """This function is called by the TabWidget to redraw the widget.""" self._refresh_utilization() # remove old production line data parent_container = self.widget.child_finder('production_lines') while parent_container.children: child = parent_container.children[-1] if hasattr(child, "anim"): child.anim.stop() del child.anim parent_container.removeChild(child) # create a container for each production # sort by production line id to have a consistent (basically arbitrary) order for production in self.get_displayed_productions(): # we need to be notified of small production changes # that aren't passed through the instance production.add_change_listener(self._schedule_refresh, no_duplicates=True) gui = load_uh_widget(self.production_line_gui_xml) # fill in values to gui reflecting the current game state container = gui.findChild(name="production_line_container") centered_container = container.findChild(name='centered_production_icons') center_y = self._center_production_line(container, production) centered_container.position = (centered_container.position[0], center_y - 44 // 2) self._set_resource_amounts(container, production) if production.is_paused(): centered_container.removeChild(centered_container.findChild(name="toggle_active_active")) toggle_icon = centered_container.findChild(name="toggle_active_inactive") toggle_icon.name = "toggle_active" else: centered_container.removeChild(centered_container.findChild(name="toggle_active_inactive")) toggle_icon = centered_container.findChild(name="toggle_active_active") toggle_icon.name = "toggle_active" if production.get_state() == PRODUCTION.STATES.producing: bg = Icon(image=self.__class__.BUTTON_BACKGROUND) bg.position = toggle_icon.position centered_container.addChild(bg) centered_container.removeChild(toggle_icon) # fix z-ordering centered_container.addChild(toggle_icon) anim = PychanAnimation(toggle_icon, self.__class__.ACTIVE_PRODUCTION_ANIM_DIR) centered_container.anim = anim anim.start(1.0/12, -1) # always start anew, people won't notice self._animations.append(weakref.ref(anim)) # fill it with input and output resources in_res_container = container.findChild(name="input_res") self._add_resource_icons(in_res_container, production.get_consumed_resources(), marker=True) out_res_container = container.findChild(name="output_res") self._add_resource_icons(out_res_container, production.get_produced_resources()) # active toggle_active button toggle_active = ToggleActive(self.instance.get_component(Producer), production) centered_container.mapEvents({ 'toggle_active': Callback(toggle_active.execute, self.instance.session) }) # NOTE: this command causes a refresh, so we needn't change the toggle_active-button-image parent_container.addChild(container) super(ProductionOverviewTab, self).refresh()