Mercurial > fife-parpg
comparison clients/editor/plugins/LayerTool.py @ 255:51cc05d862f2
Merged editor_rewrite branch to trunk.
This contains changes that may break compatibility against existing clients.
For a list of changes that may affect your client, see: http://wiki.fifengine.de/Changes_to_pychan_and_FIFE_in_editor_rewrite_branch
author | cheesesucker@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 08 Jun 2009 16:00:02 +0000 |
parents | |
children | 07709bffab8f |
comparison
equal
deleted
inserted
replaced
254:10b5f7f36dd4 | 255:51cc05d862f2 |
---|---|
1 #!/usr/bin/env python | |
2 # coding: utf-8 | |
3 # ################################################### | |
4 # Copyright (C) 2008 The Zero-Projekt team | |
5 # http://zero-projekt.net | |
6 # info@zero-projekt.net | |
7 # This file is part of Zero "Was vom Morgen blieb" | |
8 # | |
9 # The Zero-Projekt codebase is free software; you can redistribute it and/or modify | |
10 # it under the terms of the GNU General Public License as published by | |
11 # the Free Software Foundation; either version 2 of the License, or | |
12 # (at your option) any later version. | |
13 # | |
14 # This program is distributed in the hope that it will be useful, | |
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 # GNU General Public License for more details. | |
18 # | |
19 # You should have received a copy of the GNU General Public License | |
20 # along with this program; if not, write to the | |
21 # Free Software Foundation, Inc., | |
22 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
23 # ################################################### | |
24 | |
25 """ An advanced layer tool for FIFedit """ | |
26 | |
27 import fife | |
28 import scripts.plugin as plugin | |
29 import scripts.editor | |
30 from scripts.events import * | |
31 from scripts.gui.action import Action | |
32 import pychan | |
33 import pychan.widgets as widgets | |
34 from pychan.tools import callbackWithArguments as cbwa | |
35 | |
36 # default should be pychan default, highlight can be choosen (format: r,g,b) | |
37 _DEFAULT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['base_color'] | |
38 _HIGHLIGHT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['selection_color'] | |
39 | |
40 # the dynamicly created widgets have the name scheme prefix + layerid | |
41 _LABEL_NAME_PREFIX = "select_" | |
42 | |
43 class LayerTool(plugin.Plugin): | |
44 """ The B{LayerTool} is an advanced method to view | |
45 and change layer informations. | |
46 | |
47 While the original FIFedit tool only allows to select | |
48 layers, this one will provide the following functionality: | |
49 | |
50 - toggle layer visibility | |
51 - select layer | |
52 - list layers | |
53 | |
54 """ | |
55 def __init__(self): | |
56 self._editor = None | |
57 self._enabled = False | |
58 self._mapview = None | |
59 | |
60 self._showAction = None | |
61 | |
62 self.subwrappers = [] | |
63 | |
64 #--- Plugin function ---# | |
65 def enable(self): | |
66 if self._enabled is True: | |
67 return | |
68 | |
69 # Fifedit plugin data | |
70 self._editor = scripts.editor.getEditor() | |
71 self._showAction = Action(u"LayerTool", checkable=True) | |
72 scripts.gui.action.activated.connect(self.toggle, sender=self._showAction) | |
73 self._editor._toolsMenu.addAction(self._showAction) | |
74 | |
75 self.__create_gui() | |
76 | |
77 self.toggle() | |
78 | |
79 events.postMapShown.connect(self.update) | |
80 | |
81 def disable(self): | |
82 if self._enabled is False: | |
83 return | |
84 self.container.setDocked(False) | |
85 self.container.hide() | |
86 self.removeAllChildren() | |
87 | |
88 events.postMapShown.disconnect(self.update) | |
89 | |
90 self._editor._toolsMenu.removeAction(self._showAction) | |
91 | |
92 def isEnabled(self): | |
93 return self._enabled; | |
94 | |
95 def getName(self): | |
96 return u"Layertool" | |
97 | |
98 #--- End plugin functions ---# | |
99 | |
100 def __create_gui(self): | |
101 """ create the basic gui container """ | |
102 self.container = pychan.loadXML('gui/layertool.xml') | |
103 self.wrapper = self.container.findChild(name="layers_wrapper") | |
104 self.update(None) | |
105 | |
106 def _adjust_position(self): | |
107 """ adjusts the position of the container - we don't want to | |
108 let the window appear at the center of the screen. | |
109 (new default position: left, beneath the tools window) | |
110 """ | |
111 self.container.position = (50, 200) | |
112 | |
113 def clear(self): | |
114 """ remove all subwrappers """ | |
115 if self.subwrappers is []: return | |
116 | |
117 for subwrapper in self.subwrappers: | |
118 self.wrapper.removeChild(subwrapper) | |
119 | |
120 self.subwrappers = [] | |
121 | |
122 def update(self, mapview): | |
123 """ Dump new layer informations into the wrapper | |
124 | |
125 We group one ToggleButton and one Label into a HBox, the main wrapper | |
126 itself is a VBox and we also capture both the Button and the Label to listen | |
127 for mouse actions | |
128 """ | |
129 layers = [] | |
130 self._mapview = mapview | |
131 if self._mapview is not None: | |
132 layers = self._mapview.getMap().getLayers() | |
133 | |
134 self.clear() | |
135 | |
136 if len(layers) <= 0: | |
137 layerid = "No layers" | |
138 subwrapper = pychan.widgets.HBox() | |
139 | |
140 layer_name_widget = pychan.widgets.Label() | |
141 layer_name_widget.text = unicode(layerid) | |
142 layer_name_widget.name = _LABEL_NAME_PREFIX + layerid | |
143 subwrapper.addChild(layer_name_widget) | |
144 | |
145 self.wrapper.addChild(subwrapper) | |
146 self.subwrappers.append(subwrapper) | |
147 | |
148 active_layer = self.getActiveLayer() | |
149 if active_layer: | |
150 active_layer = active_layer.getId() | |
151 for layer in reversed(layers): | |
152 layerid = layer.getId() | |
153 subwrapper = pychan.widgets.HBox() | |
154 | |
155 visibility_widget = pychan.widgets.ToggleButton(hexpand=0, up_image="gui/icons/is_visible.png", down_image="gui/icons/is_visible.png", hover_image="gui/icons/is_visible.png") | |
156 visibility_widget.name = "toggle_" + layerid | |
157 if layer.areInstancesVisible(): | |
158 visibility_widget.toggled = True | |
159 visibility_widget.capture(self.toggle_layer_visibility,"mousePressed") | |
160 | |
161 layer_name_widget = pychan.widgets.Label() | |
162 layer_name_widget.text = unicode(layerid) | |
163 layer_name_widget.name = _LABEL_NAME_PREFIX + layerid | |
164 layer_name_widget.capture(self.select_active_layer,"mousePressed") | |
165 | |
166 if active_layer == layerid: | |
167 layer_name_widget.background_color = _HIGHLIGHT_BACKGROUND_COLOR | |
168 layer_name_widget.foreground_color = _HIGHLIGHT_BACKGROUND_COLOR | |
169 layer_name_widget.base_color = _HIGHLIGHT_BACKGROUND_COLOR | |
170 | |
171 subwrapper.addChild(visibility_widget) | |
172 subwrapper.addChild(layer_name_widget) | |
173 | |
174 self.wrapper.addChild(subwrapper) | |
175 self.subwrappers.append(subwrapper) | |
176 | |
177 self.container.adaptLayout() | |
178 | |
179 def toggle_layer_visibility(self, event, widget): | |
180 """ Callback for ToggleButtons | |
181 | |
182 Toggle the chosen layer visible / invisible | |
183 | |
184 NOTE: | |
185 - if a layer is set to invisible, it also shouldn't be the active layer anymore | |
186 | |
187 @type event: object | |
188 @param event: pychan mouse event | |
189 @type widget: object | |
190 @param widget: the pychan widget where the event occurs, transports the layer id in it's name | |
191 """ | |
192 | |
193 layerid = widget.name[len(_LABEL_NAME_PREFIX):] | |
194 | |
195 layer = self._mapview.getMap().getLayer(layerid) | |
196 active_layer = self.getActiveLayer() | |
197 if active_layer: | |
198 active_layer = active_layer.getId() | |
199 | |
200 if layer.areInstancesVisible(): | |
201 layer.setInstancesVisible(False) | |
202 else: | |
203 layer.setInstancesVisible(True) | |
204 | |
205 if active_layer == layerid: | |
206 self.select_no_layer() | |
207 | |
208 | |
209 def select_no_layer(self): | |
210 """ the exception approach - as soon as the user hides a layer, the mapedit module should stop to use this | |
211 one, too. | |
212 | |
213 A bunch of exceptions is the result (each click on the map will result in a exception as no layer is set etc...) | |
214 """ | |
215 previous_active_layer = self.getActiveLayer() | |
216 if previous_active_layer is not None: | |
217 previous_layer_id = previous_active_layer.getId() | |
218 previous_active_widget = self.container.findChild(name=_LABEL_NAME_PREFIX + previous_layer_id) | |
219 previous_active_widget.background_color = _DEFAULT_BACKGROUND_COLOR | |
220 previous_active_widget.foreground_color = _DEFAULT_BACKGROUND_COLOR | |
221 previous_active_widget.base_color = _DEFAULT_BACKGROUND_COLOR | |
222 previous_active_widget.text = unicode(previous_layer_id) | |
223 | |
224 self._mapview.getController().selectLayer(None) | |
225 | |
226 def getActiveLayer(self): | |
227 """ Returns the active layer """ | |
228 if self._mapview: | |
229 return self._mapview.getController()._layer | |
230 | |
231 def select_active_layer(self, event, widget): | |
232 """ callback for Labels | |
233 | |
234 We hand the layerid over to the mapeditor module to select a | |
235 new active layer | |
236 | |
237 Additionally, we mark the active layer widget (changing base color) and reseting the previous one | |
238 | |
239 @type event: object | |
240 @param event: pychan mouse event | |
241 @type widget: object | |
242 @param widget: the pychan widget where the event occurs, transports the layer id in it's name | |
243 """ | |
244 | |
245 self.select_no_layer() | |
246 | |
247 layerid = widget.name[7:] | |
248 | |
249 widget.background_color = _HIGHLIGHT_BACKGROUND_COLOR | |
250 widget.foreground_color = _HIGHLIGHT_BACKGROUND_COLOR | |
251 widget.base_color = _HIGHLIGHT_BACKGROUND_COLOR | |
252 self.container.adaptLayout() | |
253 | |
254 self._mapview.getController().selectLayer(layerid) | |
255 | |
256 def toggle(self): | |
257 if self.container.isVisible() or self.container.isDocked(): | |
258 self.container.setDocked(False) | |
259 self.container.hide() | |
260 | |
261 self._showAction.setChecked(False) | |
262 else: | |
263 self.container.show() | |
264 self._showAction.setChecked(True) | |
265 self._adjust_position() |