Skip to content

Instantly share code, notes, and snippets.

@classilla
Created July 28, 2018 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save classilla/9ca19fdc28d588bf54f3d730d16e2836 to your computer and use it in GitHub Desktop.
Save classilla/9ca19fdc28d588bf54f3d730d16e2836 to your computer and use it in GitHub Desktop.
A simple modal date panel using undocumented methods in Mac OS X Tiger.
#import <Cocoa/Cocoa.h>
// (C)2018 Cameron Kaiser. BSD license.
// gcc -o datepanel datepanel.m -framework Cocoa
// 10.4 does not have an accessory view method for NSAlert, but we can
// simulate it with these undocumented methods.
@interface NSAlert(WithCustomStyle)
- (void)prepare;
- (id)buildAlertStyle:(int)fp8 title:(id)fp12 formattedMsg:(id)fp16 first:(id)fp20 second:(id)fp24 third:(id)fp28 oldStyle:(BOOL)fp32;
- (id)buildAlertStyle:(int)fp8 title:(id)fp12 message:(id)fp16 first:(id)fp20 second:(id)fp24 third:(id)fp28 oldStyle:(BOOL)fp32 args:(char *)fp36;
@end
////// NSPopUpDatePicker
////// based on NSAlertCheckbox, http://cocoadev.github.io/NSAlertCheckbox/
@interface NSPopUpDatePicker : NSAlert {
NSDatePicker *_picker;
}
- (void)dealloc;
- (NSPopUpDatePicker *)datePicker:(NSString *)message
defaultButton:(NSString *)defaultButton
alternateButton:(NSString *)alternateButton
otherButton:(NSString *)otherButton
informativeTextWithFormat:(NSString *)format;
- (NSDate *)date;
- (void)setDate:(NSDate *)date;
@end
@interface NSPopUpDatePicker(Private)
- (void)_ensureDatePicker;
- (void)_addDatePickerToAlert;
@end
@implementation NSPopUpDatePicker
- (void)dealloc
{
// NSLog(@"dealloc");
[_picker release];
[super dealloc];
}
- (NSPopUpDatePicker *)datePicker:(NSString *)message
defaultButton:(NSString *)defaultButton
alternateButton:(NSString *)alternateButton
otherButton:(NSString *)otherButton
informativeTextWithFormat:(NSString *)format
{
NSAlert *alert = [super alertWithMessageText:message
defaultButton:defaultButton
alternateButton:alternateButton
otherButton:otherButton
informativeTextWithFormat:format];
return (NSPopUpDatePicker *)alert;
}
- (id)buildAlertStyle:(int)fp8
title:(id)fp12
formattedMsg:(id)fp16
first:(id)fp20
second:(id)fp24
third:(id)fp28
oldStyle:(BOOL)fp32
{
// NSLog(@"buildAlertStyle 1");
id rv = [super buildAlertStyle:fp8
title:fp12
formattedMsg:fp16
first:fp20
second:fp24
third:fp28
oldStyle:fp32];
[self _addDatePickerToAlert];
return rv;
}
- (id)buildAlertStyle:(int)fp8
title:(id)fp12
message:(id)fp16
first:(id)fp20
second:(id)fp24
third:(id)fp28
oldStyle:(BOOL)fp32
args:(char *)fp36
{
// NSLog(@"buildAlertStyle 2");
id rv = [super buildAlertStyle:fp8
title:fp12
message:fp16
first:fp20
second:fp24
third:fp28
oldStyle:fp32
args:fp36];
[self _addDatePickerToAlert];
return rv;
}
- (NSDate *)date
{
[self _ensureDatePicker];
return [_picker dateValue];
}
- (void)setDate:(NSDate *)date
{
[self _ensureDatePicker];
[_picker setDateValue:date];
}
@end
@implementation NSPopUpDatePicker(Private)
- (void)_ensureDatePicker
{
if (!_picker) {
// NSLog(@"picker init");
_picker = [[NSDatePicker alloc] initWithFrame:NSMakeRect(10,10,295,154)];
[_picker setDatePickerStyle:NSClockAndCalendarDatePickerStyle];
[_picker setDatePickerElements:NSYearMonthDayDatePickerElementFlag];
}
}
- (void)_addDatePickerToAlert
{
NSWindow *window = [self window];
NSView *content = [window contentView];
float padding = 14.0f;
NSArray *subviews = [content subviews];
NSEnumerator *en = [subviews objectEnumerator];
NSView *subview = nil;
NSTextField *messageText = nil;
int count = 0;
[self _ensureDatePicker];
// Find the main text field.
while (subview = [en nextObject]) {
if ([subview isKindOfClass:[NSTextField class]]) {
if (++count == 2)
messageText = (NSTextField *)subview;
}
}
if (messageText) {
[content addSubview:_picker];
[_picker sizeToFit];
// Expand the alert window.
NSRect windowFrame = [window frame];
NSRect pickerFrame = [_picker frame];
windowFrame.size.height += pickerFrame.size.height + padding;
[window setFrame:windowFrame display:YES];
// Insert the picker below the main text field.
pickerFrame.origin.y = [messageText frame].origin.y -
pickerFrame.size.height - padding;
pickerFrame.origin.x = [messageText frame].origin.x;
[_picker setFrame:pickerFrame];
//NSLog(@"Picker installed");
} else
NSLog(@"Couldn't find message text, did not add picker");
}
@end
////// App delegate runner
@interface AppDelegate : NSObject
- (id) init;
- (void) applicationWillFinishLaunching: (NSNotification*) aNotification;
- (void) applicationDidFinishLaunching: (NSNotification*) aNotification;
@end
@implementation AppDelegate
- (id) init
{
return [super init];
}
- (void) applicationWillFinishLaunching: (NSNotification*) aNotification
{
// NSLog(@"WillFinish");
}
- (void) applicationDidFinishLaunching: (NSNotification*) aNotification;
{
NSPopUpDatePicker *alert = [NSPopUpDatePicker
alertWithMessageText:@"One"
defaultButton:@"OK"
alternateButton:@"Cancel"
otherButton:nil
informativeTextWithFormat:@"Blah blah"];
[alert setDate:[NSDate date]];
int32_t result = [alert runModal];
NSDate *date = [alert date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[formatter setDateFormat:@"yyyy-MM-dd"];
NSString *stringFromDate = [formatter stringFromDate:date];
printf("%d %s\n", result, [stringFromDate UTF8String]);
[[NSApplication sharedApplication] terminate:nil];
}
@end
int main(int argc, char **argv) {
NSAutoreleasePool *shutup = [[NSAutoreleasePool alloc] init];
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *applicationDelegate = [[AppDelegate alloc] init];
[application setDelegate:applicationDelegate];
[application run];
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment