Add the functionality to draw markers
[macgdbp.git] / Source / BSLineNumberView.m
1 /*
2 * MacGDBp
3 * Copyright (c) 2007 - 2008, Blue Static <http://www.bluestatic.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17 #import "BSLineNumberView.h"
18 #import "Breakpoint.h"
19 #import "BSSourceView.h"
20
21 @interface BSLineNumberView (Private)
22 - (void)drawMarkerInRect:(NSRect)rect;
23 @end
24
25 @implementation BSLineNumberView
26
27 @synthesize sourceView, lineNumberRange, markers;
28
29 /**
30 * Initializer for the line number view
31 */
32 - (id)initWithFrame:(NSRect)frame
33 {
34 if (self = [super initWithFrame:frame])
35 {
36 lineNumberRange = NSMakeRange(0, 0);
37 }
38 return self;
39 }
40
41 /**
42 * Flip the coordinates
43 */
44 - (BOOL)isFlipped
45 {
46 return YES;
47 }
48
49 /**
50 * Draws the line numbers whenever necessary
51 */
52 - (void)drawRect:(NSRect)rect
53 {
54 // background color
55 [[NSColor colorWithDeviceRed:0.871 green:0.871 blue:0.871 alpha:1] set];
56 [NSBezierPath fillRect:rect];
57
58 [[NSColor blackColor] set];
59 [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y)];
60
61 [[NSColor grayColor] set];
62 [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.size.height) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.size.height)];
63
64 // font attributes for the line number
65 NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:[NSFont fontWithName:@"Monaco" size:9.0], NSFontAttributeName, [NSColor grayColor], NSForegroundColorAttributeName, nil];
66
67 lineNumberRange = NSMakeRange(0, 0);
68
69 unsigned i = 0, line = 1;
70 while (i < [[[sourceView textView] layoutManager] numberOfGlyphs])
71 {
72 NSRange fragRange;
73 NSRect fragRect = [self convertRect:[[[sourceView textView] layoutManager] lineFragmentRectForGlyphAtIndex:i effectiveRange:&fragRange] fromView:[sourceView textView]];
74 fragRect.origin.x = rect.origin.x; // horizontal scrolling matters not
75 fragRect.size.width = [self bounds].size.width;
76
77 // we want to paint the top and bottom line number even if they're cut off
78 NSRect testRect = rect;
79 testRect.origin.y -= fragRect.size.height - 1;
80 testRect.size.height += fragRect.size.height - 1;
81 if (NSPointInRect(fragRect.origin, testRect))
82 {
83 lineNumberRange.location = (lineNumberRange.length == 0 ? line : lineNumberRange.location);
84 lineNumberRange.length++;
85 NSString *num = [NSString stringWithFormat:@"%u", line];
86 NSSize strSize = [num sizeWithAttributes:attrs];
87 [num drawAtPoint:NSMakePoint([self frame].size.width - strSize.width - 3, fragRect.origin.y + ((fragRect.size.height - strSize.height) / 2)) withAttributes:attrs];
88 if ([markers containsObject:[[Breakpoint alloc] initWithLine:line inFile:[sourceView file]]])
89 {
90 [self drawMarkerInRect:fragRect];
91 NSLog(@"marking %i", line);
92 }
93 }
94
95 i += fragRange.length;
96 line++;
97 }
98 }
99
100 /**
101 * Handles the mouse down event (which is adding, deleting, and toggling breakpoints)
102 */
103 - (void)mouseDown:(NSEvent *)event
104 {
105 NSTextView *textView = [sourceView textView];
106
107 NSPoint clickLoc = [self convertPoint:[event locationInWindow] fromView:nil];
108
109 unsigned line = 1;
110 unsigned i = 0;
111 while (i < [[textView layoutManager] numberOfGlyphs])
112 {
113 NSRange fragRange;
114 NSRect fragRect = [[textView layoutManager] lineFragmentRectForGlyphAtIndex:i effectiveRange:&fragRange];
115 fragRect.size.width = [self bounds].size.width;
116 if (NSPointInRect(clickLoc, fragRect))
117 {
118 [[sourceView delegate] gutterClickedAtLine:(line + lineNumberRange.location - 1) forFile:[sourceView file]];
119 return;
120 }
121
122 i += fragRange.length;
123 line++;
124 }
125 }
126
127 #pragma mark Private
128
129 /**
130 * Draws a marker in a given rectangle
131 */
132 - (void)drawMarkerInRect:(NSRect)rect
133 {
134 NSBezierPath *path = [NSBezierPath bezierPath];
135
136 [path moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 2)]; // initial origin
137 [path lineToPoint:NSMakePoint(rect.size.width - 7, rect.origin.y + 2)]; // upper right
138 [path curveToPoint:NSMakePoint(rect.size.width - 7, rect.origin.y + rect.size.height - 2)
139 controlPoint1:NSMakePoint(rect.size.width - 1, rect.origin.y + (rect.size.height / 2) - 1)
140 controlPoint2:NSMakePoint(rect.size.width - 1, rect.origin.y + (rect.size.height / 2) + 1)];
141 //[path lineToPoint:NSMakePoint(rect.size.width, rect.origin.y + rect.size.height)]; // lower right
142 [path lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + rect.size.height - 2)]; // lower left
143 [path lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 2)]; // upper left
144
145 [[NSColor colorWithDeviceRed:0.004 green:0.557 blue:0.851 alpha:0.75] set];
146 [path fill];
147 }
148
149 @end