summaryrefslogtreecommitdiff
path: root/tikzit-1/src/osx
diff options
context:
space:
mode:
Diffstat (limited to 'tikzit-1/src/osx')
-rw-r--r--tikzit-1/src/osx/AppDelegate.h57
-rw-r--r--tikzit-1/src/osx/AppDelegate.m124
-rw-r--r--tikzit-1/src/osx/CALayer+DrawLabel.h21
-rw-r--r--tikzit-1/src/osx/CALayer+DrawLabel.m84
-rw-r--r--tikzit-1/src/osx/CoreGraphicsRenderContext.h44
-rw-r--r--tikzit-1/src/osx/CoreGraphicsRenderContext.m234
-rw-r--r--tikzit-1/src/osx/CustomNodeCellView.h23
-rw-r--r--tikzit-1/src/osx/CustomNodeCellView.m83
-rw-r--r--tikzit-1/src/osx/CustomNodeController.h35
-rw-r--r--tikzit-1/src/osx/CustomNodeController.m58
-rw-r--r--tikzit-1/src/osx/CustomNodes.xib249
-rw-r--r--tikzit-1/src/osx/DraggablePDFView.h28
-rw-r--r--tikzit-1/src/osx/DraggablePDFView.m60
-rw-r--r--tikzit-1/src/osx/EdgeControlLayer.h44
-rw-r--r--tikzit-1/src/osx/EdgeControlLayer.m150
-rw-r--r--tikzit-1/src/osx/EdgeStyle+Coder.h30
-rw-r--r--tikzit-1/src/osx/EdgeStyle+Coder.m50
-rw-r--r--tikzit-1/src/osx/Graph+Coder.h17
-rw-r--r--tikzit-1/src/osx/Graph+Coder.m24
-rw-r--r--tikzit-1/src/osx/GraphicsView.h129
-rw-r--r--tikzit-1/src/osx/GraphicsView.m1216
-rw-r--r--tikzit-1/src/osx/Grid.h48
-rw-r--r--tikzit-1/src/osx/Grid.m152
-rw-r--r--tikzit-1/src/osx/MultiCombo.h18
-rw-r--r--tikzit-1/src/osx/MultiCombo.m38
-rw-r--r--tikzit-1/src/osx/MultiField.h18
-rw-r--r--tikzit-1/src/osx/MultiField.m53
-rw-r--r--tikzit-1/src/osx/NilToEmptyStringTransformer.h28
-rw-r--r--tikzit-1/src/osx/NilToEmptyStringTransformer.m53
-rw-r--r--tikzit-1/src/osx/NodeLayer.h62
-rw-r--r--tikzit-1/src/osx/NodeLayer.m238
-rw-r--r--tikzit-1/src/osx/NodeSelectionLayer.h45
-rw-r--r--tikzit-1/src/osx/NodeSelectionLayer.m93
-rw-r--r--tikzit-1/src/osx/NodeStyle+Coder.h36
-rw-r--r--tikzit-1/src/osx/NodeStyle+Coder.m91
-rw-r--r--tikzit-1/src/osx/ParseErrorView.h13
-rw-r--r--tikzit-1/src/osx/ParseErrorView.m40
-rw-r--r--tikzit-1/src/osx/PreambleController.h57
-rw-r--r--tikzit-1/src/osx/PreambleController.m168
-rw-r--r--tikzit-1/src/osx/Preambles+Coder.h32
-rw-r--r--tikzit-1/src/osx/Preambles+Coder.m41
-rw-r--r--tikzit-1/src/osx/PreferenceController.h49
-rw-r--r--tikzit-1/src/osx/PreferenceController.m133
-rw-r--r--tikzit-1/src/osx/Preferences.xib1165
-rw-r--r--tikzit-1/src/osx/PreviewController.h52
-rw-r--r--tikzit-1/src/osx/PreviewController.m147
-rw-r--r--tikzit-1/src/osx/PropertyInspectorController.h83
-rw-r--r--tikzit-1/src/osx/PropertyInspectorController.m280
-rw-r--r--tikzit-1/src/osx/SelectBoxLayer.h22
-rw-r--r--tikzit-1/src/osx/SelectBoxLayer.m48
-rw-r--r--tikzit-1/src/osx/SelectableCollectionViewItem.h33
-rw-r--r--tikzit-1/src/osx/SelectableCollectionViewItem.m54
-rw-r--r--tikzit-1/src/osx/SelectableNodeView.h38
-rw-r--r--tikzit-1/src/osx/SelectableNodeView.m96
-rw-r--r--tikzit-1/src/osx/StylePaletteController.h80
-rw-r--r--tikzit-1/src/osx/StylePaletteController.m252
-rw-r--r--tikzit-1/src/osx/TikzDocument.h37
-rw-r--r--tikzit-1/src/osx/TikzDocument.m84
-rw-r--r--tikzit-1/src/osx/TikzFormatter.h29
-rw-r--r--tikzit-1/src/osx/TikzFormatter.m91
-rw-r--r--tikzit-1/src/osx/TikzSourceController.h71
-rw-r--r--tikzit-1/src/osx/TikzSourceController.m241
-rw-r--r--tikzit-1/src/osx/TikzWindowController.h31
-rw-r--r--tikzit-1/src/osx/TikzWindowController.m66
-rw-r--r--tikzit-1/src/osx/ToolPaletteController.h42
-rw-r--r--tikzit-1/src/osx/ToolPaletteController.m58
-rw-r--r--tikzit-1/src/osx/UpdatePreferenceController.h34
-rw-r--r--tikzit-1/src/osx/UpdatePreferenceController.m49
-rw-r--r--tikzit-1/src/osx/UpdatePreferencePanel.xib95
-rw-r--r--tikzit-1/src/osx/main.m26
-rw-r--r--tikzit-1/src/osx/test/main.m56
-rw-r--r--tikzit-1/src/osx/test/osx.m64
72 files changed, 7690 insertions, 0 deletions
diff --git a/tikzit-1/src/osx/AppDelegate.h b/tikzit-1/src/osx/AppDelegate.h
new file mode 100644
index 0000000..92d9add
--- /dev/null
+++ b/tikzit-1/src/osx/AppDelegate.h
@@ -0,0 +1,57 @@
+//
+// AppDelegate.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "StylePaletteController.h"
+#import "ToolPaletteController.h"
+#import "PropertyInspectorController.h"
+#import "PreambleController.h"
+#import "PreviewController.h"
+#import "GraphicsView.h"
+#import "PreferenceController.h"
+
+@interface AppDelegate : NSObject {
+ NSMapTable *table;
+ StylePaletteController *stylePaletteController;
+ PropertyInspectorController *propertyInspectorController;
+ PreambleController *preambleController;
+ PreviewController *previewController;
+ PreferenceController *preferenceController;
+ ToolPaletteController *toolPaletteController;
+ IBOutlet GraphicsView *graphicsView;
+ NSString *tempDir;
+}
+
+@property IBOutlet StylePaletteController *stylePaletteController;
+@property (strong) IBOutlet ToolPaletteController *toolPaletteController;
+
+- (void)awakeFromNib;
++ (void)setDefaults;
+- (void)applicationWillTerminate:(NSNotification *)notification;
+- (IBAction)toggleStyleInspector:(id)sender;
+- (IBAction)togglePropertyInspector:(id)sender;
+- (IBAction)togglePreamble:(id)sender;
+- (IBAction)togglePreferences:(id)sender;
+- (IBAction)refreshShapes:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/AppDelegate.m b/tikzit-1/src/osx/AppDelegate.m
new file mode 100644
index 0000000..94f5507
--- /dev/null
+++ b/tikzit-1/src/osx/AppDelegate.m
@@ -0,0 +1,124 @@
+//
+// AppDelegate.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "AppDelegate.h"
+#import "TikzDocument.h"
+#import "Shape.h"
+#import "SupportDir.h"
+
+@implementation AppDelegate
+
+@synthesize stylePaletteController, toolPaletteController;
+
++(void)initialize{
+ [self setDefaults];
+}
+
+- (void)awakeFromNib {
+ [SupportDir createUserSupportDir];
+ NSString *supportDir = [SupportDir userSupportDir];
+ //NSLog(stylePlist);
+ stylePaletteController =
+ [[StylePaletteController alloc] initWithWindowNibName:@"StylePalette"
+ supportDir:supportDir];
+
+ propertyInspectorController =
+ [[PropertyInspectorController alloc] initWithWindowNibName:@"PropertyInspector"];
+
+ [propertyInspectorController setStylePaletteController:stylePaletteController];
+
+ NSString *preamblePlist = [supportDir stringByAppendingPathComponent:@"preambles.plist"];
+ preambleController =
+ [[PreambleController alloc] initWithNibName:@"Preamble"
+ plist:preamblePlist
+ styles:[stylePaletteController nodeStyles]
+ edges:[stylePaletteController edgeStyles]];
+
+
+ char template[] = "/tmp/tikzit_tmp_XXXXXXX";
+ char *dir = mkdtemp(template);
+ tempDir = [NSString stringWithUTF8String:dir];
+
+ NSLog(@"created temp dir: %@", tempDir);
+ NSLog(@"system support dir: %@", [SupportDir systemSupportDir]);
+
+ previewController =
+ [[PreviewController alloc] initWithWindowNibName:@"Preview"
+ preambleController:preambleController
+ tempDir:tempDir];
+
+ preferenceController = [[PreferenceController alloc] initWithWindowNibName:@"Preferences" preambleController:preambleController];
+
+ // each application has one global preview controller
+ [PreviewController setDefaultPreviewController:previewController];
+}
+
++ (void)setDefaults{
+ NSString *userDefaultsValuesPath;
+ NSDictionary *userDefaultsValuesDict;
+
+ userDefaultsValuesPath=[[NSBundle mainBundle] pathForResource:@"UserDefaults"
+ ofType:@"plist"];
+ userDefaultsValuesDict=[NSDictionary dictionaryWithContentsOfFile:userDefaultsValuesPath];
+
+ [[NSUserDefaults standardUserDefaults] registerDefaults:userDefaultsValuesDict];
+}
+
+- (void)applicationWillTerminate:(NSNotification *)notification {
+ NSString *supportDir = [SupportDir userSupportDir];
+ [stylePaletteController saveStyles:supportDir];
+ [preambleController savePreambles:[supportDir stringByAppendingPathComponent:@"preambles.plist"]];
+
+ NSLog(@"wiping temp dir: %@", tempDir);
+ [[NSFileManager defaultManager] removeItemAtPath:tempDir error:NULL];
+}
+
+- (void)toggleController:(NSWindowController*)c {
+ if ([[c window] isVisible]) {
+ [c close];
+ } else {
+ [c showWindow:self];
+ }
+}
+
+- (IBAction)toggleStyleInspector:(id)sender {
+ [self toggleController:stylePaletteController];
+}
+
+- (IBAction)togglePropertyInspector:(id)sender {
+ [self toggleController:propertyInspectorController];
+}
+
+- (IBAction)togglePreamble:(id)sender {
+ [self toggleController:(NSWindowController *) preambleController];
+}
+
+- (IBAction)togglePreferences:(id)sender {
+ [self toggleController:preferenceController];
+}
+
+- (IBAction)refreshShapes:(id)sender {
+ [Shape refreshShapeDictionary];
+}
+
+@end
diff --git a/tikzit-1/src/osx/CALayer+DrawLabel.h b/tikzit-1/src/osx/CALayer+DrawLabel.h
new file mode 100644
index 0000000..32282d9
--- /dev/null
+++ b/tikzit-1/src/osx/CALayer+DrawLabel.h
@@ -0,0 +1,21 @@
+//
+// CALayer+DrawLabel.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 09/05/2011.
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+
+@class Transformer;
+
+@interface CALayer(DrawLabel)
+
+- (void)drawLabel:(NSString*)label
+ atPoint:(NSPoint)pt
+ inContext:(CGContextRef)context
+ usingTrans:(Transformer*)t;
+
+@end
diff --git a/tikzit-1/src/osx/CALayer+DrawLabel.m b/tikzit-1/src/osx/CALayer+DrawLabel.m
new file mode 100644
index 0000000..4860a3c
--- /dev/null
+++ b/tikzit-1/src/osx/CALayer+DrawLabel.m
@@ -0,0 +1,84 @@
+//
+// CALayer+DrawLabel.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 09/05/2011.
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+
+#import "CALayer+DrawLabel.h"
+#import "Transformer.h"
+
+@implementation CALayer(DrawLabel)
+
+- (void)drawLabel:(NSString*)label
+ atPoint:(NSPoint)pt
+ inContext:(CGContextRef)context
+ usingTrans:(Transformer*)t {
+
+ CGContextSaveGState(context);
+
+ if ([label length] > 15) {
+ label = [[label substringToIndex:12] stringByAppendingString:@"..."];
+ }
+
+ float fontSize = [t scaleToScreen:0.18f]; // size 9 @ 100%
+ if (fontSize > 18.0f) fontSize = 18.0f;
+
+ // Prepare font
+ CTFontRef font = CTFontCreateWithName(CFSTR("Monaco"), fontSize, NULL);
+
+ // Create an attributed string
+ CFStringRef keys[] = { kCTFontAttributeName };
+ CFTypeRef values[] = { font };
+ CFDictionaryRef attr = CFDictionaryCreate(NULL,
+ (const void **)&keys,
+ (const void **)&values,
+ sizeof(keys) / sizeof(keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CFAttributedStringRef attrString =
+ CFAttributedStringCreate(NULL, (CFStringRef)label, attr);
+ CFRelease(attr);
+
+ // Draw the string
+ CTLineRef line = CTLineCreateWithAttributedString(attrString);
+ CGContextSetTextMatrix(context, CGAffineTransformIdentity);
+ CGContextSetTextPosition(context, 0, 0);
+
+ CGRect labelBounds = CGRectIntegral(CTLineGetImageBounds(line, context));
+ //int shiftx = round(labelBounds.size.width / 2);
+
+ CGContextSetTextPosition(context,
+ round(pt.x - (labelBounds.size.width/2)),
+ round(pt.y - (0.9*labelBounds.size.height/2)));
+
+ labelBounds = CGRectIntegral(CTLineGetImageBounds(line, context));
+ labelBounds.origin.x -= 2;
+ labelBounds.origin.y -= 2;
+ labelBounds.size.width += 4;
+ labelBounds.size.height += 4;
+
+ CGContextSetShouldAntialias(context, NO);
+
+ CGContextSetRGBFillColor(context, 1.0f, 1.0f, 0.5f, 0.7f);
+ CGContextSetRGBStrokeColor(context, 0.5f, 0.0f, 0.0f, 0.7f);
+
+ CGContextFillRect(context, labelBounds);
+ CGContextStrokeRect(context, labelBounds);
+
+ CGContextSetShouldAntialias(context, YES);
+
+ CGContextSetRGBFillColor(context, 0.3f, 0.3f, 0.3f, 0.7f);
+
+ CTLineDraw(line, context);
+
+ // Clean up
+ CFRelease(line);
+ CFRelease(attrString);
+ CFRelease(font);
+
+ CGContextRestoreGState(context);
+}
+
+@end
diff --git a/tikzit-1/src/osx/CoreGraphicsRenderContext.h b/tikzit-1/src/osx/CoreGraphicsRenderContext.h
new file mode 100644
index 0000000..7b00484
--- /dev/null
+++ b/tikzit-1/src/osx/CoreGraphicsRenderContext.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 Alex Merry <alex.merry@kdemail.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "RenderContext.h"
+
+@interface CoreTextLayout: NSObject<TextLayout> {
+ CFAttributedStringRef attrString;
+ CTFontRef font;
+ CTLineRef line;
+ CGContextRef ctx;
+}
+
++ (CoreTextLayout*) layoutForContext:(CGContextRef)c withString:(NSString*)string fontSize:(CGFloat)fontSize;
+- (id) initWithContext:(CGContextRef)cr withString:(NSString*)string fontSize:(CGFloat)fontSize;
+
+@end
+
+@interface CoreGraphicsRenderContext: NSObject<RenderContext> {
+ CGContextRef ctx;
+}
+
++ (CoreGraphicsRenderContext*) contextWithCGContext:(CGContextRef)c;
++ (id) initWithCGContext:(CGContextRef)c;
+
+- (CGContextRef) ctx;
+
+@end
+
+// vim:ft=objc:ts=4:noet:sts=4:sw=4
diff --git a/tikzit-1/src/osx/CoreGraphicsRenderContext.m b/tikzit-1/src/osx/CoreGraphicsRenderContext.m
new file mode 100644
index 0000000..1cb0daf
--- /dev/null
+++ b/tikzit-1/src/osx/CoreGraphicsRenderContext.m
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2011 Alex Merry <alex.merry@kdemail.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import <Cocoa/Cocoa.h>
+#import "RenderContext.h"
+
+@implementation CoreTextLayout
+
++ (CoreTextLayout*) layoutForContext:(CGContextRef)c withString:(NSString*)string fontSize:(CGFloat)fontSize {
+ return [[[self alloc] initWithContext:c withString:string fontSize:fontSize] autorelease];
+}
+
+- (id) initWithContext:(CGContextRef)cr withString:(NSString*)string fontSize:(CGFloat)fontSize {
+ self = [super init];
+
+ if (self == nil) {
+ return nil;
+ }
+
+ CGContextRetain (cr);
+ ctx = cr;
+ font = CTFontCreateWithName(CFSTR("Monaco"), fontSize, NULL);
+
+ // Create an attributed string
+ CFStringRef keys[] = { kCTFontAttributeName };
+ CFTypeRef values[] = { font };
+ CFDictionaryRef attr = CFDictionaryCreate(NULL,
+ (const void **)&keys,
+ (const void **)&values,
+ sizeof(keys) / sizeof(keys[0]),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ attrString = CFAttributedStringCreate(NULL, (CFStringRef)lab, attr);
+ CFRelease(attr);
+ line = CTLineCreateWithAttributedString(attrString);
+
+ return self;
+}
+
+- (NSSize) size {
+ CGRect labelBounds = CGRectIntegral(CTLineGetImageBounds(line, ctx));
+ return labelBounds.size;
+}
+
+- (NSString*) text {
+ return CFAttributedStringGetString (attrString);
+}
+
+- (void) showTextAt:(NSPoint)topLeft withColor:(RColor)color {
+ CGContextSaveGState(ctx);
+
+ CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextSetRGBStrokeColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextSetShouldAntialias(ctx, YES);
+
+ CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
+ CGContextSetTextPosition(ctx, 0, 0);
+ CGRect bounds = CGRectIntegral(CTLineGetImageBounds(line, ctx));
+ CGContextSetTextPosition(ctx, topLeft.x - bounds.x, topLeft.y - bounds.y);
+
+ CTLineDraw(line, ctx);
+
+ CGContextRestoreGState(ctx);
+}
+
+- (void) dealloc {
+ CFRelease(line);
+ CFRelease(attrString);
+ CFRelease(font);
+ CGContextRelease (ctx);
+
+ [super dealloc];
+}
+
+@end
+
+@implementation CoreGraphicsRenderContext
+
++ (CoreGraphicsRenderContext*) contextWithCGContext:(CGContextRef)c {
+ return [[[self alloc] initWithCGContext:c] autorelease];
+}
+
++ (id) initWithCGContext:(CGContextRef)c {
+ self = [super init];
+
+ if (self) {
+ ctx = c;
+ CGContextRetain (ctx);
+ }
+
+ return self;
+}
+
+- (void) dealloc {
+ CGContextRelease (ctx);
+
+ [super dealloc];
+}
+
+- (CGContextRef) ctx {
+ return ctx;
+}
+
+- (void) saveState {
+ CGContextSaveGState(ctx);
+}
+
+- (void) restoreState {
+ CGContextRestoreGState(ctx);
+}
+
+- (NSRect) clipBoundingBox {
+ return CGContextGetClipBoundingBox (ctx);
+}
+
+- (BOOL) strokeIncludesPoint:(NSPoint)p {
+ return CGContextPathContainsPoint(ctx, NSPointToCGPoint(p), kCGPathStroke);
+}
+
+- (BOOL) fillIncludesPoint:(NSPoint)p {
+ return CGContextPathContainsPoint(ctx, NSPointToCGPoint(p), kCGPathFill);
+}
+
+- (id<TextLayout>) layoutText:(NSString*)text withSize:(CGFloat)fontSize {
+ return [CoreTextLayout layoutForContext:ctx withString:text fontSize:fontSize];
+}
+
+// this may not affect text rendering
+- (void) setAntialiasMode:(AntialiasMode)mode {
+ CGContextSetShouldAntialias(ctx, mode != AntialiasDisabled);
+}
+
+- (void) setLineWidth:(CGFloat)width {
+ CGContextSetLineWidth(ctx, width);
+}
+
+// setting to 0 will unset the dash
+- (void) setLineDash:(CGFloat)dashLength {
+ if (dashLength <= 0.0f) {
+ CGContextSetLineDash(ctx, 0.0f, NULL, 0);
+ } else {
+ const CGFloat dash[] = {dashLength, dashLength};
+ CGContextSetLineDash(ctx, 0.0f, dash, 2);
+ }
+}
+
+// paths
+- (void) startPath {
+ CGContextBeginPath (ctx);
+}
+
+- (void) closeSubPath {
+ CGContextClosePath (ctx);
+}
+
+- (void) moveTo:(NSPoint)p {
+ CGContextMoveToPoint (ctx, p.x, p.y);
+}
+
+- (void) curveTo:(NSPoint)end withCp1:(NSPoint)cp1 andCp2:(NSPoint)cp2 {
+ CGContextAddCurveToPoint(ctx, cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);
+}
+
+- (void) lineTo:(NSPoint)end {
+ CGContextAddLineToPoint(ctx, end.x, end.y);
+}
+
+- (void) rect:(NSRect)rect {
+ CGContextAddRect (ctx, rect);
+}
+
+- (void) circleAt:(NSPoint)c withRadius:(CGFloat)r {
+ CGContextMoveToPoint (ctx, c.x + r, c.y);
+ CGContextAddArc (ctx, c.x, c.y, r, 0.0f, M_PI, 1);
+}
+
+// these methods clear the path
+- (void) strokePathWithColor:(RColor)color {
+ CGContextSetRGBStrokeColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextDrawPath (ctx, kCGPathStroke);
+}
+
+- (void) fillPathWithColor:(RColor)color {
+ CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextDrawPath (ctx, kCGPathFill);
+}
+
+- (void) strokePathWithColor:(RColor)scolor
+ andFillWithColor:(RColor)fcolor {
+ CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextSetRGBStrokeColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGContextDrawPath (ctx, kCGPathFillStroke);
+}
+
+- (void) strokePathWithColor:(RColor)scolor
+ andFillWithColor:(RColor)fcolor
+ usingAlpha:(CGFloat)alpha {
+ CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha * alpha);
+ CGContextSetRGBStrokeColor(ctx, color.red, color.green, color.blue, color.alpha * alpha);
+ CGContextDrawPath (ctx, kCGPathFillStroke);
+}
+
+- (void) clipToPath {
+ CGContextClip (ctx);
+}
+
+// paint everywhere within the clip
+- (void) paintWithColor:(RColor)color {
+ CGContextSetRGBFillColor(ctx, color.red, color.green, color.blue, color.alpha);
+ CGRect r = CGContextGetClipBoundingBox (ctx);
+ r.origin.x -= 1;
+ r.origin.y -= 1;
+ r.size.width += 2;
+ r.size.height += 2;
+ CGContextFillRect(context, r);
+}
+
+@end
+
+// vim:ft=objc:ts=4:noet:sts=4:sw=4
diff --git a/tikzit-1/src/osx/CustomNodeCellView.h b/tikzit-1/src/osx/CustomNodeCellView.h
new file mode 100644
index 0000000..22606d7
--- /dev/null
+++ b/tikzit-1/src/osx/CustomNodeCellView.h
@@ -0,0 +1,23 @@
+//
+// CustomNodeCellView.h
+// TikZiT
+//
+// Created by Johan Paulsson on 12/12/13.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+#import "NodeLayer.h"
+#import "NodeStyle.h"
+#import "NodeStyle+Coder.h"
+
+@interface CustomNodeCellView : NSTableCellView{
+ NodeLayer *nodeLayer;
+ NodeStyle *nodeStyle;
+ BOOL selected;
+}
+
+@property (strong) id objectValue;
+
+@end
diff --git a/tikzit-1/src/osx/CustomNodeCellView.m b/tikzit-1/src/osx/CustomNodeCellView.m
new file mode 100644
index 0000000..612394b
--- /dev/null
+++ b/tikzit-1/src/osx/CustomNodeCellView.m
@@ -0,0 +1,83 @@
+//
+// CustomNodeCellView.m
+// TikZiT
+//
+// Created by Johan Paulsson on 12/12/13.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import "CustomNodeCellView.h"
+
+@implementation CustomNodeCellView
+
+- (id)initWithFrame:(NSRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ // Initialization code here.
+ }
+ return self;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+ [super drawRect:dirtyRect];
+
+ // Drawing code here.
+}
+
+- (id) objectValue{
+ return [super objectValue];
+}
+
+-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
+ if (nodeLayer!=nil) {
+ if (![[[self layer] sublayers] containsObject:nodeLayer]) {
+ [[self layer] addSublayer:nodeLayer];
+ NSPoint c = NSMakePoint((CGRectGetMinX([[self layer] frame])+CGRectGetWidth([nodeLayer bounds])/2),
+ CGRectGetMidY([[self layer] frame]));
+ //c = NSMakePoint(-16.5,-16.5);
+ [nodeLayer setCenter:c andAnimateWhen:NO];
+ [[self textField] setFrame:NSMakeRect(CGRectGetWidth([nodeLayer bounds]), CGRectGetMidY([[self layer] frame]), CGRectGetWidth([[self textField] frame]), CGRectGetHeight([[self textField] frame]))];
+ }
+
+ if (selected){
+ [nodeStyle setStrokeColor:[NSColor whiteColor]];
+ [[nodeLayer node] setStyle:nodeStyle];
+ }else{
+ [nodeStyle setStrokeColor:[NSColor blackColor]];
+ [[nodeLayer node] setStyle:nodeStyle];
+ }
+
+ [nodeLayer updateFrame];
+ }
+}
+
+- (void) setObjectValue:(id)objectValue{
+ if(objectValue == nil)
+ return;
+
+ nodeStyle = (NodeStyle *)objectValue;
+ [[self textField] setStringValue:[nodeStyle shapeName]];
+
+ if (nodeLayer == nil) {
+ nodeLayer = [[NodeLayer alloc] initWithNode:[Node node]
+ transformer:[Transformer defaultTransformer]];
+ [nodeLayer setRescale:NO];
+ }
+ [nodeStyle setName:[nodeStyle shapeName]];
+
+ [[nodeLayer node] setStyle:nodeStyle];
+ [nodeLayer updateFrame];
+
+ NSLog(@"asd");
+}
+
+- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
+ [super setBackgroundStyle:backgroundStyle];
+
+ selected = (backgroundStyle == NSBackgroundStyleDark);
+ [self setNeedsDisplay:YES];
+}
+
+@end
diff --git a/tikzit-1/src/osx/CustomNodeController.h b/tikzit-1/src/osx/CustomNodeController.h
new file mode 100644
index 0000000..67adf0b
--- /dev/null
+++ b/tikzit-1/src/osx/CustomNodeController.h
@@ -0,0 +1,35 @@
+//
+// CustomNodeController.h
+// TikZiT
+//
+// Created by Johan Paulsson on 12/4/13.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "Shape.h"
+#import "TikzShape.h"
+
+#import "GraphicsView.h"
+#import "TikzSourceController.h"
+
+#import "SupportDir.h"
+
+@interface CustomNodeController : NSViewController <NSTableViewDelegate>{
+ NSDictionary *nodeStyles;
+ NSMutableArray* customNodeStyles;
+
+ GraphicsView *__weak graphicsView;
+ TikzSourceController *__weak tikzSourceController;
+ NSTableView *customNodeTable;
+}
+
+@property NSDictionary *nodeStyles;
+@property NSMutableArray* customNodeStyles;
+
+@property IBOutlet NSTableView *customNodeTable;
+
+@property (weak) IBOutlet GraphicsView *graphicsView;
+@property (weak) IBOutlet TikzSourceController *tikzSourceController;
+
+@end
diff --git a/tikzit-1/src/osx/CustomNodeController.m b/tikzit-1/src/osx/CustomNodeController.m
new file mode 100644
index 0000000..4f46acc
--- /dev/null
+++ b/tikzit-1/src/osx/CustomNodeController.m
@@ -0,0 +1,58 @@
+//
+// CustomNodeController.m
+// TikZiT
+//
+// Created by Johan Paulsson on 12/4/13.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import "CustomNodeController.h"
+#import "NodeStyle.h"
+
+@interface CustomNodeController ()
+
+@end
+
+@implementation CustomNodeController
+
+@synthesize nodeStyles, customNodeStyles;
+@synthesize graphicsView, tikzSourceController;
+@synthesize customNodeTable;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
+ nodeStyles = [Shape shapeDictionary];
+ customNodeStyles = [NSMutableArray array];
+
+ for(id key in nodeStyles) {
+ Shape *value = [nodeStyles objectForKey:key];
+
+ if([value isKindOfClass:[TikzShape class]]){
+ NodeStyle *newNodeStyle = [[NodeStyle alloc] init];
+ [newNodeStyle setShapeName:key];
+
+ [customNodeStyles addObject:newNodeStyle];
+ }
+ }
+ }
+
+ return self;
+}
+
+- (void)tableViewSelectionDidChange:(NSNotification *)aNotification{
+ NSInteger selectedRow = [customNodeTable selectedRow];
+
+ NodeStyle* selectedNodeStyle = [customNodeStyles objectAtIndex:selectedRow];
+ TikzShape *tikzshape = (TikzShape *) [nodeStyles objectForKey:[selectedNodeStyle shapeName]];
+
+ [[tikzSourceController graphicsView] setEnabled:NO];
+ [tikzSourceController setTikz:[tikzshape tikzSrc]];
+ [tikzSourceController parseTikz:self];
+}
+
+- (id)valueForUndefinedKey:(NSString *)key{
+ return nil;
+}
+
+@end
diff --git a/tikzit-1/src/osx/CustomNodes.xib b/tikzit-1/src/osx/CustomNodes.xib
new file mode 100644
index 0000000..1cc8db2
--- /dev/null
+++ b/tikzit-1/src/osx/CustomNodes.xib
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+ <dependencies>
+ <deployment defaultVersion="1070" identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="CustomNodeController">
+ <connections>
+ <outlet property="graphicsView" destination="3MT-Yc-Dhv" id="9gg-fS-oBl"/>
+ <outlet property="tikzSourceController" destination="il5-cQ-3oh" id="Wny-jd-sKZ"/>
+ <outlet property="view" destination="1" id="sH5-DU-xwB"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application"/>
+ <arrayController objectClassName="NodeStyle" id="iyU-U5-XAU" userLabel="Node Style Array Controller">
+ <declaredKeys>
+ <string>name</string>
+ <string>strokeThickness</string>
+ <string>strokeColor</string>
+ <string>fillColor</string>
+ <string>strokeColorIsKnown</string>
+ <string>fillColorIsKnown</string>
+ <string>representedObject.name</string>
+ <string>shapeName</string>
+ <string>scale</string>
+ <string>@distinctUnionOfObjects.category</string>
+ <string>category</string>
+ </declaredKeys>
+ <connections>
+ <binding destination="-2" name="contentArray" keyPath="onodeStyles" id="Yzy-xv-qEa"/>
+ </connections>
+ </arrayController>
+ <customObject id="il5-cQ-3oh" customClass="TikzSourceController">
+ <connections>
+ <outlet property="errorMessage" destination="6rJ-4b-syy" id="cin-Wb-6uD"/>
+ <outlet property="errorNotification" destination="R3k-mz-hMn" id="jtn-fQ-Amk"/>
+ <outlet property="graphicsView" destination="3MT-Yc-Dhv" id="hK1-h1-Dsr"/>
+ <outlet property="sourceView" destination="QXu-0d-uF0" id="SEj-FL-5Ac"/>
+ <outlet property="status" destination="6rJ-4b-syy" id="lVN-cK-3Cb"/>
+ </connections>
+ </customObject>
+ <customView id="1">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <subviews>
+ <splitView dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DO1-FS-fZd">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <subviews>
+ <scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="32" horizontalPageScroll="10" verticalLineScroll="32" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="Ry0-48-577">
+ <rect key="frame" x="0.0" y="0.0" width="117" height="272"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <clipView key="contentView" id="9D3-br-lEi">
+ <rect key="frame" x="1" y="1" width="115" height="270"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="30" rowSizeStyle="automatic" viewBased="YES" id="ieg-vU-MzM">
+ <rect key="frame" x="0.0" y="0.0" width="115" height="270"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <size key="intercellSpacing" width="3" height="2"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
+ <tableColumns>
+ <tableColumn width="112" minWidth="40" maxWidth="1000" id="k91-pc-nbl">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
+ </tableHeaderCell>
+ <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="ZaR-9P-sAp">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+ <prototypeCellViews>
+ <tableCellView id="0ce-nA-hcl" customClass="CustomNodeCellView">
+ <rect key="frame" x="1" y="1" width="112" height="30"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KUl-Qh-CHH">
+ <rect key="frame" x="36" y="3" width="87" height="17"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
+ <textFieldCell key="cell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Table View Cell" id="92K-au-Qpa">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ <connections>
+ <binding destination="0ce-nA-hcl" name="value" keyPath="objectValue" id="06y-KE-8wP"/>
+ </connections>
+ </textFieldCell>
+ </textField>
+ </subviews>
+ <connections>
+ <outlet property="textField" destination="KUl-Qh-CHH" id="Cze-5m-UmF"/>
+ </connections>
+ </tableCellView>
+ </prototypeCellViews>
+ </tableColumn>
+ </tableColumns>
+ <connections>
+ <binding destination="-2" name="selectionIndexes" keyPath="selectedNode" id="C4J-62-GDG"/>
+ <outlet property="delegate" destination="-2" id="M05-fU-pjz"/>
+ </connections>
+ </tableView>
+ </subviews>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </clipView>
+ <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="QIL-7j-JmC">
+ <rect key="frame" x="1" y="256" width="0.0" height="15"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="ElP-ub-Uwa">
+ <rect key="frame" x="224" y="17" width="15" height="102"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ </scrollView>
+ <view fixedFrame="YES" id="F5P-T2-9eB">
+ <rect key="frame" x="118" y="0.0" width="362" height="272"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <splitView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="KKi-SZ-dS6">
+ <rect key="frame" x="0.0" y="0.0" width="362" height="272"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <customView fixedFrame="YES" id="d61-FR-v2c">
+ <rect key="frame" x="0.0" y="0.0" width="362" height="156"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <customView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="3MT-Yc-Dhv" customClass="GraphicsView">
+ <rect key="frame" x="0.0" y="0.0" width="362" height="155"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ </customView>
+ <customView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="R3k-mz-hMn" customClass="ParseErrorView">
+ <rect key="frame" x="0.0" y="113" width="361" height="42"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
+ <subviews>
+ <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6rJ-4b-syy">
+ <rect key="frame" x="5" y="10" width="354" height="27"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" placeholderString="parser information" allowsEditingTextAttributes="YES" id="3y1-Zn-Hv4">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ <button wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Et8-Cc-Xac">
+ <rect key="frame" x="340" y="21" width="17" height="19"/>
+ <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="squareTextured" bezelStyle="texturedSquare" image="NSStopProgressFreestandingTemplate" imagePosition="only" alignment="center" state="on" imageScaling="proportionallyDown" id="7vB-Le-tP4">
+ <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="closeParseError:" target="il5-cQ-3oh" id="jdZ-7K-cwe"/>
+ </connections>
+ </button>
+ </subviews>
+ </customView>
+ </subviews>
+ </customView>
+ <customView fixedFrame="YES" id="Fal-9S-dwR">
+ <rect key="frame" x="0.0" y="165" width="362" height="107"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <subviews>
+ <scrollView fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yLp-gf-r49">
+ <rect key="frame" x="0.0" y="0.0" width="362" height="107"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <clipView key="contentView" ambiguous="YES" misplaced="YES" id="qOT-id-lqk">
+ <rect key="frame" x="1" y="1" width="345" height="105"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <textView ambiguous="YES" importsGraphics="NO" richText="NO" findStyle="panel" allowsUndo="YES" usesRuler="YES" verticallyResizable="YES" allowsNonContiguousLayout="YES" spellingCorrection="YES" smartInsertDelete="YES" id="QXu-0d-uF0">
+ <rect key="frame" x="0.0" y="0.0" width="345" height="105"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ <size key="minSize" width="345" height="105"/>
+ <size key="maxSize" width="877" height="10000000"/>
+ <attributedString key="textStorage">
+ <fragment>
+ <string key="content">\begin{tikzpicture}
+
+\end{tikzpicture}</string>
+ <attributes>
+ <font key="NSFont" metaFont="toolTip"/>
+ <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural"/>
+ </attributes>
+ </fragment>
+ </attributedString>
+ <color key="insertionPointColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
+ <size key="minSize" width="345" height="105"/>
+ <size key="maxSize" width="877" height="10000000"/>
+ <connections>
+ <binding destination="il5-cQ-3oh" name="attributedString" keyPath="source" id="15z-o3-4ni"/>
+ <outlet property="delegate" destination="il5-cQ-3oh" id="9Mr-J3-zvR"/>
+ </connections>
+ </textView>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+ </clipView>
+ <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" doubleValue="1" horizontal="YES" id="BYM-Xm-JpT">
+ <rect key="frame" x="-100" y="-100" width="87" height="18"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ <scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="0.90909090909090906" horizontal="NO" id="SEU-Jq-fwu">
+ <rect key="frame" x="346" y="1" width="15" height="105"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ </scrollView>
+ </subviews>
+ </customView>
+ </subviews>
+ <holdingPriorities>
+ <real value="250"/>
+ <real value="250"/>
+ </holdingPriorities>
+ </splitView>
+ <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="esG-a3-KD7">
+ <rect key="frame" x="220" y="-184" width="128" height="14"/>
+ <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" id="7uu-y8-NcI">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ </textField>
+ </subviews>
+ </view>
+ </subviews>
+ <holdingPriorities>
+ <real value="250"/>
+ <real value="250"/>
+ </holdingPriorities>
+ </splitView>
+ </subviews>
+ <constraints>
+ <constraint firstAttribute="trailing" secondItem="DO1-FS-fZd" secondAttribute="trailing" id="Bow-1P-jx4"/>
+ <constraint firstAttribute="bottom" secondItem="DO1-FS-fZd" secondAttribute="bottom" id="c94-eC-Rhp"/>
+ <constraint firstItem="DO1-FS-fZd" firstAttribute="leading" secondItem="1" secondAttribute="leading" id="j1G-Ag-RLs"/>
+ <constraint firstItem="DO1-FS-fZd" firstAttribute="top" secondItem="1" secondAttribute="top" id="tBr-89-Ipp"/>
+ </constraints>
+ </customView>
+ </objects>
+ <resources>
+ <image name="NSStopProgressFreestandingTemplate" width="12" height="12"/>
+ </resources>
+</document>
diff --git a/tikzit-1/src/osx/DraggablePDFView.h b/tikzit-1/src/osx/DraggablePDFView.h
new file mode 100644
index 0000000..9e53c44
--- /dev/null
+++ b/tikzit-1/src/osx/DraggablePDFView.h
@@ -0,0 +1,28 @@
+//
+// PreviewController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Quartz/Quartz.h>
+
+@interface DraggablePDFView : PDFView
+
+@end
diff --git a/tikzit-1/src/osx/DraggablePDFView.m b/tikzit-1/src/osx/DraggablePDFView.m
new file mode 100644
index 0000000..ce393c7
--- /dev/null
+++ b/tikzit-1/src/osx/DraggablePDFView.m
@@ -0,0 +1,60 @@
+//
+// PreviewController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "DraggablePDFView.h"
+
+@implementation DraggablePDFView
+
+- (id)initWithFrame:(NSRect)frame
+{
+ self = [super initWithFrame:frame];
+ return self;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+ [super drawRect:dirtyRect];
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ NSRect pageBox = [[[self document] pageAtIndex:0] boundsForBox:kPDFDisplayBoxMediaBox];
+ NSRect pageRect= [self convertRect:pageBox fromPage:[[self document] pageAtIndex:0]];
+
+ NSArray *fileList = [NSArray arrayWithObjects:[[[self document] documentURL] path], nil];
+ NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
+ [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
+ [pboard setPropertyList:fileList forType:NSFilenamesPboardType];
+
+ [self dragImage:[[NSImage alloc] initWithData:[[self document] dataRepresentation]]
+ at:pageRect.origin
+ offset:pageRect.size
+ event:theEvent
+ pasteboard:pboard
+ source:self
+ slideBack:YES];
+
+ return;
+}
+
+@end
diff --git a/tikzit-1/src/osx/EdgeControlLayer.h b/tikzit-1/src/osx/EdgeControlLayer.h
new file mode 100644
index 0000000..4cdf8bc
--- /dev/null
+++ b/tikzit-1/src/osx/EdgeControlLayer.h
@@ -0,0 +1,44 @@
+//
+// EdgeControlLayer.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+#import "Edge.h"
+#import "Transformer.h"
+
+
+@interface EdgeControlLayer : CALayer {
+ Edge *edge;
+ Transformer *transformer;
+ BOOL selected;
+}
+
+- (id)initWithEdge:(Edge*)e andTransformer:(Transformer*)t;
+- (void)highlight;
+- (void)unhighlight;
+- (void)select;
+- (void)deselect;
+
++ (float)handleRadius;
+
+@end
diff --git a/tikzit-1/src/osx/EdgeControlLayer.m b/tikzit-1/src/osx/EdgeControlLayer.m
new file mode 100644
index 0000000..facdd84
--- /dev/null
+++ b/tikzit-1/src/osx/EdgeControlLayer.m
@@ -0,0 +1,150 @@
+//
+// EdgeControlLayer.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "EdgeControlLayer.h"
+#import "util.h"
+
+
+@implementation EdgeControlLayer
+
+
+- (id)initWithEdge:(Edge*)e andTransformer:(Transformer*)t {
+ if (!(self = [super init])) return nil;
+ transformer = t;
+ edge = e;
+ self.opacity = 0.0f;
+ return self;
+}
+
+- (void)select {
+ selected = YES;
+ self.opacity = 1.0f;
+}
+
+- (void)deselect {
+ selected = NO;
+ self.opacity = 0.0f;
+}
+
+- (void)highlight {
+ if (!selected) {
+ self.opacity = 0.5f;
+ }
+}
+
+- (void)unhighlight {
+ if (!selected) {
+ self.opacity = 0.0f;
+ }
+}
+
+- (void)drawInContext:(CGContextRef)ctx {
+ CGContextSaveGState(ctx);
+
+ [edge updateControls];
+ CGPoint source = NSPointToCGPoint([transformer toScreen:[[edge source] point]]);
+ CGPoint target = NSPointToCGPoint([transformer toScreen:[[edge target] point]]);
+ CGPoint mid = NSPointToCGPoint([transformer toScreen:[edge mid]]);
+ CGPoint cp1 = NSPointToCGPoint([transformer toScreen:[edge cp1]]);
+ CGPoint cp2 = NSPointToCGPoint([transformer toScreen:[edge cp2]]);
+
+ float dx = (target.x - source.x);
+ float dy = (target.y - source.y);
+
+ // draw a circle at the midpoint
+ CGRect mid_rect = CGRectMake(mid.x-3.0f, mid.y-3.0f, 6.0f, 6.0f);
+ CGContextAddEllipseInRect(ctx, mid_rect);
+ CGContextSetLineWidth(ctx, 1.0f);
+ CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 0.5f);
+ CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 1.0f, 0.5f);
+ CGContextDrawPath(ctx, kCGPathFillStroke);
+
+
+ CGContextSetShouldAntialias(ctx, YES);
+
+ // compute size of control circles
+ float cdist;
+ if (dx == 0 && dy == 0) cdist = [transformer scaleToScreen:edge.weight];
+ else cdist = sqrt(dx*dx + dy*dy) * edge.weight;
+
+ // if basic bend, draw blue, if inout, draw green
+ if ([edge bendMode] == EdgeBendModeBasic) CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 0.4f);
+ else CGContextSetRGBStrokeColor(ctx, 0, 0.7f, 0, 0.4f);
+
+ // draw source control circle
+ CGRect ellipse1 = CGRectMake(source.x-cdist, source.y-cdist, cdist*2.0f, cdist*2.0f);
+ CGContextAddEllipseInRect(ctx, ellipse1);
+ if (dx!=0 || dy!=0) {
+ CGRect ellipse2 = CGRectMake(target.x-cdist, target.y-cdist, cdist*2.0f, cdist*2.0f);
+ CGContextAddEllipseInRect(ctx, ellipse2);
+ }
+
+ CGContextStrokePath(ctx);
+
+ float handleRad = [EdgeControlLayer handleRadius];
+
+ // handles
+ CGRect ctrl1 = CGRectMake(cp1.x-handleRad, cp1.y-handleRad, 2*handleRad, 2*handleRad);
+ CGRect ctrl2 = CGRectMake(cp2.x-handleRad, cp2.y-handleRad, 2*handleRad, 2*handleRad);
+
+ CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 0.8f);
+
+ // draw a line from source vertex to first handle
+ if ([edge bendMode] == EdgeBendModeInOut) {
+ if ([edge outAngle] % 45 == 0) CGContextSetRGBStrokeColor(ctx, 1, 0, 1, 0.6f);
+ else CGContextSetRGBStrokeColor(ctx, 0, 0.7f, 0, 0.4f);
+ } else {
+ if ([edge bend] % 45 == 0) CGContextSetRGBStrokeColor(ctx, 1, 0, 1, 0.6f);
+ else CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 0.4f);
+ }
+
+ CGContextMoveToPoint(ctx, source.x, source.y);
+ CGContextAddLineToPoint(ctx, cp1.x, cp1.y);
+ CGContextStrokePath(ctx);
+
+ CGContextAddEllipseInRect(ctx, ctrl1);
+ CGContextDrawPath(ctx, kCGPathFillStroke);
+
+
+ // draw a line from target vertex to second handle
+ if ([edge bendMode] == EdgeBendModeInOut) {
+ if ([edge inAngle] % 45 == 0) CGContextSetRGBStrokeColor(ctx, 1, 0, 1, 0.6f);
+ else CGContextSetRGBStrokeColor(ctx, 0, 0.7f, 0, 0.4f);
+ } else {
+ if ([edge bend] % 45 == 0) CGContextSetRGBStrokeColor(ctx, 1, 0, 1, 0.6f);
+ else CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 0.4f);
+ }
+
+ CGContextMoveToPoint(ctx, target.x, target.y);
+ CGContextAddLineToPoint(ctx, cp2.x, cp2.y);
+ CGContextStrokePath(ctx);
+
+ CGContextAddEllipseInRect(ctx, ctrl2);
+ CGContextDrawPath(ctx, kCGPathFillStroke);
+
+ CGContextRestoreGState(ctx);
+}
+
++ (float)handleRadius { return 4.0f; }
+
+@end
diff --git a/tikzit-1/src/osx/EdgeStyle+Coder.h b/tikzit-1/src/osx/EdgeStyle+Coder.h
new file mode 100644
index 0000000..e35c18f
--- /dev/null
+++ b/tikzit-1/src/osx/EdgeStyle+Coder.h
@@ -0,0 +1,30 @@
+//
+// EdgeStyle+Coder.h
+// TikZiT
+//
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "EdgeStyle.h"
+
+@interface EdgeStyle (Coder)
+- (id)initWithCoder:(NSCoder*)coder;
+- (void)encodeWithCoder:(NSCoder*)coder;
+@end
diff --git a/tikzit-1/src/osx/EdgeStyle+Coder.m b/tikzit-1/src/osx/EdgeStyle+Coder.m
new file mode 100644
index 0000000..039344d
--- /dev/null
+++ b/tikzit-1/src/osx/EdgeStyle+Coder.m
@@ -0,0 +1,50 @@
+//
+// EdgeStyle+Coder.m
+// TikZiT
+//
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "EdgeStyle+Coder.h"
+
+@implementation EdgeStyle (Coder)
+
+- (id)initWithCoder:(NSCoder*)coder {
+ if (!(self = [super init])) return nil;
+
+ name = [coder decodeObjectForKey:@"name"];
+ category = [coder decodeObjectForKey:@"category"];
+ headStyle = [coder decodeIntForKey:@"headStyle"];
+ tailStyle = [coder decodeIntForKey:@"tailStyle"];
+ decorationStyle = [coder decodeIntForKey:@"decorationStyle"];
+ thickness = [coder decodeFloatForKey:@"thickness"];
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder {
+ [coder encodeObject:name forKey:@"name"];
+ [coder encodeObject:category forKey:@"category"];
+ [coder encodeInt:headStyle forKey:@"headStyle"];
+ [coder encodeInt:tailStyle forKey:@"tailStyle"];
+ [coder encodeInt:decorationStyle forKey:@"decorationStyle"];
+ [coder encodeFloat:thickness forKey:@"thickness"];
+}
+
+@end
diff --git a/tikzit-1/src/osx/Graph+Coder.h b/tikzit-1/src/osx/Graph+Coder.h
new file mode 100644
index 0000000..1404fc2
--- /dev/null
+++ b/tikzit-1/src/osx/Graph+Coder.h
@@ -0,0 +1,17 @@
+//
+// Graph+Coder.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 27/04/2010.
+// Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "Graph.h"
+
+@interface Graph (Coder)
+
+- (id)initWithCoder:(NSCoder*)coder;
+- (void)encodeWithCoder:(NSCoder*)coder;
+
+@end
diff --git a/tikzit-1/src/osx/Graph+Coder.m b/tikzit-1/src/osx/Graph+Coder.m
new file mode 100644
index 0000000..7d3787e
--- /dev/null
+++ b/tikzit-1/src/osx/Graph+Coder.m
@@ -0,0 +1,24 @@
+//
+// Graph+Coder.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 27/04/2010.
+// Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import "Graph+Coder.h"
+#import "TikzGraphAssembler.h"
+
+@implementation Graph(Coder)
+
+- (id)initWithCoder:(NSCoder*)coder {
+ NSString *tikz = [coder decodeObject];
+ [TikzGraphAssembler parseTikz:tikz forGraph:self];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder {
+ [coder encodeObject:[self tikz]];
+}
+
+@end
diff --git a/tikzit-1/src/osx/GraphicsView.h b/tikzit-1/src/osx/GraphicsView.h
new file mode 100644
index 0000000..329b1e5
--- /dev/null
+++ b/tikzit-1/src/osx/GraphicsView.h
@@ -0,0 +1,129 @@
+//
+// GraphicsView.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+#import "PickSupport.h"
+#import "Grid.h"
+#import "Transformer.h"
+#import "Graph.h"
+#import "NodeStyle.h"
+#import "StylePaletteController.h"
+#import "ToolPaletteController.h"
+#import "SelectBoxLayer.h"
+
+// mouse modes, corresponding to different tools. format: (tool)[sub-mode]Mode
+typedef enum {
+ SelectMode = 0x10,
+ SelectBoxMode = 0x11,
+ SelectMoveMode = 0x12,
+ SelectEdgeBendMode = 0x14,
+
+ NodeMode = 0x20,
+
+ EdgeMode = 0x40,
+ EdgeDragMode = 0x41,
+
+ CropMode = 0x80,
+ CropDragMode = 0x81
+} MouseMode;
+
+@class TikzSourceController;
+
+@interface GraphicsView : NSView {
+ BOOL enabled;
+
+ IBOutlet NSApplication *application;
+ StylePaletteController *stylePaletteController;
+ ToolPaletteController *toolPaletteController;
+
+ BOOL frameMoveMode;
+
+ Graph *graph;
+ NSString *graphTikzOnMouseDown;
+ PickSupport *pickSupport;
+ //NSMapTable *nodeSelectionLayers;
+ NSMapTable *edgeControlLayers;
+ NSMapTable *nodeLayers;
+ NSPoint dragOrigin;
+ NSPoint dragTarget;
+ NSPoint oldTransformerOrigin;
+ NSPoint oldMainOrigin;
+ NSRect oldBounds;
+ //NSRect selectionBox;
+ Transformer *transformer;
+
+ CALayer *mainLayer;
+ CALayer *gridLayer;
+ CALayer *graphLayer;
+ CALayer *hudLayer;
+ SelectBoxLayer *selectionLayer;
+
+ MouseMode mouseMode;
+ Node *leaderNode;
+ Grid *grid;
+
+ Edge *modifyEdge;
+ BOOL firstControlPoint;
+
+ int bboxLeftRight;
+ int bboxBottomTop;
+
+ NSUndoManager *documentUndoManager;
+ NSPoint startPoint;
+
+ TikzSourceController *tikzSourceController;
+}
+
+@property BOOL enabled;
+@property (weak) Graph *graph;
+@property IBOutlet TikzSourceController *tikzSourceController;
+@property (readonly) Transformer *transformer;
+@property (readonly) PickSupport *pickSupport;
+
+- (void)setDocumentUndoManager:(NSUndoManager*)um;
+- (void)applyStyleToSelectedNodes:(NodeStyle*)style;
+- (void)applyStyleToSelectedEdges:(EdgeStyle*)style;
+
+- (void)updateMouseMode;
+- (void)refreshLayers;
+
+//- (void)registerUndo:(GraphChange *)change withActionName:(NSString*)name;
+- (void)registerUndo:(NSString*)oldTikz withActionName:(NSString*)name;
+//- (void)undoGraphChange:(GraphChange *)change;
+- (void)undoGraphChange:(NSString*)oldTikz;
+- (void)postGraphChange;
+- (void)postSelectionChange;
+
+- (void)deselectAll:(id)sender;
+- (void)selectAll:(id)sender;
+- (void)cut:(id)sender;
+- (void)copy:(id)sender;
+- (void)paste:(id)sender;
+- (void)delete:(id)sender;
+- (void)bringForward:(id)sender;
+- (void)flipHorizonal:(id)sender;
+- (void)flipVertical:(id)sender;
+- (void)reverseEdgeDirection:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/GraphicsView.m b/tikzit-1/src/osx/GraphicsView.m
new file mode 100644
index 0000000..efa7ecb
--- /dev/null
+++ b/tikzit-1/src/osx/GraphicsView.m
@@ -0,0 +1,1216 @@
+//
+// GraphicsView.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "GraphicsView.h"
+#import "util.h"
+#import "CALayer+DrawLabel.h"
+
+#import "NodeSelectionLayer.h"
+#import "NodeLayer.h"
+#import "EdgeControlLayer.h"
+#import "AppDelegate.h"
+#import "TikzGraphAssembler.h"
+#import "TikzSourceController.h"
+
+@interface GraphicsView (Private)
+- (void)setupLayers;
+- (void)addNodeLayers:(Node*)n;
+- (void)addEdgeLayers:(Edge*)e;
+- (void)removeNodeLayers:(Node*)n;
+- (void)resetMainOrigin;
+- (void)setMainOrigin:(NSPoint)o;
+@end
+
+static CGColorRef cgGrayColor, cgWhiteColor, cgClearColor = nil;
+
+
+@implementation GraphicsView
+
+@synthesize enabled, transformer, pickSupport, tikzSourceController;
+
+- (void)postGraphChange {
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"GraphChanged"
+ object:self];
+ [self postSelectionChange];
+}
+
+- (void)postSelectionChange {
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"SelectionChanged"
+ object:self];
+}
+
+- (id)initWithFrame:(NSRect)frame {
+ self = [super initWithFrame:frame];
+ if (self) {
+ if (cgClearColor == nil) {
+ cgClearColor = CGColorGetConstantColor(kCGColorClear);
+ cgGrayColor = CGColorCreateGenericGray(0.5f, 0.5f);
+ cgWhiteColor = CGColorCreateGenericRGB(1, 1, 1, 1);
+ }
+
+ transformer = [[Transformer alloc] init];
+ mouseMode = SelectMode;
+ grid = [Grid gridWithSpacing:1.0f
+ subdivisions:4
+ transformer:transformer];
+ [grid setSize:NSSizeFromCGSize([gridLayer bounds].size)];
+ [transformer setScale:PIXELS_PER_UNIT];
+
+ [self setupLayers];
+
+ leaderNode = nil;
+ pickSupport = [[PickSupport alloc] init];
+ frameMoveMode = NO;
+
+ enabled = YES;
+ [self setGraph:[Graph graph]];
+ }
+ return self;
+}
+
+- (void)awakeFromNib {
+ AppDelegate *del = [application delegate];
+ stylePaletteController = [del stylePaletteController];
+ toolPaletteController = [del toolPaletteController];
+ [self refreshLayers];
+ [self postGraphChange];
+}
+
+- (void)setupLayers {
+ mainLayer = [CALayer layer];
+ [mainLayer setBackgroundColor:cgWhiteColor];
+ [mainLayer setFrame:CGRectIntegral(NSRectToCGRect([self bounds]))];
+ [mainLayer setOpacity:1.0f];
+ [self setLayer:mainLayer];
+ [self resetMainOrigin];
+
+ gridLayer = [CALayer layer];
+ [gridLayer setDelegate:grid];
+ [gridLayer setOpacity:0.3f];
+ [mainLayer addSublayer:gridLayer];
+
+ graphLayer = [CALayer layer];
+ [graphLayer setDelegate:self];
+ [mainLayer addSublayer:graphLayer];
+
+ hudLayer = [CALayer layer];
+ [mainLayer addSublayer:hudLayer];
+
+ selectionLayer = [SelectBoxLayer layer];
+ [mainLayer addSublayer:selectionLayer];
+
+ [transformer setOrigin:NSMakePoint(NSMidX([self bounds]),NSMidY([self bounds]))];
+ oldBounds = [self bounds];
+ [self refreshLayers];
+}
+
+// Lion resume feature
+//- (void)encodeRestorableStateWithCoder:(NSCoder*)coder {
+// NSLog(@"got encode request");
+//}
+//- (void)restoreStateWithCoder:(NSCoder*)coder {
+// NSLog(@"got decode request");
+//}
+
+- (void)registerUndo:(NSString*)oldTikz withActionName:(NSString*)nm {
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoGraphChange:)
+ object:oldTikz];
+ [documentUndoManager setActionName:nm];
+}
+
+- (void)revertToTikz:(NSString*)tikz {
+ [tikzSourceController setTikz:tikz];
+ [tikzSourceController tryParseTikz];
+ [self refreshLayers];
+ [self postGraphChange];
+}
+
+
+- (void)undoGraphChange:(NSString*)oldTikz {
+ NSString *currentTikz = [graph tikz];
+ [self revertToTikz:oldTikz];
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoGraphChange:)
+ object:currentTikz];
+}
+
+- (void)setGraph:(Graph*)gr {
+ graph = gr;
+
+ NSEnumerator *e;
+ CALayer *layer;
+
+ e = [edgeControlLayers objectEnumerator];
+ while (layer = [e nextObject]) [layer removeFromSuperlayer];
+ edgeControlLayers = [NSMapTable mapTableWithStrongToStrongObjects];
+
+
+ e = [nodeLayers objectEnumerator];
+ while (layer = [e nextObject]) [layer removeFromSuperlayer];
+ nodeLayers = [NSMapTable mapTableWithStrongToStrongObjects];
+
+ for (Node *n in [graph nodes]) {
+ [n attachStyleFromTable:[stylePaletteController nodeStyles]];
+ [self addNodeLayers:n];
+ }
+
+ for (Edge *e in [graph edges]) {
+ [e setAttributesFromData];
+ [e attachStyleFromTable:[stylePaletteController edgeStyles]];
+ [self addEdgeLayers:e];
+ }
+}
+
+- (Graph*)graph { return graph; }
+
+- (void)setMainOrigin:(NSPoint)o {
+ o.x = round(o.x);
+ o.y = round(o.y);
+ CGRect rect = [mainLayer frame];
+ rect.origin = NSPointToCGPoint(o);
+ [mainLayer setFrame:rect];
+}
+
+- (void)resetMainOrigin {
+ NSRect bds = [self bounds];
+ bds.origin.x -= bds.size.width;
+ bds.origin.y -= bds.size.height;
+ bds.size.width *= 3;
+ bds.size.height *= 3;
+ [mainLayer setFrame:NSRectToCGRect([self bounds])];
+}
+
+- (void)refreshLayers {
+ [gridLayer setFrame:[mainLayer frame]];
+ [graphLayer setFrame:[mainLayer frame]];
+ [hudLayer setFrame:[mainLayer frame]];
+ [selectionLayer setFrame:[mainLayer frame]];
+
+ if (enabled) {
+ [hudLayer setBackgroundColor:cgClearColor];
+ } else {
+ [hudLayer setBackgroundColor:cgGrayColor];
+ }
+
+ [grid setSize:NSSizeFromCGSize([gridLayer bounds].size)];
+ [gridLayer setNeedsDisplay];
+ [graphLayer setNeedsDisplay];
+ [hudLayer setNeedsDisplay];
+
+ NSEnumerator *e = [edgeControlLayers objectEnumerator];
+ CALayer *layer;
+ while (layer = [e nextObject]) {
+ [layer setFrame:[graphLayer frame]];
+ [layer setNeedsDisplay];
+ }
+}
+
+
+- (void)viewDidEndLiveResize {
+ [super viewDidEndLiveResize];
+ NSPoint o = [transformer origin];
+ o.x += round(([self bounds].size.width - oldBounds.size.width)/2.0f);
+ o.y += round(([self bounds].size.height - oldBounds.size.height)/2.0f);
+ [transformer setOrigin:o];
+ oldBounds = [self bounds];
+ [self refreshLayers];
+}
+
+- (void)applyStyleToSelectedNodes:(NodeStyle*)style {
+ NSString *oldTikz = [graph tikz];
+
+ for (Node *n in [pickSupport selectedNodes]) {
+ [n setStyle:style];
+ [[nodeLayers objectForKey:n] setNeedsDisplay];
+ }
+
+ [self registerUndo:oldTikz withActionName:@"Apply Style to Nodes"];
+ [self refreshLayers];
+ [self postGraphChange];
+}
+
+- (void)applyStyleToSelectedEdges:(EdgeStyle*)style {
+ NSString *oldTikz = [graph tikz];
+
+ for (Edge *e in [pickSupport selectedEdges]) {
+ [e setStyle:style];
+ }
+
+ [self registerUndo:oldTikz withActionName:@"Apply Style to Edges"];
+ [self refreshLayers];
+ [self postGraphChange];
+}
+
+- (void)addNodeLayers:(Node*)n {
+ // add a node to the graph
+ [graph addNode:n];
+
+ NSPoint pt = [transformer toScreen:[n point]];
+
+ // add a node layer
+ NodeLayer *nl = [[NodeLayer alloc] initWithNode:n transformer:transformer];
+ [nl setCenter:pt];
+ [nodeLayers setObject:nl forKey:n];
+ [graphLayer addSublayer:nl];
+ [nl setNeedsDisplay];
+}
+
+- (void)removeNodeLayers:(Node*)n {
+ [[nodeLayers objectForKey:n] removeFromSuperlayer];
+ [nodeLayers removeObjectForKey:n];
+}
+
+- (void)addEdgeLayers:(Edge *)e {
+ [graph addEdge:e];
+ EdgeControlLayer *ecl = [[EdgeControlLayer alloc] initWithEdge:e andTransformer:transformer];
+ [edgeControlLayers setObject:ecl forKey:e];
+ [ecl setFrame:CGRectMake(10, 10, 100, 100)];
+ [hudLayer addSublayer:ecl];
+ [ecl setNeedsDisplay];
+}
+
+- (void)removeEdgeLayers:(Edge*)e {
+ [[edgeControlLayers objectForKey:e] removeFromSuperlayer];
+ [edgeControlLayers removeObjectForKey:e];
+ [self refreshLayers];
+}
+
+- (BOOL)circleWithCenter:(NSPoint)center andRadius:(float)radius containsPoint:(NSPoint)p {
+ float dx = center.x - p.x;
+ float dy = center.y - p.y;
+ return (dx*dx + dy*dy) <= radius*radius;
+}
+
+- (BOOL)node:(Node*)node containsPoint:(NSPoint)p {
+ NodeLayer *nl = [nodeLayers objectForKey:node];
+ return [nl nodeContainsPoint:p];
+}
+
+- (BOOL)edge:(Edge*)edge containsPoint:(NSPoint)p {
+// NSPoint center = [transformer toScreen:edge.mid];
+// float dx = center.x - p.x;
+// float dy = center.y - p.y;
+// float radius = 5.0f; // tolerence for clicks
+// return (dx*dx + dy*dy) <= radius*radius;
+
+ CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+
+ // Save the graphics state before doing the hit detection.
+ CGContextSaveGState(ctx);
+
+ NSPoint src = [transformer toScreen:[edge tail]];
+ NSPoint targ = [transformer toScreen:[edge head]];
+ NSPoint cp1 = [transformer toScreen:[edge cp1]];
+ NSPoint cp2 = [transformer toScreen:[edge cp2]];
+
+ CGContextSetLineWidth(ctx, 8.0f);
+
+ CGContextMoveToPoint(ctx, src.x, src.y);
+ CGContextAddCurveToPoint(ctx, cp1.x, cp1.y, cp2.x, cp2.y, targ.x, targ.y);
+
+ BOOL containsPoint = CGContextPathContainsPoint(ctx, NSPointToCGPoint(p), kCGPathStroke);
+
+ CGContextSetRGBStrokeColor(ctx, 0, 0, 0, 0);
+
+ CGContextStrokePath(ctx);
+ //CGContextFlush(ctx);
+ CGContextRestoreGState(ctx);
+
+ return containsPoint;
+}
+
+- (void)shiftNodes:(NSSet*)set from:(NSPoint)source to:(NSPoint)dest {
+ float dx = dest.x - source.x;
+ float dy = dest.y - source.y;
+
+ for (Node *n in set) {
+ NSPoint p = [transformer toScreen:[n point]];
+ p = [grid snapScreenPoint:NSMakePoint(p.x+dx, p.y+dy)];
+ [n setPoint:[transformer fromScreen:p]];
+ }
+}
+
+
+- (void)mouseDown:(NSEvent*)theEvent {
+ if (!enabled) return;
+
+ [self updateMouseMode];
+
+ dragOrigin = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+ dragTarget = dragOrigin;
+
+ graphTikzOnMouseDown = [graph tikz];
+
+ if ([theEvent modifierFlags] & NSCommandKeyMask) {
+ oldTransformerOrigin = [transformer origin];
+ oldMainOrigin = [self frame].origin;
+ frameMoveMode = YES;
+ return;
+ }
+
+ if (mouseMode == SelectMode) {
+ [selectionLayer setActive:YES];
+ [selectionLayer setSelectBox:NSRectAroundPoints(dragOrigin, dragOrigin)];
+ [selectionLayer setNeedsDisplay];
+
+ modifyEdge = nil;
+ NSPoint cp1, cp2;
+ for (Edge *e in [pickSupport selectedEdges]) {
+ cp1 = [transformer toScreen:[e cp1]];
+ cp2 = [transformer toScreen:[e cp2]];
+ if ([self circleWithCenter:cp1
+ andRadius:[EdgeControlLayer handleRadius]
+ containsPoint:dragOrigin])
+ {
+ mouseMode = SelectEdgeBendMode;
+ modifyEdge = e;
+ firstControlPoint = YES;
+ break;
+ } else if ([self circleWithCenter:cp2
+ andRadius:[EdgeControlLayer handleRadius]
+ containsPoint:dragOrigin])
+ {
+ mouseMode = SelectEdgeBendMode;
+ modifyEdge = e;
+ firstControlPoint = NO;
+ break;
+ }
+ }
+
+ if (modifyEdge == nil) { // skip all the rest if we're modifying an edge
+
+ leaderNode = nil;
+
+ // in first pass, try to find a leader node, under the mouse
+ for (Node* n in [graph nodes]) {
+ if ([self node:n containsPoint:dragOrigin]) {
+ leaderNode = n;
+ [gridLayer setOpacity:1.0f];
+ break;
+ }
+ }
+
+ // if we found one, deselect the others (if appropriate) and go to move mode
+ if (leaderNode != nil) {
+ startPoint = [leaderNode point];
+
+ // if we select a node, we should always deselect all edges:
+ for (Edge *e in [graph edges]) [[edgeControlLayers objectForKey:e] deselect];
+ [pickSupport deselectAllEdges];
+
+ BOOL shouldDeselect =
+ !([theEvent modifierFlags] & NSShiftKeyMask)
+ && ![pickSupport isNodeSelected:leaderNode];
+ for (Node *n in [graph nodes]) {
+ if (n != leaderNode && shouldDeselect) {
+ [pickSupport deselectNode:n];
+ [[[nodeLayers objectForKey:n] selection] deselect];
+ }
+ }
+
+ // ensure the leader node is actually selected
+ if (![pickSupport isNodeSelected:leaderNode]) {
+ [pickSupport selectNode:leaderNode];
+ [[[nodeLayers objectForKey:leaderNode] selection] select];
+ }
+
+
+ // put us in move mode
+ mouseMode = SelectMoveMode;
+ } else {
+ mouseMode = SelectBoxMode;
+
+ // if we didn't select a node, start hunting for an edge to select
+ BOOL shouldDeselect = !([theEvent modifierFlags] & NSShiftKeyMask);
+
+ if (shouldDeselect) {
+ [pickSupport deselectAllEdges];
+ for (Edge *e in graph.edges) [[edgeControlLayers objectForKey:e] deselect];
+ }
+
+ for (Edge* e in [graph edges]) {
+ // find the first node under the pointer, select it, show its controls
+ // and deselect all others if shift isn't down
+ if ([self edge:e containsPoint:dragOrigin]) {
+ for (Node *n in [pickSupport selectedNodes]) [[[nodeLayers objectForKey:n] selection] deselect];
+
+ [pickSupport deselectAllNodes];
+ [pickSupport selectEdge:e];
+ [[edgeControlLayers objectForKey:e] select];
+ break;
+ }
+ } // end for e in [graph edges]
+ } // end if leaderNode == nil
+ } // end if modifyEdge == nil
+
+ } else if (mouseMode == NodeMode) {
+ // do nothing...
+ } else if (mouseMode == EdgeMode) {
+ for (Node *n in [graph nodes]) {
+ if ([self node:n containsPoint:dragOrigin]) {
+ [[[nodeLayers objectForKey:n] selection] highlight];
+ }
+ }
+ mouseMode = EdgeDragMode;
+ } else if (mouseMode == CropMode) {
+ if ([graph hasBoundingBox]) {
+ float fudge = 3;
+
+ NSRect bb = [graph boundingBox];
+ NSPoint bl = [transformer toScreen:bb.origin];
+ NSPoint tr = [transformer
+ toScreen:NSMakePoint(bb.origin.x+bb.size.width,
+ bb.origin.y+bb.size.height)];
+ if (dragOrigin.x > bl.x-fudge && dragOrigin.x < tr.x+fudge &&
+ dragOrigin.y > tr.y-fudge && dragOrigin.y < tr.y+fudge)
+ {
+ bboxBottomTop = 1;
+ } else if (dragOrigin.x > bl.x-fudge && dragOrigin.x < tr.x+fudge &&
+ dragOrigin.y > bl.y-fudge && dragOrigin.y < bl.y+fudge)
+ {
+ bboxBottomTop = -1;
+ } else {
+ bboxBottomTop = 0;
+ }
+
+ if (dragOrigin.y > bl.y-fudge && dragOrigin.y < tr.y+fudge &&
+ dragOrigin.x > tr.x-fudge && dragOrigin.x < tr.x+fudge)
+ {
+ bboxLeftRight = 1;
+ } else if (dragOrigin.y > bl.y-fudge && dragOrigin.y < tr.y+fudge &&
+ dragOrigin.x > bl.x-fudge && dragOrigin.x < bl.x+fudge)
+ {
+ bboxLeftRight = -1;
+ } else {
+ bboxLeftRight = 0;
+ }
+
+ if (bboxBottomTop != 0 || bboxLeftRight != 0) {
+ mouseMode = CropDragMode;
+ }
+ }
+ } else {
+ printf("WARNING: MOUSE DOWN IN INVALID MODE.\n");
+ }
+
+ [self refreshLayers];
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent {
+ if (!enabled) return;
+ dragTarget = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+
+ if (frameMoveMode) {
+ NSPoint newTransOrigin, newMainOrigin;
+ NSPoint diff = NSMakePoint(dragTarget.x - dragOrigin.x, dragTarget.y - dragOrigin.y);
+ newTransOrigin.x = oldTransformerOrigin.x + diff.x;
+ newTransOrigin.y = oldTransformerOrigin.y + diff.y;
+ newMainOrigin.x = oldMainOrigin.x + diff.x;
+ newMainOrigin.y = oldMainOrigin.y + diff.y;
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+ [self setMainOrigin:newMainOrigin];
+ [CATransaction commit];
+
+ [transformer setOrigin:newTransOrigin];
+ return;
+ }
+
+ if (mouseMode == SelectBoxMode) {
+ [selectionLayer setSelectBox:NSRectAroundPoints(dragOrigin, dragTarget)];
+ [selectionLayer setNeedsDisplay];
+
+ for (Node* n in [graph nodes]) {
+ if (NSPointInRect([transformer toScreen:[n point]], [selectionLayer selectBox])) {
+ [[[nodeLayers objectForKey:n] selection] highlight];
+ } else if (!([theEvent modifierFlags] & NSShiftKeyMask)) {
+ [[[nodeLayers objectForKey:n] selection] unhighlight];
+ }
+ }
+ } else if (mouseMode == SelectMoveMode) {
+ if (leaderNode != nil) {
+ [self shiftNodes:[pickSupport selectedNodes]
+ from:[transformer toScreen:[leaderNode point]]
+ to:dragTarget];
+ } else {
+ printf("WARNING: LEADER NODE SHOULD NOT BE NIL.\n");
+ }
+
+ [self refreshLayers];
+ } else if (mouseMode == SelectEdgeBendMode) {
+ NSPoint src = [transformer toScreen:[[modifyEdge source] point]];
+ NSPoint targ = [transformer toScreen:[[modifyEdge target] point]];
+ float dx1 = targ.x - src.x;
+ float dy1 = targ.y - src.y;
+ float dx2, dy2;
+ if (firstControlPoint) {
+ dx2 = dragTarget.x - src.x;
+ dy2 = dragTarget.y - src.y;
+ } else {
+ dx2 = dragTarget.x - targ.x;
+ dy2 = dragTarget.y - targ.y;
+ }
+ float base_dist = sqrt(dx1*dx1 + dy1*dy1);
+ float handle_dist = sqrt(dx2*dx2 + dy2*dy2);
+ float wcourseness = 0.1f;
+
+ if (![modifyEdge isSelfLoop]) {
+ if (base_dist != 0) {
+ [modifyEdge setWeight:roundToNearest(wcourseness, handle_dist/base_dist)];
+ //round(handle_dist / (base_dist*wcourseness)) * wcourseness;
+ } else {
+ [modifyEdge setWeight:
+ roundToNearest(wcourseness, [transformer scaleFromScreen:handle_dist])];
+ }
+ }
+
+
+ float control_angle = good_atan(dx2, dy2);
+
+ int bcourseness = 15;
+
+ if ([modifyEdge bendMode] == EdgeBendModeBasic) {
+ float bnd;
+ float base_angle = good_atan(dx1, dy1);
+ if (firstControlPoint) {
+ bnd = base_angle - control_angle;
+ } else {
+ bnd = control_angle - base_angle + pi;
+ if (bnd > pi) bnd -= 2*pi;
+ }
+
+ [modifyEdge setBend:round(bnd * (180.0f / pi) *
+ (1.0f / (float)bcourseness)) *
+ bcourseness];
+ } else {
+ int bnd = round(control_angle * (180.0f / pi) *
+ (1.0f / (float)bcourseness)) *
+ bcourseness;
+ if (firstControlPoint) {
+ if ([theEvent modifierFlags] & NSAlternateKeyMask) {
+ if ([modifyEdge isSelfLoop]) {
+ [modifyEdge setInAngle:[modifyEdge inAngle] +
+ (bnd - [modifyEdge outAngle])];
+ } else {
+ [modifyEdge setInAngle:[modifyEdge inAngle] -
+ (bnd - [modifyEdge outAngle])];
+ }
+ }
+
+ [modifyEdge setOutAngle:bnd];
+ } else {
+ if (theEvent.modifierFlags & NSAlternateKeyMask) {
+ if ([modifyEdge isSelfLoop]) {
+ [modifyEdge setOutAngle:[modifyEdge outAngle] +
+ (bnd - [modifyEdge inAngle])];
+ } else {
+ [modifyEdge setOutAngle:[modifyEdge outAngle] -
+ (bnd - [modifyEdge inAngle])];
+ }
+ }
+
+ [modifyEdge setInAngle:bnd];
+ }
+ }
+
+ [self refreshLayers];
+ } else if (mouseMode == NodeMode) {
+ // do nothing...
+ } else if (mouseMode == EdgeDragMode) {
+ for (Node *n in [graph nodes]) {
+ if ([self node:n containsPoint:dragOrigin] ||
+ [self node:n containsPoint:dragTarget])
+ {
+ [[[nodeLayers objectForKey:n] selection] highlight];
+ } else {
+ [[[nodeLayers objectForKey:n] selection] unhighlight];
+ }
+ }
+
+ [self refreshLayers];
+ } else if (mouseMode == CropMode || mouseMode == CropDragMode) {
+ NSPoint p1 = [transformer fromScreen:[grid snapScreenPoint:dragOrigin]];
+ NSPoint p2 = [transformer fromScreen:[grid snapScreenPoint:dragTarget]];
+
+ NSRect bbox;
+ if (mouseMode == CropDragMode) {
+ bbox = [graph boundingBox];
+ if (bboxBottomTop == -1) {
+ float dy = p2.y - bbox.origin.y;
+ bbox.origin.y += dy;
+ bbox.size.height -= dy;
+ } else if (bboxBottomTop == 1) {
+ float dy = p2.y - (bbox.origin.y + bbox.size.height);
+ bbox.size.height += dy;
+ }
+
+ if (bboxLeftRight == -1) {
+ float dx = p2.x - bbox.origin.x;
+ bbox.origin.x += dx;
+ bbox.size.width -= dx;
+ } else if (bboxLeftRight == 1) {
+ float dx = p2.x - (bbox.origin.x + bbox.size.width);
+ bbox.size.width += dx;
+ }
+ } else {
+ bbox = NSRectAroundPoints(p1, p2);
+ }
+
+ [graph setBoundingBox:bbox];
+ [self postGraphChange];
+ [self refreshLayers];
+ } else {
+ printf("WARNING: MOUSE DRAGGED IN INVALID MODE.\n");
+ }
+}
+
+- (void)mouseUp:(NSEvent*)theEvent {
+ if (!enabled) return;
+
+ if (frameMoveMode) {
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+ [self resetMainOrigin];
+ [self refreshLayers];
+ [CATransaction commit];
+ frameMoveMode = NO;
+ return;
+ }
+
+ dragTarget = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+
+ if ((mouseMode & SelectMode) == SelectMode && [theEvent clickCount] == 2) {
+ for (Edge *e in [graph edges]) {
+ if ([self edge:e containsPoint:dragTarget]) {
+ if ([e bendMode] == EdgeBendModeBasic) {
+ [e convertBendToAngles];
+ [e setBendMode:EdgeBendModeInOut];
+ } else {
+ [e convertAnglesToBend];
+ [e setBendMode:EdgeBendModeBasic];
+ }
+
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Change Edge Mode"];
+ [self postGraphChange];
+ break;
+ }
+ }
+ }
+
+ if (mouseMode == SelectBoxMode) {
+ for (Node* n in [graph nodes]) {
+ if (NSPointInRect([transformer toScreen:[n point]], [selectionLayer selectBox])) {
+ [pickSupport selectNode:n];
+ [[[nodeLayers objectForKey:n] selection] select];
+ } else if (!([theEvent modifierFlags] & NSShiftKeyMask)) {
+ [pickSupport deselectNode:n];
+ [[[nodeLayers objectForKey:n] selection] deselect];
+ }
+ }
+
+ [selectionLayer setActive:NO];
+ [selectionLayer setNeedsDisplay];
+ [self postSelectionChange];
+
+ mouseMode = SelectMode;
+ } else if (mouseMode == SelectMoveMode) {
+ [gridLayer setOpacity:0.3f];
+
+ if (dragTarget.x != dragOrigin.x || dragTarget.y != dragOrigin.y) {
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Shift Nodes"];
+ }
+
+ leaderNode = nil;
+
+ [self postGraphChange];
+ mouseMode = SelectMode;
+ } else if (mouseMode == SelectEdgeBendMode) {
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Adjust Edge"];
+ [self postGraphChange];
+ mouseMode = SelectMode;
+ modifyEdge = nil;
+ } else if (mouseMode == NodeMode) {
+ NSPoint coords = [transformer fromScreen:[grid snapScreenPoint:dragTarget]];
+ Node *n = [Node nodeWithPoint:coords];
+ [n setStyle:[stylePaletteController activeNodeStyle]];
+ [graph addNode:n];
+
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Add Node"];
+
+ [self addNodeLayers:n];
+ [self postGraphChange];
+ } else if (mouseMode == EdgeDragMode) {
+ Node *src = nil;
+ Node *targ = nil;
+ BOOL found = NO; // don't break the loop until everything is unhighlighted
+ for (Node *n in [graph nodes]) {
+ [[[nodeLayers objectForKey:n] selection] unhighlight];
+ if (!found) {
+ if ([self node:n containsPoint:dragOrigin]) src = n;
+ if ([self node:n containsPoint:dragTarget]) targ = n;
+ if (src != nil && targ != nil) {
+ Edge *e = [Edge edgeWithSource:src andTarget:targ];
+ [e setStyle:[stylePaletteController activeEdgeStyle]];
+ [graph addEdge:e];
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Add Edge"];
+ [self addEdgeLayers:e];
+ found = YES;
+ }
+ }
+ }
+
+ [self postGraphChange];
+ mouseMode = EdgeMode;
+ } else if (mouseMode == CropMode || mouseMode == CropDragMode) {
+ if (dragOrigin.x == dragTarget.x && dragOrigin.y == dragTarget.y) {
+ [graph setBoundingBox:NSMakeRect(0, 0, 0, 0)];
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Clear Bounding Box"];
+ [self postGraphChange];
+ } else {
+ [self registerUndo:graphTikzOnMouseDown withActionName:@"Change Bounding Box"];
+ }
+
+ mouseMode = CropMode;
+ } else {
+ if (! ([theEvent modifierFlags] & NSCommandKeyMask))
+ printf("WARNING: MOUSE UP IN INVALID MODE.\n");
+ }
+
+ [self refreshLayers];
+}
+
+- (void)drawNode:(Node*)nd onLayer:(CALayer*)layer inContext:(CGContextRef)context {
+ NSPoint pt = [transformer toScreen:[nd point]];
+
+ NodeLayer *nl = [nodeLayers objectForKey:nd];
+ //[nl setStrokeWidth:2.0f];
+ [nl setCenter:pt andAnimateWhen:(mouseMode != SelectMoveMode)];
+}
+
+- (void)drawEdge:(Edge*)e onLayer:(CALayer*)layer inContext:(CGContextRef)context {
+ CGContextSaveGState(context);
+ NSPoint src = [transformer toScreen:[e tail]];
+ NSPoint targ = [transformer toScreen:[e head]];
+ NSPoint cp1 = [transformer toScreen:[e cp1]];
+ NSPoint cp2 = [transformer toScreen:[e cp2]];
+
+ // all nodes have the same radius. this will need to be fixed
+ float sradius = 0;//(slayer.ghost) ? 0 : slayer.radius;
+ float tradius = 0;//(tlayer.ghost) ? 0 : tlayer.radius;
+
+ float sdx = cp1.x - src.x;
+ float sdy = cp1.y - src.y;
+ float sdist = sqrt(sdx*sdx + sdy*sdy);
+ float sshortx = (sdist==0) ? 0 : sdx/sdist * sradius;
+ float sshorty = (sdist==0) ? 0 : sdy/sdist * sradius;
+
+ float tdx = cp2.x - targ.x;
+ float tdy = cp2.y - targ.y;
+ float tdist = sqrt(tdx*tdx + tdy*tdy);
+ float tshortx = (tdist==0) ? 0 : tdx/tdist * tradius;
+ float tshorty = (tdist==0) ? 0 : tdy/tdist * tradius;
+
+ CGContextMoveToPoint(context, src.x+sshortx, src.y+sshorty);
+ CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, targ.x+tshortx, targ.y+tshorty);
+
+
+ float lineWidth = [transformer scaleToScreen:0.04f];
+
+ CGContextSetLineWidth(context, lineWidth);
+ CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
+ CGContextSetRGBFillColor(context, 0, 0, 0, 1);
+ CGContextStrokePath(context);
+
+ if ([e style] != nil) {
+ NSPoint p1,p2,p3;
+
+ // draw edge decoration
+ switch ([[e style] decorationStyle]) {
+ case ED_None:
+ break;
+ case ED_Tick:
+ p1 = [transformer toScreen:[e leftNormal]];
+ p2 = [transformer toScreen:[e rightNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextStrokePath(context);
+ break;
+ case ED_Arrow:
+ p1 = [transformer toScreen:[e leftNormal]];
+ p2 = [transformer toScreen:[e midTan]];
+ p3 = [transformer toScreen:[e rightNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextAddLineToPoint(context, p3.x, p3.y);
+ CGContextStrokePath(context);
+ break;
+ }
+
+ // draw arrow head
+ switch ([[e style] headStyle]) {
+ case AH_None:
+ break;
+ case AH_Plain:
+ p1 = [transformer toScreen:[e leftHeadNormal]];
+ p2 = [transformer toScreen:[e head]];
+ p3 = [transformer toScreen:[e rightHeadNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextAddLineToPoint(context, p3.x, p3.y);
+ CGContextStrokePath(context);
+ break;
+ case AH_Latex:
+ p1 = [transformer toScreen:[e leftHeadNormal]];
+ p2 = [transformer toScreen:[e head]];
+ p3 = [transformer toScreen:[e rightHeadNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextAddLineToPoint(context, p3.x, p3.y);
+ CGContextClosePath(context);
+ CGContextFillPath(context);
+ break;
+ }
+
+ // draw arrow tail
+ switch ([[e style] tailStyle]) {
+ case AH_None:
+ break;
+ case AH_Plain:
+ p1 = [transformer toScreen:[e leftTailNormal]];
+ p2 = [transformer toScreen:[e tail]];
+ p3 = [transformer toScreen:[e rightTailNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextAddLineToPoint(context, p3.x, p3.y);
+ CGContextStrokePath(context);
+ break;
+ case AH_Latex:
+ p1 = [transformer toScreen:[e leftTailNormal]];
+ p2 = [transformer toScreen:[e tail]];
+ p3 = [transformer toScreen:[e rightTailNormal]];
+ CGContextMoveToPoint(context, p1.x, p1.y);
+ CGContextAddLineToPoint(context, p2.x, p2.y);
+ CGContextAddLineToPoint(context, p3.x, p3.y);
+ CGContextClosePath(context);
+ CGContextFillPath(context);
+ break;
+ }
+ }
+
+
+ CGContextRestoreGState(context);
+
+ if ([e hasEdgeNode]) {
+ Node *en = [e edgeNode];
+ NSPoint mid = [transformer toScreen:[e mid]];
+ if (![[en label] isEqual:@""]) {
+ [layer drawLabel:[en label]
+ atPoint:mid
+ inContext:context
+ usingTrans:transformer];
+ }
+ }
+
+ EdgeControlLayer *ecl = [edgeControlLayers objectForKey:e];
+ [ecl setNeedsDisplay];
+}
+
+
+// draw the graph layer
+-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
+ for (Edge* e in [graph edges]) [self drawEdge:e onLayer:layer inContext:context];
+
+ for (Node* n in [graph nodes]) [self drawNode:n onLayer:layer inContext:context];
+
+ if ([graph hasBoundingBox]) {
+ CGRect bbox = NSRectToCGRect(NSIntegralRect(
+ [transformer rectToScreen:[graph boundingBox]]));
+ CGContextSetRGBStrokeColor(context, 1.0f, 0.7f, 0.5f, 1.0f);
+ CGContextSetLineWidth(context, 1.0f);
+ CGContextSetShouldAntialias(context, NO);
+ CGContextStrokeRect(context, bbox);
+ CGContextSetShouldAntialias(context, YES);
+ }
+
+ if (mouseMode == EdgeDragMode) {
+ CGContextMoveToPoint(context, dragOrigin.x, dragOrigin.y);
+ CGContextAddLineToPoint(context, dragTarget.x, dragTarget.y);
+ CGContextSetLineWidth(context, 2);
+ CGContextSetRGBStrokeColor(context, 0, 0, 1, 1);
+ CGContextStrokePath(context);
+ }
+}
+
+// if enabled, suppress the default "bonk" behaviour on key presses
+- (void)keyDown:(NSEvent *)theEvent {
+ if (!enabled) [super keyDown:theEvent];
+}
+
+- (void)delete:(id)sender {
+ BOOL didDelete = NO;
+ NSString *oldTikz = [graph tikz];
+
+ if ([[pickSupport selectedNodes] count] != 0) {
+ GraphChange *change = [graph removeNodes:[pickSupport selectedNodes]];
+ for (Node *n in [change affectedNodes]) [self removeNodeLayers:n];
+ for (Edge *e in [change affectedEdges]) [self removeEdgeLayers:e];
+
+ [self refreshLayers];
+ [self postGraphChange];
+ didDelete = YES;
+ }
+
+ if ([[pickSupport selectedEdges] count] != 0) {
+ [graph removeEdges:[pickSupport selectedEdges]];
+ for (Edge *e in [pickSupport selectedEdges]) [self removeEdgeLayers:e];
+ [self refreshLayers];
+ [self postGraphChange];
+ didDelete = YES;
+ }
+
+ [pickSupport deselectAllNodes];
+ [pickSupport deselectAllEdges];
+
+ if (didDelete) [self registerUndo:oldTikz withActionName:@"Delete Nodes or Edges"];
+}
+
+- (void)keyUp:(NSEvent *)theEvent {
+ if (!enabled) return;
+
+ id sender = self;
+ switch ([theEvent keyCode]) {
+ case 51: // delete
+ [self delete:sender]; // "self" is the sender
+ break;
+ case 1: // S
+ [toolPaletteController setSelectedTool:TikzToolSelect];
+ break;
+ case 45: // N
+ case 9: // V
+ [toolPaletteController setSelectedTool:TikzToolNode];
+ break;
+ case 14: // E
+ [toolPaletteController setSelectedTool:TikzToolEdge];
+ //[self updateMouseMode];
+ break;
+ case 40: // K
+ [toolPaletteController setSelectedTool:TikzToolCrop];
+ break;
+ }
+ [self refreshLayers];
+}
+
+
+- (void)deselectAll:(id)sender {
+ [pickSupport deselectAllNodes];
+ [pickSupport deselectAllEdges];
+
+ for (Node *n in [graph nodes]) {
+ [[[nodeLayers objectForKey:n] selection] deselect];
+ }
+
+ for (Edge *e in [graph edges]) {
+ [[edgeControlLayers objectForKey:e] deselect];
+ }
+
+ [self postSelectionChange];
+}
+
+- (void)selectAll:(id)sender {
+ [pickSupport selectAllNodes:[NSSet setWithArray:[graph nodes]]];
+
+ for (Node *n in [graph nodes]) {
+ [[[nodeLayers objectForKey:n] selection] select];
+ }
+
+ [self postSelectionChange];
+}
+
+
+- (void)updateMouseMode {
+ switch (toolPaletteController.selectedTool) {
+ case TikzToolSelect:
+ mouseMode = SelectMode;
+ break;
+ case TikzToolNode:
+ mouseMode = NodeMode;
+ break;
+ case TikzToolEdge:
+ mouseMode = EdgeMode;
+ break;
+ case TikzToolCrop:
+ mouseMode = CropMode;
+ break;
+ }
+}
+
+- (void)setDocumentUndoManager:(NSUndoManager *)um {
+ documentUndoManager = um;
+}
+
+- (void)copy:(id)sender {
+ if ([[pickSupport selectedNodes] count] != 0) {
+ Graph *clip = [graph copyOfSubgraphWithNodes:[pickSupport selectedNodes]];
+ NSString *tikz = [clip tikz];
+ NSData *data = [tikz dataUsingEncoding:NSUTF8StringEncoding];
+ //NSLog(@"about to copy: %@", tikz);
+ NSPasteboard *cb = [NSPasteboard generalPasteboard];
+ [cb declareTypes:[NSArray arrayWithObject:@"tikzpicture"] owner:self];
+ [cb setData:data forType:@"tikzpicture"];
+ }
+}
+
+- (void)cut:(id)sender {
+ if ([[pickSupport selectedNodes] count] != 0) {
+ [self copy:sender];
+ [self delete:sender];
+
+ // otherwise, menu will say "Undo Delete Graph"
+ [documentUndoManager setActionName:@"Cut Graph"];
+ }
+}
+
+- (void)paste:(id)sender {
+ NSPasteboard *cb = [NSPasteboard generalPasteboard];
+ NSString *type = [cb availableTypeFromArray:[NSArray arrayWithObject:@"tikzpicture"]];
+ if (type) {
+ NSData *data = [cb dataForType:type];
+ NSString *tikz = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ //NSLog(@"pasting tikz:\n%@",tikz);
+ Graph *clip = [TikzGraphAssembler parseTikz:tikz];
+ if (clip) {
+ //NSLog(@"tikz pasted:\n%@",tikz);
+ NSRect graphBounds = [graph bounds];
+ NSRect clipBounds = [clip bounds];
+ float dx = graphBounds.origin.x +
+ graphBounds.size.width -
+ clipBounds.origin.x + 0.5f;
+ [clip shiftNodes:[clip nodes] byPoint:NSMakePoint(dx, 0)];
+
+ if ([[clip nodes] count] != 0) {
+ NSString *oldTikz = [graph tikz];
+ [self deselectAll:self];
+
+ // select everything from the clipboard
+ for (Node *n in [clip nodes]) {
+ [n attachStyleFromTable:[stylePaletteController nodeStyles]];
+ [self addNodeLayers:n];
+ [pickSupport selectNode:n];
+ [[[nodeLayers objectForKey:n] selection] select];
+ }
+
+ for (Edge *e in [clip edges]) {
+ [e attachStyleFromTable:[stylePaletteController edgeStyles]];
+ [self addEdgeLayers:e];
+ }
+
+ [graph insertGraph:clip];
+
+ [self registerUndo:oldTikz withActionName:@"Paste Graph"];
+ [self refreshLayers];
+ [self postGraphChange];
+ }
+ } else {
+ NSLog(@"Error: couldn't parse tikz picture from clipboard.");
+ }
+
+ }
+}
+
+- (void)bringForward:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph bringNodesForward:[pickSupport selectedNodes]];
+ [graph bringEdgesForward:[pickSupport selectedEdges]];
+ [self registerUndo:oldTikz withActionName:@"Bring Forward"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)sendBackward:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph sendNodesBackward:[pickSupport selectedNodes]];
+ [graph sendEdgesBackward:[pickSupport selectedEdges]];
+ [self registerUndo:oldTikz withActionName:@"Send Backward"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)bringToFront:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph bringNodesToFront:[pickSupport selectedNodes]];
+ [graph bringEdgesToFront:[pickSupport selectedEdges]];
+ [self registerUndo:oldTikz withActionName:@"Bring to Front"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)sendToBack:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph sendNodesToBack:[pickSupport selectedNodes]];
+ [graph sendEdgesToBack:[pickSupport selectedEdges]];
+ [self registerUndo:oldTikz withActionName:@"Send to Back"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)flipHorizonal:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph flipHorizontalNodes:[pickSupport selectedNodes]];
+ [self registerUndo:oldTikz withActionName:@"Flip Horizontal"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)flipVertical:(id)sender {
+ NSString *oldTikz = [graph tikz];
+ [graph flipVerticalNodes:[pickSupport selectedNodes]];
+ [self registerUndo:oldTikz withActionName:@"Flip Vertical"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (void)reverseEdgeDirection:(id)sender {
+ NSString *oldTikz = [graph tikz];
+
+ NSSet *es;
+ if ([[pickSupport selectedEdges] count] != 0) {
+ es = [pickSupport selectedEdges];
+ } else {
+ es = [graph incidentEdgesForNodes:[pickSupport selectedNodes]];
+ }
+
+ for (Edge *e in es) [e reverse];
+
+ [self registerUndo:oldTikz withActionName:@"Flip Edge Direction"];
+ [self postGraphChange];
+ [self refreshLayers];
+}
+
+- (BOOL)acceptsFirstResponder { return YES; }
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { return YES; }
+- (BOOL)canBecomeKeyView { return YES; }
+
+
+@end
diff --git a/tikzit-1/src/osx/Grid.h b/tikzit-1/src/osx/Grid.h
new file mode 100644
index 0000000..76826e2
--- /dev/null
+++ b/tikzit-1/src/osx/Grid.h
@@ -0,0 +1,48 @@
+//
+// Grid.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "Transformer.h"
+
+@interface Grid : NSObject {
+ float gridX, gridY;
+ //float gridCellX, gridCellY;
+ int subdivisions;
+ Transformer *transformer;
+ NSSize size;
+}
+
+@property NSSize size;
+
+- (id)initWithSpacing:(float)spacing subdivisions:(int)subs transformer:(Transformer*)t;
++ (Grid*)gridWithSpacing:(float)spacing subdivisions:(int)subs transformer:(Transformer*)t;
+- (NSPoint)snapScreenPoint:(NSPoint)p;
+- (float)gridX;
+- (float)gridY;
+- (int)subdivisions;
+- (void)setSubdivisions:(int)subs;
+
+// Grid can also draw itself on a layer
+- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
+
+@end
diff --git a/tikzit-1/src/osx/Grid.m b/tikzit-1/src/osx/Grid.m
new file mode 100644
index 0000000..aa35c1f
--- /dev/null
+++ b/tikzit-1/src/osx/Grid.m
@@ -0,0 +1,152 @@
+//
+// Grid.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "Grid.h"
+
+
+@implementation Grid
+
+@synthesize size;
+
+- (id)initWithSpacing:(float)spacing
+ subdivisions:(int)subs
+ transformer:(Transformer*)t
+{
+ if (!(self = [super init])) return nil;
+ gridX = spacing;
+ gridY = spacing;
+ subdivisions = subs;
+ size.width = 0;
+ size.height = 0;
+ transformer = t;
+ return self;
+}
+
++ (Grid*)gridWithSpacing:(float)spacing
+ subdivisions:(int)subs
+ transformer:(Transformer*)t
+{
+ return [[Grid alloc] initWithSpacing:spacing
+ subdivisions:subs
+ transformer:t];
+}
+
+- (float)gridX {
+ return gridX;
+}
+
+- (float)gridY {
+ return gridY;
+}
+
+- (int)subdivisions {
+ return subdivisions;
+}
+
+- (void)setSubdivisions:(int)subs {
+ subdivisions = subs;
+}
+
+- (NSPoint)snapScreenPoint:(NSPoint)p {
+ NSPoint snap;
+
+ float gridCellX = [transformer scaleToScreen:gridX] / (float)subdivisions;
+ float gridCellY = [transformer scaleToScreen:gridY] / (float)subdivisions;
+
+ // snap along grid lines, relative to the origin
+ snap.x = floor(((p.x-[transformer origin].x)/gridCellX)+0.5)*gridCellX + [transformer origin].x;
+ snap.y = floor(((p.y-[transformer origin].y)/gridCellY)+0.5)*gridCellY + [transformer origin].y;
+ return snap;
+}
+
+-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context
+{
+ CGContextSaveGState(context);
+
+ CGContextSetShouldAntialias(context, NO);
+
+ float x,y;
+ float grX = [transformer scaleToScreen:gridX];
+ float grY = [transformer scaleToScreen:gridY];
+
+ float gridCellX = grX / (float)subdivisions;
+ float gridCellY = grY / (float)subdivisions;
+
+ for (x = [transformer origin].x + gridCellX; x < size.width; x += gridCellX) {
+ CGContextMoveToPoint(context, x, 0);
+ CGContextAddLineToPoint(context, x, size.height);
+ }
+
+ for (x = [transformer origin].x - gridCellX; x > 0; x -= gridCellX) {
+ CGContextMoveToPoint(context, x, 0);
+ CGContextAddLineToPoint(context, x, size.height);
+ }
+
+ for (y = [transformer origin].y + gridCellY; y < size.height; y += gridCellY) {
+ CGContextMoveToPoint(context, 0, y);
+ CGContextAddLineToPoint(context, size.width, y);
+ }
+
+ for (y = [transformer origin].y - gridCellY; y > 0; y -= gridCellY) {
+ CGContextMoveToPoint(context, 0, y);
+ CGContextAddLineToPoint(context, size.width, y);
+ }
+
+ CGContextSetRGBStrokeColor(context, 0.9, 0.9, 1, 1);
+ CGContextStrokePath(context);
+
+ for (x = [transformer origin].x + grX; x < size.width; x += grX) {
+ CGContextMoveToPoint(context, x, 0);
+ CGContextAddLineToPoint(context, x, size.height);
+ }
+
+ for (x = [transformer origin].x - grX; x > 0; x -= grX) {
+ CGContextMoveToPoint(context, x, 0);
+ CGContextAddLineToPoint(context, x, size.height);
+ }
+
+ for (y = [transformer origin].y + grY; y < size.height; y += grY) {
+ CGContextMoveToPoint(context, 0, y);
+ CGContextAddLineToPoint(context, size.width, y);
+ }
+
+ for (y = [transformer origin].y + grY; y > 0; y -= grY) {
+ CGContextMoveToPoint(context, 0, y);
+ CGContextAddLineToPoint(context, size.width, y);
+ }
+
+ CGContextSetRGBStrokeColor(context, 0.8, 0.8, 0.9, 1);
+ CGContextStrokePath(context);
+
+ CGContextMoveToPoint(context, [transformer origin].x, 0);
+ CGContextAddLineToPoint(context, [transformer origin].x, size.height);
+ CGContextMoveToPoint(context, 0, [transformer origin].y);
+ CGContextAddLineToPoint(context, size.width, [transformer origin].y);
+
+ CGContextSetRGBStrokeColor(context, 0.6, 0.6, 0.7, 1);
+ CGContextStrokePath(context);
+
+ CGContextRestoreGState(context);
+}
+
+@end
diff --git a/tikzit-1/src/osx/MultiCombo.h b/tikzit-1/src/osx/MultiCombo.h
new file mode 100644
index 0000000..c8ec769
--- /dev/null
+++ b/tikzit-1/src/osx/MultiCombo.h
@@ -0,0 +1,18 @@
+//
+// MultiCombo.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 21/04/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface MultiCombo : NSComboBox {
+ BOOL multi;
+}
+
+@property (readwrite,assign) BOOL multi;
+
+@end
diff --git a/tikzit-1/src/osx/MultiCombo.m b/tikzit-1/src/osx/MultiCombo.m
new file mode 100644
index 0000000..8930460
--- /dev/null
+++ b/tikzit-1/src/osx/MultiCombo.m
@@ -0,0 +1,38 @@
+//
+// MultiCombo.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 21/04/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import "MultiCombo.h"
+
+
+@implementation MultiCombo
+
+- (void)textDidChange:(NSNotification *)notification {
+ [super textDidChange:notification];
+ [self setMulti:NO];
+}
+
+- (void)setMulti:(BOOL)m {
+ multi = m;
+ if (multi) {
+ [self setTextColor:[NSColor grayColor]];
+ [self setStringValue:@"multiple values"];
+ }
+}
+
+- (BOOL)multi { return multi; }
+
+- (BOOL)becomeFirstResponder {
+ [super becomeFirstResponder];
+ if ([self multi]) {
+ [self setTextColor:[NSColor blackColor]];
+ [self setStringValue:@""];
+ }
+ return YES;
+}
+
+@end
diff --git a/tikzit-1/src/osx/MultiField.h b/tikzit-1/src/osx/MultiField.h
new file mode 100644
index 0000000..39eeefa
--- /dev/null
+++ b/tikzit-1/src/osx/MultiField.h
@@ -0,0 +1,18 @@
+//
+// LabelField.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 20/04/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface MultiField : NSTextField {
+ BOOL multi;
+}
+
+@property (readwrite,assign) BOOL multi;
+
+@end
diff --git a/tikzit-1/src/osx/MultiField.m b/tikzit-1/src/osx/MultiField.m
new file mode 100644
index 0000000..7c5aac3
--- /dev/null
+++ b/tikzit-1/src/osx/MultiField.m
@@ -0,0 +1,53 @@
+//
+// LabelField.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 20/04/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import "MultiField.h"
+
+
+@implementation MultiField
+
+- (void)textDidChange:(NSNotification *)notification {
+ [super textDidChange:notification];
+ [self setMulti:NO];
+}
+
+- (void)setMulti:(BOOL)m {
+ multi = m;
+ if (multi) {
+ [self setTextColor:[NSColor grayColor]];
+ [self setStringValue:@"multiple values"];
+ }
+}
+
+- (BOOL)multi { return multi; }
+
+- (BOOL)becomeFirstResponder {
+ [super becomeFirstResponder];
+ if ([self multi]) {
+ [self setTextColor:[NSColor blackColor]];
+ [self setStringValue:@""];
+ }
+ return YES;
+}
+
+//- (BOOL)textShouldBeginEditing:(NSText *)textObject {
+// [super textShouldBeginEditing:textObject];
+// NSLog(@"about to type");
+// return YES;
+//}
+
+//- (void)textDidEndEditing:(NSNotification *)obj {
+// [super textDidEndEditing:obj];
+//
+// NSLog(@"focus lost");
+// if ([self multi]) {
+// [self setMulti:YES];
+// }
+//}
+
+@end
diff --git a/tikzit-1/src/osx/NilToEmptyStringTransformer.h b/tikzit-1/src/osx/NilToEmptyStringTransformer.h
new file mode 100644
index 0000000..1445a94
--- /dev/null
+++ b/tikzit-1/src/osx/NilToEmptyStringTransformer.h
@@ -0,0 +1,28 @@
+//
+// NilToEmptyStringTransformer.h
+// TikZiT
+//
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NilToEmptyStringTransformer : NSValueTransformer
+
+@end
diff --git a/tikzit-1/src/osx/NilToEmptyStringTransformer.m b/tikzit-1/src/osx/NilToEmptyStringTransformer.m
new file mode 100644
index 0000000..413f404
--- /dev/null
+++ b/tikzit-1/src/osx/NilToEmptyStringTransformer.m
@@ -0,0 +1,53 @@
+//
+// NilToEmptyStringTransformer.m
+// TikZiT
+//
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "NilToEmptyStringTransformer.h"
+
+@implementation NilToEmptyStringTransformer
+
+- (id)init {
+ if (!(self = [super init])) return nil;
+ return self;
+}
+
++ (Class)transformedValueClass {
+ return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation {
+ return YES;
+}
+
+- (id)transformedValue:(id)value {
+ if (value == nil) {
+ return @"";
+ } else {
+ return value;
+ }
+}
+
+- (id)reverseTransformedValue:(id)value {
+ return [self transformedValue:value];
+}
+
+@end
diff --git a/tikzit-1/src/osx/NodeLayer.h b/tikzit-1/src/osx/NodeLayer.h
new file mode 100644
index 0000000..dbcdac5
--- /dev/null
+++ b/tikzit-1/src/osx/NodeLayer.h
@@ -0,0 +1,62 @@
+//
+// NodeLayer.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+#import "Transformer.h"
+#import "Shape.h"
+#import "Node.h"
+#import "NodeStyle+Coder.h"
+#import "NodeSelectionLayer.h"
+
+@interface NodeLayer : CALayer {
+ Node *node;
+ Shape *shape;
+ CGMutablePathRef path;
+ float textwidth;
+ NSPoint center;
+ Transformer *transformer;
+ Transformer *localTrans;
+ NodeSelectionLayer *selection;
+ BOOL rescale;
+ BOOL dirty; // need to rebuild CGBezierPath of the shape
+}
+
+@property (strong) Node *node;
+@property (assign) NSPoint center;
+@property (assign) BOOL rescale;
+@property (strong) NodeSelectionLayer *selection;
+@property (readonly) CGMutablePathRef path;
+
+- (id)initWithNode:(Node*)n transformer:(Transformer*)t;
+- (NSColor*)strokeColor;
+- (NSColor*)fillColor;
+- (float)strokeWidth;
+
+- (void)setCenter:(NSPoint)ctr andAnimateWhen:(BOOL)anim;
+- (void)updateFrame;
+- (BOOL)nodeContainsPoint:(NSPoint)p;
+
+- (void)drawInContext:(CGContextRef)context;
+
+@end
diff --git a/tikzit-1/src/osx/NodeLayer.m b/tikzit-1/src/osx/NodeLayer.m
new file mode 100644
index 0000000..5d15585
--- /dev/null
+++ b/tikzit-1/src/osx/NodeLayer.m
@@ -0,0 +1,238 @@
+//
+// NodeLayer.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "NodeLayer.h"
+#import "CALayer+DrawLabel.h"
+#import "NSString+LatexConstants.h"
+#import "Shape.h"
+#import "ShapeNames.h"
+#import "Node.h"
+#import "Edge.h"
+
+@implementation NodeLayer
+
+@synthesize node, selection, rescale;
+
+- (id)initWithNode:(Node *)n transformer:(Transformer*)t {
+ if (!(self = [super init])) return nil;
+ node = n;
+ selection = [[NodeSelectionLayer alloc] init];
+ [selection setNodeLayer:self];
+ localTrans = [[Transformer alloc] init];
+
+ [self addSublayer:selection];
+ textwidth = 0.0f;
+ center = NSMakePoint(0.0f, 0.0f);
+ transformer = t;
+
+ path = NULL;
+ rescale = YES;
+ dirty = YES;
+
+ [self updateFrame];
+ return self;
+}
+
+- (NSColor*)strokeColor {
+ if ([node style] != nil) {
+ return [[[node style] strokeColor] colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
+ } else {
+ return nil;
+ }
+}
+
+- (NSColor*)fillColor {
+ if ([node style] != nil) {
+ return [[[node style] fillColor] colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]];
+ } else {
+ return nil;
+ }
+}
+
+- (float)strokeWidth {
+ if ([node style] != nil) {
+ return [node.style strokeThickness];
+ } else {
+ return [NodeStyle defaultStrokeThickness];
+ }
+}
+
+- (NSPoint)center { return center; }
+
+- (void)setCenter:(NSPoint)ctr {
+ center.x = round(ctr.x);
+ center.y = round(ctr.y);
+ [self updateFrame];
+}
+
+- (void)setCenter:(NSPoint)ctr andAnimateWhen:(BOOL)anim {
+ [CATransaction begin];
+ if (!anim) {
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+ }
+ [self setCenter:ctr];
+ [CATransaction commit];
+}
+
+- (void)updateShape {
+ Shape *s = ([node style] != nil) ?
+ [Shape shapeForName:[[node style] shapeName]] :
+ [Shape shapeForName:SHAPE_CIRCLE];
+ if (s != shape) { // straight pointer comparison
+ shape = s;
+ dirty = YES;
+ }
+}
+
+- (void)updateLocalTrans {
+ float scale = ([node style] != nil) ? [[node style] scale] : 1.0f;
+
+ Transformer *t = [Transformer transformer];
+ float rad = ([transformer scaleToScreen:scale] / 2.0f) + 8.0f;
+ [t setOrigin:NSMakePoint(rad, rad)];
+ [t setScale:[transformer scale]*((rescale)?scale:0.8f)];
+
+ if (![localTrans isEqual:t]) {
+ dirty = YES;
+ localTrans = t;
+ }
+}
+
+- (void)updateFrame {
+ [self updateLocalTrans];
+ [self updateShape];
+ float rad = [localTrans origin].x;
+ [self setFrame:CGRectIntegral(CGRectMake(center.x - rad, center.y - rad, 2*rad, 2*rad))];
+ NSRect bds = NSMakeRect(0, 0, 2*rad, 2*rad);
+ [selection setFrame:NSRectToCGRect(bds)];
+
+ [self setNeedsDisplay];
+ [selection setNeedsDisplay];
+}
+
+- (CGMutablePathRef)path {
+ if (dirty) {
+ CGMutablePathRef pth = CGPathCreateMutable();
+ NSPoint p, cp1, cp2;
+ for (NSArray *arr in [shape paths]) {
+ BOOL fst = YES;
+ for (Edge *e in arr) {
+ if (fst) {
+ fst = NO;
+ p = [localTrans toScreen:[[e source] point]];
+ CGPathMoveToPoint(pth, nil, p.x, p.y);
+ }
+
+ p = [localTrans toScreen:[[e target] point]];
+ if ([e isStraight]) {
+ CGPathAddLineToPoint(pth, nil, p.x, p.y);
+ } else {
+ cp1 = [localTrans toScreen:[e cp1]];
+ cp2 = [localTrans toScreen:[e cp2]];
+ CGPathAddCurveToPoint(pth, nil, cp1.x, cp1.y, cp2.x, cp2.y, p.x, p.y);
+ }
+ }
+
+ CGPathCloseSubpath(pth);
+ }
+
+ if (path != NULL) CFRelease(path);
+ path = pth;
+ dirty = NO;
+ }
+
+
+ return path;
+}
+
+- (BOOL)nodeContainsPoint:(NSPoint)p {
+ CGPoint p1 = CGPointMake(p.x - [self frame].origin.x, p.y - [self frame].origin.y);
+ return CGPathContainsPoint([self path],nil,p1,NO);
+}
+
+
+- (void)drawInContext:(CGContextRef)context {
+ CGContextSaveGState(context);
+
+
+ if ([node style] == nil) {
+ CGContextSetRGBStrokeColor(context, 0.4f, 0.4f, 0.7f, 1.0f);
+ CGContextSetRGBFillColor(context, 0.4f, 0.4f, 0.7f, 1.0f);
+ //CGRect fr = [self frame];
+ CGRect bds = NSRectToCGRect([localTrans rectToScreen:NSMakeRect(-0.5, -0.5, 1, 1)]);
+ CGRect pt = CGRectMake(CGRectGetMidX(bds)-1.0f, CGRectGetMidY(bds)-1.0f, 2.0f, 2.0f);
+ CGContextSetLineWidth(context, 0);
+ CGContextAddEllipseInRect(context, pt);
+ CGContextFillPath(context);
+
+ // HACK: for some reason, CGFloat isn't getting typedef'ed properly
+
+#ifdef __x86_64__
+ const double dash[2] = {2.0,2.0};
+#else
+ const float dash[2] = {2.0,2.0};
+#endif
+ CGContextSetLineDash(context, 0.0, dash, 2);
+ CGContextSetLineWidth(context, 1);
+ CGContextAddPath(context, [self path]);
+ CGContextStrokePath(context);
+ } else {
+ NSColor *stroke = [self strokeColor];
+ NSColor *fill = [self fillColor];
+
+ CGContextSetRGBStrokeColor(context,
+ [stroke redComponent],
+ [stroke greenComponent],
+ [stroke blueComponent],
+ [stroke alphaComponent]);
+
+ CGContextSetLineWidth(context, [self strokeWidth]);
+
+ CGContextSetRGBFillColor(context,
+ [fill redComponent],
+ [fill greenComponent],
+ [fill blueComponent],
+ [fill alphaComponent]);
+
+
+ CGContextSetLineWidth(context, [self strokeWidth]);
+ CGContextAddPath(context, [self path]);
+ CGContextDrawPath(context, kCGPathFillStroke);
+ }
+
+ if (!([node label] == nil || [[node label] isEqual:@""])) {
+ NSPoint labelPt = NSMakePoint([self frame].size.width/2, [self frame].size.height/2);
+ [self drawLabel:[[node label] stringByExpandingLatexConstants]
+ atPoint:labelPt
+ inContext:context
+ usingTrans:transformer];
+ }
+
+ CGContextRestoreGState(context);
+}
+
+- (void)dealloc {
+ if (path != NULL) CFRelease(path);
+}
+
+@end
diff --git a/tikzit-1/src/osx/NodeSelectionLayer.h b/tikzit-1/src/osx/NodeSelectionLayer.h
new file mode 100644
index 0000000..99ee75f
--- /dev/null
+++ b/tikzit-1/src/osx/NodeSelectionLayer.h
@@ -0,0 +1,45 @@
+//
+// NodeSelectionLayer.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+#import "Shape.h"
+
+@class NodeLayer;
+
+@interface NodeSelectionLayer : CALayer {
+ BOOL selected;
+ CGMutablePathRef path;
+ NSLock *drawLock;
+ NodeLayer *nodeLayer;
+}
+
+@property NodeLayer *nodeLayer;
+
+- (id)init;
+- (void)select;
+- (void)deselect;
+- (void)highlight;
+- (void)unhighlight;
+
+@end
diff --git a/tikzit-1/src/osx/NodeSelectionLayer.m b/tikzit-1/src/osx/NodeSelectionLayer.m
new file mode 100644
index 0000000..02b8ac2
--- /dev/null
+++ b/tikzit-1/src/osx/NodeSelectionLayer.m
@@ -0,0 +1,93 @@
+//
+// NodeSelectionLayer.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "NodeSelectionLayer.h"
+#import "NodeLayer.h"
+#import "CircleShape.h"
+
+@implementation NodeSelectionLayer
+
+@synthesize nodeLayer;
+
+- (id)init {
+ if (!(self = [super init])) return nil;
+ selected = NO;
+ drawLock = [[NSLock alloc] init];
+ nodeLayer = nil;
+ [self setOpacity:0.0f];
+ return self;
+}
+
+
+- (void)select {
+ selected = YES;
+ [self setOpacity:0.5f];
+}
+
+- (void)deselect {
+ selected = NO;
+ [self setOpacity:0.0f];
+}
+
+- (void)highlight {
+ if (!selected) {
+ [self setOpacity:0.25f];
+ }
+}
+
+- (void)unhighlight {
+ if (!selected) {
+ [self setOpacity:0.0f];
+ }
+}
+
+//- (CGMutablePathRef)path {
+// return path;
+//}
+//
+//- (void)setPath:(CGMutablePathRef)p {
+// path = CGPathCreateMutableCopy(p);
+// CFMakeCollectable(path);
+//}
+
+- (void)drawInContext:(CGContextRef)context {
+ [drawLock lock];
+ CGContextSaveGState(context);
+
+ //CGContextSetRGBStrokeColor(context, 0.61f, 0.735f, 1.0f, 1.0f);
+ CGContextSetRGBStrokeColor(context, 0.61f, 0.735f, 1.0f, 1.0f);
+ CGContextSetRGBFillColor(context, 0.61f, 0.735f, 1.0f, 1.0f);
+ CGContextSetLineWidth(context, 6.0f);
+
+ if (nodeLayer != nil) {
+ CGContextAddPath(context, [nodeLayer path]);
+ } else {
+ NSLog(@"WARNING: attempting to draw selection with path = nil.");
+ }
+ CGContextDrawPath(context, kCGPathFillStroke);
+
+ CGContextRestoreGState(context);
+ [drawLock unlock];
+}
+
+@end
diff --git a/tikzit-1/src/osx/NodeStyle+Coder.h b/tikzit-1/src/osx/NodeStyle+Coder.h
new file mode 100644
index 0000000..b6443af
--- /dev/null
+++ b/tikzit-1/src/osx/NodeStyle+Coder.h
@@ -0,0 +1,36 @@
+//
+// NodeStyle+Coder.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "NodeStyle.h"
+
+
+@interface NodeStyle(Coder)
+
+@property (copy) NSColor *fillColor;
+@property (copy) NSColor *strokeColor;
+
+- (id)initWithCoder:(NSCoder *)coder;
+- (void)encodeWithCoder:(NSCoder *)coder;
+
+@end
diff --git a/tikzit-1/src/osx/NodeStyle+Coder.m b/tikzit-1/src/osx/NodeStyle+Coder.m
new file mode 100644
index 0000000..d3623f5
--- /dev/null
+++ b/tikzit-1/src/osx/NodeStyle+Coder.m
@@ -0,0 +1,91 @@
+//
+// NodeStyle+Coder.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "NodeStyle+Coder.h"
+#import "ShapeNames.h"
+
+@implementation NodeStyle(Coder)
+
+- (NSColor*)fillColor {
+ return [NSColor colorWithDeviceRed:fillColorRGB.redFloat
+ green:fillColorRGB.greenFloat
+ blue:fillColorRGB.blueFloat
+ alpha:1.0f];
+}
+
+- (void)setFillColor:(NSColor*)c {
+ NSColor *c1 = [c colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ [self willChangeValueForKey:@"fillColorIsKnown"];
+ fillColorRGB = [ColorRGB colorWithFloatRed:c1.redComponent
+ green:c1.greenComponent
+ blue:c1.blueComponent];
+ [self didChangeValueForKey:@"fillColorIsKnown"];
+}
+
+- (NSColor*)strokeColor {
+ return [NSColor colorWithDeviceRed:strokeColorRGB.redFloat
+ green:strokeColorRGB.greenFloat
+ blue:strokeColorRGB.blueFloat
+ alpha:1.0f];
+}
+
+- (void)setStrokeColor:(NSColor*)c {
+ NSColor *c1 = [c colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ [self willChangeValueForKey:@"strokeColorIsKnown"];
+ strokeColorRGB = [ColorRGB colorWithFloatRed:c1.redComponent
+ green:c1.greenComponent
+ blue:c1.blueComponent];
+ [self didChangeValueForKey:@"strokeColorIsKnown"];
+}
+
+- (id)initWithCoder:(NSCoder *)coder {
+ if (!(self = [super init])) return nil;
+
+ // decode keys
+ name = [coder decodeObjectForKey:@"name"];
+ [self setStrokeColor:[coder decodeObjectForKey:@"strokeColor"]];
+ [self setFillColor:[coder decodeObjectForKey:@"fillColor"]];
+ strokeThickness = [coder decodeIntForKey:@"strokeThickness"];
+ shapeName = [coder decodeObjectForKey:@"shapeName"];
+ category = [coder decodeObjectForKey:@"category"];
+ scale = [coder decodeFloatForKey:@"scale"];
+
+ // apply defaults
+ if (scale == 0.0f) scale = 1.0f;
+ if (shapeName == nil) shapeName = SHAPE_CIRCLE;
+
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+ [coder encodeObject:name forKey:@"name"];
+ [coder encodeObject:[self strokeColor] forKey:@"strokeColor"];
+ [coder encodeObject:[self fillColor] forKey:@"fillColor"];
+ [coder encodeInt:strokeThickness forKey:@"strokeThickness"];
+ [coder encodeObject:shapeName forKey:@"shapeName"];
+ [coder encodeObject:category forKey:@"category"];
+ [coder encodeFloat:scale forKey:@"scale"];
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/ParseErrorView.h b/tikzit-1/src/osx/ParseErrorView.h
new file mode 100644
index 0000000..bb6141f
--- /dev/null
+++ b/tikzit-1/src/osx/ParseErrorView.h
@@ -0,0 +1,13 @@
+//
+// ParseErrorView.h
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 27/01/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface ParseErrorView : NSView
+
+@end
diff --git a/tikzit-1/src/osx/ParseErrorView.m b/tikzit-1/src/osx/ParseErrorView.m
new file mode 100644
index 0000000..83383f0
--- /dev/null
+++ b/tikzit-1/src/osx/ParseErrorView.m
@@ -0,0 +1,40 @@
+//
+// ParseErrorView.m
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 27/01/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+
+#import "ParseErrorView.h"
+
+@implementation ParseErrorView
+
+- (id)initWithFrame:(NSRect)frame
+{
+ self = [super initWithFrame:frame];
+ if (self) {
+ // Initialization code here.
+ }
+
+ return self;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+ // Drawing code here.
+}
+
+- (void)awakeFromNib{
+ self.layer = [CALayer layer];
+ self.wantsLayer = YES;
+ CALayer *newLayer = [CALayer layer];
+ self.layer.backgroundColor = [[NSColor controlColor] CGColor];
+ //CGColorCreate(CGColorSpaceCreateDeviceRGB(), (CGFloat[]){ 1, .9, .64, 1 });
+// newLayer.backgroundColor = [NSColor redColor].CGColor;
+ newLayer.frame = CGRectMake(100,100,100,100);//NSMakeRect(0,0,image.size.width,image.size.height);
+ newLayer.position = CGPointMake(20,20);
+ //[self.layer addSublayer:newLayer];
+}
+
+@end
diff --git a/tikzit-1/src/osx/PreambleController.h b/tikzit-1/src/osx/PreambleController.h
new file mode 100644
index 0000000..5b0931d
--- /dev/null
+++ b/tikzit-1/src/osx/PreambleController.h
@@ -0,0 +1,57 @@
+//
+// PreambleController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "Preambles.h"
+#import "Preambles+Coder.h"
+
+@interface PreambleController : NSViewController {
+ Preambles *preambles;
+ IBOutlet NSTextView *textView;
+ IBOutlet NSDictionaryController *preambleDictionaryController;
+
+ NSDictionary *textAttrs;
+ NSAttributedString *preambleText;
+ NSColor *ghostColor;
+ NSIndexSet *selectionIndexes;
+}
+
+@property (readonly) BOOL useDefaultPreamble;
+@property (readonly) Preambles *preambles;
+@property (strong) NSAttributedString *preambleText;
+@property (strong) NSIndexSet *selectionIndexes;
+
+- (id)initWithNibName:(NSString *)nibName plist:(NSString*)plist styles:(NSArray*)sty edges:(NSArray*)edg;
+- (void)savePreambles:(NSString*)plist;
+- (NSString*)currentPreamble;
+- (NSString*)currentPostamble;
+- (NSString*)buildDocumentForTikz:(NSString*)tikz;
+
+- (IBAction)setPreambleToDefault:(id)sender;
+- (IBAction)setPreamble:(id)sender;
+- (IBAction)insertDefaultStyles:(id)sender;
+
+- (IBAction)addPreamble:(id)sender;
+- (IBAction)duplicatePreamble:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/PreambleController.m b/tikzit-1/src/osx/PreambleController.m
new file mode 100644
index 0000000..206bb30
--- /dev/null
+++ b/tikzit-1/src/osx/PreambleController.m
@@ -0,0 +1,168 @@
+//
+// PreambleController.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "PreambleController.h"
+
+
+@implementation PreambleController
+
+@synthesize preambleText, preambles;
+
+- (id)initWithNibName:(NSString *)nibName plist:(NSString*)plist styles:(NSArray*)sty edges:(NSArray*)edg {
+ if (!(self = [super initWithNibName:nibName bundle:Nil])) return nil;
+
+ preambles = (Preambles*)[NSKeyedUnarchiver unarchiveObjectWithFile:plist];
+ [preambles setStyles:sty];
+ [preambles setEdges:edg];
+ if (preambles == nil) preambles = [[Preambles alloc] init];
+
+ preambleText = nil;
+
+ NSFont *font = [NSFont userFixedPitchFontOfSize:11.0f];
+ textAttrs = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
+ ghostColor = [NSColor colorWithDeviceRed:0.9f green:0.9f blue:0.9f alpha:1.0f];
+
+
+
+ return self;
+}
+
+- (void)awakeFromNib {
+ NSArray *arr = [preambleDictionaryController arrangedObjects];
+ NSString *current = [preambles selectedPreambleName];
+
+ if (current != nil && ![current isEqual:@"default"]) {
+ for (int i = 0; i < [arr count]; ++i) {
+ if ([[[arr objectAtIndex:i] key] isEqual:current]) {
+ [self setSelectionIndexes:[NSIndexSet indexSetWithIndex:i]];
+ break;
+ }
+ }
+ }
+}
+
+- (BOOL)useDefaultPreamble {
+ return [[preambles selectedPreambleName] isEqualToString:@"default"];
+}
+
+- (void)flushText {
+ if (preambleText != nil && ![self useDefaultPreamble]) {
+ [preambles setCurrentPreamble:[preambleText string]];
+ }
+}
+
+- (void)setCurrentPreamble:(NSString*)current {
+ [self flushText];
+
+ [self willChangeValueForKey:@"useDefaultPreamble"];
+ [preambles setSelectedPreambleName:current];
+ [self didChangeValueForKey:@"useDefaultPreamble"];
+
+ [self setPreambleText:
+ [[NSAttributedString alloc] initWithString:[preambles currentPreamble]
+ attributes:textAttrs]];
+}
+
+- (void)savePreambles:(NSString*)plist {
+ [self flushText];
+ [NSKeyedArchiver archiveRootObject:preambles toFile:plist];
+}
+
+- (NSString*)currentPreamble {
+ [self flushText];
+ return [preambles currentPreamble];
+}
+
+- (NSString*)currentPostamble {
+ return [preambles currentPostamble];
+}
+
+- (NSString*)buildDocumentForTikz:(NSString*)tikz {
+ [self flushText];
+ return [preambles buildDocumentForTikz:tikz];
+}
+
+- (void)setSelectionIndexes:(NSIndexSet *)idx {
+ [self willChangeValueForKey:@"selectionIndexes"];
+ selectionIndexes = idx;
+ [self didChangeValueForKey:@"selectionIndexes"];
+
+ [self setPreamble:self];
+}
+
+- (NSIndexSet*)selectionIndexes {
+ return selectionIndexes;
+}
+
+- (IBAction)setPreambleToDefault:(id)sender{
+ [self setCurrentPreamble:@"default"];
+ [textView setBackgroundColor:ghostColor];
+}
+
+- (IBAction)setPreamble:(id)sender {
+ //if ([[toolbar selectedItemIdentifier] isEqualToString:[defaultToolbarItem itemIdentifier]]) {
+ // [self setCurrentPreamble:@"default"];
+ // [textView setBackgroundColor:ghostColor];
+ //} else if ([[toolbar selectedItemIdentifier] isEqualToString:[customToolbarItem itemIdentifier]]) {
+ NSString *key = nil;
+ if ([selectionIndexes count]==1) {
+ int i = [selectionIndexes firstIndex];
+ key = [[[preambleDictionaryController arrangedObjects] objectAtIndex:i] key];
+ }
+ if (key != nil) {
+ [self setCurrentPreamble:key];
+ //NSLog(@"preamble set to %@", key);
+ } else {
+ [self setCurrentPreamble:@"custom"];
+ //NSLog(@"preamble set to custom");
+ }
+ [textView setBackgroundColor:[NSColor whiteColor]];
+ //}
+}
+
+- (IBAction)insertDefaultStyles:(id)sender {
+ [textView insertText:[preambles styleDefinitions]];
+}
+
+- (IBAction)addPreamble:(id)sender {
+ [preambleDictionaryController setInitialKey:@"new preamble"];
+ [preambleDictionaryController setInitialValue:[preambles defaultPreamble]];
+ [preambleDictionaryController add:sender];
+}
+
+- (void)controlTextDidEndEditing:(NSNotification *)obj {
+ //NSLog(@"got a text change");
+ [self setPreamble:[obj object]];
+}
+
+
+// NOT IMPLEMENTED
+- (IBAction)duplicatePreamble:(id)sender {
+// NSLog(@"set text to: %@", [preambles currentPreamble]);
+// [preambleDictionaryController setInitialKey:[preambles selectedPreambleName]];
+// [preambleDictionaryController setInitialValue:[preambles currentPreamble]];
+// [preambleDictionaryController add:sender];
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/Preambles+Coder.h b/tikzit-1/src/osx/Preambles+Coder.h
new file mode 100644
index 0000000..5a270c5
--- /dev/null
+++ b/tikzit-1/src/osx/Preambles+Coder.h
@@ -0,0 +1,32 @@
+//
+// Preambles+Coder.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "Preambles.h"
+#import <Cocoa/Cocoa.h>
+
+@interface Preambles (Coder)
+
+- (id)initWithCoder:(NSCoder *)coder;
+- (void)encodeWithCoder:(NSCoder *)coder;
+
+@end
diff --git a/tikzit-1/src/osx/Preambles+Coder.m b/tikzit-1/src/osx/Preambles+Coder.m
new file mode 100644
index 0000000..5e468b2
--- /dev/null
+++ b/tikzit-1/src/osx/Preambles+Coder.m
@@ -0,0 +1,41 @@
+//
+// Preambles+Coder.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "Preambles+Coder.h"
+
+
+@implementation Preambles (Coder)
+
+- (id)initWithCoder:(NSCoder *)coder {
+ if (!(self = [super init])) return nil;
+ selectedPreambleName = [coder decodeObjectForKey:@"selectedPreamble"];
+ preambleDict = [coder decodeObjectForKey:@"preambles"];
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder {
+ [coder encodeObject:selectedPreambleName forKey:@"selectedPreamble"];
+ [coder encodeObject:preambleDict forKey:@"preambles"];
+}
+
+@end
diff --git a/tikzit-1/src/osx/PreferenceController.h b/tikzit-1/src/osx/PreferenceController.h
new file mode 100644
index 0000000..b2b23f3
--- /dev/null
+++ b/tikzit-1/src/osx/PreferenceController.h
@@ -0,0 +1,49 @@
+//
+// PreferenceController.h
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 26/02/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "UpdatePreferenceController.h"
+#import "PreambleController.h"
+#import "CustomNodeController.h"
+
+@interface PreferenceController : NSWindowController{
+
+ IBOutlet NSView *engineView;
+ IBOutlet NSView *generalView;
+ IBOutlet NSView *updateView;
+ IBOutlet NSView *preambleView;
+ IBOutlet NSView *customNodeView;
+
+ UpdatePreferenceController *updateController;
+ PreambleController *preambleController;
+ CustomNodeController *customNodeController;
+
+ int currentViewTag;
+}
+
+- (id)initWithWindowNibName:(NSString *)windowNibName preambleController:(PreambleController *)pc;
+
+- (IBAction)switchView:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/PreferenceController.m b/tikzit-1/src/osx/PreferenceController.m
new file mode 100644
index 0000000..e785358
--- /dev/null
+++ b/tikzit-1/src/osx/PreferenceController.m
@@ -0,0 +1,133 @@
+//
+// PreferenceController.m
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 26/02/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "PreferenceController.h"
+
+@interface PreferenceController ()
+
+@end
+
+@implementation PreferenceController
+
+- (id)initWithWindowNibName:(NSString *)windowNibName preambleController:(PreambleController *)pc{
+ if (!(self = [super initWithWindowNibName:windowNibName])) return nil;
+
+ preambleController = pc;
+
+ return self;
+}
+
+- (NSRect)newFrameForNewContentView:(NSView*)view {
+ NSWindow *window = [self window];
+ NSRect newFrameRect = [window frameRectForContentRect:[view frame]];
+ NSRect oldFrameRect = [window frame];
+ NSSize newSize = newFrameRect.size;
+ NSSize oldSize = oldFrameRect.size;
+
+ NSRect frame = [window frame];
+ frame.size = newSize;
+ frame.origin.y -= (newSize.height - oldSize.height);
+
+ return frame;
+}
+
+- (NSView *)viewForTag:(int)tag {
+
+ NSView *view = nil;
+ switch (tag) {
+ default:
+ case 0:
+ view = generalView;
+ break;
+ case 1:
+ view = engineView;
+ break;
+ case 2:
+ view = updateView;
+ break;
+ case 3:
+ view = preambleView;
+ break;
+ case 4:
+ view = customNodeView;
+ break;
+ }
+
+ return view;
+}
+
+- (BOOL)validateToolbarItem:(NSToolbarItem *)item {
+
+ if ([item tag] == currentViewTag) return NO;
+ else return YES;
+
+}
+
+- (void)awakeFromNib {
+
+ [[self window] setContentSize:[generalView frame].size];
+ [[[self window] contentView] addSubview:generalView];
+ [[[self window] contentView] setWantsLayer:YES];
+
+ updateController = [[UpdatePreferenceController alloc] initWithNibName:@"UpdatePreferencePanel" bundle:nil];
+ [[updateController view] setFrame:[updateView frame]];
+ [[[self window] contentView] replaceSubview:updateView with:[updateController view]];
+ updateView = [updateController view];
+
+ [[preambleController view] setFrame:[preambleView frame]];
+ [[[self window] contentView] replaceSubview:preambleView with:[preambleController view]];
+ preambleView = [preambleController view];
+
+ customNodeController = [[CustomNodeController alloc] initWithNibName:@"CustomNodes" bundle:nil];
+ [[customNodeController view] setFrame:[customNodeView frame]];
+ [[[self window] contentView] replaceSubview:customNodeView with:[customNodeController view]];
+ customNodeView = [customNodeController view];
+
+ [[self window] setContentSize:[engineView frame].size];
+ [[[self window] contentView] addSubview:engineView];
+ currentViewTag = 1;
+}
+
+- (IBAction)switchView:(id)sender {
+
+ int tag = [sender tag];
+ NSView *view = [self viewForTag:tag];
+ NSView *previousView = [self viewForTag:currentViewTag];
+ currentViewTag = tag;
+
+ NSRect newFrame = [self newFrameForNewContentView:view];
+
+ [NSAnimationContext beginGrouping];
+
+ if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
+ [[NSAnimationContext currentContext] setDuration:1.0];
+
+ [[[[self window] contentView] animator] replaceSubview:previousView with:view];
+ [[[self window] animator] setFrame:newFrame display:YES];
+
+ [NSAnimationContext endGrouping];
+
+}
+
+@end
diff --git a/tikzit-1/src/osx/Preferences.xib b/tikzit-1/src/osx/Preferences.xib
new file mode 100644
index 0000000..1be3f9f
--- /dev/null
+++ b/tikzit-1/src/osx/Preferences.xib
@@ -0,0 +1,1165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
+ <data>
+ <int key="IBDocument.SystemTarget">1070</int>
+ <string key="IBDocument.SystemVersion">13C64</string>
+ <string key="IBDocument.InterfaceBuilderVersion">5053</string>
+ <string key="IBDocument.AppKitVersion">1265.19</string>
+ <string key="IBDocument.HIToolboxVersion">697.40</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="NS.object.0">5053</string>
+ </object>
+ <array key="IBDocument.IntegratedClassDependencies">
+ <string>IBNSLayoutConstraint</string>
+ <string>NSButton</string>
+ <string>NSButtonCell</string>
+ <string>NSCustomObject</string>
+ <string>NSCustomView</string>
+ <string>NSTextField</string>
+ <string>NSTextFieldCell</string>
+ <string>NSToolbar</string>
+ <string>NSToolbarItem</string>
+ <string>NSUserDefaultsController</string>
+ <string>NSView</string>
+ <string>NSWindowTemplate</string>
+ </array>
+ <array key="IBDocument.PluginDependencies">
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </array>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+ <integer value="1" key="NS.object.0"/>
+ </object>
+ <array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <object class="NSCustomObject" id="1001">
+ <string key="NSClassName">PreferenceController</string>
+ </object>
+ <object class="NSCustomObject" id="1003">
+ <string key="NSClassName">FirstResponder</string>
+ </object>
+ <object class="NSCustomObject" id="1004">
+ <string key="NSClassName">NSApplication</string>
+ </object>
+ <object class="NSWindowTemplate" id="1005">
+ <int key="NSWindowStyleMask">7</int>
+ <int key="NSWindowBacking">2</int>
+ <string key="NSWindowRect">{{196, 240}, {480, 270}}</string>
+ <int key="NSWTFlags">544736256</int>
+ <string key="NSWindowTitle">Preferences</string>
+ <string key="NSWindowClass">NSWindow</string>
+ <object class="NSToolbar" key="NSViewClass" id="338765480">
+ <object class="NSMutableString" key="NSToolbarIdentifier">
+ <characters key="NS.bytes">C1747407-DC9A-4297-9C1C-0A5010984E6C</characters>
+ </object>
+ <nil key="NSToolbarDelegate"/>
+ <bool key="NSToolbarPrefersToBeShown">YES</bool>
+ <bool key="NSToolbarShowsBaselineSeparator">YES</bool>
+ <bool key="NSToolbarAllowsUserCustomization">NO</bool>
+ <bool key="NSToolbarAutosavesConfiguration">NO</bool>
+ <int key="NSToolbarDisplayMode">1</int>
+ <int key="NSToolbarSizeMode">1</int>
+ <dictionary class="NSMutableDictionary" key="NSToolbarIBIdentifiedItems">
+ <object class="NSToolbarItem" key="197F9408-AFB0-404B-B2B6-4DB1250B0A80" id="224936444">
+ <object class="NSMutableString" key="NSToolbarItemIdentifier">
+ <characters key="NS.bytes">197F9408-AFB0-404B-B2B6-4DB1250B0A80</characters>
+ </object>
+ <string key="NSToolbarItemLabel">Updates</string>
+ <string key="NSToolbarItemPaletteLabel">Updates</string>
+ <string key="NSToolbarItemToolTip"/>
+ <nil key="NSToolbarItemView"/>
+ <object class="NSCustomResource" key="NSToolbarItemImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">updates</string>
+ </object>
+ <nil key="NSToolbarItemTarget"/>
+ <nil key="NSToolbarItemAction"/>
+ <string key="NSToolbarItemMinSize">{0, 0}</string>
+ <string key="NSToolbarItemMaxSize">{0, 0}</string>
+ <bool key="NSToolbarItemEnabled">YES</bool>
+ <bool key="NSToolbarItemAutovalidates">YES</bool>
+ <int key="NSToolbarItemTag">2</int>
+ <bool key="NSToolbarIsUserRemovable">YES</bool>
+ <int key="NSToolbarItemVisibilityPriority">0</int>
+ </object>
+ <object class="NSToolbarItem" key="A3DDD070-5637-444B-92C6-905084CAC389" id="914743654">
+ <object class="NSMutableString" key="NSToolbarItemIdentifier">
+ <characters key="NS.bytes">A3DDD070-5637-444B-92C6-905084CAC389</characters>
+ </object>
+ <string key="NSToolbarItemLabel">General</string>
+ <string key="NSToolbarItemPaletteLabel">General</string>
+ <string key="NSToolbarItemToolTip"/>
+ <nil key="NSToolbarItemView"/>
+ <object class="NSCustomResource" key="NSToolbarItemImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSPreferencesGeneral</string>
+ </object>
+ <nil key="NSToolbarItemTarget"/>
+ <nil key="NSToolbarItemAction"/>
+ <string key="NSToolbarItemMinSize">{0, 0}</string>
+ <string key="NSToolbarItemMaxSize">{0, 0}</string>
+ <bool key="NSToolbarItemEnabled">YES</bool>
+ <bool key="NSToolbarItemAutovalidates">YES</bool>
+ <int key="NSToolbarItemTag">1</int>
+ <bool key="NSToolbarIsUserRemovable">YES</bool>
+ <int key="NSToolbarItemVisibilityPriority">0</int>
+ </object>
+ <object class="NSToolbarItem" key="A96DC4D4-2171-4D05-8C08-8D01B3829158" id="265637031">
+ <object class="NSMutableString" key="NSToolbarItemIdentifier">
+ <characters key="NS.bytes">A96DC4D4-2171-4D05-8C08-8D01B3829158</characters>
+ </object>
+ <string key="NSToolbarItemLabel">Preamble</string>
+ <string key="NSToolbarItemPaletteLabel">Preamble</string>
+ <string key="NSToolbarItemToolTip"/>
+ <nil key="NSToolbarItemView"/>
+ <object class="NSCustomResource" key="NSToolbarItemImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">preamble</string>
+ </object>
+ <nil key="NSToolbarItemTarget"/>
+ <nil key="NSToolbarItemAction"/>
+ <string key="NSToolbarItemMinSize">{0, 0}</string>
+ <string key="NSToolbarItemMaxSize">{0, 0}</string>
+ <bool key="NSToolbarItemEnabled">YES</bool>
+ <bool key="NSToolbarItemAutovalidates">YES</bool>
+ <int key="NSToolbarItemTag">3</int>
+ <bool key="NSToolbarIsUserRemovable">YES</bool>
+ <int key="NSToolbarItemVisibilityPriority">0</int>
+ </object>
+ <object class="NSToolbarItem" key="CBA2626C-DD4C-4ADD-BD5D-26D21216D9A8" id="845520355">
+ <object class="NSMutableString" key="NSToolbarItemIdentifier">
+ <characters key="NS.bytes">CBA2626C-DD4C-4ADD-BD5D-26D21216D9A8</characters>
+ </object>
+ <string key="NSToolbarItemLabel">Custom Nodes</string>
+ <string key="NSToolbarItemPaletteLabel">Custom Nodes</string>
+ <string key="NSToolbarItemToolTip"/>
+ <nil key="NSToolbarItemView"/>
+ <object class="NSCustomResource" key="NSToolbarItemImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">customshape</string>
+ </object>
+ <nil key="NSToolbarItemTarget"/>
+ <nil key="NSToolbarItemAction"/>
+ <string key="NSToolbarItemMinSize">{0, 0}</string>
+ <string key="NSToolbarItemMaxSize">{0, 0}</string>
+ <bool key="NSToolbarItemEnabled">YES</bool>
+ <bool key="NSToolbarItemAutovalidates">YES</bool>
+ <int key="NSToolbarItemTag">4</int>
+ <bool key="NSToolbarIsUserRemovable">YES</bool>
+ <int key="NSToolbarItemVisibilityPriority">0</int>
+ </object>
+ <object class="NSToolbarItem" key="F85FE7C2-9847-4E58-8BF6-BE334E918CA7" id="641338426">
+ <object class="NSMutableString" key="NSToolbarItemIdentifier">
+ <characters key="NS.bytes">F85FE7C2-9847-4E58-8BF6-BE334E918CA7</characters>
+ </object>
+ <string key="NSToolbarItemLabel">Engine</string>
+ <string key="NSToolbarItemPaletteLabel">Engine</string>
+ <string key="NSToolbarItemToolTip"/>
+ <nil key="NSToolbarItemView"/>
+ <object class="NSCustomResource" key="NSToolbarItemImage">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">engine</string>
+ </object>
+ <nil key="NSToolbarItemTarget"/>
+ <nil key="NSToolbarItemAction"/>
+ <string key="NSToolbarItemMinSize">{0, 0}</string>
+ <string key="NSToolbarItemMaxSize">{0, 0}</string>
+ <bool key="NSToolbarItemEnabled">YES</bool>
+ <bool key="NSToolbarItemAutovalidates">YES</bool>
+ <int key="NSToolbarItemTag">1</int>
+ <bool key="NSToolbarIsUserRemovable">YES</bool>
+ <int key="NSToolbarItemVisibilityPriority">0</int>
+ </object>
+ </dictionary>
+ <array class="NSMutableArray" key="NSToolbarIBAllowedItems">
+ <reference ref="914743654"/>
+ <reference ref="224936444"/>
+ <reference ref="641338426"/>
+ <reference ref="265637031"/>
+ <reference ref="845520355"/>
+ </array>
+ <array key="NSToolbarIBDefaultItems">
+ <reference ref="914743654"/>
+ <reference ref="265637031"/>
+ <reference ref="845520355"/>
+ <reference ref="224936444"/>
+ </array>
+ <array key="NSToolbarIBSelectableItems" id="0"/>
+ </object>
+ <nil key="NSUserInterfaceItemIdentifier"/>
+ <object class="NSView" key="NSWindowView" id="1006">
+ <reference key="NSNextResponder"/>
+ <string key="NSFrameSize">{480, 270}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ </object>
+ <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+ <string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+ <bool key="NSWindowIsRestorable">YES</bool>
+ </object>
+ <object class="NSCustomView" id="103531975">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">268</int>
+ <array class="NSMutableArray" key="NSSubviews">
+ <object class="NSButton" id="521024449">
+ <reference key="NSNextResponder" ref="103531975"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{18, 106}, {219, 18}}</string>
+ <reference key="NSSuperview" ref="103531975"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="550678479">
+ <int key="NSCellFlags">-2080374784</int>
+ <int key="NSCellFlags2">268435456</int>
+ <string key="NSContents">Keep inspector windows on top</string>
+ <object class="NSFont" key="NSSupport" id="924461577">
+ <string key="NSName">.LucidaGrandeUI</string>
+ <double key="NSSize">13</double>
+ <int key="NSfFlags">1044</int>
+ </object>
+ <string key="NSCellIdentifier">_NS:9</string>
+ <reference key="NSControlView" ref="521024449"/>
+ <int key="NSButtonFlags">1211912448</int>
+ <int key="NSButtonFlags2">2</int>
+ <object class="NSCustomResource" key="NSNormalImage" id="959728078">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">NSSwitch</string>
+ </object>
+ <object class="NSButtonImageSource" key="NSAlternateImage" id="808033943">
+ <string key="NSImageName">NSSwitch</string>
+ </object>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ <object class="NSButton" id="118735803">
+ <reference key="NSNextResponder" ref="103531975"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{18, 126}, {168, 18}}</string>
+ <reference key="NSSuperview" ref="103531975"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="521024449"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="63691474">
+ <int key="NSCellFlags">-2080374784</int>
+ <int key="NSCellFlags2">268435456</int>
+ <string key="NSContents">Autocomplete brackets</string>
+ <reference key="NSSupport" ref="924461577"/>
+ <string key="NSCellIdentifier">_NS:9</string>
+ <reference key="NSControlView" ref="118735803"/>
+ <int key="NSButtonFlags">1211912448</int>
+ <int key="NSButtonFlags2">2</int>
+ <reference key="NSNormalImage" ref="959728078"/>
+ <reference key="NSAlternateImage" ref="808033943"/>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ <object class="NSButton" id="764495169">
+ <reference key="NSNextResponder" ref="103531975"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{18, 18}, {214, 18}}</string>
+ <reference key="NSSuperview" ref="103531975"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="292348615">
+ <int key="NSCellFlags">-2080374784</int>
+ <int key="NSCellFlags2">268435456</int>
+ <string key="NSContents">Bring preview window to focus</string>
+ <reference key="NSSupport" ref="924461577"/>
+ <string key="NSCellIdentifier">_NS:9</string>
+ <reference key="NSControlView" ref="764495169"/>
+ <int key="NSButtonFlags">1211912448</int>
+ <int key="NSButtonFlags2">2</int>
+ <reference key="NSNormalImage" ref="959728078"/>
+ <reference key="NSAlternateImage" ref="808033943"/>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ </object>
+ <object class="NSTextField" id="762565485">
+ <reference key="NSNextResponder" ref="103531975"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{20, 42}, {440, 22}}</string>
+ <reference key="NSSuperview" ref="103531975"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="764495169"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="186397132">
+ <int key="NSCellFlags">-1804599231</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents"/>
+ <reference key="NSSupport" ref="924461577"/>
+ <string key="NSCellIdentifier">_NS:9</string>
+ <reference key="NSControlView" ref="762565485"/>
+ <bool key="NSDrawsBackground">YES</bool>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textBackgroundColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MQA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">textColor</string>
+ <object class="NSColor" key="NSColor" id="433834218">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MAA</bytes>
+ </object>
+ </object>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ <int key="NSTextFieldAlignmentRectInsetsVersion">1</int>
+ </object>
+ <object class="NSTextField" id="539123669">
+ <reference key="NSNextResponder" ref="103531975"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{18, 72}, {140, 17}}</string>
+ <reference key="NSSuperview" ref="103531975"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="762565485"/>
+ <string key="NSReuseIdentifierKey">_NS:1535</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSTextFieldCell" key="NSCell" id="459248896">
+ <int key="NSCellFlags">68157504</int>
+ <int key="NSCellFlags2">272630784</int>
+ <string key="NSContents">pdfLaTeX source path</string>
+ <reference key="NSSupport" ref="924461577"/>
+ <string key="NSCellIdentifier">_NS:1535</string>
+ <reference key="NSControlView" ref="539123669"/>
+ <object class="NSColor" key="NSBackgroundColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlColor</string>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+ </object>
+ </object>
+ <object class="NSColor" key="NSTextColor">
+ <int key="NSColorSpace">6</int>
+ <string key="NSCatalogName">System</string>
+ <string key="NSColorName">controlTextColor</string>
+ <reference key="NSColor" ref="433834218"/>
+ </object>
+ </object>
+ <bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+ <int key="NSTextFieldAlignmentRectInsetsVersion">1</int>
+ </object>
+ </array>
+ <string key="NSFrameSize">{480, 162}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView" ref="118735803"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <string key="NSClassName">NSView</string>
+ </object>
+ <object class="NSCustomView" id="596032684">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">268</int>
+ <array class="NSMutableArray" key="NSSubviews"/>
+ <string key="NSFrameSize">{480, 96}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <string key="NSClassName">NSView</string>
+ </object>
+ <object class="NSCustomView" id="169128791">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">12</int>
+ <array class="NSMutableArray" key="NSSubviews"/>
+ <string key="NSFrameSize">{480, 115}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <string key="NSClassName">NSView</string>
+ </object>
+ <object class="NSCustomView" id="812696929">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">12</int>
+ <array class="NSMutableArray" key="NSSubviews"/>
+ <string key="NSFrameSize">{557, 354}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <string key="NSClassName">NSView</string>
+ </object>
+ <object class="NSCustomView" id="443314002">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">12</int>
+ <array class="NSMutableArray" key="NSSubviews"/>
+ <string key="NSFrameSize">{557, 354}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <reference key="NSNextKeyView"/>
+ <string key="NSReuseIdentifierKey">_NS:9</string>
+ <string key="NSClassName">NSView</string>
+ </object>
+ <object class="NSUserDefaultsController" id="706090457">
+ <bool key="NSSharedInstance">YES</bool>
+ </object>
+ </array>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <array class="NSMutableArray" key="connectionRecords">
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">window</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="1005"/>
+ </object>
+ <int key="connectionID">3</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">engineView</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="103531975"/>
+ </object>
+ <int key="connectionID">23</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">generalView</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="596032684"/>
+ </object>
+ <int key="connectionID">25</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">switchView:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="914743654"/>
+ </object>
+ <int key="connectionID">26</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">switchView:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="641338426"/>
+ </object>
+ <int key="connectionID">27</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">switchView:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="224936444"/>
+ </object>
+ <int key="connectionID">116</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">updateView</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="169128791"/>
+ </object>
+ <int key="connectionID">117</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">switchView:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="265637031"/>
+ </object>
+ <int key="connectionID">120</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">preambleView</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="812696929"/>
+ </object>
+ <int key="connectionID">121</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">customNodeView</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="443314002"/>
+ </object>
+ <int key="connectionID">123</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">switchView:</string>
+ <reference key="source" ref="1001"/>
+ <reference key="destination" ref="845520355"/>
+ </object>
+ <int key="connectionID">125</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="1005"/>
+ <reference key="destination" ref="1001"/>
+ </object>
+ <int key="connectionID">4</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: values.net.sourceforge.tikzit.pdflatexpath</string>
+ <reference key="source" ref="186397132"/>
+ <reference key="destination" ref="706090457"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="186397132"/>
+ <reference key="NSDestination" ref="706090457"/>
+ <string key="NSLabel">value: values.net.sourceforge.tikzit.pdflatexpath</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">values.net.sourceforge.tikzit.pdflatexpath</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">54</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: values.net.sourceforge.tikzit.previewfocus</string>
+ <reference key="source" ref="292348615"/>
+ <reference key="destination" ref="706090457"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="292348615"/>
+ <reference key="NSDestination" ref="706090457"/>
+ <string key="NSLabel">value: values.net.sourceforge.tikzit.previewfocus</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">values.net.sourceforge.tikzit.previewfocus</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">62</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: values.net.sourceforge.tikzit.autocomplete</string>
+ <reference key="source" ref="118735803"/>
+ <reference key="destination" ref="706090457"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="118735803"/>
+ <reference key="NSDestination" ref="706090457"/>
+ <string key="NSLabel">value: values.net.sourceforge.tikzit.autocomplete</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">values.net.sourceforge.tikzit.autocomplete</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">149</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBBindingConnection" key="connection">
+ <string key="label">value: values.net.sourceforge.tikzit.inspectorsontop</string>
+ <reference key="source" ref="521024449"/>
+ <reference key="destination" ref="706090457"/>
+ <object class="NSNibBindingConnector" key="connector">
+ <reference key="NSSource" ref="521024449"/>
+ <reference key="NSDestination" ref="706090457"/>
+ <string key="NSLabel">value: values.net.sourceforge.tikzit.inspectorsontop</string>
+ <string key="NSBinding">value</string>
+ <string key="NSKeyPath">values.net.sourceforge.tikzit.inspectorsontop</string>
+ <int key="NSNibBindingConnectorVersion">2</int>
+ </object>
+ </object>
+ <int key="connectionID">150</int>
+ </object>
+ </array>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <array key="orderedObjects">
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="1001"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="1003"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">First Responder</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-3</int>
+ <reference key="object" ref="1004"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">Application</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">1</int>
+ <reference key="object" ref="1005"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="1006"/>
+ <reference ref="338765480"/>
+ </array>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">2</int>
+ <reference key="object" ref="1006"/>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5</int>
+ <reference key="object" ref="338765480"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="641338426"/>
+ <reference ref="914743654"/>
+ <reference ref="224936444"/>
+ <reference ref="265637031"/>
+ <reference ref="845520355"/>
+ </array>
+ <reference key="parent" ref="1005"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">11</int>
+ <reference key="object" ref="641338426"/>
+ <reference key="parent" ref="338765480"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">12</int>
+ <reference key="object" ref="914743654"/>
+ <reference key="parent" ref="338765480"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">13</int>
+ <reference key="object" ref="103531975"/>
+ <array class="NSMutableArray" key="children">
+ <object class="IBNSLayoutConstraint" id="727314944">
+ <reference key="firstItem" ref="103531975"/>
+ <int key="firstAttribute">4</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="764495169"/>
+ <int key="secondAttribute">4</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">8</int>
+ <float key="scoringTypeFloat">23</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="728277728">
+ <reference key="firstItem" ref="764495169"/>
+ <int key="firstAttribute">3</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="762565485"/>
+ <int key="secondAttribute">4</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">8</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">6</int>
+ <float key="scoringTypeFloat">24</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="116293249">
+ <reference key="firstItem" ref="764495169"/>
+ <int key="firstAttribute">5</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="103531975"/>
+ <int key="secondAttribute">5</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">0</int>
+ <float key="scoringTypeFloat">29</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="206376115">
+ <reference key="firstItem" ref="103531975"/>
+ <int key="firstAttribute">6</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="762565485"/>
+ <int key="secondAttribute">6</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">0</int>
+ <float key="scoringTypeFloat">29</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="921593038">
+ <reference key="firstItem" ref="762565485"/>
+ <int key="firstAttribute">3</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="539123669"/>
+ <int key="secondAttribute">4</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">8</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">6</int>
+ <float key="scoringTypeFloat">24</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="783720041">
+ <reference key="firstItem" ref="762565485"/>
+ <int key="firstAttribute">5</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="103531975"/>
+ <int key="secondAttribute">5</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">0</int>
+ <float key="scoringTypeFloat">29</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="559306534">
+ <reference key="firstItem" ref="539123669"/>
+ <int key="firstAttribute">5</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="103531975"/>
+ <int key="secondAttribute">5</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">0</int>
+ <float key="scoringTypeFloat">29</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="852545348">
+ <reference key="firstItem" ref="521024449"/>
+ <int key="firstAttribute">5</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="539123669"/>
+ <int key="secondAttribute">5</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBLayoutConstant" key="constant">
+ <double key="value">0.0</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">6</int>
+ <float key="scoringTypeFloat">24</float>
+ <int key="contentType">2</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="750010708">
+ <reference key="firstItem" ref="521024449"/>
+ <int key="firstAttribute">3</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="118735803"/>
+ <int key="secondAttribute">4</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">6</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">6</int>
+ <float key="scoringTypeFloat">24</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="295298081">
+ <reference key="firstItem" ref="521024449"/>
+ <int key="firstAttribute">5</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="118735803"/>
+ <int key="secondAttribute">5</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBLayoutConstant" key="constant">
+ <double key="value">0.0</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">6</int>
+ <float key="scoringTypeFloat">24</float>
+ <int key="contentType">2</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <object class="IBNSLayoutConstraint" id="956205451">
+ <reference key="firstItem" ref="118735803"/>
+ <int key="firstAttribute">3</int>
+ <int key="relation">0</int>
+ <reference key="secondItem" ref="103531975"/>
+ <int key="secondAttribute">3</int>
+ <float key="multiplier">1</float>
+ <string key="multiplierString">1</string>
+ <object class="IBNSLayoutSymbolicConstant" key="constant">
+ <double key="value">20</double>
+ </object>
+ <float key="priority">1000</float>
+ <reference key="containingView" ref="103531975"/>
+ <int key="scoringType">8</int>
+ <float key="scoringTypeFloat">23</float>
+ <int key="contentType">3</int>
+ <bool key="placeholder">NO</bool>
+ </object>
+ <reference ref="539123669"/>
+ <reference ref="762565485"/>
+ <reference ref="764495169"/>
+ <reference ref="118735803"/>
+ <reference ref="521024449"/>
+ </array>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">14</int>
+ <reference key="object" ref="596032684"/>
+ <array class="NSMutableArray" key="children"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">15</int>
+ <reference key="object" ref="539123669"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="459248896"/>
+ </array>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">16</int>
+ <reference key="object" ref="459248896"/>
+ <reference key="parent" ref="539123669"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">30</int>
+ <reference key="object" ref="559306534"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">32</int>
+ <reference key="object" ref="762565485"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="186397132"/>
+ </array>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">33</int>
+ <reference key="object" ref="186397132"/>
+ <reference key="parent" ref="762565485"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">36</int>
+ <reference key="object" ref="783720041"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">39</int>
+ <reference key="object" ref="706090457"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">55</int>
+ <reference key="object" ref="921593038"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">56</int>
+ <reference key="object" ref="206376115"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">57</int>
+ <reference key="object" ref="764495169"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="292348615"/>
+ </array>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">58</int>
+ <reference key="object" ref="292348615"/>
+ <reference key="parent" ref="764495169"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">59</int>
+ <reference key="object" ref="116293249"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">60</int>
+ <reference key="object" ref="728277728"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">64</int>
+ <reference key="object" ref="169128791"/>
+ <array class="NSMutableArray" key="children"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">115</int>
+ <reference key="object" ref="224936444"/>
+ <reference key="parent" ref="338765480"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">118</int>
+ <reference key="object" ref="812696929"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">119</int>
+ <reference key="object" ref="265637031"/>
+ <reference key="parent" ref="338765480"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">122</int>
+ <reference key="object" ref="443314002"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">124</int>
+ <reference key="object" ref="845520355"/>
+ <reference key="parent" ref="338765480"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">126</int>
+ <reference key="object" ref="727314944"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">127</int>
+ <reference key="object" ref="118735803"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="63691474"/>
+ </array>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">128</int>
+ <reference key="object" ref="63691474"/>
+ <reference key="parent" ref="118735803"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">130</int>
+ <reference key="object" ref="956205451"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">131</int>
+ <reference key="object" ref="521024449"/>
+ <array class="NSMutableArray" key="children">
+ <reference ref="550678479"/>
+ </array>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">132</int>
+ <reference key="object" ref="550678479"/>
+ <reference key="parent" ref="521024449"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">134</int>
+ <reference key="object" ref="295298081"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">135</int>
+ <reference key="object" ref="750010708"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">153</int>
+ <reference key="object" ref="852545348"/>
+ <reference key="parent" ref="103531975"/>
+ </object>
+ </array>
+ </object>
+ <dictionary class="NSMutableDictionary" key="flattenedProperties">
+ <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="1.IBWindowTemplateEditedContentRect">{{357, 418}, {480, 270}}</string>
+ <boolean value="NO" key="1.NSWindowTemplate.visibleAtLaunch"/>
+ <string key="11.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="115.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="118.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="119.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="12.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="122.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="124.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="126.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="127.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+ <string key="127.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="128.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <array key="13.IBNSViewMetadataConstraints">
+ <reference ref="956205451"/>
+ <reference ref="295298081"/>
+ <reference ref="750010708"/>
+ <reference ref="852545348"/>
+ <reference ref="559306534"/>
+ <reference ref="783720041"/>
+ <reference ref="921593038"/>
+ <reference ref="206376115"/>
+ <reference ref="116293249"/>
+ <reference ref="728277728"/>
+ <reference ref="727314944"/>
+ </array>
+ <string key="13.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="130.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="131.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+ <string key="131.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="132.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="134.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="135.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="14.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="15.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+ <string key="15.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="153.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="16.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="30.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="32.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+ <string key="32.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="33.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="36.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="39.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="55.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="56.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <boolean value="NO" key="57.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
+ <string key="57.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="59.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="60.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string key="64.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
+ </dictionary>
+ <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
+ <nil key="activeLocalization"/>
+ <dictionary class="NSMutableDictionary" key="localizations"/>
+ <nil key="sourceID"/>
+ <int key="maxID">153</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <array class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <object class="IBPartialClassDescription">
+ <string key="className">PreferenceController</string>
+ <string key="superclassName">NSWindowController</string>
+ <object class="NSMutableDictionary" key="actions">
+ <string key="NS.key.0">switchView:</string>
+ <string key="NS.object.0">id</string>
+ </object>
+ <object class="NSMutableDictionary" key="actionInfosByName">
+ <string key="NS.key.0">switchView:</string>
+ <object class="IBActionInfo" key="NS.object.0">
+ <string key="name">switchView:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ </object>
+ <dictionary class="NSMutableDictionary" key="outlets">
+ <string key="customNodeView">NSView</string>
+ <string key="engineView">NSView</string>
+ <string key="generalView">NSView</string>
+ <string key="preambleView">NSView</string>
+ <string key="updateView">NSView</string>
+ </dictionary>
+ <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <object class="IBToOneOutletInfo" key="customNodeView">
+ <string key="name">customNodeView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="engineView">
+ <string key="name">engineView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="generalView">
+ <string key="name">generalView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="preambleView">
+ <string key="name">preambleView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo" key="updateView">
+ <string key="name">updateView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ </dictionary>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/PreferenceController.h</string>
+ </object>
+ </object>
+ </array>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+ <bool key="IBDocument.previouslyAttemptedUpgradeToXcode5">YES</bool>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string>
+ <real value="1070" key="NS.object.0"/>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+ <integer value="4600" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <dictionary class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+ <string key="NSPreferencesGeneral">{32, 32}</string>
+ <string key="NSSwitch">{15, 15}</string>
+ <string key="customshape">{32, 32}</string>
+ <string key="engine">{32, 32}</string>
+ <string key="preamble">{32, 32}</string>
+ <string key="updates">{32, 32}</string>
+ </dictionary>
+ <bool key="IBDocument.UseAutolayout">YES</bool>
+ </data>
+</archive>
diff --git a/tikzit-1/src/osx/PreviewController.h b/tikzit-1/src/osx/PreviewController.h
new file mode 100644
index 0000000..6c51a23
--- /dev/null
+++ b/tikzit-1/src/osx/PreviewController.h
@@ -0,0 +1,52 @@
+//
+// PreviewController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+
+#import <Cocoa/Cocoa.h>
+#import "DraggablePDFView.h"
+
+@class PDFView;
+@class PreambleController;
+
+@interface PreviewController : NSWindowController {
+ IBOutlet DraggablePDFView *pdfView;
+ IBOutlet NSProgressIndicator *progressIndicator;
+ IBOutlet NSScrollView *errorTextView;
+ IBOutlet NSTextView *errorText;
+ PreambleController *preambleController;
+ NSString *tempDir;
+ NSLock *latexLock;
+ int typesetCount;
+}
+
+
+- (id)initWithWindowNibName:(NSString*)nib
+ preambleController:(PreambleController*)pc
+ tempDir:(NSString*)dir;
+
+- (void)buildTikz:(NSString*)tikz;
+
++ (void)setDefaultPreviewController:(PreviewController*)pc;
++ (PreviewController*)defaultPreviewController;
+
+@end
diff --git a/tikzit-1/src/osx/PreviewController.m b/tikzit-1/src/osx/PreviewController.m
new file mode 100644
index 0000000..cf069b1
--- /dev/null
+++ b/tikzit-1/src/osx/PreviewController.m
@@ -0,0 +1,147 @@
+//
+// PreviewController.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "PreviewController.h"
+#import "AppDelegate.h"
+#import "PreambleController.h"
+#import <Quartz/Quartz.h>
+
+@implementation PreviewController
+
+static PreviewController *preview = nil;
+
+- (id)initWithWindowNibName:(NSString*)nib
+ preambleController:(PreambleController*)pc
+ tempDir:(NSString*)dir {
+ if (!(self = [super initWithWindowNibName:nib])) return nil;
+ tempDir = [dir copy];
+ typesetCount = 0;
+ preambleController = pc;
+ latexLock = [[NSLock alloc] init];
+ return self;
+}
+
+- (void)runLatex:(id)tikz {
+ // Only build one tex file at a time, so we don't get funky results.
+ //[latexLock lock];
+ [progressIndicator startAnimation:self];
+
+ if([[NSUserDefaults standardUserDefaults] boolForKey:@"net.sourceforge.tikzit.previewfocus"]){
+ [[preview window] makeKeyAndOrderFront:self];
+ }
+
+ int fnum = typesetCount++;
+
+ NSString *tex = [preambleController buildDocumentForTikz:tikz];
+
+ NSString *texFile = [NSString stringWithFormat:@"%@/tikzit_%d.tex", tempDir, fnum];
+ NSString *pdfFile = [NSString stringWithFormat:@"%@/tikzit_%d.pdf", tempDir, fnum];
+
+ [tex writeToFile:texFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
+
+ NSString *pdflatexPath = [[NSUserDefaults standardUserDefaults] stringForKey:@"net.sourceforge.tikzit.pdflatexpath"];
+
+ // We run pdflatex in a bash shell to have easy access to the setup from unix-land
+ NSTask *latexTask = [[NSTask alloc] init];
+ [latexTask setCurrentDirectoryPath:tempDir];
+ [latexTask setLaunchPath:@"/bin/bash"];
+
+ // This assumes the user has $PATH set up to find pdflatex in either .profile
+ // or .bashrc. This should be improved to take other path setups into account
+ // and to be customisable.
+ NSString *latexCmd =
+ [NSString stringWithFormat:
+ @"if [ -e ~/.profile ]; then source ~/.profile; fi\n"
+ @"if [ -e ~/.bashrc ]; then source ~/.bashrc; fi\n"
+ @"%@ -interaction=nonstopmode -output-format=pdf -halt-on-error '%@'\n", pdflatexPath, texFile];
+
+ NSLog(@"Telling bash: %@", latexCmd);
+
+ NSPipe *pout = [NSPipe pipe];
+ NSPipe *pin = [NSPipe pipe];
+ [latexTask setStandardOutput:pout];
+ [latexTask setStandardInput:pin];
+
+ NSFileHandle *latexIn = [pin fileHandleForWriting];
+ NSFileHandle *latexOut = [pout fileHandleForReading];
+
+ [latexTask launch];
+ [latexIn writeData:[latexCmd dataUsingEncoding:NSUTF8StringEncoding]];
+ [latexIn closeFile];
+
+
+ NSData *data = [latexOut readDataToEndOfFile];
+ NSString *str = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+
+ [latexTask waitUntilExit];
+ if ([latexTask terminationStatus] != 0) {
+ if ([latexTask terminationStatus] == 127) {
+ [errorTextView setHidden:YES];
+ [errorText setString:@"\nCouldn't find pdflatex, change settings and try again."];
+ [errorTextView setHidden:NO];
+ }else{
+ [errorTextView setHidden:YES];
+ [errorText setString:[@"\nAN ERROR HAS OCCURRED, PDFLATEX SAID:\n\n" stringByAppendingString:str]];
+ [errorTextView setHidden:NO];
+ }
+ } else {
+ [errorText setString:@""];
+ [errorTextView setHidden:YES];
+
+ PDFDocument *doc = [[PDFDocument alloc] initWithURL:[[NSURL alloc] initFileURLWithPath:pdfFile]];
+
+ // pad the PDF by a couple of pixels
+ if ([doc pageCount] >= 1) {
+ PDFPage *page = [doc pageAtIndex:0];
+ NSRect box = [page boundsForBox:kPDFDisplayBoxCropBox];
+ box.origin.x -= 2.0f;
+ box.origin.y -= 2.0f;
+ box.size.width += 4.0f;
+ box.size.height += 4.0f;
+ [page setBounds:box forBox:kPDFDisplayBoxCropBox];
+ [page setBounds:box forBox:kPDFDisplayBoxMediaBox];
+ }
+
+ [pdfView setDocument:doc];
+ }
+
+ [progressIndicator stopAnimation:self];
+ //[latexLock unlock];
+}
+
+- (void)buildTikz:(NSString*)tikz {
+ // Build on a separate thread to keep the interface responsive.
+ [NSThread detachNewThreadSelector:@selector(runLatex:) toTarget:self withObject:tikz];
+}
+
++ (void)setDefaultPreviewController:(PreviewController*)pc {
+ preview = pc;
+}
+
++ (PreviewController*)defaultPreviewController {
+ return preview;
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/PropertyInspectorController.h b/tikzit-1/src/osx/PropertyInspectorController.h
new file mode 100644
index 0000000..663ee4a
--- /dev/null
+++ b/tikzit-1/src/osx/PropertyInspectorController.h
@@ -0,0 +1,83 @@
+//
+// PropertyInspectorController.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 17/07/2011.
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "NodeStyle.h"
+#import "GraphElementData.h"
+
+@class SFBInspectorView;
+@class StylePaletteController;
+
+@interface PropertyInspectorController : NSWindowController {
+ IBOutlet SFBInspectorView *propertyInspectorView;
+ IBOutlet NSView *nodePropertiesView;
+ IBOutlet NSView *graphPropertiesView;
+ IBOutlet NSView *edgePropertiesView;
+ IBOutlet NSComboBox *sourceAnchorComboBox;
+ IBOutlet NSComboBox *targetAnchorComboBox;
+ IBOutlet NSTextField *edgeNodeLabelField;
+ IBOutlet NSButton *edgeNodeCheckbox;
+ IBOutlet NSArrayController *nodeDataArrayController;
+ IBOutlet NSArrayController *graphDataArrayController;
+ IBOutlet NSArrayController *edgeDataArrayController;
+ IBOutlet NSArrayController *edgeNodeDataArrayController;
+
+ NSMutableArray *sourceAnchorNames;
+ IBOutlet NSArrayController *sourceAnchorNamesArrayController;
+
+ NSMutableArray *targetAnchorNames;
+ IBOutlet NSArrayController *targetAnchorNamesArrayController;
+
+ NSMutableArray *selectedNodes;
+ IBOutlet NSArrayController *selectedNodesArrayController;
+
+ NSMutableArray *selectedEdges;
+ IBOutlet NSArrayController *selectedEdgesArrayController;
+
+ // this data lists exists solely for displaying messages in disabled data tables
+ GraphElementData *noSelection;
+ GraphElementData *multipleSelection;
+ GraphElementData *noEdgeNode;
+ GraphElementData *noGraph;
+
+
+ // used to get access to the global style table
+ StylePaletteController *stylePaletteController;
+}
+
+//@property (readonly) BOOL enableNodeDataControls;
+//@property (readonly) BOOL enableEdgeDataControls;
+@property (strong) NSMutableArray *selectedNodes;
+@property (strong) NSMutableArray *selectedEdges;
+@property (strong) NSMutableArray *sourceAnchorNames;
+@property (strong) NSMutableArray *targetAnchorNames;
+@property (strong) StylePaletteController *stylePaletteController;
+
+- (id)initWithWindowNibName:(NSString *)windowNibName;
+- (void)graphSelectionChanged:(NSNotification*)notification;
+
+- (IBAction)addNodeProperty:(id)sender;
+- (IBAction)addNodeAtom:(id)sender;
+- (IBAction)removeNodeProperty:(id)sender;
+
+- (IBAction)addGraphProperty:(id)sender;
+- (IBAction)addGraphAtom:(id)sender;
+- (IBAction)removeGraphProperty:(id)sender;
+
+- (IBAction)addEdgeProperty:(id)sender;
+- (IBAction)addEdgeAtom:(id)sender;
+- (IBAction)removeEdgeProperty:(id)sender;
+
+- (IBAction)addEdgeNodeProperty:(id)sender;
+- (IBAction)addEdgeNodeAtom:(id)sender;
+- (IBAction)removeEdgeNodeProperty:(id)sender;
+
+//- (IBAction)addRemoveChildNode:(id)sender;
+- (IBAction)refreshDocument:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/PropertyInspectorController.m b/tikzit-1/src/osx/PropertyInspectorController.m
new file mode 100644
index 0000000..039a30f
--- /dev/null
+++ b/tikzit-1/src/osx/PropertyInspectorController.m
@@ -0,0 +1,280 @@
+//
+// PropertyInspectorController.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 17/07/2011.
+// Copyright 2011 Aleks Kissinger. All rights reserved.
+//
+
+#import "PropertyInspectorController.h"
+#import "StylePaletteController.h"
+#import "TikzDocument.h"
+#import "SFBInspectors/SFBInspectorView.h"
+#import "PickSupport.h"
+#import "Node.h"
+#import "Edge.h"
+#import "NodeStyle.h"
+#import "GraphicsView.h"
+#import "GraphElementProperty.h"
+#import "Shape.h"
+
+@implementation PropertyInspectorController
+
+@synthesize stylePaletteController;
+@synthesize selectedNodes, selectedEdges;
+@synthesize sourceAnchorNames, targetAnchorNames;
+
+- (id)initWithWindowNibName:(NSString *)windowNibName {
+ if (!(self = [super initWithWindowNibName:windowNibName])) return nil;
+
+ noSelection = [[GraphElementData alloc] init];
+ [noSelection setProperty:@"" forKey:@"No Selection"];
+ multipleSelection = [[GraphElementData alloc] init];
+ [multipleSelection setProperty:@"" forKey:@"Mult. Selection"];
+ noEdgeNode = [[GraphElementData alloc] init];
+ [noEdgeNode setProperty:@"" forKey:@"No Child"];
+ noGraph = [[GraphElementData alloc] init];
+ [noGraph setProperty:@"" forKey:@"No Graph"];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(graphSelectionChanged:)
+ name:@"SelectionChanged"
+ object:nil];
+
+// [[NSDocumentController sharedDocumentController] addObserver:self
+// forKeyPath:@"currentDocument"
+// options:NSKeyValueObservingOptionNew
+// context:NULL];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(graphSelectionChanged:)
+ name:@"NSWindowDidBecomeMainNotification"
+ object:nil];
+
+ [self setSourceAnchorNames: [[NSMutableArray alloc] initWithArray: [@"north south west east" componentsSeparatedByString:@" "]]];
+
+ [self setTargetAnchorNames: [[NSMutableArray alloc] initWithArray:[@"north south west east" componentsSeparatedByString:@" "]]];
+
+
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"net.sourceforge.tikzit.inspectorsontop"] == YES) {
+ [[self window] setLevel:NSFloatingWindowLevel];
+ } else {
+ [[self window] setLevel:NSNormalWindowLevel];
+ }
+
+ [self showWindow:self];
+ return self;
+}
+
+- (void)observeValueForKeyPath:(NSString*)keyPath
+ ofObject:(id)object
+ change:(NSDictionary*)change
+ context:(void*)context {
+ [self graphSelectionChanged:nil];
+}
+
+//- (void)willChangeValueForKey:(NSString *)key {
+// [super willChangeValueForKey:key];
+// NSLog(@"will: %@",key);
+//}
+//
+//- (void)didChangeValueForKey:(NSString *)key {
+// [super didChangeValueForKey:key];
+// NSLog(@"did: %@",key);
+//}
+
+- (void)windowDidLoad {
+ [[self window] setMovableByWindowBackground:YES];
+
+ [propertyInspectorView addInspectorPane:graphPropertiesView
+ title:@"Graph Properties"];
+ [propertyInspectorView addInspectorPane:nodePropertiesView
+ title:@"Node Properties"];
+ [propertyInspectorView addInspectorPane:edgePropertiesView
+ title:@"Edge Properties"];
+ [super windowDidLoad];
+}
+
+- (IBAction)refreshDocument:(id)sender {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ [[doc graphicsView] postGraphChange];
+ [[doc graphicsView] refreshLayers];
+ }
+}
+
+
+- (void)updateGraphFields {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ [graphDataArrayController setContent:[[[doc graphicsView] graph] data]];
+ [graphDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [graphDataArrayController setEditable:YES];
+ } else {
+ [graphDataArrayController setContent:noGraph];
+ [graphDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [graphDataArrayController setEditable:NO];
+ }
+}
+
+- (void)updateNodeFields {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+ if (doc != nil) {
+ NSSet *sel = [[[doc graphicsView] pickSupport] selectedNodes];
+ [self setSelectedNodes:[[sel allObjects] mutableCopy]];
+ [selectedNodesArrayController setSelectedObjects:selectedNodes];
+ if ([sel count] == 1) {
+ Node *n = [sel anyObject];
+ [nodeDataArrayController setContent:[n data]];
+ [nodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [nodeDataArrayController setEditable:YES];
+ } else if ([sel count] == 0) {
+ [nodeDataArrayController setContent:noSelection];
+ [nodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [nodeDataArrayController setEditable:NO];
+ } else {
+ [nodeDataArrayController setContent:multipleSelection];
+ [nodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [nodeDataArrayController setEditable:NO];
+ }
+ } else {
+ [nodeDataArrayController setContent:noGraph];
+ [nodeDataArrayController setEditable:NO];
+ }
+}
+
+- (void)updateEdgeFields {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ NSSet *sel = [[[doc graphicsView] pickSupport] selectedEdges];
+ [self setSelectedEdges:[[sel allObjects] mutableCopy]];
+ [selectedEdgesArrayController setSelectedObjects:selectedEdges];
+ if ([sel count] == 1) {
+ Edge *e = [sel anyObject];
+ [edgeDataArrayController setContent:[e data]];
+ [edgeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeDataArrayController setEditable:YES];
+ if ([e hasEdgeNode]) {
+ Node *n = [e edgeNode];
+ [edgeNodeDataArrayController setContent:[n data]];
+ [edgeNodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeNodeDataArrayController setEditable:YES];
+ } else {
+ [edgeNodeDataArrayController setContent:noEdgeNode];
+ [edgeNodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeNodeDataArrayController setEditable:NO];
+ }
+ } else if ([sel count] == 0) {
+ [edgeDataArrayController setContent:noSelection];
+ [edgeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeDataArrayController setEditable:NO];
+ [edgeNodeDataArrayController setContent:noSelection];
+ [edgeNodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeNodeDataArrayController setEditable:NO];
+ } else {
+ [edgeDataArrayController setContent:multipleSelection];
+ [edgeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeDataArrayController setEditable:NO];
+ [edgeNodeDataArrayController setContent:multipleSelection];
+ [edgeNodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeNodeDataArrayController setEditable:NO];
+ }
+ } else {
+ [edgeDataArrayController setContent:noGraph];
+ [edgeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeDataArrayController setEditable:NO];
+ [edgeNodeDataArrayController setContent:noGraph];
+ [edgeNodeDataArrayController setSelectionIndexes:[NSIndexSet indexSet]];
+ [edgeNodeDataArrayController setEditable:NO];
+ }
+}
+
+- (void)graphSelectionChanged:(NSNotification*)notification {
+ [self updateNodeFields];
+ [self updateEdgeFields];
+ [self updateGraphFields];
+}
+
+- (void)controlTextDidEndEditing:(NSNotification*)notification {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+ if (doc != nil) {
+ PickSupport *pick = [[doc graphicsView] pickSupport];
+ for (Node *n in [pick selectedNodes]) {
+ [n attachStyleFromTable:[stylePaletteController nodeStyles]];
+ }
+
+ for (Edge *e in [pick selectedEdges]) {
+ [e attachStyleFromTable:[stylePaletteController edgeStyles]];
+ }
+ }
+
+ [self refreshDocument:[notification object]];
+}
+
+- (void)addPropertyToAC:(NSArrayController*)ac {
+ [ac addObject:[[GraphElementProperty alloc] initWithPropertyValue:@"val" forKey:@"new_property"]];
+ [self refreshDocument:nil];
+}
+
+- (void)addAtomToAC:(NSArrayController*)ac {
+ [ac addObject:[[GraphElementProperty alloc] initWithAtomName:@"new_atom"]];
+ [self refreshDocument:nil];
+}
+
+- (void)removeFromAC:(NSArrayController*)ac {
+ [ac remove:nil];
+ [self refreshDocument:nil];
+}
+
+- (IBAction)addNodeProperty:(id)sender { [self addPropertyToAC:nodeDataArrayController]; }
+- (IBAction)addNodeAtom:(id)sender { [self addAtomToAC:nodeDataArrayController]; }
+- (IBAction)removeNodeProperty:(id)sender { [self removeFromAC:nodeDataArrayController]; }
+
+- (IBAction)addGraphProperty:(id)sender { [self addPropertyToAC:graphDataArrayController]; }
+- (IBAction)addGraphAtom:(id)sender { [self addAtomToAC:graphDataArrayController]; }
+- (IBAction)removeGraphProperty:(id)sender { [self removeFromAC:graphDataArrayController]; }
+
+- (IBAction)addEdgeProperty:(id)sender { [self addPropertyToAC:edgeDataArrayController]; }
+- (IBAction)addEdgeAtom:(id)sender { [self addAtomToAC:edgeDataArrayController]; }
+- (IBAction)removeEdgeProperty:(id)sender { [self removeFromAC:edgeDataArrayController]; }
+
+- (IBAction)addEdgeNodeProperty:(id)sender { [self addPropertyToAC:edgeNodeDataArrayController]; }
+- (IBAction)addEdgeNodeAtom:(id)sender { [self addAtomToAC:edgeNodeDataArrayController]; }
+- (IBAction)removeEdgeNodeProperty:(id)sender { [self removeFromAC:edgeNodeDataArrayController]; }
+
+//- (BOOL)enableEdgeDataControls {
+// NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+// TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+//
+// if (doc != nil) {
+// return ([[[[doc graphicsView] pickSupport] selectedEdges] count] == 1);
+// } else {
+// return NO;
+// }
+//}
+//
+//- (BOOL)enableEdgeNodeDataControls {
+// NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+// TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+//
+// if (doc != nil) {
+// PickSupport *pick = [[doc graphicsView] pickSupport];
+// if ([[pick selectedEdges] count] == 1) {
+// return ([[[pick selectedEdges] anyObject] hasEdgeNode]);
+// } else {
+// return NO;
+// }
+// } else {
+// return NO;
+// }
+//}
+
+@end
diff --git a/tikzit-1/src/osx/SelectBoxLayer.h b/tikzit-1/src/osx/SelectBoxLayer.h
new file mode 100644
index 0000000..45b43c7
--- /dev/null
+++ b/tikzit-1/src/osx/SelectBoxLayer.h
@@ -0,0 +1,22 @@
+//
+// SelectBoxLayer.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 14/06/2010.
+// Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CoreAnimation.h>
+
+@interface SelectBoxLayer : CALayer {
+ BOOL active;
+ CGRect box;
+}
+
+@property (assign) BOOL active;
+@property (assign) NSRect selectBox;
+
++ (SelectBoxLayer*)layer;
+
+@end
diff --git a/tikzit-1/src/osx/SelectBoxLayer.m b/tikzit-1/src/osx/SelectBoxLayer.m
new file mode 100644
index 0000000..a7abe33
--- /dev/null
+++ b/tikzit-1/src/osx/SelectBoxLayer.m
@@ -0,0 +1,48 @@
+//
+// SelectBoxLayer.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 14/06/2010.
+// Copyright 2010 __MyCompanyName__. All rights reserved.
+//
+
+#import "SelectBoxLayer.h"
+
+
+@implementation SelectBoxLayer
+
+@synthesize active;
+
+- (id)init {
+ if (!(self = [super init])) return nil;
+ box = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
+ active = NO;
+ return self;
+}
+
+- (void)setSelectBox:(NSRect)r {
+ box = NSRectToCGRect(r);
+}
+
+- (NSRect)selectBox {
+ return NSRectFromCGRect(box);
+}
+
+- (void)drawInContext:(CGContextRef)context {
+ if (active) {
+ CGContextAddRect(context, box);
+
+ CGContextSetRGBStrokeColor(context, 0.6, 0.6, 0.6, 1);
+ CGContextSetRGBFillColor(context, 0.8, 0.8, 0.8, 0.2);
+ CGContextSetLineWidth(context, 1);
+
+ CGContextSetShouldAntialias(context, NO);
+ CGContextDrawPath(context, kCGPathFillStroke);
+ }
+}
+
++ (SelectBoxLayer*)layer {
+ return [[SelectBoxLayer alloc] init];
+}
+
+@end
diff --git a/tikzit-1/src/osx/SelectableCollectionViewItem.h b/tikzit-1/src/osx/SelectableCollectionViewItem.h
new file mode 100644
index 0000000..4a2c571
--- /dev/null
+++ b/tikzit-1/src/osx/SelectableCollectionViewItem.h
@@ -0,0 +1,33 @@
+//
+// SelectableCollectionViewItem.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "StylePaletteController.h"
+
+@interface SelectableCollectionViewItem : NSCollectionViewItem {
+ IBOutlet StylePaletteController *stylePaletteController;
+}
+
+- (void)setStylePaletteController:(StylePaletteController*)spc;
+
+@end
diff --git a/tikzit-1/src/osx/SelectableCollectionViewItem.m b/tikzit-1/src/osx/SelectableCollectionViewItem.m
new file mode 100644
index 0000000..880c37b
--- /dev/null
+++ b/tikzit-1/src/osx/SelectableCollectionViewItem.m
@@ -0,0 +1,54 @@
+//
+// SelectableCollectionViewItem.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "SelectableCollectionViewItem.h"
+#import "SelectableNodeView.h"
+
+@implementation SelectableCollectionViewItem
+
+- (id)copyWithZone:(NSZone *)zone {
+ SelectableCollectionViewItem *item = [super copyWithZone:zone];
+ [item setStylePaletteController:stylePaletteController];
+ return (id)item;
+}
+
+- (void)setSelected:(BOOL)flag {
+ [super setSelected:flag];
+ [(SelectableNodeView*)[self view] setSelected:flag];
+
+ // only fire this event from the view that lost selection
+ //if (flag == NO) [stylePaletteController selectionDidChange];
+
+ [[self view] setNeedsDisplay:YES];
+}
+
+- (void)setRepresentedObject:(id)object {
+ [super setRepresentedObject:object];
+ [(SelectableNodeView*)[self view] setNodeStyle:(NodeStyle*)object];
+}
+
+- (void)setStylePaletteController:(StylePaletteController*)spc {
+ stylePaletteController = spc;
+}
+
+@end
diff --git a/tikzit-1/src/osx/SelectableNodeView.h b/tikzit-1/src/osx/SelectableNodeView.h
new file mode 100644
index 0000000..6b0841d
--- /dev/null
+++ b/tikzit-1/src/osx/SelectableNodeView.h
@@ -0,0 +1,38 @@
+//
+// SelectableView.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "NodeLayer.h"
+#import "NodeStyle.h"
+#import "NodeStyle+Coder.h"
+
+@interface SelectableNodeView : NSView {
+ BOOL selected;
+ NodeLayer *nodeLayer;
+}
+
+@property (assign) BOOL selected;
+@property (strong) NodeStyle *nodeStyle;
+
+
+@end
diff --git a/tikzit-1/src/osx/SelectableNodeView.m b/tikzit-1/src/osx/SelectableNodeView.m
new file mode 100644
index 0000000..797a137
--- /dev/null
+++ b/tikzit-1/src/osx/SelectableNodeView.m
@@ -0,0 +1,96 @@
+//
+// SelectableView.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "SelectableNodeView.h"
+#import "Shape.h"
+#import "Transformer.h"
+
+@implementation SelectableNodeView
+
+@synthesize selected;
+
+- (id)initWithFrame:(NSRect)frameRect {
+ if (!(self = [super initWithFrame:frameRect])) return nil;
+ nodeLayer = nil;
+ return self;
+}
+
+-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
+// NSLog(@"got draw");
+// CGContextSaveGState(context);
+//
+// if (selected) {
+// CGContextSetRGBStrokeColor(context, 0.61f, 0.735f, 1.0f, 1.0f);
+// CGContextSetRGBFillColor(context, 0.61f, 0.735f, 1.0f, 0.5f);
+// CGContextSetLineWidth(context, 1.0f);
+//
+// CGRect box = CGRectMake([layer frame].origin.x + 2,
+// [layer frame].origin.y + 2,
+// [layer frame].size.width - 4,
+// [layer frame].size.height - 4);
+//
+// //CGContextAddRect(context, box);
+// CGContextDrawPath(context, kCGPathFillStroke);
+// }
+//
+// CGContextRestoreGState(context);
+
+ if (nodeLayer!=nil) {
+ if (![[[self layer] sublayers] containsObject:nodeLayer]) {
+ [[self layer] addSublayer:nodeLayer];
+ NSPoint c = NSMakePoint(CGRectGetMidX([[self layer] frame]),
+ CGRectGetMidY([[self layer] frame]));
+ [nodeLayer setCenter:c andAnimateWhen:NO];
+ }
+
+ if (selected) [[nodeLayer selection] select];
+ else [[nodeLayer selection] deselect];
+
+ [nodeLayer updateFrame];
+ }
+}
+
+- (void)drawRect:(NSRect)rect {
+ [super drawRect:rect];
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { return YES; }
+
+- (void)setNodeStyle:(NodeStyle *)sty {
+ if (nodeLayer == nil) {
+ nodeLayer = [[NodeLayer alloc] initWithNode:[Node node]
+ transformer:[Transformer defaultTransformer]];
+ [nodeLayer setRescale:NO];
+ }
+
+ [[nodeLayer node] setStyle:sty];
+ [nodeLayer updateFrame];
+}
+
+- (NodeStyle*)nodeStyle {
+ if (nodeLayer != nil) return [[nodeLayer node] style];
+ else return nil;
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/StylePaletteController.h b/tikzit-1/src/osx/StylePaletteController.h
new file mode 100644
index 0000000..05f0684
--- /dev/null
+++ b/tikzit-1/src/osx/StylePaletteController.h
@@ -0,0 +1,80 @@
+//
+// StylePaletteController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "NodeStyle.h"
+#import "EdgeStyle.h"
+
+@class SFBInspectorView;
+
+@interface StylePaletteController : NSWindowController {
+ NSMutableArray *nodeStyles;
+ NSMutableArray *edgeStyles;
+ IBOutlet NSArrayController *nodeStyleArrayController;
+ IBOutlet NSArrayController *filteredNodeStyleArrayController;
+ IBOutlet NSArrayController *edgeStyleArrayController;
+ IBOutlet NSArrayController *filteredEdgeStyleArrayController;
+ IBOutlet NSCollectionView *collectionView;
+ IBOutlet SFBInspectorView *nodeStyleInspectorView;
+ IBOutlet NSView *nodeStyleView;
+ IBOutlet NSView *edgeStyleView;
+ IBOutlet NSPopUpButton *shapeDropdown;
+ NSString *displayedNodeStyleCategory;
+ NSString *displayedEdgeStyleCategory;
+}
+
+@property (strong) NSMutableArray *nodeStyles;
+@property (strong) NSMutableArray *edgeStyles;
+@property (readonly) BOOL documentActive;
+@property (strong) NodeStyle *activeNodeStyle;
+@property (strong) EdgeStyle *activeEdgeStyle;
+@property (copy) NSString *displayedNodeStyleCategory;
+@property (copy) NSString *displayedEdgeStyleCategory;
+@property (readonly) NSPredicate *displayedNodeStylePredicate;
+@property (readonly) NSPredicate *displayedEdgeStylePredicate;
+
+//@property NSString *nodeLabel;
+
+- (id)initWithWindowNibName:(NSString *)windowNibName
+ supportDir:(NSString*)supportDir;
+- (void)saveStyles:(NSString *)plist;
+
+- (IBAction)refreshCollection:(id)sender;
+
+- (IBAction)applyActiveNodeStyle:(id)sender;
+- (IBAction)clearActiveNodeStyle:(id)sender;
+- (IBAction)addNodeStyle:(id)sender;
+
+- (IBAction)appleActiveEdgeStyle:(id)sender;
+- (IBAction)clearActiveEdgeStyle:(id)sender;
+- (IBAction)addEdgeStyle:(id)sender;
+- (void)setActiveEdgeStyle:(EdgeStyle*)style;
+
+- (IBAction)setFillToClosestHashed:(id)sender;
+- (IBAction)setStrokeToClosestHashed:(id)sender;
+
+
+//- (IBAction)changeShape:(id)sender;
+
+
+@end
diff --git a/tikzit-1/src/osx/StylePaletteController.m b/tikzit-1/src/osx/StylePaletteController.m
new file mode 100644
index 0000000..4fe46be
--- /dev/null
+++ b/tikzit-1/src/osx/StylePaletteController.m
@@ -0,0 +1,252 @@
+//
+// StylePaletteController.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "StylePaletteController.h"
+#import "TikzDocument.h"
+#import "SFBInspectors/SFBInspectorView.h"
+#import "PickSupport.h"
+#import "Node.h"
+#import "Edge.h"
+#import "NodeStyle.h"
+#import "GraphicsView.h"
+#import "GraphElementProperty.h"
+#import "Shape.h"
+
+@implementation StylePaletteController
+
+@synthesize nodeStyles, edgeStyles;
+
+- (id)initWithWindowNibName:(NSString *)windowNibName
+ supportDir:(NSString*)supportDir
+{
+ if (self = [super initWithWindowNibName:windowNibName]) {
+ NSString *ns = [supportDir stringByAppendingPathComponent:@"nodeStyles.plist"];
+ NSString *es = [supportDir stringByAppendingPathComponent:@"edgeStyles.plist"];
+ nodeStyles = (NSMutableArray*)[NSKeyedUnarchiver
+ unarchiveObjectWithFile:ns];
+ edgeStyles = (NSMutableArray*)[NSKeyedUnarchiver
+ unarchiveObjectWithFile:es];
+
+ if (nodeStyles == nil) nodeStyles = [NSMutableArray array];
+ if (edgeStyles == nil) edgeStyles = [NSMutableArray array];
+
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"net.sourceforge.tikzit.inspectorsontop"] == YES) {
+ [[self window] setLevel:NSFloatingWindowLevel];
+ } else {
+ [[self window] setLevel:NSNormalWindowLevel];
+ }
+
+ [self showWindow:self];
+ }
+
+ return self;
+}
+
+- (void)windowDidLoad {
+ [[self window] setMovableByWindowBackground:YES];
+ [shapeDropdown addItemsWithTitles:[[Shape shapeDictionary] allKeys]];
+ if ([self activeNodeStyle] != nil) {
+ [shapeDropdown setTitle:[[self activeNodeStyle] shapeName]];
+ }
+
+ [nodeStyleInspectorView addInspectorPane:nodeStyleView
+ title:@"Node Styles"];
+
+ [nodeStyleInspectorView addInspectorPane:edgeStyleView
+ title:@"Edge Styles"];
+
+ [super windowDidLoad];
+}
+
+- (void)saveStyles:(NSString*)supportDir {
+ NSString *ns = [supportDir stringByAppendingPathComponent:@"nodeStyles.plist"];
+ NSString *es = [supportDir stringByAppendingPathComponent:@"edgeStyles.plist"];
+ [NSKeyedArchiver archiveRootObject:nodeStyles toFile:ns];
+ [NSKeyedArchiver archiveRootObject:edgeStyles toFile:es];
+}
+
+- (IBAction)refreshCollection:(id)sender {
+ [collectionView setNeedsDisplay:YES];
+}
+
+
+- (BOOL)documentActive {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ return dc.currentDocument != nil;
+}
+
+-(BOOL)collectionView:(NSCollectionView*)collectionView canDragItemsAtIndexes:(NSIndexSet*)indexes withEvent:(NSEvent*)event {
+ return YES;
+}
+
+
+//===========================
+//= setting SVG-safe colors =
+//===========================
+- (IBAction)setFillToClosestHashed:(id)sender {
+ NSArray *sel = [nodeStyleArrayController selectedObjects];
+ if ([sel count] != 0) {
+ NodeStyle *sty = [sel objectAtIndex:0];
+ [sty willChangeValueForKey:@"fillColor"];
+ [sty willChangeValueForKey:@"fillColorIsKnown"];
+ [sty.fillColorRGB setToClosestHashed];
+ [sty didChangeValueForKey:@"fillColor"];
+ [sty didChangeValueForKey:@"fillColorIsKnown"];
+ }
+}
+
+- (IBAction)setStrokeToClosestHashed:(id)sender {
+ NSArray *sel = [nodeStyleArrayController selectedObjects];
+ if ([sel count] != 0) {
+ NodeStyle *sty = [sel objectAtIndex:0];
+ [sty willChangeValueForKey:@"strokeColor"];
+ [sty willChangeValueForKey:@"strokeColorIsKnown"];
+ [sty.strokeColorRGB setToClosestHashed];
+ [sty didChangeValueForKey:@"strokeColor"];
+ [sty didChangeValueForKey:@"strokeColorIsKnown"];
+ }
+}
+
+//=================================================
+//= setting filter predicates for nodes and edges =
+//=================================================
+- (NSString*)displayedNodeStyleCategory {
+ return displayedNodeStyleCategory;
+}
+
+- (void)setDisplayedNodeStyleCategory:(NSString *)cat {
+ [self willChangeValueForKey:@"displayedNodeStylePredicate"];
+ displayedNodeStyleCategory = cat;
+ [self didChangeValueForKey:@"displayedNodeStylePredicate"];
+}
+
+- (NSString*)displayedEdgeStyleCategory {
+ return displayedEdgeStyleCategory;
+}
+
+- (void)setDisplayedEdgeStyleCategory:(NSString *)cat {
+ [self willChangeValueForKey:@"displayedEdgeStylePredicate"];
+ displayedEdgeStyleCategory = cat;
+ [self didChangeValueForKey:@"displayedEdgeStylePredicate"];
+}
+
+- (NSPredicate*)displayedNodeStylePredicate {
+ return [NSPredicate predicateWithFormat:@"category == %@", displayedNodeStyleCategory];
+}
+
+- (NSPredicate*)displayedEdgeStylePredicate {
+ return [NSPredicate predicateWithFormat:@"category == %@", displayedEdgeStyleCategory];
+}
+
+
+//==============================
+//= getting and setting styles =
+//==============================
+
+- (IBAction)applyActiveNodeStyle:(id)sender {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ [[doc graphicsView] applyStyleToSelectedNodes:[self activeNodeStyle]];
+ }
+
+ [[doc graphicsView] postSelectionChange];
+}
+
+- (IBAction)clearActiveNodeStyle:(id)sender {
+ [self setActiveNodeStyle:nil];
+
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ [[doc graphicsView] applyStyleToSelectedNodes:nil];
+ }
+
+ [[doc graphicsView] postSelectionChange];
+}
+
+- (NodeStyle*)activeNodeStyle {
+ NSArray *sel = [filteredNodeStyleArrayController selectedObjects];
+ if ([sel count] == 0) return nil;
+ else return [sel objectAtIndex:0];
+}
+
+- (void)setActiveNodeStyle:(NodeStyle*)style {
+ if ([nodeStyles containsObject:style]) {
+ [filteredNodeStyleArrayController setSelectedObjects:[NSArray arrayWithObject:style]];
+ } else {
+ [filteredNodeStyleArrayController setSelectedObjects:[NSArray array]];
+ }
+}
+
+- (IBAction)appleActiveEdgeStyle:(id)sender {
+ NSDocumentController *dc = [NSDocumentController sharedDocumentController];
+ TikzDocument *doc = (TikzDocument*)[dc currentDocument];
+
+ if (doc != nil) {
+ [[doc graphicsView] applyStyleToSelectedEdges:[self activeEdgeStyle]];
+ }
+}
+
+- (IBAction)clearActiveEdgeStyle:(id)sender {
+ [self setActiveEdgeStyle:nil];
+ [self appleActiveEdgeStyle:sender];
+}
+
+- (EdgeStyle*)activeEdgeStyle {
+ NSArray *sel = [filteredEdgeStyleArrayController selectedObjects];
+ if ([sel count] == 0) return nil;
+ else return [sel objectAtIndex:0];
+}
+
+- (void)setActiveEdgeStyle:(EdgeStyle*)style {
+ if ([edgeStyles containsObject:style]) {
+ [filteredEdgeStyleArrayController setSelectedObjects:[NSArray arrayWithObject:style]];
+ } else {
+ [filteredEdgeStyleArrayController setSelectedObjects:[NSArray array]];
+ }
+}
+
+
+//=================
+//= adding styles =
+//=================
+
+- (IBAction)addEdgeStyle:(id)sender {
+ EdgeStyle *sty = [[EdgeStyle alloc] init];
+ [sty setCategory:displayedEdgeStyleCategory];
+ [edgeStyleArrayController addObject:sty];
+ [self setActiveEdgeStyle:sty];
+}
+
+- (IBAction)addNodeStyle:(id)sender {
+ NodeStyle *sty = [[NodeStyle alloc] init];
+ [sty setCategory:displayedNodeStyleCategory];
+ [nodeStyleArrayController addObject:sty];
+ [self setActiveNodeStyle:sty];
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/TikzDocument.h b/tikzit-1/src/osx/TikzDocument.h
new file mode 100644
index 0000000..1881994
--- /dev/null
+++ b/tikzit-1/src/osx/TikzDocument.h
@@ -0,0 +1,37 @@
+//
+// TikzDocument.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "GraphicsView.h"
+#import "TikzSourceController.h"
+#import "PreviewController.h"
+#import "GraphicsView.h"
+
+@interface TikzDocument : NSDocument {
+ NSString *tikz;
+}
+
+@property (readonly) NSString *tikz;
+@property (weak, readonly) GraphicsView *graphicsView;
+
+@end
diff --git a/tikzit-1/src/osx/TikzDocument.m b/tikzit-1/src/osx/TikzDocument.m
new file mode 100644
index 0000000..ef5908d
--- /dev/null
+++ b/tikzit-1/src/osx/TikzDocument.m
@@ -0,0 +1,84 @@
+//
+// TikzDocument.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "TikzDocument.h"
+#import "TikzWindowController.h"
+
+@implementation TikzDocument
+
+@synthesize tikz;
+
+- (id)init {
+ self = [super init];
+ if (self) {
+ tikz = nil;
+ }
+ return self;
+}
+
+//- (NSString *)windowNibName {
+// // Override returning the nib file name of the document
+// // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
+// return @"TikzDocument";
+//}
+
+- (void)makeWindowControllers {
+ TikzWindowController *wc = [[TikzWindowController alloc] initWithDocument:self];
+ [self addWindowController:wc];
+}
+
+- (void)windowControllerDidLoadNib:(NSWindowController *) aController {
+ [super windowControllerDidLoadNib:aController];
+ [[self graphicsView] refreshLayers];
+ // Add any code here that needs to be executed once the windowController has loaded the document's window.
+}
+
+- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
+ TikzWindowController *wc =
+ (TikzWindowController*)[[self windowControllers] objectAtIndex:0];
+ NSData *outData = [[[wc tikzSourceController] tikz] dataUsingEncoding:NSUTF8StringEncoding];
+
+ if ( outError != NULL ) {
+ *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
+ }
+ return outData;
+}
+
+- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
+ tikz = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+
+ if ( outError != NULL ) {
+ *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
+ }
+
+ return YES;
+}
+
+- (GraphicsView*)graphicsView {
+ TikzWindowController *wc =
+ (TikzWindowController*)[[self windowControllers] objectAtIndex:0];
+ return [wc graphicsView];
+}
+
+
+@end
diff --git a/tikzit-1/src/osx/TikzFormatter.h b/tikzit-1/src/osx/TikzFormatter.h
new file mode 100644
index 0000000..4d9ec04
--- /dev/null
+++ b/tikzit-1/src/osx/TikzFormatter.h
@@ -0,0 +1,29 @@
+//
+// NSTikzFormatter.h
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 27/01/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface TikzFormatter : NSFormatter
+
+@end
diff --git a/tikzit-1/src/osx/TikzFormatter.m b/tikzit-1/src/osx/TikzFormatter.m
new file mode 100644
index 0000000..cb0865d
--- /dev/null
+++ b/tikzit-1/src/osx/TikzFormatter.m
@@ -0,0 +1,91 @@
+//
+// NSTikzFormatter.m
+// TikZiT
+//
+// Created by Karl Johan Paulsson on 27/01/2013.
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "TikzFormatter.h"
+#import "TikzGraphAssembler.h"
+
+@implementation TikzFormatter
+
+- (NSString *)stringForObjectValue:(id)obj{
+ if (![obj isKindOfClass:[NSString class]]) {
+ return @"";
+ }
+
+ return [NSString stringWithString:obj];
+}
+
+- (BOOL)getObjectValue:(out id *)obj forString:(NSString *)string errorDescription:(out NSString **)error{
+ *obj = [NSString stringWithString:string];
+
+ BOOL r = [TikzGraphAssembler validateTikzPropertyNameOrValue:string];
+
+ if (!r && error)
+ *error = NSLocalizedString(@"Invalid input, couldn't parse value.", @"tikz user input error");
+
+ return r;
+}
+
+- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error{
+ NSRange addedRange;
+ NSString *addedString;
+
+ if(![[NSUserDefaults standardUserDefaults] boolForKey:@"net.sourceforge.tikzit.autocomplete"]){
+ return YES;
+ }
+
+ addedRange = NSMakeRange(origSelRange.location, proposedSelRangePtr->location - origSelRange.location);
+ addedString = [*partialStringPtr substringWithRange: addedRange];
+
+ if([addedString isEqualToString:@"{"]){
+ NSString *s = [[NSString stringWithString:*partialStringPtr] stringByAppendingString:@"}"];
+ *partialStringPtr = s;
+
+ return NO;
+ }
+
+ if([addedString isEqualToString:@"}"]){
+ NSScanner *scanner = [NSScanner scannerWithString:*partialStringPtr];
+
+ NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:@"{}"];
+ NSMutableString *strippedString = [NSMutableString stringWithCapacity:[*partialStringPtr length]];
+
+ while ([scanner isAtEnd] == NO) {
+ NSString *buffer;
+ if ([scanner scanCharactersFromSet:cs intoString:&buffer]) {
+ [strippedString appendString:buffer];
+
+ } else {
+ [scanner setScanLocation:([scanner scanLocation] + 1)];
+ }
+ }
+
+ if([strippedString length] % 2 == 1){
+ return NO;
+ }
+ }
+
+ return YES;
+}
+
+@end
diff --git a/tikzit-1/src/osx/TikzSourceController.h b/tikzit-1/src/osx/TikzSourceController.h
new file mode 100644
index 0000000..84d36da
--- /dev/null
+++ b/tikzit-1/src/osx/TikzSourceController.h
@@ -0,0 +1,71 @@
+//
+// TikzSourceController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+
+#import "GraphicsView.h"
+#import "ParseErrorView.h"
+
+@interface TikzSourceController : NSObject {
+ GraphicsView *__weak graphicsView;
+ NSTextView *__unsafe_unretained sourceView;
+ NSAttributedString *source;
+ NSTextField *__weak status;
+ NSDictionary *textAttrs;
+ NSColor *successColor;
+ NSColor *failedColor;
+ NSTextField *__weak errorMessage;
+ ParseErrorView *__weak errorNotification;
+
+ NSUndoManager *__weak documentUndoManager;
+
+ BOOL tikzChanged;
+ BOOL justUndid;
+
+ NSError *lastError;
+}
+
+@property BOOL tikzChanged;
+@property (weak) IBOutlet GraphicsView *graphicsView;
+@property (unsafe_unretained) IBOutlet NSTextView *sourceView;
+@property (weak) IBOutlet NSTextField *status;
+@property (weak) NSUndoManager *documentUndoManager;
+@property (copy) NSAttributedString *source;
+@property (copy) NSString *tikz;
+@property (weak) IBOutlet ParseErrorView *errorNotification;
+@property (weak) IBOutlet NSTextField *errorMessage;
+
+- (void)updateTikzFromGraph;
+- (void)graphChanged:(NSNotification*)n;
+
+- (IBAction)closeParseError:(id)pId;
+
+// called by code, these do not register an undo
+- (BOOL)tryParseTikz;
+- (void)doRevertTikz;
+
+// called by user, these do register an undo
+- (void)parseTikz:(id)sender;
+- (void)revertTikz:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/TikzSourceController.m b/tikzit-1/src/osx/TikzSourceController.m
new file mode 100644
index 0000000..84eb3a5
--- /dev/null
+++ b/tikzit-1/src/osx/TikzSourceController.m
@@ -0,0 +1,241 @@
+//
+// TikzSourceController.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "TikzSourceController.h"
+#import "TikzGraphAssembler.h"
+#import "Graph.h"
+
+@implementation TikzSourceController
+
+@synthesize graphicsView, sourceView, source, status;
+@synthesize documentUndoManager, tikzChanged;
+@synthesize errorMessage, errorNotification;
+
+- (void)endEditing {
+ NSResponder *res = [[sourceView window] firstResponder];
+ [[sourceView window] makeFirstResponder:nil];
+ [[sourceView window] makeFirstResponder:res];
+}
+
+- (void)undoParseTikz:(Graph *)oldGraph {
+ [graphicsView setGraph:oldGraph];
+ [graphicsView setEnabled:NO];
+ [graphicsView postGraphChange];
+ [graphicsView refreshLayers];
+
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(parseTikz:)
+ object:self];
+ [documentUndoManager setActionName:@"Parse Tikz"];
+}
+
+- (void)undoRevertTikz:(NSString*)oldTikz {
+ [self setTikz:oldTikz];
+ [graphicsView setEnabled:NO];
+ [graphicsView refreshLayers];
+
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(revertTikz:)
+ object:self];
+ [documentUndoManager setActionName:@"Revert Tikz"];
+}
+
+- (void)undoTikzChange:(id)ignore {
+ [graphicsView setEnabled:YES];
+ [graphicsView refreshLayers];
+ [self endEditing];
+ [self updateTikzFromGraph];
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(redoTikzChange:)
+ object:nil];
+ [documentUndoManager setActionName:@"Tikz Change"];
+}
+
+- (void)redoTikzChange:(id)ignore {
+ [graphicsView setEnabled:NO];
+ [graphicsView refreshLayers];
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoTikzChange:)
+ object:nil];
+ [documentUndoManager setActionName:@"Tikz Change"];
+}
+
+
+- (void)awakeFromNib {
+ justUndid = NO;
+ successColor = [NSColor colorWithCalibratedRed:0.0f
+ green:0.5f
+ blue:0.0f
+ alpha:1.0f];
+ failedColor = [NSColor redColor];
+
+ NSFont *font = [NSFont userFixedPitchFontOfSize:11.0f];
+
+ if (font != nil) {
+ textAttrs = [NSDictionary dictionaryWithObject:font
+ forKey:NSFontAttributeName];
+ } else {
+ NSLog(@"WARNING: couldn't find monospaced font.");
+ textAttrs = [NSDictionary dictionary];
+ }
+
+
+ [self graphChanged:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(graphChanged:)
+ name:@"GraphChanged"
+ object:graphicsView];
+}
+
+- (void)setTikz:(NSString *)str {
+ [self willChangeValueForKey:@"source"];
+ source = [[NSAttributedString alloc] initWithString:str attributes:textAttrs];
+ [self didChangeValueForKey:@"source"];
+}
+
+- (NSString*)tikz {
+ return [source string];
+}
+
+- (void)updateTikzFromGraph {
+ [self setTikz:[[graphicsView graph] tikz]];
+ [errorNotification setHidden:TRUE];
+}
+
+- (void)graphChanged:(NSNotification*)n {
+ if ([graphicsView enabled]) [self updateTikzFromGraph];
+}
+
+- (IBAction)closeParseError:(id)pId{
+ [errorNotification setHidden:TRUE];
+}
+
+- (void)textDidBeginEditing:(NSNotification *)notification {
+ if ([graphicsView enabled]){
+ [graphicsView setEnabled:NO];
+ [graphicsView refreshLayers];
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoTikzChange:)
+ object:nil];
+ [documentUndoManager setActionName:@"Tikz Change"];
+ }
+}
+
+- (BOOL)tryParseTikz {
+ NSError *thisError;
+
+ Graph *g = [TikzGraphAssembler parseTikz:[self tikz]
+ error:&thisError];
+
+ lastError = thisError;
+
+ if (g) {
+ [graphicsView deselectAll:self];
+ [graphicsView setGraph:g];
+ [graphicsView refreshLayers];
+ [self doRevertTikz];
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
+- (void)doRevertTikz {
+ [self updateTikzFromGraph];
+ [self endEditing];
+ [graphicsView setEnabled:YES];
+ [graphicsView refreshLayers];
+ [status setStringValue:@""];
+}
+
+- (void)parseTikz:(id)sender {
+ if (![graphicsView enabled]) {
+ Graph *oldGraph = [graphicsView graph];
+ if ([self tryParseTikz]) {
+ [self endEditing];
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoParseTikz:)
+ object:oldGraph];
+ [documentUndoManager setActionName:@"Parse Tikz"];
+
+ [status setStringValue:@"success"];
+ [status setTextColor:successColor];
+
+ [errorNotification setHidden:TRUE];
+ } else {
+ [status setStringValue:@"parse error"];
+ [status setTextColor:failedColor];
+
+ NSDictionary *d = [lastError userInfo];
+
+ NSString *ts = [NSString stringWithFormat: @"Parse error on line %@: %@\n", [d valueForKey:@"startLine"], [d valueForKey:NSLocalizedDescriptionKey]];
+ NSMutableAttributedString *as = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat: @"Parse error on line %@: %@\n%@\n", [d valueForKey:@"startLine"], [d valueForKey:NSLocalizedDescriptionKey], [[d valueForKey:@"syntaxString"] stringByReplacingOccurrencesOfString:@"\t" withString:@""]]];
+
+ NSInteger tokenLength = [[d valueForKey:@"tokenLength"] integerValue];
+ // Bit of a mess, offset around to find correct position and correct for 4 characters for every one character of \t
+ NSInteger addedTokenStart = [[d valueForKey:@"tokenStart"] integerValue] + [ts length] - ([[[d valueForKey:@"syntaxString"] componentsSeparatedByString:@"\t"] count]-1)*4 - tokenLength;
+
+ // Can't see if the error is a start paranthesis as only that will be underlined, underline the entire paranthesis instead
+ if(tokenLength == 1 && [[as string] characterAtIndex:addedTokenStart] == '('){
+ tokenLength += [[[as string] substringFromIndex:addedTokenStart+1] rangeOfString:@")"].location + 1;
+ }
+
+ // Same if unexpected endparanthesis
+ if(tokenLength == 1 && [[as string] characterAtIndex:addedTokenStart] == ')'){
+ NSInteger d = addedTokenStart - [[[as string] substringToIndex:addedTokenStart] rangeOfString:@"(" options:NSBackwardsSearch].location;
+
+ tokenLength += d;
+ addedTokenStart -= d;
+ }
+
+ [as beginEditing];
+ [as addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:NSUnderlineStyleSingle | NSUnderlinePatternDot], NSUnderlineStyleAttributeName,
+ [NSColor redColor], NSUnderlineColorAttributeName,
+ nil]
+ range:NSMakeRange(addedTokenStart, tokenLength)];
+ [as endEditing];
+
+ [errorMessage setAttributedStringValue:as];
+ [errorNotification setHidden:FALSE];
+ }
+ }
+}
+
+- (void)revertTikz:(id)sender {
+ if (![graphicsView enabled]) {
+ NSString *oldTikz = [[self tikz] copy];
+ [self doRevertTikz];
+
+ [documentUndoManager registerUndoWithTarget:self
+ selector:@selector(undoRevertTikz:)
+ object:oldTikz];
+ [documentUndoManager setActionName:@"Revert Tikz"];
+ }
+}
+
+- (void)dealloc {
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+@end
diff --git a/tikzit-1/src/osx/TikzWindowController.h b/tikzit-1/src/osx/TikzWindowController.h
new file mode 100644
index 0000000..eab427c
--- /dev/null
+++ b/tikzit-1/src/osx/TikzWindowController.h
@@ -0,0 +1,31 @@
+//
+// TikzWindowController.h
+// TikZiT
+//
+// Created by Aleks Kissinger on 26/01/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@class TikzDocument, GraphicsView, TikzSourceController;
+
+@interface TikzWindowController : NSWindowController {
+ GraphicsView *__weak graphicsView;
+ TikzSourceController *__weak tikzSourceController;
+ TikzDocument *document;
+}
+
+@property (weak) IBOutlet GraphicsView *graphicsView;
+@property (weak) IBOutlet TikzSourceController *tikzSourceController;
+
+- (id)initWithDocument:(TikzDocument*)doc;
+
+// pass these straight to the tikz source controller
+- (void)parseTikz:(id)sender;
+- (void)revertTikz:(id)sender;
+- (void)zoomIn:(id)sender;
+- (void)zoomOut:(id)sender;
+- (void)zoomToActualSize:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/TikzWindowController.m b/tikzit-1/src/osx/TikzWindowController.m
new file mode 100644
index 0000000..bfacbfb
--- /dev/null
+++ b/tikzit-1/src/osx/TikzWindowController.m
@@ -0,0 +1,66 @@
+//
+// TikzWindowController.m
+// TikZiT
+//
+// Created by Aleks Kissinger on 26/01/2011.
+// Copyright 2011 __MyCompanyName__. All rights reserved.
+//
+
+#import "TikzWindowController.h"
+#import "TikzDocument.h"
+#import "GraphicsView.h"
+#import "TikzSourceController.h"
+
+@implementation TikzWindowController
+
+@synthesize graphicsView, tikzSourceController;
+
+- (id)initWithDocument:(TikzDocument*)doc {
+ if (!(self = [super initWithWindowNibName:@"TikzDocument"])) return nil;
+ document = doc;
+ return self;
+}
+
+- (void)awakeFromNib {
+ if ([document tikz] != nil) {
+ [graphicsView setEnabled:NO];
+ [tikzSourceController setTikz:[document tikz]];
+ [tikzSourceController parseTikz:self];
+ }
+
+ [graphicsView setDocumentUndoManager:[document undoManager]];
+ [tikzSourceController setDocumentUndoManager:[document undoManager]];
+}
+
+- (void)parseTikz:(id)sender {
+ [tikzSourceController parseTikz:sender];
+}
+
+- (void)revertTikz:(id)sender {
+ [tikzSourceController revertTikz:sender];
+}
+
+- (void)previewTikz:(id)sender {
+ PreviewController *pc = [PreviewController defaultPreviewController];
+ if (![[pc window] isVisible]) [pc showWindow:sender];
+ [pc buildTikz:[tikzSourceController tikz]];
+}
+
+- (void)zoomIn:(id)sender {
+ float scale = [[graphicsView transformer] scale] * 1.25f;
+ [[graphicsView transformer] setScale:scale];
+ [graphicsView refreshLayers];
+}
+
+- (void)zoomOut:(id)sender {
+ float scale = [[graphicsView transformer] scale] * 0.8f;
+ [[graphicsView transformer] setScale:scale];
+ [graphicsView refreshLayers];
+}
+
+- (void)zoomToActualSize:(id)sender {
+ [[graphicsView transformer] setScale:50.0f];
+ [graphicsView refreshLayers];
+}
+
+@end
diff --git a/tikzit-1/src/osx/ToolPaletteController.h b/tikzit-1/src/osx/ToolPaletteController.h
new file mode 100644
index 0000000..6301c6b
--- /dev/null
+++ b/tikzit-1/src/osx/ToolPaletteController.h
@@ -0,0 +1,42 @@
+//
+// ToolPaletteController.h
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+#import <Cocoa/Cocoa.h>
+
+typedef enum {
+ TikzToolSelect,
+ TikzToolNode,
+ TikzToolEdge,
+ TikzToolCrop
+} TikzTool;
+
+@interface ToolPaletteController : NSObject {
+ NSPanel *__weak toolPalette;
+ NSMatrix *__weak toolMatrix;
+}
+
+@property TikzTool selectedTool;
+@property (weak) IBOutlet NSPanel *toolPalette;
+@property (weak) IBOutlet NSMatrix *toolMatrix;
+
+
+@end
diff --git a/tikzit-1/src/osx/ToolPaletteController.m b/tikzit-1/src/osx/ToolPaletteController.m
new file mode 100644
index 0000000..000287d
--- /dev/null
+++ b/tikzit-1/src/osx/ToolPaletteController.m
@@ -0,0 +1,58 @@
+//
+// ToolPaletteController.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "ToolPaletteController.h"
+
+
+@implementation ToolPaletteController
+
+@synthesize toolPalette, toolMatrix;
+
+- (TikzTool)selectedTool {
+ switch (toolMatrix.selectedRow) {
+ case 0: return TikzToolSelect;
+ case 1: return TikzToolNode;
+ case 2: return TikzToolEdge;
+ case 3: return TikzToolCrop;
+ }
+ return TikzToolSelect;
+}
+
+- (void)setSelectedTool:(TikzTool)tool {
+ switch (tool) {
+ case TikzToolSelect:
+ [toolMatrix selectCellAtRow:0 column:0];
+ break;
+ case TikzToolNode:
+ [toolMatrix selectCellAtRow:1 column:0];
+ break;
+ case TikzToolEdge:
+ [toolMatrix selectCellAtRow:2 column:0];
+ break;
+ case TikzToolCrop:
+ [toolMatrix selectCellAtRow:3 column:0];
+ break;
+ }
+}
+
+@end
diff --git a/tikzit-1/src/osx/UpdatePreferenceController.h b/tikzit-1/src/osx/UpdatePreferenceController.h
new file mode 100644
index 0000000..816322f
--- /dev/null
+++ b/tikzit-1/src/osx/UpdatePreferenceController.h
@@ -0,0 +1,34 @@
+//
+// UpdatePreferenceController.h
+// TikZiT
+//
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Cocoa/Cocoa.h>
+#import <Sparkle/Sparkle.h>
+
+@interface UpdatePreferenceController : NSViewController{
+ IBOutlet SUUpdater *sharedUpdater;
+ IBOutlet NSDate *lastUpdate;
+}
+
+- (IBAction)checkForUpdates:(id)sender;
+
+@end
diff --git a/tikzit-1/src/osx/UpdatePreferenceController.m b/tikzit-1/src/osx/UpdatePreferenceController.m
new file mode 100644
index 0000000..2ff270f
--- /dev/null
+++ b/tikzit-1/src/osx/UpdatePreferenceController.m
@@ -0,0 +1,49 @@
+//
+// UpdatePreferenceController.h
+// TikZiT
+//
+// Copyright (c) 2013 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "UpdatePreferenceController.h"
+
+@interface UpdatePreferenceController ()
+
+@end
+
+@implementation UpdatePreferenceController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+ if (self) {
+ sharedUpdater = [SUUpdater sharedUpdater];
+ }
+ return self;
+}
+
+- (IBAction)checkForUpdates:(id)sender{
+ [sharedUpdater checkForUpdates:sender];
+}
+
+- (NSDate*)getLastUpdate{
+ return [sharedUpdater lastUpdateCheckDate];
+}
+
+@end
diff --git a/tikzit-1/src/osx/UpdatePreferencePanel.xib b/tikzit-1/src/osx/UpdatePreferencePanel.xib
new file mode 100644
index 0000000..a9f57bd
--- /dev/null
+++ b/tikzit-1/src/osx/UpdatePreferencePanel.xib
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13A603" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+ <dependencies>
+ <deployment defaultVersion="1070" identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="UpdatePreferenceController">
+ <connections>
+ <outlet property="view" destination="Rvg-HP-aJv" id="BaV-kv-ixT"/>
+ </connections>
+ </customObject>
+ <customObject id="QYw-wO-Hk1" customClass="SUUpdater"/>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application"/>
+ <customView autoresizesSubviews="NO" id="Rvg-HP-aJv">
+ <rect key="frame" x="0.0" y="0.0" width="480" height="118"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <subviews>
+ <button translatesAutoresizingMaskIntoConstraints="NO" id="r97-6h-YHZ">
+ <rect key="frame" x="18" y="82" width="225" height="18"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="check" title="Automatically check for updates" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="lJX-eh-125">
+ <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="checkForUpdates:" target="QYw-wO-Hk1" id="V6O-vN-gzU"/>
+ </connections>
+ </button>
+ <popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="rTe-Zb-gRB">
+ <rect key="frame" x="247" y="77" width="75" height="26"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <constraints>
+ <constraint firstAttribute="width" constant="70" id="E5t-Vq-EsW"/>
+ </constraints>
+ <popUpButtonCell key="cell" type="push" title="Hourly" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" tag="3600" imageScaling="proportionallyDown" inset="2" id="1sH-Qj-rJY">
+ <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ <menu key="menu" title="OtherViews" id="Thn-kJ-wMh">
+ <items>
+ <menuItem title="Hourly" state="on" tag="3600" id="pfB-GR-wmt"/>
+ <menuItem title="Daily" tag="86400" id="i4M-UZ-VYz"/>
+ <menuItem title="Weekly" tag="604800" id="xUT-n5-NQ6"/>
+ <menuItem title="Monthly" tag="2629800" id="6fb-Ll-N0L"/>
+ </items>
+ </menu>
+ </popUpButtonCell>
+ <connections>
+ <binding destination="QYw-wO-Hk1" name="enabled" keyPath="automaticallyChecksForUpdates" id="MEk-e1-13l"/>
+ <binding destination="QYw-wO-Hk1" name="selectedTag" keyPath="updateCheckInterval" id="ZgU-vh-YId"/>
+ </connections>
+ </popUpButton>
+ <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Edp-7i-rVO">
+ <rect key="frame" x="151" y="40" width="179" height="32"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="push" title="Check for update now" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6TE-6d-y5s">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ <connections>
+ <action selector="checkForUpdates:" target="-2" id="3kl-5L-9j6"/>
+ </connections>
+ </button>
+ <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kog-eQ-eh0">
+ <rect key="frame" x="18" y="20" width="444" height="14"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="center" title="Label" id="yBa-Dx-WK4">
+ <font key="font" size="11" name="LucidaGrande"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+ <connections>
+ <binding destination="-2" name="value" keyPath="lastUpdate" id="ULc-O0-aZL">
+ <dictionary key="options">
+ <bool key="NSRaisesForNotApplicableKeys" value="NO"/>
+ <bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
+ </dictionary>
+ </binding>
+ </connections>
+ </textFieldCell>
+ <connections>
+ <outlet property="formatter" destination="N9w-eT-NdL" id="Yn2-zV-GqY"/>
+ </connections>
+ </textField>
+ </subviews>
+ <constraints>
+ <constraint firstItem="r97-6h-YHZ" firstAttribute="top" secondItem="Rvg-HP-aJv" secondAttribute="top" constant="20" symbolic="YES" id="5PN-8T-E7N"/>
+ <constraint firstItem="rTe-Zb-gRB" firstAttribute="leading" secondItem="r97-6h-YHZ" secondAttribute="trailing" constant="8" symbolic="YES" id="JEG-EP-kMS"/>
+ <constraint firstItem="rTe-Zb-gRB" firstAttribute="baseline" secondItem="r97-6h-YHZ" secondAttribute="baseline" id="TAn-67-9cC"/>
+ <constraint firstItem="r97-6h-YHZ" firstAttribute="leading" secondItem="Rvg-HP-aJv" secondAttribute="leading" constant="20" symbolic="YES" id="o4v-st-ibG"/>
+ </constraints>
+ </customView>
+ <dateFormatter dateStyle="short" timeStyle="short" doesRelativeDateFormatting="YES" id="N9w-eT-NdL"/>
+ </objects>
+</document> \ No newline at end of file
diff --git a/tikzit-1/src/osx/main.m b/tikzit-1/src/osx/main.m
new file mode 100644
index 0000000..e6b4499
--- /dev/null
+++ b/tikzit-1/src/osx/main.m
@@ -0,0 +1,26 @@
+//
+// main.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+
+#import <Cocoa/Cocoa.h>
+
+int main(int argc, char *argv[])
+{
+ return NSApplicationMain(argc, (const char **) argv);
+}
diff --git a/tikzit-1/src/osx/test/main.m b/tikzit-1/src/osx/test/main.m
new file mode 100644
index 0000000..ad0c1f7
--- /dev/null
+++ b/tikzit-1/src/osx/test/main.m
@@ -0,0 +1,56 @@
+//
+// main.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "test/test.h"
+#include <string.h>
+
+void testCommon();
+void testOSX();
+
+int main(int argc, char **argv) {
+ if (argc == 2 && strcmp(argv[1], "--disable-color")==0) {
+ setColorEnabled(NO);
+ } else {
+ setColorEnabled(YES);
+ }
+
+ NSBundle *bund = [NSBundle bundleWithPath:@"TikZiT.app"];
+
+
+ PUTS(@"");
+ PUTS(@"**********************************************");
+ PUTS(@"TikZiT TESTS, OS X BUNDLE VERSION %@",
+ [bund objectForInfoDictionaryKey:@"CFBundleVersion"]);
+ PUTS(@"**********************************************");
+ PUTS(@"");
+
+ startTests();
+ testCommon();
+ testOSX();
+
+ PUTS(@"");
+ PUTS(@"**********************************************");
+ endTests();
+ PUTS(@"**********************************************");
+ PUTS(@"");
+} \ No newline at end of file
diff --git a/tikzit-1/src/osx/test/osx.m b/tikzit-1/src/osx/test/osx.m
new file mode 100644
index 0000000..f9565ab
--- /dev/null
+++ b/tikzit-1/src/osx/test/osx.m
@@ -0,0 +1,64 @@
+//
+// osx.m
+// TikZiT
+//
+// Copyright 2010 Aleks Kissinger. All rights reserved.
+//
+//
+// This file is part of TikZiT.
+//
+// TikZiT is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// TikZiT is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with TikZiT. If not, see <http://www.gnu.org/licenses/>.
+//
+#import "test/test.h"
+
+#import <Cocoa/Cocoa.h>
+
+void testOSX() {
+// char template[] = "/tmp/tikzit_test_tmp_XXXXXXX";
+// char *dir = mkdtemp(template);
+// NSString *tempDir = [NSString stringWithUTF8String:dir];
+//
+// NSString *testLatex =
+// @"\\documentclass{article}\n"
+// @"\\begin{document}\n"
+// @"test document\n"
+// @"\\end{document}\n";
+//
+// NSString *texFile = [NSString stringWithFormat:@"%@/test.tex", tempDir];
+// NSString *pdfFile = [NSString stringWithFormat:@"%@/test.pdf", tempDir];
+//
+// [testLatex writeToFile:texFile atomically:NO encoding:NSUTF8StringEncoding error:NULL];
+//
+// NSTask *task = [[NSTask alloc] init];
+// [task setLaunchPath:@"/bin/bash"];
+// NSPipe *inpt = [NSPipe pipe];
+// NSPipe *outpt = [NSPipe pipe];
+// [task setStandardInput:inpt];
+// [task setStandardOutput:outpt];
+//
+// [task launch];
+//
+// NSFileHandle *wr = [inpt fileHandleForWriting];
+// NSString *cmd =
+// [NSString stringWithFormat:
+// @"if [ -e ~/.profile ]; then source ~/.profile; fi"
+// @"if [ -e ~/.profile ]; then source ~/.profile; fi";
+// [wr writeData:[cmd dataUsingEncoding:NSUTF8StringEncoding]];
+// [wr closeFile];
+//
+// NSFileHandle *rd = [outpt fileHandleForReading];
+// NSString *res = [[NSString alloc] initWithData:[rd readDataToEndOfFile]
+// encoding:NSUTF8StringEncoding];
+// NSLog(@"got:\n %@", res);
+}