From 1802977b95d29198f27535b1b731d1180c083667 Mon Sep 17 00:00:00 2001 From: Aleks Kissinger Date: Wed, 11 Jan 2017 16:33:00 +0100 Subject: made new subdir --- tikzit-1/src/osx/AppDelegate.h | 57 ++ tikzit-1/src/osx/AppDelegate.m | 124 +++ tikzit-1/src/osx/CALayer+DrawLabel.h | 21 + tikzit-1/src/osx/CALayer+DrawLabel.m | 84 ++ tikzit-1/src/osx/CoreGraphicsRenderContext.h | 44 + tikzit-1/src/osx/CoreGraphicsRenderContext.m | 234 +++++ tikzit-1/src/osx/CustomNodeCellView.h | 23 + tikzit-1/src/osx/CustomNodeCellView.m | 83 ++ tikzit-1/src/osx/CustomNodeController.h | 35 + tikzit-1/src/osx/CustomNodeController.m | 58 ++ tikzit-1/src/osx/CustomNodes.xib | 249 +++++ tikzit-1/src/osx/DraggablePDFView.h | 28 + tikzit-1/src/osx/DraggablePDFView.m | 60 ++ tikzit-1/src/osx/EdgeControlLayer.h | 44 + tikzit-1/src/osx/EdgeControlLayer.m | 150 +++ tikzit-1/src/osx/EdgeStyle+Coder.h | 30 + tikzit-1/src/osx/EdgeStyle+Coder.m | 50 + tikzit-1/src/osx/Graph+Coder.h | 17 + tikzit-1/src/osx/Graph+Coder.m | 24 + tikzit-1/src/osx/GraphicsView.h | 129 +++ tikzit-1/src/osx/GraphicsView.m | 1216 +++++++++++++++++++++++ tikzit-1/src/osx/Grid.h | 48 + tikzit-1/src/osx/Grid.m | 152 +++ tikzit-1/src/osx/MultiCombo.h | 18 + tikzit-1/src/osx/MultiCombo.m | 38 + tikzit-1/src/osx/MultiField.h | 18 + tikzit-1/src/osx/MultiField.m | 53 + tikzit-1/src/osx/NilToEmptyStringTransformer.h | 28 + tikzit-1/src/osx/NilToEmptyStringTransformer.m | 53 + tikzit-1/src/osx/NodeLayer.h | 62 ++ tikzit-1/src/osx/NodeLayer.m | 238 +++++ tikzit-1/src/osx/NodeSelectionLayer.h | 45 + tikzit-1/src/osx/NodeSelectionLayer.m | 93 ++ tikzit-1/src/osx/NodeStyle+Coder.h | 36 + tikzit-1/src/osx/NodeStyle+Coder.m | 91 ++ tikzit-1/src/osx/ParseErrorView.h | 13 + tikzit-1/src/osx/ParseErrorView.m | 40 + tikzit-1/src/osx/PreambleController.h | 57 ++ tikzit-1/src/osx/PreambleController.m | 168 ++++ tikzit-1/src/osx/Preambles+Coder.h | 32 + tikzit-1/src/osx/Preambles+Coder.m | 41 + tikzit-1/src/osx/PreferenceController.h | 49 + tikzit-1/src/osx/PreferenceController.m | 133 +++ tikzit-1/src/osx/Preferences.xib | 1165 ++++++++++++++++++++++ tikzit-1/src/osx/PreviewController.h | 52 + tikzit-1/src/osx/PreviewController.m | 147 +++ tikzit-1/src/osx/PropertyInspectorController.h | 83 ++ tikzit-1/src/osx/PropertyInspectorController.m | 280 ++++++ tikzit-1/src/osx/SelectBoxLayer.h | 22 + tikzit-1/src/osx/SelectBoxLayer.m | 48 + tikzit-1/src/osx/SelectableCollectionViewItem.h | 33 + tikzit-1/src/osx/SelectableCollectionViewItem.m | 54 + tikzit-1/src/osx/SelectableNodeView.h | 38 + tikzit-1/src/osx/SelectableNodeView.m | 96 ++ tikzit-1/src/osx/StylePaletteController.h | 80 ++ tikzit-1/src/osx/StylePaletteController.m | 252 +++++ tikzit-1/src/osx/TikzDocument.h | 37 + tikzit-1/src/osx/TikzDocument.m | 84 ++ tikzit-1/src/osx/TikzFormatter.h | 29 + tikzit-1/src/osx/TikzFormatter.m | 91 ++ tikzit-1/src/osx/TikzSourceController.h | 71 ++ tikzit-1/src/osx/TikzSourceController.m | 241 +++++ tikzit-1/src/osx/TikzWindowController.h | 31 + tikzit-1/src/osx/TikzWindowController.m | 66 ++ tikzit-1/src/osx/ToolPaletteController.h | 42 + tikzit-1/src/osx/ToolPaletteController.m | 58 ++ tikzit-1/src/osx/UpdatePreferenceController.h | 34 + tikzit-1/src/osx/UpdatePreferenceController.m | 49 + tikzit-1/src/osx/UpdatePreferencePanel.xib | 95 ++ tikzit-1/src/osx/main.m | 26 + tikzit-1/src/osx/test/main.m | 56 ++ tikzit-1/src/osx/test/osx.m | 64 ++ 72 files changed, 7690 insertions(+) create mode 100644 tikzit-1/src/osx/AppDelegate.h create mode 100644 tikzit-1/src/osx/AppDelegate.m create mode 100644 tikzit-1/src/osx/CALayer+DrawLabel.h create mode 100644 tikzit-1/src/osx/CALayer+DrawLabel.m create mode 100644 tikzit-1/src/osx/CoreGraphicsRenderContext.h create mode 100644 tikzit-1/src/osx/CoreGraphicsRenderContext.m create mode 100644 tikzit-1/src/osx/CustomNodeCellView.h create mode 100644 tikzit-1/src/osx/CustomNodeCellView.m create mode 100644 tikzit-1/src/osx/CustomNodeController.h create mode 100644 tikzit-1/src/osx/CustomNodeController.m create mode 100644 tikzit-1/src/osx/CustomNodes.xib create mode 100644 tikzit-1/src/osx/DraggablePDFView.h create mode 100644 tikzit-1/src/osx/DraggablePDFView.m create mode 100644 tikzit-1/src/osx/EdgeControlLayer.h create mode 100644 tikzit-1/src/osx/EdgeControlLayer.m create mode 100644 tikzit-1/src/osx/EdgeStyle+Coder.h create mode 100644 tikzit-1/src/osx/EdgeStyle+Coder.m create mode 100644 tikzit-1/src/osx/Graph+Coder.h create mode 100644 tikzit-1/src/osx/Graph+Coder.m create mode 100644 tikzit-1/src/osx/GraphicsView.h create mode 100644 tikzit-1/src/osx/GraphicsView.m create mode 100644 tikzit-1/src/osx/Grid.h create mode 100644 tikzit-1/src/osx/Grid.m create mode 100644 tikzit-1/src/osx/MultiCombo.h create mode 100644 tikzit-1/src/osx/MultiCombo.m create mode 100644 tikzit-1/src/osx/MultiField.h create mode 100644 tikzit-1/src/osx/MultiField.m create mode 100644 tikzit-1/src/osx/NilToEmptyStringTransformer.h create mode 100644 tikzit-1/src/osx/NilToEmptyStringTransformer.m create mode 100644 tikzit-1/src/osx/NodeLayer.h create mode 100644 tikzit-1/src/osx/NodeLayer.m create mode 100644 tikzit-1/src/osx/NodeSelectionLayer.h create mode 100644 tikzit-1/src/osx/NodeSelectionLayer.m create mode 100644 tikzit-1/src/osx/NodeStyle+Coder.h create mode 100644 tikzit-1/src/osx/NodeStyle+Coder.m create mode 100644 tikzit-1/src/osx/ParseErrorView.h create mode 100644 tikzit-1/src/osx/ParseErrorView.m create mode 100644 tikzit-1/src/osx/PreambleController.h create mode 100644 tikzit-1/src/osx/PreambleController.m create mode 100644 tikzit-1/src/osx/Preambles+Coder.h create mode 100644 tikzit-1/src/osx/Preambles+Coder.m create mode 100644 tikzit-1/src/osx/PreferenceController.h create mode 100644 tikzit-1/src/osx/PreferenceController.m create mode 100644 tikzit-1/src/osx/Preferences.xib create mode 100644 tikzit-1/src/osx/PreviewController.h create mode 100644 tikzit-1/src/osx/PreviewController.m create mode 100644 tikzit-1/src/osx/PropertyInspectorController.h create mode 100644 tikzit-1/src/osx/PropertyInspectorController.m create mode 100644 tikzit-1/src/osx/SelectBoxLayer.h create mode 100644 tikzit-1/src/osx/SelectBoxLayer.m create mode 100644 tikzit-1/src/osx/SelectableCollectionViewItem.h create mode 100644 tikzit-1/src/osx/SelectableCollectionViewItem.m create mode 100644 tikzit-1/src/osx/SelectableNodeView.h create mode 100644 tikzit-1/src/osx/SelectableNodeView.m create mode 100644 tikzit-1/src/osx/StylePaletteController.h create mode 100644 tikzit-1/src/osx/StylePaletteController.m create mode 100644 tikzit-1/src/osx/TikzDocument.h create mode 100644 tikzit-1/src/osx/TikzDocument.m create mode 100644 tikzit-1/src/osx/TikzFormatter.h create mode 100644 tikzit-1/src/osx/TikzFormatter.m create mode 100644 tikzit-1/src/osx/TikzSourceController.h create mode 100644 tikzit-1/src/osx/TikzSourceController.m create mode 100644 tikzit-1/src/osx/TikzWindowController.h create mode 100644 tikzit-1/src/osx/TikzWindowController.m create mode 100644 tikzit-1/src/osx/ToolPaletteController.h create mode 100644 tikzit-1/src/osx/ToolPaletteController.m create mode 100644 tikzit-1/src/osx/UpdatePreferenceController.h create mode 100644 tikzit-1/src/osx/UpdatePreferenceController.m create mode 100644 tikzit-1/src/osx/UpdatePreferencePanel.xib create mode 100644 tikzit-1/src/osx/main.m create mode 100644 tikzit-1/src/osx/test/main.m create mode 100644 tikzit-1/src/osx/test/osx.m (limited to 'tikzit-1/src/osx') 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 . +// + +#import +#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 . +// + +#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 +#import + +@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 + * + * 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 . + */ + +#import +#import "RenderContext.h" + +@interface CoreTextLayout: NSObject { + 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 { + 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 + * + * 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 . + */ + +#import +#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) 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 + +#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 +#import "Shape.h" +#import "TikzShape.h" + +#import "GraphicsView.h" +#import "TikzSourceController.h" + +#import "SupportDir.h" + +@interface CustomNodeController : NSViewController { + 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 @@ + + + + + + + + + + + + + + + + + + + name + strokeThickness + strokeColor + fillColor + strokeColorIsKnown + fillColorIsKnown + representedObject.name + shapeName + scale + @distinctUnionOfObjects.category + category + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \begin{tikzpicture} + +\end{tikzpicture} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 . +// + +#import + +@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 . +// + +#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 . +// + +#import +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 +#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 . +// + +#import +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 + + +@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 + + +@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 . +// + +#import + +@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 . +// + +#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 . +// + +#import +#import +#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 . +// + +#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 . +// + +#import +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 + +@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 . +// + +#import +#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 . +// + +#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 . +// + +#import "Preambles.h" +#import + +@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 . +// + +#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 . +// + +#import +#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 . +// + +#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 @@ + + + + 1070 + 13C64 + 5053 + 1265.19 + 697.40 + + com.apple.InterfaceBuilder.CocoaPlugin + 5053 + + + IBNSLayoutConstraint + NSButton + NSButtonCell + NSCustomObject + NSCustomView + NSTextField + NSTextFieldCell + NSToolbar + NSToolbarItem + NSUserDefaultsController + NSView + NSWindowTemplate + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + PreferenceController + + + FirstResponder + + + NSApplication + + + 7 + 2 + {{196, 240}, {480, 270}} + 544736256 + Preferences + NSWindow + + + C1747407-DC9A-4297-9C1C-0A5010984E6C + + + YES + YES + NO + NO + 1 + 1 + + + + 197F9408-AFB0-404B-B2B6-4DB1250B0A80 + + Updates + Updates + + + + NSImage + updates + + + + {0, 0} + {0, 0} + YES + YES + 2 + YES + 0 + + + + A3DDD070-5637-444B-92C6-905084CAC389 + + General + General + + + + NSImage + NSPreferencesGeneral + + + + {0, 0} + {0, 0} + YES + YES + 1 + YES + 0 + + + + A96DC4D4-2171-4D05-8C08-8D01B3829158 + + Preamble + Preamble + + + + NSImage + preamble + + + + {0, 0} + {0, 0} + YES + YES + 3 + YES + 0 + + + + CBA2626C-DD4C-4ADD-BD5D-26D21216D9A8 + + Custom Nodes + Custom Nodes + + + + NSImage + customshape + + + + {0, 0} + {0, 0} + YES + YES + 4 + YES + 0 + + + + F85FE7C2-9847-4E58-8BF6-BE334E918CA7 + + Engine + Engine + + + + NSImage + engine + + + + {0, 0} + {0, 0} + YES + YES + 1 + YES + 0 + + + + + + + + + + + + + + + + + + + + + {480, 270} + + + + + {{0, 0}, {1680, 1028}} + {10000000000000, 10000000000000} + YES + + + + 268 + + + + 268 + {{18, 106}, {219, 18}} + + + + _NS:9 + YES + + -2080374784 + 268435456 + Keep inspector windows on top + + .LucidaGrandeUI + 13 + 1044 + + _NS:9 + + 1211912448 + 2 + + NSImage + NSSwitch + + + NSSwitch + + + + 200 + 25 + + NO + + + + 268 + {{18, 126}, {168, 18}} + + + + _NS:9 + YES + + -2080374784 + 268435456 + Autocomplete brackets + + _NS:9 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + + + + 268 + {{18, 18}, {214, 18}} + + + + _NS:9 + YES + + -2080374784 + 268435456 + Bring preview window to focus + + _NS:9 + + 1211912448 + 2 + + + + + 200 + 25 + + NO + + + + 268 + {{20, 42}, {440, 22}} + + + + _NS:9 + YES + + -1804599231 + 272630784 + + + _NS:9 + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + 3 + MAA + + + + NO + 1 + + + + 268 + {{18, 72}, {140, 17}} + + + + _NS:1535 + YES + + 68157504 + 272630784 + pdfLaTeX source path + + _NS:1535 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + + + NO + 1 + + + {480, 162} + + + + _NS:9 + NSView + + + + 268 + + {480, 96} + + + + _NS:9 + NSView + + + + 12 + + {480, 115} + + + + _NS:9 + NSView + + + + 12 + + {557, 354} + + + + _NS:9 + NSView + + + + 12 + + {557, 354} + + + + _NS:9 + NSView + + + YES + + + + + + + window + + + + 3 + + + + engineView + + + + 23 + + + + generalView + + + + 25 + + + + switchView: + + + + 26 + + + + switchView: + + + + 27 + + + + switchView: + + + + 116 + + + + updateView + + + + 117 + + + + switchView: + + + + 120 + + + + preambleView + + + + 121 + + + + customNodeView + + + + 123 + + + + switchView: + + + + 125 + + + + delegate + + + + 4 + + + + value: values.net.sourceforge.tikzit.pdflatexpath + + + + + + value: values.net.sourceforge.tikzit.pdflatexpath + value + values.net.sourceforge.tikzit.pdflatexpath + 2 + + + 54 + + + + value: values.net.sourceforge.tikzit.previewfocus + + + + + + value: values.net.sourceforge.tikzit.previewfocus + value + values.net.sourceforge.tikzit.previewfocus + 2 + + + 62 + + + + value: values.net.sourceforge.tikzit.autocomplete + + + + + + value: values.net.sourceforge.tikzit.autocomplete + value + values.net.sourceforge.tikzit.autocomplete + 2 + + + 149 + + + + value: values.net.sourceforge.tikzit.inspectorsontop + + + + + + value: values.net.sourceforge.tikzit.inspectorsontop + value + values.net.sourceforge.tikzit.inspectorsontop + 2 + + + 150 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + + + + + + + 2 + + + + + 5 + + + + + + + + + + + + 11 + + + + + 12 + + + + + 13 + + + + + 4 + 0 + + 4 + 1 + 1 + + 20 + + 1000 + + 8 + 23 + 3 + NO + + + + 3 + 0 + + 4 + 1 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + NO + + + + 5 + 0 + + 5 + 1 + 1 + + 20 + + 1000 + + 0 + 29 + 3 + NO + + + + 6 + 0 + + 6 + 1 + 1 + + 20 + + 1000 + + 0 + 29 + 3 + NO + + + + 3 + 0 + + 4 + 1 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + NO + + + + 5 + 0 + + 5 + 1 + 1 + + 20 + + 1000 + + 0 + 29 + 3 + NO + + + + 5 + 0 + + 5 + 1 + 1 + + 20 + + 1000 + + 0 + 29 + 3 + NO + + + + 5 + 0 + + 5 + 1 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + NO + + + + 3 + 0 + + 4 + 1 + 1 + + 6 + + 1000 + + 6 + 24 + 3 + NO + + + + 5 + 0 + + 5 + 1 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + NO + + + + 3 + 0 + + 3 + 1 + 1 + + 20 + + 1000 + + 8 + 23 + 3 + NO + + + + + + + + + + + 14 + + + + + + 15 + + + + + + + + 16 + + + + + 30 + + + + + 32 + + + + + + + + 33 + + + + + 36 + + + + + 39 + + + + + 55 + + + + + 56 + + + + + 57 + + + + + + + + 58 + + + + + 59 + + + + + 60 + + + + + 64 + + + + + + 115 + + + + + 118 + + + + + 119 + + + + + 122 + + + + + 124 + + + + + 126 + + + + + 127 + + + + + + + + 128 + + + + + 130 + + + + + 131 + + + + + + + + 132 + + + + + 134 + + + + + 135 + + + + + 153 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{357, 418}, {480, 270}} + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 153 + + + + + PreferenceController + NSWindowController + + switchView: + id + + + switchView: + + switchView: + id + + + + NSView + NSView + NSView + NSView + NSView + + + + customNodeView + NSView + + + engineView + NSView + + + generalView + NSView + + + preambleView + NSView + + + updateView + NSView + + + + IBProjectSource + ./Classes/PreferenceController.h + + + + + 0 + IBCocoaFramework + YES + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {32, 32} + {15, 15} + {32, 32} + {32, 32} + {32, 32} + {32, 32} + + YES + + 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 . +// + + +#import +#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 . +// + +#import "PreviewController.h" +#import "AppDelegate.h" +#import "PreambleController.h" +#import + +@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 +#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 +#import + +@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 . +// + +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 . +// + +#import +#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 . +// + +#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 . +// + +#import + +@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 . +// + +#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 . +// + +#import + +#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 . +// + +#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 + +@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 . +// +#import + +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 . +// + +#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 . +// + +#import +#import + +@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 . +// + +#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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 + +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 . +// + +#import "test/test.h" +#include + +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 . +// +#import "test/test.h" + +#import + +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); +} -- cgit v1.2.3