Skip to content

Commit

Permalink
Make date picker popup appear more like that of Apple’s Calendar.
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoNatan committed Sep 19, 2019
1 parent d02a6f0 commit 046172d
Show file tree
Hide file tree
Showing 17 changed files with 423 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
394148702095E85900A21F96 /* LNPropertyListDatePickerCell.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */; };
3946906C20976ED300B4A457 /* LNPropertyListDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */; };
3946906D20976ED300B4A457 /* LNPropertyListDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */; };
39D1528F23289668009124C8 /* LNPropertyListDatePickerPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */; };
39D1529023289668009124C8 /* LNPropertyListDatePickerPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */; };
39D152962328A9C4009124C8 /* _LNPropertyListDatePicker.h in Headers */ = {isa = PBXBuildFile; fileRef = 39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */; };
39D152972328A9C4009124C8 /* _LNPropertyListDatePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */; };
39DE8E942092030500ED16B4 /* LNPropertyListPopUpButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 39DE8E922092030500ED16B4 /* LNPropertyListPopUpButtonCell.h */; };
39DE8E952092030500ED16B4 /* LNPropertyListPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */; };
39DE8E9C2092214400ED16B4 /* LNPropertyListEditor-Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 39DE8E9B2092214300ED16B4 /* LNPropertyListEditor-Private.h */; };
Expand All @@ -49,6 +53,10 @@
3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LNPropertyListDatePickerCell.mm; sourceTree = "<group>"; };
3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDatePicker.h; sourceTree = "<group>"; };
3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListDatePicker.m; sourceTree = "<group>"; };
39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListDatePickerPanel.h; sourceTree = "<group>"; };
39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListDatePickerPanel.m; sourceTree = "<group>"; };
39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _LNPropertyListDatePicker.h; sourceTree = "<group>"; };
39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = _LNPropertyListDatePicker.m; sourceTree = "<group>"; };
39DE8E922092030500ED16B4 /* LNPropertyListPopUpButtonCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LNPropertyListPopUpButtonCell.h; sourceTree = "<group>"; };
39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LNPropertyListPopUpButtonCell.m; sourceTree = "<group>"; };
39DE8E9B2092214300ED16B4 /* LNPropertyListEditor-Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LNPropertyListEditor-Private.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -119,6 +127,10 @@
39DE8E932092030500ED16B4 /* LNPropertyListPopUpButtonCell.m */,
3941486D2095E85900A21F96 /* LNPropertyListDatePickerCell.h */,
3941486E2095E85900A21F96 /* LNPropertyListDatePickerCell.mm */,
39D1528D23289668009124C8 /* LNPropertyListDatePickerPanel.h */,
39D1528E23289668009124C8 /* LNPropertyListDatePickerPanel.m */,
39D152942328A9C4009124C8 /* _LNPropertyListDatePicker.h */,
39D152952328A9C4009124C8 /* _LNPropertyListDatePicker.m */,
3946906A20976ED300B4A457 /* LNPropertyListDatePicker.h */,
3946906B20976ED300B4A457 /* LNPropertyListDatePicker.m */,
);
Expand All @@ -133,6 +145,7 @@
buildActionMask = 2147483647;
files = (
393E1882207FAD26002E6136 /* LNPropertyListNode-Private.h in Headers */,
39D1528F23289668009124C8 /* LNPropertyListDatePickerPanel.h in Headers */,
391FF0332084270400005D0F /* LNPropertyListOutlineView.h in Headers */,
393E1875207F64A0002E6136 /* LNPropertyListEditor.h in Headers */,
391FF02F208412CC00005D0F /* LNPropertyListRowView.h in Headers */,
Expand All @@ -142,6 +155,7 @@
39DE8E942092030500ED16B4 /* LNPropertyListPopUpButtonCell.h in Headers */,
3946906C20976ED300B4A457 /* LNPropertyListDatePicker.h in Headers */,
3941486F2095E85900A21F96 /* LNPropertyListDatePickerCell.h in Headers */,
39D152962328A9C4009124C8 /* _LNPropertyListDatePicker.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -219,10 +233,12 @@
393E187A207F68B4002E6136 /* LNPropertyListNode.m in Sources */,
393E1886207FAEC6002E6136 /* LNPropertyListCellView.m in Sources */,
391FF0342084270400005D0F /* LNPropertyListOutlineView.m in Sources */,
39D152972328A9C4009124C8 /* _LNPropertyListDatePicker.m in Sources */,
3946906D20976ED300B4A457 /* LNPropertyListDatePicker.m in Sources */,
394148702095E85900A21F96 /* LNPropertyListDatePickerCell.mm in Sources */,
393E1876207F64A0002E6136 /* LNPropertyListEditor.m in Sources */,
39DE8E952092030500ED16B4 /* LNPropertyListPopUpButtonCell.m in Sources */,
39D1529023289668009124C8 /* LNPropertyListDatePickerPanel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -252,7 +268,6 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down Expand Up @@ -314,7 +329,6 @@
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
Expand Down
4 changes: 2 additions & 2 deletions LNPropertyListEditor/LNPropertyListEditor/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>1.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 Leo Natan. All rights reserved.</string>
<string>Copyright © 2018-2019 Leo Natan. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,9 @@
//

#import "LNPropertyListDatePicker.h"
#import "_LNPropertyListDatePicker.h"
#import "LNPropertyListDatePickerCell.h"

static NSPopover* __LNPropertyListDatePickerPopover;
static NSDatePicker* __LNPropertyListPopoverDatePicker;

@interface LNPropertyListDatePicker ()

@property (class, nonatomic, readonly, retain) NSDatePicker* __datePicker;
@property (class, nonatomic, readonly, retain) NSPopover* __datePickerPopover;

@end

@interface _LNPropertyListDatePickerInnerCell : NSCell

@property (nonatomic, copy) NSArray<NSCell*>* childCells;
Expand All @@ -39,82 +30,13 @@ - (void)setHighlighted:(BOOL)highlighted

@end

@interface _LNPropertyListDatePicker : NSDatePicker @end

@implementation _LNPropertyListDatePicker

- (BOOL)becomeFirstResponder
{
BOOL rv = [super becomeFirstResponder];

if(rv)
{
LNPropertyListDatePicker.__datePicker.dateValue = self.dateValue;
LNPropertyListDatePicker.__datePicker.target = self.target;
LNPropertyListDatePicker.__datePicker.action = self.action;

[LNPropertyListDatePicker.__datePickerPopover showRelativeToRect:self.bounds ofView:self preferredEdge:NSRectEdgeMinY];

}

return rv;
}

- (BOOL)resignFirstResponder
{
BOOL rv = [super resignFirstResponder];

if(rv)
{
[self unbind:NSValueBinding];
LNPropertyListDatePicker.__datePicker.target = nil;
LNPropertyListDatePicker.__datePicker.action = nil;

[LNPropertyListDatePicker.__datePickerPopover close];
}

return rv;
}

@end


IB_DESIGNABLE
@implementation LNPropertyListDatePicker
{
NSDatePicker* _datePicker;
_LNPropertyListDatePicker* _datePicker;
NSDatePicker* _timePicker;
}

+ (NSDatePicker*)__datePicker
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
__LNPropertyListPopoverDatePicker = [NSDatePicker new];
__LNPropertyListPopoverDatePicker.datePickerStyle = NSClockAndCalendarDatePickerStyle;
__LNPropertyListPopoverDatePicker.datePickerElements = NSTimeZoneDatePickerElementFlag | NSYearMonthDayDatePickerElementFlag | NSEraDatePickerElementFlag;
__LNPropertyListPopoverDatePicker.bordered = NO;
__LNPropertyListPopoverDatePicker.drawsBackground = NO;
[__LNPropertyListPopoverDatePicker sizeToFit];
});

return __LNPropertyListPopoverDatePicker;
}

+ (NSPopover*)__datePickerPopover
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSViewController* vc = [NSViewController new];
vc.view = LNPropertyListDatePicker.__datePicker;

__LNPropertyListDatePickerPopover = [NSPopover new];
__LNPropertyListDatePickerPopover.contentViewController = vc;
});

return __LNPropertyListDatePickerPopover;
}

- (void)prepareForInterfaceBuilder
{
_timePicker.dateValue = _datePicker.dateValue = [NSDate date];
Expand All @@ -135,10 +57,10 @@ - (void)awakeFromNib
NSFont* font = [NSFont monospacedDigitSystemFontOfSize:NSFont.smallSystemFontSize weight:NSFontWeightRegular];

_datePicker = [_LNPropertyListDatePicker new];
_datePicker.cell = [LNPropertyListDatePickerCell new];
_datePicker.cell = [LNLeadingZerosDatePickerCell new];
_datePicker.font = font;
_datePicker.datePickerStyle = NSTextFieldDatePickerStyle;
_datePicker.datePickerElements = NSYearMonthDayDatePickerElementFlag | NSEraDatePickerElementFlag;
_datePicker.datePickerStyle = NSDatePickerStyleTextField;
_datePicker.datePickerElements = NSDatePickerElementFlagYearMonthDay | NSDatePickerElementFlagEra;
_datePicker.bordered = NO;
_datePicker.drawsBackground = NO;
_datePicker.translatesAutoresizingMaskIntoConstraints = NO;
Expand All @@ -148,8 +70,8 @@ - (void)awakeFromNib
_timePicker = [NSDatePicker new];
_timePicker.cell = [LNPropertyListDatePickerCell new];
_timePicker.font = font;
_timePicker.datePickerStyle = NSTextFieldDatePickerStyle;
_timePicker.datePickerElements = NSHourMinuteSecondDatePickerElementFlag | NSTimeZoneDatePickerElementFlag;
_timePicker.datePickerStyle = NSDatePickerStyleTextField;
_timePicker.datePickerElements = NSDatePickerElementFlagHourMinuteSecond | NSDatePickerElementFlagTimeZone;
_timePicker.bordered = NO;
_timePicker.drawsBackground = NO;
_timePicker.translatesAutoresizingMaskIntoConstraints = NO;
Expand All @@ -171,14 +93,17 @@ - (void)awakeFromNib
[NSLayoutConstraint activateConstraints:@[
[self.heightAnchor constraintEqualToAnchor:_datePicker.heightAnchor],
[self.leadingAnchor constraintEqualToAnchor:_datePicker.leadingAnchor],
[self.centerYAnchor constraintEqualToAnchor:_datePicker.centerYAnchor],
[self.centerYAnchor constraintEqualToAnchor:_datePicker.centerYAnchor constant:-1.5],
[_timePicker.leadingAnchor constraintEqualToAnchor:_datePicker.trailingAnchor constant:2],
[self.centerYAnchor constraintEqualToAnchor:_timePicker.centerYAnchor],
[self.centerYAnchor constraintEqualToAnchor:_timePicker.centerYAnchor constant:-1.5],
[self.trailingAnchor constraintEqualToAnchor:_timePicker.trailingAnchor],
]];

[self setContentHuggingPriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];
[self setContentCompressionResistancePriority:NSLayoutPriorityRequired forOrientation:NSLayoutConstraintOrientationHorizontal];

self.wantsLayer = YES;
self.layer.masksToBounds = NO;
}

- (void)_setDateValue:(NSDate *)dateValue sendAction:(BOOL)sendAction
Expand All @@ -187,10 +112,8 @@ - (void)_setDateValue:(NSDate *)dateValue sendAction:(BOOL)sendAction

_datePicker.dateValue = self.dateValue;
_timePicker.dateValue = self.dateValue;
if(LNPropertyListDatePicker.__datePicker.target == self)
{
LNPropertyListDatePicker.__datePicker.dateValue = self.dateValue;
}
_datePicker.visualDatePicker.dateValue = self.dateValue;
_datePicker.textDatePicker.dateValue = self.dateValue;

if(sendAction)
{
Expand All @@ -213,4 +136,9 @@ - (IBAction)_internalDatePickerValueChanged:(id)sender
[self _setDateValue:[sender dateValue] sendAction:YES];
}

- (BOOL)resignFirstResponder
{
return [super resignFirstResponder];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

#import <Cocoa/Cocoa.h>

@interface LNPropertyListDatePickerCell : NSDatePickerCell
@interface NSDatePickerCell ()

- (BOOL)_textFieldWithStepperTrackMouse:(id)arg1 inRect:(NSRect)arg2 ofView:(id)arg3 untilMouseUp:(BOOL)arg4;

@end

@interface LNLeadingZerosDatePickerCell : NSDatePickerCell

@end

@interface LNPropertyListDatePickerCell : LNLeadingZerosDatePickerCell

@end
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
#import "LNPropertyListDatePickerCell.h"
#import <objc/runtime.h>

static thread_local BOOL __drawingDatePicker;
static NSDatePickerCell* __strong __drawingDatePickerCell;

@interface NSDatePickerCell ()

- (void)_setForcesLeadingZeroes:(BOOL)arg1;
- (NSColor*)_textColorBasedOnEnabledState;

@end

Expand All @@ -33,9 +34,9 @@ + (void)load

+ (NSBezierPath *)__ln_bezierPathWithRoundedRect:(NSRect)rect xRadius:(CGFloat)xRadius yRadius:(CGFloat)yRadius
{
if(__drawingDatePicker == YES)
if(__drawingDatePickerCell != nil)
{
[[NSColor.alternateSelectedControlColor highlightWithLevel:0.35] set];
// [[__drawingDatePickerCell._textColorBasedOnEnabledState blendedColorWithFraction:0.6 ofColor:NSColor.alternateSelectedControlColor] set];
}

NSBezierPath* rv = [self __ln_bezierPathWithRoundedRect:rect xRadius:xRadius yRadius:yRadius];
Expand All @@ -45,7 +46,7 @@ + (NSBezierPath *)__ln_bezierPathWithRoundedRect:(NSRect)rect xRadius:(CGFloat)x

@end

@implementation LNPropertyListDatePickerCell
@implementation LNLeadingZerosDatePickerCell

- (instancetype)init
{
Expand All @@ -59,18 +60,39 @@ - (instancetype)init
return self;
}

@end

@implementation LNPropertyListDatePickerCell

- (BOOL)_isFirstResponder
{
return self.controlView.window.firstResponder == self.controlView;
}

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
__drawingDatePicker = YES;
__drawingDatePickerCell = self;
if(self._isFirstResponder)
{
[NSColor.textBackgroundColor setFill];
[[NSBezierPath bezierPathWithRect:cellFrame] fill];
}

[super drawWithFrame:cellFrame inView:controlView];
__drawingDatePicker = NO;

__drawingDatePickerCell = nil;
}

//This is faster than setting the text color when the background color changes.
- (NSColor*)_textColorBasedOnEnabledState
{
return self.isEnabled ? self.backgroundStyle == NSBackgroundStyleEmphasized ? NSColor.alternateSelectedControlTextColor : NSColor.controlTextColor : self.backgroundStyle == NSBackgroundStyleEmphasized ? [NSColor valueForKey:@"_alternateDisabledSelectedControlTextColor"] : NSColor.disabledControlTextColor;

return self.isEnabled ? self.backgroundStyle == NSBackgroundStyleEmphasized ? self._isFirstResponder ? NSColor.controlTextColor : NSColor.alternateSelectedControlTextColor : NSColor.controlTextColor : self.backgroundStyle == NSBackgroundStyleEmphasized ? [NSColor valueForKey:@"_alternateDisabledSelectedControlTextColor"] : NSColor.disabledControlTextColor;
}

- (BOOL)_shouldShowFocusRingInView:(id)arg1
{
return YES;
}

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// LNPropertyListDatePickerPanel.h
// LNPropertyListEditor
//
// Created by Leo Natan (Wix) on 9/11/19.
// Copyright © 2019 Leo Natan. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNPropertyListDatePickerPanelBackgroundView : NSView

@property (nonatomic, weak) NSView* textDatePicker;
@property (nonatomic, weak) NSView* visualDatePicker;

@end

@class LNPropertyListDatePickerPanel;

@protocol LNPropertyListDatePickerPanelDelegate <NSObject>

- (void)propertyListDatePickerPanelDidClose:(LNPropertyListDatePickerPanel*)panel;

@end

@interface LNPropertyListDatePickerPanel : NSPanel

@property (nonatomic, weak) id<LNPropertyListDatePickerPanelDelegate> datePickerPanelDelegate;

@end
Loading

0 comments on commit 046172d

Please sign in to comment.