diff clients/editor/plugins/HistoryManager.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 e893afb4963b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clients/editor/plugins/HistoryManager.py	Mon Jun 08 16:00:02 2009 +0000
@@ -0,0 +1,259 @@
+# coding: utf-8
+
+import pychan
+from pychan import widgets, tools, attrs, internal
+import scripts
+import scripts.plugin as plugin
+from scripts.events import *
+from scripts.gui.action import Action, ActionGroup
+import fife
+from fife import Color
+from scripts import undomanager
+import scripts.gui
+from scripts.gui.panel import Panel
+import pdb
+
+class HistoryManager(plugin.Plugin):
+	def __init__(self):
+		self.editor = None
+		self.engine = None
+		
+		self._enabled = False
+		self.undomanager = None
+
+	def enable(self):
+		if self._enabled is True:
+			return
+			
+		self.editor = scripts.editor.getEditor()
+		self.engine = self.editor.getEngine()
+			
+		self._undoGroup = ActionGroup(name=u"UndoGroup")
+		self._showAction = Action(u"History manager", checkable=True)
+		self._undoAction = Action(u"Undo", "gui/icons/undo.png")
+		self._redoAction = Action(u"Redo", "gui/icons/redo.png")
+		self._nextAction = Action(u"Next branch", "gui/icons/next_branch.png")
+		self._prevAction = Action(u"Previous branch", "gui/icons/previous_branch.png")
+		scripts.gui.action.activated.connect(self.toggle, sender=self._showAction)
+		scripts.gui.action.activated.connect(self._undo, sender=self._undoAction)
+		scripts.gui.action.activated.connect(self._redo, sender=self._redoAction)
+		scripts.gui.action.activated.connect(self._next, sender=self._nextAction)
+		scripts.gui.action.activated.connect(self._prev, sender=self._prevAction)
+		
+		self._undoGroup.addAction(self._undoAction)
+		self._undoGroup.addAction(self._redoAction)
+		self._undoGroup.addAction(self._nextAction)
+		self._undoGroup.addAction(self._prevAction)
+		
+		self.editor._toolsMenu.addAction(self._showAction)
+		self.editor._editMenu.insertAction(self._undoGroup, 0)
+		self.editor._editMenu.insertSeparator(position=1)
+		
+		events.postMapShown.connect(self.update)
+		undomanager.changed.connect(self.update)
+		
+		self.buildGui()
+
+	def disable(self):
+		if self._enabled is False:
+			return
+			
+		self.gui.hide()
+		self.removeAllChildren()
+		
+		events.postMapShown.disconnect(self.update)
+		undomanager.changed.disconnect(self.update)
+		
+		scripts.gui.action.activated.connect(self.toggle, sender=self._showAction)
+		scripts.gui.action.activated.disconnect(self._undo, sender=self._undoAction)
+		scripts.gui.action.activated.disconnect(self._redo, sender=self._redoAction)
+		scripts.gui.action.activated.disconnect(self._next, sender=self._nextAction)
+		scripts.gui.action.activated.disconnect(self._prev, sender=self._prevAction)
+		
+		self.editor._toolsMenu.removeAction(self._showAction)
+		self.editor._toolsMenu.removeAction(self._undoGroup)
+
+
+	def isEnabled(self):
+		return self._enabled;
+
+	def getName(self):
+		return "History manager"
+		
+
+	def buildGui(self):
+		self.gui = Panel(title=u"History")
+		self.scrollarea = widgets.ScrollArea(min_size=(200,300))
+		self.list = widgets.ListBox()
+		self.list.capture(self._itemSelected)
+		
+		self.gui.addChild(self.scrollarea)
+		self.scrollarea.addChild(self.list)
+		
+		self.gui.position_technique = "right:center"
+		
+	def _itemSelected(self):
+		mapview = self.editor.getActiveMapView()
+		if mapview is None:
+			return
+			
+		undomanager = mapview.getController().getUndoManager()
+		
+		stackitem = self.list.selected_item.item
+		if stackitem == undomanager.current_item:
+			#print "Selected current item"
+			return
+		
+		searchlist = []
+		searchlist2 = []
+		parent = stackitem
+		branch = parent.next
+		while parent is not None:
+			if parent is undomanager.first_item or len(parent._branches) > 1:
+				searchlist.append( (parent, branch) )
+			branch = parent
+			parent = parent.parent
+		
+		current_item = undomanager.current_item
+		
+		parent = current_item
+		branch = parent.next
+		while parent is not None:
+			if parent is undomanager.first_item or len(parent._branches) > 1:
+				searchlist2.append( (parent, branch) )
+			branch = parent
+			parent = parent.parent
+			
+		searchlist.reverse()
+		searchlist2.reverse()
+		
+		# Remove duplicate entries, except the last duplicate, so we don't undo
+		# more items than necessary
+		sl = len(searchlist);
+		if len(searchlist2) < sl:
+			sl = len(searchlist2)
+		for s in range(sl):
+			if searchlist[s][0] != searchlist[s][0]:
+				searchlist = searchlist[s-1:]
+		
+		s_item = searchlist[0][0]
+
+		# Undo until we reach the first shared parent
+		i = 0
+		item = current_item
+		while item is not None:
+			if item == s_item:
+				undomanager.undo(i)
+				current_item = item
+				break
+			i += 1
+			item = item.previous
+		else:
+			print "Nada (undo)"
+			return
+				
+		# Switch branches
+		for s_item in searchlist:
+			 if s_item[0].setBranch(s_item[1]) is False:
+				print "Warning: HistoryManager: Switching branch failed for: ", s_item
+			 
+		# Redo to stackitem
+		item = current_item
+		i = 0
+		while item is not None:
+			if item == stackitem:
+				undomanager.redo(i)
+				break
+			i += 1
+			item = item.next
+		else:
+			print "Nada (redo)"
+		
+		# Select the current item, important to see if the undo/redo didn't work as expected
+		self.update()
+		
+		
+	def recursiveUpdate(self, item, indention, parent=None, branchstr="-"):
+		items = []
+		
+		branchnr = 0
+		
+		class _ListItem:
+			def __init__(self, str, item, parent):
+				self.str = str
+				self.item = item
+				self.parent = parent
+				
+			def __str__(self):
+				return self.str
+		
+		while item is not None:
+			listitem = _ListItem(u" "*indention + branchstr + " " + item.object.name, item, parent)
+			items.append(listitem)
+			branchnr = -1
+			
+			for branch in item._branches:
+				branchnr += 1
+				if branchnr == 0:
+					continue
+					
+				items.extend(self.recursiveUpdate(branch, indention+2, listitem, str(branchnr)))
+			
+			if len(item._branches) > 0:
+				item = item._branches[0]
+			else:
+				break
+			#item = item.next
+
+		return items
+		
+	def update(self):
+		mapview = self.editor.getActiveMapView()
+		if mapview is None:
+			self.list.items = []
+			return
+			
+		self.undomanager = undomanager = mapview.getController().getUndoManager()
+		items = []
+		items = self.recursiveUpdate(undomanager.first_item, 0)
+
+		self.list.items = items
+		i = 0
+		for it in items:
+			if it.item == undomanager.current_item:
+				self.list.selected = i
+				break
+			i += 1
+		self.scrollarea.adaptLayout()
+
+	def show(self):
+		self.update()
+		self.gui.show()
+		self._showAction.setChecked(True)
+
+	def hide(self):
+		self.gui.setDocked(False)
+		self.gui.hide()
+		self._showAction.setChecked(False)
+		
+	def _undo(self):
+		if self.undomanager:
+			self.undomanager.undo()
+	
+	def _redo(self):
+		if self.undomanager:
+			self.undomanager.redo()
+		
+	def _next(self):
+		if self.undomanager:
+			self.undomanager.nextBranch()
+		
+	def _prev(self):
+		if self.undomanager:
+			self.undomanager.previousBranch()
+		
+	def toggle(self):
+		if self.gui.isVisible() or self.gui.isDocked():
+			self.hide()
+		else:
+			self.show()