Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added support for editing mode

  • Loading branch information...
commit 94ee7eaaa70dd10e1ad2dfa50eb2966c4d4a1a11 1 parent 4a48d58
@gmoledina authored
View
13 GMGridView.xcodeproj/project.pbxproj
@@ -19,6 +19,7 @@
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 */; };
+ 16955523146FA81800DECCA6 /* close_x.png in Resources */ = {isa = PBXBuildFile; fileRef = 16955522146FA81800DECCA6 /* close_x.png */; };
169AE3781460E1B300C0CBCD /* OptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 169AE3771460E1B300C0CBCD /* OptionsViewController.m */; };
16A0D030145342F8004D7BBC /* GMGridViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 16A0D02F145342F8004D7BBC /* GMGridViewCell.m */; };
16DF1A6E145E3456006AA43C /* GMGridViewLayoutStrategies.m in Sources */ = {isa = PBXBuildFile; fileRef = 16DF1A6D145E3456006AA43C /* GMGridViewLayoutStrategies.m */; };
@@ -46,6 +47,7 @@
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; };
+ 16955522146FA81800DECCA6 /* close_x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = close_x.png; sourceTree = "<group>"; };
169AE3761460E1B300C0CBCD /* OptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionsViewController.h; path = GMGridView/OptionsViewController.h; sourceTree = SOURCE_ROOT; };
169AE3771460E1B300C0CBCD /* OptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OptionsViewController.m; path = GMGridView/OptionsViewController.m; sourceTree = SOURCE_ROOT; };
16A0D02E145342F8004D7BBC /* GMGridViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GMGridViewCell.h; path = GMGridView/API/GMGridViewCell.h; sourceTree = SOURCE_ROOT; };
@@ -85,6 +87,7 @@
children = (
16924B11144156FE00E6E556 /* Demo */,
16924B361442CA9400E6E556 /* API */,
+ 16955520146FA80200DECCA6 /* Resources */,
16026C10145462EC00093AFF /* Documentation */,
16924B0A144156FE00E6E556 /* Frameworks */,
16924B08144156FE00E6E556 /* Products */,
@@ -155,6 +158,15 @@
path = DraggableGridView/API;
sourceTree = "<group>";
};
+ 16955520146FA80200DECCA6 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 16955522146FA81800DECCA6 /* close_x.png */,
+ );
+ name = Resources;
+ path = GMGridView/Resources;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -208,6 +220,7 @@
files = (
16026C131454631600093AFF /* LICENSE in Resources */,
16026C141454631600093AFF /* README in Resources */,
+ 16955523146FA81800DECCA6 /* close_x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
3  GMGridView/API/GMGridView.h
@@ -66,6 +66,9 @@ typedef enum
@property (nonatomic) CFTimeInterval minimumPressDuration; // Default is 0.2; if set to 0, the scrollView will not be scrollable
@property (nonatomic) BOOL showFullSizeViewWithAlphaWhenTransforming; // Default is YES - not working right now
+// Editing
+@property (nonatomic, getter=isEditing) BOOL editing; // Default is NO
+
// Actions
- (void)reloadData;
- (void)insertObjectAtIndex:(NSInteger)index;
View
52 GMGridView/API/GMGridView.m
@@ -117,7 +117,7 @@ - (void)cleanupUnseenItems;
- (void)queueReusableCell:(GMGridViewCell *)cell;
- (GMGridViewCell *)dequeueReusableCell;
-
+// Memory warning
- (void)receivedMemoryWarningNotification:(NSNotification *)notification;
@end
@@ -140,6 +140,7 @@ @implementation GMGridView
@synthesize centerGrid = _centerGrid;
@synthesize minEdgeInsets = _minEdgeInsets;
@synthesize showFullSizeViewWithAlphaWhenTransforming;
+@synthesize editing = _editing;
@synthesize itemsSubviewsCacheIsValid = _itemsSubviewsCacheIsValid;
@synthesize itemSubviewsCache;
@@ -209,6 +210,7 @@ - (id)initWithFrame:(CGRect)frame
self.layoutStrategy = [GMGridViewLayoutStrategyFactory strategyFromType:GMGridViewLayoutVertical];
self.mainSuperView = self;
+ self.editing = NO;
self.itemSpacing = 10;
self.style = GMGridViewStyleSwap;
self.minimumPressDuration = 0.2;
@@ -302,6 +304,20 @@ - (CFTimeInterval)minimumPressDuration
return _sortingLongPressGesture.minimumPressDuration;
}
+- (void)setEditing:(BOOL)editing
+{
+ if (![self isInTransformingState]
+ && ((self.isEditing && !editing) || (!self.isEditing && editing)))
+ {
+ for (GMGridViewCell *cell in [self itemSubviews])
+ {
+ [cell setEditing:editing];
+ }
+
+ _editing = editing;
+ }
+}
+
//////////////////////////////////////////////////////////////
#pragma mark UIScrollView delegate
//////////////////////////////////////////////////////////////
@@ -327,11 +343,11 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
if (gestureRecognizer == _tapGesture)
{
CGPoint locationTouch = [_tapGesture locationInView:_scrollView];
- valid = [self.layoutStrategy itemPositionFromLocation:locationTouch] != GMGV_INVALID_POSITION;
+ valid = !self.isEditing && [self.layoutStrategy itemPositionFromLocation:locationTouch] != GMGV_INVALID_POSITION;
}
else if (gestureRecognizer == _sortingLongPressGesture)
{
- valid = (self.sortingDelegate != nil);
+ valid = !self.isEditing && (self.sortingDelegate != nil);
}
else if (gestureRecognizer == _sortingPanGesture)
{
@@ -347,7 +363,7 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
NSInteger positionTouch1 = [self.layoutStrategy itemPositionFromLocation:locationTouch1];
NSInteger positionTouch2 = [self.layoutStrategy itemPositionFromLocation:locationTouch2];
- valid = [self isInTransformingState] || ((positionTouch1 == positionTouch2) && (positionTouch1 != GMGV_INVALID_POSITION));
+ valid = !self.isEditing && ([self isInTransformingState] || ((positionTouch1 == positionTouch2) && (positionTouch1 != GMGV_INVALID_POSITION)));
}
else
{
@@ -966,6 +982,17 @@ - (GMGridViewCell *)createItemSubViewForPosition:(NSInteger)position
if (!cell)
{
cell = [[GMGridViewCell alloc] initContentView:contentView];
+ cell.deleteButtonIcon = [UIImage imageNamed:@"close_x.png"];
+ cell.deleteButtonOffset = CGPointMake(-15, -15);
+ cell.deleteBlock = ^(GMGridViewCell *cell)
+ {
+ NSInteger index = [self positionForItemSubview:cell];
+ if (index != GMGV_INVALID_POSITION)
+ {
+ [self removeObjectAtIndex:index];
+ //todo: tell the delegate !!!!
+ }
+ };
}
else
{
@@ -976,6 +1003,7 @@ - (GMGridViewCell *)createItemSubViewForPosition:(NSInteger)position
cell.frame = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height);
cell.tag = position + kTagOffset;
+ cell.editing = self.editing;
return cell;
}
@@ -1159,9 +1187,9 @@ - (void)cleanupUnseenItems
[self setSubviewsCacheAsInvalid];
}
- if (rangeOfPositions.location + rangeOfPositions.length < self.lastPositionLoaded)
+ if (NSMaxRange(rangeOfPositions) < self.lastPositionLoaded)
{
- for (int i = rangeOfPositions.location + rangeOfPositions.length; i <= self.lastPositionLoaded; i++)
+ for (int i = NSMaxRange(rangeOfPositions); i <= self.lastPositionLoaded; i++)
{
cell = [self itemSubViewForPosition:i];
if(cell)
@@ -1172,7 +1200,7 @@ - (void)cleanupUnseenItems
}
}
- self.lastPositionLoaded = rangeOfPositions.location + rangeOfPositions.length;
+ self.lastPositionLoaded = NSMaxRange(rangeOfPositions);
[self setSubviewsCacheAsInvalid];
}
}
@@ -1182,6 +1210,7 @@ - (void)queueReusableCell:(GMGridViewCell *)cell
if (cell)
{
[cell prepareForReuse];
+ cell.alpha = 1;
[_reusableCells addObject:cell];
}
}
@@ -1348,17 +1377,22 @@ - (void)removeObjectAtIndex:(NSInteger)index
delay:0
options:kDefaultAnimationOptions
animations:^{
- cell.contentView.alpha = 0;
+ cell.contentView.alpha = 0.3;
+ cell.alpha = 0;
[_scrollView scrollRectToVisible:CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height) animated:NO];
}
completion:^(BOOL finished){
[self queueReusableCell:cell];
[cell removeFromSuperview];
+
+ self.firstPositionLoaded = self.lastPositionLoaded = GMGV_INVALID_POSITION;
+ [self loadRequiredItems];
+
+ [self setNeedsLayout];
}
];
[self setSubviewsCacheAsInvalid];
- [self setNeedsLayout];
}
- (void)swapObjectAtIndex:(NSInteger)index1 withObjectAtIndex:(NSInteger)index2
View
9 GMGridView/API/GMGridViewCell.h
@@ -28,6 +28,11 @@
#import <UIKit/UIKit.h>
+@class GMGridViewCell;
+typedef void (^GMGridViewCellDeleteBlock)(GMGridViewCell*);
+
+
+
@interface GMGridViewCell : UIView
@property (nonatomic, strong) UIView *contentView;
@@ -37,6 +42,10 @@
@property (nonatomic, readonly, getter=isInShakingMode) BOOL inShakingMode;
@property (nonatomic, readonly, getter=isInFullSizeMode) BOOL inFullSizeMode;
+@property (nonatomic, getter=isEditing) BOOL editing;
+@property (nonatomic, copy) GMGridViewCellDeleteBlock deleteBlock;
+@property (nonatomic, strong) UIImage *deleteButtonIcon;
+@property (nonatomic) CGPoint deleteButtonOffset;
- (id)initContentView:(UIView *)contentView;
- (void)prepareForReuse;
View
104 GMGridView/API/GMGridViewCell.m
@@ -40,6 +40,9 @@ @interface GMGridViewCell ()
}
@property (nonatomic, assign) UIViewAutoresizing defaultFullsizeViewResizingMask;
+@property (nonatomic, weak) UIButton *deleteButton;
+
+- (void)actionDelete;
@end
@@ -53,11 +56,16 @@ @interface GMGridViewCell ()
@implementation GMGridViewCell
@synthesize contentView = _contentView;
+@synthesize editing = _editing;
@synthesize inShakingMode = _inShakingMode;
@synthesize fullSize = _fullSize;
@synthesize fullSizeView = _fullSizeView;
@synthesize inFullSizeMode = _inFullSizeMode;
-@synthesize defaultFullsizeViewResizingMask;
+@synthesize defaultFullsizeViewResizingMask = _defaultFullsizeViewResizingMask;
+@synthesize deleteButton = _deleteButton;
+@synthesize deleteBlock = _deleteBlock;
+@synthesize deleteButtonIcon = _deleteButtonIcon;
+@synthesize deleteButtonOffset;
//////////////////////////////////////////////////////////////
#pragma mark Constructors
@@ -78,6 +86,17 @@ - (id)initContentView:(UIView *)contentView
{
self.contentView = contentView;
self.autoresizesSubviews = YES;
+ self.editing = NO;
+
+ UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
+ self.deleteButton = deleteButton;
+ [self.deleteButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
+ self.deleteButton.showsTouchWhenHighlighted = YES;
+ self.deleteButtonIcon = nil;
+ self.deleteButtonOffset = CGPointMake(-5, -5);
+ self.deleteButton.alpha = 0;
+ [self addSubview:deleteButton];
+ [deleteButton addTarget:self action:@selector(actionDelete) forControlEvents:UIControlEventTouchUpInside];
}
return self;
@@ -109,11 +128,13 @@ - (void)layoutSubviews
- (void)setContentView:(UIView *)contentView
{
[self shake:NO];
- [_contentView removeFromSuperview];
+ [self.contentView removeFromSuperview];
_contentView = contentView;
- _contentView.frame = self.bounds;
- _contentView.autoresizingMask = UIViewAutoresizingNone;
- [self addSubview:_contentView];
+ self.contentView.frame = self.bounds;
+ self.contentView.autoresizingMask = UIViewAutoresizingNone;
+ [self addSubview:self.contentView];
+
+ [self bringSubviewToFront:self.deleteButton];
}
- (void)setFullSizeView:(UIView *)fullSizeView
@@ -136,6 +157,8 @@ - (void)setFullSizeView:(UIView *)fullSizeView
[_fullSizeView removeFromSuperview];
_fullSizeView = fullSizeView;
[self addSubview:_fullSizeView];
+
+ [self bringSubviewToFront:self.deleteButton];
}
- (void)setFullSize:(CGSize)fullSize
@@ -145,6 +168,76 @@ - (void)setFullSize:(CGSize)fullSize
[self setNeedsLayout];
}
+- (void)setEditing:(BOOL)editing
+{
+ _editing = editing;
+
+ [UIView animateWithDuration:0.2
+ delay:0
+ options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut
+ animations:^{
+ self.deleteButton.alpha = editing ? 1 : 0;
+ }
+ completion:nil];
+}
+
+- (void)setDeleteButtonOffset:(CGPoint)offset
+{
+ self.deleteButton.frame = CGRectMake(offset.x,
+ offset.y,
+ self.deleteButton.frame.size.width,
+ self.deleteButton.frame.size.height);
+}
+
+- (CGPoint)deleteButtonOffset
+{
+ return self.deleteButton.frame.origin;
+}
+
+- (void)setDeleteButtonIcon:(UIImage *)deleteButtonIcon
+{
+ [self.deleteButton setImage:deleteButtonIcon forState:UIControlStateNormal];
+
+ if (deleteButtonIcon)
+ {
+ self.deleteButton.frame = CGRectMake(self.deleteButton.frame.origin.x,
+ self.deleteButton.frame.origin.y,
+ deleteButtonIcon.size.width,
+ deleteButtonIcon.size.height);
+
+ [self.deleteButton setTitle:nil forState:UIControlStateNormal];
+ [self.deleteButton setBackgroundColor:[UIColor clearColor]];
+ }
+ else
+ {
+ self.deleteButton.frame = CGRectMake(self.deleteButton.frame.origin.x,
+ self.deleteButton.frame.origin.y,
+ 35,
+ 35);
+
+ [self.deleteButton setTitle:@"X" forState:UIControlStateNormal];
+ [self.deleteButton setBackgroundColor:[UIColor lightGrayColor]];
+ }
+
+
+}
+
+- (UIImage *)deleteButtonIcon
+{
+ return [self.deleteButton currentImage];
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark Private methods
+//////////////////////////////////////////////////////////////
+
+- (void)actionDelete
+{
+ if (self.deleteBlock)
+ {
+ self.deleteBlock(self);
+ }
+}
//////////////////////////////////////////////////////////////
#pragma mark Public methods
@@ -155,6 +248,7 @@ - (void)prepareForReuse
self.contentView = nil;
self.fullSize = CGSizeZero;
self.fullSizeView = nil;
+ self.editing = NO;
}
- (void)shake:(BOOL)on
View
43 GMGridView/OptionsViewController.m
@@ -12,13 +12,21 @@
// Sections
typedef enum {
- OptionSectionLayout = 0,
+ OptionSectionGeneral = 0,
+ OptionSectionLayout,
OptionSectionSorting,
OptionSectionDebug,
OptionSectionsCount
} OptionsTypeSections;
+// General
+typedef enum {
+ OptionTypeGeneralEditing = 0,
+
+ OptionGeneralCount
+} OptionsTypeGeneral;
+
// Options layout
typedef enum {
OptionTypeLayoutStrategy = 0,
@@ -49,6 +57,7 @@ @interface OptionsViewController () <UITableViewDelegate, UITableViewDataSource>
__weak UITableView *_tableView;
}
+- (void)editingSwitchChanged:(UISwitch *)control;
- (void)sortStyleSegmentedControlChanged:(UISegmentedControl *)control;
- (void)layoutStrategySegmentedControlChanged:(UISegmentedControl *)control;
- (void)layoutCenterSwitchChanged:(UISwitch *)control;
@@ -133,6 +142,9 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInte
switch (section)
{
+ case OptionSectionGeneral:
+ title = @"General";
+ break;
case OptionSectionLayout:
title = @"Layout";
break;
@@ -153,6 +165,9 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger
switch (section)
{
+ case OptionSectionGeneral:
+ count = OptionGeneralCount;
+ break;
case OptionSectionLayout:
count = OptionLayoutCount;
break;
@@ -178,7 +193,25 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
- if ([indexPath section] == OptionSectionLayout)
+
+
+ if ([indexPath section] == OptionSectionGeneral)
+ {
+ switch ([indexPath row])
+ {
+ case OptionTypeGeneralEditing:
+ {
+ cell.detailTextLabel.text = @"Editing";
+
+ UISwitch *editingSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
+ [editingSwitch addTarget:self action:@selector(editingSwitchChanged:) forControlEvents:UIControlEventValueChanged];
+ editingSwitch.on = self.gridView.isEditing;
+
+ cell.accessoryView = editingSwitch;
+ }
+ }
+ }
+ else if ([indexPath section] == OptionSectionLayout)
{
switch ([indexPath row])
{
@@ -304,6 +337,12 @@ - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)
#pragma mark Control callbacks
//////////////////////////////////////////////////////////////
+- (void)editingSwitchChanged:(UISwitch *)control
+{
+ self.gridView.editing = control.on;
+ control.on = self.gridView.isEditing;
+}
+
- (void)sortStyleSegmentedControlChanged:(UISegmentedControl *)control
{
switch (control.selectedSegmentIndex)
View
BIN  GMGridView/Resources/close_x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Please sign in to comment.
Something went wrong with that request. Please try again.