IJInventoryView.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. //
  2. // IJInventoryView.m
  3. // InsideJob
  4. //
  5. // Created by Adam Preble on 10/9/10.
  6. // Copyright 2010 Adam Preble. All rights reserved.
  7. //
  8. #import "IJInventoryView.h"
  9. #import "IJInventoryItem.h"
  10. #import "IJItemPropertiesViewController.h"
  11. #import "MAAttachedWindow.h"
  12. NSString * const IJPasteboardTypeInventoryItem = @"net.adampreble.insidejob.inventoryitem";
  13. const static CGFloat cellSize = 32;
  14. const static CGFloat cellOffset = 40;
  15. @implementation IJInventoryView
  16. @synthesize delegate;
  17. - (id)initWithFrame:(NSRect)frameRect
  18. {
  19. if (self = [super initWithFrame:frameRect])
  20. {
  21. // Initialization code here.
  22. [self registerForDraggedTypes:[NSArray arrayWithObjects:IJPasteboardTypeInventoryItem, nil]];
  23. }
  24. return self;
  25. }
  26. - (void)dealloc
  27. {
  28. [items release];
  29. [mouseDownEvent release];
  30. [propertiesViewController release];
  31. [super dealloc];
  32. }
  33. - (void)awakeFromNib
  34. {
  35. }
  36. - (BOOL)acceptsFirstResponder
  37. {
  38. return YES;
  39. }
  40. - (void)removePropertiesWindow
  41. {
  42. [self.window removeChildWindow:propertiesWindow];
  43. [propertiesWindow orderOut:nil];
  44. [propertiesWindow release];
  45. propertiesWindow = nil;
  46. }
  47. - (BOOL)resignFirstResponder
  48. {
  49. [self removePropertiesWindow];
  50. return YES;
  51. }
  52. - (void)setRows:(int)numberOfRows columns:(int)numberOfColumns
  53. {
  54. CALayer *layer = [CALayer layer];
  55. layer.bounds = NSRectToCGRect(self.bounds);
  56. layer.anchorPoint = CGPointZero;
  57. layer.position = CGPointZero; //CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds));
  58. layer.geometryFlipped = YES;
  59. [self setLayer:layer];
  60. [self setWantsLayer:YES];
  61. rows = numberOfRows;
  62. cols = numberOfColumns;
  63. // reset the layers
  64. for (CALayer *layer in self.layer.sublayers)
  65. {
  66. [layer removeFromSuperlayer];
  67. }
  68. for (int y = 0; y < rows; y++)
  69. {
  70. for (int x = 0; x < cols; x++)
  71. {
  72. CALayer *layer = [CALayer layer];
  73. layer.anchorPoint = CGPointZero;
  74. layer.position = CGPointMake(x * cellOffset, y * cellOffset);
  75. layer.bounds = CGRectMake(0, 0, cellSize, cellSize);
  76. layer.borderWidth = 1.0;
  77. layer.borderColor = CGColorGetConstantColor(kCGColorBlack);
  78. [self.layer addSublayer:layer];
  79. }
  80. }
  81. }
  82. - (CALayer *)layerAtRow:(int)row column:(int)column
  83. {
  84. return [self.layer.sublayers objectAtIndex:row * cols + column];
  85. }
  86. - (void)setItems:(NSArray *)theItems
  87. {
  88. NSLog(@"%s", __PRETTY_FUNCTION__);
  89. [items autorelease];
  90. [theItems retain];
  91. items = theItems;
  92. //NSLog(@"%@ sublayers=%@", [self layer], self.layer.sublayers);
  93. [items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  94. IJInventoryItem *item = obj;
  95. CALayer *layer = [self.layer.sublayers objectAtIndex:idx];
  96. layer.contents = item.image;
  97. }];
  98. }
  99. - (int)itemIndexForPoint:(NSPoint)point
  100. {
  101. point.y = self.bounds.size.height - point.y;
  102. point.x /= cellOffset;
  103. point.y /= cellOffset;
  104. int index = floor(point.y) * cols + floor(point.x); // flip y
  105. return index;
  106. }
  107. #pragma mark -
  108. #pragma mark Drag & Drop: Source
  109. - (void)mouseDown:(NSEvent *)theEvent
  110. {
  111. [theEvent retain];
  112. [mouseDownEvent release];
  113. mouseDownEvent = theEvent;
  114. dragging = NO;
  115. }
  116. - (void)mouseDragged:(NSEvent *)theEvent
  117. {
  118. NSPoint mouseDownPoint = [mouseDownEvent locationInWindow];
  119. NSPoint mouseDragPoint = [theEvent locationInWindow];
  120. float dragDistance = hypot(mouseDownPoint.x - mouseDragPoint.x, mouseDownPoint.y - mouseDragPoint.y);
  121. if (dragDistance < 3)
  122. return;
  123. dragging = YES;
  124. // Find the IJInventoryItem:
  125. NSPoint pointInView = [self convertPoint:mouseDownPoint fromView:nil];
  126. int itemIndex = [self itemIndexForPoint:pointInView];
  127. IJInventoryItem *item = [items objectAtIndex:itemIndex];
  128. if (item.itemId == 0)
  129. return; // can't drag nothing
  130. NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
  131. [pasteboard declareTypes:[NSArray arrayWithObjects:IJPasteboardTypeInventoryItem, nil] owner:nil];
  132. [pasteboard setData:[NSKeyedArchiver archivedDataWithRootObject:item]
  133. forType:IJPasteboardTypeInventoryItem];
  134. NSImage *image = item.image;
  135. // Now clear out item:
  136. [delegate inventoryView:self removeItemAtIndex:itemIndex];
  137. NSPoint dragPoint = NSMakePoint(pointInView.x - image.size.width*0.5, pointInView.y - image.size.height*0.5);
  138. [self dragImage:image
  139. at:dragPoint
  140. offset:NSZeroSize
  141. event:mouseDownEvent
  142. pasteboard:pasteboard
  143. source:self
  144. slideBack:YES];
  145. }
  146. - (void)mouseUp:(NSEvent *)theEvent
  147. {
  148. if (!dragging)
  149. {
  150. // Show the properties window for this item.
  151. [self removePropertiesWindow];
  152. NSPoint mouseDownPoint = [mouseDownEvent locationInWindow];
  153. NSPoint pointInView = [self convertPoint:mouseDownPoint fromView:nil];
  154. int itemIndex = [self itemIndexForPoint:pointInView];
  155. IJInventoryItem *item = [items objectAtIndex:itemIndex];
  156. if (item.itemId == 0)
  157. return; // can't show info on nothing
  158. if (!propertiesViewController)
  159. {
  160. propertiesViewController = [[IJItemPropertiesViewController alloc] initWithNibName:@"ItemPropertiesView" bundle:nil];
  161. }
  162. propertiesViewController.item = item;
  163. propertiesWindow = [[MAAttachedWindow alloc] initWithView:propertiesViewController.view
  164. attachedToPoint:mouseDownPoint
  165. inWindow:self.window
  166. onSide:MAPositionRight
  167. atDistance:0];
  168. [propertiesWindow setViewMargin:10.0];
  169. [propertiesWindow setAlphaValue:0.0];
  170. [[propertiesWindow animator] setAlphaValue:1.0];
  171. [[self window] addChildWindow:propertiesWindow ordered:NSWindowAbove];
  172. }
  173. }
  174. - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
  175. {
  176. return NSDragOperationEvery;
  177. }
  178. //- (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint
  179. //{
  180. // NSLog(@"%s", __PRETTY_FUNCTION__);
  181. //}
  182. - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation
  183. {
  184. NSLog(@"%s operation=%d", __PRETTY_FUNCTION__, operation);
  185. if (operation == NSDragOperationMove)
  186. {
  187. //
  188. }
  189. }
  190. //- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint
  191. //{
  192. // NSLog(@"%s", __PRETTY_FUNCTION__);
  193. //}
  194. #pragma mark -
  195. #pragma mark Drag & Drop: Destination
  196. - (void)moveHighlightToLayerAtIndex:(int)index
  197. {
  198. [self.layer.sublayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  199. CALayer *layer = obj;
  200. if (idx == index)
  201. layer.borderColor = CGColorGetConstantColor(kCGColorWhite);
  202. else
  203. layer.borderColor = CGColorGetConstantColor(kCGColorBlack);
  204. }];
  205. }
  206. - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
  207. {
  208. // TODO: Detect and ignore same slot.
  209. int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
  210. [self moveHighlightToLayerAtIndex:index];
  211. if ([[sender draggingSource] isKindOfClass:[self class]])
  212. return NSDragOperationMove; // moving between inventories
  213. else
  214. return NSDragOperationCopy; // copying from the item selector, presumably
  215. }
  216. - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
  217. {
  218. // TODO: Detect and ignore same slot.
  219. int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
  220. [self moveHighlightToLayerAtIndex:index];
  221. if ([[sender draggingSource] isKindOfClass:[self class]])
  222. return NSDragOperationMove; // moving between inventories
  223. else
  224. return NSDragOperationCopy; // copying from the item selector, presumably
  225. }
  226. - (void)draggingExited:(id <NSDraggingInfo>)sender
  227. {
  228. [self moveHighlightToLayerAtIndex:-1];
  229. }
  230. - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
  231. {
  232. return YES;
  233. }
  234. - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
  235. {
  236. NSLog(@"%s operation=%d", __PRETTY_FUNCTION__, sender.draggingSourceOperationMask);
  237. int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
  238. NSData *itemData = [[sender draggingPasteboard] dataForType:IJPasteboardTypeInventoryItem];
  239. IJInventoryItem *item = [NSKeyedUnarchiver unarchiveObjectWithData:itemData];
  240. [delegate inventoryView:self setItem:item atIndex:index];
  241. return YES;
  242. }
  243. - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
  244. {
  245. [self moveHighlightToLayerAtIndex:-1];
  246. }
  247. @end