Skip to content

Commit

Permalink
• initial commit to support text chunk folding in RScriptEditor
Browse files Browse the repository at this point in the history
- not yet activated since testing phase is not yet finished (esp. for speed)
• fixed line numbering refreshing calls

git-svn-id: https://svn.r-project.org/R-packages/trunk/Mac-GUI@6128 694ef91d-65df-0310-b7bb-92e67a308ead
  • Loading branch information
Hans-Jörg Bibiko committed Mar 1, 2012
1 parent 186554c commit 7c3e992
Show file tree
Hide file tree
Showing 18 changed files with 1,101 additions and 50 deletions.
43 changes: 43 additions & 0 deletions FoldingSignTextAttachmentCell.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
*
* R.app Copyright notes:
* Copyright (C) 2004-12 The R Foundation
* written by Stefano M. Iacus and Simon Urbanek
*
*
* R Copyright notes:
* Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998-2001 The R Development Core Team
* Copyright (C) 2002-2004 The R Foundation
*
* 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.
*
* A copy of the GNU General Public License is available via WWW at
* http://www.gnu.org/copyleft/gpl.html. You can also obtain it by
* writing to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA.
*
* FoldingSignTextAttachmentCell.h
*
* Created by Hans-J. Bibiko on 01/03/2012.
*
*/

#import <Cocoa/Cocoa.h>


@interface FoldingSignTextAttachmentCell : NSTextAttachmentCell
{

}

@end
138 changes: 138 additions & 0 deletions FoldingSignTextAttachmentCell.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
*
* R.app Copyright notes:
* Copyright (C) 2004-12 The R Foundation
* written by Stefano M. Iacus and Simon Urbanek
*
*
* R Copyright notes:
* Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998-2001 The R Development Core Team
* Copyright (C) 2002-2004 The R Foundation
*
* 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.
*
* A copy of the GNU General Public License is available via WWW at
* http://www.gnu.org/copyleft/gpl.html. You can also obtain it by
* writing to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA.
*
* FoldingSignTextAttachmentCell.h
*
* Created by Hans-J. Bibiko on 01/03/2012.
*
*/

#import "FoldingSignTextAttachmentCell.h"
#import "RScriptEditorTextView.h"
#import "RScriptEditorTextStorage.h"

#define HorizontalInset (4.0)
#define VerticalInset (1.0)
#define MaxWidth (100.0)

@implementation FoldingSignTextAttachmentCell

static NSLayoutManager *scratchLayoutManager = nil;

+ (void)initialize
{
if (self == [FoldingSignTextAttachmentCell class]) {
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSZeroSize];

scratchLayoutManager = [[NSLayoutManager alloc] init];
[scratchLayoutManager addTextContainer:textContainer];
[textContainer release];
}
}

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView characterIndex:(NSUInteger)charIndex layoutManager:(NSLayoutManager *)layoutManager
{

// don't render for scratchLayoutManager
if (layoutManager == scratchLayoutManager) return;

CGFloat h = cellFrame.size.height;
CGFloat y = cellFrame.origin.y;

y += h/4;
h -= h/2;

NSRect p = NSMakeRect(cellFrame.origin.x+4.0f, y, cellFrame.size.width-8.0f, h);
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:p xRadius:4.0 yRadius:4.0];

NSColor *col = [[layoutManager textStorage] foregroundColor];

[[col colorWithAlphaComponent:0.6f] setFill];
[path fill];
[path stroke];
[col setFill];

p = NSMakeRect(cellFrame.origin.x+4.0f+5.0f, y+h/2-1.0f, 3.0f, 3.0f);
NSRectFill(p);
p.origin.x+=5.0f;
NSRectFill(p);
p.origin.x+=5.0f;
NSRectFill(p);
}

- (BOOL)wantsToTrackMouseForEvent:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView atCharacterIndex:(NSUInteger)charIndex
{
return YES;
}

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView atCharacterIndex:(NSUInteger)charIndex untilMouseUp:(BOOL)flag
{

if ([controlView respondsToSelector:@selector(unfoldLinesContainingCharacterAtIndex:)]) {
return [(RScriptEditorTextView *)controlView unfoldLinesContainingCharacterAtIndex:charIndex];
}

return NO;
}

- (NSRect)cellFrameForTextContainer:(NSTextContainer *)textContainer proposedLineFragment:(NSRect)lineFrag glyphPosition:(NSPoint)position characterIndex:(NSUInteger)charIndex
{

NSLayoutManager *layoutManager = [textContainer layoutManager];

// we don't do layout for scratchLayoutManager
if (layoutManager == scratchLayoutManager) return NSZeroRect;

NSTextStorage *textStorage = [layoutManager textStorage];
NSTextContainer *scratchContainer = [[scratchLayoutManager textContainers] objectAtIndex:0];
NSRect textFrame;
NSRange glyphRange;
NSRect frame;
BOOL lineFoldingEnabled = [(RScriptEditorTextStorage *)textStorage lineFoldingEnabled];

[(RScriptEditorTextStorage *)textStorage setLineFoldingEnabled:NO];

if ([scratchLayoutManager textStorage] != textStorage) {
[textStorage addLayoutManager:scratchLayoutManager];
}

if (!NSEqualSizes([textContainer containerSize], [scratchContainer containerSize])) [scratchContainer setContainerSize:[textContainer containerSize]];

[scratchLayoutManager ensureLayoutForCharacterRange:NSMakeRange(charIndex, 1)];
textFrame = [scratchLayoutManager lineFragmentRectForGlyphAtIndex:[scratchLayoutManager glyphIndexForCharacterAtIndex:charIndex] effectiveRange:&glyphRange];

[(RScriptEditorTextStorage *)textStorage setLineFoldingEnabled:lineFoldingEnabled];

frame.origin = NSZeroPoint;
frame.size = NSMakeSize(30.0f, NSHeight(lineFrag));
frame.origin.y -= [[scratchLayoutManager typesetter] baselineOffsetInLayoutManager:scratchLayoutManager glyphIndex:glyphRange.location];

return frame;
}

@end
2 changes: 2 additions & 0 deletions NoodleLineNumberView.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,6 @@ static inline id NSArrayObjectAtIndex(NSArray *self, NSUInteger i)
- (NSUInteger)lineNumberForLocation:(CGFloat)location;
- (NSUInteger)lineNumberForCharacterIndex:(NSUInteger)index;

- (void)refresh;

@end
34 changes: 27 additions & 7 deletions NoodleLineNumberView.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
@interface NoodleLineNumberView (Private)

- (NSArray *)lineIndices;
- (void)invalidateLineIndices;
- (void)calculateLines;
- (void)invalidateLineIndices;
- (void)updateGutterThicknessConstants;

@end
Expand Down Expand Up @@ -196,6 +196,13 @@ - (void)setClientView:(NSView *)aView

#pragma mark -

- (void)refresh
{
if(![(RScriptEditorTextView*)clientView lineNumberingEnabled]) return;
[self invalidateLineIndices];
[self setNeedsDisplay:YES];
}

- (void)textDidChange:(NSNotification *)notification
{

Expand Down Expand Up @@ -325,6 +332,10 @@ - (void)drawHashMarksAndLabelsInRect:(NSRect)aRect
CGFloat boundsWidthRULER = NSWidth(bounds) - RULER_MARGIN;
CGFloat yinsetMinY = yinset - NSMinY(visibleRect);
CGFloat rectHeight;
CGFloat last_y = -10.0f;
CGFloat y;
// BOOL didDrawFoldingLine = NO;
// [[NSColor grayColor] setFill];

for (line = (NSUInteger)(*lineNumberForCharacterIndexIMP)(self, lineNumberForCharacterIndexSel, range.location); line < count; line++)
{
Expand All @@ -351,12 +362,21 @@ - (void)drawHashMarksAndLabelsInRect:(NSRect)aRect
while(idx) { numOfDigits++; idx/=10; }

rectHeight = NSHeight(rects[0]);
// Draw string flush right, centered vertically within the line
[labelText drawInRect:
NSMakeRect(boundsWidthRULER - (maxWidthOfGlyph * numOfDigits),
yinsetMinY + NSMinY(rects[0]) + ((NSInteger)(rectHeight - maxHeightOfGlyph) >> 1),
boundsRULERMargin2, rectHeight)
withAttributes:textAttributes];
y = yinsetMinY + NSMinY(rects[0]) + ((NSInteger)(rectHeight - maxHeightOfGlyph) >> 1);
if(y != last_y) {
// didDrawFoldingLine = NO;
// Draw string flush right, centered vertically within the line
[labelText drawInRect:
NSMakeRect(boundsWidthRULER - (maxWidthOfGlyph * numOfDigits), y,
boundsRULERMargin2, rectHeight)
withAttributes:textAttributes];
// } else {
// if(!didDrawFoldingLine) {
// NSRectFill(NSMakeRect(0, NSMaxY(rects[rectCount-1])-1, NSWidth(bounds), 2));
// didDrawFoldingLine = YES;
// }
}
last_y = y;
}
}

Expand Down
2 changes: 2 additions & 0 deletions PreferenceKeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@

// other constants

#define foldingAttributeName @"folded"

#define iBackgroundColor 0
#define iInputColor 1
#define iOutputColor 2
Expand Down
40 changes: 40 additions & 0 deletions R.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@
BCEFEBD81336705800CED44F /* RFontPreviewTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEFEBD61336705800CED44F /* RFontPreviewTextField.m */; };
BCEFEBE21336709A00CED44F /* RColorWellCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BCEFEBE01336709A00CED44F /* RColorWellCell.h */; };
BCEFEBE31336709A00CED44F /* RColorWellCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEFEBE11336709A00CED44F /* RColorWellCell.m */; };
BCF18DAB14FC8A1000670A26 /* RScriptEditorGlyphGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF18DA914FC8A1000670A26 /* RScriptEditorGlyphGenerator.h */; };
BCF18DAC14FC8A1000670A26 /* RScriptEditorGlyphGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF18DAA14FC8A1000670A26 /* RScriptEditorGlyphGenerator.m */; };
BCF18DAF14FC8A2200670A26 /* RScriptEditorLayoutManager.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF18DAD14FC8A2200670A26 /* RScriptEditorLayoutManager.h */; };
BCF18DB014FC8A2200670A26 /* RScriptEditorLayoutManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF18DAE14FC8A2200670A26 /* RScriptEditorLayoutManager.m */; };
BCF18DB314FC8A3B00670A26 /* FoldingSignTextAttachmentCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF18DB114FC8A3B00670A26 /* FoldingSignTextAttachmentCell.h */; };
BCF18DB414FC8A3B00670A26 /* FoldingSignTextAttachmentCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF18DB214FC8A3B00670A26 /* FoldingSignTextAttachmentCell.m */; };
BCF18DB714FC8A5E00670A26 /* RScriptEditorTextStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF18DB514FC8A5E00670A26 /* RScriptEditorTextStorage.h */; };
BCF18DB814FC8A5E00670A26 /* RScriptEditorTextStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF18DB614FC8A5E00670A26 /* RScriptEditorTextStorage.m */; };
BCF18DBB14FC8A7100670A26 /* RScriptEditorTypeSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF18DB914FC8A7100670A26 /* RScriptEditorTypeSetter.h */; };
BCF18DBC14FC8A7100670A26 /* RScriptEditorTypeSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF18DBA14FC8A7100670A26 /* RScriptEditorTypeSetter.m */; };
BCF4B2C114D9815400F14715 /* NSString_RAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF4B2BF14D9815400F14715 /* NSString_RAdditions.h */; };
BCF4B2C214D9815400F14715 /* NSString_RAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = BCF4B2C014D9815400F14715 /* NSString_RAdditions.m */; };
BCF5D88A14BB564A000A71F6 /* RdScriptEditorTokens.l in Sources */ = {isa = PBXBuildFile; fileRef = BCF5D88914BB564A000A71F6 /* RdScriptEditorTokens.l */; };
Expand Down Expand Up @@ -512,6 +522,16 @@
BCEFEBD61336705800CED44F /* RFontPreviewTextField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RFontPreviewTextField.m; sourceTree = "<group>"; };
BCEFEBE01336709A00CED44F /* RColorWellCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RColorWellCell.h; sourceTree = "<group>"; };
BCEFEBE11336709A00CED44F /* RColorWellCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RColorWellCell.m; sourceTree = "<group>"; };
BCF18DA914FC8A1000670A26 /* RScriptEditorGlyphGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RScriptEditorGlyphGenerator.h; sourceTree = "<group>"; };
BCF18DAA14FC8A1000670A26 /* RScriptEditorGlyphGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RScriptEditorGlyphGenerator.m; sourceTree = "<group>"; };
BCF18DAD14FC8A2200670A26 /* RScriptEditorLayoutManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RScriptEditorLayoutManager.h; sourceTree = "<group>"; };
BCF18DAE14FC8A2200670A26 /* RScriptEditorLayoutManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RScriptEditorLayoutManager.m; sourceTree = "<group>"; };
BCF18DB114FC8A3B00670A26 /* FoldingSignTextAttachmentCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoldingSignTextAttachmentCell.h; sourceTree = "<group>"; };
BCF18DB214FC8A3B00670A26 /* FoldingSignTextAttachmentCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FoldingSignTextAttachmentCell.m; sourceTree = "<group>"; };
BCF18DB514FC8A5E00670A26 /* RScriptEditorTextStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RScriptEditorTextStorage.h; sourceTree = "<group>"; };
BCF18DB614FC8A5E00670A26 /* RScriptEditorTextStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RScriptEditorTextStorage.m; sourceTree = "<group>"; };
BCF18DB914FC8A7100670A26 /* RScriptEditorTypeSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RScriptEditorTypeSetter.h; sourceTree = "<group>"; };
BCF18DBA14FC8A7100670A26 /* RScriptEditorTypeSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RScriptEditorTypeSetter.m; sourceTree = "<group>"; };
BCF4B2BF14D9815400F14715 /* NSString_RAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSString_RAdditions.h; sourceTree = "<group>"; };
BCF4B2C014D9815400F14715 /* NSString_RAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSString_RAdditions.m; sourceTree = "<group>"; };
BCF5D88914BB564A000A71F6 /* RdScriptEditorTokens.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = RdScriptEditorTokens.l; sourceTree = "<group>"; };
Expand Down Expand Up @@ -910,6 +930,16 @@
68756ED907FDDAEF0014821A /* REditorToolbar.m */,
BC884B6914BAD86C00DEFFE0 /* RdEditorToolbar.h */,
BC884B6A14BAD86C00DEFFE0 /* RdEditorToolbar.m */,
BCF18DA914FC8A1000670A26 /* RScriptEditorGlyphGenerator.h */,
BCF18DAA14FC8A1000670A26 /* RScriptEditorGlyphGenerator.m */,
BCF18DAD14FC8A2200670A26 /* RScriptEditorLayoutManager.h */,
BCF18DAE14FC8A2200670A26 /* RScriptEditorLayoutManager.m */,
BCF18DB114FC8A3B00670A26 /* FoldingSignTextAttachmentCell.h */,
BCF18DB214FC8A3B00670A26 /* FoldingSignTextAttachmentCell.m */,
BCF18DB514FC8A5E00670A26 /* RScriptEditorTextStorage.h */,
BCF18DB614FC8A5E00670A26 /* RScriptEditorTextStorage.m */,
BCF18DB914FC8A7100670A26 /* RScriptEditorTypeSetter.h */,
BCF18DBA14FC8A7100670A26 /* RScriptEditorTypeSetter.m */,
);
name = Editor;
sourceTree = "<group>";
Expand Down Expand Up @@ -1033,6 +1063,11 @@
BCB4FEAB14F24B0E00281019 /* RWindow.h in Headers */,
BCED54F514FA37BD00F5AD8A /* RTooltip.h in Headers */,
BCED54F914FA380A00F5AD8A /* RChooseMenuItemDialog.h in Headers */,
BCF18DAB14FC8A1000670A26 /* RScriptEditorGlyphGenerator.h in Headers */,
BCF18DAF14FC8A2200670A26 /* RScriptEditorLayoutManager.h in Headers */,
BCF18DB314FC8A3B00670A26 /* FoldingSignTextAttachmentCell.h in Headers */,
BCF18DB714FC8A5E00670A26 /* RScriptEditorTextStorage.h in Headers */,
BCF18DBB14FC8A7100670A26 /* RScriptEditorTypeSetter.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -1293,6 +1328,11 @@
BCB4FEAC14F24B0E00281019 /* RWindow.m in Sources */,
BCED54F614FA37BD00F5AD8A /* RTooltip.m in Sources */,
BCED54FA14FA380A00F5AD8A /* RChooseMenuItemDialog.m in Sources */,
BCF18DAC14FC8A1000670A26 /* RScriptEditorGlyphGenerator.m in Sources */,
BCF18DB014FC8A2200670A26 /* RScriptEditorLayoutManager.m in Sources */,
BCF18DB414FC8A3B00670A26 /* FoldingSignTextAttachmentCell.m in Sources */,
BCF18DB814FC8A5E00670A26 /* RScriptEditorTextStorage.m in Sources */,
BCF18DBC14FC8A7100670A26 /* RScriptEditorTypeSetter.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
15 changes: 4 additions & 11 deletions RController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1000,20 +1000,13 @@ - (void) fontSizeChangedBy:(float)delta withSender:(id)sender
NSRange r = [firstResponder selectedRange];
[firstResponder shouldChangeTextInRange:r replacementString:[[firstResponder string] substringWithRange:r]];
[[firstResponder textStorage] addAttribute:NSFontAttributeName value:font range:r];
// TODO: Invoke refreshing line numbering and view; no other way found yet
[firstResponder setAllowsUndo:NO];
[firstResponder setSelectedRange:NSMakeRange(r.location, 0)];
[firstResponder insertText:@""];
[firstResponder setSelectedRange:r];
[firstResponder setAllowsUndo:YES];
if([firstResponder lineNumberingEnabled]) {
[[[firstResponder enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
}
} else {
[[NSUserDefaults standardUserDefaults] setObject:[NSArchiver archivedDataWithRootObject:font] forKey:RScriptEditorDefaultFont];
// TODO: Invoke refreshing line numbering; no other way found yet
// and force to scroll view to cursor
if([firstResponder lineNumberingEnabled]) {
[firstResponder setAllowsUndo:NO];
[firstResponder insertText:@""];
[firstResponder setAllowsUndo:YES];
[[[firstResponder enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
}
}
}
Expand Down
Loading

0 comments on commit 7c3e992

Please sign in to comment.