Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

#20 use NSTextField instead of NSTextView

- add QMBorderedView
- fix test
- add settings[XYZ]
  • Loading branch information...
commit 630459b13a6959d255fabfe468142be7554acf49 1 parent 9b1bd6e
Tae Won Ha authored
View
8 Qmind.xcodeproj/project.pbxproj
@@ -20,6 +20,7 @@
1929B36A99C420734C86E3CE /* QMCellPropertiesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBD6539D9FDEC76E6137 /* QMCellPropertiesManager.m */; };
1929B3A02CC1561045BF1FEC /* QMCellPropertiesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBD6539D9FDEC76E6137 /* QMCellPropertiesManager.m */; };
1929B3DBFDDCED6A832EBA6B /* ToolbarZoomOutTemplate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1929B38391793C25EF358118 /* ToolbarZoomOutTemplate@2x.png */; };
+ 1929B4013A5FFD5A6E6DF6F9 /* QMBorderedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5877760CCBAFC69427F /* QMBorderedView.m */; };
1929B502755E4F47D5612FA2 /* ToolbarDeleteNodeTemplate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1929B7F07C814229B2270D34 /* ToolbarDeleteNodeTemplate@2x.png */; };
1929B5884D28A022A0F52F48 /* QMIdGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB6573724B1C6F3E369C /* QMIdGenerator.m */; };
1929B676F4A74F9E9F96AB42 /* QMIcon.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA02C47D9D0A43F49EFA /* QMIcon.m */; };
@@ -52,6 +53,7 @@
4B39307A14EC418900A9D541 /* QMMindmapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B39307914EC418900A9D541 /* QMMindmapView.m */; };
4B396DD614F7E446000C7B36 /* dummy.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4BFCD7AC14F3E32A00850936 /* dummy.pdf */; };
4B521D9C17A54EB600153278 /* fontawesome-webfont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4B521D9B17A54EB600153278 /* fontawesome-webfont.ttf */; };
+ 4B551D8B1882A448007A16D6 /* QMBorderedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5877760CCBAFC69427F /* QMBorderedView.m */; };
4B5CB60A15E1187500E05BD7 /* QMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCD74E14F3D33600850924 /* QMAppDelegate.m */; };
4B5CB60B15E1187500E05BD7 /* QMAppSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B85653514E46D6800C6FF26 /* QMAppSettings.m */; };
4B5CB60C15E1187500E05BD7 /* QMUiDrawer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B20B51839B9482813969 /* QMUiDrawer.m */; };
@@ -372,6 +374,7 @@
1929B20B51839B9482813969 /* QMUiDrawer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QMUiDrawer.m; sourceTree = "<group>"; };
1929B2B42279F40C0CE08187 /* QMIdGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMIdGenerator.h; sourceTree = "<group>"; };
1929B2FCB4A407CCC68D9D45 /* QMIconsPaneView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QMIconsPaneView.m; sourceTree = "<group>"; };
+ 1929B302EBBFF24DFC769829 /* QMBorderedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMBorderedView.h; sourceTree = "<group>"; };
1929B353C299640D7D91AA9D /* QMCellSizeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QMCellSizeManager.m; sourceTree = "<group>"; };
1929B38391793C25EF358118 /* ToolbarZoomOutTemplate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ToolbarZoomOutTemplate@2x.png"; path = "Resources/ToolbarZoomOutTemplate@2x.png"; sourceTree = "<group>"; };
1929B3AAAFA6CF293F45F812 /* QMLookUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QMLookUtil.m; sourceTree = "<group>"; };
@@ -379,6 +382,7 @@
1929B49C1022861E4672965B /* QMCellPropertiesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMCellPropertiesManager.h; sourceTree = "<group>"; };
1929B4E814EA183B1791462A /* QMUiDrawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMUiDrawer.h; sourceTree = "<group>"; };
1929B5323A40ED9F3A4A04BE /* ToolbarZoomInTemplate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "ToolbarZoomInTemplate@2x.png"; path = "Resources/ToolbarZoomInTemplate@2x.png"; sourceTree = "<group>"; };
+ 1929B5877760CCBAFC69427F /* QMBorderedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QMBorderedView.m; sourceTree = "<group>"; };
1929B5969C8028EF888FAA7C /* QMIconsPaneView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMIconsPaneView.h; sourceTree = "<group>"; };
1929B5A9AAEC82B9CE22DFA2 /* QMCellSizeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QMCellSizeManager.h; sourceTree = "<group>"; };
1929B743A0D8FAB8C620E299 /* IconCollectionViewItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IconCollectionViewItemTest.m; sourceTree = "<group>"; };
@@ -640,6 +644,8 @@
4B85653514E46D6800C6FF39 /* QMMindmapViewDataSource.h */,
4B39307814EC418900A9D541 /* QMMindmapView.h */,
4B39307914EC418900A9D541 /* QMMindmapView.m */,
+ 1929B5877760CCBAFC69427F /* QMBorderedView.m */,
+ 1929B302EBBFF24DFC769829 /* QMBorderedView.h */,
);
name = View;
sourceTree = "<group>";
@@ -1226,6 +1232,7 @@
1929BB6FEB32F64962B24562 /* QMManualBeanProvider.m in Sources */,
1929B32033377AB1DF3E6675 /* QMCellPropertiesManager.m in Sources */,
1929B5884D28A022A0F52F48 /* QMIdGenerator.m in Sources */,
+ 1929B4013A5FFD5A6E6DF6F9 /* QMBorderedView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1265,6 +1272,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 4B551D8B1882A448007A16D6 /* QMBorderedView.m in Sources */,
4B6BC4B516AF303B00F24572 /* QMManualBeanProvider.m in Sources */,
4B1752D416A48B01002FAFC4 /* MindmapReaderTest.m in Sources */,
4B12E236168CC34900D972BE /* QMIconTest.m in Sources */,
View
53 Qmind.xcodeproj/xcshareddata/xcschemes/QmindSenTesting.xcscheme
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
- LastUpgradeVersion = "0500"
- version = "1.3">
- <BuildAction
- parallelizeBuildables = "YES"
- buildImplicitDependencies = "YES">
- </BuildAction>
- <TestAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Debug">
- <Testables>
- <TestableReference
- skipped = "NO">
- <BuildableReference
- BuildableIdentifier = "primary"
- BlueprintIdentifier = "4BFCD75514F3D34700850924"
- BuildableName = "QmindSenTesting.xctest"
- BlueprintName = "QmindSenTesting"
- ReferencedContainer = "container:Qmind.xcodeproj">
- </BuildableReference>
- </TestableReference>
- </Testables>
- </TestAction>
- <LaunchAction
- selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
- selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- launchStyle = "0"
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Debug"
- ignoresPersistentStateOnLaunch = "NO"
- debugDocumentVersioning = "YES"
- allowLocationSimulation = "YES">
- <AdditionalOptions>
- </AdditionalOptions>
- </LaunchAction>
- <ProfileAction
- shouldUseLaunchSchemeArgsEnv = "YES"
- savedToolIdentifier = ""
- useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
- debugDocumentVersioning = "YES">
- </ProfileAction>
- <AnalyzeAction
- buildConfiguration = "Debug">
- </AnalyzeAction>
- <ArchiveAction
- buildConfiguration = "Release"
- revealArchiveInOrganizer = "YES">
- </ArchiveAction>
-</Scheme>
View
1  Qmind/QMAppSettings.h
@@ -60,6 +60,7 @@ extern NSString * const qSettingCellVerticalPadding;
* General getter for a setting. When the result is a number, an NSNumber is returned.
*/
- (id)settingForKey:(NSString *)key;
+- (id)objectForKeyedSubscript:(id)key;
/**
* If you want to access CGFloat values, for example folding marker radius, use this method.
View
143 Qmind/QMAppSettings.m
@@ -55,7 +55,7 @@
static const NSUInteger qSpaceCharacter = 0x20;
static inline NSCharacterSet *single_key_charset(NSUInteger charCode) {
- return [NSCharacterSet characterSetWithRange:NSMakeRange(charCode, 1)];
+ return [NSCharacterSet characterSetWithRange:NSMakeRange(charCode, 1)];
}
@@ -70,109 +70,114 @@ @implementation QMAppSettings
#pragma mark Public
- (id)settingForKey:(NSString *)key {
- return self.settingsDict[key];
+ return self.settingsDict[key];
}
+- (id)objectForKeyedSubscript:(id)key {
+ return [self settingForKey:key];
+}
+
+
- (CGFloat)floatForKey:(NSString *)key {
- return (CGFloat) [self.settingsDict[key] floatValue];
+ return (CGFloat) [self.settingsDict[key] floatValue];
}
#pragma mark NSObject
- (id)init {
- self = [super init];
- if (self) {
- [self initSettingsDict];
- }
+ self = [super init];
+ if (self) {
+ [self initSettingsDict];
+ }
- return self;
+ return self;
}
#pragma mark Private
- (void)initSettingsDict {
- NSFont *defaultFont = [NSFont fontWithName:@"Helvetica" size:12.0];
- NSMutableDictionary *attrDict = [[NSMutableDictionary alloc] initWithCapacity:2];
- NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
+ NSFont *defaultFont = [NSFont fontWithName:@"Helvetica" size:12.0];
+ NSMutableDictionary *attrDict = [[NSMutableDictionary alloc] initWithCapacity:2];
+ NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
- NSFont *fontawesomeFont = [self fontawesomeFont];
+ NSFont *fontawesomeFont = [self fontawesomeFont];
- [style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
- [style setAlignment:NSLeftTextAlignment];
- [style setLineBreakMode:NSLineBreakByWordWrapping];
+ [style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
+ [style setAlignment:NSLeftTextAlignment];
+ [style setLineBreakMode:NSLineBreakByWordWrapping];
- attrDict[NSParagraphStyleAttributeName] = style;
- attrDict[NSFontAttributeName] = defaultFont;
+ attrDict[NSParagraphStyleAttributeName] = style;
+ attrDict[NSFontAttributeName] = defaultFont;
- _settingsDict = [[NSMutableDictionary alloc] initWithDictionary:@{
- qSettingDefaultFont : defaultFont,
- qSettingDefaultParagraphStyle : style,
- qSettingDefaultStringAttributeDict : attrDict,
- qSettingIconFont : [NSFont fontWithName:@"Apple Color Emoji" size:14],
- qSettingBackgroundColor : [NSColor whiteColor],
+ _settingsDict = [[NSMutableDictionary alloc] initWithDictionary:@{
+ qSettingDefaultFont : defaultFont,
+ qSettingDefaultParagraphStyle : style,
+ qSettingDefaultStringAttributeDict : attrDict,
+ qSettingIconFont : [NSFont fontWithName:@"Apple Color Emoji" size:14],
+ qSettingBackgroundColor : [NSColor whiteColor],
- qSettingInternodeHorizontalDistance : @30,
- qSettingInternodeVerticalDistance : @7.5,
- qSettingInternodeLineWidth : @1,
+ qSettingInternodeHorizontalDistance : @30,
+ qSettingInternodeVerticalDistance : @7.5,
+ qSettingInternodeLineWidth : @1,
- qSettingNodeEditMinWidth : @200,
- qSettingNodeEditMinHeight : @9,
- qSettingNodeEditMaxWidth : @640,
+ qSettingNodeEditMinWidth : @200,
+ qSettingNodeEditMinHeight : @9,
+ qSettingNodeEditMaxWidth : @640,
- qSettingNodeMinWidth : @100,
- qSettingNodeMinHeight : @14,
+ qSettingNodeMinWidth : @100,
+ qSettingNodeMinHeight : @14,
- qSettingFoldingMarkerRadius : @6,
- qSettingFoldingMarkerLineWidth : @1,
+ qSettingFoldingMarkerRadius : @6,
+ qSettingFoldingMarkerLineWidth : @1,
- qSettingMaxTextNodeWidth : @640,
- qSettingMaxRootCellTextWidth : @400,
+ qSettingMaxTextNodeWidth : @640,
+ qSettingMaxRootCellTextWidth : @400,
- qSettingMindMapViewMargin : @20,
+ qSettingMindMapViewMargin : @20,
- qSettingNodeFocusRingMargin : @0,
- qSettingNodeFocusRingBorderRadius : @2,
+ qSettingNodeFocusRingMargin : @0,
+ qSettingNodeFocusRingBorderRadius : @2,
- qSettingBezierControlPoint1 : @20,
- qSettingBezierControlPoint2 : @15,
+ qSettingBezierControlPoint1 : @20,
+ qSettingBezierControlPoint2 : @15,
- qSettingDefaultNewNodeWidth : @100,
+ qSettingDefaultNewNodeWidth : @100,
- qSettingCellHorizontalPadding : @3,
- qSettingCellVerticalPadding : @3,
+ qSettingCellHorizontalPadding : @3,
+ qSettingCellVerticalPadding : @3,
- qSettingIconTextDistance : @5,
- qSettingInterIconDistance : @3,
- qSettingIconDrawSize : @16,
+ qSettingIconTextDistance : @5,
+ qSettingInterIconDistance : @3,
+ qSettingIconDrawSize : @16,
- qSettingLinkIconFont: fontawesomeFont,
- qSettingLinkIconDrawSize : @16,
- qSettingLinkIconHorizontalMargin : @3,
+ qSettingLinkIconFont : fontawesomeFont,
+ qSettingLinkIconDrawSize : @16,
+ qSettingLinkIconHorizontalMargin : @3,
- qSettingNewChildNodeChars : single_key_charset(NSTabCharacter),
- qSettingNewLeftChildNodeChars : single_key_charset(NSBackTabCharacter),
- qSettingEditSelectedNodeChars : single_key_charset(NSCarriageReturnCharacter),
- qSettingNewSiblingNodeChars : single_key_charset(NSCarriageReturnCharacter),
- qSettingDeleteNodeChars : single_key_charset(NSDeleteFunctionKey),
- qSettingDeselectCell : single_key_charset(qEscCharacter),
- qSettingFoldingChars : single_key_charset(qSpaceCharacter),
- }];
+ qSettingNewChildNodeChars : single_key_charset(NSTabCharacter),
+ qSettingNewLeftChildNodeChars : single_key_charset(NSBackTabCharacter),
+ qSettingEditSelectedNodeChars : single_key_charset(NSCarriageReturnCharacter),
+ qSettingNewSiblingNodeChars : single_key_charset(NSCarriageReturnCharacter),
+ qSettingDeleteNodeChars : single_key_charset(NSDeleteFunctionKey),
+ qSettingDeselectCell : single_key_charset(qEscCharacter),
+ qSettingFoldingChars : single_key_charset(qSpaceCharacter),
+ }];
}
- (NSFont *)fontawesomeFont {
- NSString *fontPath = [[NSBundle bundleForClass:self.class] pathForResource:@"fontawesome-webfont" ofType:@"ttf"];
- NSData *fontData = [[NSData alloc] initWithContentsOfFile:fontPath];
+ NSString *fontPath = [[NSBundle bundleForClass:self.class] pathForResource:@"fontawesome-webfont" ofType:@"ttf"];
+ NSData *fontData = [[NSData alloc] initWithContentsOfFile:fontPath];
- CGDataProviderRef fontDataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef) fontData);
- CGFontRef cgFont = CGFontCreateWithDataProvider(fontDataProvider);
- CGDataProviderRelease(fontDataProvider);
+ CGDataProviderRef fontDataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef) fontData);
+ CGFontRef cgFont = CGFontCreateWithDataProvider(fontDataProvider);
+ CGDataProviderRelease(fontDataProvider);
- // if we pass NULL for attributes, we crash when releasing the font descriptor
- CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef) @{});
- CTFontRef ctFont = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
- CFRelease(fontDescriptor);
- CGFontRelease(cgFont);
+ // if we pass NULL for attributes, we crash when releasing the font descriptor
+ CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef) @{});
+ CTFontRef ctFont = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
+ CFRelease(fontDescriptor);
+ CGFontRelease(cgFont);
- NSFont *fontawesomeFont = (__bridge_transfer NSFont *) ctFont;
- return fontawesomeFont;
+ NSFont *fontawesomeFont = (__bridge_transfer NSFont *) ctFont;
+ return fontawesomeFont;
}
@end
View
17 Qmind/QMBorderedView.h
@@ -0,0 +1,17 @@
+/**
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
+ * http://qvacua.com
+ *
+ * See LICENSE
+ */
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface QMBorderedView : NSView
+
+@property CGFloat borderWidth;
+
+@end
View
60 Qmind/QMBorderedView.m
@@ -0,0 +1,60 @@
+/**
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
+ * http://qvacua.com
+ *
+ * See LICENSE
+ */
+
+#import "QMBorderedView.h"
+#import <Qkit/Qkit.h>
+
+
+@interface QMBorderedView ()
+
+@property NSBezierPath *borderPath;
+
+@end
+
+@implementation QMBorderedView
+
+#pragma mark NSView
+- (void)setFrame:(NSRect)frameRect {
+ self.borderPath = [NSBezierPath bezierPathWithRect:NewRectWithSize(0, 0, frameRect.size)];
+ self.borderPath.lineWidth = self.borderWidth;
+
+ [super setFrame:frameRect];
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+ [NSGraphicsContext saveGraphicsState];
+ {
+ [[NSColor grayColor] setStroke];
+ [[NSColor whiteColor] setFill];
+
+ [self.borderPath fill];
+ [self.borderPath stroke];
+ }
+ [NSGraphicsContext restoreGraphicsState];
+
+ [super drawRect:dirtyRect];
+}
+
+- (id)initWithFrame:(NSRect)frameRect {
+ self = [super initWithFrame:frameRect];
+ if (self) {
+ _borderWidth = 1;
+
+ _borderPath = [NSBezierPath bezierPathWithRect:frameRect];
+ _borderPath.lineWidth = _borderWidth;
+ }
+
+ return self;
+}
+
+- (BOOL)isFlipped {
+ return YES;
+}
+
+@end
View
14 Qmind/QMCellEditor.h
@@ -1,7 +1,8 @@
/**
- * Tae Won Ha
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
* http://qvacua.com
- * https://github.com/qvacua
*
* See LICENSE
*/
@@ -12,17 +13,20 @@
@class QMCell;
@class QMAppSettings;
@protocol QMCellEditorDelegate;
+@class QMBorderedView;
-@interface QMCellEditor : NSObject <NSTextViewDelegate>
+@interface QMCellEditor : NSObject <NSTextFieldDelegate>
@property (weak) QMAppSettings *settings;
-@property (weak) QMMindmapView *view;
@property (weak) id<QMCellEditorDelegate> delegate;
@property (readonly, weak) QMCell *currentlyEditedCell;
+@property (readonly, getter=isEditing) BOOL editing;
+
+@property (weak) QMMindmapView *view;
+@property (readonly) QMBorderedView *editorView;
- (void)beginEditStringValueForCell:(QMCell *)cellToEdit;
-- (BOOL)isEditing;
- (void)endEditing;
@end
View
249 Qmind/QMCellEditor.m
@@ -1,32 +1,33 @@
/**
- * Tae Won Ha
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
* http://qvacua.com
- * https://github.com/qvacua
*
* See LICENSE
*/
+#import <Qkit/Qkit.h>
#import "QMCellEditor.h"
#import "QMMindmapView.h"
#import "QMCell.h"
-#import <Qkit/Qkit.h>
#import "QMAppSettings.h"
+#import "QMBorderedView.h"
static NSInteger const qEscUnicode = 27;
+static const int qEditBoxBorderWidth = 1;
+
+static inline unichar current_event_char() {
+ return [[[NSApp currentEvent] characters] characterAtIndex:0];
+}
+
@interface QMCellEditor ()
@property (readwrite, weak) QMCell *currentlyEditedCell;
-
-@property NSUndoManager *undoManager;
@property BOOL editingCanceled;
-
-@property NSLayoutManager *layoutManager;
-@property NSTextStorage *textStorage;
-@property NSTextContainer *textContainer;
-@property NSTextView *textView;
-@property NSScrollView *scrollView;
+@property (readonly) NSTextField *textField;
@end
@@ -35,170 +36,148 @@ @implementation QMCellEditor
TB_MANUALWIRE(settings)
+#pragma mark Public
- (BOOL)isEditing {
- return self.currentlyEditedCell != nil;
+ return self.currentlyEditedCell != nil;
}
-- (NSSize)textViewSizeForCell:(QMCell *)cell {
- const NSSize textSize = cell.textSize;
+- (void)endEditing {
+ [self.view.window makeFirstResponder:self.view];
+}
- CGFloat defaultCellWidth = [self.settings floatForKey:qSettingNodeEditMinWidth];
- CGFloat widthForTextView = MAX(defaultCellWidth, textSize.width);
- CGFloat maxWidth = [self.settings floatForKey:qSettingNodeEditMaxWidth];
- widthForTextView = MIN(maxWidth, widthForTextView);
+- (NSSize)textFieldSizeForCell:(QMCell *)cell {
+ const NSSize textSize = cell.textSize;
- /**
- * when the default font size is 14, the text view size was ok, however, now with 12, it's too small, thus + 2
- */
- CGFloat heightForTextView = textSize.height + 2;
+ CGFloat defaultCellWidth = [self.settings floatForKey:qSettingNodeEditMinWidth];
+ CGFloat widthForTextView = MAX(defaultCellWidth, textSize.width);
+ CGFloat maxWidth = [self.settings floatForKey:qSettingNodeEditMaxWidth];
+ widthForTextView = MIN(maxWidth, widthForTextView);
- if ([cell.stringValue length] == 0) {
- NSFont *font = [self.settings settingForKey:qSettingDefaultFont];
- if (cell.font != nil) {
- font = cell.font;
- }
+ /**
+ * when the default font size is 14, the text view size was ok, however, now with 12, it's too small, thus + 2
+ */
+ CGFloat heightForTextView = textSize.height + 2;
- heightForTextView += [font pointSize];
+ if (cell.stringValue.length == 0) {
+ NSFont *font = self.settings[qSettingDefaultFont];
+ if (cell.font != nil) {
+ font = cell.font;
}
- return NewSize(widthForTextView, heightForTextView);
+ heightForTextView += font.pointSize;
+ }
+
+ return NewSize(widthForTextView, heightForTextView);
}
- (void)beginEditStringValueForCell:(QMCell *)cellToEdit {
- self.currentlyEditedCell = cellToEdit;
+ self.currentlyEditedCell = cellToEdit;
- [self.textStorage setAttributedString:cellToEdit.attributedString];
+ NSString *str = cellToEdit.stringValue;
+ self.textField.stringValue = str;
- if (self.textStorage.length == 0) {
- NSFont *font = [self.settings settingForKey:qSettingDefaultFont];
+ NSFont *font = self.settings[qSettingDefaultFont];
+ if (cellToEdit.font != nil) {
+ font = cellToEdit.font;
+ }
- if (cellToEdit.font != nil) {
- font = cellToEdit.font;
- }
+ self.textField.font = font;
- [self.textView setFont:font];
- }
+ NSPoint textOrigin = cellToEdit.textOrigin;
+ NSSize textFieldSize = [self textFieldSizeForCell:cellToEdit];
+ NSPoint containerOrigin = NewPoint(
+ textOrigin.x - qEditBoxBorderWidth - 2,
+ textOrigin.y - qEditBoxBorderWidth - 1
+ ); // using heuristic such that the text in the text field is at the same position as the node text
+ NSSize containerSize = NewSize(textFieldSize.width + qEditBoxBorderWidth, textFieldSize.height + qEditBoxBorderWidth);
- NSSize textViewSize = [self textViewSizeForCell:cellToEdit];
- NSSize scrollViewSize = [NSScrollView frameSizeForContentSize:textViewSize hasHorizontalScroller:NO hasVerticalScroller:NO borderType:NSBezelBorder];
+ [self.editorView setFrame:NewRectWithOriginAndSize(containerOrigin, containerSize)];
- [self.scrollView setFrame:NewRectWithSize(0, 0, scrollViewSize)];
+ self.editorView.hidden = NO;
+ [self.view scrollRectToVisible:self.editorView.frame];
+ [self.view.window makeFirstResponder:self.textField];
- NSPoint textOrigin = cellToEdit.textOrigin;
- NSPoint containerOrigin = NewPoint(textOrigin.x - CONTAINER_BORDER_WIDTH, textOrigin.y - CONTAINER_BORDER_WIDTH);
+ [self.view setNeedsDisplay:YES];
+}
- [self.scrollView setFrameOrigin:containerOrigin];
+#pragma mark NSControlSubclassNotifications
+- (void)controlTextDidEndEditing:(NSNotification *)notification {
+ NSAttributedString *attrString = [[NSAttributedString alloc] initWithAttributedString:self.textField.attributedStringValue];
- [self.view addSubview:self.scrollView];
- [self.view scrollRectToVisible:self.scrollView.frame];
- [self.view.window makeFirstResponder:self.textView];
+ if (self.editingCanceled) {
- [self.view setNeedsDisplay:YES];
-}
+ [self.delegate editingCancelledWithString:attrString forCell:self.currentlyEditedCell];
-- (void)textDidEndEditing:(NSNotification *)notification {
- NSAttributedString *const attrString = [[NSAttributedString alloc] initWithAttributedString:self.textStorage];
+ } else {
- if (self.editingCanceled) {
- [self.delegate editingCancelledWithString:attrString forCell:self.currentlyEditedCell];
+ unichar character;
+ NSEventType eventType = [[NSApp currentEvent] type];
+ if (eventType == NSKeyDown || eventType == NSKeyUp) {
+ character = current_event_char();
} else {
- NSEventType eventType = [[NSApp currentEvent] type];
-
- unichar character;
- if (eventType == NSKeyDown || eventType == NSKeyUp) {
- character = [[[NSApp currentEvent] characters] characterAtIndex:0];
- } else {
- character = NSCarriageReturnCharacter;
- }
-
- [self.delegate editingEndedWithString:attrString forCell:self.currentlyEditedCell byChar:character];
+ character = NSCarriageReturnCharacter;
}
- self.editingCanceled = NO;
- self.currentlyEditedCell = nil;
+ [self.delegate editingEndedWithString:attrString forCell:self.currentlyEditedCell byChar:character];
- [self.scrollView removeFromSuperview];
+ }
- [self.undoManager removeAllActions];
+ self.editingCanceled = NO;
+ self.currentlyEditedCell = nil;
+ self.editorView.hidden = YES;
- [self.view.window makeFirstResponder:self.view];
- [self.view setNeedsDisplay:YES];
+ [self.view.window makeFirstResponder:self.view];
+ [self.view setNeedsDisplay:YES];
}
-- (NSArray *)textView:(NSTextView *)textView
- completions:(NSArray *)words
- forPartialWordRange:(NSRange)charRange
- indexOfSelectedItem:(NSInteger *)index {
-
- unichar character = [[[NSApp currentEvent] characters] characterAtIndex:0];
-
- if (character == qEscUnicode) {
- self.editingCanceled = YES;
- [self.view.window makeFirstResponder:self.view];
-
- return nil;
- }
+#pragma mark NSControlTextEditingDelegate
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
+ if (commandSelector == @selector(insertNewline:)) {
+ log4Debug(@"insertNewLine:");
+ }
- return words;
+ return NO;
}
-- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
- if (commandSelector == @selector(insertNewline:)) {
- log4Debug(@"insertNewLine:");
- }
-
- return NO;
-}
+- (NSArray *)control:(NSControl *)control
+ textView:(NSTextView *)textView
+ completions:(NSArray *)words
+ forPartialWordRange:(NSRange)charRange
+ indexOfSelectedItem:(NSInteger *)index {
-- (NSUndoManager *)undoManagerForTextView:(NSTextView *)view {
- return self.undoManager;
-}
+ if (current_event_char() == qEscUnicode) {
+ self.editingCanceled = YES;
+ [self.view.window makeFirstResponder:self.view];
-- (id)init {
- self = [super init];
- if (self) {
- [[TBContext sharedContext] autowireSeed:self];
-
- _editingCanceled = NO;
-
- _undoManager = [[NSUndoManager alloc] init];
-
- _layoutManager = [[NSLayoutManager alloc] init];
- _textStorage = [[NSTextStorage alloc] init];
- _textContainer = [[NSTextContainer alloc] init];
-
- [_textContainer setLineFragmentPadding:0.0];
- [_textContainer setWidthTracksTextView:YES];
- [_textContainer setContainerSize:NewSize(0, MAX_CGFLOAT)];
- [_textStorage addLayoutManager:_layoutManager];
- [_layoutManager addTextContainer:_textContainer];
-
- _textView = [[NSTextView alloc] initWithFrame:NewRect(0, 0, 100, 24) textContainer:_textContainer];
- _scrollView = [[NSScrollView alloc] initWithFrame:NewRect(0, 0, 150, 40)];
-
- [_textView setDelegate:self];
- [_textView setAllowsUndo:YES];
- [_textView setEditable:YES];
- [_textView setTextContainerInset:NSZeroSize];
- [_textView setVerticallyResizable:YES];
- [_textView setHorizontallyResizable:YES];
- [_textView setRichText:NO];
- [_textView setFieldEditor:YES];
- [_textView setContinuousSpellCheckingEnabled:YES];
- [_textView setAutoresizingMask:NSViewWidthSizable];
- [_textView setMaxSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
-
- [_scrollView setDocumentView:_textView];
- [_scrollView setBorderType:NSBezelBorder];
- [_scrollView setHasHorizontalScroller:NO];
- [_scrollView setHasVerticalScroller:NO];
- }
+ return nil;
+ }
- return self;
+ return words;
}
-- (void)endEditing {
- [self.view.window makeFirstResponder:self.view];
+#pragma mark NSObject
+- (id)init {
+ self = [super init];
+ if (self) {
+ [[TBContext sharedContext] autowireSeed:self];
+
+ _editingCanceled = NO;
+
+ _textField = [[NSTextField alloc] initWithFrame:NewRect(1, 1, 20, 20)];
+ _textField.delegate = self;
+// _textField.allowsEditingTextAttributes = YES;
+ _textField.focusRingType = NSFocusRingTypeNone;
+ _textField.bordered = NO;
+ _textField.bezeled = NO;
+ _textField.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+
+ _editorView = [[QMBorderedView alloc] initWithFrame:NewRect(0, 0, 22, 22)];
+ _editorView.borderWidth = qEditBoxBorderWidth;
+ _editorView.autoresizesSubviews = YES;
+ [_editorView addSubview:_textField];
+ }
+
+ return self;
}
@end
View
5 Qmind/QMMindmapView.h
@@ -1,7 +1,8 @@
/**
- * Tae Won Ha
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
* http://qvacua.com
- * https://github.com/qvacua
*
* See LICENSE
*/
View
1,877 Qmind/QMMindmapView.m
@@ -1,7 +1,8 @@
/**
- * Tae Won Ha
+ * Tae Won Ha — @hataewon
+ *
+ * http://taewon.de
* http://qvacua.com
- * https://github.com/qvacua
*
* See LICENSE
*/
@@ -21,6 +22,8 @@
#import "QMNode.h"
#import "QMIcon.h"
#import "QMCellPropertiesManager.h"
+#import "QMBorderedView.h"
+
static const CGFloat qZoomScrollWheelStep = 0.25;
@@ -31,15 +34,15 @@
static const NSSize qSizeOfBadgeCircle = {20., 20.};
static inline CGFloat area(NSRect rect) {
- return rect.size.width * rect.size.height;
+ return rect.size.width * rect.size.height;
}
static inline BOOL sign(CGFloat x) {
- return (BOOL) ((x > 0) - (x < 0));
+ return (BOOL) ((x > 0) - (x < 0));
}
static inline BOOL modifier_check(NSUInteger value, NSUInteger modifier) {
- return (value & modifier) == modifier;
+ return (value & modifier) == modifier;
}
@interface QMMindmapView ()
@@ -57,290 +60,290 @@ @interface QMMindmapView ()
@implementation QMMindmapView
-TB_MANUALWIRE(cellSelector)
TB_MANUALWIRE(cellLayoutManager)
TB_MANUALWIRE(settings)
TB_MANUALWIRE(uiDrawer)
+TB_MANUALWIRE(cellSelector)
#pragma mark Public
- (void)endEditing {
- if ([self.cellEditor isEditing]) {
- [self.cellEditor endEditing];
- }
+ if (self.cellEditor.editing) {
+ [self.cellEditor endEditing];
+ }
}
- (NSPoint)middlePointOfVisibleRect {
- NSRect visibleRect = [self visibleRect];
- CGPoint origin = visibleRect.origin;
- CGSize size = visibleRect.size;
+ NSRect visibleRect = self.visibleRect;
+ CGPoint origin = visibleRect.origin;
+ CGSize size = visibleRect.size;
- return NewPoint(origin.x + size.width / 2, origin.y + size.height / 2);
+ return NewPoint(origin.x + size.width / 2, origin.y + size.height / 2);
}
- (void)insertChild {
- NSArray *const selCells = [self.cellStateManager selectedCells];
- if ([selCells count] > 1) {
- return;
- }
+ NSArray *const selCells = self.cellStateManager.selectedCells;
+ if (selCells.count > 1) {
+ return;
+ }
- QMCell *selCell;
- if (![self.cellStateManager hasSelectedCells]) {
- selCell = self.rootCell;
- } else {
- selCell = [selCells lastObject];
- }
+ QMCell *selCell;
+ if (!self.cellStateManager.hasSelectedCells) {
+ selCell = self.rootCell;
+ } else {
+ selCell = selCells.lastObject;
+ }
- if ([selCell isFolded]) {
- [self toggleFoldingOfSelectedCell];
- }
- [self.dataSource mindmapView:self addNewChildToItem:selCell.identifier atIndex:[selCell countOfChildren]];
+ if (selCell.folded) {
+ [self toggleFoldingOfSelectedCell];
+ }
+ [self.dataSource mindmapView:self addNewChildToItem:selCell.identifier atIndex:[selCell countOfChildren]];
}
- (void)insertLeftChild {
- NSArray *const selCells = [self.cellStateManager selectedCells];
- if ([selCells count] > 1) {
- return;
- }
-
- if (![self.cellStateManager hasSelectedCells]) {
- [self.dataSource mindmapView:self addNewLeftChildToItem:self.rootCell.identifier atIndex:[self.rootCell countOfLeftChildren]];
- return;
- }
-
- QMCell *const selCell = [selCells lastObject];
- if ([selCell isRoot]) {
- [self.dataSource mindmapView:self addNewLeftChildToItem:self.rootCell.identifier atIndex:[self.rootCell countOfLeftChildren]];
- } else {
- if ([selCell isFolded]) {
- [self toggleFoldingOfSelectedCell];
- }
- [self.dataSource mindmapView:self addNewChildToItem:selCell.identifier atIndex:[selCell countOfChildren]];
+ NSArray *const selCells = self.cellStateManager.selectedCells;
+ if (selCells.count > 1) {
+ return;
+ }
+
+ if (!self.cellStateManager.hasSelectedCells) {
+ [self.dataSource mindmapView:self addNewLeftChildToItem:self.rootCell.identifier atIndex:[self.rootCell countOfLeftChildren]];
+ return;
+ }
+
+ QMCell *const selCell = selCells.lastObject;
+ if (selCell.root) {
+ [self.dataSource mindmapView:self addNewLeftChildToItem:self.rootCell.identifier atIndex:[self.rootCell countOfLeftChildren]];
+ } else {
+ if (selCell.folded) {
+ [self toggleFoldingOfSelectedCell];
}
+ [self.dataSource mindmapView:self addNewChildToItem:selCell.identifier atIndex:[selCell countOfChildren]];
+ }
}
- (void)insertPreviousSibling {
- if (![self.cellStateManager hasSelectedCells]) {
- return;
- }
+ if (![self.cellStateManager hasSelectedCells]) {
+ return;
+ }
- NSArray *const selCells = [self.cellStateManager selectedCells];
- if ([selCells count] > 1) {
- return;
- }
+ NSArray *const selCells = [self.cellStateManager selectedCells];
+ if ([selCells count] > 1) {
+ return;
+ }
- QMCell *selCell = [selCells lastObject];
- if ([selCell isRoot]) {
- return;
- }
+ QMCell *selCell = [selCells lastObject];
+ if ([selCell isRoot]) {
+ return;
+ }
- [self.dataSource mindmapView:self addNewPreviousSiblingToItem:selCell.identifier];
+ [self.dataSource mindmapView:self addNewPreviousSiblingToItem:selCell.identifier];
}
- (void)insertNextSibling {
- if (![self.cellStateManager hasSelectedCells]) {
- return;
- }
+ if (![self.cellStateManager hasSelectedCells]) {
+ return;
+ }
- NSArray *const selCells = [self.cellStateManager selectedCells];
- if ([selCells count] > 1) {
- return;
- }
+ NSArray *const selCells = [self.cellStateManager selectedCells];
+ if ([selCells count] > 1) {
+ return;
+ }
- QMCell *selCell = [selCells lastObject];
- if ([selCell isRoot]) {
- return;
- }
+ QMCell *selCell = [selCells lastObject];
+ if ([selCell isRoot]) {
+ return;
+ }
- [self.dataSource mindmapView:self addNewNextSiblingToItem:selCell.identifier];
+ [self.dataSource mindmapView:self addNewNextSiblingToItem:selCell.identifier];
}
- (NSArray *)selectedCells {
- return self.cellStateManager.selectedCells;
+ return self.cellStateManager.selectedCells;
}
- (void)clearSelection {
- [self.cellStateManager clearSelection];
+ [self.cellStateManager clearSelection];
}
- (BOOL)rootCellSelected {
- if (![self.cellStateManager hasSelectedCells]) {
- return NO;
- }
+ if (![self.cellStateManager hasSelectedCells]) {
+ return NO;
+ }
- if ([[[self.cellStateManager selectedCells] lastObject] identifier] == self.rootCell.identifier) {
- return YES;
- }
+ if ([[[self.cellStateManager selectedCells] lastObject] identifier] == self.rootCell.identifier) {
+ return YES;
+ }
- return NO;
+ return NO;
}
- (void)zoomToActualSize {
- CGFloat currentScale = ([self convertSize:qUnitSize toView:nil]).width;
- [self zoomByFactor:1. / currentScale withFixedPoint:[self middlePointOfVisibleRect]];
+ CGFloat currentScale = ([self convertSize:qUnitSize toView:nil]).width;
+ [self zoomByFactor:1. / currentScale withFixedPoint:[self middlePointOfVisibleRect]];
}
- (void)updateCanvasSize {
- if (self.cellEditor.isEditing) {
- [self.cellEditor endEditing];
- }
+ if (self.cellEditor.isEditing) {
+ [self.cellEditor endEditing];
+ }
- [self setFrameSize:[self scaledBoundsSizeWithParentSize:self.superview.frame.size]];
- [self setNeedsDisplay:YES];
+ [self setFrameSize:[self scaledBoundsSizeWithParentSize:self.superview.frame.size]];
+ [self setNeedsDisplay:YES];
}
- (void)updateCanvasWithOldClipViewOrigin:(NSPoint)oldClipViewOrigin oldClipViewSize:(NSSize)oldClipViewSize oldCenterInView:(NSPoint)oldCenterInView {
- NSPoint oldMapOrigin = [self rootCellOriginForParentSize:oldClipViewSize];
- NSSize oldDist = NewSize(oldCenterInView.x - oldClipViewOrigin.x, oldCenterInView.y - oldClipViewOrigin.y);
+ NSPoint oldMapOrigin = [self rootCellOriginForParentSize:oldClipViewSize];
+ NSSize oldDist = NewSize(oldCenterInView.x - oldClipViewOrigin.x, oldCenterInView.y - oldClipViewOrigin.y);
- [self updateCanvasSize];
+ [self updateCanvasSize];
- NSClipView *clipView = self.enclosingScrollView.contentView;
- NSSize newParentSize = [self convertSize:clipView.frame.size fromView:clipView];
- NSPoint newMapOrigin = [self rootCellOriginForParentSize:newParentSize];
+ NSClipView *clipView = self.enclosingScrollView.contentView;
+ NSSize newParentSize = [self convertSize:clipView.frame.size fromView:clipView];
+ NSPoint newMapOrigin = [self rootCellOriginForParentSize:newParentSize];
- NSSize deltaMapOrigin = NewSize(oldMapOrigin.x - newMapOrigin.x, oldMapOrigin.y - newMapOrigin.y);
- NSPoint newScrollPt = NewPoint(oldCenterInView.x - deltaMapOrigin.width - oldDist.width, oldCenterInView.y - deltaMapOrigin.height - oldDist.height);
+ NSSize deltaMapOrigin = NewSize(oldMapOrigin.x - newMapOrigin.x, oldMapOrigin.y - newMapOrigin.y);
+ NSPoint newScrollPt = NewPoint(oldCenterInView.x - deltaMapOrigin.width - oldDist.width, oldCenterInView.y - deltaMapOrigin.height - oldDist.height);
- [self scrollPoint:newScrollPt];
- [self setNeedsDisplay:YES];
+ [self scrollPoint:newScrollPt];
+ [self setNeedsDisplay:YES];
}
- (void)zoomByFactor:(CGFloat)factor {
- [self zoomByFactor:factor withFixedPoint:[self middlePointOfVisibleRect]];
+ [self zoomByFactor:factor withFixedPoint:[self middlePointOfVisibleRect]];
}
- (void)updateFontOfSelectedCellsToFont:(NSFont *)newFont {
- if (!self.cellStateManager.hasSelectedCells) {
- return;
- }
+ if (!self.cellStateManager.hasSelectedCells) {
+ return;
+ }
- for (QMCell *cell in self.cellStateManager.selectedCells) {
- cell.font = newFont;
- }
+ for (QMCell *cell in self.cellStateManager.selectedCells) {
+ cell.font = newFont;
+ }
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
- (void)toggleFoldingOfSelectedCell {
- [self.dataSource mindmapView:self toggleFoldingForItem:[[self.cellStateManager selectedCells][0] identifier]];
+ [self.dataSource mindmapView:self toggleFoldingForItem:[[self.cellStateManager selectedCells][0] identifier]];
}
- (BOOL)hasSelectedCells {
- return self.cellStateManager.hasSelectedCells;
+ return self.cellStateManager.hasSelectedCells;
}
- (BOOL)cellIsSelected:(QMCell *)cell {
- return [self.cellStateManager cellIsSelected:cell];
+ return [self.cellStateManager cellIsSelected:cell];
}
- (BOOL)cellIsCurrentlyEdited:(QMCell *)cell {
- return self.cellEditor.currentlyEditedCell == cell;
+ return self.cellEditor.currentlyEditedCell == cell;
}
- (void)updateCellWithIdentifier:(id)identifier {
- QMCell *cellToUpdate = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
+ QMCell *cellToUpdate = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
- NSString *const stringValueOfItem = [self.dataSource mindmapView:self stringValueOfItem:identifier];
- if (![cellToUpdate.stringValue isEqualToString:stringValueOfItem]) {
- cellToUpdate.stringValue = stringValueOfItem;
- }
+ NSString *const stringValueOfItem = [self.dataSource mindmapView:self stringValueOfItem:identifier];
+ if (![cellToUpdate.stringValue isEqualToString:stringValueOfItem]) {
+ cellToUpdate.stringValue = stringValueOfItem;
+ }
- NSFont *const fontOfItem = [self.dataSource mindmapView:self fontOfItem:identifier];
- if (![cellToUpdate.font isEqual:fontOfItem]) {
- cellToUpdate.font = fontOfItem;
- }
+ NSFont *const fontOfItem = [self.dataSource mindmapView:self fontOfItem:identifier];
+ if (![cellToUpdate.font isEqual:fontOfItem]) {
+ cellToUpdate.font = fontOfItem;
+ }
- NSUInteger countOfOldIcons = [cellToUpdate.icons count];
- for (int i = 0; i < countOfOldIcons; i++) {
- [cellToUpdate removeObjectFromIconsAtIndex:0];
- }
- [self.cellPropertiesManager fillIconsOfCell:cellToUpdate];
+ NSUInteger countOfOldIcons = [cellToUpdate.icons count];
+ for (int i = 0; i < countOfOldIcons; i++) {
+ [cellToUpdate removeObjectFromIconsAtIndex:0];
+ }
+ [self.cellPropertiesManager fillIconsOfCell:cellToUpdate];
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
- (void)updateCellFoldingWithIdentifier:(id)identifier {
- QMCell *cellToUpdate = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
- BOOL folded = [self.dataSource mindmapView:self isItemFolded:identifier];
- [cellToUpdate setFolded:folded];
-
- NSRect visibleRect = [self visibleRect];
- BOOL cellVisible = NO;
- if (NSIntersectsRect(visibleRect, cellToUpdate.frame)) {
- cellVisible = YES;
- }
-
- if (cellVisible) {
- NSPoint cellOrigin = cellToUpdate.origin;
- NSPoint visibleOrigin = visibleRect.origin;
- NSSize distFromVisibleRect = NewSize(cellOrigin.x - visibleOrigin.x, cellOrigin.y - visibleOrigin.y);
-
- [self updateCanvasSize];
- QMCell *const newCell = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
+ QMCell *cellToUpdate = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
+ BOOL folded = [self.dataSource mindmapView:self isItemFolded:identifier];
+ [cellToUpdate setFolded:folded];
- NSPoint newCellOrigin = newCell.origin;
- NSPoint newVisibleRectOrigin = NewPoint(newCellOrigin.x - distFromVisibleRect.width, newCellOrigin.y - distFromVisibleRect.height);
+ NSRect visibleRect = [self visibleRect];
+ BOOL cellVisible = NO;
+ if (NSIntersectsRect(visibleRect, cellToUpdate.frame)) {
+ cellVisible = YES;
+ }
- // [self scrollPoint:newVisibleRectOrigin] animates the scrolling, we don't want that
- NSPoint newVisibleRectOriginInClipView = [self convertPoint:newVisibleRectOrigin toView:self.superview];
- [self.enclosingScrollView.contentView setBoundsOrigin:newVisibleRectOriginInClipView];
- [self setNeedsDisplay:YES];
-
- return;
- }
+ if (cellVisible) {
+ NSPoint cellOrigin = cellToUpdate.origin;
+ NSPoint visibleOrigin = visibleRect.origin;
+ NSSize distFromVisibleRect = NewSize(cellOrigin.x - visibleOrigin.x, cellOrigin.y - visibleOrigin.y);
[self updateCanvasSize];
QMCell *const newCell = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
- [self scrollRectToVisible:newCell.familyFrame];
- [self scrollRectToVisible:newCell.frame];
+ NSPoint newCellOrigin = newCell.origin;
+ NSPoint newVisibleRectOrigin = NewPoint(newCellOrigin.x - distFromVisibleRect.width, newCellOrigin.y - distFromVisibleRect.height);
+ // [self scrollPoint:newVisibleRectOrigin] animates the scrolling, we don't want that
+ NSPoint newVisibleRectOriginInClipView = [self convertPoint:newVisibleRectOrigin toView:self.superview];
+ [self.enclosingScrollView.contentView setBoundsOrigin:newVisibleRectOriginInClipView];
[self setNeedsDisplay:YES];
+
+ return;
+ }
+
+ [self updateCanvasSize];
+ QMCell *const newCell = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
+
+ [self scrollRectToVisible:newCell.familyFrame];
+ [self scrollRectToVisible:newCell.frame];
+
+ [self setNeedsDisplay:YES];
}
- (void)updateCellFamilyForRemovalWithIdentifier:(id)identifier {
- NSArray *idArray = [self allChildrenIdentifierOfIdentifier:identifier];
+ NSArray *idArray = [self allChildrenIdentifierOfIdentifier:identifier];
- QMCell *parentCell = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
- QMCell *cellToDel;
- if (idArray.count == 0) {
- cellToDel = parentCell.children.lastObject;
- } else {
- for (QMCell *cell in parentCell.children) {
- if (![idArray containsObject:cell.identifier]) {
- cellToDel = cell;
- break;
- }
- }
+ QMCell *parentCell = [self.cellSelector cellWithIdentifier:identifier fromParentCell:self.rootCell];
+ QMCell *cellToDel;
+ if (idArray.count == 0) {
+ cellToDel = parentCell.children.lastObject;
+ } else {
+ for (QMCell *cell in parentCell.children) {
+ if (![idArray containsObject:cell.identifier]) {
+ cellToDel = cell;
+ break;
+ }
}
+ }
- [parentCell removeChild:cellToDel];
+ [parentCell removeChild:cellToDel];
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
- (void)updateLeftCellFamilyForRemovalWithIdentifier:(id)identifier {
- NSArray *idArray = [self leftChildrenIdentifierOfRootCell];
+ NSArray *idArray = [self leftChildrenIdentifierOfRootCell];
- QMCell *cellToDel;
- if (idArray.count == 0) {
- cellToDel = [self.rootCell.leftChildren lastObject];
- } else {
- for (QMCell *cell in self.rootCell.leftChildren) {
- if (![idArray containsObject:cell.identifier]) {
- cellToDel = cell;
- break;
- }
- }
+ QMCell *cellToDel;
+ if (idArray.count == 0) {
+ cellToDel = [self.rootCell.leftChildren lastObject];
+ } else {
+ for (QMCell *cell in self.rootCell.leftChildren) {
+ if (![idArray containsObject:cell.identifier]) {
+ cellToDel = cell;
+ break;
+ }
}
+ }
- [self.rootCell removeChild:cellToDel];
+ [self.rootCell removeChild:cellToDel];
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
/*
@@ -348,12 +351,12 @@ - (void)updateLeftCellFamilyForRemovalWithIdentifier:(id)identifier {
we only test the begin edit part. We are being to lazy here...
*/
- (void)updateCellFamily:(id)parentId forNewCell:(id)childId {
- [self updateCellFamilyForInsertionWithIdentifier:parentId];
- QMCell *cellToEdit = [self.cellSelector cellWithIdentifier:childId fromParentCell:self.rootCell];
+ [self updateCellFamilyForInsertionWithIdentifier:parentId];
+ QMCell *cellToEdit = [self.cellSelector cellWithIdentifier:childId fromParentCell:self.rootCell];
- [self.cellStateManager clearSelection];
- [self.cellStateManager addCellToSelection:cellToEdit modifier:0];
- [self editCell:cellToEdit];
+ [self.cellStateManager clearSelection];
+ [self.cellStateManager addCellToSelection:cellToEdit modifier:0];
+ [self editCell:cellToEdit];
}
/*
@@ -361,1095 +364,1103 @@ - (void)updateCellFamily:(id)parentId forNewCell:(id)childId {
we only test the begin edit part... We are being to lazy here...
*/
- (void)updateLeftCellFamily:(id)parentId forNewCell:(id)childId {
- [self updateLeftCellFamilyForInsertionWithIdentifier:parentId];
- QMCell *cellToEdit = [self.cellSelector cellWithIdentifier:childId fromParentCell:self.rootCell];
+ [self updateLeftCellFamilyForInsertionWithIdentifier:parentId];
+ QMCell *cellToEdit = [self.cellSelector cellWithIdentifier:childId fromParentCell:self.rootCell];
- [self.cellStateManager clearSelection];
- [self.cellStateManager addCellToSelection:cellToEdit modifier:0];
- [self editCell:cellToEdit];
+ [self.cellStateManager clearSelection];
+ [self.cellStateManager addCellToSelection:cellToEdit modifier:0];
+ [self editCell:cellToEdit];
}
- (void)updateCellFamilyForInsertionWithIdentifier:(id)parentId {
- NSArray *idArray = [self leftChildrenIdentifierOfIdentifier:parentId];
- QMCell *parentCell = [self.cellSelector cellWithIdentifier:parentId fromParentCell:self.rootCell];
- NSUInteger maxIndex = [idArray count] - 1;
-
- __block NSUInteger indexToInsert;
- __block id itemToInsert;
+ NSArray *idArray = [self leftChildrenIdentifierOfIdentifier:parentId];
+ QMCell *parentCell = [self.cellSelector cellWithIdentifier:parentId fromParentCell:self.rootCell];
+ NSUInteger maxIndex = [idArray count] - 1;
+
+ __block NSUInteger indexToInsert;
+ __block id itemToInsert;
+
+ if (parentCell.countOfChildren == 0) {
+ indexToInsert = 0;
+ itemToInsert = [idArray lastObject];
+ } else {
+ [idArray enumerateObjectsUsingBlock:^(id item, NSUInteger index, BOOL *stop) {
+ if (index == maxIndex) {
+ indexToInsert = index;
+ itemToInsert = item;
+ *stop = YES;
+ return;
+ }
- if (parentCell.countOfChildren == 0) {
- indexToInsert = 0;
- itemToInsert = [idArray lastObject];
- } else {
- [idArray enumerateObjectsUsingBlock:^(id item, NSUInteger index, BOOL *stop) {
- if (index == maxIndex) {
- indexToInsert = index;
- itemToInsert = item;
- *stop = YES;
- return;
- }
-
- if ([[parentCell objectInChildrenAtIndex:index] identifier] != item) {
- indexToInsert = index;
- itemToInsert = item;
- *stop = YES;
- return;
- }
- }];
- }
+ if ([[parentCell objectInChildrenAtIndex:index] identifier] != item) {
+ indexToInsert = index;
+ itemToInsert = item;
+ *stop = YES;
+ return;
+ }
+ }];
+ }
- const BOOL parentIsLeft = [self.dataSource mindmapView:self isItemLeft:parentId];
+ const BOOL parentIsLeft = [self.dataSource mindmapView:self isItemLeft:parentId];
- QMCell *cellToInsert = [[QMCell alloc] initWithView:self];
- cellToInsert.left = parentIsLeft;
- [self.cellPropertiesManager fillCellPropertiesWithIdentifier:itemToInsert cell:cellToInsert];
- [self.cellPropertiesManager fillAllChildrenWithIdentifier:itemToInsert cell:cellToInsert];
+ QMCell *cellToInsert = [[QMCell alloc] initWithView:self];
+ cellToInsert.left = parentIsLeft;
+ [self.cellPropertiesManager fillCellPropertiesWithIdentifier:itemToInsert cell:cellToInsert];
+ [self.cellPropertiesManager fillAllChildrenWithIdentifier:itemToInsert cell:cellToInsert];
- [parentCell insertObject:cellToInsert inChildrenAtIndex:indexToInsert];
+ [parentCell insertObject:cellToInsert inChildrenAtIndex:indexToInsert];
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
- (void)updateLeftCellFamilyForInsertionWithIdentifier:(id)identifier {
- NSArray *leftIdArray = [self leftChildrenIdentifierOfRootCell];
-
- NSUInteger maxIndex = [leftIdArray count] - 1;
-
- __block NSUInteger indexToInsert;
- __block id itemToInsert;
+ NSArray *leftIdArray = [self leftChildrenIdentifierOfRootCell];
+
+ NSUInteger maxIndex = [leftIdArray count] - 1;
+
+ __block NSUInteger indexToInsert;
+ __block id itemToInsert;
+
+ if (self.rootCell.countOfChildren == 0) {
+ indexToInsert = 0;
+ itemToInsert = [leftIdArray lastObject];
+ } else {
+ [leftIdArray enumerateObjectsUsingBlock:^(id item, NSUInteger index, BOOL *stop) {
+ if (index == maxIndex) {
+ indexToInsert = index;
+ itemToInsert = item;
+ *stop = YES;
+ return;
+ }
- if (self.rootCell.countOfChildren == 0) {
- indexToInsert = 0;
- itemToInsert = [leftIdArray lastObject];
- } else {
- [leftIdArray enumerateObjectsUsingBlock:^(id item, NSUInteger index, BOOL *stop) {
- if (index == maxIndex) {
- indexToInsert = index;
- itemToInsert = item;
- *stop = YES;
- return;
- }
-
- if ([[self.rootCell objectInLeftChildrenAtIndex:index] identifier] != item) {
- indexToInsert = index;
- itemToInsert = item;
- *stop = YES;
- return;
- }
- }];
- }
+ if ([[self.rootCell objectInLeftChildrenAtIndex:index] identifier] != item) {
+ indexToInsert = index;
+ itemToInsert = item;
+ *stop = YES;
+ return;
+ }
+ }];
+ }
- QMCell *cellToInsert = [[QMCell alloc] initWithView:self];
- cellToInsert.left = YES;
+ QMCell *cellToInsert = [[QMCell alloc] initWithView:self];
+ cellToInsert.left = YES;
- [self.cellPropertiesManager fillCellPropertiesWithIdentifier:itemToInsert cell:cellToInsert];
- [self.cellPropertiesManager fillAllChildrenWithIdentifier:itemToInsert cell:cellToInsert];
+ [self.cellPropertiesManager fillCellPropertiesWithIdentifier:itemToInsert cell:cellToInsert];
+ [self.cellPropertiesManager fillAllChildrenWithIdentifier:itemToInsert cell:cellToInsert];
- [self.rootCell insertObject:cellToInsert inLeftChildrenAtIndex:indexToInsert];
+ [self.rootCell insertObject:cellToInsert inLeftChildrenAtIndex:indexToInsert];
- [self updateCanvasSize];
- [self setNeedsDisplay:YES];
+ [self updateCanvasSize];
+ [self setNeedsDisplay:YES];
}
- (void)initMindmapViewWithDataSource:(id <QMMindmapViewDataSource>)aDataSource {
- _currentScale = NewSize(1, 1);
- _dataSource = aDataSource;
- _cellPropertiesManager = [[QMCellPropertiesManager alloc] initWithMindmapView:self];
+ _currentScale = NewSize(1, 1);
+ _dataSource = aDataSource;
+ _cellPropertiesManager = [[QMCellPropertiesManager alloc] initWithMindmapView:self];
- _rootCell = (QMRootCell *) [self.cellPropertiesManager cellWithParent:nil itemOfParent:nil];
- [self registerForDraggedTypes:@[qNodeUti]];
+ _rootCell = (QMRootCell *) [self.cellPropertiesManager cellWithParent:nil itemOfParent:nil];
+ [self registerForDraggedTypes:@[qNodeUti]];
- NSSize parentSize = self.superview.frame.size;
+ NSSize parentSize = self.superview.frame.size;
- [self setFrameSize:[self scaledBoundsSizeWithParentSize:parentSize]];
- [self scrollToCenter];
- [self setNeedsDisplay:YES];
+ [self setFrameSize:[self scaledBoundsSizeWithParentSize:parentSize]];
+ [self scrollToCenter];
+ [self setNeedsDisplay:YES];
}
#pragma mark QMCellEditorDelegate
- (void)editingEndedWithString:(NSAttributedString *)newAttrStr forCell:(QMCell *)editedCell byChar:(unichar)character {
- id identifier = editedCell.identifier;
+ id identifier = editedCell.identifier;
- [self.dataSource mindmapView:self editingEndedForItem:identifier];
+ [self.dataSource mindmapView:self editingEndedForItem:identifier];
- NSString *const newString = [newAttrStr string];
- NSFont *const newFont = [newAttrStr fontOfTheBeginning];
- NSFont *oldFont = editedCell.font;
+ NSString *const newString = [newAttrStr string];
+ NSFont *const newFont = [newAttrStr fontOfTheBeginning];
+ NSFont *oldFont = editedCell.font;
- BOOL stringModified = ![newString isEqualToString:editedCell.stringValue];
- BOOL fontModified;
+ BOOL stringModified = ![newString isEqualToString:editedCell.stringValue];
+ BOOL fontModified;
- if (oldFont == nil) {
- fontModified = ![newFont isEqual:[self.settings settingForKey:qSettingDefaultFont]];
- } else {
- fontModified = ![newFont isEqual:oldFont];
- }
+ if (oldFont == nil) {
+ fontModified = ![newFont isEqual:[self.settings settingForKey:qSettingDefaultFont]];
+ } else {
+ fontModified = ![newFont isEqual:oldFont];
+ }
- if (stringModified) {
- [self.dataSource mindmapView:self setStringValue:newString ofItem:identifier];
- }
+ if (stringModified) {
+ [self.dataSource mindmapView:self setStringValue:newString ofItem:identifier];
+ }
- if (fontModified) {
- [self.dataSource mindmapView:self setFont:newFont ofItems:[[NSArray alloc] initWithObjects:identifier, nil]];
- }
+ if (fontModified) {
+ [self.dataSource mindmapView:self setFont:newFont ofItems:[[NSArray alloc] initWithObjects:identifier, nil]];
+ }
}
- (void)editingCancelledWithString:(NSAttributedString *)newAttrStr forCell:(QMCell *)editedCell {
- [self.cellStateManager clearSelection];
+ [self.cellStateManager clearSelection];
- [self.dataSource mindmapView:self editingCancelledForItem:editedCell.identifier withAttrString:newAttrStr];
+ [self.dataSource mindmapView:self editingCancelledForItem:editedCell.identifier withAttrString:newAttrStr];
}
#pragma mark NSDraggingSource
- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session {
- return NO;
+ return NO;
}
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
- return NSDragOperationEvery;
+ return NSDragOperationEvery;
}
#pragma mark NSDraggingDestination
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender {
- NSPoint currentMousePosition = [self convertPoint:[sender draggingLocation] fromView:nil];
+ NSPoint currentMousePosition = [self convertPoint:[sender draggingLocation] fromView:nil];
- QMCell *oldDragTargetCell = self.cellStateManager.dragTargetCell;
- QMCell *newDragTargetCell = [self.cellSelector cellContainingPoint:currentMousePosition inCell:self.rootCell];
+ QMCell *oldDragTargetCell = self.cellStateManager.dragTargetCell;
+ QMCell *newDragTargetCell = [self.cellSelector cellContainingPoint:currentMousePosition inCell:self.rootCell];
- if (oldDragTargetCell != newDragTargetCell) {
- oldDragTargetCell.dragRegion = QMCellRegionNone;
+ if (oldDragTargetCell != newDragTargetCell) {
+ oldDragTargetCell.dragRegion = QMCellRegionNone;
- // We don't do the following, since we scroll during dragging
- //[self displayRect:oldDragTargetCell.nodeCellFrame];
- [self setNeedsDisplay:YES];
- }
+ // We don't do the following, since we scroll during dragging
+ //[self displayRect:oldDragTargetCell.nodeCellFrame];
+ [self setNeedsDisplay:YES];
+ }
- self.cellStateManager.dragTargetCell = newDragTargetCell;
- if (newDragTargetCell != nil && ![self.cellStateManager cellIsBeingDragged:newDragTargetCell]) {
- newDragTargetCell.dragRegion = [self.cellLayoutManager regionOfCell:newDragTargetCell atPoint:currentMousePosition];
- [self displayRect:NewRectWithOriginAndSize(newDragTargetCell.origin, newDragTargetCell.size)];
- }
+ self.cellStateManager.dragTargetCell = newDragTargetCell;
+ if (newDragTargetCell != nil && ![self.cellStateManager cellIsBeingDragged:newDragTargetCell]) {
+ newDragTargetCell.dragRegion = [self.cellLayoutManager regionOfCell:newDragTargetCell atPoint:currentMousePosition];
+ [self displayRect:NewRectWithOriginAndSize(newDragTargetCell.origin, newDragTargetCell.size)];
+ }
- return [sender draggingSourceOperationMask];
+ return [sender draggingSourceOperationMask];
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
- return YES;
+ return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
- NSPasteboard *pasteboard = [sender draggingPasteboard];
+ NSPasteboard *pasteboard = [sender draggingPasteboard];
- // As of now we only accept our own Node as drag & drop item
- if ([[pasteboard types] containsObject:qNodeUti] == NO) {
- return NO;
- }
+ // As of now we only accept our own Node as drag & drop item
+ if ([[pasteboard types] containsObject:qNodeUti] == NO) {
+ return NO;
+ }
- if ([sender draggingSource] != self) {
- return NO;
- }
+ if ([sender draggingSource] != self) {
+ return NO;
+ }
- // we are in the same view, the only supported mode as of now
- QMCell *dragTargetCell = self.cellStateManager.dragTargetCell;
- if (dragTargetCell == nil) {
- return NO;
- }
+ // we are in the same view, the only supported mode as of now
+ QMCell *dragTargetCell = self.cellStateManager.dragTargetCell;
+ if (dragTargetCell == nil) {
+ return NO;
+ }
- if ([self.cellStateManager cellIsBeingDragged:dragTargetCell]) {
- return NO;
- }
+ if ([self.cellStateManager cellIsBeingDragged:dragTargetCell]) {
+ return NO;
+ }
- if ([self.cellStateManager cellIsBeingDragged:self.rootCell]) {
- return NO;
- }
+ if ([self.cellStateManager cellIsBeingDragged:self.rootCell]) {
+ return NO;
+ }
- NSArray *draggedCells = self.cellStateManager.draggedCells;
- NSMutableArray *draggedItems = [[NSMutableArray alloc] initWithCapacity:[draggedCells count]];
- for (QMCell *cell in draggedCells) {
- [draggedItems addObject:cell.identifier];
- }
+ NSArray *draggedCells = self.cellStateManager.draggedCells;
+ NSMutableArray *draggedItems = [[NSMutableArray alloc] initWithCapacity:[draggedCells count]];
+ for (QMCell *cell in draggedCells) {
+ [draggedItems addObject:cell.identifier];
+ }
- if ([dragTargetCell isFolded]) {
- [self.dataSource mindmapView:self toggleFoldingForItem:dragTargetCell.identifier];
- }
+ if ([dragTargetCell isFolded]) {
+ [self.dataSource mindmapView:self toggleFoldingForItem:dragTargetCell.identifier];
+ }
- BOOL isCopying = [self dragIsCopying:[sender draggingSourceOperationMask]];
- if (isCopying) {
- [self.dataSource mindmapView:self copyItems:draggedItems toItem:dragTargetCell.identifier inDirection:[self directionFromCellRegion:dragTargetCell.dragRegion]];
- } else {
- [self.dataSource mindmapView:self moveItems:draggedItems toItem:dragTargetCell.identifier inDirection:[self directionFromCellRegion:dragTargetCell.dragRegion]];
- }
+ BOOL isCopying = [self dragIsCopying:[sender draggingSourceOperationMask]];
+ if (isCopying) {
+ [self.dataSource mindmapView:self copyItems:draggedItems toItem:dragTargetCell.identifier inDirection:[self directionFromCellRegion:dragTargetCell.dragRegion]];
+ } else {
+ [self.dataSource mindmapView:self moveItems:draggedItems toItem:dragTargetCell.identifier inDirection:[self directionFromCellRegion:dragTargetCell.dragRegion]];
+ }
- dragTargetCell.dragRegion = QMCellRegionNone;
- [self setNeedsDisplay:YES];
+ dragTargetCell.dragRegion = QMCellRegionNone;
+ [self setNeedsDisplay:YES];
- return YES;
+ return YES;
}
- (void)draggingEnded:(id <NSDraggingInfo>)sender {
- /**
- * As described in -doMouseUp:, we get out of the mouse-track loop when a drag session is started. Therefore, we have
- * to end the mouse-track loop by setting self.keepMouseTrackOn.
- */
+ /**
+ * As described in -doMouseUp:, we get out of the mouse-track loop when a drag session is started. Therefore, we have
+ * to end the mouse-track loop by setting self.keepMouseTrackOn.
+ */
- [self clearMouseTrackLoopFlags];
+ [self clearMouseTrackLoopFlags];
- [self.cellStateManager clearCellsForDrag];
+ [self.cellStateManager clearCellsForDrag];
}
#pragma mark NSResponder
- (void)keyDown:(NSEvent *)theEvent {
- // [super keyDown:] cause the app to beep since the super does not implement it
+ // [super keyDown:] cause the app to beep since the super does not implement it
- NSArray *selectedCells = [self.cellStateManager selectedCells];
- if ([selectedCells count] > 1) {
- return;
- }
+ NSArray *selectedCells = [self.cellStateManager selectedCells];
+ if ([selectedCells count] > 1) {
+ return;
+ }
- unichar keyChar = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
- NSUInteger modifierFlags = [theEvent modifierFlags];
- BOOL commandKey = modifier_check(modifierFlags, NSCommandKeyMask);
- BOOL shiftKey = modifier_check(modifierFlags, NSShiftKeyMask);
+ unichar keyChar = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
+ NSUInteger modifierFlags = [theEvent modifierFlags];
+ BOOL commandKey = modifier_check(modifierFlags, NSCommandKeyMask);
+ BOOL shiftKey = modifier_check(modifierFlags, NSShiftKeyMask);
- if (keyChar == qPageUpKeyCode || keyChar == qPageDownKeyCode) {
- [self scrollViewOnePageAccordingToKey:keyChar];
- return;
- }
+ if (keyChar == qPageUpKeyCode || keyChar == qPageDownKeyCode) {
+ [self scrollViewOnePageAccordingToKey:keyChar];
+ return;
+ }
- if (modifierFlags & NSNumericPadKeyMask) {
- [self interpretKeyEvents:@[theEvent]];
- return;
- }
+ if (modifierFlags & NSNumericPadKeyMask) {
+ [self interpretKeyEvents:@[theEvent]];
+ return;
+ }
- BOOL hasSelectedCells = [self.cellStateManager hasSelectedCells];
- QMCell *selCell = hasSelectedCells ? [selectedCells lastObject] : self.rootCell;
- id selIdentifier = selCell.identifier;
+ BOOL hasSelectedCells = [self.cellStateManager hasSelectedCells];
+ QMCell *selCell = hasSelectedCells ? [selectedCells lastObject] : self.rootCell;
+ id selIdentifier = selCell.identifier;
- if ([[self.settings settingForKey:qSettingNewChildNodeChars] characterIsMember:keyChar]) {
- [self insertChild];
- return;
- }
+ if ([[self.settings settingForKey:qSettingNewChildNodeChars] characterIsMember:keyChar]) {
+ [self insertChild];
+ return;
+ }
- if ([[self.settings settingForKey:qSettingNewLeftChildNodeChars] characterIsMember:keyChar]) {
- [self insertLeftChild];
- return;
- }
+ if ([[self.settings settingForKey:qSettingNewLeftChildNodeChars] characterIsMember:keyChar]) {
+ [self insertLeftChild];
+ return;
+ }
- if (!hasSelectedCells) {
- return;
- }
+ if (!hasSelectedCells) {
+ return;
+ }
- if ([[self.settings settingForKey:qSettingEditSelectedNodeChars] characterIsMember:keyChar]
- && !commandKey
- && !shiftKey) {
+ if ([[self.settings settingForKey:qSettingEditSelectedNodeChars] characterIsMember:keyChar]
+ && !commandKey
+ && !shiftKey) {
- [self editCell:selCell];
+ [self editCell:selCell];
- return;
- }
+ return;
+ }
- if (selCell.isRoot) {
- return;
- }
-
- if ([[self.settings settingForKey:qSettingFoldingChars] characterIsMember:keyChar]) {
- [self.dataSource mindmapView:self toggleFoldingForItem:selIdentifier];
- return;
- }
+ if (selCell.isRoot) {
+ return;
+ }
- if ([[self.settings settingForKey:qSettingNewSiblingNodeChars] characterIsMember:keyChar]) {
+ if ([[self.settings settingForKey:qSettingFoldingChars] characterIsMember:keyChar]) {
+ [self.dataSource mindmapView:self toggleFoldingForItem:selIdentifier];
+ return;
+ }
- if (!commandKey) {
- return;
- }
+ if ([[self.settings settingForKey:qSettingNewSiblingNodeChars] characterIsMember:keyChar]) {
- if (shiftKey) {
- [self insertPreviousSibling];
- return;
- }
+ if (!commandKey) {
+ return;
+ }
- [self insertNextSibling];
- return;
+ if (shiftKey) {
+ [self insertPreviousSibling];
+ return;
}
+
+ [self insertNextSibling];
+ return;
+ }
}
- (void)mouseDown:(NSEvent *)event {
- /**
- * We're using the mouse-track loop approach to handle mouse dragging and mouse up events
- * because of the issue #6:
- *
- * https://github.com/qvacua/qmind/issues/6
- */
+ /**
+ * We're using the mouse-track loop approach to handle mouse dragging and mouse up events
+ * because of the issue #6:
+ *
+ * https://github.com/qvacua/qmind/issues/6
+ */
- /**
- * Single click event always precede the double click event, i.e. when the user double-clicks, then:
- *
- * - mouseDown event with clickCount = 1
- * - mouseDown event with clickCount = 2
- */
+ /**
+ * Single click event always precede the double click event, i.e. when the user double-clicks, then:
+ *
+ * - mouseDown event with clickCount = 1
+ * - mouseDown event with clickCount = 2
+ */
- NSInteger clickCount = [event clickCount];
- NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
- NSUInteger modifier = [event modifierFlags];
+ NSInteger clickCount = [event clickCount];
+ NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
+ NSUInteger modifier = [event modifierFlags];
- if (clickCount == 1) {
+ if (clickCount == 1) {
- [self handleSingleMouseDown:clickLocation modifier:modifier];
+ [self handleSingleMouseDown:clickLocation modifier:modifier];
- } else if (clickCount == 2) {
- if (modifier_check(modifier, NSCommandKeyMask) || modifier_check(modifier, NSShiftKeyMask)) {
- return;
- }
-
- if (![self.cellStateManager hasSelectedCells]) {
- return;
- }
+ } else if (clickCount == 2) {
+ if (modifier_check(modifier, NSCommandKeyMask) || modifier_check(modifier, NSShiftKeyMask)) {
+ return;
+ }
- NSArray *selCells = [self.cellStateManager selectedCells];
- if ([selCells count] > 1) {
- return;
- }
+ if (![self.cellStateManager hasSelectedCells]) {
+ return;
+ }
- [self.dataSource mindmapView:self toggleFoldingForItem:[selCells.lastObject identifier]];
+ NSArray *selCells = [self.cellStateManager selectedCells];
+ if ([selCells count] > 1) {
+ return;
}
- NSEvent *currentEvent;
- self.keepMouseTrackOn = YES;
- while (self.keepMouseTrackOn) {
- currentEvent = [self.window nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask];
+ [self.dataSource mindmapView:self toggleFoldingForItem:[selCells.lastObject identifier]];
+ }
+
+ NSEvent *currentEvent;
+ self.keepMouseTrackOn = YES;
+ while (self.keepMouseTrackOn) {
+ currentEvent = [self.window nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask];
- switch ([currentEvent type]) {
- case NSLeftMouseDragged:
- [self doMouseDragged:currentEvent];
- break;
+ switch ([currentEvent type]) {
+ case NSLeftMouseDragged:
+ [self doMouseDragged:currentEvent];
+ break;
- case NSLeftMouseUp:
- [[NSCursor arrowCursor] set];
- [self doMouseUp:currentEvent];
+ case NSLeftMouseUp:
+ [[NSCursor arrowCursor] set];
+ [self doMouseUp:currentEvent];
- [self clearMouseTrackLoopFlags];
- break;
+ [self clearMouseTrackLoopFlags];
+ break;
- default:
- break;
- }
+ default:
+ break;
}
+ }
}
- (void)scrollWheel:(NSEvent *)event {
- NSUInteger modifierFlags = [event modifierFlags];
- BOOL commandKey = modifier_check(modifierFlags, NSCommandKeyMask);
+ NSUInteger modifierFlags = [event modifierFlags];
+ BOOL commandKey = modifier_check(modifierFlags, NSCommandKeyMask);
- if (!commandKey) {
- [super scrollWheel:event];
- return;
- }
+ if (!commandKey) {
+ [super scrollWheel:event];
+ return;
+ }
- if ([self.cellEditor isEditing]) {
- return;
- }
+ if ([self.cellEditor isEditing]) {
+ return;
+ }
- CGFloat factor = 1.0 + sign([event deltaY]) * qZoomScrollWheelStep;
- NSPoint locInView = [self convertPoint:[event locationInWindow] fromView:nil];
+ CGFloat factor = 1.0 + sign([event deltaY]) * qZoomScrollWheelStep;
+ NSPoint locInView = [self convertPoint:[event locationInWindow] fromView:nil];
- [self zoomByFactor:factor withFixedPoint:locInView];
+ [self zoomByFactor:factor withFixedPoint:locInView];
}
- (void)magnifyWithEvent:(NSEvent *)event {
- if ([self.cellEditor isEditing]) {
- return;
- }
+ if ([self.cellEditor isEditing]) {
+ return;
+ }
- CGFloat factor = 1.0 + [event magnification];
- NSPoint locInView = [self convertPoint:[event locationInWindow] fromView:nil];
+ CGFloat factor = 1.0 + [event magnification];
+ NSPoint locInView = [self convertPoint:[event locationInWindow] fromView:nil];
- [self zoomByFactor:factor withFixedPoint:locInView];
+ [self zoomByFactor:factor withFixedPoint:locInView];
}
- (BOOL)acceptsFirstResponder {
- return YES;
+ return YES;
}
- (BOOL)becomeFirstResponder {
- return YES;
+ return YES;
}
- (void)moveRight:(id)sender {
- NSArray *selectedCells = [self.cellStateManager selectedCells];
- if ([selectedCells count] != 1) {
- return;
- }
+ NSArray *selectedCells = [self.cellStateManager selectedCells];
+ if ([selectedCells count] != 1) {
+ return;
+ }
- QMCell *selCell = selectedCells[0];
- if ([selCell isLeft]) {
- [self replaceSelectionWithCellAndRedisplay:selCell.parent];
- return;
- }
+ QMCell *selCell = selectedCells[0];
+ if ([selCell isLeft]) {
+ [self replaceSelectionWithCellAndRedisplay:selCell.parent];
+ return;
+ }
- if ([selCell isLeaf]) {
- return;
- }
+ if ([selCell isLeaf]) {
+ return;
+ }
- if ([selCell isFolded]) {
- [self.dataSource mindmapView:self toggleFoldingForItem:selCell.identifier];
- }
+ if ([selCell isFolded]) {
+ [self.dataSource mindmapView:self toggleFoldingForItem:selCell.identifier];
+ }
- NSArray *children = selCell.children;
- if ([selCell countOfChildren] == 1) {
- [self replaceSelectionWithCellAndRedisplay:children[0]];
- return;
- }
+ NSArray *children = selCell.children;
+ if ([selCell countOfChildren] == 1) {
+ [self replaceSelectionWithCellAndRedisplay:children[0]];
+ return;
+ }
- QMCell *chosenChildCell = [self verticallyNearestCellFromCells:children withCell:selCell];
- [self replaceSelectionWithCellAndRedisplay:chosenChildCell];
+ QMCell *chosenChildCell = [self verticallyNearestCellFromCells:children withCell:selCell];
+ [self replaceSelectionWithCellAndRedisplay:chosenChildCell];
}
- (void)moveLeft:(id)sender {
- NSArray *selectedCells = [self.cellStateManager selectedCells];
- if ([selectedCells count] != 1) {
- return;
- }
+ NSArray *selectedCells = [self.cellStateManager selectedCells];
+ if ([selectedCells count] != 1) {
+ return;
+ }
- QMCell *selCell = selectedCells[0];
- BOOL selCellIsRoot = [selCell isRoot];
- NSArray *children = selCellIsRoot ? self.rootCell.leftChildren : selCell.children;
+ QMCell *selCell = selectedCells[0];
+ BOOL selCellIsRoot = [selCell isRoot];
+ NSArray *children = selCellIsRoot ? self.rootCell.leftChildren : selCell.children;
- if ([selCell isLeft] || selCellIsRoot) {
- if ([children count] == 0) {
- return;
- }
-
- if ([selCell isFolded]) {
- [self.dataSource mindmapView:self toggleFoldingForItem:selCell.identifier];
- }
+ if ([selCell isLeft] || selCellIsRoot) {
+ if ([children count] == 0) {
+ return;
+ }
- if ([children count] == 1) {
- [self replaceSelectionWithCellAndRedisplay:children[0]];
- return;
- }
+ if ([selCell isFolded]) {
+ [self.dataSource mindmapView:self toggleFoldingForItem:selCell.identifier];
+ }
- QMCell *chosenChildCell = [self verticallyNearestCellFromCells:children withCell:selCell];
- [self replaceSelectionWithCellAndRedisplay:chosenChildCell];
- return;
+ if ([children count] == 1) {
+ [self replaceSelectionWithCellAndRedisplay:children[0]];
+ return;
}
- [self replaceSelectionWithCellAndRedisplay:selCell.parent];
+ QMCell *chosenChildCell = [self verticallyNearestCellFromCells:children withCell:selCell];
+ [self replaceSelectionWithCellAndRedisplay:chosenChildCell];
+ return;
+ }
+
+ [self replaceSelectionWithCellAndRedisplay:selCell.parent];
}
- (void)moveDown:(id)sender {
- NSUInteger (^nextLevelIndexOperation)(NSUInteger) = ^(NSUInteger givenIndex) {
- return givenIndex + 1;
- };
+ NSUInteger (^nextLevelIndexOperation)(NSUInteger) = ^(NSUInteger givenIndex) {
+ return givenIndex + 1;
+ };
- QMCell *(^positionOfCell)(NSArray *) = ^(NSArray *cells) {
- return [cells lastObject];
- };
+ QMCell *(^positionOfCell)(NSArray *) = ^(NSArray *cells) {
+ return [cells lastObject];
+ };
- QMCell *(^cellSelector)(NSArray *) = ^(NSArray *cells) {
- return cells[0];
- };
+ QMCell *(^cellSelector)(NSArray *) = ^(NSArray *cells) {
+ return cells[0];
+ };
- [self moveUpOrDownUsingLevelIndexOperation:nextLevelIndexOperation positionOfCell:positionOfCell cellSelector:cellSelector];
+ [self moveUpOrDownUsingLevelIndexOperation:nextLevelIndexOperation positionOfCell:positionOfCell cellSelector:cellSelector];
}
- (void)moveUp:(id)sender {
- NSUInteger (^nextLevelIndexOperation)(NSUInteger) = ^(NSUInteger givenIndex) {
- return givenIndex - 1;
- };
+ NSUInteger (^nextLevelIndexOperation)(NSUInteger) = ^(NSUInteger givenIndex) {
+ return givenIndex - 1;
+ };
- QMCell *(^positionOfCell)(NSArray *) = ^(NSArray *cells) {
- return cells[0];
- };
+ QMCell *(^positionOfCell)(NSArray *) = ^(NSArray *cells) {
+ return cells[0];
+ };
- QMCell *(^cellSelector)(NSArray *) = ^(NSArray *cells) {
- return [cells lastObject];
- };
+ QMCell *(^cellSelector)(NSArray *) = ^(NSArray *cells) {
+ return [cells lastObject];
+ };
- [self moveUpOrDownUsingLevelIndexOperation:nextLevelIndexOperation positionOfCell:positionOfCell cellSelector:cellSelector];
+ [self moveUpOrDownUsingLevelIndexOperation:nextLevelIndexOperation positionOfCell:positionOfCell cellSelector:cellSelector];
}
#pragma mark NSView
- (id)initWithFrame:(NSRect)frame {
- if ((self = [super initWithFrame:frame])) {
- [[TBContext sharedContext] autowireSeed:self];
+ if ((self = [super initWithFrame:frame])) {
+ [[TBContext sharedContext] autowireSeed:self];
- _cellStateManager = [[QMCellStateManager alloc] init];
- _cellEditor = [[QMCellEditor alloc] init];
- _cellEditor.view = self;
- _cellEditor.delegate = self;
- }
+ _cellStateManager = [[QMCellStateManager alloc] init];
+ _cellEditor = [[QMCellEditor alloc] init];
+ _cellEditor.view = self;
+ _cellEditor.delegate = self;
+
+ [self addSubview:_cellEditor.editorView];
+ _cellEditor.editorView.hidden = YES;
+ }
- return self;
+ return self;
}
- (NSMenu *)menuForEvent:(NSEvent *)event {
- if ([event type] != NSRightMouseDown) {
- return nil;
- }
+ if ([event type] != NSRightMouseDown) {
+ return nil;
+ }
- NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
- QMCell *mouseDownHitCell = [self.cellSelector cellContainingPoint:clickLocation inCell:self.rootCell];
+ NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
+ QMCell *mouseDownHitCell = [self.cellSelector cellContainingPoint:clickLocation inCell:self.rootCell];
- NSMenu *menu = [self menu];
- NSMenuItem *deleteIconMenuItem = [menu itemWithTag:qDeleteIconMenuItemTag];
- NSMenuItem *deleteAllIconsMenuItem = [menu itemWithTag:qDeleteAllIconsMenuItemTag];
+ NSMenu *menu = [self menu];
+ NSMenuItem *deleteIconMenuItem = [menu itemWithTag:qDeleteIconMenuItemTag];
+ NSMenuItem *deleteAllIconsMenuItem = [menu itemWithTag:qDeleteAllIconsMenuItemTag];
- if (mouseDownHitCell == nil || [mouseDownHitCell countOfIcons] == 0) {
- [self disableDeleteIconMenuItem:deleteIconMenuItem];
+ if (mouseDownHitCell == nil || [mouseDownHitCell countOfIcons] == 0) {
+ [self disableDeleteIconMenuItem:deleteIconMenuItem];
- [deleteAllIconsMenuItem setEnabled:NO];
- [deleteAllIconsMenuItem setBlockAction:nil];
+ [deleteAllIconsMenuItem setEnabled:NO];
+ [deleteAllIconsMenuItem setBlockAction:nil];
- return menu;
- }
+ return menu;
+ }
- void (^deleteAllIconsBlock)(id) = ^(id sender) {
- [self.dataSource mindmapView:self deleteAllIconsOfItem:mouseDownHitCell.identifier];
- };
+ void (^deleteAllIconsBlock)(id) = ^(id sender) {
+ [self.dataSource mindmapView:self deleteAllIconsOfItem:mouseDownHitCell.identifier];
+ };
- if (NSPointInRect(clickLocation, mouseDownHitCell.textFrame)) {
- [self disableDeleteIconMenuItem:deleteIconMenuItem];
- [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
+ if (NSPointInRect(clickLocation, mouseDownHitCell.textFrame)) {
+ [self disableDeleteIconMenuItem:deleteIconMenuItem];
+ [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
- return menu;
- }
+ return menu;
+ }
- __block QMIcon *hitIcon = nil;
- [mouseDownHitCell.icons enumerateObjectsUsingBlock:^(QMIcon *icon, NSUInteger index, BOOL *stop) {
- if (NSPointInRect(clickLocation, icon.frame)) {
- hitIcon = icon;
- *stop = YES;
- }
- }];
+ __block QMIcon *hitIcon = nil;
+ [mouseDownHitCell.icons enumerateObjectsUsingBlock:^(QMIcon *icon, NSUInteger index, BOOL *stop) {
+ if (NSPointInRect(clickLocation, icon.frame)) {
+ hitIcon = icon;
+ *stop = YES;
+ }
+ }];
- if (hitIcon == nil) {
- [self disableDeleteIconMenuItem:deleteIconMenuItem];
- [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
+ if (hitIcon == nil) {
+ [self disableDeleteIconMenuItem:deleteIconMenuItem];
+ [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
- return menu;
- }
+ return menu;
+ }
- NSString *unicode = hitIcon.unicode;
- if (unicode == nil) {
- unicode = NSLocalizedString(@"delete.node.unsupported.icon", @"Unsupported Icon");
- }
+ NSString *unicode = hitIcon.unicode;
+ if (unicode == nil) {
+ unicode = NSLocalizedString(@"delete.node.unsupported.icon", @"Unsupported Icon");
+ }
- [deleteIconMenuItem setTitle:[NSString stringWithFormat:NSLocalizedString(@"delete.node.icon", @"Delete %@"), unicode]];
- [deleteIconMenuItem setEnabled:YES];
- [deleteIconMenuItem setBlockAction:^(id sender) {
- NSUInteger indexOfHitIcon = [mouseDownHitCell.icons indexOfObject:hitIcon];
- [self.dataSource mindmapView:self deleteIconOfItem:mouseDownHitCell.identifier atIndex:indexOfHitIcon];
- }];
+ [deleteIconMenuItem setTitle:[NSString stringWithFormat:NSLocalizedString(@"delete.node.icon", @"Delete %@"), unicode]];
+ [deleteIconMenuItem setEnabled:YES];
+ [deleteIconMenuItem setBlockAction:^(id sender) {
+ NSUInteger indexOfHitIcon = [mouseDownHitCell.icons indexOfObject:hitIcon];
+ [self.dataSource mindmapView:self deleteIconOfItem:mouseDownHitCell.identifier atIndex:indexOfHitIcon];
+ }];
- [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
+ [self enableDeleteAllIconsMenuItem:deleteAllIconsMenuItem withBlock:deleteAllIconsBlock];
- return menu;
+ return menu;
}
- (void)drawRect:(NSRect)dirtyRect {
- [super drawRect:dirtyRect];
+ [super drawRect:dirtyRect]; </