123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- //
- // IJInventoryView.m
- // InsideJob
- //
- // Created by Adam Preble on 10/9/10.
- // Copyright 2010 Adam Preble. All rights reserved.
- //
- #import "IJInventoryView.h"
- #import "IJInventoryItem.h"
- #import "MAAttachedWindow.h"
- #import "NSColor+Additions.h"
- #import <QuartzCore/QuartzCore.h>
- NSString * const IJPasteboardTypeInventoryItem = @"net.adampreble.insidejob.inventoryitem";
- const static CGFloat cellSize = 36;
- const static CGFloat cellOffset = 40;
- @implementation IJInventoryView
- @synthesize delegate;
- - (id)initWithFrame:(NSRect)frameRect
- {
- if (self = [super initWithFrame:frameRect])
- {
- // Initialization code here.
- [self registerForDraggedTypes:[NSArray arrayWithObjects:IJPasteboardTypeInventoryItem, nil]];
- }
- return self;
- }
- - (void)dealloc
- {
- [items release];
- [mouseDownEvent release];
- [super dealloc];
- }
- - (void)awakeFromNib
- {
- }
- - (BOOL)acceptsFirstResponder
- {
- return YES;
- }
- - (CGColorRef)borderColor
- {
- return [[NSColor colorWithCalibratedWhite:0.5 alpha:1.0] CGColor];
- }
- - (CGColorRef)highlightedBorderColor
- {
- return [[NSColor colorWithCalibratedWhite:0 alpha:1.0] CGColor];
- }
- // For use by external stuff, since it flips the coordinates and our layer uses flipped geometry.
- - (NSPoint)pointForItemAtIndex:(int)index
- {
- int x = index % cols;
- int y = index / cols;
- if (invert)
- y = rows - 1 - y;
- return NSMakePoint(x * cellOffset, self.bounds.size.height - y * cellOffset);
- }
- - (void)setRows:(int)numberOfRows columns:(int)numberOfColumns invert:(BOOL)inv
- {
- invert = inv;
-
- CALayer *layer = [CALayer layer];
-
- layer.bounds = NSRectToCGRect(self.bounds);
- layer.anchorPoint = CGPointZero;
- layer.position = CGPointZero; //CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds));
- layer.geometryFlipped = YES;
-
- [self setLayer:layer];
- [self setWantsLayer:YES];
-
- rows = numberOfRows;
- cols = numberOfColumns;
-
- // reset the layers
-
- for (CALayer *layer in self.layer.sublayers)
- {
- [layer removeFromSuperlayer];
- }
-
- for (int y = 0; y < rows; y++)
- {
- for (int x = 0; x < cols; x++)
- {
- CALayer *layer = [CALayer layer];
- layer.anchorPoint = CGPointZero;
-
- if (invert)
- layer.position = CGPointMake(x * cellOffset, (rows - 1 - y) * cellOffset);
- else
- layer.position = CGPointMake(x * cellOffset, y * cellOffset);
-
- layer.bounds = CGRectMake(0, 0, cellSize, cellSize);
- layer.borderWidth = 1.0;
- layer.borderColor = [self borderColor];
- layer.backgroundColor = [[NSColor colorWithCalibratedWhite:0.7 alpha:1.0] CGColor];
- layer.cornerRadius = 2.0;
-
- CALayer *imageLayer = [CALayer layer];
- imageLayer.position = CGPointMake(cellSize/2.0, cellSize/2.0);
- imageLayer.bounds = CGRectMake(0, 0, 32, 32);
- [layer addSublayer:imageLayer];
-
- CATextLayer *textLayer = [CATextLayer layer];
- textLayer.bounds = CGRectMake(0, 0, cellSize-2, 18);
- textLayer.position = CGPointMake(cellSize/2.0, cellSize/2.0 + 18/2 + 1);
- textLayer.foregroundColor = CGColorGetConstantColor(kCGColorWhite);
- textLayer.fontSize = 18;
- textLayer.shadowOpacity = 1.0;
- textLayer.shadowRadius = 0.5;
- textLayer.shadowOffset = CGSizeMake(0, 1);
- textLayer.alignmentMode = @"right";
- [layer addSublayer:textLayer];
-
- [self.layer addSublayer:layer];
- }
- }
- }
- - (void)reloadItemAtIndex:(int)itemIndex
- {
- IJInventoryItem *item = [items objectAtIndex:itemIndex];
- CALayer *layer = [self.layer.sublayers objectAtIndex:itemIndex];
-
- CALayer *imageLayer = [layer.sublayers objectAtIndex:0];
- imageLayer.contents = item.image;
-
- CATextLayer *textLayer = [layer.sublayers objectAtIndex:1];
- if (item.count <= 1) // for 1 and 0, show no number.
- textLayer.string = @"";
- else
- textLayer.string = [NSString stringWithFormat:@"%d", item.count];
- }
- - (void)setItems:(NSArray *)theItems
- {
- [items autorelease];
- [theItems retain];
- items = theItems;
-
- for (int i = 0; i < items.count; i++)
- [self reloadItemAtIndex:i];
- }
- - (int)itemIndexForPoint:(NSPoint)point
- {
- point.y = self.bounds.size.height - point.y;
- point.x /= cellOffset;
- point.y /= cellOffset;
- if (invert)
- point.y = rows - 1 - floor(point.y);
- int index = floor(point.y) * cols + floor(point.x); // flip y
- return index;
- }
- #pragma mark -
- #pragma mark Drag & Drop: Source
- - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
- {
- // NSLog(@"%s", __PRETTY_FUNCTION__);
- // if (propertiesWindow) // take the first mouse while the properties window is up.
- // return YES;
- // else
- // return NO;
- // the above doesn't work since the window has already been dismissed by the time we get here
- return YES;
- }
- - (void)mouseDown:(NSEvent *)theEvent
- {
- [theEvent retain];
- [mouseDownEvent release];
- mouseDownEvent = theEvent;
- dragging = NO;
- }
- - (void)mouseDragged:(NSEvent *)theEvent
- {
- NSPoint mouseDownPoint = [mouseDownEvent locationInWindow];
- NSPoint mouseDragPoint = [theEvent locationInWindow];
- float dragDistance = hypot(mouseDownPoint.x - mouseDragPoint.x, mouseDownPoint.y - mouseDragPoint.y);
- if (dragDistance < 3)
- return;
-
- dragging = YES;
-
- // Find the IJInventoryItem:
- NSPoint pointInView = [self convertPoint:mouseDownPoint fromView:nil];
- int itemIndex = [self itemIndexForPoint:pointInView];
- IJInventoryItem *item = [items objectAtIndex:itemIndex];
- if (item.itemId == 0)
- return; // can't drag nothing
-
- NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
-
- [pasteboard declareTypes:[NSArray arrayWithObjects:IJPasteboardTypeInventoryItem, nil] owner:nil];
-
- [pasteboard setData:[NSKeyedArchiver archivedDataWithRootObject:item]
- forType:IJPasteboardTypeInventoryItem];
-
- NSImage *image = item.image;
-
- // Now clear out item, if the option key isn't down (option for copy):
- if (([theEvent modifierFlags] & NSAlternateKeyMask) == 0)
- [delegate inventoryView:self removeItemAtIndex:itemIndex];
-
- NSPoint dragPoint = NSMakePoint(pointInView.x - image.size.width*0.5, pointInView.y - image.size.height*0.5);
-
- [self dragImage:image
- at:dragPoint
- offset:NSZeroSize
- event:mouseDownEvent
- pasteboard:pasteboard
- source:self
- slideBack:NO];
- }
- - (void)mouseUp:(NSEvent *)theEvent
- {
- if (!dragging)
- {
- NSPoint mouseDownPoint = [mouseDownEvent locationInWindow];
- NSPoint pointInView = [self convertPoint:mouseDownPoint fromView:nil];
-
- int itemIndex = [self itemIndexForPoint:pointInView];
- [delegate inventoryView:self selectedItemAtIndex:itemIndex];
- }
- }
- - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal
- {
- return NSDragOperationEvery;
- }
- //- (void)draggedImage:(NSImage *)image beganAt:(NSPoint)screenPoint
- //{
- // NSLog(@"%s", __PRETTY_FUNCTION__);
- //}
- - (void)draggedImage:(NSImage *)image endedAt:(NSPoint)screenPoint operation:(NSDragOperation)operation
- {
- NSLog(@"%s operation=%d", __PRETTY_FUNCTION__, operation);
-
- if (operation == NSDragOperationMove)
- {
- //
- }
- }
- //- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint
- //{
- // NSLog(@"%s", __PRETTY_FUNCTION__);
- //}
- #pragma mark -
- #pragma mark Drag & Drop: Destination
- - (void)moveHighlightToLayerAtIndex:(int)index
- {
- [self.layer.sublayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
- CALayer *layer = obj;
- if (idx == index)
- layer.borderColor = [self highlightedBorderColor];
- else
- layer.borderColor = [self borderColor];
- }];
- }
- - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
- {
- // TODO: Detect and ignore same slot.
- int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
- [self moveHighlightToLayerAtIndex:index];
-
- if ([[sender draggingSource] isKindOfClass:[self class]])
- return NSDragOperationMove; // moving between inventories
- else
- return NSDragOperationCopy; // copying from the item selector, presumably
- }
- - (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
- {
- // TODO: Detect and ignore same slot.
- int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
- [self moveHighlightToLayerAtIndex:index];
- if ([[sender draggingSource] isKindOfClass:[self class]])
- return NSDragOperationMove; // moving between inventories
- else
- return NSDragOperationCopy; // copying from the item selector, presumably
- }
- - (void)draggingExited:(id <NSDraggingInfo>)sender
- {
- [self moveHighlightToLayerAtIndex:-1];
- }
- - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
- {
- return YES;
- }
- - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
- {
- //NSLog(@"%s operation=%d", __PRETTY_FUNCTION__, sender.draggingSourceOperationMask);
-
- int index = [self itemIndexForPoint:[self convertPoint:[sender draggingLocation] fromView:nil]];
-
- NSData *itemData = [[sender draggingPasteboard] dataForType:IJPasteboardTypeInventoryItem];
- IJInventoryItem *item = [NSKeyedUnarchiver unarchiveObjectWithData:itemData];
-
- IJInventoryItem *existingItem = [items objectAtIndex:index];
-
- if (existingItem.itemId == item.itemId)
- {
- item.count = MIN(64, item.count + existingItem.count);
- }
- [delegate inventoryView:self setItem:item atIndex:index];
- return YES;
- }
- - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
- {
- [self moveHighlightToLayerAtIndex:-1];
- }
- @end
|