From a7184527c392a02cf34b85f7f40f9d59348dfb26 Mon Sep 17 00:00:00 2001 From: randomguy3 Date: Mon, 30 Jan 2012 15:33:15 +0000 Subject: Undo/redo support for ordering changes git-svn-id: https://tikzit.svn.sourceforge.net/svnroot/tikzit/trunk@404 7c02a99a-9b00-45e3-bf44-6f3dd7fddb64 --- tikzit/src/common/Graph.m | 56 +++++++--- tikzit/src/common/GraphChange.h | 47 +++++++- tikzit/src/common/GraphChange.m | 242 ++++++++++------------------------------ tikzit/src/gtk/TikzDocument.m | 84 ++++++++------ 4 files changed, 199 insertions(+), 230 deletions(-) (limited to 'tikzit/src') diff --git a/tikzit/src/common/Graph.m b/tikzit/src/common/Graph.m index 8bf8dfa..cbb005e 100644 --- a/tikzit/src/common/Graph.m +++ b/tikzit/src/common/Graph.m @@ -287,6 +287,7 @@ } - (GraphChange*)bringNodesForward:(NSSet*)nodeSet { + NSArray *oldOrder = [nodes copy]; [graphLock lock]; // start at the top of the array and work backwards for (int i = [nodes count]-2; i >= 0; --i) { @@ -296,12 +297,15 @@ [self setIndex:(i+1) ofNode:[nodes objectAtIndex:i]]; } } + GraphChange *change = [GraphChange nodeOrderChangeFrom:oldOrder to:nodes moved:nodeSet]; [graphLock unlock]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)bringNodesToFront:(NSSet*)nodeSet { + NSArray *oldOrder = [nodes copy]; int i = 0, top = [nodes count]-1; while (i <= top) { @@ -312,12 +316,15 @@ ++i; } } + GraphChange *change = [GraphChange nodeOrderChangeFrom:oldOrder to:nodes moved:nodeSet]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)bringEdgesForward:(NSSet*)edgeSet { [graphLock lock]; + NSArray *oldOrder = [edges copy]; // start at the top of the array and work backwards for (int i = [edges count]-2; i >= 0; --i) { if ( [edgeSet containsObject:[edges objectAtIndex:i]] && @@ -326,12 +333,15 @@ [self setIndex:(i+1) ofEdge:[edges objectAtIndex:i]]; } } + GraphChange *change = [GraphChange edgeOrderChangeFrom:oldOrder to:edges moved:edgeSet]; [graphLock unlock]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)bringEdgesToFront:(NSSet*)edgeSet { + NSArray *oldOrder = [edges copy]; int i = 0, top = [edges count]-1; while (i <= top) { @@ -342,12 +352,15 @@ ++i; } } + GraphChange *change = [GraphChange edgeOrderChangeFrom:oldOrder to:edges moved:edgeSet]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)sendNodesBackward:(NSSet*)nodeSet { [graphLock lock]; + NSArray *oldOrder = [nodes copy]; // start at the top of the array and work backwards for (int i = 1; i < [nodes count]; ++i) { if ( [nodeSet containsObject:[nodes objectAtIndex:i]] && @@ -356,13 +369,16 @@ [self setIndex:(i-1) ofNode:[nodes objectAtIndex:i]]; } } + GraphChange *change = [GraphChange nodeOrderChangeFrom:oldOrder to:nodes moved:nodeSet]; [graphLock unlock]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)sendEdgesBackward:(NSSet*)edgeSet { [graphLock lock]; + NSArray *oldOrder = [edges copy]; // start at the top of the array and work backwards for (int i = 1; i < [edges count]; ++i) { if ( [edgeSet containsObject:[edges objectAtIndex:i]] && @@ -371,12 +387,15 @@ [self setIndex:(i-1) ofEdge:[edges objectAtIndex:i]]; } } + GraphChange *change = [GraphChange edgeOrderChangeFrom:oldOrder to:edges moved:edgeSet]; [graphLock unlock]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)sendNodesToBack:(NSSet*)nodeSet { + NSArray *oldOrder = [nodes copy]; int i = [nodes count]-1, bot = 0; while (i >= bot) { @@ -387,11 +406,14 @@ --i; } } + GraphChange *change = [GraphChange nodeOrderChangeFrom:oldOrder to:nodes moved:nodeSet]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)sendEdgesToBack:(NSSet*)edgeSet { + NSArray *oldOrder = [edges copy]; int i = [edges count]-1, bot = 0; while (i >= bot) { @@ -402,8 +424,10 @@ --i; } } + GraphChange *change = [GraphChange edgeOrderChangeFrom:oldOrder to:edges moved:edgeSet]; + [oldOrder release]; - return nil; + return change; } - (GraphChange*)insertGraph:(Graph*)g { @@ -554,18 +578,18 @@ case GraphAddition: en = [[ch affectedNodes] objectEnumerator]; while ((n = [en nextObject])) [nodes addObject:n]; - + en = [[ch affectedEdges] objectEnumerator]; while ((e = [en nextObject])) [edges addObject:e]; - + break; case GraphDeletion: en = [[ch affectedEdges] objectEnumerator]; while ((e = [en nextObject])) [edges removeObject:e]; - + en = [[ch affectedNodes] objectEnumerator]; while ((n = [en nextObject])) [nodes removeObject:n]; - + break; case NodePropertyChange: [[ch nodeRef] setPropertiesFromNode:[ch nwNode]]; @@ -609,8 +633,14 @@ case GraphPropertyChange: [self setData:[ch nwGraphData]]; break; + case NodeOrderChange: + [nodes setArray:[ch newNodeOrder]]; + break; + case EdgeOrderChange: + [edges setArray:[ch newEdgeOrder]]; + break; } - + dirty = YES; [graphLock unlock]; } diff --git a/tikzit/src/common/GraphChange.h b/tikzit/src/common/GraphChange.h index 73a912a..cb4ca09 100644 --- a/tikzit/src/common/GraphChange.h +++ b/tikzit/src/common/GraphChange.h @@ -34,7 +34,9 @@ typedef enum { NodesShift, NodesFlip, BoundingBoxChange, - GraphPropertyChange + GraphPropertyChange, + NodeOrderChange, + EdgeOrderChange } ChangeType; /*! @@ -66,6 +68,9 @@ typedef enum { NSMapTable *oldEdgeTable, *nwEdgeTable; NSRect oldBoundingBox, nwBoundingBox; GraphElementData *oldGraphData, *nwGraphData; + + NSArray *oldNodeOrder, *newNodeOrder; + NSArray *oldEdgeOrder, *newEdgeOrder; } /*! @@ -182,6 +187,30 @@ typedef enum { */ @property (copy) GraphElementData *nwGraphData; +/*! + @property oldNodeOrder + @brief The old node list. + */ +@property (copy) NSArray *oldNodeOrder; + +/*! + @property newNodeOrder + @brief The new node list. + */ +@property (copy) NSArray *newNodeOrder; + +/*! + @property oldEdgeOrder + @brief The old edge list. + */ +@property (copy) NSArray *oldEdgeOrder; + +/*! + @property newEdgeOrder + @brief The new edge list. + */ +@property (copy) NSArray *newEdgeOrder; + /*! @brief Invert a GraphChange. @details Invert a GraphChange. Calling [graph applyGraphChange:[[graph msg:...] invert]] @@ -287,6 +316,22 @@ typedef enum { */ + (GraphChange*)propertyChangeOfGraphFrom:(GraphElementData*)oldData to:(GraphElementData*)newData; +/*! + @brief Construct a node order change + @param old The old ordering + @param new The new ordering + @result A node order change + */ ++ (GraphChange*)nodeOrderChangeFrom:(NSArray*)old to:(NSArray*)new moved:(NSSet*)affected; + +/*! + @brief Construct an edge order change + @param old The old ordering + @param new The new ordering + @result A edge order change + */ ++ (GraphChange*)edgeOrderChangeFrom:(NSArray*)old to:(NSArray*)new moved:(NSSet*)affected; + @end // vi:ft=objc:noet:ts=4:sts=4:sw=4 diff --git a/tikzit/src/common/GraphChange.m b/tikzit/src/common/GraphChange.m index f9210df..02999c8 100644 --- a/tikzit/src/common/GraphChange.m +++ b/tikzit/src/common/GraphChange.m @@ -36,220 +36,84 @@ return self; } -- (ChangeType)changeType { return changeType; } +@synthesize changeType; +@synthesize shiftPoint, horizontal; +@synthesize affectedEdges, affectedNodes; +@synthesize edgeRef, nodeRef; -- (void)setChangeType:(ChangeType)ct { - changeType = ct; -} - -- (BOOL)horizontal { return horizontal; } -- (void)setHorizontal:(BOOL)b { - horizontal = b; -} - -- (NSPoint)shiftPoint { return shiftPoint; } -- (void)setShiftPoint:(NSPoint)p { - shiftPoint = p; -} - -- (NSSet*)affectedNodes { return affectedNodes; } - -- (void)setAffectedNodes:(NSSet*)set { - if (affectedNodes != set) { - [affectedNodes release]; - affectedNodes = [[NSSet alloc] initWithSet:set]; - } -} - -- (NSSet*)affectedEdges { return affectedEdges; } - -- (void)setAffectedEdges:(NSSet*)set { - if (affectedEdges != set) { - [affectedEdges release]; - affectedEdges = [[NSSet alloc] initWithSet:set]; - } -} - -- (Node*)nodeRef { return nodeRef; } - -- (void)setNodeRef:(Node*)nd { - if (nodeRef != nd) { - [nodeRef release]; - nodeRef = [nd retain]; - } -} - -- (Node*)oldNode { return oldNode; } - -- (void)setOldNode:(Node*)nd { - if (oldNode != nd) { - [oldNode release]; - oldNode = [nd copy]; - } -} - -- (Node*)nwNode { return nwNode; } - -- (void)setNwNode:(Node*)nd { - if (nwNode != nd) { - [nwNode release]; - nwNode = [nd copy]; - } -} - -- (Edge*)edgeRef { return edgeRef; } - -- (void)setEdgeRef:(Edge*)ed { - if (edgeRef != ed) { - [edgeRef release]; - edgeRef = [ed retain]; - } -} - -- (Edge*)oldEdge { return oldEdge; } - -- (void)setOldEdge:(Edge*)ed { - if (oldEdge != ed) { - [oldEdge release]; - oldEdge = [ed copy]; - } -} - -- (Edge*)nwEdge { return nwEdge; } - -- (void)setNwEdge:(Edge*)ed { - if (nwEdge != ed) { - [nwEdge release]; - nwEdge = [ed copy]; - } -} - -- (NSMapTable*)oldNodeTable { return oldNodeTable; } +@synthesize oldNode, nwNode; +@synthesize oldEdge, nwEdge; +@synthesize oldNodeTable, nwNodeTable; +@synthesize oldEdgeTable, nwEdgeTable; -- (void)setOldNodeTable:(NSMapTable*)tab { - if (oldNodeTable != tab) { - [oldNodeTable release]; - oldNodeTable = [tab retain]; - } -} - -- (NSMapTable*)nwNodeTable { return nwNodeTable; } - -- (void)setNwNodeTable:(NSMapTable*)tab { - if (nwNodeTable != tab) { - [nwNodeTable release]; - nwNodeTable = [tab retain]; - } -} - -- (NSMapTable*)oldEdgeTable { return oldEdgeTable; } - -- (void)setOldEdgeTable:(NSMapTable*)tab { - if (oldEdgeTable != tab) { - [oldEdgeTable release]; - oldEdgeTable = [tab retain]; - } -} - -- (NSMapTable*)nwEdgeTable { return nwEdgeTable; } - -- (void)setNwEdgeTable:(NSMapTable*)tab { - if (nwEdgeTable != tab) { - [nwEdgeTable release]; - nwEdgeTable = [tab retain]; - } -} - -- (NSRect)oldBoundingBox { return oldBoundingBox; } - -- (void)setOldBoundingBox:(NSRect)bbox { - oldBoundingBox = bbox; -} - -- (NSRect)nwBoundingBox { return nwBoundingBox; } - -- (void)setNwBoundingBox:(NSRect)bbox { - nwBoundingBox = bbox; -} - -- (GraphElementData*)oldGraphData { - return oldGraphData; -} - -- (void)setOldGraphData:(GraphElementData*)data { - id origOGD = oldGraphData; - oldGraphData = [data copy]; - [origOGD release]; -} +@synthesize oldBoundingBox, nwBoundingBox; -- (GraphElementData*)nwGraphData { - return nwGraphData; -} +@synthesize oldGraphData, nwGraphData; -- (void)setNwGraphData:(GraphElementData*)data { - id origNGD = nwGraphData; - nwGraphData = [data copy]; - [origNGD release]; -} +@synthesize oldNodeOrder, newNodeOrder; +@synthesize oldEdgeOrder, newEdgeOrder; - (GraphChange*)invert { GraphChange *inverse = [[GraphChange alloc] init]; + [inverse setChangeType:[self changeType]]; switch ([self changeType]) { case GraphAddition: [inverse setChangeType:GraphDeletion]; - [inverse setAffectedNodes:[self affectedNodes]]; - [inverse setAffectedEdges:[self affectedEdges]]; + inverse->affectedNodes = [affectedNodes retain]; + inverse->affectedEdges = [affectedEdges retain]; break; case GraphDeletion: [inverse setChangeType:GraphAddition]; - [inverse setAffectedNodes:[self affectedNodes]]; - [inverse setAffectedEdges:[self affectedEdges]]; + inverse->affectedNodes = [affectedNodes retain]; + inverse->affectedEdges = [affectedEdges retain]; break; case NodePropertyChange: - [inverse setChangeType:NodePropertyChange]; - [inverse setNodeRef:[self nodeRef]]; - [inverse setOldNode:[self nwNode]]; - [inverse setNwNode:[self oldNode]]; + inverse->nodeRef = [nodeRef retain]; + inverse->oldNode = [nwNode retain]; + inverse->nwNode = [oldNode retain]; break; case NodesPropertyChange: - [inverse setChangeType:NodesPropertyChange]; - [inverse setOldNodeTable:[self nwNodeTable]]; - [inverse setNwNodeTable:[self oldNodeTable]]; + inverse->oldNodeTable = [nwNodeTable retain]; + inverse->nwNodeTable = [oldNodeTable retain]; break; case EdgePropertyChange: - [inverse setChangeType:EdgePropertyChange]; - [inverse setEdgeRef:[self edgeRef]]; - [inverse setOldEdge:[self nwEdge]]; - [inverse setNwEdge:[self oldEdge]]; + inverse->edgeRef = [edgeRef retain]; + inverse->oldEdge = [nwEdge retain]; + inverse->nwEdge = [oldEdge retain]; break; case EdgesPropertyChange: - [inverse setChangeType:EdgesPropertyChange]; - [inverse setOldEdgeTable:[self nwEdgeTable]]; - [inverse setNwEdgeTable:[self oldEdgeTable]]; + inverse->oldEdgeTable = [nwEdgeTable retain]; + inverse->nwEdgeTable = [oldEdgeTable retain]; break; case NodesShift: - [inverse setChangeType:NodesShift]; - [inverse setAffectedNodes:[self affectedNodes]]; + inverse->affectedNodes = [affectedNodes retain]; [inverse setShiftPoint:NSMakePoint(-[self shiftPoint].x, -[self shiftPoint].y)]; break; case NodesFlip: - [inverse setChangeType:NodesFlip]; - [inverse setAffectedNodes:[self affectedNodes]]; + inverse->affectedNodes = [affectedNodes retain]; [inverse setHorizontal:[self horizontal]]; break; case BoundingBoxChange: - [inverse setChangeType:BoundingBoxChange]; - [inverse setOldBoundingBox:[self nwBoundingBox]]; - [inverse setNwBoundingBox:[self oldBoundingBox]]; + inverse->oldBoundingBox = nwBoundingBox; + inverse->nwBoundingBox = oldBoundingBox; break; case GraphPropertyChange: - [inverse setChangeType:GraphPropertyChange]; - [inverse setOldGraphData:[self nwGraphData]]; - [inverse setNwGraphData:[self oldGraphData]]; + inverse->oldGraphData = [nwGraphData retain]; + inverse->nwGraphData = [oldGraphData retain]; + break; + case NodeOrderChange: + inverse->affectedNodes = [affectedNodes retain]; + inverse->oldNodeOrder = [newNodeOrder retain]; + inverse->newNodeOrder = [oldNodeOrder retain]; + break; + case EdgeOrderChange: + inverse->affectedEdges = [affectedEdges retain]; + inverse->oldEdgeOrder = [newEdgeOrder retain]; + inverse->newEdgeOrder = [oldEdgeOrder retain]; break; } - + return [inverse autorelease]; } @@ -353,6 +217,24 @@ return [gc autorelease]; } ++ (GraphChange*)nodeOrderChangeFrom:(NSArray*)old to:(NSArray*)new moved:(NSSet*)affected { + GraphChange *gc = [[GraphChange alloc] init]; + [gc setChangeType:NodeOrderChange]; + [gc setAffectedNodes:affected]; + [gc setOldNodeOrder:old]; + [gc setNewNodeOrder:new]; + return [gc autorelease]; +} + ++ (GraphChange*)edgeOrderChangeFrom:(NSArray*)old to:(NSArray*)new moved:(NSSet*)affected { + GraphChange *gc = [[GraphChange alloc] init]; + [gc setChangeType:EdgeOrderChange]; + [gc setAffectedEdges:affected]; + [gc setOldEdgeOrder:old]; + [gc setNewEdgeOrder:new]; + return [gc autorelease]; +} + @end // vi:ft=objc:ts=4:noet:sts=4:sw=4 diff --git a/tikzit/src/gtk/TikzDocument.m b/tikzit/src/gtk/TikzDocument.m index 8672266..40411d9 100644 --- a/tikzit/src/gtk/TikzDocument.m +++ b/tikzit/src/gtk/TikzDocument.m @@ -697,20 +697,23 @@ if (!hasNodeSelection && !hasEdgeSelection) return; - //[self startUndoGroup]; + [self startUndoGroup]; + GraphChange *nodeChange; + GraphChange *edgeChange; if (hasNodeSelection) { - /*GraphChange *change =*/ - [graph bringNodesForward:[pickSupport selectedNodes]]; - //[self registerUndoForChange:change]; + nodeChange = [graph bringNodesForward:[pickSupport selectedNodes]]; + [self registerUndoForChange:nodeChange]; } if (hasEdgeSelection) { - /*GraphChange *change =*/ - [graph bringEdgesForward:[pickSupport selectedEdges]]; - //[self registerUndoForChange:change]; + edgeChange = [graph bringEdgesForward:[pickSupport selectedEdges]]; + [self registerUndoForChange:edgeChange]; } - //[self nameAndEndUndoGroup:@"Bring forward"]; + [self nameAndEndUndoGroup:@"Bring forward"]; [self regenerateTikz]; - //[self postGraphChange:change]; + if (hasNodeSelection) + [self postGraphChange:nodeChange]; + if (hasEdgeSelection) + [self postGraphChange:edgeChange]; } - (void) bringSelectionToFront { @@ -719,20 +722,23 @@ if (!hasNodeSelection && !hasEdgeSelection) return; - //[self startUndoGroup]; + [self startUndoGroup]; + GraphChange *nodeChange; + GraphChange *edgeChange; if (hasNodeSelection) { - /*GraphChange *change =*/ - [graph bringNodesToFront:[pickSupport selectedNodes]]; - //[self registerUndoForChange:change]; + nodeChange = [graph bringNodesToFront:[pickSupport selectedNodes]]; + [self registerUndoForChange:nodeChange]; } if (hasEdgeSelection) { - /*GraphChange *change =*/ - [graph bringEdgesToFront:[pickSupport selectedEdges]]; - //[self registerUndoForChange:change]; + edgeChange = [graph bringEdgesToFront:[pickSupport selectedEdges]]; + [self registerUndoForChange:edgeChange]; } - //[self nameAndEndUndoGroup:@"Bring to front"]; + [self nameAndEndUndoGroup:@"Bring to front"]; [self regenerateTikz]; - //[self postGraphChange:change]; + if (hasNodeSelection) + [self postGraphChange:nodeChange]; + if (hasEdgeSelection) + [self postGraphChange:edgeChange]; } - (void) sendSelectionBackward { @@ -741,20 +747,23 @@ if (!hasNodeSelection && !hasEdgeSelection) return; - //[self startUndoGroup]; + [self startUndoGroup]; + GraphChange *nodeChange; + GraphChange *edgeChange; if (hasNodeSelection) { - /*GraphChange *change =*/ - [graph sendNodesBackward:[pickSupport selectedNodes]]; - //[self registerUndoForChange:change]; + nodeChange = [graph sendNodesBackward:[pickSupport selectedNodes]]; + [self registerUndoForChange:nodeChange]; } if (hasEdgeSelection) { - /*GraphChange *change =*/ - [graph sendNodesBackward:[pickSupport selectedEdges]]; - //[self registerUndoForChange:change]; + edgeChange = [graph sendNodesBackward:[pickSupport selectedEdges]]; + [self registerUndoForChange:edgeChange]; } - //[self nameAndEndUndoGroup:@"Send backward"]; + [self nameAndEndUndoGroup:@"Send backward"]; [self regenerateTikz]; - //[self postGraphChange:change]; + if (hasNodeSelection) + [self postGraphChange:nodeChange]; + if (hasEdgeSelection) + [self postGraphChange:edgeChange]; } - (void) sendSelectionToBack { @@ -763,20 +772,23 @@ if (!hasNodeSelection && !hasEdgeSelection) return; - //[self startUndoGroup]; + [self startUndoGroup]; + GraphChange *nodeChange; + GraphChange *edgeChange; if (hasNodeSelection) { - /*GraphChange *change =*/ - [graph sendNodesToBack:[pickSupport selectedNodes]]; - //[self registerUndoForChange:change]; + nodeChange = [graph sendNodesToBack:[pickSupport selectedNodes]]; + [self registerUndoForChange:nodeChange]; } if (hasEdgeSelection) { - /*GraphChange *change =*/ - [graph sendNodesToBack:[pickSupport selectedEdges]]; - //[self registerUndoForChange:change]; + edgeChange = [graph sendNodesToBack:[pickSupport selectedEdges]]; + [self registerUndoForChange:edgeChange]; } - //[self nameAndEndUndoGroup:@"Send to back"]; + [self nameAndEndUndoGroup:@"Send to back"]; [self regenerateTikz]; - //[self postGraphChange:change]; + if (hasNodeSelection) + [self postGraphChange:nodeChange]; + if (hasEdgeSelection) + [self postGraphChange:edgeChange]; } - (BOOL) saveCopyToPath: (NSString*)p error: (NSError**)error { -- cgit v1.2.3