Authored by Tracy Harton

Two-finger rotate support. set mapView.enableRotate to enable. See MapTestbedFlipMaps for example

... ... @@ -102,6 +102,7 @@ svn checkout http://route-me.googlecode.com/svn/trunk/ route-me-read-only
*/
typedef struct {
CGPoint center;
CGFloat angle;
float averageDistanceFromCenter;
int numTouches;
} RMGestureDetails;
... ... @@ -124,15 +125,19 @@ typedef struct {
id<RMMapViewDelegate> delegate;
BOOL enableDragging;
BOOL enableZoom;
BOOL enableRotate;
RMGestureDetails lastGesture;
float decelerationFactor;
BOOL deceleration;
CGFloat rotation;
@private
BOOL _delegateHasBeforeMapMove;
BOOL _delegateHasAfterMapMove;
BOOL _delegateHasBeforeMapZoomByFactor;
BOOL _delegateHasAfterMapZoomByFactor;
BOOL _delegateHasBeforeMapRotate;
BOOL _delegateHasAfterMapRotate;
BOOL _delegateHasDoubleTapOnMap;
BOOL _delegateHasSingleTapOnMap;
BOOL _delegateHasTapOnMarker;
... ... @@ -152,6 +157,11 @@ typedef struct {
/// property. The RMMapContents class holds the actual map bits.
@property (nonatomic, retain) RMMapContents *contents;
// View properties
@property (readwrite) BOOL enableDragging;
@property (readwrite) BOOL enableZoom;
@property (readwrite) BOOL enableRotate;
@property (nonatomic, retain, readonly) RMMarkerManager *markerManager;
// do not retain the delegate so you can let the corresponding controller implement the
... ... @@ -160,6 +170,7 @@ typedef struct {
@property (readwrite) float decelerationFactor;
@property (readwrite) BOOL deceleration;
@property (readonly) CGFloat rotation;
- (id)initWithFrame:(CGRect)frame WithLocation:(CLLocationCoordinate2D)latlong;
... ...
... ... @@ -44,9 +44,16 @@
@end
@implementation RMMapView
@synthesize contents;
@synthesize decelerationFactor;
@synthesize deceleration;
@synthesize contents;
@synthesize rotation;
@synthesize enableDragging;
@synthesize enableZoom;
@synthesize enableRotate;
#pragma mark --- begin constants ----
#define kDefaultDecelerationFactor .88f
... ... @@ -64,12 +71,13 @@
enableDragging = YES;
enableZoom = YES;
enableRotate = NO;
decelerationFactor = kDefaultDecelerationFactor;
deceleration = NO;
// [self recalculateImageSet];
if (enableZoom)
if (enableZoom || enableRotate)
[self setMultipleTouchEnabled:TRUE];
self.backgroundColor = [UIColor grayColor];
... ... @@ -171,6 +179,9 @@
_delegateHasBeforeMapZoomByFactor = [(NSObject*) delegate respondsToSelector: @selector(beforeMapZoom: byFactor: near:)];
_delegateHasAfterMapZoomByFactor = [(NSObject*) delegate respondsToSelector: @selector(afterMapZoom: byFactor: near:)];
_delegateHasBeforeMapRotate = [(NSObject*) delegate respondsToSelector: @selector(beforeMapRotate: fromAngle:)];
_delegateHasAfterMapRotate = [(NSObject*) delegate respondsToSelector: @selector(afterMapRotate: toAngle:)];
_delegateHasDoubleTapOnMap = [(NSObject*) delegate respondsToSelector: @selector(doubleTapOnMap:At:)];
_delegateHasSingleTapOnMap = [(NSObject*) delegate respondsToSelector: @selector(singleTapOnMap:At:)];
... ... @@ -240,6 +251,7 @@
RMGestureDetails gesture;
gesture.center.x = gesture.center.y = 0;
gesture.averageDistanceFromCenter = 0;
gesture.angle = 0.0;
int interestingTouches = 0;
... ... @@ -287,12 +299,21 @@
// RMLog(@"delta = %.0f, %.0f distance = %f", dx, dy, sqrtf((dx*dx) + (dy*dy)));
gesture.averageDistanceFromCenter += sqrtf((dx*dx) + (dy*dy));
}
gesture.averageDistanceFromCenter /= interestingTouches;
gesture.numTouches = interestingTouches;
if ([touches count] == 2)
{
CGPoint first = [[[touches allObjects] objectAtIndex:0] locationInView:[self superview]];
CGPoint second = [[[touches allObjects] objectAtIndex:1] locationInView:[self superview]];
CGFloat height = second.y - first.y;
CGFloat width = first.x - second.x;
gesture.angle = atan2(height,width);
}
// RMLog(@"center = %.0f,%.0f dist = %f", gesture.center.x, gesture.center.y, gesture.averageDistanceFromCenter);
//RMLog(@"center = %.0f,%.0f dist = %f, angle = %f", gesture.center.x, gesture.center.y, gesture.averageDistanceFromCenter, gesture.angle);
return gesture;
}
... ... @@ -482,6 +503,17 @@
RMGestureDetails newGesture = [self gestureDetails:[event allTouches]];
if(enableRotate && (newGesture.numTouches == lastGesture.numTouches))
{
if(newGesture.numTouches == 2)
{
CGFloat angleDiff = lastGesture.angle - newGesture.angle;
CGFloat newAngle = self.rotation + angleDiff;
[self setRotation:newAngle];
}
}
if (enableDragging && newGesture.numTouches == lastGesture.numTouches)
{
CGSize delta;
... ... @@ -502,7 +534,6 @@
{
[self moveBy:delta];
}
}
lastGesture = newGesture;
... ... @@ -566,10 +597,20 @@
- (void)setRotation:(float)angle
{
[contents setRotation:angle];
if (_delegateHasBeforeMapRotate) [delegate beforeMapRotate: self fromAngle: rotation];
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
self.transform = CGAffineTransformMakeRotation(angle);
}
rotation = angle;
self.transform = CGAffineTransformMakeRotation(rotation);
[contents setRotation:rotation];
[CATransaction commit];
if (_delegateHasAfterMapRotate) [delegate afterMapRotate: self toAngle: rotation];
}
@end
... ...
... ... @@ -41,6 +41,9 @@
- (void) beforeMapZoom: (RMMapView*) map byFactor: (float) zoomFactor near:(CGPoint) center;
- (void) afterMapZoom: (RMMapView*) map byFactor: (float) zoomFactor near:(CGPoint) center;
- (void) beforeMapRotate: (RMMapView*) map fromAngle: (CGFloat) angle;
- (void) afterMapRotate: (RMMapView*) map toAngle: (CGFloat) angle;
- (void) doubleTapOnMap: (RMMapView*) map At: (CGPoint) point;
- (void) singleTapOnMap: (RMMapView*) map At: (CGPoint) point;
... ...
... ... @@ -1184,6 +1184,7 @@
);
OTHER_LDFLAGS = "";
PREBINDING = NO;
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = iphonesimulator2.1;
};
name = Debug;
... ...
... ... @@ -34,6 +34,12 @@
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRequested object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tileNotification:) name:RMTileRetrieved object:nil];
[[mapView contents] setMinZoom:1.0];
[[mapView contents] setMaxZoom:20.0];
[[mapView contents] setFrame:CGRectMake(-100,-10,500,500)]; // Add some width for rotation, but keep centered
mapView.enableRotate = TRUE;
RMMarkerManager *markerManager = [mapView markerManager];
NSAssert(markerManager, @"null markerManager returned");
... ...
... ... @@ -12,7 +12,7 @@
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="49"/>
<integer value="39"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
... ... @@ -45,6 +45,21 @@
<int key="NSvFlags">274</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBUIView" id="1052103930">
<reference key="NSNextResponder" ref="79822186"/>
<int key="NSvFlags">292</int>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview" ref="79822186"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace" id="298040433">
<int key="NSID">2</int>
</object>
</object>
<bool key="IBUIOpaque">NO</bool>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
</object>
<object class="IBUITextView" id="922595057">
<reference key="NSNextResponder" ref="79822186"/>
<int key="NSvFlags">274</int>
... ... @@ -126,12 +141,10 @@ ZAo</string>
</object>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview" ref="702763708"/>
<object class="NSColor" key="IBUIBackgroundColor">
<object class="NSColor" key="IBUIBackgroundColor" id="1026550307">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace" id="298040433">
<int key="NSID">2</int>
</object>
<reference key="NSCustomColorSpace" ref="298040433"/>
</object>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool>
... ... @@ -139,11 +152,7 @@ ZAo</string>
</object>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<reference key="NSCustomColorSpace" ref="298040433"/>
</object>
<reference key="IBUIBackgroundColor" ref="1026550307"/>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
</object>
</object>
... ... @@ -152,22 +161,6 @@ ZAo</string>
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="702763708"/>
</object>
<int key="connectionID">40</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">mapView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="79822186"/>
</object>
<int key="connectionID">41</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">infoTextView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="922595057"/>
... ... @@ -191,6 +184,22 @@ ZAo</string>
</object>
<int key="connectionID">54</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">mapView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="1052103930"/>
</object>
<int key="connectionID">57</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="79822186"/>
</object>
<int key="connectionID">58</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
... ... @@ -228,6 +237,7 @@ ZAo</string>
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="922595057"/>
<reference ref="171590242"/>
<reference ref="1052103930"/>
</object>
<reference key="parent" ref="702763708"/>
</object>
... ... @@ -241,6 +251,11 @@ ZAo</string>
<reference key="object" ref="171590242"/>
<reference key="parent" ref="79822186"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">56</int>
<reference key="object" ref="1052103930"/>
<reference key="parent" ref="79822186"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
... ... @@ -255,6 +270,8 @@ ZAo</string>
<string>39.IBPluginDependency</string>
<string>44.IBPluginDependency</string>
<string>49.IBPluginDependency</string>
<string>56.CustomClassName</string>
<string>56.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
... ... @@ -262,9 +279,11 @@ ZAo</string>
<string>UIResponder</string>
<string>{{1129, 497}, {320, 460}}</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>RMMapView</string>
<string>MainView</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>RMMapView</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object>
</object>
... ... @@ -284,12 +303,20 @@ ZAo</string>
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">54</int>
<int key="maxID">58</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">MainView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/MainView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">MainViewController</string>
<string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="actions">
... ...