Skip to content
Browse files

First commit of GMGridView

  • Loading branch information...
1 parent 45180e2 commit 4748931e34a424f80b8d657cdf14d3d3ad018062 @gmoledina committed Oct 10, 2011
View
289 GMGridView.xcodeproj/project.pbxproj
@@ -0,0 +1,289 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1691D7A11442CFA800F472BF /* GMGridView-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1691D7A01442CFA800F472BF /* GMGridView-Info.plist */; };
+ 1691D7A41442CFC300F472BF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7A31442CFC300F472BF /* main.m */; };
+ 1691D7AA1442D01F00F472BF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7A71442D01F00F472BF /* AppDelegate.m */; };
+ 1691D7AB1442D01F00F472BF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7A91442D01F00F472BF /* ViewController.m */; };
+ 1691D7AE1442D02C00F472BF /* GMGridView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7AD1442D02C00F472BF /* GMGridView.m */; };
+ 16924B0C144156FE00E6E556 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0B144156FE00E6E556 /* UIKit.framework */; };
+ 16924B0E144156FE00E6E556 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0D144156FE00E6E556 /* Foundation.framework */; };
+ 16924B10144156FE00E6E556 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0F144156FE00E6E556 /* CoreGraphics.framework */; };
+ 16924B16144156FE00E6E556 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 16924B14144156FE00E6E556 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 1691D7A01442CFA800F472BF /* GMGridView-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GMGridView-Info.plist"; path = "GMGridView/GMGridView-Info.plist"; sourceTree = SOURCE_ROOT; };
+ 1691D7A21442CFC300F472BF /* GMGridView-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GMGridView-Prefix.pch"; path = "GMGridView/GMGridView-Prefix.pch"; sourceTree = SOURCE_ROOT; };
+ 1691D7A31442CFC300F472BF /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = GMGridView/main.m; sourceTree = SOURCE_ROOT; };
+ 1691D7A61442D01F00F472BF /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = GMGridView/AppDelegate.h; sourceTree = SOURCE_ROOT; };
+ 1691D7A71442D01F00F472BF /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = GMGridView/AppDelegate.m; sourceTree = SOURCE_ROOT; };
+ 1691D7A81442D01F00F472BF /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ViewController.h; path = GMGridView/ViewController.h; sourceTree = SOURCE_ROOT; };
+ 1691D7A91442D01F00F472BF /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ViewController.m; path = GMGridView/ViewController.m; sourceTree = SOURCE_ROOT; };
+ 1691D7AC1442D02C00F472BF /* GMGridView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GMGridView.h; path = GMGridView/API/GMGridView.h; sourceTree = SOURCE_ROOT; };
+ 1691D7AD1442D02C00F472BF /* GMGridView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GMGridView.m; path = GMGridView/API/GMGridView.m; sourceTree = SOURCE_ROOT; };
+ 16924B07144156FE00E6E556 /* GMGridView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GMGridView.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 16924B0B144156FE00E6E556 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 16924B0D144156FE00E6E556 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 16924B0F144156FE00E6E556 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 16924B04144156FE00E6E556 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 16924B0C144156FE00E6E556 /* UIKit.framework in Frameworks */,
+ 16924B0E144156FE00E6E556 /* Foundation.framework in Frameworks */,
+ 16924B10144156FE00E6E556 /* CoreGraphics.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 16924AFC144156FD00E6E556 = {
+ isa = PBXGroup;
+ children = (
+ 16924B11144156FE00E6E556 /* Demo */,
+ 16924B361442CA9400E6E556 /* API */,
+ 16924B0A144156FE00E6E556 /* Frameworks */,
+ 16924B08144156FE00E6E556 /* Products */,
+ );
+ sourceTree = "<group>";
+ };
+ 16924B08144156FE00E6E556 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 16924B07144156FE00E6E556 /* GMGridView.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 16924B0A144156FE00E6E556 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 16924B0B144156FE00E6E556 /* UIKit.framework */,
+ 16924B0D144156FE00E6E556 /* Foundation.framework */,
+ 16924B0F144156FE00E6E556 /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 16924B11144156FE00E6E556 /* Demo */ = {
+ isa = PBXGroup;
+ children = (
+ 1691D7A61442D01F00F472BF /* AppDelegate.h */,
+ 1691D7A71442D01F00F472BF /* AppDelegate.m */,
+ 1691D7A81442D01F00F472BF /* ViewController.h */,
+ 1691D7A91442D01F00F472BF /* ViewController.m */,
+ 16924B12144156FE00E6E556 /* Supporting Files */,
+ );
+ name = Demo;
+ path = DraggableGridView;
+ sourceTree = "<group>";
+ };
+ 16924B12144156FE00E6E556 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 1691D7A01442CFA800F472BF /* GMGridView-Info.plist */,
+ 1691D7A21442CFC300F472BF /* GMGridView-Prefix.pch */,
+ 1691D7A31442CFC300F472BF /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 16924B361442CA9400E6E556 /* API */ = {
+ isa = PBXGroup;
+ children = (
+ 1691D7AC1442D02C00F472BF /* GMGridView.h */,
+ 1691D7AD1442D02C00F472BF /* GMGridView.m */,
+ );
+ name = API;
+ path = DraggableGridView/API;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 16924B06144156FE00E6E556 /* GMGridView */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 16924B28144156FE00E6E556 /* Build configuration list for PBXNativeTarget "GMGridView" */;
+ buildPhases = (
+ 16924B03144156FE00E6E556 /* Sources */,
+ 16924B04144156FE00E6E556 /* Frameworks */,
+ 16924B05144156FE00E6E556 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = GMGridView;
+ productName = DraggableGridView;
+ productReference = 16924B07144156FE00E6E556 /* GMGridView.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 16924AFE144156FD00E6E556 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0420;
+ ORGANIZATIONNAME = GMoledina.ca;
+ };
+ buildConfigurationList = 16924B01144156FD00E6E556 /* Build configuration list for PBXProject "GMGridView" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 16924AFC144156FD00E6E556;
+ productRefGroup = 16924B08144156FE00E6E556 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 16924B06144156FE00E6E556 /* GMGridView */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 16924B05144156FE00E6E556 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 16924B16144156FE00E6E556 /* InfoPlist.strings in Resources */,
+ 1691D7A11442CFA800F472BF /* GMGridView-Info.plist in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 16924B03144156FE00E6E556 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 1691D7A41442CFC300F472BF /* main.m in Sources */,
+ 1691D7AA1442D01F00F472BF /* AppDelegate.m in Sources */,
+ 1691D7AB1442D01F00F472BF /* ViewController.m in Sources */,
+ 1691D7AE1442D02C00F472BF /* GMGridView.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 16924B14144156FE00E6E556 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ );
+ name = InfoPlist.strings;
+ path = "/Users/gmoledina/Documents/iOS Projects/GMGridView/DraggableGridView";
+ sourceTree = "<absolute>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 16924B26144156FE00E6E556 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 16924B27144156FE00E6E556 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 5.0;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 16924B29144156FE00E6E556 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "GMGridView/GMGridView-Prefix.pch";
+ INFOPLIST_FILE = "GMGridView/GMGridView-Info.plist";
+ PRODUCT_NAME = GMGridView;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 16924B2A144156FE00E6E556 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "GMGridView/GMGridView-Prefix.pch";
+ INFOPLIST_FILE = "GMGridView/GMGridView-Info.plist";
+ PRODUCT_NAME = GMGridView;
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 16924B01144156FD00E6E556 /* Build configuration list for PBXProject "GMGridView" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 16924B26144156FE00E6E556 /* Debug */,
+ 16924B27144156FE00E6E556 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 16924B28144156FE00E6E556 /* Build configuration list for PBXNativeTarget "GMGridView" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 16924B29144156FE00E6E556 /* Debug */,
+ 16924B2A144156FE00E6E556 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 16924AFE144156FD00E6E556 /* Project object */;
+}
View
7 GMGridView.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:GMGridView.xcodeproj">
+ </FileRef>
+</Workspace>
View
70 GMGridView/API/GMGridView.h
@@ -0,0 +1,70 @@
+//
+// GMGridView.h
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@protocol DraggableGridViewDelegate;
+@protocol DraggableGridViewDataSource;
+
+typedef enum
+{
+ DraggableGridViewStylePush = 0,
+ DraggableGridViewStyleSwap
+} DraggableGridViewStyle;
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Interface DraggableGridView
+//////////////////////////////////////////////////////////////
+
+@interface GMGridView : UIView
+{
+
+}
+
+@property (nonatomic, weak) id<DraggableGridViewDataSource> dataSource;
+@property (nonatomic, weak) id<DraggableGridViewDelegate> delegate;
+
+@property (nonatomic, assign) NSInteger itemPadding;
+@property (nonatomic, assign) DraggableGridViewStyle style;
+@property (nonatomic) CFTimeInterval minimumPressDuration; // If set to 0, the scrollView will not be scrollable
+
+- (void)reloadData;
+- (void)insertObjectAtIndex:(NSInteger)index;
+- (void)removeObjectAtIndex:(NSInteger)index;
+- (void)swapObjectAtIndex:(NSInteger)index1 withObjectAtIndex:(NSInteger)index2;
+- (void)reloadObjectAtIndex:(NSInteger)index;
+
+@end
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Protocol DraggableGridViewDataSource
+//////////////////////////////////////////////////////////////
+
+@protocol DraggableGridViewDataSource
+
+- (NSInteger)numberOfItemsInDraggableView:(GMGridView *)draggableView;
+- (NSInteger)widthForItemsInDraggableView:(GMGridView *)draggableView;
+- (NSInteger)heightForItemsInDraggableView:(GMGridView *)draggableView;
+- (UIView *)draggableView:(GMGridView *)draggableView viewForItemAtIndex:(NSInteger)index;
+
+@end
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Protocol DraggableGridViewDelegate
+//////////////////////////////////////////////////////////////
+
+@protocol DraggableGridViewDelegate
+
+- (void)draggableView:(GMGridView *)draggableView didStartMovingView:(UIView *)view;
+- (void)draggableView:(GMGridView *)draggableView didEndMovingView:(UIView *)view;
+- (void)draggableView:(GMGridView *)draggableView itemAtIndex:(NSInteger)oldIndex movedToIndex:(NSInteger)newIndex;
+
+@end
View
528 GMGridView/API/GMGridView.m
@@ -0,0 +1,528 @@
+//
+// GMGridView.m
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import "GMGridView.h"
+
+#define GMGV_POSITION_AND_TAG_OFFSET 50
+
+//////////////////////////////////////////////////////////////
+#pragma -
+#pragma mark Private interface
+//////////////////////////////////////////////////////////////
+
+@interface GMGridView () <UIGestureRecognizerDelegate>
+{
+ // Views
+ UIScrollView *m_scrollView;
+ NSMutableOrderedSet *m_orderedSubviews;
+
+ // Gestures
+ UIPanGestureRecognizer *m_panGesture;
+ UILongPressGestureRecognizer *m_longPressGesture;
+
+ // General vars
+ NSInteger m_numberOfItemsInRow;
+ CGSize m_itemSize;
+
+ // Moving control vars
+ UIView *m_movingItem;
+ NSInteger m_futurePosition;
+ CGPoint m_movingItemStartingPoint;
+}
+
+// Gestures
+- (void)panGestureUpdated:(UIPanGestureRecognizer *)panGesture;
+- (void)longPressGestureUpdated:(UILongPressGestureRecognizer *)longPressGesture;
+
+// Movement control
+- (void)movingDidStartAtPoint:(CGPoint)point;
+- (void)movingDidContinueToPoint:(CGPoint)point;
+- (void)movingDidStopAtPoint:(CGPoint)point;
+- (void)updateIndexOfItem:(UIView *)view toIndex:(NSInteger)index;
+
+// Helpers & more
+- (CGSize)relayoutItems;
+- (NSInteger)itemPositionFromLocation:(CGPoint)location;
+
+
+@end
+
+
+
+
+//////////////////////////////////////////////////////////////
+#pragma -
+#pragma mark Implementation
+//////////////////////////////////////////////////////////////
+
+@implementation GMGridView
+
+@synthesize delegate = mw_delegate, dataSource = mw_dataSource;
+@synthesize itemPadding = m_itemPadding;
+@synthesize style = m_style;
+@synthesize minimumPressDuration;
+
+//////////////////////////////////////////////////////////////
+#pragma mark Constructors and destructor
+//////////////////////////////////////////////////////////////
+
+- (id)init
+{
+ return [self initWithFrame:CGRectZero];
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if ((self = [super initWithFrame:frame]))
+ {
+ m_orderedSubviews = [[NSMutableOrderedSet alloc] init];
+
+ m_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureUpdated:)];
+ m_panGesture.delegate = self;
+ [self addGestureRecognizer:m_panGesture];
+
+ m_longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureUpdated:)];
+ [self addGestureRecognizer:m_longPressGesture];
+
+ m_scrollView = [[UIScrollView alloc] initWithFrame:frame];
+ m_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ m_scrollView.backgroundColor = [UIColor yellowColor];
+ [m_scrollView.panGestureRecognizer requireGestureRecognizerToFail:m_panGesture];
+ [self addSubview:m_scrollView];
+
+ self.itemPadding = 10;
+ self.style = DraggableGridViewStylePush;
+ self.minimumPressDuration = 0.2;
+
+ m_futurePosition = -1;
+ m_itemSize = CGSizeZero;
+ }
+ return self;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Layout
+//////////////////////////////////////////////////////////////
+
+- (void)layoutSubviews
+{
+ [super layoutSubviews];
+
+ m_scrollView.contentSize = [self relayoutItems];
+ [m_scrollView flashScrollIndicators];
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Custom drawing
+//////////////////////////////////////////////////////////////
+
+//- (void)drawRect:(CGRect)rect {
+// // Drawing code
+//}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Setters / getters
+//////////////////////////////////////////////////////////////
+
+- (void)setDataSource:(NSObject<DraggableGridViewDataSource> *)dataSource
+{
+ mw_dataSource = dataSource;
+ [self reloadData];
+}
+
+- (void)setItemPadding:(NSInteger)itemPadding
+{
+ m_itemPadding = itemPadding;
+ [self setNeedsLayout];
+}
+
+- (void)setMinimumPressDuration:(CFTimeInterval)duration
+{
+ m_longPressGesture.minimumPressDuration = duration;
+}
+
+- (CFTimeInterval)minimumPressDuration
+{
+ return m_longPressGesture.minimumPressDuration;
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark GestureRecognizer delegate
+//////////////////////////////////////////////////////////////
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
+{
+ return YES;
+}
+
+- (void)longPressGestureUpdated:(UILongPressGestureRecognizer *)longPressGesture
+{
+ switch (longPressGesture.state)
+ {
+ case UIGestureRecognizerStateBegan:
+ {
+ CGPoint location = [longPressGesture locationInView:m_scrollView];
+
+ NSInteger position = [self itemPositionFromLocation:location];
+
+ if (position >= 0)
+ {
+ UIView *item = [m_scrollView viewWithTag:position];
+
+ if (CGRectContainsPoint(item.frame, location))
+ {
+ [m_scrollView bringSubviewToFront:item];
+ m_movingItem = item;
+
+ [self movingDidStartAtPoint:location];
+ }
+ }
+ break;
+ }
+
+ case UIGestureRecognizerStateEnded:
+ case UIGestureRecognizerStateCancelled:
+ case UIGestureRecognizerStateFailed:
+ {
+ if (m_movingItem)
+ {
+ CGPoint location = [longPressGesture locationInView:m_scrollView];
+ [self movingDidStopAtPoint:location];
+ m_movingItem = nil;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
+{
+ return (m_movingItem != nil);
+}
+
+- (void)panGestureUpdated:(UIPanGestureRecognizer *)panGesture
+{
+ switch (panGesture.state)
+ {
+ case UIGestureRecognizerStateEnded:
+ case UIGestureRecognizerStateCancelled:
+ case UIGestureRecognizerStateFailed:
+ {
+ m_movingItemStartingPoint = CGPointZero;
+ break;
+ }
+ case UIGestureRecognizerStateBegan:
+ {
+ m_movingItemStartingPoint = [panGesture locationInView:m_scrollView];
+
+ break;
+ }
+ case UIGestureRecognizerStateChanged:
+ {
+ CGPoint translation = [panGesture translationInView:m_scrollView];
+ CGPoint offset = translation;
+
+ m_movingItem.transform = CGAffineTransformMakeTranslation(offset.x, offset.y);
+ [self movingDidContinueToPoint:[panGesture locationInView:m_scrollView]];
+
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Privates Movement control
+//////////////////////////////////////////////////////////////
+
+- (void)movingDidStartAtPoint:(CGPoint)point
+{
+ [self bringSubviewToFront:m_movingItem];
+
+ m_futurePosition = m_movingItem.tag;
+
+ [self.delegate draggableView:self didStartMovingView:m_movingItem];
+}
+
+- (void)movingDidContinueToPoint:(CGPoint)point
+{
+ int position = [self itemPositionFromLocation:point];
+
+ if (position >= 0 && position != m_futurePosition && (position - GMGV_POSITION_AND_TAG_OFFSET) < [m_orderedSubviews count])
+ {
+ BOOL positionTaken = NO;
+
+ for (UIView *v in m_orderedSubviews)
+ {
+ if (v != m_movingItem && v.tag == position)
+ {
+ positionTaken = YES;
+ break;
+ }
+ }
+
+ if (positionTaken)
+ {
+ switch (self.style)
+ {
+ case DraggableGridViewStylePush:
+ {
+ if (position > m_futurePosition)
+ {
+ for (UIView *v in m_orderedSubviews)
+ {
+ if (v.tag == position || (v.tag < position && v.tag >= m_futurePosition))
+ {
+ v.tag = v.tag - 1;
+ }
+ }
+ }
+ else
+ {
+ for (UIView *v in m_orderedSubviews)
+ {
+ if (v.tag == position || (v.tag > position && v.tag <= m_futurePosition))
+ {
+ v.tag = v.tag + 1;
+ }
+ }
+ }
+ break;
+ }
+ case DraggableGridViewStyleSwap:
+ default:
+ {
+ UIView *v = [m_scrollView viewWithTag:position];
+ v.tag = m_futurePosition;
+ [self updateIndexOfItem:v toIndex:v.tag - GMGV_POSITION_AND_TAG_OFFSET];
+ break;
+ }
+ }
+ }
+
+ m_futurePosition = position;
+
+ [self setNeedsLayout];
+ }
+}
+
+- (void)movingDidStopAtPoint:(CGPoint)point
+{
+ m_movingItem.tag = m_futurePosition;
+ [self updateIndexOfItem:m_movingItem toIndex:m_movingItem.tag - GMGV_POSITION_AND_TAG_OFFSET];
+ m_futurePosition = -1;
+
+ [self.delegate draggableView:self didEndMovingView:m_movingItem];
+
+ [UIView animateWithDuration:0.2 animations:^() {
+ m_movingItem.transform = CGAffineTransformIdentity;
+ m_movingItem = nil;
+ [self relayoutItems];
+ }];
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark public methods
+//////////////////////////////////////////////////////////////
+
+- (void)reloadData
+{
+ [m_orderedSubviews enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop){
+ [(UIView *)obj removeFromSuperview];
+ }];
+
+ [m_orderedSubviews removeAllObjects];
+
+ NSUInteger numberItems = [self.dataSource numberOfItemsInDraggableView:self];
+ NSUInteger width = [self.dataSource widthForItemsInDraggableView:self];
+ NSUInteger height = [self.dataSource heightForItemsInDraggableView:self];
+
+ for (int i = 0; i < numberItems; i++)
+ {
+ UIView *itemView = [self.dataSource draggableView:self viewForItemAtIndex:i];
+ itemView.frame = CGRectMake(0, 0, width, height);
+ itemView.tag = i + GMGV_POSITION_AND_TAG_OFFSET;
+
+ [m_scrollView addSubview:itemView];
+ [m_orderedSubviews addObject:itemView];
+ }
+
+ m_itemSize = CGSizeMake(width, height);
+ [self setNeedsLayout];
+}
+
+- (void)reloadObjectAtIndex:(NSInteger)index
+{
+ NSAssert((index >= 0 && index < [m_orderedSubviews count]), @"Invalid index");
+
+ UIView *currentView = [m_orderedSubviews objectAtIndex:index];
+
+ UIView *view = [self.dataSource draggableView:self viewForItemAtIndex:index];
+ view.frame = currentView.frame;
+ view.tag = currentView.tag;
+ view.alpha = 0;
+ [m_scrollView addSubview:view];
+
+ [m_orderedSubviews replaceObjectAtIndex:index withObject:view];
+
+ [UIView animateWithDuration:0.3 animations:^{
+ currentView.alpha = 0;
+ view.alpha = 1;
+ }
+ completion:^(BOOL finished)
+ {
+ [currentView removeFromSuperview];
+ [self setNeedsLayout];
+ }];
+}
+
+- (void)insertObjectAtIndex:(NSInteger)index
+{
+ NSAssert((index >= 0 && index <= [m_orderedSubviews count]), @"Invalid index specified");
+
+ UIView *view = [self.dataSource draggableView:self viewForItemAtIndex:index];
+ view.frame = CGRectMake(-20, -20, m_itemSize.width, m_itemSize.height);
+ view.tag = index + GMGV_POSITION_AND_TAG_OFFSET;
+
+ for (int i = index; i < [m_orderedSubviews count]; i++)
+ {
+ UIView *oldView = [m_orderedSubviews objectAtIndex:i];
+ oldView.tag = oldView.tag + 1;
+ }
+
+ [m_orderedSubviews insertObject:view atIndex:index];
+ [m_scrollView addSubview:view];
+ [self setNeedsLayout];
+}
+
+- (void)removeObjectAtIndex:(NSInteger)index
+{
+ NSAssert((index >= 0 && index < [m_orderedSubviews count]), @"Invalid index specified");
+
+ UIView *view = (UIView *)[m_orderedSubviews objectAtIndex:index];
+
+ for (int i = index + 1; i < [m_orderedSubviews count]; i++)
+ {
+ UIView *oldView = [m_orderedSubviews objectAtIndex:i];
+ oldView.tag = oldView.tag - 1;
+ }
+
+ [m_orderedSubviews removeObjectAtIndex:index];
+
+ [UIView animateWithDuration:0.2 delay:0 options:0 animations:^{
+ view.alpha = 0;
+ }
+ completion:^(BOOL finished)
+ {
+ [view removeFromSuperview];
+ [self setNeedsLayout];
+ }];
+}
+
+- (void)swapObjectAtIndex:(NSInteger)index1 withObjectAtIndex:(NSInteger)index2
+{
+ NSAssert((index1 >= 0 && index1 < [m_orderedSubviews count]), @"Invalid index1 specified");
+ NSAssert((index2 >= 0 && index2 < [m_orderedSubviews count]), @"Invalid index2 specified");
+
+ UIView *view1 = [m_orderedSubviews objectAtIndex:index1];
+ UIView *view2 = [m_orderedSubviews objectAtIndex:index2];
+
+ NSInteger tempTag = view1.tag;
+ view1.tag = view2.tag;
+ view2.tag = tempTag;
+
+ [m_orderedSubviews exchangeObjectAtIndex:index1 withObjectAtIndex:index2];
+ [self setNeedsLayout];
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark private methods
+//////////////////////////////////////////////////////////////
+
+- (void)updateIndexOfItem:(UIView *)view toIndex:(NSInteger)index
+{
+ NSUInteger oldIndex = [m_orderedSubviews indexOfObject:view];
+
+ if (index >= 0 && oldIndex != index && oldIndex < [m_orderedSubviews count])
+ {
+ [m_orderedSubviews moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:oldIndex] toIndex:index];
+ [self.delegate draggableView:self itemAtIndex:oldIndex movedToIndex:index];
+ }
+}
+
+- (NSInteger)itemPositionFromLocation:(CGPoint)location
+{
+ int col = (int) (location.x / (m_itemSize.width + self.itemPadding));
+ int row = (int) (location.y / (m_itemSize.height + self.itemPadding));
+
+ int position = col + row * m_numberOfItemsInRow;
+
+ if (position >= [m_orderedSubviews count] || position < 0)
+ {
+ position = -1;
+ }
+ else
+ {
+ position += GMGV_POSITION_AND_TAG_OFFSET;
+ }
+
+ return position;
+}
+
+- (CGSize)relayoutItems
+{
+ NSUInteger itemsPerRow = 1;
+
+ while ((itemsPerRow+1) * (m_itemSize.width + self.itemPadding) + self.itemPadding < self.bounds.size.width)
+ {
+ itemsPerRow++;
+ }
+
+ m_numberOfItemsInRow = itemsPerRow;
+ int numberOfRowsInPage = ceil( [m_orderedSubviews count] / (1.0 * m_numberOfItemsInRow));
+
+ [UIView animateWithDuration:0.3 delay:0
+ options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState
+ animations:^{
+
+ for (UIView *view in m_orderedSubviews)
+ {
+ if (view != m_movingItem)
+ {
+ NSInteger index = view.tag - GMGV_POSITION_AND_TAG_OFFSET;
+
+ NSUInteger col = index % m_numberOfItemsInRow;
+ NSUInteger row = index / m_numberOfItemsInRow;
+
+ CGFloat originX = col * (m_itemSize.width + self.itemPadding) + self.itemPadding;
+ CGFloat originY = row * (m_itemSize.height + self.itemPadding) + self.itemPadding;
+
+
+ view.frame = CGRectMake(originX, originY, m_itemSize.width, m_itemSize.height);
+ }
+ }
+ }
+ completion:^(BOOL finished) {
+
+ }];
+
+ return CGSizeMake(self.bounds.size.width, ceil(numberOfRowsInPage * (m_itemSize.height + self.itemPadding) + self.itemPadding));
+}
+
+
+@end
View
17 GMGridView/AppDelegate.h
@@ -0,0 +1,17 @@
+//
+// AppDelegate.h
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@class ViewController;
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
View
67 GMGridView/AppDelegate.m
@@ -0,0 +1,67 @@
+//
+// AppDelegate.m
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+#import "ViewController.h"
+
+@implementation AppDelegate
+
+@synthesize window = _window;
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+
+ self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application
+{
+ /*
+ Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+ */
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application
+{
+ /*
+ Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+ */
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application
+{
+ /*
+ Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+ */
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application
+{
+ /*
+ Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+ */
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application
+{
+ /*
+ Called when the application is about to terminate.
+ Save data if appropriate.
+ See also applicationDidEnterBackground:.
+ */
+}
+
+@end
View
43 GMGridView/GMGridView-Info.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFiles</key>
+ <array/>
+ <key>CFBundleIdentifier</key>
+ <string>Gmoledina.ca.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
View
14 GMGridView/GMGridView-Prefix.pch
@@ -0,0 +1,14 @@
+//
+// Prefix header for all source files of the 'DraggableGridView' target in the 'DraggableGridView' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_5_0
+#warning "This project uses features only available in iOS SDK 5.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
View
13 GMGridView/ViewController.h
@@ -0,0 +1,13 @@
+//
+// ViewController.h
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface ViewController : UIViewController
+
+@end
View
288 GMGridView/ViewController.m
@@ -0,0 +1,288 @@
+//
+// ViewController.m
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import "ViewController.h"
+#import "GMGridView.h"
+#import <QuartzCore/QuartzCore.h>
+
+//////////////////////////////////////////////////////////////
+#pragma mark ViewController (privates methods)
+//////////////////////////////////////////////////////////////
+
+@interface ViewController () <DraggableGridViewDataSource, DraggableGridViewDelegate>
+{
+ GMGridView *mw_draggableView;
+ NSMutableOrderedSet *m_data;
+ CGSize m_itemSize;
+}
+
+- (void)addMoreItem;
+- (void)removeItem;
+- (void)refreshItem;
+- (void)segmentedControlChanged:(UISegmentedControl *)control;
+- (void)presentInfo;
+
+@end
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark ViewController implementation
+//////////////////////////////////////////////////////////////
+@implementation ViewController
+
+
+- (id)init
+{
+ if ((self =[super init]))
+ {
+ // Left bar
+
+ UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addMoreItem)];
+
+ UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
+ space.width = 10;
+
+ UIBarButtonItem *removeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(removeItem)];
+
+ UIBarButtonItem *space2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
+ space2.width = 10;
+
+ UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshItem)];
+
+ self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:addButton, space, removeButton, space2, refreshButton, nil];
+
+
+
+ // Right bar
+
+ UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Swap", @"Push", nil]];
+ segmentedControl.frame = CGRectMake(0, 0, 150, 30);
+ [segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
+ segmentedControl.selectedSegmentIndex = 0;
+
+ UIBarButtonItem *segmentedBarItem = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];
+
+ self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:segmentedBarItem, nil];
+
+
+ // Data
+
+ m_data = [[NSMutableOrderedSet alloc] init];
+
+ for (int i = 0; i < 200; i ++)
+ {
+ [m_data addObject:[NSString stringWithFormat:@"%d", i]];
+ }
+
+
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
+ {
+ m_itemSize = CGSizeMake(60, 50);
+ }
+ else
+ {
+ m_itemSize = CGSizeMake(120, 90);
+ }
+ }
+
+ return self;
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark controller events
+//////////////////////////////////////////////////////////////
+- (void)loadView
+{
+ [super loadView];
+ self.view.backgroundColor = [UIColor redColor];
+
+ GMGridView *draggableView = [[GMGridView alloc] initWithFrame:self.view.bounds];
+ draggableView.style = DraggableGridViewStyleSwap;
+ draggableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ draggableView.itemPadding = 15;
+
+ [self.view addSubview:draggableView];
+ mw_draggableView = draggableView;
+
+ mw_draggableView.delegate = self;
+ mw_draggableView.dataSource = self;
+
+
+ UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
+ infoButton.frame = CGRectMake(self.view.bounds.size.width - 40,
+ self.view.bounds.size.height - 40,
+ 40,
+ 40);
+ infoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
+ [infoButton addTarget:self action:@selector(presentInfo) forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:infoButton];
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark memory management
+//////////////////////////////////////////////////////////////
+//- (void)didReceiveMemoryWarning {
+// [super didReceiveMemoryWarning];
+//}
+
+//////////////////////////////////////////////////////////////
+#pragma mark orientation management
+//////////////////////////////////////////////////////////////
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark DraggableGridViewDataSource
+//////////////////////////////////////////////////////////////
+
+- (NSInteger)numberOfItemsInDraggableView:(GMGridView *)draggableView
+{
+ return [m_data count];
+}
+
+- (NSInteger)widthForItemsInDraggableView:(GMGridView *)draggableView
+{
+ return m_itemSize.width;
+}
+
+- (NSInteger)heightForItemsInDraggableView:(GMGridView *)draggableView
+{
+ return m_itemSize.height;
+}
+
+- (UIView *)draggableView:(GMGridView *)draggableView viewForItemAtIndex:(NSInteger)index
+{
+ UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, m_itemSize.width, m_itemSize.height)];
+ view.backgroundColor = [UIColor redColor];
+ view.layer.masksToBounds = NO;
+ view.layer.cornerRadius = 8;
+ view.layer.shadowColor = [UIColor grayColor].CGColor;
+ view.layer.shadowOffset = CGSizeMake(5, 5);
+ view.layer.shadowPath = [UIBezierPath bezierPathWithRect:view.bounds].CGPath;
+ view.layer.shadowRadius = 8;
+
+ UILabel *label = [[UILabel alloc] initWithFrame:view.frame];
+ NSString *message = (NSString *)[m_data objectAtIndex:index];
+ label.text = message;
+ label.textAlignment = UITextAlignmentCenter;
+ label.backgroundColor = [UIColor clearColor];
+ label.textColor = [UIColor blackColor];
+ label.font = [UIFont boldSystemFontOfSize:20];
+ [view addSubview:label];
+
+ return view;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark DraggableGridViewProtocol
+//////////////////////////////////////////////////////////////
+
+- (void)draggableView:(GMGridView *)draggableView itemAtIndex:(NSInteger)oldIndex movedToIndex:(NSInteger)newIndex
+{
+ [m_data moveObjectsAtIndexes:[NSIndexSet indexSetWithIndex:oldIndex] toIndex:newIndex];
+}
+
+- (void)draggableView:(GMGridView *)draggableView didStartMovingView:(UIView *)view
+{
+ view.backgroundColor = [UIColor orangeColor];
+ view.layer.shadowOpacity = 0.7;
+}
+
+- (void)draggableView:(GMGridView *)draggableView didEndMovingView:(UIView *)view
+{
+ view.backgroundColor = [UIColor redColor];
+ view.layer.shadowOpacity = 0;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark public methods
+//////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////
+#pragma mark private methods
+//////////////////////////////////////////////////////////////
+
+- (void)addMoreItem
+{
+ NSString *newItem = [NSString stringWithFormat:@"%d", (int)(arc4random() % 1000)];
+
+ if (![m_data containsObject:newItem])
+ {
+ [m_data addObject:newItem];
+
+ [mw_draggableView insertObjectAtIndex:[m_data count] - 1];
+ }
+ else
+ {
+ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Duplicate" message:[NSString stringWithFormat:@"Data already contains '%@'", newItem] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
+
+ [alertView show];
+ }
+}
+
+- (void)removeItem
+{
+ if ([m_data count] > 0)
+ {
+ NSInteger index = [m_data count] - 1;
+
+ [mw_draggableView removeObjectAtIndex:index];
+ [m_data removeObjectAtIndex:index];
+ }
+}
+
+- (void)refreshItem
+{
+ if ([m_data count] > 0)
+ {
+ int index = [m_data count] - 1;
+
+ NSString *newMessage = [NSString stringWithFormat:@"%d", (arc4random() % 1000)];
+
+ if (![m_data containsObject:newMessage])
+ {
+ [m_data replaceObjectAtIndex:index withObject:newMessage];
+ [mw_draggableView reloadObjectAtIndex:index];
+ }
+ }
+}
+
+- (void)presentInfo
+{
+ NSString *info = @"Long-press an item and its color will change; letting you know that you can now move it around.";
+ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Info" message:info delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
+
+ [alertView show];
+}
+
+- (void)segmentedControlChanged:(UISegmentedControl *)control
+{
+ switch (control.selectedSegmentIndex)
+ {
+ case 1:
+ mw_draggableView.style = DraggableGridViewStylePush;
+ break;
+ case 0:
+ default:
+ mw_draggableView.style = DraggableGridViewStyleSwap;
+ break;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark control events
+//////////////////////////////////////////////////////////////
+
+@end
View
2 GMGridView/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
View
18 GMGridView/main.m
@@ -0,0 +1,18 @@
+//
+// main.m
+// DraggableGridView
+//
+// Created by Gulam Moledina on 11-10-09.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}

0 comments on commit 4748931

Please sign in to comment.
Something went wrong with that request. Please try again.