Project import
diff --git a/WEPopover/LICENSE b/WEPopover/LICENSE
new file mode 100755
index 0000000..163d133
--- /dev/null
+++ b/WEPopover/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Werner IT Consultancy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/WEPopover/UIBarButtonItem+WEPopover.h b/WEPopover/UIBarButtonItem+WEPopover.h
new file mode 100755
index 0000000..0b8391a
--- /dev/null
+++ b/WEPopover/UIBarButtonItem+WEPopover.h
@@ -0,0 +1,15 @@
+/*
+ *  UIBarButtonItem+WEPopover.h
+ *  WEPopover
+ *
+ *  Created by Werner Altewischer on 07/05/11.
+ *  Copyright 2010 Werner IT Consultancy. All rights reserved.
+ *
+ */
+
+@interface UIBarButtonItem(WEPopover)
+
+- (CGRect)frameInView:(UIView *)v;
+- (UIView *)superview;
+
+@end
diff --git a/WEPopover/UIBarButtonItem+WEPopover.m b/WEPopover/UIBarButtonItem+WEPopover.m
new file mode 100755
index 0000000..06faf17
--- /dev/null
+++ b/WEPopover/UIBarButtonItem+WEPopover.m
@@ -0,0 +1,50 @@
+/*
+ *  UIBarButtonItem+WEPopover.m
+ *  WEPopover
+ *
+ *  Created by Werner Altewischer on 07/05/11.
+ *  Copyright 2010 Werner IT Consultancy. All rights reserved.
+ *
+ */
+
+#import "UIBarButtonItem+WEPopover.h" 
+
+@implementation UIBarButtonItem(WEPopover)
+
+- (CGRect)frameInView:(UIView *)v {
+	
+	BOOL hasCustomView = (self.customView != nil);
+	
+	if (!hasCustomView) {
+		UIView *tempView = [[UIView alloc] initWithFrame:CGRectZero];
+		self.customView = tempView;
+	}
+	
+	UIView *parentView = self.customView.superview;
+	NSUInteger indexOfView = [parentView.subviews indexOfObject:self.customView];
+	
+	if (!hasCustomView) {
+		self.customView = nil;
+	}
+	UIView *button = [parentView.subviews objectAtIndex:indexOfView];
+	return [parentView convertRect:button.frame toView:v];
+}
+
+- (UIView *)superview {
+	
+	BOOL hasCustomView = (self.customView != nil);
+	
+	if (!hasCustomView) {
+		UIView *tempView = [[UIView alloc] initWithFrame:CGRectZero];
+		self.customView = tempView;
+	}
+	
+	UIView *parentView = self.customView.superview;
+	
+	if (!hasCustomView) {
+		self.customView = nil;
+	}
+	return parentView;
+}
+
+@end
diff --git a/WEPopover/WEPopoverContainerView.h b/WEPopover/WEPopoverContainerView.h
new file mode 100755
index 0000000..93d1d3e
--- /dev/null
+++ b/WEPopover/WEPopoverContainerView.h
@@ -0,0 +1,98 @@
+//
+//  WEPopoverContainerView.h
+//  WEPopover
+//
+//  Created by Werner Altewischer on 02/09/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/**
+ * @brief Properties for the container view determining the area where the actual content view can/may be displayed. Also Images can be supplied for the arrow images and background.
+ */
+@interface WEPopoverContainerViewProperties : NSObject
+{
+	NSString *bgImageName;
+	NSString *upArrowImageName;
+	NSString *downArrowImageName;
+	NSString *leftArrowImageName;
+	NSString *rightArrowImageName;
+	CGFloat leftBgMargin;
+	CGFloat rightBgMargin;
+	CGFloat topBgMargin;
+	CGFloat bottomBgMargin;
+	NSInteger topBgCapSize;
+	NSInteger leftBgCapSize;
+	CGFloat arrowMargin;
+}
+
+@property(nonatomic, strong) NSString *bgImageName;
+@property(nonatomic, strong) NSString *upArrowImageName;
+@property(nonatomic, strong) NSString *downArrowImageName;
+@property(nonatomic, strong) NSString *leftArrowImageName;
+@property(nonatomic, strong) NSString *rightArrowImageName;
+@property(nonatomic, assign) CGFloat leftBgMargin;
+@property(nonatomic, assign) CGFloat rightBgMargin;
+@property(nonatomic, assign) CGFloat topBgMargin;
+@property(nonatomic, assign) CGFloat bottomBgMargin;
+@property(nonatomic, assign) CGFloat leftContentMargin;
+@property(nonatomic, assign) CGFloat rightContentMargin;
+@property(nonatomic, assign) CGFloat topContentMargin;
+@property(nonatomic, assign) CGFloat bottomContentMargin;
+@property(nonatomic, assign) NSInteger topBgCapSize;
+@property(nonatomic, assign) NSInteger leftBgCapSize;
+@property(nonatomic, assign) CGFloat arrowMargin;
+
+@end
+
+@class WEPopoverContainerView;
+
+/**
+ * @brief Container/background view for displaying a popover view.
+ */
+@interface WEPopoverContainerView : UIView {
+	UIImage *bgImage;
+	UIImage *arrowImage;
+	
+	WEPopoverContainerViewProperties *properties;
+	
+	UIPopoverArrowDirection arrowDirection;
+	
+	CGRect arrowRect;
+	CGRect bgRect;
+	CGPoint offset;
+	CGPoint arrowOffset;
+	
+	CGSize correctedSize;
+	UIView *contentView;
+}
+
+/**
+ * @brief The current arrow direction for the popover.
+ */
+@property (nonatomic, readonly) UIPopoverArrowDirection arrowDirection;
+
+/**
+ * @brief The content view being displayed.
+ */
+@property (nonatomic, strong) UIView *contentView;
+
+/**
+ * @brief Initializes the position of the popover with a size, anchor rect, display area and permitted arrow directions and optionally the properties. 
+ * If the last is not supplied the defaults are taken (requires images to be present in bundle representing a black rounded background with partial transparency).
+ */
+- (id)initWithSize:(CGSize)theSize 
+		anchorRect:(CGRect)anchorRect 
+	   displayArea:(CGRect)displayArea
+permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections
+		properties:(WEPopoverContainerViewProperties *)properties;	
+
+/**
+ * @brief To update the position of the popover with a new anchor rect, display area and permitted arrow directions
+ */
+- (void)updatePositionWithAnchorRect:(CGRect)anchorRect 
+						 displayArea:(CGRect)displayArea
+			permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections;	
+
+@end
diff --git a/WEPopover/WEPopoverContainerView.m b/WEPopover/WEPopoverContainerView.m
new file mode 100755
index 0000000..b40f875
--- /dev/null
+++ b/WEPopover/WEPopoverContainerView.m
@@ -0,0 +1,204 @@
+//
+//  WEPopoverContainerViewProperties.m
+//  WEPopover
+//
+//  Created by Werner Altewischer on 02/09/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import "WEPopoverContainerView.h"
+
+@implementation WEPopoverContainerViewProperties
+
+@synthesize bgImageName, upArrowImageName, downArrowImageName, leftArrowImageName, rightArrowImageName, topBgMargin, bottomBgMargin, leftBgMargin, rightBgMargin, topBgCapSize, leftBgCapSize;
+@synthesize leftContentMargin, rightContentMargin, topContentMargin, bottomContentMargin, arrowMargin;
+
+
+@end
+
+@interface WEPopoverContainerView(Private)
+
+- (void)determineGeometryForSize:(CGSize)theSize anchorRect:(CGRect)anchorRect displayArea:(CGRect)displayArea permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections;
+- (CGRect)contentRect;
+- (CGSize)contentSize;
+- (void)setProperties:(WEPopoverContainerViewProperties *)props;
+- (void)initFrame;
+
+@end
+
+@implementation WEPopoverContainerView
+
+@synthesize arrowDirection, contentView;
+
+- (id)initWithSize:(CGSize)theSize 
+		anchorRect:(CGRect)anchorRect 
+	   displayArea:(CGRect)displayArea
+permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections
+		properties:(WEPopoverContainerViewProperties *)theProperties {
+	if ((self = [super initWithFrame:CGRectZero])) {
+		
+		[self setProperties:theProperties];
+		correctedSize = CGSizeMake(theSize.width + properties.leftBgMargin + properties.rightBgMargin + properties.leftContentMargin + properties.rightContentMargin, 
+								   theSize.height + properties.topBgMargin + properties.bottomBgMargin + properties.topContentMargin + properties.bottomContentMargin);	
+		[self determineGeometryForSize:correctedSize anchorRect:anchorRect displayArea:displayArea permittedArrowDirections:permittedArrowDirections];
+		[self initFrame];
+		self.backgroundColor = [UIColor clearColor];
+		UIImage *theImage = [UIImage imageNamed:properties.bgImageName];
+		bgImage = [theImage stretchableImageWithLeftCapWidth:properties.leftBgCapSize topCapHeight:properties.topBgCapSize];
+		
+		self.clipsToBounds = YES;
+		self.userInteractionEnabled = YES;
+		
+		self.layer.shadowOffset = CGSizeMake(3, 3);
+		self.layer.shadowRadius = 6;
+		self.layer.shadowOpacity = 0.3;
+		self.clipsToBounds = NO;
+	}
+	return self;
+}
+
+
+- (void)drawRect:(CGRect)rect {
+	[bgImage drawInRect:bgRect blendMode:kCGBlendModeNormal alpha:1.0];
+	[arrowImage drawInRect:arrowRect blendMode:kCGBlendModeNormal alpha:1.0]; 
+}
+
+- (void)updatePositionWithAnchorRect:(CGRect)anchorRect 
+						 displayArea:(CGRect)displayArea
+			permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections {
+	[self determineGeometryForSize:correctedSize anchorRect:anchorRect displayArea:displayArea permittedArrowDirections:permittedArrowDirections];
+	[self initFrame];
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+	return CGRectContainsPoint(self.contentRect, point);	
+} 
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+	
+}
+
+- (void)setContentView:(UIView *)v {
+	if (v != contentView) {
+		contentView = v;		
+		contentView.frame = self.contentRect;		
+		[self addSubview:contentView];
+	}
+}
+
+
+
+@end
+
+@implementation WEPopoverContainerView(Private)
+
+- (void)initFrame {
+	CGRect theFrame = CGRectOffset(CGRectUnion(bgRect, arrowRect), offset.x, offset.y);
+	
+	//If arrow rect origin is < 0 the frame above is extended to include it so we should offset the other rects
+	arrowOffset = CGPointMake(MAX(0, -arrowRect.origin.x), MAX(0, -arrowRect.origin.y));
+	bgRect = CGRectOffset(bgRect, arrowOffset.x, arrowOffset.y);
+	arrowRect = CGRectOffset(arrowRect, arrowOffset.x, arrowOffset.y);
+	
+	self.frame = theFrame;	
+}																		 
+
+- (CGSize)contentSize {
+	return self.contentRect.size;
+}
+
+- (CGRect)contentRect {
+	CGRect rect = CGRectMake(properties.leftBgMargin + properties.leftContentMargin + arrowOffset.x, 
+							 properties.topBgMargin + properties.topContentMargin + arrowOffset.y, 
+							 bgRect.size.width - properties.leftBgMargin - properties.rightBgMargin - properties.leftContentMargin - properties.rightContentMargin,
+							 bgRect.size.height - properties.topBgMargin - properties.bottomBgMargin - properties.topContentMargin - properties.bottomContentMargin);
+	return rect;
+}
+
+- (void)setProperties:(WEPopoverContainerViewProperties *)props {
+	if (properties != props) {
+		properties = props;
+	}
+}
+
+// NOTE: this method is completely rewritten by Nest Labs to do layout that meets our UI needs.
+// It's kinda shoehorned in so we didn't need to modify other WEPopover code.
+// It's not a general solution, does not obey supportedArrowDirections, and has bugs.
+// Sorry.
+- (void)determineGeometryForSize:(CGSize)theSize anchorRect:(CGRect)anchorRect displayArea:(CGRect)displayArea permittedArrowDirections:(UIPopoverArrowDirection)supportedArrowDirections {	
+	UIImage *downArrowImage = [UIImage imageNamed:properties.downArrowImageName];
+	UIImage *leftArrowImage = [UIImage imageNamed:properties.leftArrowImageName];
+	UIImage *rightArrowImage = [UIImage imageNamed:properties.rightArrowImageName];
+	
+	// try displaying above anchor
+	float topFreeSpace = (anchorRect.origin.y - (theSize.height + downArrowImage.size.height)) - displayArea.origin.y;
+	float leftFreeSpace = CGRectGetMidX(anchorRect) - CGRectGetMinX(displayArea);
+	float rightFreeSpace = CGRectGetMaxX(displayArea) - CGRectGetMidX(anchorRect);
+	if ((topFreeSpace >= 0) && (leftFreeSpace >= (rightArrowImage.size.width / 2) + 16) && (rightFreeSpace >= (leftArrowImage.size.width / 2) + 16)) {
+		bgRect = CGRectMake(0, 0, theSize.width, theSize.height);
+		arrowRect = CGRectMake((theSize.width - downArrowImage.size.width) / 2, theSize.height, downArrowImage.size.width, downArrowImage.size.height);
+		offset = CGPointMake(CGRectGetMidX(anchorRect) - (bgRect.size.width / 2), -(arrowRect.origin.y + arrowRect.size.height - anchorRect.origin.y));
+		arrowDirection = UIPopoverArrowDirectionDown;
+		arrowImage = downArrowImage;
+
+		// ...check for going off right edge
+		float overage = (bgRect.size.width + offset.x) - (displayArea.origin.x + displayArea.size.width);
+		if (overage > 0) {
+			arrowRect = CGRectOffset(arrowRect, overage, 0);
+			offset.x -= overage;
+		}
+		
+		// ...check for going off left edge
+		float underage = offset.x - displayArea.origin.x;
+		if (underage < 0) {
+			arrowRect = CGRectOffset(arrowRect, underage, 0);
+			offset.x -= underage;
+		}
+	} else {
+		// try left or right side
+		if (leftFreeSpace > rightFreeSpace) {
+			// ...to left
+			bgRect = CGRectMake(0, 0, theSize.width, theSize.height);
+			arrowRect = CGRectMake(theSize.width, (theSize.height - rightArrowImage.size.height) / 2, rightArrowImage.size.width, rightArrowImage.size.height);
+			offset = CGPointMake(anchorRect.origin.x - theSize.width - rightArrowImage.size.width, -((theSize.height - anchorRect.size.height) / 2) + anchorRect.origin.y);
+			arrowDirection = UIPopoverArrowDirectionRight;
+			arrowImage = rightArrowImage;
+		} else {
+			// ...to right
+			bgRect = CGRectMake(0, 0, theSize.width, theSize.height);
+			arrowRect = CGRectMake(-leftArrowImage.size.width, (theSize.height - leftArrowImage.size.height) / 2, leftArrowImage.size.width, leftArrowImage.size.height);
+			offset = CGPointMake(anchorRect.origin.x + anchorRect.size.width + leftArrowImage.size.width, -((theSize.height - anchorRect.size.height) / 2) + anchorRect.origin.y);
+			arrowDirection = UIPopoverArrowDirectionLeft;
+			arrowImage = leftArrowImage;
+		}
+		
+		// ...check for going off bottom
+		float overage = (CGRectGetMaxY(bgRect) + offset.y) - CGRectGetMaxY(displayArea);
+		if (overage > 0) {
+			overage = MIN(overage, CGRectGetMaxY(bgRect) - CGRectGetMaxY(arrowRect) - 12);
+			arrowRect = CGRectOffset(arrowRect, 0, overage);
+			offset.y -= overage;
+		}
+		
+		// ...check for going off top
+		float underage = (CGRectGetMinY(bgRect) + offset.y) - CGRectGetMinY(displayArea);
+		if (underage < 0) {
+			arrowRect = CGRectOffset(arrowRect, 0, underage);
+			offset.y -= underage;
+		}
+	}
+}
+
+@end
\ No newline at end of file
diff --git a/WEPopover/WEPopoverController.h b/WEPopover/WEPopoverController.h
new file mode 100755
index 0000000..aebc0f0
--- /dev/null
+++ b/WEPopover/WEPopoverController.h
@@ -0,0 +1,67 @@
+//
+//  WEPopoverController.h
+//  WEPopover
+//
+//  Created by Werner Altewischer on 02/09/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "WEPopoverContainerView.h"
+#import "WETouchableView.h"
+
+@class WEPopoverController;
+
+@protocol WEPopoverControllerDelegate<NSObject>
+
+- (void)popoverControllerDidDismissPopover:(WEPopoverController *)popoverController;
+- (BOOL)popoverControllerShouldDismissPopover:(WEPopoverController *)popoverController;
+
+@end
+
+/**
+ * @brief Popover controller for the iPhone, mimicing the iPad UIPopoverController interface. See that class for more details.
+ */
+@interface WEPopoverController : NSObject<WETouchableViewDelegate> {
+	UIViewController *contentViewController;
+	UIView *__weak view;
+	WETouchableView *backgroundView;
+	
+	BOOL popoverVisible;
+	UIPopoverArrowDirection popoverArrowDirection;
+	id <WEPopoverControllerDelegate> __weak delegate;
+	CGSize popoverContentSize;
+	WEPopoverContainerViewProperties *containerViewProperties;
+	id <NSObject> context;
+	NSArray *passthroughViews;	
+}
+
+@property(nonatomic, strong) UIViewController *contentViewController;
+
+@property (weak, nonatomic, readonly) UIView *view;
+@property (nonatomic, readonly, getter=isPopoverVisible) BOOL popoverVisible;
+@property (nonatomic, readonly) UIPopoverArrowDirection popoverArrowDirection;
+@property (nonatomic, weak) id <WEPopoverControllerDelegate> delegate;
+@property (nonatomic, assign) CGSize popoverContentSize;
+@property (nonatomic, strong) WEPopoverContainerViewProperties *containerViewProperties;
+@property (nonatomic, strong) id <NSObject> context;
+@property (nonatomic, copy) NSArray *passthroughViews;
+
+- (id)initWithContentViewController:(UIViewController *)theContentViewController;
+
+- (void)dismissPopoverAnimated:(BOOL)animated;
+
+- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item 
+			   permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections 
+							   animated:(BOOL)animated;
+
+- (void)presentPopoverFromRect:(CGRect)rect 
+						inView:(UIView *)view 
+	  permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections 
+					  animated:(BOOL)animated;
+
+- (void)repositionPopoverFromRect:(CGRect)rect
+						   inView:(UIView *)view
+		 permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections;
+
+@end
diff --git a/WEPopover/WEPopoverController.m b/WEPopover/WEPopoverController.m
new file mode 100755
index 0000000..b173ed0
--- /dev/null
+++ b/WEPopover/WEPopoverController.m
@@ -0,0 +1,278 @@
+//
+//  WEPopoverController.m
+//  WEPopover
+//
+//  Created by Werner Altewischer on 02/09/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import "WEPopoverController.h"
+#import "WEPopoverParentView.h"
+#import "UIBarButtonItem+WEPopover.h"
+
+#define FADE_DURATION 0.3
+
+@interface WEPopoverController(Private)
+
+- (UIView *)keyView;
+- (void)updateBackgroundPassthroughViews;
+- (void)setView:(UIView *)v;
+- (CGRect)displayAreaForView:(UIView *)theView;
+- (WEPopoverContainerViewProperties *)defaultContainerViewProperties;
+- (void)dismissPopoverAnimated:(BOOL)animated userInitiated:(BOOL)userInitiated;
+
+@end
+
+
+@implementation WEPopoverController
+
+@synthesize contentViewController;
+@synthesize popoverContentSize;
+@synthesize popoverVisible;
+@synthesize popoverArrowDirection;
+@synthesize delegate;
+@synthesize view;
+@synthesize containerViewProperties;
+@synthesize context;
+@synthesize passthroughViews;
+
+- (id)init {
+	if ((self = [super init])) {
+	}
+	return self;
+}
+
+- (id)initWithContentViewController:(UIViewController *)viewController {
+	if ((self = [self init])) {
+		self.contentViewController = viewController;
+	}
+	return self;
+}
+
+- (void)dealloc {
+	[self dismissPopoverAnimated:NO];
+}
+
+- (void)setContentViewController:(UIViewController *)vc {
+	if (vc != contentViewController) {
+		contentViewController = vc;
+		popoverContentSize = CGSizeZero;
+	}
+}
+
+//Overridden setter to copy the passthroughViews to the background view if it exists already
+- (void)setPassthroughViews:(NSArray *)array {
+	passthroughViews = nil;
+	if (array) {
+		passthroughViews = [[NSArray alloc] initWithArray:array];
+	}
+	[self updateBackgroundPassthroughViews];
+}
+
+- (void)dismissPopoverAnimated:(BOOL)animated {
+	
+	[self dismissPopoverAnimated:animated userInitiated:NO];
+}
+
+- (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item 
+			   permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections 
+							   animated:(BOOL)animated {
+	
+	UIView *v = [self keyView];
+	CGRect rect = [item frameInView:v];
+	
+	return [self presentPopoverFromRect:rect inView:v permittedArrowDirections:arrowDirections animated:animated];
+}
+
+- (void)presentPopoverFromRect:(CGRect)rect 
+						inView:(UIView *)theView 
+	  permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections 
+					  animated:(BOOL)animated {
+	
+	
+	[self dismissPopoverAnimated:NO];
+	
+	//First force a load view for the contentViewController so the popoverContentSize is properly initialized
+	// NEST: edit to avoid warning
+	if (contentViewController.view == nil) return;
+	
+	if (CGSizeEqualToSize(popoverContentSize, CGSizeZero)) {
+		popoverContentSize = contentViewController.contentSizeForViewInPopover;
+	}
+	
+	CGRect displayArea = [self displayAreaForView:theView];
+	
+	WEPopoverContainerViewProperties *props = self.containerViewProperties ? self.containerViewProperties : [self defaultContainerViewProperties];
+	WEPopoverContainerView *containerView = [[WEPopoverContainerView alloc] initWithSize:self.popoverContentSize anchorRect:rect displayArea:displayArea permittedArrowDirections:arrowDirections properties:props];
+	popoverArrowDirection = containerView.arrowDirection;
+	
+	UIView *keyView = self.keyView;
+	
+	backgroundView = [[WETouchableView alloc] initWithFrame:keyView.bounds];
+	backgroundView.contentMode = UIViewContentModeScaleToFill;
+	backgroundView.autoresizingMask = ( UIViewAutoresizingFlexibleLeftMargin |
+									   UIViewAutoresizingFlexibleWidth |
+									   UIViewAutoresizingFlexibleRightMargin |
+									   UIViewAutoresizingFlexibleTopMargin |
+									   UIViewAutoresizingFlexibleHeight |
+									   UIViewAutoresizingFlexibleBottomMargin);
+	backgroundView.backgroundColor = [UIColor clearColor];
+	backgroundView.delegate = self;
+	
+	[keyView addSubview:backgroundView];
+	
+	containerView.frame = [theView convertRect:containerView.frame toView:backgroundView];
+	
+	[backgroundView addSubview:containerView];
+	
+	containerView.contentView = contentViewController.view;
+	containerView.autoresizingMask = ( UIViewAutoresizingFlexibleLeftMargin |
+									  UIViewAutoresizingFlexibleRightMargin);
+	
+	self.view = containerView;
+	[self updateBackgroundPassthroughViews];
+	
+	[contentViewController viewWillAppear:animated];
+	
+	[self.view becomeFirstResponder];
+	
+	if (animated) {
+		self.view.alpha = 0.0;
+
+		[UIView animateWithDuration:FADE_DURATION animations:^{
+			self.view.alpha = 1.0;
+		} completion:^(BOOL finished) {
+			self.view.userInteractionEnabled = YES;
+			popoverVisible = YES;
+			[contentViewController viewDidAppear:YES];
+		}];
+	} else {
+		popoverVisible = YES;
+		[contentViewController viewDidAppear:animated];
+	}	
+}
+
+- (void)repositionPopoverFromRect:(CGRect)rect
+						   inView:(UIView *)theView
+		 permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections {
+	
+	CGRect displayArea = [self displayAreaForView:theView];
+	WEPopoverContainerView *containerView = (WEPopoverContainerView *)self.view;
+	[containerView updatePositionWithAnchorRect:rect
+									displayArea:displayArea
+					   permittedArrowDirections:arrowDirections];
+	
+	popoverArrowDirection = containerView.arrowDirection;
+	containerView.frame = [theView convertRect:containerView.frame toView:backgroundView];
+}
+
+#pragma mark -
+#pragma mark WETouchableViewDelegate implementation
+
+- (void)viewWasTouched:(WETouchableView *)view {
+	if (popoverVisible) {
+		if (!delegate || [delegate popoverControllerShouldDismissPopover:self]) {
+			[self dismissPopoverAnimated:YES userInitiated:YES];
+		}
+	}
+}
+
+@end
+
+
+@implementation WEPopoverController(Private)
+
+- (UIView *)keyView {
+	UIWindow *w = [[UIApplication sharedApplication] keyWindow];
+	if (w.subviews.count > 0) {
+		return [w.subviews objectAtIndex:0];
+	} else {
+		return w;
+	}
+}
+
+- (void)setView:(UIView *)v {
+	if (view != v) {
+		view = v;
+	}
+}
+
+- (void)updateBackgroundPassthroughViews {
+	backgroundView.passthroughViews = passthroughViews;
+}
+
+
+- (void)dismissPopoverAnimated:(BOOL)animated userInitiated:(BOOL)userInitiated {
+	if (self.view) {
+		[contentViewController viewWillDisappear:animated];
+		popoverVisible = NO;
+		[self.view resignFirstResponder];
+		if (animated) {
+			
+			self.view.userInteractionEnabled = NO;
+			[UIView animateWithDuration:FADE_DURATION animations:^{
+				self.view.alpha = 0.0;
+			} completion:^(BOOL finished) {
+				popoverVisible = NO;
+				[contentViewController viewDidDisappear:YES];
+				[self.view removeFromSuperview];
+				self.view = nil;
+				[backgroundView removeFromSuperview];
+				backgroundView = nil;
+								
+				if (userInitiated) {
+					//Only send message to delegate in case the user initiated this event, which is if he touched outside the view
+					[delegate popoverControllerDidDismissPopover:self];
+				}
+			}];
+		} else {
+			[contentViewController viewDidDisappear:animated];
+			[self.view removeFromSuperview];
+			self.view = nil;
+			[backgroundView removeFromSuperview];
+			backgroundView = nil;
+		}
+	}
+}
+
+- (CGRect)displayAreaForView:(UIView *)theView {
+	CGRect displayArea = CGRectZero;
+	if ([theView conformsToProtocol:@protocol(WEPopoverParentView)] && [theView respondsToSelector:@selector(displayAreaForPopover)]) {
+		displayArea = [(id <WEPopoverParentView>)theView displayAreaForPopover];
+	} else {
+		displayArea = [[[UIApplication sharedApplication] keyWindow] convertRect:[[UIScreen mainScreen] applicationFrame] toView:theView];
+		displayArea = CGRectInset(displayArea, 6, 6);	// give some margin from the edges of the screen
+	}
+	return displayArea;
+}
+
+//Enable to use the simple popover style
+- (WEPopoverContainerViewProperties *)defaultContainerViewProperties {
+	WEPopoverContainerViewProperties *ret = [WEPopoverContainerViewProperties new];
+	
+	CGSize imageSize = CGSizeMake(30.0f, 30.0f);
+	NSString *bgImageName = @"popoverBgSimple.png";
+	CGFloat bgMargin = 0.0;
+	CGFloat contentMargin = 12.0;
+	
+	ret.leftBgMargin = bgMargin;
+	ret.rightBgMargin = bgMargin;
+	ret.topBgMargin = bgMargin;
+	ret.bottomBgMargin = bgMargin;
+	ret.leftBgCapSize = imageSize.width/2;
+	ret.topBgCapSize = imageSize.height/2;
+	ret.bgImageName = bgImageName;
+	ret.leftContentMargin = contentMargin;
+	ret.rightContentMargin = contentMargin;
+	ret.topContentMargin = contentMargin;
+	ret.bottomContentMargin = contentMargin;
+	ret.arrowMargin = 1.0;
+	
+	ret.upArrowImageName = @"popoverArrowUpSimple.png";
+	ret.downArrowImageName = @"popoverArrowDownSimple.png";
+	ret.leftArrowImageName = @"popoverArrowLeftSimple.png";
+	ret.rightArrowImageName = @"popoverArrowRightSimple.png";
+	return ret;
+}
+
+@end
diff --git a/WEPopover/WEPopoverParentView.h b/WEPopover/WEPopoverParentView.h
new file mode 100755
index 0000000..111f8fa
--- /dev/null
+++ b/WEPopover/WEPopoverParentView.h
@@ -0,0 +1,15 @@
+/*
+ *  WEPopoverParentView.h
+ *  WEPopover
+ *
+ *  Created by Werner Altewischer on 02/09/10.
+ *  Copyright 2010 Werner IT Consultancy. All rights reserved.
+ *
+ */
+
+@protocol WEPopoverParentView
+
+@optional
+- (CGRect)displayAreaForPopover;
+
+@end
\ No newline at end of file
diff --git a/WEPopover/WETouchableView.h b/WEPopover/WETouchableView.h
new file mode 100755
index 0000000..5b8321f
--- /dev/null
+++ b/WEPopover/WETouchableView.h
@@ -0,0 +1,36 @@
+//
+//  WETouchableView.h
+//  WEPopover
+//
+//  Created by Werner Altewischer on 12/21/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class WETouchableView;
+
+/**
+  * @brief delegate to receive touch events
+  */
+@protocol WETouchableViewDelegate<NSObject>
+
+- (void)viewWasTouched:(WETouchableView *)view;
+
+@end
+
+/**
+ * @brief View that can handle touch events and/or disable touch forwording to child views
+ */
+@interface WETouchableView : UIView {
+	BOOL touchForwardingDisabled;
+	id <WETouchableViewDelegate> __weak delegate;
+	NSArray *passthroughViews;
+	BOOL testHits;
+}
+
+@property (nonatomic, assign) BOOL touchForwardingDisabled;
+@property (nonatomic, weak) id <WETouchableViewDelegate> delegate;
+@property (nonatomic, copy) NSArray *passthroughViews;
+
+@end
diff --git a/WEPopover/WETouchableView.m b/WEPopover/WETouchableView.m
new file mode 100755
index 0000000..304ed39
--- /dev/null
+++ b/WEPopover/WETouchableView.m
@@ -0,0 +1,66 @@
+//
+//  WETouchableView.m
+//  WEPopover
+//
+//  Created by Werner Altewischer on 12/21/10.
+//  Copyright 2010 Werner IT Consultancy. All rights reserved.
+//
+
+#import "WETouchableView.h"
+
+@interface WETouchableView(Private)
+
+- (BOOL)isPassthroughView:(UIView *)v;
+
+@end
+
+@implementation WETouchableView
+
+@synthesize touchForwardingDisabled, delegate, passthroughViews;
+
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+	if (testHits) {
+		return nil;
+	} else if (touchForwardingDisabled) {
+		return self;
+	} else {
+		UIView *hitView = [super hitTest:point withEvent:event];
+		
+		if (hitView == self) {
+			//Test whether any of the passthrough views would handle this touch
+			testHits = YES;
+			UIView *superHitView = [self.superview hitTest:point withEvent:event];
+			testHits = NO;
+			
+			if ([self isPassthroughView:superHitView]) {
+				hitView = superHitView;
+			}
+		}
+		
+		return hitView;
+	}
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+	[self.delegate viewWasTouched:self];
+}
+
+@end
+
+@implementation WETouchableView(Private)
+
+- (BOOL)isPassthroughView:(UIView *)v {
+	
+	if (v == nil) {
+		return NO;
+	}
+	
+	if ([passthroughViews containsObject:v]) {
+		return YES;
+	}
+	
+	return [self isPassthroughView:v.superview];
+}
+
+@end