99ff72b1e2ebe911d8f3ac907d6ad7b56e07ff1c
[WebKit-https.git] / Source / WebKit / UIProcess / ios / forms / WKFormPopover.mm
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKFormPopover.h"
28
29 #if PLATFORM(IOS_FAMILY)
30
31 #import "UIKitSPI.h"
32 #import "WKContentView.h"
33 #import "WKContentViewInteraction.h"
34 #import "WebPageProxy.h"
35 #import <wtf/RetainPtr.h>
36
37 using namespace WebKit;
38
39 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
40
41 @implementation WKFormRotatingAccessoryPopover
42
43 - (id)initWithView:(WKContentView *)view
44 {
45     if (!(self = [super initWithView:view]))
46         return nil;
47     self.dismissionDelegate = self;
48     return self;
49 }
50
51 - (void)accessoryDone
52 {
53     [self.view accessoryDone];
54 }
55
56 - (UIPopoverArrowDirection)popoverArrowDirections
57 {
58     UIPopoverArrowDirection directions = UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown;
59     if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) && [[UIPeripheralHost sharedInstance] isOnScreen])
60         directions = UIPopoverArrowDirectionLeft | UIPopoverArrowDirectionRight;
61     return directions;
62 }
63
64 - (void)popoverWasDismissed:(WKRotatingPopover *)popover
65 {
66     [self accessoryDone];
67 }
68
69 @end
70
71 @interface WKRotatingPopover () <UIPopoverControllerDelegate>
72 @end
73
74 @implementation WKRotatingPopover {
75     WKContentView *_view;
76
77     BOOL _isRotating;
78     CGPoint _presentationPoint;
79     RetainPtr<UIPopoverController> _popoverController;
80     id <WKRotatingPopoverDelegate> _dismissionDelegate;
81 }
82
83 - (id)initWithView:(WKContentView *)view
84 {
85     if (!(self = [super init]))
86         return nil;
87
88     _view = view;
89     self.presentationPoint = CGPointZero;
90
91     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
92     [center addObserver:self selector:@selector(willRotate:) name:UIWindowWillRotateNotification object:nil];
93     [center addObserver:self selector:@selector(didRotate:) name:UIWindowDidRotateNotification object:nil];
94
95     return self;
96 }
97
98 - (void)dealloc
99 {
100     _view = nil;
101
102     [_popoverController dismissPopoverAnimated:YES];
103     [_popoverController setDelegate:nil];
104     self.popoverController = nil;
105
106     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
107     [center removeObserver:self name:UIWindowWillRotateNotification object:nil];
108     [center removeObserver:self name:UIWindowDidRotateNotification object:nil];
109
110     [super dealloc];
111 }
112
113 - (UIPopoverController *)popoverController
114 {
115     return _popoverController.get();
116 }
117
118 - (void)setPopoverController:(UIPopoverController *)popoverController
119 {
120     if (_popoverController == popoverController)
121         return;
122
123     [_popoverController setDelegate:nil];
124     _popoverController = popoverController;
125     [_popoverController setDelegate:self];
126 }
127
128 - (UIPopoverArrowDirection)popoverArrowDirections
129 {
130     return UIPopoverArrowDirectionAny;
131 }
132
133 - (void)presentPopoverAnimated:(BOOL)animated
134 {
135     UIPopoverArrowDirection directions = [self popoverArrowDirections];
136
137     BOOL presentWithPoint = !CGPointEqualToPoint(self.presentationPoint, CGPointZero);
138     if (presentWithPoint) {
139         CGFloat scale = [_view page]->pageScaleFactor();
140         [_popoverController presentPopoverFromRect:CGRectIntegral(CGRectMake(self.presentationPoint.x * scale, self.presentationPoint.y * scale, 1, 1))
141                                             inView:_view
142                           permittedArrowDirections:directions
143                                           animated:animated];
144     } else {
145         CGRect boundingBoxOfDOMNode = _view.assistedNodeInformation.elementRect;
146         [_popoverController presentPopoverFromRect:CGRectIntegral(boundingBoxOfDOMNode)
147                                             inView:_view
148                           permittedArrowDirections:directions
149                                           animated:animated];
150     }
151 }
152
153 - (void)dismissPopoverAnimated:(BOOL)animated
154 {
155     [_popoverController dismissPopoverAnimated:animated];
156 }
157
158 - (void)willRotate:(NSNotification *)notification
159 {
160     _isRotating = YES;
161     [_popoverController dismissPopoverAnimated:NO];
162 }
163
164 - (void)didRotate:(NSNotification *)notification
165 {
166     _isRotating = NO;
167     [self presentPopoverAnimated:NO];
168 }
169
170 IGNORE_WARNINGS_BEGIN("deprecated-implementations")
171 - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
172 IGNORE_WARNINGS_END
173 {
174     if (_isRotating)
175         return;
176
177     [_dismissionDelegate popoverWasDismissed:self];
178 }
179
180 @end
181
182 ALLOW_DEPRECATED_DECLARATIONS_END
183
184 #endif // PLATFORM(IOS_FAMILY)