diff clients/editor/scripts/gui/menubar.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 6add14ebe9f5
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clients/editor/scripts/gui/menubar.py	Mon Jun 08 16:00:02 2009 +0000
@@ -0,0 +1,318 @@
+from pychan import widgets
+from pychan.tools import callbackWithArguments as cbwa
+
+import scripts.events
+import scripts.gui.action
+from action import Action, ActionGroup
+from fife import Color
+import fife_timer
+
+MENU_ICON_SIZE = 24
+
+class MenuBar(widgets.HBox):
+	def __init__(self, *args, **kwargs):
+		super(MenuBar, self).__init__(*args, **kwargs)
+		
+		self.menulist = []
+		self._buttonlist = []
+		self.gui = None
+		self._buildGui()
+		
+		self._timer = fife_timer.Timer(500, self._autoHideMenu)
+		self._timer.start()
+			
+	def _buildGui(self):
+		if self.gui is not None:
+			self.removeChild(self.gui)
+			self._buttonlist = []
+			
+		self.gui = widgets.HBox()
+		for i, menu in enumerate(self.menulist):
+			button = widgets.Button(name=menu.name, text=menu.name)
+			button.hexpand = 0
+			button.capture(cbwa(self._showMenu, i))
+			self._buttonlist.append(button)
+			self.gui.addChild(button)
+			
+		self.gui.addSpacer(widgets.Spacer())
+		
+		self.addChild(self.gui)
+		
+	def _showMenu(self, i):
+		if self.menulist[i].isVisible():
+			self.menulist[i].hide()
+			return
+	
+		# Hide all menus
+		for m in self.menulist:
+			m.hide()
+	
+		menu = self.menulist[i]
+		button = self._buttonlist[i]
+		
+		menu.x = 0
+		menu.y = button.height
+
+		# Get absolute position of button
+		parent = button
+		while parent is not None:
+			menu.x += parent.x
+			menu.y += parent.y
+			parent = parent.parent
+
+		menu.show()
+		
+	def _autoHideMenu(self):
+		for i, m in enumerate(self.menulist):
+			if not m.isVisible(): continue
+			if self._buttonlist[i].real_widget.isFocused(): continue
+			if self._isMenuFocused(m) is False:
+				m.hide()
+		
+	def _isMenuFocused(self, widget):
+		if widget.real_widget.isFocused(): return True
+		if hasattr(widget, "children"):
+			for c in widget.children:
+				if self._isMenuFocused(c):
+					return True
+		return False
+		
+	def addMenu(self, menu):
+		if menu is not None and self.menulist.count(menu) <= 0:
+			self.menulist.append(menu)
+		self._buildGui()
+		
+	def insertMenu(self, menu, beforeMenu):
+		try:
+			i = self.menulist.index(beforeMenu)
+			self.menulist.insert(i, menu)
+			self._buildGui()
+			
+		except ValueError:
+			print "MenuBar::insertMenu:", "MenuBar does not contain specified menu."
+			return
+			
+	def insertMenuAt(self, menu, index):
+		self.menulist.insert(index, menu)
+		self._buildGui()
+
+	def removeMenu(self, menu):
+		self.menulist.remove(menu)
+		self._buildGui()
+		
+	def clear(self):
+		self.menulist = []
+		self._buildGui()
+
+class Menu(widgets.VBox):
+	def __init__(self, name=u"", icon=u"", min_width=100, min_height=15, margins=(2,2), *args, **kwargs):
+		super(Menu, self).__init__(*args, **kwargs)
+		self.min_width=min_width
+		self.min_height=min_height
+		self.margins=margins
+		
+		self.name = name
+		self.icon = icon
+		
+		self._actions = []
+		self._actionbuttons = []
+		
+		self._update()
+
+	def addSeparator(self, separator=None): 
+		self.insertSeparator(separator, len(self._actions))
+
+	def addAction(self, action):
+		self.insertAction(action, len(self._actions))
+		
+	def removeAction(self, action):
+		self._actions.remove(action)
+		
+		actions = [action]
+		if isinstance(action, ActionGroup):
+			actions = action.getActions()
+			scripts.gui.action.changed.disconnect(self._updateActionGroup, sender=action)
+
+		for a in actions:
+			for b in self._actionbuttons[:]:
+				if a == b.action:
+					self.removeChild(b)
+					self._actionbuttons.remove(b)
+			
+		self.adaptLayout()
+		
+	def hasAction(self, action):
+		for a in self._actions:
+			if a == action: return True
+		return False
+		
+	def insertAction(self, action, position=0, before=None):
+		if self.hasAction(action):
+			print "Action already added to toolbar"
+			return
+
+		if before is not None:
+			position = self._actions.index(before)
+
+		self._actions.insert(position, action)
+		self._insertButton(action, position)
+		
+	def _updateActionGroup(self, sender):
+		position = self._actions.index(sender)
+		self.removeAction(sender)
+		self.insertAction(sender, position)
+		self.adaptLayout()
+		
+	def _insertButton(self, action, position):
+		actions = [action]
+		if isinstance(action, ActionGroup):
+			actions = action.getActions()
+			scripts.gui.action.changed.connect(self._updateActionGroup, sender=action)
+
+		if position >= 0:
+			actions = reversed(actions)
+		
+		# Action groups are counted as one action, add the hidde number of actions to position
+		for i in range(position):
+			if isinstance(self._actions[i], ActionGroup):
+				position += len(self._actions[i].getActions()) - 1
+
+		for a in actions:
+			button = MenuButton(a, name=a.text)
+			self.insertChild(button, position)
+			self._actionbuttons.insert(position, button)
+		
+	def insertSeparator(self, separator=None, position=0, before=None): 
+		if separator==None:
+			separator = Action(separator=True)
+		self.insertAction(separator, position, before)
+		
+	def clear(self):
+		self.removeAllChildren()
+		self._actions = []
+		
+		for i in reversed(range(len(self._actionbuttons))):
+			self._actionbuttons[i].removeEvents()
+		self._actionbuttons = []
+
+	def _update(self):
+		actions = self._actions
+		
+		self.clear()
+		
+		for action in actions:
+			self.addAction(action)
+
+		self.adaptLayout()
+		
+	def show(self):
+		self._update()
+		super(Menu, self).show()
+		
+class MenuButton(widgets.HBox):
+	def __init__(self, action, **kwargs):
+		self._action = action
+		self._widget = None
+		
+		super(MenuButton, self).__init__(**kwargs)
+		
+		self.update()
+
+		self.initEvents()
+	
+	def initEvents(self):
+		# Register eventlisteners
+		self.capture(self._showTooltip, "mouseEntered")
+		self.capture(self._hideTooltip, "mouseExited")
+		
+		scripts.gui.action.changed.connect(self._actionChanged, sender=self._action)
+	
+	def removeEvents(self):
+		# Remove eventlisteners
+		self.capture(None, "mouseEntered")
+		self.capture(None, "mouseExited")
+		
+		scripts.gui.action.changed.disconnect(self.update, sender=self._action)
+	
+	def setAction(self, action):
+		self.removeEvents()
+		
+		self._action = action
+		self.update()
+		self.adaptLayout()
+		
+		self.initEvents()
+	
+	def getAction(self):
+		return self._action
+	action = property(getAction, setAction)
+	
+	def _showTooltip(self):
+		if self._action is not None and self._action.helptext != "":
+			scripts.editor.getEditor().getStatusBar().showTooltip(self._action.helptext)
+			
+	def _hideTooltip(self):
+		scripts.editor.getEditor().getStatusBar().hideTooltip()
+		
+	def _actionChanged(self):
+		self.update()
+		self.adaptLayout()
+		
+	def update(self):
+		""" Sets up the button widget """
+		if self._widget != None:
+			self.removeChild(self._widget)
+			self._widget = None
+			
+		if self._action is None:
+			return
+			
+		widget = None
+		icon = None
+		text = None
+
+		if self._action.isSeparator():
+			widget = widgets.HBox()
+			widget.base_color += Color(8, 8, 8)
+			widget.min_size = (2, 2)
+		else:
+			hasIcon = len(self._action.icon) > 0
+			
+			if self._action.isCheckable():
+				text = widgets.ToggleButton(text=self._action.text)
+				text.toggled = self._action.isChecked()
+				text.hexpand = 1
+			else:
+				text = widgets.Button(text=self._action.text)
+			text.min_size = (1, MENU_ICON_SIZE)
+			text.max_size = (1000, MENU_ICON_SIZE)
+			text.capture(self._action.activate)
+
+			if hasIcon:
+				if self._action.isCheckable():
+					icon = widgets.ToggleButton(hexpand=0, up_image=self._action.icon,down_image=self._action.icon,hover_image=self._action.icon,offset=(1,1))
+					icon.toggled = self._action.isChecked()
+				else:
+					icon = widgets.ImageButton(hexpand=0, up_image=self._action.icon,down_image=self._action.icon,hover_image=self._action.icon,offset=(1,1))
+
+			else:
+				if self._action.isCheckable():
+					icon = widgets.ToggleButton(hexpand=0, offset=(1,1))
+					icon.toggled = self._action.isChecked()
+				else:
+					icon = widgets.Button(text=u"", hexpand=0, offset=(1,1))
+				
+			icon.min_size = icon.max_size = (MENU_ICON_SIZE, MENU_ICON_SIZE)
+			icon.capture(self._action.activate)
+			
+			widget = widgets.HBox()
+			widget.addChild(icon)
+			widget.addChild(text)
+			
+		widget.position_technique = "left:center"
+		widget.hexpand = 1
+		widget.vexpand = 0
+		
+		self._widget = widget
+		self.addChild(self._widget)
+		
\ No newline at end of file