changeset 192:bec4b69ad83a

* Redid the editor's ObjectSelector to display previews for all objects instead of only 1 preview + paths/filenames * ImageButton now takes GuiImage's as argument for up/down/hover image, like icon does. * Tab cleanup
author nihathrael@33b003aa-7bff-0310-803a-e67f0ece8222
date Sat, 28 Feb 2009 22:33:21 +0000
parents c725ecb2ce4c
children 9661d611b346
files clients/editor/plugins/mapeditor.py clients/editor/plugins/objectselector.py engine/extensions/pychan/widgets.py
diffstat 3 files changed, 163 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/clients/editor/plugins/mapeditor.py	Sat Feb 28 12:39:59 2009 +0000
+++ b/clients/editor/plugins/mapeditor.py	Sat Feb 28 22:33:21 2009 +0000
@@ -60,7 +60,7 @@
 		self._onSelect, self._onMove, self._onInsert, self._onDelete = onSelect, onMove, onInsert, onDelete
 		self.onBtnEnter, self.onBtnExit = onBtnEnter, onBtnExit
 		self._toolbar = None
-	
+
 	def show(self):
 		if not self._toolbar:
 			self._toolbar = pychan.loadXML('gui/tools.xml')
@@ -75,15 +75,15 @@
 				btn = self._toolbar.findChild(name=k)
 				btn.setEnterCallback(self.onBtnEnter)
 				btn.setExitCallback(self.onBtnExit)
-		
+
 		#self._toolbar.adaptLayout()
 		self._toolbar.show()
 		self._toolbar.x = 10
 		self._toolbar.y = 50
-	
+
 	def hide(self):
 		self._toolbar.hide()
-	
+
 	def _enableBtn(self, enabled, btn):
 		btn.toggled = enabled;
 
@@ -104,7 +104,7 @@
 		self.enableSelect(False)
 		self.enableInsert(False)
 		self.enableMove(False)
-	
+
 class StatusBar(object):
 	def __init__(self, screenw, screenh):
 		self._statusbar = pychan.loadXML('gui/statuspanel.xml')
@@ -119,7 +119,7 @@
 		self.statustxt = msg
 		self.lbl.text = '  ' + msg
 		self.lbl.resizeToContent()
-	
+
 	def showTooltip(self, elem):
 		self.lbl.text = elem.helptext
 		self.lbl.resizeToContent()
@@ -160,7 +160,7 @@
 		self._dragy = NOT_INITIALIZED
 		self._scrollx = 0
 		self._scrolly = 0
-		
+
 		self._mapselector = MapSelection(self._selectLayer, self._selectObject)
 		self._objectselector = None
 		rb = self._engine.getRenderBackend()
@@ -178,7 +178,7 @@
 		if not statement:
 			print msg
 			raise EditorLogicError(msg)
-	
+
 	def _setMode(self, mode):
 		if (mode != NOTHING_LOADED) and (not self._camera):
 			self._statusbar.setStatus('Please load map first')
@@ -187,7 +187,7 @@
 		if (mode == INSERTING) and (not self._object):
 			self._statusbar.setStatus('Please select object first')
 			mode = self._mode
-		
+
 		# Update toolbox buttons
 		if (mode == INSERTING):
 			self._toolbar.enableInsert(True)
@@ -199,22 +199,22 @@
 			self._toolbar.enableMove(True)
 		else:
 			self._toolbar.disableAll()
-		
+
 		self._mode = mode
 		print "Entered mode " + mode
 		self._statusbar.setStatus(mode.replace('_', ' ').capitalize())
-	
+
 	# gui for selecting a map
 	def _selectMap(self):
 		Selection([map.getId() for map in self._engine.getModel().getMaps()], self.editMap)
 
 	def _selectDefaultCamera(self, map):
 		self._camera = None
-		
+
 		self._engine.getView().resetRenderers()
 		for cam in self._engine.getView().getCameras():
 			cam.setEnabled(False)
-			
+
 		for cam in self._engine.getView().getCameras():
 			if cam.getLocationRef().getMap().getId() == map.getId():
 				rb = self._engine.getRenderBackend()
@@ -233,21 +233,21 @@
 		self._selection = None
 		self._instances = None
 		self._setMode(NOTHING_LOADED)
-		
+
 		self._map = self._engine.getModel().getMap(mapid)
 		if not self._map.getLayers():
 			raise AttributeError('Editor error: map ' + self._map.getId() + ' has no layers. Cannot edit.')
-		
+
 		self._layer = self._map.getLayers()[0]
 		self._selectDefaultCamera(self._map)
 		self._setMode(VIEWING)
-		
+
 		self._mapselector.show(self._map)
-		
+
 		# zero-projekt plugin
 		if self.layertool is not None:
 			self.layertool.update()
-	
+
 	def _selectLayer(self):
 		Selection([layer.getId() for layer in self._map.getLayers()], self._editLayer)
 
@@ -267,7 +267,7 @@
 
 	def _selectCell(self, screenx, screeny, preciseCoords=False):
 		self._assert(self._camera, 'No camera bind yet, cannot select any cell')
-		
+
 		self._selection = self._camera.toMapCoordinates(fife.ScreenPoint(screenx, screeny), False)
 		self._selection.z = 0
 		loc = fife.Location(self._layer)
@@ -284,7 +284,7 @@
 		self._assert(self._layer, 'No layer assigned in _getInstancesFromPosition')
 		self._assert(position, 'No position assigned in _getInstancesFromPosition')
 		self._assert(self._camera, 'No camera assigned in _getInstancesFromPosition')
-		
+
 		loc = fife.Location(self._layer)
 		if type(position) == fife.ExactModelCoordinate:
 			loc.setExactLayerCoordinates(position)
@@ -301,7 +301,7 @@
 			self._undo = True
 			self._undoStack.pop()()
 			self._undo = False
-	
+
 	def _placeInstance(self,position,object):
 		mname = '_placeInstance'
 		self._assert(object, 'No object assigned in %s' % mname)
@@ -310,7 +310,7 @@
 
 		print 'Placing instance of ' + object.getId() + ' at ' + str(position)
 		print object
-		
+
 		# don't place repeat instances
 		for i in self._getInstancesFromPosition(position, False):
 			if i.getObject().getId() == object.getId():
@@ -335,13 +335,13 @@
 				object = i.getObject()
 				self._undoStack.append(lambda: self._placeInstance(position,object))
 			self._layer.deleteInstance(i)
-				
+
 	def _moveInstances(self):
 		mname = '_moveInstances'
 		self._assert(self._selection, 'No selection assigned in %s' % mname)
 		self._assert(self._layer, 'No layer assigned in %s' % mname)
 		self._assert(self._mode == MOVING, 'Mode is not MOVING in %s (is instead %s)' % (mname, str(self._mode)))
-		
+
 		loc = fife.Location(self._layer)
 		if self._shiftdown:
 			loc.setExactLayerCoordinates(self._selection)
@@ -352,12 +352,12 @@
 			f.setExactLayerCoordinates(i.getFacingLocation().getExactLayerCoordinates() + fife.ExactModelCoordinate(float(self._selection.x), float(self._selection.y)) - i.getLocation().getExactLayerCoordinates())
 			i.setLocation(loc)
 			i.setFacingLocation(f)
-	
+
 	def _rotateInstances(self):
 		mname = '_rotateInstances'
 		self._assert(self._selection, 'No selection assigned in %s' % mname)
 		self._assert(self._layer, 'No layer assigned in %s' % mname)
-		
+
 		for i in self._getInstancesFromPosition(self._selection, top_only=True):
 # by c 09/11/08
 # FIXME:
@@ -381,13 +381,13 @@
 					else:
 						index = 0
 #				print "index, new: ", index
-					
+
 					i.setRotation( int(self._objectedit_rotations[index]) )
 #				print "new rotation: ", self._objectedit_rotations[index]
 			except:
 				# Fallback
 				i.setRotation((i.getRotation() + 90) % 360)
-			
+
 # end FIXME
 # end edit c
 
@@ -415,7 +415,7 @@
 	def changeRotation(self):
 		currot = self._camera.getRotation()
 		self._camera.setRotation((currot + 90) % 360)
-	
+
 	def _moveCamera(self, screen_x, screen_y):
 		coords = self._camera.getLocationRef().getMapCoordinates()
 		z = self._camera.getZoom()
@@ -428,11 +428,11 @@
 			coords.y -= screen_y / z * math.cos(-r / 180.0 * math.pi) / 100;
 		coords = self._camera.getLocationRef().setMapCoordinates(coords)
 		self._camera.refresh()
-	
+
 	def mousePressed(self, evt):
 		if evt.isConsumedByWidgets():
 			return
-		
+
 		if self._ctrldown:
 			if evt.getButton() == fife.MouseEvent.LEFT:
 				self._dragx = evt.getX()
@@ -450,11 +450,11 @@
 				self._instances = self._getInstancesFromPosition(self._selection, top_only=True)
 			else:
 				self._setMode(self._mode) # refresh status
-	
+
 	def mouseDragged(self, evt):
 		if evt.isConsumedByWidgets():
 			return
-		
+
 		if self._ctrldown:
 			if (self._dragx != NOT_INITIALIZED) and (self._dragy != NOT_INITIALIZED):
 				self._moveCamera(evt.getX() - self._dragx, evt.getY() - self._dragy)
@@ -474,10 +474,10 @@
 	def mouseReleased(self, evt):
 		if evt.isConsumedByWidgets():
 			return
-		
+
 		self._dragx = NOT_INITIALIZED
 		self._dragy = NOT_INITIALIZED
-	
+
 	def mouseMoved(self, evt):
 		if self._camera:
 			screen_x = self._engine.getRenderBackend().getWidth()
@@ -509,20 +509,20 @@
 		pass
 	def mouseClicked(self, evt):
 		pass
-	
+
 	def mouseWheelMovedUp(self, evt):
 		if self._ctrldown and self._camera:
 			self._camera.setZoom(self._camera.getZoom() * 1.05)
-			
+
 	def mouseWheelMovedDown(self, evt):
 		if self._ctrldown and self._camera:
 			self._camera.setZoom(self._camera.getZoom() / 1.05)
-			
+
 
 	def keyPressed(self, evt):
 		keyval = evt.getKey().getValue()
 		keystr = evt.getKey().getAsString().lower()
-		
+
 		if keyval == fife.Key.LEFT:
 			self._moveCamera(50, 0)
 		elif keyval == fife.Key.RIGHT:
@@ -537,7 +537,7 @@
 			self._shiftdown = True
 		elif keyval in (fife.Key.LEFT_ALT, fife.Key.RIGHT_ALT):
 			self._altdown = True
-		
+
 		elif keyval == fife.Key.INSERT:
 			if self._mode != INSERTING:
 				self._setMode(INSERTING)
@@ -549,13 +549,13 @@
 				self._setMode(REMOVING)
 			else:
 				self._setMode(VIEWING)
-			
+
 		elif keystr == 'm':
 			if self._mode != MOVING:
 				self._setMode(MOVING)
 			else:
 				self._setMode(VIEWING)
-		
+
 		elif keystr == 't':
 			gridrenderer = self._camera.getRenderer('GridRenderer')
 			gridrenderer.setEnabled(not gridrenderer.isEnabled())
@@ -563,7 +563,7 @@
 		elif keystr == 'b':
 			blockrenderer = self._camera.getRenderer('BlockingInfoRenderer')
 			blockrenderer.setEnabled(not blockrenderer.isEnabled())
-		
+
 		elif keystr == 'r':
 			if self._selection:
 				self._rotateInstances()
@@ -573,7 +573,7 @@
 
 		elif keystr == 'u':
 			self.undo()
-	
+
 	def keyReleased(self, evt):
 		keyval = evt.getKey().getValue()
 		if keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL):
--- a/clients/editor/plugins/objectselector.py	Sat Feb 28 12:39:59 2009 +0000
+++ b/clients/editor/plugins/objectselector.py	Sat Feb 28 22:33:21 2009 +0000
@@ -1,95 +1,99 @@
 # coding: utf-8
 
-from pychan import widgets
+from pychan import widgets, tools
 import fife
 
 class ObjectSelector(object):
-	def __init__(self,engine,map,selectNotify):
+	"""The ObjectSelector class offers a gui Widget that let's you select the object you
+	wish to use to in the editor.
+	@param engine: fife instance
+	@param map: fife.Map instance containing your map
+	@param selectNotify: callback function used to tell the editor you selected an object.
+	"""
+	def __init__(self, engine, map, selectNotify):
 		self.engine = engine
 		self.map = map
 		self.notify = selectNotify
-		
+
 		self.buildGui()
-	
+
 	def buildGui(self):
+		# Create the main Window
 		self.gui = widgets.Window(title="Object selector")
+		hbox = widgets.HBox()
+		self.gui.addChild(hbox)
+
+		# Add the Scrollarea with list of namespaces
+		scrollArea = widgets.ScrollArea(size=(200,300))
+		hbox.addChild(scrollArea)
+		self.namespaces = widgets.ListBox()
+		self.namespaces.capture(self.fillList)
+		self.namespaces.items = self.engine.getModel().getNamespaces()
+		self.namespaces.selected = 0
+		scrollArea.addChild(self.namespaces)
+
+		# This Vbox is used to display the preview images
+		scrollArea = widgets.ScrollArea(size=(200,300))
+		self.objects = widgets.VBox(size=(200,300))
+		scrollArea.addChild(self.objects)
+		hbox.addChild(scrollArea)
+
+		# Add another Hbox to hold the close button
 		hbox = widgets.HBox(parent=self.gui)
 		self.gui.addChild(hbox)
-		scrollArea = widgets.ScrollArea(parent=hbox,size=(200,300))
-		hbox.addChild(scrollArea)
-		self.namespaces = widgets.ListBox(parent=scrollArea)
-		scrollArea.content = self.namespaces
-		scrollArea = widgets.ScrollArea(parent=hbox,size=(200,300))
-		hbox.addChild(scrollArea)
-		self.objects = widgets.ListBox(parent=scrollArea)
-		scrollArea.content = self.objects
-		scrollArea = widgets.ScrollArea(parent=hbox, size=(200,300))
-		hbox.addChild(scrollArea)
-		self.preview = widgets.Icon()
-		scrollArea.content = self.preview
+		hbox.addSpacer(widgets.Spacer())
+		closeButton = widgets.Button(text="Close")
+		closeButton.capture(self.hide)
+		hbox.addChild(closeButton)
 
-		hbox = widgets.HBox(parent=self.gui)
-		self.gui.addChild(hbox)
-		hbox.addSpacer( widgets.Spacer() )
-		closeButton = widgets.Button(parent=hbox,text="Close")
-		hbox.addChild( closeButton )
-		closeButton.capture(self.hide)
-		
-		self.namespaces.capture(self.updateObjects)
-		self.namespaces.items = self.engine.getModel().getNamespaces()
-		self.namespaces.selected = 0
-		self.updateObjects()
-	
-		self.objects.capture(self.objectSelected)
 
 	def update(self):
 		self.namespaces.items = self.engine.getModel().getNamespaces()
 		self.namespaces.selected = 0
-		self.updateObjects()
-	
-	def updateObjects(self):
-		if not self.namespaces.selected_item: return
+		self.fillList()
 
-		self.objects.items = [obj.getId() for obj in self.engine.getModel().getObjects(self.namespaces.selected_item)]
-		if not self.objects.selected_item:
-			self.objects.selected = 0
-		self.objectSelected()
+	def fillList(self):
+		for obj in self.engine.getModel().getObjects(self.namespaces.selected_item):
+			# Find visual for the object
+			visual = None
+			try:
+				visual = obj.get2dGfxVisual()
+			except:
+				print 'Visual Selection created for type without a visual?'
+				raise
 
-	def objectSelected(self):
-		if not self.objects.selected_item: return
-		object = self.engine.getModel().getObject(self.objects.selected_item, self.namespaces.selected_item)
-		self.notify(object)
-		self._refreshPreview(object)
+			# Try to find a usable image
+			index = visual.getStaticImageIndexByAngle(0)
 
-	def _refreshPreview(self, object):
-		visual = None
-		
-		try:
-			visual = object.get2dGfxVisual()
-		except:
-			print 'Visual Selection created for type without a visual?'
-			raise	
+			# if no static image available, try default action
+			if index == -1:
+				action = obj.getDefaultAction()
+				if action:
+					animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(0)
+					animation = self.engine.getAnimationPool().getAnimation(animation_id)
+					image = animation.getFrameByTimestamp(0)
+					index = image.getPoolId()
 
-		index = visual.getStaticImageIndexByAngle(0)
-		if index == -1:
-			# no static image available, try default action
-			action = object.getDefaultAction()
-			if action:
-				animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(0)
-				animation = self.engine.getAnimationPool().getAnimation(animation_id)
-				image = animation.getFrameByTimestamp(0)
-				index = image.getPoolId()
-		
-		if index != -1:
-			image = fife.GuiImage(index, self.engine.getImagePool())
-			self.preview.image = image
-			self.gui.adaptLayout()
-		else:
-			print 'No image available for selected object'
-	
-	
+			# Use the hopefully found image to set up the imagebutton
+			if index != -1:
+				image = fife.GuiImage(index, self.engine.getImagePool())
+				imagebutton = widgets.ImageButton(up_image=image, down_image=image, hover_image=image)
+				imagebutton.capture(tools.callbackWithArguments(self.objectSelected, obj))
+				self.objects.addChild(imagebutton)
+				self.objects._recursiveResizeToContent()
+				self.gui.adaptLayout()
+			else:
+				print 'No image available for selected object'
+
+	def objectSelected(self, obj):
+		"""This is used as callback function to notify the editor that a new object has
+		been selected.
+		@param obj: fife.Object instance"""
+		self.notify(obj)
+
 	def show(self):
 		self.update()
 		self.gui.show()
+
 	def hide(self):
 		self.gui.hide()
--- a/engine/extensions/pychan/widgets.py	Sat Feb 28 12:39:59 2009 +0000
+++ b/engine/extensions/pychan/widgets.py	Sat Feb 28 22:33:21 2009 +0000
@@ -1161,33 +1161,61 @@
 		self.hover_image = hover_image
 		self.offset = offset
 
-	def _setUpImage(self,image):
-		self._upimage_source = image
-		try:
-			self._upimage = get_manager().loadImage(image)
+	def _setUpImage(self, source):
+		if isinstance(source,str):
+			self._upimage_source = source
+			try:
+				self._upimage = get_manager().loadImage(image)
+				self.real_widget.setUpImage( self._upimage )
+			except:
+				self._upimage = _DummyImage()
+		elif isinstance(source,fife.GuiImage):
+			self._upimage_source = None
+			self._upimage = source
 			self.real_widget.setUpImage( self._upimage )
-		except:
-			self._upimage = _DummyImage()
+		else:
+			raise RuntimeError("Icon.image only accepts GuiImage and python strings, not '%s'" % repr(source))
+
+		# Set minimum size accoriding to image
+		self.min_size = self.real_widget.getWidth(),self.real_widget.getHeight()
+		self.size  = self.max_size = self.min_size
+
 	def _getUpImage(self): return self._upimage_source
 	up_image = property(_getUpImage,_setUpImage)
 
-	def _setDownImage(self,image):
-		self._downimage_source = image
-		try:
-			self._downimage = get_manager().loadImage(image)
+	def _setDownImage(self, source):
+		if isinstance(source,str):
+			self._downimage_source = source
+			try:
+				self._downimage = get_manager().loadImage(image)
+				self.real_widget.setDownImage( self._downimage )
+			except:
+				self._downimage = _DummyImage()
+		elif isinstance(source,fife.GuiImage):
+			self._downimage_source = None
+			self._downimage = source
 			self.real_widget.setDownImage( self._downimage )
-		except:
-			self._downimage = _DummyImage()
+		else:
+			raise RuntimeError("Icon.image only accepts GuiImage and python strings, not '%s'" % repr(source))
+
 	def _getDownImage(self): return self._downimage_source
 	down_image = property(_getDownImage,_setDownImage)
 
-	def _setHoverImage(self,image):
-		self._hoverimage_source = image
-		try:
-			self._hoverimage = get_manager().loadImage(image)
+	def _setHoverImage(self, source):
+		if isinstance(source, str):
+			self._hoverimage_source = source
+			try:
+				self._hoverimage = get_manager().loadImage(image)
+				self.real_widget.setHoverImage( self._hoverimage )
+			except:
+				self._hoverimage = _DummyImage()
+		elif isinstance(source,fife.GuiImage):
+			self._hoverimage_source = None
+			self._hoverimage = source
 			self.real_widget.setHoverImage( self._hoverimage )
-		except:
-			self._hoverimage = _DummyImage()
+		else:
+			raise RuntimeError("Icon.image only accepts GuiImage and python strings, not '%s'" % repr(source))
+
 	def _getHoverImage(self): return self._hoverimage_source
 	hover_image = property(_getHoverImage,_setHoverImage)
 
@@ -1613,7 +1641,7 @@
 	==============
 
 	  - content: The wrapped widget.
-	  - vertical_scrollbar: Boolean: Set this to False to hide the Vertcial scrollbar
+	  - vertical_scrollbar: Boolean: Set this to False to hide the Vertical scrollbar
 	  - horizontal_scrollbar: Boolean: Set this to False to hide the Horizontal scrollbar
 
 	"""