comparison tools/editor/plugins/LayerTool.py @ 378:64738befdf3b

bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Mon, 11 Jan 2010 23:34:52 +0000
parents
children 9d94f4676d17
comparison
equal deleted inserted replaced
377:fe6fb0e0ed23 378:64738befdf3b
1 # -*- coding: utf-8 -*-
2
3 # ####################################################################
4 # Copyright (C) 2005-2009 by the FIFE team
5 # http://www.fifengine.de
6 # This file is part of FIFE.
7 #
8 # FIFE is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the
20 # Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # ####################################################################
23
24 """ A layer tool for FIFedit """
25
26 from fife import fife
27 from fife.extensions import pychan
28 import fife.extensions.pychan.widgets as widgets
29 from fife.extensions.pychan.tools import callbackWithArguments as cbwa
30
31 import scripts.plugin as plugin
32 import scripts.editor
33 from scripts.events import *
34 from scripts.gui.action import Action
35 from scripts.gui.layerdialog import LayerDialog
36
37 class LayerTool(plugin.Plugin):
38 """ The B{LayerTool} allows to select and show / hide layers of a loaded
39 map as well as creating new layers or edit layer properties
40 """
41
42 # default should be pychan default, highlight can be choosen (format: r,g,b)
43 DEFAULT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['base_color']
44 HIGHLIGHT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['selection_color']
45
46 # the dynamicly created widgets have the name scheme prefix + layerid
47 LABEL_NAME_PREFIX = "select_"
48
49 def __init__(self):
50 # Editor instance
51 self._editor = None
52
53 # Plugin variables
54 self._enabled = False
55
56 # Current mapview
57 self._mapview = None
58
59 # Toolbar button to display LayerTool
60 self._action_show = None
61
62 # GUI
63 self._layer_wizard = None
64 self._container = None
65 self._wrapper = None
66 self._remove_layer_button = None
67 self._create_layer_button = None
68 self._edit_layer_button = None
69
70 #--- Plugin functions ---#
71 def enable(self):
72 """ Enable plugin """
73 if self._enabled is True:
74 return
75
76 # Fifedit plugin data
77 self._editor = scripts.editor.getEditor()
78 self._action_show = Action(u"LayerTool", checkable=True)
79 scripts.gui.action.activated.connect(self.toggle, sender=self._action_show)
80 self._editor._tools_menu.addAction(self._action_show)
81
82 self._createGui()
83
84 self.toggle()
85
86 events.postMapShown.connect(self.update)
87 events.preMapClosed.connect(self._mapClosed)
88
89 def disable(self):
90 """ Disable plugin """
91 if self._enabled is False:
92 return
93 self._container.setDocked(False)
94 self._container.hide()
95
96 events.postMapShown.disconnect(self.update)
97 events.preMapClosed.disconnect(self._mapClosed)
98
99 self._editor._tools_menu.removeAction(self._action_show)
100
101 def isEnabled(self):
102 """ Returns True if plugin is enabled """
103 return self._enabled;
104
105 def getName(self):
106 """ Return plugin name """
107 return u"Layertool"
108
109 #--- End plugin functions ---#
110 def _mapClosed(self):
111 self.update(mapview=None)
112
113
114 def showLayerWizard(self):
115 """ Show layer wizard """
116 if not self._mapview: return
117
118 if self._layer_wizard: self._layer_wizard._widget.hide()
119 self._layer_wizard = LayerDialog(self._editor.getEngine(), self._mapview.getMap(), callback=self._layerCreated)
120
121 def showEditDialog(self):
122 """ Show layerdialog for active layer """
123 if not self._mapview: return
124 layer = self.getActiveLayer()
125 if not layer: return
126
127 if self._layer_wizard: self._layer_wizard._widget.hide()
128 self._layer_wizard = LayerDialog(self._editor.getEngine(), self._mapview.getMap(), layer=layer, callback=cbwa(self.update, self._mapview))
129
130 def clear(self):
131 """ Remove all subwrappers """
132 self._wrapper.removeAllChildren()
133
134 def update(self, mapview):
135 """ Update layertool with information from mapview
136
137 We group one ToggleButton and one Label into a HBox, the main wrapper
138 itself is a VBox and we also capture both the Button and the Label to listen
139 for mouse actions
140
141 @type event: object
142 @param event: pychan mouse event
143 """
144 layers = []
145 self._mapview = mapview
146 if self._mapview is not None:
147 layers = self._mapview.getMap().getLayers()
148
149 self.clear()
150
151 if len(layers) <= 0:
152 if not self._mapview:
153 layerid = "No map is open"
154 else:
155 layerid = "No layers"
156 subwrapper = pychan.widgets.HBox()
157
158 layerLabel = pychan.widgets.Label()
159 layerLabel.text = unicode(layerid)
160 layerLabel.name = LayerTool.LABEL_NAME_PREFIX + layerid
161 subwrapper.addChild(layerLabel)
162
163 self._wrapper.addChild(subwrapper)
164
165 active_layer = self.getActiveLayer()
166 if active_layer:
167 active_layer = active_layer.getId()
168 for layer in reversed(layers):
169 layerid = layer.getId()
170 subwrapper = pychan.widgets.HBox()
171
172 toggleVisibleButton = 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")
173 toggleVisibleButton.name = "toggle_" + layerid
174 if layer.areInstancesVisible():
175 toggleVisibleButton.toggled = True
176 toggleVisibleButton.capture(self.toggleLayerVisibility)
177
178 layerLabel = pychan.widgets.Label()
179 layerLabel.text = unicode(layerid)
180 layerLabel.name = LayerTool.LABEL_NAME_PREFIX + layerid
181 layerLabel.capture(self.selectLayer,"mousePressed")
182
183 if active_layer == layerid:
184 layerLabel.background_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
185 layerLabel.foreground_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
186 layerLabel.base_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
187
188 subwrapper.addChild(toggleVisibleButton)
189 subwrapper.addChild(layerLabel)
190
191 self._wrapper.addChild(subwrapper)
192
193 self._container.adaptLayout()
194
195 def toggleLayerVisibility(self, event, widget):
196 """ Callback for ToggleButtons
197
198 Toggle the chosen layer visible / invisible. If the active layer is hidden,
199 it will be deselected.
200
201 @type event: object
202 @param event: pychan mouse event
203 @type widget: object
204 @param widget: the pychan widget where the event occurs, transports the layer id in it's name
205 """
206
207 layerid = widget.name[len(LayerTool.LABEL_NAME_PREFIX):]
208
209 layer = self._mapview.getMap().getLayer(layerid)
210 active_layer = self.getActiveLayer()
211 if active_layer:
212 active_layer = active_layer.getId()
213
214 if layer.areInstancesVisible():
215 layer.setInstancesVisible(False)
216 else:
217 layer.setInstancesVisible(True)
218
219 if active_layer == layerid:
220 self.resetSelection()
221
222 def getActiveLayer(self):
223 """ Returns the active layer """
224 if self._mapview:
225 return self._mapview.getController()._layer
226
227 def selectLayer(self, event, widget=None, layerid=None):
228 """ Callback for Labels
229
230 We hand the layerid over to the mapeditor module to select a
231 new active layer
232
233 Additionally, we mark the active layer widget (changing base color) and reseting the previous one
234
235 @type event: object
236 @param event: pychan mouse event
237 @type widget: object
238 @param widget: the pychan widget where the event occurs, transports the layer id in it's name
239 @type layerid: string
240 @param layerid: the layer id
241 """
242
243 if not widget and not layerid:
244 print "No layer ID or widget passed to LayerTool.selectLayer"
245 return
246
247 if widget is not None:
248 layerid = widget.name[len(LayerTool.LABEL_NAME_PREFIX):]
249
250 self.resetSelection()
251
252 widget.background_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
253 widget.foreground_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
254 widget.base_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR
255
256 self._mapview.getController().selectLayer(layerid)
257
258 def resetSelection(self):
259 """ Deselects selected layer """
260 previous_active_layer = self.getActiveLayer()
261 if previous_active_layer is not None:
262 previous_layer_id = previous_active_layer.getId()
263 previous_active_widget = self._container.findChild(name=LayerTool.LABEL_NAME_PREFIX + previous_layer_id)
264 previous_active_widget.background_color = LayerTool.DEFAULT_BACKGROUND_COLOR
265 previous_active_widget.foreground_color = LayerTool.DEFAULT_BACKGROUND_COLOR
266 previous_active_widget.base_color = LayerTool.DEFAULT_BACKGROUND_COLOR
267 previous_active_widget.text = unicode(previous_layer_id)
268
269 self._mapview.getController().selectLayer(None)
270
271
272 def removeSelectedLayer(self):
273 """ Deletes the selected layer """
274 if not self._mapview: return
275
276 if self._mapview.getMap().getNumLayers() <= 1:
277 print "Can't remove the last layer"
278 return
279
280 layer = self.getActiveLayer()
281 if not layer: return
282
283 self.resetSelection()
284
285 map = self._mapview.getMap()
286
287 # FIFE will crash if we try to delete the layer which is in use by a camera
288 # so we will set the camera to another layer instead
289 for cam in self._editor.getEngine().getView().getCameras():
290 if cam.getLocationRef().getMap().getId() != map.getId():
291 continue
292
293 if cam.getLocation().getLayer().getId() != layer.getId():
294 continue
295
296 for l in map.getLayers():
297 if l.getId() == layer.getId():
298 continue
299
300 cam.getLocationRef().setLayer(l)
301 break
302
303 map.deleteLayer(layer)
304 self.update(self._mapview)
305
306 def toggle(self):
307 """ Toggles the layertool visible / invisible and sets
308 dock status
309 """
310 if self._container.isVisible() or self._container.isDocked():
311 self._container.setDocked(False)
312 self._container.hide()
313
314 self._action_show.setChecked(False)
315 else:
316 self._container.show()
317 self._action_show.setChecked(True)
318 self._adjustPosition()
319
320 def _createGui(self):
321 """ Create the basic gui container """
322 self._container = pychan.loadXML('gui/layertool.xml')
323 self._wrapper = self._container.findChild(name="layers_wrapper")
324 self._remove_layer_button = self._container.findChild(name="remove_layer_button")
325 self._create_layer_button = self._container.findChild(name="add_layer_button")
326 self._edit_layer_button = self._container.findChild(name="edit_layer_button")
327
328 self._remove_layer_button.capture(self.removeSelectedLayer)
329 self._remove_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._remove_layer_button.helptext), 'mouseEntered')
330 self._remove_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited')
331
332 self._create_layer_button.capture(self.showLayerWizard)
333 self._create_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._create_layer_button.helptext), 'mouseEntered')
334 self._create_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited')
335
336 self._edit_layer_button.capture(self.showEditDialog)
337 self._edit_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._edit_layer_button.helptext), 'mouseEntered')
338 self._edit_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited')
339
340 self.update(None)
341
342 def _adjustPosition(self):
343 """ Adjusts the position of the container - we don't want to
344 let the window appear at the center of the screen.
345 (new default position: left, beneath the tools window)
346 """
347 self._container.position = (50, 200)
348
349 def _layerCreated(self, layer):
350 self.update(self._mapview)
351 self.selectLayer(None, self._wrapper.findChild(name=LayerTool.LABEL_NAME_PREFIX + layer.getId()))
352
353
354