@@ -407,11 +407,26 @@ - (void) updateContentRectWithOldMaxLocation: (CGPoint) oldMaxLocation gridSize:
407407
408408- (void ) handleGridViewBoundsChanged : (CGRect) oldBounds toNewBounds : (CGRect) bounds
409409{
410+ CGSize oldGridSize = [_gridData sizeForEntireGrid ];
411+ BOOL wasAtBottom = CGRectGetMaxY (oldBounds) == oldGridSize.height ;
412+
410413 [_gridData gridViewDidChangeBoundsSize: bounds.size];
411414 _flags.numColumns = [_gridData numberOfItemsPerRow ];
415+ CGSize newGridSize = [_gridData sizeForEntireGrid ];
412416
413417 CGPoint oldMaxLocation = CGPointMake (CGRectGetMaxX (oldBounds), CGRectGetMaxY (oldBounds));
414- [self updateContentRectWithOldMaxLocation: oldMaxLocation gridSize: [_gridData sizeForEntireGrid ]];
418+ [self updateContentRectWithOldMaxLocation: oldMaxLocation gridSize: newGridSize];
419+
420+ if ( (wasAtBottom) && (newGridSize.height > oldGridSize.height ) )
421+ {
422+ CGRect contentRect = self.bounds ;
423+ if ( CGRectGetMaxY (contentRect) < newGridSize.height )
424+ {
425+ contentRect.origin .y += (newGridSize.height - oldGridSize.height );
426+ self.contentOffset = contentRect.origin ;
427+ }
428+ }
429+
415430 [self updateVisibleGridCellsNow ];
416431 _flags.allCellsNeedLayout = 1 ;
417432}
@@ -601,6 +616,15 @@ - (NSUInteger) indexForItemAtPoint: (CGPoint) point
601616 return ( [_gridData itemIndexForPoint: point] );
602617}
603618
619+ - (NSUInteger ) indexForCell : (AQGridViewCell *) cell
620+ {
621+ NSUInteger index = [_visibleCells indexOfObject: cell];
622+ if (index == NSNotFound )
623+ return NSNotFound ;
624+
625+ return _visibleIndices.location + index;
626+ }
627+
604628- (AQGridViewCell *) cellForItemAtPoint : (CGPoint) point
605629{
606630 return ( [self cellForItemAtIndex: [_gridData itemIndexForPoint: point]] );
@@ -697,6 +721,19 @@ - (void) fixCellsFromAnimation
697721 self.animatingCells = nil ;
698722 _revealingIndices.length = _revealingIndices.location = 0 ;
699723
724+ NSMutableSet * removals = [[NSMutableSet alloc ] init ];
725+ for ( UIView * view in self.subviews )
726+ {
727+ if ( [view isKindOfClass: [AQGridViewCell class ]] == NO )
728+ continue ;
729+
730+ if ( [_visibleCells containsObject: view] == NO )
731+ [removals addObject: view];
732+ }
733+
734+ [removals makeObjectsPerformSelector: @selector (removeFromSuperview )];
735+ [removals release ];
736+
700737 // update the content size/offset based on the new grid data
701738 CGPoint oldMaxLocation = CGPointMake (CGRectGetMaxX (self.bounds ), CGRectGetMaxY (self.bounds ));
702739 [self updateContentRectWithOldMaxLocation: oldMaxLocation gridSize: [_gridData sizeForEntireGrid ]];
@@ -719,11 +756,29 @@ - (void) endUpdateAnimations
719756 if ( _updateInfo.numberOfUpdates == 0 )
720757 {
721758 // _reloadingSuspendedCount--;
759+ _flags.isAnimatingUpdates = 0 ;
760+ _flags.updating = 0 ;
722761 [_updateInfo release ];
723762 _updateInfo = nil ;
724763 return ;
725764 }
726765
766+ NSUInteger expectedItemCount = [_updateInfo numberOfItemsAfterUpdates ];
767+ NSUInteger actualItemCount = [_dataSource numberOfItemsInGridView: self ];
768+ if ( expectedItemCount != actualItemCount )
769+ {
770+ NSUInteger numAdded = [[_updateInfo sortedInsertItems ] count ];
771+ NSUInteger numDeleted = [[_updateInfo sortedDeleteItems ] count ];
772+
773+ // _reloadingSuspendedCount--;
774+ _flags.isAnimatingUpdates = 0 ;
775+ _flags.updating = 0 ;
776+ [_updateInfo release ];
777+ _updateInfo = nil ;
778+
779+ [NSException raise: NSInternalInconsistencyException format: @" Invalid number of items in AQGridView: Started with %u , added %u , deleted %u . Expected %u items after changes, but got %u " , (unsigned )_gridData.numberOfItems, (unsigned )numAdded, (unsigned )numDeleted, (unsigned )expectedItemCount, (unsigned )actualItemCount];
780+ }
781+
727782 [_updateInfo cleanupUpdateItems ];
728783
729784 [UIView beginAnimations: @" CellUpdates" context: nil ];
@@ -819,26 +874,6 @@ - (NSUInteger) indexOfSelectedItem
819874 return ( _selectedIndex );
820875}
821876
822- - (void ) selectItemAtIndex : (NSUInteger ) index animated : (BOOL ) animated
823- scrollPosition : (AQGridViewScrollPosition) scrollPosition
824- {
825- if ( _selectedIndex != NSNotFound )
826- [self deselectItemAtIndex: _selectedIndex animated: NO ];
827-
828- _selectedIndex = index;
829- [self scrollToItemAtIndex: index atScrollPosition: AQGridViewScrollPositionNone animated: animated];
830- }
831-
832- - (void ) deselectItemAtIndex : (NSUInteger ) index animated : (BOOL ) animated
833- {
834- AQGridViewCell * cell = [self cellForItemAtIndex: index];
835- if ( cell != nil )
836- [cell setSelected: NO animated: animated];
837-
838- if ( _selectedIndex == index )
839- _selectedIndex = NSNotFound ;
840- }
841-
842877- (void ) highlightItemAtIndex : (NSUInteger ) index animated : (BOOL ) animated scrollPosition : (AQGridViewScrollPosition) position
843878{
844879 if ( [_highlightedIndices containsIndex: index] )
@@ -876,6 +911,11 @@ - (void) unhighlightItemAtIndex: (NSUInteger) index animated: (BOOL) animated
876911 return ;
877912
878913 [_highlightedIndices removeIndex: index];
914+
915+ // don't remove highlighting if the cell is actually the selected cell
916+ if ( index == _selectedIndex )
917+ return ;
918+
879919 AQGridViewCell * cell = [self cellForItemAtIndex: index];
880920 if ( cell != nil )
881921 [cell setHighlighted: NO animated: animated];
@@ -909,7 +949,7 @@ - (void) _selectItemAtIndex: (NSUInteger) index animated: (BOOL) animated
909949 return ; // already selected this item
910950
911951 if ( _selectedIndex != NSNotFound )
912- [self _deselectItemAtIndex: _selectedIndex animated: animated notifyDelegate: NO ];
952+ [self _deselectItemAtIndex: _selectedIndex animated: animated notifyDelegate: notifyDelegate ];
913953
914954 if ( _flags.allowsSelection == 0 )
915955 return ;
@@ -931,6 +971,20 @@ - (void) _selectItemAtIndex: (NSUInteger) index animated: (BOOL) animated
931971
932972 if ( notifyDelegate && _flags.delegateDidSelectItem )
933973 [self .delegate gridView: self didSelectItemAtIndex: index];
974+
975+ // ensure that the selected item is no longer marked as just 'highlighted' (that's an intermediary state)
976+ [_highlightedIndices removeIndex: index];
977+ }
978+
979+ - (void ) selectItemAtIndex : (NSUInteger ) index animated : (BOOL ) animated
980+ scrollPosition : (AQGridViewScrollPosition) scrollPosition
981+ {
982+ [self _selectItemAtIndex: index animated: animated scrollPosition: scrollPosition notifyDelegate: NO ];
983+ }
984+
985+ - (void ) deselectItemAtIndex : (NSUInteger ) index animated : (BOOL ) animated
986+ {
987+ [self _deselectItemAtIndex: index animated: animated notifyDelegate: NO ];
934988}
935989
936990#pragma mark -
@@ -1029,6 +1083,43 @@ - (void) _userSelectItemAtIndex: (NSNumber *) indexNum
10291083 _pendingSelectionIndex = NSNotFound ;
10301084}
10311085
1086+ - (BOOL ) _gestureRecognizerIsHandlingTouches : (NSSet *) touches
1087+ {
1088+ // see if the touch is (possibly) being tracked by a gesture recognizer
1089+ for ( id recognizer in self.gestureRecognizers )
1090+ {
1091+ switch ( [recognizer state ] )
1092+ {
1093+ case UIGestureRecognizerStateEnded:
1094+ case UIGestureRecognizerStateCancelled:
1095+ case UIGestureRecognizerStateFailed:
1096+ continue ;
1097+
1098+ default :
1099+ break ;
1100+ }
1101+
1102+ if ( [recognizer numberOfTouches ] == [touches count ] )
1103+ {
1104+ // simple version:
1105+ // pick a touch from our event's set, and see if it's in the recognizer's set
1106+ UITouch * touch = [touches anyObject ];
1107+ CGPoint touchLocation = [touch locationInView: self ];
1108+
1109+ for ( NSUInteger i = 0 ; i < [recognizer numberOfTouches ]; i++ )
1110+ {
1111+ CGPoint test = [recognizer locationOfTouch: i inView: self ];
1112+ if ( CGPointEqualToPoint (test, touchLocation) )
1113+ {
1114+ return ( YES );
1115+ }
1116+ }
1117+ }
1118+ }
1119+
1120+ return ( NO );
1121+ }
1122+
10321123- (void ) touchesBegan : (NSSet *) touches withEvent : (UIEvent *) event
10331124{
10341125 _flags.ignoreTouchSelect = ([self isDragging ] ? 1 : 0 );
@@ -1080,12 +1171,20 @@ - (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event
10801171{
10811172 if ( _flags.ignoreTouchSelect == 0 )
10821173 {
1174+ Class cls = NSClassFromString (@" UILongPressGestureRecognizer" );
1175+ if ( (cls != Nil ) && ([cls instancesRespondToSelector: @selector (setNumberOfTouchesRequired: )]) )
1176+ {
1177+ if ( [self _gestureRecognizerIsHandlingTouches: touches] )
1178+ goto passToSuper; // I feel all icky now
1179+ }
1180+
10831181 // [self _cancelContentTouchUsingEvent: event forced: NO];
10841182 [self highlightItemAtIndex: NSNotFound animated: NO scrollPosition: AQGridViewScrollPositionNone];
10851183 _flags.ignoreTouchSelect = 1 ;
10861184 _touchedContentView = nil ;
10871185 }
10881186
1187+ passToSuper:
10891188 [super touchesMoved: touches withEvent: event];
10901189}
10911190
@@ -1180,6 +1279,9 @@ - (void) updateVisibleGridCellsNow
11801279 if ( _reloadingSuspendedCount > 0 )
11811280 return ;
11821281
1282+ if ( _flags.isAnimatingUpdates || _flags.updating )
1283+ return ;
1284+
11831285 _reloadingSuspendedCount++;
11841286 NSIndexSet * newVisibleIndices = [_gridData indicesOfCellsInRect: [self gridViewVisibleBounds ]];
11851287
@@ -1456,8 +1558,8 @@ - (void) viewWillRotateToInterfaceOrientation: (UIInterfaceOrientation) orientat
14561558 // to avoid cell pop-in or pop-out:
14571559 // if we're switching to landscape, don't update cells until after the transition.
14581560 // if we're switching to portrait, update cells first.
1459- if ( UIInterfaceOrientationIsLandscape (orientation) )
1460- _reloadingSuspendedCount++;
1561+ // if ( UIInterfaceOrientationIsLandscape(orientation) )
1562+ // _reloadingSuspendedCount++;
14611563}
14621564
14631565- (void ) viewDidRotate
0 commit comments