Add a link to GitX Homepage in the about dialog
[GitX.git] / PBGitRevisionCell.m
blob83bf9060fbaf926fde2d4de3aa2517f8d23e09fb
1 //
2 //  PBGitRevisionCell.m
3 //  GitX
4 //
5 //  Created by Pieter de Bie on 17-06-08.
6 //  Copyright 2008 __MyCompanyName__. All rights reserved.
7 //
9 #import "PBGitRevisionCell.h"
10 #import "PBGitRef.h"
11 #import "RoundedRectangle.h"
13 @implementation PBGitRevisionCell
16 - (id) initWithCoder: (id) coder
18         self = [super initWithCoder:coder];
19         textCell = [[NSTextFieldCell alloc] initWithCoder:coder];
20         return self;
23 - (NSArray*) colors
25         return  [NSArray arrayWithObjects:
26                                 [NSColor colorWithCalibratedRed: 0X4e/256.0 green:0X9A/256.0 blue: 0X06/256.0 alpha: 1.0],
27                                 [NSColor colorWithCalibratedRed: 0X20/256.0 green:0X4A/256.0 blue: 0X87/256.0 alpha: 1.0],
28                                 [NSColor colorWithCalibratedRed: 0XC4/256.0 green:0XA0/256.0 blue: 0 alpha: 1.0],
29                                 [NSColor colorWithCalibratedRed: 0X5C/256.0 green:0X35/256.0 blue: 0X66/256.0 alpha: 1.0],
30                                 [NSColor colorWithCalibratedRed: 0XA4/256.0 green:0X00/256.0 blue: 0X00/256.0 alpha: 1.0],
31                                 [NSColor colorWithCalibratedRed: 0XCE/256.0 green:0X5C/256.0 blue: 0 alpha: 1.0],
32                                 nil];
35 - (void) drawLineFromColumn: (int) from toColumn: (int) to inRect: (NSRect) r offset: (int) offset color: (int) c
38         int columnWidth = 10;
39         NSPoint origin = r.origin;
40         
41         NSPoint source = NSMakePoint(origin.x + columnWidth* from, origin.y + offset);
42         NSPoint center = NSMakePoint( origin.x + columnWidth * to, origin.y + r.size.height * 0.5 + 0.5);
44         // Just use red for now.
45         NSArray* colors = [self colors];
46         [[colors objectAtIndex: c % [colors count]] set];
47         
48         NSBezierPath * path = [NSBezierPath bezierPath];
49         [path setLineWidth:2];
50         
51         [path moveToPoint: source];
52         [path lineToPoint: center];
53         [path stroke];
54         
57 - (void) drawCircleInRect: (NSRect) r
60         int c = cellInfo.position;
61         int columnWidth = 10;
62         NSPoint origin = r.origin;
63         NSPoint columnOrigin = { origin.x + columnWidth * c, origin.y};
65         NSRect oval = { columnOrigin.x - 5, columnOrigin.y + r.size.height * 0.5 - 5, 10, 10};
67         
68         NSBezierPath * path = [NSBezierPath bezierPathWithOvalInRect:oval];
70         [[NSColor blackColor] set];
71         [path fill];
72         
73         NSRect smallOval = { columnOrigin.x - 3, columnOrigin.y + r.size.height * 0.5 - 3, 6, 6};
74         [[NSColor whiteColor] set];
75         path = [NSBezierPath bezierPathWithOvalInRect:smallOval];
76         [path fill];    
79 - (void) drawTriangleInRect: (NSRect) r sign: (char) sign
81         int c = cellInfo.position;
82         int columnHeight = 10;
83         int columnWidth = 8;
85         NSPoint top;
86         if (sign == '<')
87                 top.x = round(r.origin.x) + 10 * c + 4;
88         else {
89                 top.x = round(r.origin.x) + 10 * c - 4;
90                 columnWidth *= -1;
91         }
92         top.y = r.origin.y + (r.size.height - columnHeight) / 2;
94         NSBezierPath * path = [NSBezierPath bezierPath];
95         // Start at top
96         [path moveToPoint: NSMakePoint(top.x, top.y)];
97         // Go down
98         [path lineToPoint: NSMakePoint(top.x, top.y + columnHeight)];
99         // Go left top
100         [path lineToPoint: NSMakePoint(top.x - columnWidth, top.y + columnHeight / 2)];
101         // Go to top again
102         [path closePath];
104         [[NSColor whiteColor] set];
105         [path fill];
106         [[NSColor blackColor] set];
107         [path setLineWidth: 2];
108         [path stroke];
111 - (NSMutableDictionary*) attributesForRefLabelSelected: (BOOL) selected isCurrentBranch: (BOOL) curBranch
113         NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
114         NSMutableParagraphStyle* style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
115         NSString *fontName;
117         if(curBranch)
118                 fontName = @"Helvetica-Bold";
119         else
120                 fontName = @"Helvetica";
121         
122         [style setAlignment:NSCenterTextAlignment];
123         [attributes setObject:style forKey:NSParagraphStyleAttributeName];
124         [attributes setObject:[NSFont fontWithName:fontName size:9] forKey:NSFontAttributeName];
126         //if (selected)
127         //      [attributes setObject:[NSColor alternateSelectedControlTextColor] forKey:NSForegroundColorAttributeName];
129         return attributes;
132 - (NSColor*) colorForRef: (PBGitRef*) ref
134         NSString* type = [ref type];
135         if ([type isEqualToString:@"head"])
136                 return [NSColor colorWithCalibratedRed: 0Xaa/256.0 green:0Xf2/256.0 blue: 0X54/256.0 alpha: 1.0];
137         else if ([type isEqualToString:@"remote"])
138                 return [NSColor colorWithCalibratedRed: 0xb2/256.0 green:0Xdf/256.0 blue: 0Xff/256.0 alpha: 1.0];
139         else if ([type isEqualToString:@"tag"])
140                 return [NSColor colorWithCalibratedRed: 0Xfc/256.0 green:0Xed/256.0 blue: 0X4f/256.0 alpha: 1.0];
141         
142         return [NSColor yellowColor];
145 -(NSArray *)rectsForRefsinRect:(NSRect) rect;
147         NSMutableArray *array = [NSMutableArray array];
148         
149         static const int ref_padding = 10;
150         static const int ref_spacing = 2;
151         
152         NSRect lastRect = rect;
153         lastRect.origin.x = round(lastRect.origin.x) - 0.5;
154         lastRect.origin.y = round(lastRect.origin.y) - 0.5;
155         
156         for (PBGitRef *ref in self.objectValue.refs) {
157                 NSMutableDictionary* attributes = [self attributesForRefLabelSelected:NO isCurrentBranch:NO];
158                 NSSize textSize = [[ref shortName] sizeWithAttributes:attributes];
159                 
160                 NSRect newRect = lastRect;
161                 newRect.size.width = textSize.width + ref_padding;
162                 newRect.size.height = textSize.height;
163                 newRect.origin.y = rect.origin.y + (rect.size.height - newRect.size.height) / 2;
164                 
165                 [array addObject:[NSValue valueWithRect:newRect]];
166                 lastRect = newRect;
167                 lastRect.origin.x += (int)lastRect.size.width + ref_spacing;
168         }
169         
170         return array;
173 - (void) drawLabelAtIndex:(int)index inRect:(NSRect)rect
175         NSArray *refs = self.objectValue.refs;
176         PBGitRef *ref = [refs objectAtIndex:index];
177         BOOL isCurBranch = [ref.ref isEqualToString:[[[controller repository] headRef] simpleRef]];
178         
179         NSMutableDictionary* attributes = [self attributesForRefLabelSelected:[self isHighlighted]
180                                                                                                                   isCurrentBranch:isCurBranch];
181         NSBezierPath *border = [NSBezierPath bezierPathWithRoundedRect:rect cornerRadius: 2.0];
182         [[self colorForRef:ref] set];
183         [border fill];
184         
185         [[ref shortName] drawInRect:rect withAttributes:attributes];
186         [border stroke];        
189 - (void) drawRefsInRect: (NSRect *)refRect
191         [[NSColor blackColor] setStroke];
193         NSRect lastRect;
194         int index = 0;
195         for (NSValue *rectValue in [self rectsForRefsinRect:*refRect])
196         {
197                 NSRect rect = [rectValue rectValue];
198                 [self drawLabelAtIndex:index inRect:rect];
199                 lastRect = rect;
200                 ++index;
201         }
202         refRect->size.width -= lastRect.origin.x - refRect->origin.x + lastRect.size.width;
203         refRect->origin.x    = lastRect.origin.x + lastRect.size.width;
206 - (void) drawWithFrame: (NSRect) rect inView:(NSView *)view
208         cellInfo = [self.objectValue lineInfo];
209         
210         if (cellInfo && ![controller hasNonlinearPath]) {
211                 float pathWidth = 10 + 10 * cellInfo.numColumns;
213                 NSRect ownRect;
214                 NSDivideRect(rect, &ownRect, &rect, pathWidth, NSMinXEdge);
216                 int i;
217                 struct PBGitGraphLine *lines = cellInfo.lines;
218                 for (i = 0; i < cellInfo.nLines; i++) {
219                         if (lines[i].upper == 0)
220                                 [self drawLineFromColumn: lines[i].from toColumn: lines[i].to inRect:ownRect offset: ownRect.size.height color: lines[i].colorIndex];
221                         else
222                                 [self drawLineFromColumn: lines[i].from toColumn: lines[i].to inRect:ownRect offset: 0 color:lines[i].colorIndex];
223                 }
225                 if (cellInfo.sign == '<' || cellInfo.sign == '>')
226                         [self drawTriangleInRect: ownRect sign: cellInfo.sign];
227                 else
228                         [self drawCircleInRect: ownRect];
229         }
232         if ([self.objectValue refs])
233                 [self drawRefsInRect:&rect];
235         // Still use this superclass because of hilighting differences
236         //_contents = [self.objectValue subject];
237         //[super drawWithFrame:rect inView:view];
238         [textCell setObjectValue: [self.objectValue subject]];
239         [textCell setHighlighted: [self isHighlighted]];
240         [textCell drawWithFrame:rect inView: view];
243 - (void) setObjectValue: (PBGitCommit*)object {
244         [super setObjectValue:[NSValue valueWithNonretainedObject:object]];
247 - (PBGitCommit*) objectValue {
248     return [[super objectValue] nonretainedObjectValue];
251 - (int) indexAtX:(float)x
253         cellInfo = [self.objectValue lineInfo];
254         float pathWidth = 0;
255         if (cellInfo && ![controller hasNonlinearPath])
256                 pathWidth = 10 + 10 * cellInfo.numColumns;
258         int index = 0;
259         NSRect refRect = NSMakeRect(pathWidth, 0, 1000, 10000);
260         for (NSValue *rectValue in [self rectsForRefsinRect:refRect])
261         {
262                 NSRect rect = [rectValue rectValue];
263                 if (x >= rect.origin.x && x <= (rect.origin.x + rect.size.width))
264                         return index;
265                 ++index;
266         }
268         return -1;
271 - (NSRect) rectAtIndex:(int)index
273         cellInfo = [self.objectValue lineInfo];
274         float pathWidth = 0;
275         if (cellInfo && ![controller hasNonlinearPath])
276                 pathWidth = 10 + 10 * cellInfo.numColumns;
277         NSRect refRect = NSMakeRect(pathWidth, 0, 1000, 10000);
279         return [[[self rectsForRefsinRect:refRect] objectAtIndex:index] rectValue];
282 # pragma mark context menu delegate methods
284 - (NSMenu *) menuForEvent:(NSEvent *)event inRect:(NSRect)rect ofView:(NSView *)view
286         if (!contextMenuDelegate)
287                 return [self menu];
289         int i = [self indexAtX:[view convertPointFromBase:[event locationInWindow]].x];
290         if (i < 0)
291                 return [self menu];
293         id ref = [[[self objectValue] refs] objectAtIndex:i];
294         if (!ref)
295                 return [self menu];
297         NSArray *items = [contextMenuDelegate menuItemsForRef:ref commit:[self objectValue]];
298         NSMenu *menu = [[NSMenu alloc] init];
299         for (NSMenuItem *item in items)
300                 [menu addItem:item];
301         return menu;
303         return [self menu];
305 @end