Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated to latest Kobo version, complete with bugfixes around animati…

…on and item layout. Bumped version to 1.2.
  • Loading branch information...
commit c37e347540cda16bb9d83be898bfb952317f4fa9 1 parent cf2dc26
Jim Dovey authored
View
11 AQGridView.xcodeproj/project.pbxproj
@@ -214,7 +214,14 @@
isa = PBXProject;
buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "AQGridView" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
mainGroup = 0867D691FE84028FC02AAC07 /* AQGridView */;
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
projectDirPath = "";
@@ -316,7 +323,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
OTHER_LDFLAGS = "-ObjC";
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -331,7 +338,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 3.0;
OTHER_LDFLAGS = "-ObjC";
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
View
37 Classes/AQGridView.m
@@ -615,11 +615,22 @@ - (void) layoutSubviews
[self layoutAllCells];
}
+
CGRect rect = CGRectZero;
rect.size.width = self.bounds.size.width;
rect.size.height = self.contentSize.height - (_gridData.topPadding + _gridData.bottomPadding);
rect.origin.y += _gridData.topPadding;
- self.backgroundView.frame = rect;
+
+ // Make sure background is an integral number of rows tall. That way, it draws patterned colours correctly on all OSes.
+ CGRect backgroundRect = rect;
+ CGFloat minimumHeight = rect.size.height;
+ CGFloat actualHeight = [_gridData cellSize].height * ([_gridData numberOfItems] / [_gridData numberOfItemsPerRow] + 1);
+ for (; actualHeight < minimumHeight; actualHeight += [_gridData cellSize].height) {
+ }
+ backgroundRect.size.height = actualHeight;
+
+
+ self.backgroundView.frame = backgroundRect;
if ( _headerView != nil )
{
@@ -636,6 +647,7 @@ - (void) layoutSubviews
rect.origin.y = self.contentSize.height - rect.size.height;
rect.size.width = self.bounds.size.width;
_footerView.frame = rect;
+ [self bringSubviewToFront:_footerView];
}
}
@@ -867,9 +879,9 @@ - (void) endUpdateAnimations
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration: 0.3];
+
self.animatingCells = [info animateCellUpdatesUsingVisibleContentRect: [self gridViewVisibleBounds]];
- [UIView commitAnimations];
[_gridData release];
_gridData = [[info newGridViewData] retain];
@@ -878,6 +890,7 @@ - (void) endUpdateAnimations
[info release];
_reloadingSuspendedCount--;
+ [UIView commitAnimations];
}
- (void) cellUpdateAnimationStopped: (NSString *) animationID finished: (BOOL) finished context: (void *) context
@@ -885,7 +898,7 @@ - (void) cellUpdateAnimationStopped: (NSString *) animationID finished: (BOOL) f
AQGridViewUpdateInfo * info = (AQGridViewUpdateInfo *)context;
// if nothing was animated, we don't have to do anything at all
- if ( self.animatingCells.count != 0 )
+// if ( self.animatingCells.count != 0 )
[self fixCellsFromAnimation];
// NB: info becomes invalid at this point
@@ -1479,7 +1492,7 @@ - (void) updateVisibleGridCellsNow
{
for ( AQGridViewAnimatorItem * item in _animatingCells )
{
- if ( [animatingInserted containsIndex: item.index] == NO )
+ if ( [newVisibleIndices containsIndex: item.index] == NO )
continue;
if ( [item.animatingView isKindOfClass: [AQGridViewCell class]] )
@@ -1525,7 +1538,12 @@ - (void) updateVisibleGridCellsNow
if ( [_visibleCells count] > [newVisibleIndices count] )
{
- NSLog( @"Have to prune visible cell list, I've still got extra cells in there!" );
+ //NSLog( @"Have to prune visible cell list, I've still got extra cells in there!" );
+ NSMutableIndexSet * animatingDestinationIndices = [[NSMutableIndexSet alloc] init];
+ for ( AQGridViewAnimatorItem * item in _animatingCells )
+ {
+ [animatingDestinationIndices addIndex: item.index];
+ }
NSMutableIndexSet * toRemove = [[NSMutableIndexSet alloc] init];
NSMutableIndexSet * seen = [[NSMutableIndexSet alloc] init];
@@ -1533,7 +1551,8 @@ - (void) updateVisibleGridCellsNow
for ( i = 0; i < count; i++ )
{
AQGridViewCell * cell = [_visibleCells objectAtIndex: i];
- if ( [newVisibleIndices containsIndex: cell.displayIndex] == NO )
+ if ( [newVisibleIndices containsIndex: cell.displayIndex] == NO &&
+ [animatingDestinationIndices containsIndex: cell.displayIndex] == NO )
{
NSLog( @"Cell for index %lu is still in visible list, removing...", (unsigned long)cell.displayIndex );
[cell removeFromSuperview];
@@ -1547,12 +1566,12 @@ - (void) updateVisibleGridCellsNow
}
[seen addIndex: cell.displayIndex];
- i++;
}
// all removed from superview, just need to remove from the list now
[_visibleCells removeObjectsAtIndexes: toRemove];
[toRemove release];
+ [seen release];
}
if ( [_visibleCells count] < [newVisibleIndices count] )
@@ -1583,6 +1602,8 @@ - (void) updateVisibleGridCellsNow
idx = [missingSet indexGreaterThanIndex: idx];
}
+
+ [missingSet release];
}
// everything should match up now, so update the visible range
@@ -2059,6 +2080,8 @@ - (void) delegateWillDisplayCell: (AQGridViewCell *) cell atIndex: (NSUInteger)
cell.separatorEdge = edge;
}
+
+ //NSLog( @"Displaying cell at index %lu", (unsigned long) index );
if ( _flags.delegateWillDisplayCell == 0 )
return;
View
4 Classes/AQGridViewAnimatorItem.m
@@ -43,9 +43,9 @@ - (NSComparisonResult) compare: (id) obj
{
if ( [obj isKindOfClass: [self class]] == NO )
{
- if ( (id)self < obj )
+ if ( (void *)self < (void *)obj )
return ( NSOrderedAscending );
- if ( (id)self > obj )
+ if ( (void *)self > (void *)obj )
return ( NSOrderedDescending );
return ( NSOrderedSame ); // how ??!?!?
}
View
39 Classes/AQGridViewCell.m
@@ -38,10 +38,7 @@
#import "AQGridViewCell+AQGridViewCellPrivate.h"
#import "UIColor+AQGridView.h"
#import <QuartzCore/QuartzCore.h>
-
-#ifdef BUILTIN_IMAGES
-#import "AQGridViewCell_png.h"
-#endif
+#import <objc/runtime.h>
@interface AQGridViewCell ()
@property (nonatomic, retain) UIView * contentView;
@@ -300,39 +297,6 @@ - (void) _beginBackgroundHighlight: (BOOL) highlightOn animated: (BOOL) animated
{
if ( (_cellFlags.usingDefaultSelectedBackgroundView == 1) && (_selectedBackgroundView == nil) )
{
-#ifdef BUILTIN_IMAGES
- unsigned char * pngBytes = AQGridSelection_png;
- NSUInteger pngLength = AQGridSelection_png_len;
- switch ( _cellFlags.selectionStyle )
- {
- case AQGridViewCellSelectionStyleBlue:
- default:
- break;
-
- case AQGridViewCellSelectionStyleGray:
- pngBytes = AQGridSelectionGray_png;
- pngLength = AQGridSelectionGray_png_len;
- break;
-
- case AQGridViewCellSelectionStyleBlueGray:
- pngBytes = AQGridSelectionGrayBlue_png;
- pngLength = AQGridSelectionGrayBlue_png_len;
- break;
-
- case AQGridViewCellSelectionStyleGreen:
- pngBytes = AQGridSelectionGreen_png;
- pngLength = AQGridSelectionGreen_png_len;
- break;
-
- case AQGridViewCellSelectionStyleRed:
- pngBytes = AQGridSelectionRed_png;
- pngLength = AQGridSelectionRed_png_len;
- break;
- }
-
- NSData *pngData = [NSData dataWithBytesNoCopy: pngBytes length: pngLength freeWhenDone: NO];
- _selectedBackgroundView = [[UIImageView alloc] initWithImage: [UIImage imageWithData: pngData]];
-#else
NSString * imageName = @"AQGridSelection.png";
switch ( _cellFlags.selectionStyle )
{
@@ -358,7 +322,6 @@ - (void) _beginBackgroundHighlight: (BOOL) highlightOn animated: (BOOL) animated
}
_selectedBackgroundView = [[UIImageView alloc] initWithImage: [UIImage imageNamed: imageName]];
-#endif
_selectedBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
_selectedBackgroundView.contentMode = UIViewContentModeScaleToFill;
}
View
4 Classes/AQGridViewController.h
@@ -39,10 +39,12 @@
#define POPOVER_SIZE CGSizeMake( 345, 525 )
-@interface AQGridViewController : UIViewController <AQGridViewDelegate, AQGridViewDataSource>
+@interface AQGridViewController : UIViewController <AQGridViewDelegate, AQGridViewDataSource, UIPopoverControllerDelegate>
{
@private
BOOL _clearsSelectionOnViewWillAppear;
+ @protected
+ BOOL _popoverShowing;
}
@property (nonatomic, retain) AQGridView * gridView;
View
10 Classes/AQGridViewController.m
@@ -71,6 +71,8 @@ - (void) viewDidLoad
{
[super viewDidLoad];
[self.gridView reloadData];
+
+ _popoverShowing = NO;
}
- (AQGridView *) gridView
@@ -168,4 +170,12 @@ - (AQGridViewCell *) gridView: (AQGridView *) gridView cellForItemAtIndex: (NSUI
return ( nil );
}
+#pragma mark -
+#pragma mark UIPopoverControllerDelegate methods
+
+- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
+{
+ _popoverShowing = NO;
+}
+
@end
View
126 Classes/AQGridViewUpdateInfo.m
@@ -146,6 +146,18 @@ - (NSUInteger) numberOfUpdates
- (void) updateNewGridDataAndCreateMappingTables
{
+#define GUARD_ITEMS 1
+#if GUARD_ITEMS
+# define TEST_GUARD(array,count) \
+ for ( int j = 0; j < 8; j++ ) \
+ { \
+ NSAssert((array)[(count)+j] == 0x55555555, @"Overwrote the guard area!" ); \
+ } \
+ do {} while (0)
+#else
+# define TEST_GUARD(array,count)
+#endif
+
NSUInteger numberOfItems = _oldGridData.numberOfItems;
numberOfItems += [_insertItems count];
numberOfItems -= [_deleteItems count];
@@ -174,8 +186,19 @@ - (void) updateNewGridDataAndCreateMappingTables
if ( _oldGridData.numberOfItems > 0 )
{
- _oldToNewIndexMap = NSZoneMalloc( [self zone], _oldGridData.numberOfItems * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ NSUInteger count = _oldGridData.numberOfItems + 8;
+#else
+ NSUInteger count = _oldGridData.numberOfItems;
+#endif
+ _oldToNewIndexMap = NSZoneMalloc( [self zone], count * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ memset(_oldToNewIndexMap, 0x55, count * sizeof(NSUInteger));
+#endif
memset_pattern4( _oldToNewIndexMap, &stamp, _oldGridData.numberOfItems * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ NSAssert(_oldToNewIndexMap[_oldGridData.numberOfItems] == 0x55555555, @"Eeek! Scribbling on guards didn't work!");
+#endif
}
else
{
@@ -184,8 +207,19 @@ - (void) updateNewGridDataAndCreateMappingTables
if ( _newGridData.numberOfItems > 0 )
{
- _newToOldIndexMap = NSZoneMalloc( [self zone], _newGridData.numberOfItems * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ NSUInteger count = _newGridData.numberOfItems + 8;
+#else
+ NSUInteger count = _newGridData.numberOfItems;
+#endif
+ _newToOldIndexMap = NSZoneMalloc( [self zone], count * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ memset(_newToOldIndexMap, 0x55, count * sizeof(NSUInteger));
+#endif
memset_pattern4( _newToOldIndexMap, &stamp, _newGridData.numberOfItems * sizeof(NSUInteger) );
+#if GUARD_ITEMS
+ NSAssert(_newToOldIndexMap[_newGridData.numberOfItems] == 0x55555555, @"Eeek! Scribbling on guards didn't work!");
+#endif
}
else
{
@@ -202,6 +236,7 @@ - (void) updateNewGridDataAndCreateMappingTables
if ( [newToOldIndices containsIndex: i] == NO )
{
_oldToNewIndexMap[i] = NSNotFound;
+ TEST_GUARD(_oldToNewIndexMap, _oldGridData.numberOfItems);
continue;
}
@@ -212,6 +247,49 @@ - (void) updateNewGridDataAndCreateMappingTables
for ( AQGridViewUpdateItem * item in _moveItems )
{
_oldToNewIndexMap[item.index] = item.newIndex;
+ TEST_GUARD(_oldToNewIndexMap, _oldGridData.numberOfItems);
+
+ if ( _moveItems.count == 1 )
+ {
+ if ( item.index < item.newIndex )
+ {
+ // moving forwards-- shuffle middle items down one place
+ for ( NSInteger i = item.index+1; i <= item.newIndex && i < _oldGridData.numberOfItems; i++ )
+ {
+ if ( _oldToNewIndexMap[i] != NSNotFound )
+ {
+ if ( i < _oldGridData.numberOfItems-1 )
+ {
+ _oldToNewIndexMap[i] = _oldToNewIndexMap[i]-1;
+ TEST_GUARD(_oldToNewIndexMap, _oldGridData.numberOfItems);
+ }
+ }
+ else
+ {
+ break; // stop when we reach a gap
+ }
+ }
+ }
+ else if ( item.index > item.newIndex )
+ {
+ // moving backwards-- shuffle middle items up one place
+ for ( NSInteger i = MIN(item.index-1, (_oldGridData.numberOfItems-1)); i >= item.newIndex; i-- )
+ {
+ if ( _oldToNewIndexMap[i] != NSNotFound )
+ {
+ if ( i >= 0 )
+ {
+ _oldToNewIndexMap[i] = _oldToNewIndexMap[i]+1;
+ TEST_GUARD(_oldToNewIndexMap, _oldGridData.numberOfItems);
+ }
+ }
+ else
+ {
+ break; // stop when we reach a gap
+ }
+ }
+ }
+ }
}
}
@@ -223,6 +301,7 @@ - (void) updateNewGridDataAndCreateMappingTables
if ( [oldToNewIndices containsIndex: i] == NO )
{
_newToOldIndexMap[i] = NSNotFound;
+ TEST_GUARD(_newToOldIndexMap, _newGridData.numberOfItems);
continue;
}
@@ -233,6 +312,49 @@ - (void) updateNewGridDataAndCreateMappingTables
for ( AQGridViewUpdateItem * item in _moveItems )
{
_newToOldIndexMap[item.newIndex] = item.index;
+ TEST_GUARD(_newToOldIndexMap, _newGridData.numberOfItems);
+
+ if ( _moveItems.count == 1 )
+ {
+ if ( item.index < item.newIndex )
+ {
+ // moving forwards-- shuffle middle items down one place
+ for ( NSInteger i = item.index; i <= item.newIndex && i < _newGridData.numberOfItems; i++ )
+ {
+ if ( _newToOldIndexMap[i] != NSNotFound )
+ {
+ if ( i < _newGridData.numberOfItems-1 )
+ {
+ _newToOldIndexMap[i] = _newToOldIndexMap[i]+1;
+ TEST_GUARD(_newToOldIndexMap, _newGridData.numberOfItems);
+ }
+ }
+ else
+ {
+ break; // stop when we reach a gap
+ }
+ }
+ }
+ else
+ {
+ // moving backwards-- shuffle middle items up one place
+ for ( NSInteger i = MIN(item.newIndex, (_newGridData.numberOfItems-1)); (i < item.index && i < _newGridData.numberOfItems); i++ )
+ {
+ if ( _newToOldIndexMap[i] != NSNotFound )
+ {
+ if ( i >= 0 )
+ {
+ _newToOldIndexMap[i] = _newToOldIndexMap[i]-1;
+ TEST_GUARD(_newToOldIndexMap, _newGridData.numberOfItems);
+ }
+ }
+ else
+ {
+ break; // stop when we reach a gap
+ }
+ }
+ }
+ }
}
}
View
5 Examples/ExpanderDemo/ExpanderDemo.xcodeproj/project.pbxproj
@@ -323,6 +323,7 @@
};
buildConfigurationList = 38D6F05F12197E62006909B6 /* Build configuration list for PBXProject "ExpanderDemo" */;
compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -435,7 +436,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Debug;
@@ -450,7 +451,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Release;
View
11 Examples/ImageDemo/ImageDemo.xcodeproj/project.pbxproj
@@ -321,7 +321,14 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ImageDemo" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
projectDirPath = "";
projectRoot = "";
@@ -436,7 +443,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Debug;
@@ -452,7 +459,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Release;
View
11 Examples/SpringBoard/SpringBoard.xcodeproj/project.pbxproj
@@ -207,7 +207,14 @@
isa = PBXProject;
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SpringBoard" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
projectDirPath = "";
projectRoot = "";
@@ -291,7 +298,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Debug;
@@ -307,7 +314,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
PREBINDING = NO;
- SDKROOT = iphoneos3.2;
+ SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = 2;
};
name = Release;
View
2  LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010, Kobo Inc.
+Copyright (c) 2010-2011, Kobo Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
View
2  README.textile
@@ -2,7 +2,7 @@ h1=. AQGridView
h3=. Winner of the _Best Developer Tool/Helper_ award at iPadDevCamp 2010 in San Jose
-p=. Version 1.1 -- 26 May 2010
+p=. Version 1.2 -- 10 January 2011
p=. By "Jim Dovey":mailto:jimdovey@mac.com <br />
Originally written for the "Kobo iPad Application":http://itunes.apple.com/ca/app/ebooks-by-kobo/id301259483?mt=8
Please sign in to comment.
Something went wrong with that request. Please try again.