Changeset 276325 in webkit
- Timestamp:
- Apr 20, 2021, 3:45:13 PM (4 years ago)
- Location:
- trunk/Source
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r276317 r276325 1 2021-04-20 Aditya Keerthi <akeerthi@apple.com> 2 3 [iOS][FCR] Update date/time picker appearance 4 https://bugs.webkit.org/show_bug.cgi?id=224794 5 <rdar://problem/76785859> 6 7 Reviewed by Wenson Hsieh. 8 9 * en.lproj/Localizable.strings: 10 11 Remove now unused string. 12 13 * platform/LocalizedStrings.cpp: 14 * platform/LocalizedStrings.h: 15 * platform/cocoa/LocalizedStringsCocoa.mm: 16 (WebCore::formControlDoneButtonTitle): 17 18 Moved definition out of PLATFORM(WATCHOS) in LocalizedStrings.cpp and 19 into LocalizedStringsCocoa, so that the "Done" string can be used by 20 PLATFORM(IOS_FAMILY). 21 1 22 2021-04-20 Fujii Hironori <Hironori.Fujii@sony.com> 2 23 -
trunk/Source/WebCore/en.lproj/Localizable.strings
r275358 r276325 332 332 "Donate with Apple Pay" = "Donate with Apple Pay"; 333 333 334 /* Title of the Done button for zoomedform controls. */334 /* Title of the Done button for form controls. */ 335 335 "Done" = "Done"; 336 336 … … 587 587 "Numbered list" = "Numbered list"; 588 588 589 /* Title of the OK button in date/time form controls. */590 "OK (OK button title in date/time picker)" = "OK";591 592 589 /* Title of the OK button for the number pad in zoomed form controls. */ 593 590 "OK (OK button title in extra zoomed number pad)" = "OK"; -
trunk/Source/WebCore/platform/LocalizedStrings.cpp
r274148 r276325 1190 1190 } 1191 1191 1192 String formControlDoneButtonTitle()1193 {1194 return WEB_UI_STRING("Done", "Title of the Done button for zoomed form controls.");1195 }1196 1197 1192 String formControlCancelButtonTitle() 1198 1193 { -
trunk/Source/WebCore/platform/LocalizedStrings.h
r274698 r276325 266 266 String fileButtonNoMediaFileSelectedLabel(); 267 267 String fileButtonNoMediaFilesSelectedLabel(); 268 269 WEBCORE_EXPORT String formControlDoneButtonTitle(); 268 270 #endif 269 271 … … 335 337 WEBCORE_EXPORT String numberPadOKButtonTitle(); 336 338 WEBCORE_EXPORT String formControlCancelButtonTitle(); 337 WEBCORE_EXPORT String formControlDoneButtonTitle();338 339 WEBCORE_EXPORT String formControlHideButtonTitle(); 339 340 WEBCORE_EXPORT String formControlGoButtonTitle(); -
trunk/Source/WebCore/platform/cocoa/LocalizedStringsCocoa.mm
r272997 r276325 268 268 return WEB_UI_STRING("no media selected (multiple)", "Text to display in file button used in HTML forms for media files when no media files are selected and the button allows multiple files to be selected"); 269 269 } 270 271 272 String formControlDoneButtonTitle() 273 { 274 return WEB_UI_STRING("Done", "Title of the Done button for form controls."); 275 } 270 276 #endif 271 277 -
trunk/Source/WebKit/ChangeLog
r276324 r276325 1 2021-04-20 Aditya Keerthi <akeerthi@apple.com> 2 3 [iOS][FCR] Update date/time picker appearance 4 https://bugs.webkit.org/show_bug.cgi?id=224794 5 <rdar://problem/76785859> 6 7 Reviewed by Wenson Hsieh. 8 9 Date/time pickers should have a system material background and should 10 avoid obscuring the associated element when possible. 11 12 * Platform/spi/ios/UIKitSPI.h: 13 14 Add new SPI declarations to support date/time picker modifications. 15 16 * UIProcess/ios/WKContentViewInteraction.mm: 17 (createTargetedPreview): 18 (createFallbackTargetedPreview): 19 (-[WKContentView _createTargetedContextMenuHintPreviewForFocusedElement]): 20 21 Set the UITargetedPreview background color to clearColor when 22 presenting a date/time picker, so that the presented picker has a 23 visible material effect. Without this change, the picker would have a 24 solid white or black background. 25 26 * UIProcess/ios/forms/WKDateTimeInputControl.mm: 27 (-[WKDateTimePickerViewController initWithDelegate:]): 28 (-[WKDateTimePickerViewController viewDidLoad]): 29 30 Add a system material background to the date picker using 31 UIVisualEffectView. 32 33 (-[WKDateTimePickerViewController datePickerChanged:]): 34 (-[WKDateTimePickerViewController resetButtonPressed:]): 35 (-[WKDateTimePickerViewController doneButtonPressed:]): 36 (-[WKDateTimePickerViewController datePickerInsets]): 37 (-[WKDateTimePickerViewController preferredDatePickerSize]): 38 (-[WKDateTimePickerViewController preferredContentSize]): 39 (-[WKDateTimePickerViewController date]): 40 (-[WKDateTimePickerViewController setDate:]): 41 (-[WKDateTimePickerViewController setDatePickerMode:]): 42 (-[WKDateTimePickerViewController timeZone]): 43 (-[WKDateTimePickerViewController setTimeZone:]): 44 (-[WKDateTimePickerViewController calendar]): 45 (-[WKDateTimePicker initWithView:datePickerMode:]): 46 (-[WKDateTimePicker _preferredEdgeInsetsForDateTimePicker]): 47 48 Attempt to present the date picker in a way that does not obscure the 49 element. 50 51 (-[WKDateTimePicker _contextMenuInteraction:styleForMenuWithConfiguration:]): 52 (-[WKDateTimePicker contextMenuInteraction:configurationForMenuAtLocation:]): 53 (-[WKDateTimePicker dateTimePickerViewControllerDidChangeDate:]): 54 (-[WKDateTimePicker dateTimePickerViewControllerDidPressResetButton:]): 55 (-[WKDateTimePicker dateTimePickerViewControllerDidPressDoneButton:]): 56 (-[WKDateTimePicker shouldForceGregorianCalendar]): 57 (-[WKDateTimePicker dealloc]): 58 (-[WKDateTimePicker _timeZoneOffsetFromGMT:]): 59 (-[WKDateTimePicker _sanitizeInputValueForFormatter:]): 60 (-[WKDateTimePicker dateFormatterForPicker]): 61 (-[WKDateTimePicker _dateChangedSetAsNumber]): 62 (-[WKDateTimePicker _dateChangedSetAsString]): 63 (-[WKDateTimePicker setDateTimePickerToInitialValue]): 64 (-[WKDateTimePicker controlView]): 65 66 Updated this method to return nil, matching other form controls that 67 do not present a keyboard input view (example: <select>). 68 69 (-[WKDateTimePicker controlBeginEditing]): 70 (-[WKDateTimePicker controlEndEditing]): 71 (-[WKDateTimePicker calendarType]): 72 (-[WKDateTimePicker hour]): 73 (-[WKDateTimePicker minute]): 74 (-[WKDateTimePicker setHour:minute:]): 75 1 76 2021-04-20 Keith Miller <keith_miller@apple.com> 2 77 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r276312 r276325 216 216 @property (nonatomic, readwrite, assign) UIDatePickerStyle preferredDatePickerStyle; 217 217 #endif 218 - (UIEdgeInsets)_appliedInsetsToEdgeOfContent; 218 219 @end 219 220 … … 1198 1199 typedef NS_ENUM(NSUInteger, _UIContextMenuLayout) { 1199 1200 _UIContextMenuLayoutActionsOnly = 1, 1201 _UIContextMenuLayoutPreviewOnly = 2, 1200 1202 _UIContextMenuLayoutCompactMenu = 3, 1201 1203 _UIContextMenuLayoutAutomatic = 100, … … 1206 1208 @property (nonatomic) UIEdgeInsets preferredEdgeInsets; 1207 1209 @property (nonatomic) BOOL hasInteractivePreview; 1210 @property (nonatomic) BOOL prefersCenteredPreviewWhenActionsAreAbsent; 1211 @property (nonatomic) BOOL ignoresDefaultSizingRules; 1208 1212 @property (nonatomic, strong) NSArray *preferredBackgroundEffects; 1209 1213 + (instancetype)defaultStyle; … … 1488 1492 1489 1493 UIEdgeInsets UIEdgeInsetsAdd(UIEdgeInsets lhs, UIEdgeInsets rhs, UIRectEdge); 1494 UIEdgeInsets UIEdgeInsetsSubtract(UIEdgeInsets lhs, UIEdgeInsets rhs, UIRectEdge); 1490 1495 1491 1496 extern NSString *const UIBacklightLevelChangedNotification; -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r276219 r276325 8355 8355 } 8356 8356 8357 static RetainPtr<UITargetedPreview> createFallbackTargetedPreview(UIView *rootView, UIView *containerView, const WebCore::FloatRect& frameInRootViewCoordinates )8357 static RetainPtr<UITargetedPreview> createFallbackTargetedPreview(UIView *rootView, UIView *containerView, const WebCore::FloatRect& frameInRootViewCoordinates, UIColor *backgroundColor) 8358 8358 { 8359 8359 if (!containerView.window) … … 8364 8364 8365 8365 auto parameters = adoptNS([[UIPreviewParameters alloc] init]); 8366 if (backgroundColor) 8367 [parameters setBackgroundColor:backgroundColor]; 8368 8366 8369 UIView *snapshotView = [rootView resizableSnapshotViewFromRect:frameInRootViewCoordinates afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero]; 8367 8370 … … 8381 8384 - (UITargetedPreview *)_createTargetedContextMenuHintPreviewForFocusedElement 8382 8385 { 8383 RetainPtr<UITargetedPreview> targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _focusedElementInformation.interactionRect); 8386 auto backgroundColor = [&]() -> UIColor * { 8387 switch (_focusedElementInformation.elementType) { 8388 case WebKit::InputType::Date: 8389 case WebKit::InputType::Month: 8390 case WebKit::InputType::DateTimeLocal: 8391 case WebKit::InputType::Time: 8392 return UIColor.clearColor; 8393 default: 8394 return nil; 8395 } 8396 }(); 8397 8398 auto targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _focusedElementInformation.interactionRect, backgroundColor); 8384 8399 8385 8400 [self _updateTargetedPreviewScrollViewUsingContainerScrollingNodeID:_focusedElementInformation.containerScrollingNodeID]; … … 8404 8419 8405 8420 if (!targetedPreview) 8406 targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _positionInformation.bounds );8421 targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _positionInformation.bounds, nil); 8407 8422 8408 8423 [self _updateTargetedPreviewScrollViewUsingContainerScrollingNodeID:_positionInformation.containerScrollingNodeID]; -
trunk/Source/WebKit/UIProcess/ios/forms/WKDateTimeInputControl.mm
r275532 r276325 34 34 #import "WKWebViewPrivateForTesting.h" 35 35 #import "WebPageProxy.h" 36 #import <UIKit/UIBarButtonItem.h>37 36 #import <UIKit/UIDatePicker.h> 38 37 #import <WebCore/LocalizedStrings.h> … … 40 39 #import <wtf/RetainPtr.h> 41 40 42 @interface WKDateTimeContextMenuViewController : UIViewController 41 @class WKDateTimePickerViewController; 42 43 @protocol WKDateTimePickerViewControllerDelegate <NSObject> 44 - (void)dateTimePickerViewControllerDidChangeDate:(WKDateTimePickerViewController *)dateTimePickerViewController; 45 - (void)dateTimePickerViewControllerDidPressResetButton:(WKDateTimePickerViewController *)dateTimePickerViewController; 46 - (void)dateTimePickerViewControllerDidPressDoneButton:(WKDateTimePickerViewController *)dateTimePickerViewController; 47 48 - (BOOL)shouldForceGregorianCalendar; 49 @end 50 51 @interface WKDateTimePickerViewController : UIViewController 52 - (instancetype)initWithDelegate:(id<WKDateTimePickerViewControllerDelegate>)delegate; 53 @end 54 55 @implementation WKDateTimePickerViewController { 56 CGSize _contentSize; 57 58 RetainPtr<UIDatePicker> _datePicker; 59 WeakObjCPtr<id <WKDateTimePickerViewControllerDelegate>> _delegate; 60 } 61 62 static const CGFloat kDateTimePickerButtonFontSize = 17; 63 static const CGFloat kDateTimePickerToolbarHeight = 44; 64 static const CGFloat kDateTimePickerSeparatorHeight = 1; 65 static const CGFloat kDateTimePickerViewMargin = 16; 66 67 static const CGFloat kDateTimePickerDefaultWidth = 320; 68 static const CGFloat kDateTimePickerTimeControlWidth = 218; 69 static const CGFloat kDateTimePickerTimeControlHeight = 172; 70 71 - (instancetype)initWithDelegate:(id <WKDateTimePickerViewControllerDelegate>)delegate 72 { 73 if (!(self = [super init])) 74 return nil; 75 76 _delegate = delegate; 77 78 _datePicker = adoptNS([[UIDatePicker alloc] init]); 79 [_datePicker addTarget:self action:@selector(datePickerChanged:) forControlEvents:UIControlEventValueChanged]; 80 [_datePicker setTranslatesAutoresizingMaskIntoConstraints:NO]; 81 82 if ([_delegate shouldForceGregorianCalendar]) 83 [_datePicker setCalendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]]; 84 85 return self; 86 } 87 88 - (void)viewDidLoad 89 { 90 [super viewDidLoad]; 91 92 CGSize contentSize = self.preferredContentSize; 93 94 auto backgroundView = adoptNS([[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemMaterial]]); 95 [backgroundView setFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)]; 96 [self.view addSubview:backgroundView.get()]; 97 98 [[backgroundView contentView] addSubview:_datePicker.get()]; 99 100 CGSize datePickerSize = self.preferredDatePickerSize; 101 UIEdgeInsets datePickerInsets = [self datePickerInsets]; 102 103 [NSLayoutConstraint activateConstraints:@[ 104 [[_datePicker topAnchor] constraintEqualToAnchor:[backgroundView contentView].topAnchor constant:datePickerInsets.top], 105 [[_datePicker leadingAnchor] constraintEqualToAnchor:[backgroundView contentView].leadingAnchor constant:datePickerInsets.left], 106 [[_datePicker widthAnchor] constraintEqualToConstant:datePickerSize.width], 107 [[_datePicker heightAnchor] constraintEqualToConstant:datePickerSize.height], 108 ]]; 109 110 auto toolbarView = adoptNS([[UIView alloc] init]); 111 [toolbarView setTranslatesAutoresizingMaskIntoConstraints:NO]; 112 [[backgroundView contentView] addSubview:toolbarView.get()]; 113 114 [NSLayoutConstraint activateConstraints:@[ 115 [[toolbarView bottomAnchor] constraintEqualToAnchor:[backgroundView contentView].bottomAnchor], 116 [[toolbarView leadingAnchor] constraintEqualToAnchor:[backgroundView contentView].leadingAnchor], 117 [[toolbarView heightAnchor] constraintEqualToConstant:kDateTimePickerToolbarHeight], 118 [[toolbarView widthAnchor] constraintEqualToAnchor:[backgroundView contentView].widthAnchor], 119 ]]; 120 121 auto separatorView = adoptNS([[UIView alloc] init]); 122 [separatorView setBackgroundColor:UIColor.separatorColor]; 123 124 NSString *resetString = WEB_UI_STRING_KEY("Reset", "Reset Button Date/Time Context Menu", "Reset button in date input context menu"); 125 UIButton *resetButton = [UIButton buttonWithType:UIButtonTypeSystem]; 126 resetButton.titleLabel.font = [UIFont systemFontOfSize:kDateTimePickerButtonFontSize]; 127 [resetButton setTitle:resetString forState:UIControlStateNormal]; 128 [resetButton addTarget:self action:@selector(resetButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 129 130 NSString *doneString = WebCore::formControlDoneButtonTitle(); 131 UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem]; 132 doneButton.titleLabel.font = [UIFont boldSystemFontOfSize:kDateTimePickerButtonFontSize]; 133 [doneButton setTitle:doneString forState:UIControlStateNormal]; 134 [doneButton addTarget:self action:@selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 135 136 for (UIView *subview in @[separatorView.get(), resetButton, doneButton]) { 137 subview.translatesAutoresizingMaskIntoConstraints = NO; 138 [toolbarView addSubview:subview]; 139 } 140 141 [NSLayoutConstraint activateConstraints:@[ 142 [[separatorView topAnchor] constraintEqualToAnchor:[toolbarView topAnchor]], 143 [[separatorView leadingAnchor] constraintEqualToAnchor:[toolbarView leadingAnchor]], 144 [[separatorView heightAnchor] constraintEqualToConstant:kDateTimePickerSeparatorHeight], 145 [[separatorView widthAnchor] constraintEqualToAnchor:[toolbarView widthAnchor]], 146 ]]; 147 148 [NSLayoutConstraint activateConstraints:@[ 149 [resetButton.leadingAnchor constraintEqualToAnchor:[toolbarView leadingAnchor] constant:kDateTimePickerViewMargin], 150 [resetButton.topAnchor constraintEqualToAnchor:[toolbarView topAnchor]], 151 [resetButton.bottomAnchor constraintEqualToAnchor:[toolbarView bottomAnchor]], 152 ]]; 153 154 [NSLayoutConstraint activateConstraints:@[ 155 [doneButton.trailingAnchor constraintEqualToAnchor:[toolbarView trailingAnchor] constant:-kDateTimePickerViewMargin], 156 [doneButton.topAnchor constraintEqualToAnchor:[toolbarView topAnchor]], 157 [doneButton.bottomAnchor constraintEqualToAnchor:[toolbarView bottomAnchor]], 158 ]]; 159 } 160 161 - (void)datePickerChanged:(id)sender 162 { 163 [_delegate dateTimePickerViewControllerDidChangeDate:self]; 164 } 165 166 - (void)resetButtonPressed:(id)sender 167 { 168 [_delegate dateTimePickerViewControllerDidPressResetButton:self]; 169 } 170 171 - (void)doneButtonPressed:(id)sender 172 { 173 [_delegate dateTimePickerViewControllerDidPressDoneButton:self]; 174 } 175 176 - (UIEdgeInsets)datePickerInsets 177 { 178 UIEdgeInsets expectedInsets = UIEdgeInsetsMake(kDateTimePickerViewMargin, kDateTimePickerViewMargin, kDateTimePickerViewMargin, kDateTimePickerViewMargin); 179 UIEdgeInsets appliedInsets = [_datePicker _appliedInsetsToEdgeOfContent]; 180 return UIEdgeInsetsSubtract(expectedInsets, appliedInsets, UIRectEdgeAll); 181 } 182 183 - (CGSize)preferredDatePickerSize 184 { 185 CGSize fittingSize = UILayoutFittingCompressedSize; 186 UILayoutPriority horizontalPriority = UILayoutPriorityFittingSizeLevel; 187 UILayoutPriority verticalPriority = UILayoutPriorityFittingSizeLevel; 188 if ([_datePicker datePickerMode] != UIDatePickerModeTime) 189 fittingSize.width = kDateTimePickerDefaultWidth; 190 else { 191 fittingSize.width = kDateTimePickerTimeControlWidth; 192 fittingSize.height = kDateTimePickerTimeControlHeight; 193 horizontalPriority = UILayoutPriorityRequired; 194 verticalPriority = UILayoutPriorityRequired; 195 } 196 197 CGSize layoutSize = [_datePicker systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:horizontalPriority verticalFittingPriority:verticalPriority]; 198 return layoutSize; 199 } 200 201 - (CGSize)preferredContentSize 202 { 203 // Cache the content size to workaround rdar://74749942. 204 if (CGSizeEqualToSize(_contentSize, CGSizeZero)) { 205 CGSize datePickerSize = [self preferredDatePickerSize]; 206 UIEdgeInsets datePickerInsets = [self datePickerInsets]; 207 208 _contentSize = CGSizeMake(datePickerSize.width + datePickerInsets.left + datePickerInsets.right, datePickerSize.height + kDateTimePickerToolbarHeight + datePickerInsets.top + datePickerInsets.bottom); 209 } 210 211 return _contentSize; 212 } 213 214 - (NSDate *)date 215 { 216 return [_datePicker date]; 217 } 218 219 - (void)setDate:(NSDate *)date 220 { 221 [_datePicker setDate:date]; 222 } 223 224 - (void)setDatePickerMode:(UIDatePickerMode)mode 225 { 226 [_datePicker setDatePickerMode:mode]; 227 228 #if HAVE(UIDATEPICKER_STYLE) 229 if (mode == UIDatePickerModeTime || mode == (UIDatePickerMode)UIDatePickerModeYearAndMonth) 230 [_datePicker setPreferredDatePickerStyle:UIDatePickerStyleWheels]; 231 else 232 [_datePicker setPreferredDatePickerStyle:UIDatePickerStyleInline]; 233 #endif 234 } 235 236 - (NSTimeZone *)timeZone 237 { 238 return [_datePicker timeZone]; 239 } 240 241 - (void)setTimeZone:(NSTimeZone *)timeZone 242 { 243 return [_datePicker setTimeZone:timeZone]; 244 } 245 246 - (NSCalendar *)calendar 247 { 248 return [_datePicker calendar]; 249 } 250 43 251 @end 44 252 … … 47 255 , UIContextMenuInteractionDelegate 48 256 #endif 257 , WKDateTimePickerViewControllerDelegate 49 258 > { 50 RetainPtr<UIDatePicker> _datePicker;51 259 NSString *_formatString; 52 260 RetainPtr<NSString> _initialValue; 53 261 NSTimeInterval _initialValueAsNumber; 54 262 BOOL _shouldRemoveTimeZoneInformation; 55 BOOL _isTimeInput;56 263 WKContentView *_view; 57 264 CGPoint _interactionPoint; 58 RetainPtr<WKDateTimeContextMenuViewController> _viewController;59 265 #if USE(UICONTEXTMENU) 60 266 RetainPtr<UIContextMenuInteraction> _dateTimeContextMenuInteraction; 61 267 #endif 62 BOOL _presenting;63 BOOL _preservingFocus; 64 } 268 RetainPtr<WKDateTimePickerViewController> _dateTimePickerViewController; 269 } 270 65 271 - (instancetype)initWithView:(WKContentView *)view datePickerMode:(UIDatePickerMode)mode; 66 - (WKDateTimeContextMenuViewController *)viewController; 272 67 273 @property (nonatomic, readonly) NSString *calendarType; 68 274 @property (nonatomic, readonly) double hour; 69 275 @property (nonatomic, readonly) double minute; 70 276 - (void)setHour:(NSInteger)hour minute:(NSInteger)minute; 71 @end72 73 @implementation WKDateTimeContextMenuViewController74 75 - (CGSize)preferredContentSize76 {77 // FIXME: Workaround, should be able to be readdressed after <rdar://problem/64143534>78 UIView *view = self.view.subviews[0];79 if (UIEdgeInsetsEqualToEdgeInsets(view.layoutMargins, UIEdgeInsetsZero)) {80 view.translatesAutoresizingMaskIntoConstraints = NO;81 [view layoutIfNeeded];82 view.translatesAutoresizingMaskIntoConstraints = YES;83 view.layoutMargins = UIEdgeInsetsMake(16, 16, 16, 16);84 }85 auto size = [view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];86 87 size.width = std::max<CGFloat>(size.width, 250.0);88 return size;89 }90 277 91 278 @end … … 98 285 static const NSTimeInterval kMillisecondsPerSecond = 1000; 99 286 100 #if HAVE(UIDATEPICKER_STYLE) 101 - (UIDatePickerStyle)datePickerStyle 102 { 103 switch (_view.focusedElementInformation.elementType) { 104 case WebKit::InputType::Month: 105 case WebKit::InputType::Time: 106 return UIDatePickerStyleWheels; 107 default: 108 return UIDatePickerStyleInline; 109 } 110 } 111 #endif 287 static const CGFloat kDateTimePickerControlMargin = 6; 112 288 113 289 - (id)initWithView:(WKContentView *)view datePickerMode:(UIDatePickerMode)mode … … 115 291 if (!(self = [super init])) 116 292 return nil; 293 117 294 _view = view; 118 295 _interactionPoint = [_view lastInteractionLocation]; 119 296 _shouldRemoveTimeZoneInformation = NO; 120 _isTimeInput = NO; 297 121 298 switch (view.focusedElementInformation.elementType) { 122 299 case WebKit::InputType::Date: … … 128 305 case WebKit::InputType::Time: 129 306 _formatString = kTimeFormatString; 130 _isTimeInput = YES;131 307 break; 132 308 case WebKit::InputType::DateTimeLocal: … … 136 312 break; 137 313 } 138 139 _datePicker = adoptNS([[UIDatePicker alloc] init]); 140 141 [_datePicker setDatePickerMode:mode]; 142 [_datePicker setHidden:NO]; 143 144 #if HAVE(UIDATEPICKER_STYLE) 145 [_datePicker setPreferredDatePickerStyle:[self datePickerStyle]]; 146 #endif 147 if ([self shouldPresentGregorianCalendar:view.focusedElementInformation]) 148 _datePicker.get().calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 149 150 [_datePicker addTarget:self action:@selector(_dateChangeHandler:) forControlEvents:UIControlEventValueChanged]; 151 314 315 _dateTimePickerViewController = adoptNS([[WKDateTimePickerViewController alloc] initWithDelegate:self]); 316 [_dateTimePickerViewController setDatePickerMode:mode]; 317 152 318 return self; 153 319 } 154 320 155 321 #if USE(UICONTEXTMENU) 322 323 - (UIEdgeInsets)_preferredEdgeInsetsForDateTimePicker 324 { 325 CGSize pickerSize = [_dateTimePickerViewController preferredContentSize]; 326 CGRect windowBounds = _view.textEffectsWindow.bounds; 327 CGRect elementFrameInWindowCoordinates = [_view convertRect:_view.focusedElementInformation.interactionRect toView:nil]; 328 329 // Attempt to present the date picker in a way that does not obscure the element. 330 331 CGFloat topInsetForBottomAlignment = CGRectGetMaxY(elementFrameInWindowCoordinates) + kDateTimePickerControlMargin; 332 CGFloat rightInsetForRightAlignment = CGRectGetWidth(windowBounds) - CGRectGetMaxX(elementFrameInWindowCoordinates); 333 334 BOOL canPresentBelowElement = (topInsetForBottomAlignment + pickerSize.height) < CGRectGetHeight(windowBounds); 335 BOOL canAlignToElementRight = (rightInsetForRightAlignment + pickerSize.width) < CGRectGetWidth(windowBounds); 336 337 // Try to present the picker from the bottom right of the element. 338 if (canPresentBelowElement && canAlignToElementRight) 339 return UIEdgeInsetsMake(topInsetForBottomAlignment, 0, 0, rightInsetForRightAlignment); 340 341 CGFloat leftInsetForLeftAlignment = CGRectGetMinX(elementFrameInWindowCoordinates); 342 343 BOOL canAlignToElementLeft = (leftInsetForLeftAlignment + pickerSize.width) <= CGRectGetWidth(windowBounds); 344 345 // Try to present the picker from the bottom left of the element. 346 if (canPresentBelowElement && canAlignToElementLeft) 347 return UIEdgeInsetsMake(topInsetForBottomAlignment, leftInsetForLeftAlignment, 0, 0); 348 349 // Try to present the picker underneath the element. 350 if (canPresentBelowElement) 351 return UIEdgeInsetsMake(topInsetForBottomAlignment, 0, 0, 0); 352 353 CGFloat bottomInsetForTopAlignment = CGRectGetHeight(windowBounds) - CGRectGetMinY(elementFrameInWindowCoordinates) + kDateTimePickerControlMargin; 354 355 BOOL canPresentAboveElement = (bottomInsetForTopAlignment + pickerSize.height) < CGRectGetHeight(windowBounds); 356 357 // Try to present the picker from the top right of the element. 358 if (canPresentAboveElement && canAlignToElementRight) 359 return UIEdgeInsetsMake(0, 0, bottomInsetForTopAlignment, rightInsetForRightAlignment); 360 361 // Try to present the picker from the top left of the element. 362 if (canPresentAboveElement && canAlignToElementLeft) 363 return UIEdgeInsetsMake(0, leftInsetForLeftAlignment, bottomInsetForTopAlignment, 0); 364 365 // Try to present the picker above the element. 366 if (canPresentAboveElement) 367 return UIEdgeInsetsMake(0, 0, bottomInsetForTopAlignment, 0); 368 369 CGFloat rightInsetForPresentingBesideElementLeft = CGRectGetWidth(windowBounds) - CGRectGetMinX(elementFrameInWindowCoordinates) + kDateTimePickerControlMargin; 370 BOOL canPresentBesideElementLeft = (rightInsetForPresentingBesideElementLeft + pickerSize.width) < CGRectGetWidth(windowBounds); 371 372 // Try to present the picker to the left of the element. 373 if (canPresentBesideElementLeft) 374 return UIEdgeInsetsMake(0, 0, 0, rightInsetForPresentingBesideElementLeft); 375 376 CGFloat leftInsetForPresentingBesideElementRight = CGRectGetMaxX(elementFrameInWindowCoordinates) + kDateTimePickerControlMargin; 377 BOOL canPresentBesideElementRight = (leftInsetForPresentingBesideElementRight + pickerSize.width) < CGRectGetWidth(windowBounds); 378 379 // Try to present the picker to the right of the element. 380 if (canPresentBesideElementRight) 381 return UIEdgeInsetsMake(0, leftInsetForPresentingBesideElementRight, 0, 0); 382 383 // Present the picker from the center of the element. 384 return UIEdgeInsetsZero; 385 } 156 386 157 387 - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration … … 165 395 style.hasInteractivePreview = YES; 166 396 style.preferredBackgroundEffects = @[ [UIVisualEffect emptyEffect] ]; 167 style.preferredLayout = _UIContextMenuLayoutAutomatic; 397 style.preferredLayout = _UIContextMenuLayoutPreviewOnly; 398 style.prefersCenteredPreviewWhenActionsAreAbsent = NO; 399 style.ignoresDefaultSizingRules = YES; 400 style.preferredEdgeInsets = [self _preferredEdgeInsetsForDateTimePicker]; 168 401 return style; 169 402 } … … 172 405 { 173 406 return [UIContextMenuConfiguration configurationWithIdentifier:@"_UIDatePickerCompactEditor" previewProvider:^{ 174 [_viewController setView:nil]; 175 _viewController = adoptNS([[WKDateTimeContextMenuViewController alloc] init]); 176 RetainPtr<UINavigationController> navigationController = adoptNS([[UINavigationController alloc] initWithRootViewController:_viewController.get()]); 177 178 NSString *resetString = WEB_UI_STRING_KEY("Reset", "Reset Button Date/Time Context Menu", "Reset button in date input context menu"); 179 NSString *okString = WEB_UI_STRING_KEY("OK", "OK (OK button title in date/time picker)", "Title of the OK button in date/time form controls."); 180 181 RetainPtr<UIBarButtonItem> okBarButton = adoptNS([[UIBarButtonItem alloc] initWithTitle:okString style:UIBarButtonItemStyleDone target:self action:@selector(ok:)]); 182 RetainPtr<UIBarButtonItem> blankBarButton = adoptNS([[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]); 183 RetainPtr<UIBarButtonItem> resetBarButton = adoptNS([[UIBarButtonItem alloc] initWithTitle:resetString style:UIBarButtonItemStylePlain target:self action:@selector(reset:)]); 184 185 [_viewController setToolbarItems:@[resetBarButton.get(), blankBarButton.get(), okBarButton.get()]]; 186 [navigationController setToolbarHidden:NO]; 187 188 auto centeringView = adoptNS([[UIView alloc] init]); 189 190 [centeringView addSubview:_datePicker.get()]; 191 192 _datePicker.get().translatesAutoresizingMaskIntoConstraints = NO; 193 auto widthConstraint = [[centeringView widthAnchor] constraintGreaterThanOrEqualToAnchor:[_datePicker widthAnchor]]; 194 auto heightConstraint = [[centeringView heightAnchor] constraintEqualToAnchor:[_datePicker heightAnchor]]; 195 auto horizontalConstraint = [[centeringView centerXAnchor] constraintEqualToAnchor:[_datePicker centerXAnchor]]; 196 auto verticalConstraint = [[centeringView centerYAnchor] constraintEqualToAnchor:[_datePicker centerYAnchor]]; 197 198 [NSLayoutConstraint activateConstraints:@[verticalConstraint, horizontalConstraint, widthConstraint, heightConstraint]]; 199 200 [_viewController setView:centeringView.get()]; 201 202 NSString *titleText = _view.inputLabelText; 203 if (![titleText isEqual:@""]) { 204 RetainPtr<UILabel> title = adoptNS([[UILabel alloc] init]); 205 [title setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]]; 206 [title setText:titleText]; 207 [title setTextColor:[UIColor secondaryLabelColor]]; 208 [title setTextAlignment:NSTextAlignmentNatural]; 209 RetainPtr<UIBarButtonItem> titleButton = adoptNS([[UIBarButtonItem alloc] initWithCustomView:title.get()]); 210 [_viewController navigationItem].leftBarButtonItem = titleButton.get(); 211 } else 212 [navigationController setNavigationBarHidden:YES animated:NO]; 213 214 [navigationController navigationBar].translucent = NO; 215 [navigationController navigationBar].barTintColor = [UIColor systemBackgroundColor]; 216 [navigationController toolbar].translucent = NO; 217 [navigationController toolbar].barTintColor = [UIColor systemBackgroundColor]; 218 return navigationController.get(); 407 return _dateTimePickerViewController.get(); 219 408 } actionProvider:nil]; 220 409 } … … 268 457 #endif 269 458 270 - (void)reset:(id)sender 459 - (void)dateTimePickerViewControllerDidChangeDate:(WKDateTimePickerViewController *)dateTimePickerViewController 460 { 461 [self _dateChanged]; 462 } 463 464 - (void)dateTimePickerViewControllerDidPressResetButton:(WKDateTimePickerViewController *)dateTimePickerViewController 271 465 { 272 466 [self setDateTimePickerToInitialValue]; … … 274 468 } 275 469 276 - (void) ok:(id)sender470 - (void)dateTimePickerViewControllerDidPressDoneButton:(WKDateTimePickerViewController *)dateTimePickerViewController 277 471 { 278 472 #if USE(UICONTEXTMENU) … … 281 475 } 282 476 283 - (NSString *)calendarType 284 { 285 return [_datePicker calendar].calendarIdentifier; 286 } 287 288 - (double)hour 289 { 290 NSCalendar *calendar = [NSCalendar currentCalendar]; 291 NSDateComponents *components = [calendar components:NSCalendarUnitHour fromDate:[_datePicker date]]; 292 293 return [components hour]; 294 } 295 296 - (double)minute 297 { 298 NSCalendar *calendar = [NSCalendar currentCalendar]; 299 NSDateComponents *components = [calendar components:NSCalendarUnitMinute fromDate:[_datePicker date]]; 300 301 return [components minute]; 477 - (BOOL)shouldForceGregorianCalendar 478 { 479 auto autofillFieldName = _view.focusedElementInformation.autofillFieldName; 480 return autofillFieldName == WebCore::AutofillFieldName::CcExpMonth 481 || autofillFieldName == WebCore::AutofillFieldName::CcExp 482 || autofillFieldName == WebCore::AutofillFieldName::CcExpYear; 302 483 } 303 484 304 485 - (void)dealloc 305 486 { 306 [_datePicker removeTarget:self action:NULL forControlEvents:UIControlEventValueChanged];307 487 #if USE(UICONTEXTMENU) 308 488 [self removeContextMenuInteraction]; … … 311 491 } 312 492 313 - (BOOL)shouldPresentGregorianCalendar:(const WebKit::FocusedElementInformation&)nodeInfo314 {315 return nodeInfo.autofillFieldName == WebCore::AutofillFieldName::CcExpMonth316 || nodeInfo.autofillFieldName == WebCore::AutofillFieldName::CcExp317 || nodeInfo.autofillFieldName == WebCore::AutofillFieldName::CcExpYear;318 }319 320 - (UIView *)controlView321 {322 return _datePicker.get();323 }324 325 493 - (NSInteger)_timeZoneOffsetFromGMT:(NSDate *)date 326 494 { … … 328 496 return 0; 329 497 330 return [ _datePicker.get().timeZonesecondsFromGMTForDate:date];498 return [[_dateTimePickerViewController timeZone] secondsFromGMTForDate:date]; 331 499 } 332 500 … … 335 503 // The "time" input type may have seconds and milliseconds information which we 336 504 // just ignore. For example: "01:56:20.391" is shortened to just "01:56". 337 if (_ isTimeInput)505 if (_view.focusedElementInformation.elementType == WebKit::InputType::Time) 338 506 return [value substringToIndex:[kTimeFormatString length]]; 339 507 340 508 return value; 341 }342 343 - (void)_dateChangedSetAsNumber344 {345 NSDate *date = [_datePicker date];346 [_view updateFocusedElementValueAsNumber:([date timeIntervalSince1970] + [self _timeZoneOffsetFromGMT:date]) * kMillisecondsPerSecond];347 509 } 348 510 … … 351 513 RetainPtr<NSLocale> englishLocale = adoptNS([[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]); 352 514 RetainPtr<NSDateFormatter> dateFormatter = adoptNS([[NSDateFormatter alloc] init]); 353 [dateFormatter setTimeZone: _datePicker.get().timeZone];515 [dateFormatter setTimeZone:[_dateTimePickerViewController timeZone]]; 354 516 [dateFormatter setDateFormat:_formatString]; 355 517 [dateFormatter setLocale:englishLocale.get()]; … … 357 519 } 358 520 521 - (void)_dateChangedSetAsNumber 522 { 523 NSDate *date = [_dateTimePickerViewController date]; 524 [_view updateFocusedElementValueAsNumber:(date.timeIntervalSince1970 + [self _timeZoneOffsetFromGMT:date]) * kMillisecondsPerSecond]; 525 } 526 359 527 - (void)_dateChangedSetAsString 360 528 { 361 529 // Force English locale because that is what HTML5 value parsing expects. 362 530 RetainPtr<NSDateFormatter> dateFormatter = [self dateFormatterForPicker]; 363 [_view updateFocusedElementValue:[dateFormatter stringFromDate:[_date Picker date]]];531 [_view updateFocusedElementValue:[dateFormatter stringFromDate:[_dateTimePickerViewController date]]]; 364 532 } 365 533 … … 376 544 } 377 545 378 - (void)_dateChangeHandler:(id)sender379 {380 [self _dateChanged];381 }382 383 546 - (void)setDateTimePickerToInitialValue 384 547 { 385 548 if ([_initialValue isEqual: @""]) { 386 [_date Picker setDate:[NSDate date]];549 [_dateTimePickerViewController setDate:[NSDate date]]; 387 550 [self _dateChanged]; 388 551 } else if (_formatString) { … … 390 553 RetainPtr<NSDateFormatter> dateFormatter = [self dateFormatterForPicker]; 391 554 NSDate *parsedDate = [dateFormatter dateFromString:[self _sanitizeInputValueForFormatter:_initialValue.get()]]; 392 [_date Picker setDate:parsedDate ? parsedDate : [NSDate date]];555 [_dateTimePickerViewController setDate:parsedDate ? parsedDate : [NSDate date]]; 393 556 } else { 394 557 // Convert the number value to a date object for the fields affected by timezones. … … 396 559 NSInteger timeZoneOffset = [self _timeZoneOffsetFromGMT:[NSDate dateWithTimeIntervalSince1970:secondsSince1970]]; 397 560 NSTimeInterval adjustedSecondsSince1970 = secondsSince1970 - timeZoneOffset; 398 [_datePicker setDate:[NSDate dateWithTimeIntervalSince1970:adjustedSecondsSince1970]]; 399 } 561 [_dateTimePickerViewController setDate:[NSDate dateWithTimeIntervalSince1970:adjustedSecondsSince1970]]; 562 } 563 } 564 565 - (UIView *)controlView 566 { 567 return nil; 400 568 } 401 569 402 570 - (void)controlBeginEditing 403 571 { 404 if (_presenting)405 return;406 407 _presenting = YES;408 409 572 auto elementType = _view.focusedElementInformation.elementType; 410 573 if (elementType == WebKit::InputType::Time || elementType == WebKit::InputType::DateTimeLocal) … … 412 575 413 576 // Set the time zone in case it changed. 414 _datePicker.get().timeZone = [NSTimeZonelocalTimeZone];577 [_dateTimePickerViewController setTimeZone:NSTimeZone.localTimeZone]; 415 578 416 579 // Currently no value for the <input>. Start the picker with the current time. … … 425 588 } 426 589 427 - (void)setHour:(NSInteger)hour minute:(NSInteger)minute428 {429 NSString *timeString = [NSString stringWithFormat:@"%.2ld:%.2ld", (long)hour, (long)minute];430 [_datePicker setDate:[[self dateFormatterForPicker] dateFromString:timeString]];431 [self _dateChanged];432 }433 434 - (WKDateTimeContextMenuViewController *)viewController435 {436 return _viewController.get();437 }438 439 590 - (void)controlEndEditing 440 591 { 441 _presenting = NO;442 443 592 [_view stopRelinquishingFirstResponderToFocusedElement]; 444 593 … … 447 596 #endif 448 597 } 598 599 - (NSString *)calendarType 600 { 601 return [_dateTimePickerViewController calendar].calendarIdentifier; 602 } 603 604 - (double)hour 605 { 606 NSCalendar *calendar = [NSCalendar currentCalendar]; 607 NSDateComponents *components = [calendar components:NSCalendarUnitHour fromDate:[_dateTimePickerViewController date]]; 608 609 return components.hour; 610 } 611 612 - (double)minute 613 { 614 NSCalendar *calendar = [NSCalendar currentCalendar]; 615 NSDateComponents *components = [calendar components:NSCalendarUnitMinute fromDate:[_dateTimePickerViewController date]]; 616 617 return components.minute; 618 } 619 620 - (void)setHour:(NSInteger)hour minute:(NSInteger)minute 621 { 622 NSString *timeString = [NSString stringWithFormat:@"%.2ld:%.2ld", (long)hour, (long)minute]; 623 [_dateTimePickerViewController setDate:[[self dateFormatterForPicker] dateFromString:timeString]]; 624 [self _dateChanged]; 625 } 626 449 627 @end 450 628
Note:
See TracChangeset
for help on using the changeset viewer.