--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2008 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
+
+#import <Foundation/Foundation.h>
+
+#include <graphviz/types.h>
+#include <graphviz/graph.h>
+
+@class GVGraph;
+
+@interface GVGraphDefaultAttributes : NSMutableDictionary
+{
+ GVGraph *_graph;
+ Agdict_t *_defaultAttributes;
+ Agsym_t *(*_attributeDeclaration)(Agraph_t *, char *, char *);
+}
+
+@property(readonly) NSString *name;
+
+- (id)initWithGraph:(GVGraph *)graph defaultAttributes:(Agdict_t *)defaultAttributes attributeDeclaration:(Agsym_t *(*)(Agraph_t *, char *, char *))attributeDeclaration;
+
+/* dictionary primitive methods */
+- (NSUInteger)count;
+- (NSEnumerator *)keyEnumerator;
+- (id)objectForKey:(id)aKey;
+
+/* mutable dictionary primitive methods */
+- (void)setObject:(id)anObject forKey:(id)aKey;
+- (void)removeObjectForKey:(id)aKey;
+
+@end
--- /dev/null
+/* $Id$ $Revision$ */
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2008 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
+
+#import "GVGraphDefaultAttributes.h"
+#import "GVGraph.h"
+
+@interface GVGraphDefaultAttributeKeyEnumerator : NSEnumerator
+{
+ Agsym_t **_nextSymbol;
+ Agsym_t **_lastSymbol;
+}
+
+- (id)initWithSymbols:(Agsym_t **)symbols count:(NSUInteger)count;
+- (NSArray *)allObjects;
+- (id)nextObject;
+
+@end
+
+@implementation GVGraphDefaultAttributeKeyEnumerator
+
+- (id)initWithSymbols:(Agsym_t **)symbols count:(NSUInteger)count
+{
+ if (self = [super init]) {
+ _nextSymbol = symbols;
+ _lastSymbol = symbols + count;
+ }
+ return self;
+}
+
+- (NSArray *)allObjects
+{
+ NSMutableArray* all = [NSMutableArray array];
+ for (; _nextSymbol < _lastSymbol; ++_nextSymbol)
+ if ((*_nextSymbol)->value && *(*_nextSymbol)->value)
+ [all addObject:[NSString stringWithUTF8String:(*_nextSymbol)->name]];
+
+ return all;
+}
+
+- (id)nextObject
+{
+ char* nextName = NULL;
+ for (; _nextSymbol < _lastSymbol && !nextName; ++_nextSymbol)
+ if ((*_nextSymbol)->value && *(*_nextSymbol)->value)
+ nextName = (*_nextSymbol)->name;
+
+ return nextName ? [NSString stringWithUTF8String:nextName] : nil;
+}
+
+@end
+
+@implementation GVGraphDefaultAttributes
+
+- (id)initWithGraph:(GVGraph *)graph defaultAttributes:(Agdict_t *)defaultAttributes attributeDeclaration:(Agsym_t *(*)(Agraph_t *, char *, char *))attributeDeclaration
+{
+ if (self = [super init]) {
+ _graph = graph; /* not retained to avoid a retain cycle */
+ _defaultAttributes = defaultAttributes;
+ _attributeDeclaration = attributeDeclaration;
+ }
+ return self;
+}
+
+- (NSString*)name
+{
+ return _defaultAttributes->name ? [NSString stringWithUTF8String:_defaultAttributes->name] : nil;
+}
+
+- (NSUInteger)count
+{
+ NSUInteger symbolCount = 0;
+ Agsym_t **nextSymbol, **lastSymbol;
+ for (nextSymbol = _defaultAttributes->list, lastSymbol = _defaultAttributes->list + dtsize(_defaultAttributes->dict); nextSymbol < lastSymbol; ++nextSymbol)
+ if ((*nextSymbol)->value && *(*nextSymbol)->value)
+ ++symbolCount;
+ return symbolCount;
+}
+
+- (NSEnumerator *)keyEnumerator
+{
+ return [[[GVGraphDefaultAttributeKeyEnumerator alloc] initWithSymbols: _defaultAttributes->list count:dtsize(_defaultAttributes->dict)] autorelease];
+}
+
+- (id)objectForKey:(id)aKey
+{
+ id object = nil;
+ Agsym_t *attributeSymbol = dtmatch(_defaultAttributes->dict, [aKey UTF8String]);
+ if (attributeSymbol) {
+ char *attributeValue = attributeSymbol->value;
+ if (attributeValue && *attributeValue)
+ object = [NSString stringWithUTF8String:attributeSymbol->value];
+ }
+ return object;
+}
+
+- (void)setObject:(id)anObject forKey:(id)aKey
+{
+ _attributeDeclaration([_graph graph], (char *)[aKey UTF8String], (char *)[anObject UTF8String]);
+ [_graph noteChanged:YES];
+}
+
+- (void)removeObjectForKey:(id)aKey
+{
+ _attributeDeclaration([_graph graph], (char *)[aKey UTF8String], "");
+ [_graph noteChanged:YES];
+}
+@end
#import <AppKit/AppKit.h>
#import <Quartz/Quartz.h>
+@class GVGraph;
+
@interface GVWindowController : NSWindowController
{
IBOutlet PDFView *documentView;
+
+ GVGraph *_graph;
}
-- (void)windowDidLoad;
+@property(readonly) GVGraph *graph;
+
+- (id)init;
+- (void)setDocument: (NSDocument *)document;
+- (void)awakeFromNib;
+
+- (void)graphDidChange:(NSNotification*)notification;
+- (void)dealloc;
@end
**********************************************************/
#import "GVWindowController.h"
-#import "GVContext.h"
+#import "GVGraph.h"
#import "GVDocument.h"
@implementation GVWindowController
-- (void)windowDidLoad
+@synthesize graph = _graph;
+
+- (id)init
+{
+ if (self = [super initWithWindowNibName: @"Document"])
+ _graph = nil;
+ return self;
+}
+
+- (void)setDocument: (NSDocument *)document
{
- GVDocument *graphDocument = [self document];
- if ([graphDocument respondsToSelector:@selector(graph)]) {
- graph_t *graph = [graphDocument graph];
- GVContext* context = [GVContext sharedContext];
- [context layoutGraph:graph withEngine:@"dot"];
- [documentView setDocument:[[[PDFDocument alloc] initWithData:[context renderGraph:graph withFormat:@"pdf:quartz"]] autorelease]];
+ if ([document respondsToSelector:@selector(graph)]) {
+ GVGraph *newGraph = [(GVDocument *)document graph];
+ if (_graph != newGraph) {
+ /* retain the new document graph and start observing any changes from it */
+ NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
+ if (_graph) {
+ [defaultCenter removeObserver:self name:@"GVGraphDidChange" object:_graph];
+ [_graph release];
+ }
+ _graph = nil;
+ if (newGraph) {
+ _graph = [newGraph retain];
+ [defaultCenter addObserver:self selector:@selector(graphDidChange:) name:@"GVGraphDidChange" object:newGraph];
+ }
+ }
}
+
+ [super setDocument:document];
+}
+
+- (void)awakeFromNib
+{
+ [self graphDidChange:nil];
+}
+
+- (void)graphDidChange:(NSNotification*)notification
+{
+ /* whenever the graph changes, rerender its PDF and display that */
+ [documentView setDocument:[[[PDFDocument alloc] initWithData:[_graph renderWithFormat:@"pdf:quartz"]] autorelease]];
+}
+
+- (void)dealloc
+{
+ if (_graph) {
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:@"GVGraphDidChange" object:_graph];
+ [_graph release];
+ }
+
+ [super dealloc];
}
@end