Package horizons :: Package gui :: Package tabs :: Module tabinterface
[hide private]
[frames] | no frames]

Source Code for Module horizons.gui.tabs.tabinterface

  1  # ################################################### 
  2  # Copyright (C) 2008-2017 The Unknown Horizons Team 
  3  # team@unknown-horizons.org 
  4  # This file is part of Unknown Horizons. 
  5  # 
  6  # Unknown Horizons is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 20  # ################################################### 
 21   
 22  from horizons.extscheduler import ExtScheduler 
 23  from horizons.gui.util import load_uh_widget 
 24  from horizons.util.changelistener import metaChangeListenerDecorator 
 25  from horizons.util.pychanchildfinder import PychanChildFinder 
 26  from horizons.util.python.callback import Callback 
27 28 29 @metaChangeListenerDecorator('remove') 30 -class TabInterface:
31 """ 32 The TabInterface should be used by all classes that represent Tabs for the 33 TabWidget. 34 35 By default the code will the widget from a file given by `widget`. If you 36 want to run code after the widget has been loaded, override `init_widget`. 37 To handle widget loading yourself, override `get_widget` and return the new 38 widget. 39 In both cases the widget is accessible at `self.widget`. 40 41 If you want to override the TabButton image used for the tab, you also have 42 to set the button_image_{up,down,hover} variables. 43 44 Use the refresh() method to implement any redrawing of the widget. The 45 TabWidget will call this method based on callbacks. If you set any callbacks 46 yourself, make sure you get them removed when the widget is deleted. 47 48 @param widget: Filename of widget to load. 49 @param icon_path: Where to look for ImageButton icons. Note: this is a `path` attribute! 50 """ 51 52 # Whether to load the tab only when it's shown. 53 # If True, self.widget will only be valid after _lazy_loading_init, which 54 # is guaranteed to be executed before show(), refresh() and the like. 55 # Usually, you will want to overwrite _lazy_loading_init and call the super impl as first step. 56 # Note: to prevent memory leak due to unshown tabs registered with WidgetManager, always set it 57 # to be true by default 58 # set it false only in its subclass if have special reason to disable lazy_loading 59 lazy_loading = True 60 61 # Override these in your subclass either as class attribute, or by passing it 62 # to the constructor. The value of the constructor has preference over the 63 # class attribute. 64 widget = None # type: str 65 icon_path = 'images/tabwidget/tab' 66 67 scheduled_update_delay = 0.4 # seconds, update after this time when an update is scheduled 68
69 - def __init__(self, widget=None, icon_path=None, **kwargs):
70 """ 71 @param widget: filename of a widget. Set this to None if you create your 72 widget in `get_widget`. 73 """ 74 super().__init__() 75 if widget or self.__class__.widget: 76 self.widget = widget or self.__class__.widget 77 if not self.__class__.lazy_loading: 78 self._setup_widget() 79 else: 80 # set manually by child 81 self.widget = None 82 83 # Regular `image` paths for Icon 84 self.button_background_image = 'content/gui/images/tabwidget/tab_dark.png' 85 self.button_background_image_active = 'content/gui/images/tabwidget/tab_active_xxl.png' 86 87 # `path` attribute for ImageButton, i.e. without 'content/gui/' and '.png' 88 self.path = icon_path or self.__class__.icon_path 89 # the active tab image has no special down or hover images, so this works with `path` too 90 self.path_active = self.path + '_a' 91 92 self._refresh_scheduled = False
93
94 - def _setup_widget(self):
95 """Gets the widget and sets up some attributes and helper. 96 97 This is called when the Tab is created, or, when lazy loading is 98 active once the tab is about to be shown. 99 """ 100 self.widget = self.get_widget() 101 self.widget.child_finder = PychanChildFinder(self.widget) 102 self.init_widget()
103
104 - def get_widget(self):
105 """Loads the filename in self.widget. 106 107 Override this in your subclass if you want to handle widget 108 loading/creation yourself. 109 """ 110 return load_uh_widget(self.widget)
111
112 - def init_widget(self):
113 """Initialize widget after it was loaded. 114 115 Override this in your subclass if you have custom post-load code. 116 """ 117 pass
118
119 - def show(self):
120 """Shows the current widget""" 121 self.ensure_loaded() 122 self.widget.show()
123
124 - def hide(self):
125 """Hides the current widget""" 126 self.ensure_loaded() 127 self.widget.hide() 128 129 if self._refresh_scheduled: 130 ExtScheduler().rem_all_classinst_calls(self) 131 self._refresh_scheduled = False
132
133 - def is_visible(self):
134 self.ensure_loaded() 135 # naming convention clash: python vs c++ 136 return self.widget.isVisible()
137
138 - def refresh(self):
139 """This function is called by the TabWidget to redraw the widget.""" 140 pass
141
142 - def _schedule_refresh(self):
143 """Schedule a refresh soon, dropping all other refresh request, that appear until then. 144 This saves a lot of CPU time, if you have a huge island, or play on high speed.""" 145 if not self._refresh_scheduled: 146 self._refresh_scheduled = True 147 def unset_flag(): 148 # set the flag here and not in refresh() since we can't be sure whether 149 # refresh() of this class will be reached or a subclass will not call super() 150 self._refresh_scheduled = False
151 ExtScheduler().add_new_object(Callback.ChainedCallbacks(unset_flag, self.refresh), 152 self, run_in=self.__class__.scheduled_update_delay)
153 154 @classmethod
155 - def shown_for(cls, instance):
156 """Method for fine-grained control of which tabs to show. 157 @return: whether this tab should really be shown for this instance""" 158 return True
159
160 - def ensure_loaded(self):
161 """Called when a tab is shown, acts as hook for lazy loading""" 162 if self.__class__.lazy_loading and not hasattr(self, "_lazy_loading_loaded"): 163 self._setup_widget() 164 self._lazy_loading_loaded = True # this is to prevent more setups if called multiple times
165
166 - def _get_position(self):
167 self.ensure_loaded() 168 return self.widget.position
169
170 - def _set_position(self, value):
171 """Sets the widgets position to tuple *value*""" 172 self.ensure_loaded() 173 self.widget.position = value
174 175 # Shortcut to set and retrieve the widget's current position. 176 position = property(_get_position, _set_position) 177