PageRenderTime 63ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/PBGitRevisionCell.m

https://github.com/dshafik/gitx
Objective C | 327 lines | 241 code | 70 blank | 16 comment | 37 complexity | 585ea1784be1d3fe4662661e5815c77c MD5 | raw file
  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. //
  8. #import "PBGitRevisionCell.h"
  9. #import "PBGitRef.h"
  10. #import "RoundedRectangle.h"
  11. #import "GitXTextFieldCell.h"
  12. @implementation PBGitRevisionCell
  13. - (id) initWithCoder: (id) coder
  14. {
  15. self = [super initWithCoder:coder];
  16. textCell = [[GitXTextFieldCell alloc] initWithCoder:coder];
  17. return self;
  18. }
  19. + (NSArray *)laneColors
  20. {
  21. static NSArray *laneColors = nil;
  22. if (!laneColors)
  23. laneColors = [NSArray arrayWithObjects:
  24. [NSColor colorWithCalibratedRed: 0X4e/256.0 green:0X9A/256.0 blue: 0X06/256.0 alpha: 1.0],
  25. [NSColor colorWithCalibratedRed: 0X20/256.0 green:0X4A/256.0 blue: 0X87/256.0 alpha: 1.0],
  26. [NSColor colorWithCalibratedRed: 0XC4/256.0 green:0XA0/256.0 blue: 0 alpha: 1.0],
  27. [NSColor colorWithCalibratedRed: 0X5C/256.0 green:0X35/256.0 blue: 0X66/256.0 alpha: 1.0],
  28. [NSColor colorWithCalibratedRed: 0XA4/256.0 green:0X00/256.0 blue: 0X00/256.0 alpha: 1.0],
  29. [NSColor colorWithCalibratedRed: 0XCE/256.0 green:0X5C/256.0 blue: 0 alpha: 1.0],
  30. nil];
  31. return laneColors;
  32. }
  33. - (void) drawLineFromColumn: (int) from toColumn: (int) to inRect: (NSRect) r offset: (int) offset color: (int) c
  34. {
  35. int columnWidth = 10;
  36. NSPoint origin = r.origin;
  37. NSPoint source = NSMakePoint(origin.x + columnWidth* from, origin.y + offset);
  38. NSPoint center = NSMakePoint( origin.x + columnWidth * to, origin.y + r.size.height * 0.5 + 0.5);
  39. NSArray* colors = [PBGitRevisionCell laneColors];
  40. NSColor * color = [colors objectAtIndex: c % [colors count]];
  41. [color set];
  42. NSBezierPath * path = [NSBezierPath bezierPath];
  43. [path setLineWidth:2];
  44. [path moveToPoint: source];
  45. [path lineToPoint: center];
  46. [path stroke];
  47. }
  48. - (BOOL) isCurrentCommit
  49. {
  50. NSString *thisSha = [self.objectValue sha];
  51. PBGitRepository* repository = [self.objectValue repository];
  52. NSString *currentSha = [repository headSHA];
  53. return [currentSha isEqual:thisSha];
  54. }
  55. - (void) drawCircleInRect: (NSRect) r
  56. {
  57. int c = cellInfo.position;
  58. int columnWidth = 10;
  59. NSPoint origin = r.origin;
  60. NSPoint columnOrigin = { origin.x + columnWidth * c, origin.y};
  61. NSRect oval = { columnOrigin.x - 5, columnOrigin.y + r.size.height * 0.5 - 5, 10, 10};
  62. NSBezierPath * path = [NSBezierPath bezierPathWithOvalInRect:oval];
  63. [[NSColor blackColor] set];
  64. [path fill];
  65. NSRect smallOval = { columnOrigin.x - 3, columnOrigin.y + r.size.height * 0.5 - 3, 6, 6};
  66. if ( [self isCurrentCommit ] ) {
  67. [[NSColor colorWithCalibratedRed: 0Xfc/256.0 green:0Xa6/256.0 blue: 0X4f/256.0 alpha: 1.0] set];
  68. } else {
  69. [[NSColor whiteColor] set];
  70. }
  71. path = [NSBezierPath bezierPathWithOvalInRect:smallOval];
  72. [path fill];
  73. }
  74. - (void) drawTriangleInRect: (NSRect) r sign: (char) sign
  75. {
  76. int c = cellInfo.position;
  77. int columnHeight = 10;
  78. int columnWidth = 8;
  79. NSPoint top;
  80. if (sign == '<')
  81. top.x = round(r.origin.x) + 10 * c + 4;
  82. else {
  83. top.x = round(r.origin.x) + 10 * c - 4;
  84. columnWidth *= -1;
  85. }
  86. top.y = r.origin.y + (r.size.height - columnHeight) / 2;
  87. NSBezierPath * path = [NSBezierPath bezierPath];
  88. // Start at top
  89. [path moveToPoint: NSMakePoint(top.x, top.y)];
  90. // Go down
  91. [path lineToPoint: NSMakePoint(top.x, top.y + columnHeight)];
  92. // Go left top
  93. [path lineToPoint: NSMakePoint(top.x - columnWidth, top.y + columnHeight / 2)];
  94. // Go to top again
  95. [path closePath];
  96. [[NSColor whiteColor] set];
  97. [path fill];
  98. [[NSColor blackColor] set];
  99. [path setLineWidth: 2];
  100. [path stroke];
  101. }
  102. - (NSMutableDictionary*) attributesForRefLabelSelected: (BOOL) selected
  103. {
  104. NSMutableDictionary *attributes = [[[NSMutableDictionary alloc] initWithCapacity:2] autorelease];
  105. NSMutableParagraphStyle* style = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
  106. [style setAlignment:NSCenterTextAlignment];
  107. [attributes setObject:style forKey:NSParagraphStyleAttributeName];
  108. [attributes setObject:[NSFont fontWithName:@"Helvetica" size:9] forKey:NSFontAttributeName];
  109. //if (selected)
  110. // [attributes setObject:[NSColor alternateSelectedControlTextColor] forKey:NSForegroundColorAttributeName];
  111. return attributes;
  112. }
  113. - (NSColor*) colorForRef: (PBGitRef*) ref
  114. {
  115. BOOL isHEAD = [ref.ref isEqualToString:[[[controller repository] headRef] simpleRef]];
  116. if (isHEAD)
  117. return [NSColor colorWithCalibratedRed: 0Xfc/256.0 green:0Xa6/256.0 blue: 0X4f/256.0 alpha: 1.0];
  118. NSString* type = [ref type];
  119. if ([type isEqualToString:@"head"])
  120. return [NSColor colorWithCalibratedRed: 0Xaa/256.0 green:0Xf2/256.0 blue: 0X54/256.0 alpha: 1.0];
  121. else if ([type isEqualToString:@"remote"])
  122. return [NSColor colorWithCalibratedRed: 0xb2/256.0 green:0Xdf/256.0 blue: 0Xff/256.0 alpha: 1.0];
  123. else if ([type isEqualToString:@"tag"])
  124. return [NSColor colorWithCalibratedRed: 0Xfc/256.0 green:0Xed/256.0 blue: 0X4f/256.0 alpha: 1.0];
  125. return [NSColor yellowColor];
  126. }
  127. -(NSArray *)rectsForRefsinRect:(NSRect) rect;
  128. {
  129. NSMutableArray *array = [NSMutableArray array];
  130. static const int ref_padding = 10;
  131. static const int ref_spacing = 2;
  132. NSRect lastRect = rect;
  133. lastRect.origin.x = round(lastRect.origin.x) + 0.5;
  134. lastRect.origin.y = round(lastRect.origin.y) + 0.5;
  135. for (PBGitRef *ref in self.objectValue.refs) {
  136. NSMutableDictionary* attributes = [self attributesForRefLabelSelected:NO];
  137. NSSize textSize = [[ref shortName] sizeWithAttributes:attributes];
  138. NSRect newRect = lastRect;
  139. newRect.size.width = textSize.width + ref_padding;
  140. newRect.size.height = textSize.height;
  141. newRect.origin.y = rect.origin.y + (rect.size.height - newRect.size.height) / 2;
  142. if (NSContainsRect(rect, newRect)) {
  143. [array addObject:[NSValue valueWithRect:newRect]];
  144. lastRect = newRect;
  145. lastRect.origin.x += (int)lastRect.size.width + ref_spacing;
  146. }
  147. }
  148. return array;
  149. }
  150. - (void) drawLabelAtIndex:(int)index inRect:(NSRect)rect
  151. {
  152. NSArray *refs = self.objectValue.refs;
  153. PBGitRef *ref = [refs objectAtIndex:index];
  154. NSMutableDictionary* attributes = [self attributesForRefLabelSelected:[self isHighlighted]];
  155. NSBezierPath *border = [NSBezierPath bezierPathWithRoundedRect:rect cornerRadius: 2.0];
  156. [[self colorForRef:ref] set];
  157. [border fill];
  158. [[ref shortName] drawInRect:rect withAttributes:attributes];
  159. [border stroke];
  160. }
  161. - (void) drawRefsInRect: (NSRect *)refRect
  162. {
  163. [[NSColor blackColor] setStroke];
  164. NSRect lastRect = NSMakeRect(0, 0, 0, 0);
  165. int index = 0;
  166. for (NSValue *rectValue in [self rectsForRefsinRect:*refRect])
  167. {
  168. NSRect rect = [rectValue rectValue];
  169. [self drawLabelAtIndex:index inRect:rect];
  170. lastRect = rect;
  171. ++index;
  172. }
  173. refRect->size.width -= lastRect.origin.x - refRect->origin.x + lastRect.size.width;
  174. refRect->origin.x = lastRect.origin.x + lastRect.size.width;
  175. }
  176. - (void) drawWithFrame: (NSRect) rect inView:(NSView *)view
  177. {
  178. cellInfo = [self.objectValue lineInfo];
  179. if (cellInfo && ![controller hasNonlinearPath]) {
  180. float pathWidth = 10 + 10 * cellInfo.numColumns;
  181. NSRect ownRect;
  182. NSDivideRect(rect, &ownRect, &rect, pathWidth, NSMinXEdge);
  183. int i;
  184. struct PBGitGraphLine *lines = cellInfo.lines;
  185. for (i = 0; i < cellInfo.nLines; i++) {
  186. if (lines[i].upper == 0)
  187. [self drawLineFromColumn: lines[i].from toColumn: lines[i].to inRect:ownRect offset: ownRect.size.height color: lines[i].colorIndex];
  188. else
  189. [self drawLineFromColumn: lines[i].from toColumn: lines[i].to inRect:ownRect offset: 0 color:lines[i].colorIndex];
  190. }
  191. if (cellInfo.sign == '<' || cellInfo.sign == '>')
  192. [self drawTriangleInRect: ownRect sign: cellInfo.sign];
  193. else
  194. [self drawCircleInRect: ownRect];
  195. }
  196. if ([self.objectValue refs] && [[self.objectValue refs] count])
  197. [self drawRefsInRect:&rect];
  198. // Still use this superclass because of hilighting differences
  199. //_contents = [self.objectValue subject];
  200. //[super drawWithFrame:rect inView:view];
  201. [textCell setObjectValue: [self.objectValue subject]];
  202. [textCell setHighlighted: [self isHighlighted]];
  203. [textCell drawWithFrame:rect inView: view];
  204. }
  205. - (void) setObjectValue: (PBGitCommit*)object {
  206. [super setObjectValue:[NSValue valueWithNonretainedObject:object]];
  207. }
  208. - (PBGitCommit*) objectValue {
  209. return [[super objectValue] nonretainedObjectValue];
  210. }
  211. - (int) indexAtX:(float)x
  212. {
  213. cellInfo = [self.objectValue lineInfo];
  214. float pathWidth = 0;
  215. if (cellInfo && ![controller hasNonlinearPath])
  216. pathWidth = 10 + 10 * cellInfo.numColumns;
  217. int index = 0;
  218. NSRect refRect = NSMakeRect(pathWidth, 0, 1000, 10000);
  219. for (NSValue *rectValue in [self rectsForRefsinRect:refRect])
  220. {
  221. NSRect rect = [rectValue rectValue];
  222. if (x >= rect.origin.x && x <= (rect.origin.x + rect.size.width))
  223. return index;
  224. ++index;
  225. }
  226. return -1;
  227. }
  228. - (NSRect) rectAtIndex:(int)index
  229. {
  230. cellInfo = [self.objectValue lineInfo];
  231. float pathWidth = 0;
  232. if (cellInfo && ![controller hasNonlinearPath])
  233. pathWidth = 10 + 10 * cellInfo.numColumns;
  234. NSRect refRect = NSMakeRect(pathWidth, 0, 1000, 10000);
  235. return [[[self rectsForRefsinRect:refRect] objectAtIndex:index] rectValue];
  236. }
  237. # pragma mark context menu delegate methods
  238. - (NSMenu *) menuForEvent:(NSEvent *)event inRect:(NSRect)rect ofView:(NSView *)view
  239. {
  240. if (!contextMenuDelegate)
  241. return [self menu];
  242. int i = [self indexAtX:[view convertPointFromBase:[event locationInWindow]].x - rect.origin.x];
  243. id ref = nil;
  244. if (i >= 0)
  245. ref = [[[self objectValue] refs] objectAtIndex:i];
  246. NSArray *items = nil;
  247. if (ref)
  248. items = [contextMenuDelegate menuItemsForRef:ref];
  249. else
  250. items = [contextMenuDelegate menuItemsForCommit:[self objectValue]];
  251. NSMenu *menu = [[NSMenu alloc] init];
  252. [menu setAutoenablesItems:NO];
  253. for (NSMenuItem *item in items)
  254. [menu addItem:item];
  255. return menu;
  256. }
  257. @end