From bc140429358e06e4e6f20fce6c0abe5b4d69872c Mon Sep 17 00:00:00 2001 From: cody271 Date: Mon, 19 Feb 2018 22:39:44 -0800 Subject: [PATCH 01/15] Add uiDateTimePickerTime() APIs --- darwin/datetimepicker.m | 12 ++++ examples/CMakeLists.txt | 6 ++ examples/datetime/main.c | 132 +++++++++++++++++++++++++++++++++++++ ui.h | 4 ++ unix/datetimepicker.c | 12 ++++ windows/datetimepicker.cpp | 12 ++++ 6 files changed, 178 insertions(+) create mode 100644 examples/datetime/main.c diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 44364d9d..7a8bdd5b 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -40,3 +40,15 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(NSHourMinuteSecondDatePickerElementFlag); } + +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ +} diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8d83566e..4c049b9a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -23,6 +23,11 @@ _add_example(histogram ${_EXAMPLE_RESOURCES_RC} ) +_add_example(datetime + datetime/main.c + ${_EXAMPLE_RESOURCES_RC} +) + _add_example(cpp-multithread cpp-multithread/main.cpp ${_EXAMPLE_RESOURCES_RC} @@ -53,4 +58,5 @@ add_custom_target(examples histogram cpp-multithread drawtext + datetime timer) diff --git a/examples/datetime/main.c b/examples/datetime/main.c new file mode 100644 index 00000000..26c835b9 --- /dev/null +++ b/examples/datetime/main.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include "../../ui.h" + +uiDateTimePicker *dtboth, *dtdate, *dttime; + +const char * timeFormat(uiDateTimePicker *d) +{ + const char *fmt; + + if (d == dtboth) + fmt = "%c"; + else if (d == dtdate) + fmt = "%x"; + else if (d == dttime) + fmt = "%X"; + else + fmt = ""; + + return fmt; +} + +void onChanged(uiDateTimePicker *d, void *data) +{ + struct tm time; + char buf[64]; + + uiDateTimePickerTime(d, &time); + strftime(buf, sizeof(buf), timeFormat(d), &time); + uiLabelSetText(uiLabel(data), buf); +} + +void onClicked(uiButton *b, void *data) +{ + intptr_t now; + time_t t; + struct tm tmbuf; + + now = (intptr_t) data; + t = 0; + if (now) + t = time(NULL); + tmbuf = *localtime(&t); + + if (now) { + uiDateTimePickerSetTime(dtdate, &tmbuf); + uiDateTimePickerSetTime(dttime, &tmbuf); + } + else + uiDateTimePickerSetTime(dtboth, &tmbuf); +} + +int onClosing(uiWindow *w, void *data) +{ + uiQuit(); + return 1; +} + +int main(void) +{ + uiInitOptions o; + uiWindow *w; + uiGrid *g; + uiLabel *l; + uiButton *b; + + memset(&o, 0, sizeof (uiInitOptions)); + if (uiInit(&o) != NULL) + abort(); + + w = uiNewWindow("Date / Time", 320, 240, 0); + uiWindowSetMargined(w, 1); + + g = uiNewGrid(); + uiGridSetPadded(g, 1); + uiWindowSetChild(w, uiControl(g)); + + dtboth = uiNewDateTimePicker(); + dtdate = uiNewDatePicker(); + dttime = uiNewTimePicker(); + + uiGridAppend(g, uiControl(dtboth), + 0, 0, 2, 1, + 1, uiAlignFill, 0, uiAlignFill); + uiGridAppend(g, uiControl(dtdate), + 0, 1, 1, 1, + 1, uiAlignFill, 0, uiAlignFill); + uiGridAppend(g, uiControl(dttime), + 1, 1, 1, 1, + 1, uiAlignFill, 0, uiAlignFill); + + uiGridAppend(g, uiControl(uiNewVerticalSeparator()), + 0, 2, 2, 1, + 1, uiAlignFill, 0, uiAlignFill); + + l = uiNewLabel(""); + uiGridAppend(g, uiControl(l), + 0, 3, 2, 1, + 1, uiAlignCenter, 0, uiAlignFill); + uiDateTimePickerOnChanged(dtboth, onChanged, l); + l = uiNewLabel(""); + uiGridAppend(g, uiControl(l), + 0, 4, 1, 1, + 1, uiAlignCenter, 0, uiAlignFill); + uiDateTimePickerOnChanged(dtdate, onChanged, l); + l = uiNewLabel(""); + uiGridAppend(g, uiControl(l), + 1, 4, 1, 1, + 1, uiAlignCenter, 0, uiAlignFill); + uiDateTimePickerOnChanged(dttime, onChanged, l); + + uiGridAppend(g, uiControl(uiNewVerticalSeparator()), + 0, 5, 2, 1, + 1, uiAlignFill, 0, uiAlignFill); + + b = uiNewButton("Now"); + uiButtonOnClicked(b, onClicked, (void *) 1); + uiGridAppend(g, uiControl(b), + 0, 6, 1, 1, + 1, uiAlignFill, 0, uiAlignFill); + b = uiNewButton("Unix epoch"); + uiButtonOnClicked(b, onClicked, (void *) 0); + uiGridAppend(g, uiControl(b), + 1, 6, 1, 1, + 1, uiAlignFill, 0, uiAlignFill); + + uiWindowOnClosing(w, onClosing, NULL); + uiControlShow(uiControl(w)); + uiMain(); + return 0; +} diff --git a/ui.h b/ui.h index ce3e4104..765b7733 100644 --- a/ui.h +++ b/ui.h @@ -248,8 +248,12 @@ _UI_EXTERN void uiRadioButtonsSetSelected(uiRadioButtons *r, int n); _UI_EXTERN void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data); _UI_EXTERN uiRadioButtons *uiNewRadioButtons(void); +struct tm; typedef struct uiDateTimePicker uiDateTimePicker; #define uiDateTimePicker(this) ((uiDateTimePicker *) (this)) +_UI_EXTERN void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time); +_UI_EXTERN void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time); +_UI_EXTERN void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data); _UI_EXTERN uiDateTimePicker *uiNewDateTimePicker(void); _UI_EXTERN uiDateTimePicker *uiNewDatePicker(void); _UI_EXTERN uiDateTimePicker *uiNewTimePicker(void); diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 19689a22..c15a610d 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -597,3 +597,15 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(newTP); } + +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ +} diff --git a/windows/datetimepicker.cpp b/windows/datetimepicker.cpp index 6784fec2..40dfe7e9 100644 --- a/windows/datetimepicker.cpp +++ b/windows/datetimepicker.cpp @@ -189,3 +189,15 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(DTS_TIMEFORMAT); } + +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ +} From 3e9bdd26f113c0cc2a8ed6a8816c6f077f0d472f Mon Sep 17 00:00:00 2001 From: cody271 Date: Wed, 21 Feb 2018 21:26:43 -0800 Subject: [PATCH 02/15] Fix layout in datetime/main.c --- examples/datetime/main.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/examples/datetime/main.c b/examples/datetime/main.c index 26c835b9..a01dc889 100644 --- a/examples/datetime/main.c +++ b/examples/datetime/main.c @@ -90,40 +90,32 @@ int main(void) 1, 1, 1, 1, 1, uiAlignFill, 0, uiAlignFill); - uiGridAppend(g, uiControl(uiNewVerticalSeparator()), - 0, 2, 2, 1, - 1, uiAlignFill, 0, uiAlignFill); - l = uiNewLabel(""); uiGridAppend(g, uiControl(l), - 0, 3, 2, 1, + 0, 2, 2, 1, 1, uiAlignCenter, 0, uiAlignFill); uiDateTimePickerOnChanged(dtboth, onChanged, l); l = uiNewLabel(""); uiGridAppend(g, uiControl(l), - 0, 4, 1, 1, + 0, 3, 1, 1, 1, uiAlignCenter, 0, uiAlignFill); uiDateTimePickerOnChanged(dtdate, onChanged, l); l = uiNewLabel(""); uiGridAppend(g, uiControl(l), - 1, 4, 1, 1, + 1, 3, 1, 1, 1, uiAlignCenter, 0, uiAlignFill); uiDateTimePickerOnChanged(dttime, onChanged, l); - uiGridAppend(g, uiControl(uiNewVerticalSeparator()), - 0, 5, 2, 1, - 1, uiAlignFill, 0, uiAlignFill); - b = uiNewButton("Now"); uiButtonOnClicked(b, onClicked, (void *) 1); uiGridAppend(g, uiControl(b), - 0, 6, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); + 0, 4, 1, 1, + 1, uiAlignFill, 1, uiAlignEnd); b = uiNewButton("Unix epoch"); uiButtonOnClicked(b, onClicked, (void *) 0); uiGridAppend(g, uiControl(b), - 1, 6, 1, 1, - 1, uiAlignFill, 0, uiAlignFill); + 1, 4, 1, 1, + 1, uiAlignFill, 1, uiAlignEnd); uiWindowOnClosing(w, onClosing, NULL); uiControlShow(uiControl(w)); From 04ce39a9413a183278a9092d7768ab3c606b4fef Mon Sep 17 00:00:00 2001 From: cody271 Date: Wed, 21 Feb 2018 21:47:45 -0800 Subject: [PATCH 03/15] Implement uiDateTimePickerTime() for OS X --- darwin/datetimepicker.m | 101 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 7a8bdd5b..c7067af8 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -4,10 +4,82 @@ struct uiDateTimePicker { uiDarwinControl c; NSDatePicker *dp; + void (*onChanged)(uiDateTimePicker *, void *); + void *onChangedData; }; +@interface datePickerDelegateClass : NSObject { + struct mapTable *pickers; +} +- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell + validateProposedDateValue:(NSDate **)proposedDateValue + timeInterval:(NSTimeInterval *)proposedTimeInterval; +- (void)doTimer:(NSTimer *)timer; +- (void)registerPicker:(uiDateTimePicker *)b; +- (void)unregisterPicker:(uiDateTimePicker *)b; +@end + +@implementation datePickerDelegateClass + +- (id)init +{ + self = [super init]; + if (self) + self->pickers = newMap(); + return self; +} + +- (void)dealloc +{ + mapDestroy(self->pickers); + [super dealloc]; +} + +- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell + validateProposedDateValue:(NSDate **)proposedDateValue + timeInterval:(NSTimeInterval *)proposedTimeInterval +{ + uiDateTimePicker *d; + + d = (uiDateTimePicker *) mapGet(self->pickers, aDatePickerCell); + [NSTimer scheduledTimerWithTimeInterval:0 + target:self + selector:@selector(doTimer:) + userInfo:[NSValue valueWithPointer:d] + repeats:NO]; +} + +- (void)doTimer:(NSTimer *)timer +{ + uiDateTimePicker *d; + + d = (uiDateTimePicker*) [[timer userInfo] pointerValue]; + (*(d->onChanged))(d, d->onChangedData); +} + +- (void)registerPicker:(uiDateTimePicker *)d +{ + mapSet(self->pickers, d->dp.cell, d); + [d->dp setDelegate:self]; +} + +- (void)unregisterPicker:(uiDateTimePicker *)d +{ + [d->dp setDelegate:nil]; + mapDelete(self->pickers, d->dp.cell); +} + +@end + +static datePickerDelegateClass *datePickerDelegate = nil; + uiDarwinControlAllDefaults(uiDateTimePicker, dp) +static void defaultOnChanged(uiDateTimePicker *d, void *data) +{ + // do nothing +} + static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elements) { uiDateTimePicker *d; @@ -15,6 +87,7 @@ static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elemen uiDarwinNewControl(uiDateTimePicker, d); d->dp = [[NSDatePicker alloc] initWithFrame:NSZeroRect]; + [d->dp setDateValue:[NSDate date]]; [d->dp setBordered:NO]; [d->dp setBezeled:YES]; [d->dp setDrawsBackground:YES]; @@ -23,6 +96,13 @@ static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elemen [d->dp setDatePickerMode:NSSingleDateMode]; uiDarwinSetControlFont(d->dp, NSRegularControlSize); + if (datePickerDelegate == nil) { + datePickerDelegate = [[datePickerDelegateClass new] autorelease]; + [delegates addObject:datePickerDelegate]; + } + [datePickerDelegate registerPicker:d]; + uiDateTimePickerOnChanged(d, defaultOnChanged, NULL); + return d; } @@ -43,12 +123,33 @@ uiDateTimePicker *uiNewTimePicker(void) void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) { + time_t t; + struct tm tmbuf; + NSDate *date; + NSTimeInterval interval; + + date = [d->dp dateValue]; + interval = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:date]; + date = [date dateByAddingTimeInterval:interval]; + t = (time_t) [date timeIntervalSince1970]; + + tmbuf = *gmtime(&t); + memcpy(time, &tmbuf, sizeof(struct tm)); } void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) { + time_t t; + struct tm tmbuf; + + memcpy(&tmbuf, time, sizeof(struct tm)); + t = mktime(&tmbuf); + + [d->dp setDateValue:[NSDate dateWithTimeIntervalSince1970:t]]; } void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) { + d->onChanged = f; + d->onChangedData = data; } From 57b225a629b828156c2777513abac7c66461e1e3 Mon Sep 17 00:00:00 2001 From: cody271 Date: Wed, 21 Feb 2018 22:06:21 -0800 Subject: [PATCH 04/15] Implement uiDateTimePickerTime() for GTK+ --- unix/datetimepicker.c | 98 ++++++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index c15a610d..3e7b47c8 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -38,6 +38,7 @@ struct dateTimePickerWidget { GdkDevice *keyboard; GdkDevice *mouse; + uiDateTimePicker *control; }; struct dateTimePickerWidgetClass { @@ -46,6 +47,16 @@ struct dateTimePickerWidgetClass { G_DEFINE_TYPE(dateTimePickerWidget, dateTimePickerWidget, GTK_TYPE_TOGGLE_BUTTON) +struct uiDateTimePicker { + uiUnixControl c; + GtkWidget *widget; + dateTimePickerWidget *d; + void (*onChanged)(uiDateTimePicker *, void *); + void *onChangedData; +}; + +uiUnixControlAllDefaults(uiDateTimePicker) + static int realSpinValue(GtkSpinButton *spinButton) { GtkAdjustment *adj; @@ -111,8 +122,11 @@ static void setLabel(dateTimePickerWidget *d) static void dateTimeChanged(dateTimePickerWidget *d) { + uiDateTimePicker *c; + + c = d->control; + (*(c->onChanged))(c, c->onChangedData); setLabel(d); - // TODO fire event here } // we don't want ::toggled to be sent again @@ -422,13 +436,37 @@ static void setTimeOnly(dateTimePickerWidget *d) gtk_container_remove(GTK_CONTAINER(d->box), d->calendar); } -static void dateTimePickerWidget_init(dateTimePickerWidget *d) +static void dateTimePickerWidget_setTime(dateTimePickerWidget *d, GDateTime *dt) { - GDateTime *dt; gint year, month, day; gint hour; gulong calendarBlock; + // notice how we block signals from firing + if (d->hasDate) { + calendarBlock = g_signal_connect(d->calendar, "day-selected", G_CALLBACK(dateChanged), d); + g_date_time_get_ymd(dt, &year, &month, &day); + month--; // GDateTime/GtkCalendar differences + g_signal_handler_block(d->calendar, calendarBlock); + gtk_calendar_select_month(GTK_CALENDAR(d->calendar), month, year); + gtk_calendar_select_day(GTK_CALENDAR(d->calendar), day); + g_signal_handler_unblock(d->calendar, calendarBlock); + } + if (d->hasTime) { + hour = g_date_time_get_hour(dt); + if (hour >= 12) { + hour -= 12; + setRealSpinValue(GTK_SPIN_BUTTON(d->ampm), 1, d->ampmBlock); + } + setRealSpinValue(GTK_SPIN_BUTTON(d->hours), hour, d->hoursBlock); + setRealSpinValue(GTK_SPIN_BUTTON(d->minutes), g_date_time_get_minute(dt), d->minutesBlock); + setRealSpinValue(GTK_SPIN_BUTTON(d->seconds), g_date_time_get_seconds(dt), d->secondsBlock); + } + g_date_time_unref(dt); +} + +static void dateTimePickerWidget_init(dateTimePickerWidget *d) +{ d->window = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_resizable(GTK_WINDOW(d->window), FALSE); gtk_window_set_attached_to(GTK_WINDOW(d->window), GTK_WIDGET(d)); @@ -446,7 +484,6 @@ static void dateTimePickerWidget_init(dateTimePickerWidget *d) gtk_container_add(GTK_CONTAINER(d->window), d->box); d->calendar = gtk_calendar_new(); - calendarBlock = g_signal_connect(d->calendar, "day-selected", G_CALLBACK(dateChanged), d); gtk_container_add(GTK_CONTAINER(d->box), d->calendar); d->timebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); @@ -493,23 +530,7 @@ static void dateTimePickerWidget_init(dateTimePickerWidget *d) d->hasDate = TRUE; // set the current date/time - // notice how we block signals from firing - dt = g_date_time_new_now_local(); - g_date_time_get_ymd(dt, &year, &month, &day); - month--; // GDateTime/GtkCalendar differences - g_signal_handler_block(d->calendar, calendarBlock); - gtk_calendar_select_month(GTK_CALENDAR(d->calendar), month, year); - gtk_calendar_select_day(GTK_CALENDAR(d->calendar), day); - g_signal_handler_unblock(d->calendar, calendarBlock); - hour = g_date_time_get_hour(dt); - if (hour >= 12) { - hour -= 12; - setRealSpinValue(GTK_SPIN_BUTTON(d->ampm), 1, d->ampmBlock); - } - setRealSpinValue(GTK_SPIN_BUTTON(d->hours), hour, d->hoursBlock); - setRealSpinValue(GTK_SPIN_BUTTON(d->minutes), g_date_time_get_minute(dt), d->minutesBlock); - setRealSpinValue(GTK_SPIN_BUTTON(d->seconds), g_date_time_get_seconds(dt), d->secondsBlock); - g_date_time_unref(dt); + dateTimePickerWidget_setTime(d, g_date_time_new_now_local()); } static void dateTimePickerWidget_dispose(GObject *obj) @@ -534,6 +555,11 @@ static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) G_OBJECT_CLASS(class)->finalize = dateTimePickerWidget_finalize; } +static void defaultOnChanged(uiDateTimePicker *d, void *data) +{ + // do nothing +} + static GtkWidget *newDTP(void) { GtkWidget *w; @@ -563,14 +589,6 @@ static GtkWidget *newTP(void) return w; } -struct uiDateTimePicker { - uiUnixControl c; - GtkWidget *widget; - dateTimePickerWidget *d; -}; - -uiUnixControlAllDefaults(uiDateTimePicker) - uiDateTimePicker *finishNewDateTimePicker(GtkWidget *(*fn)(void)) { uiDateTimePicker *d; @@ -579,6 +597,8 @@ uiDateTimePicker *finishNewDateTimePicker(GtkWidget *(*fn)(void)) d->widget = (*fn)(); d->d = dateTimePickerWidget(d->widget); + d->d->control = d; + uiDateTimePickerOnChanged(d, defaultOnChanged, NULL); return d; } @@ -600,12 +620,32 @@ uiDateTimePicker *uiNewTimePicker(void) void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) { + time_t t; + struct tm tmbuf; + GDateTime *dt; + + dt = selected(d->d); + t = g_date_time_to_unix(dt); + g_date_time_unref(dt); + + tmbuf = *localtime(&t); + memcpy(time, &tmbuf, sizeof(struct tm)); } void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) { + time_t t; + struct tm tmbuf; + + memcpy(&tmbuf, time, sizeof(struct tm)); + t = mktime(&tmbuf); + + dateTimePickerWidget_setTime(d->d, g_date_time_new_from_unix_local(t)); + dateTimeChanged(d->d); } void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) { + d->onChanged = f; + d->onChangedData = data; } From cf671c1da5ecf6f2dfabbaf5bfb4c4a72dec2e7a Mon Sep 17 00:00:00 2001 From: cody271 Date: Thu, 22 Feb 2018 18:36:37 -0800 Subject: [PATCH 05/15] uiDateTimePicker Fix NSDatePicker timezone handling --- darwin/datetimepicker.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index c7067af8..54c53b4b 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -126,14 +126,11 @@ void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) time_t t; struct tm tmbuf; NSDate *date; - NSTimeInterval interval; date = [d->dp dateValue]; - interval = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:date]; - date = [date dateByAddingTimeInterval:interval]; t = (time_t) [date timeIntervalSince1970]; - tmbuf = *gmtime(&t); + tmbuf = *localtime(&t); memcpy(time, &tmbuf, sizeof(struct tm)); } From 0baf2d2eb6d54057da8d5cb629fe18cd30fa2f0b Mon Sep 17 00:00:00 2001 From: cody271 Date: Thu, 22 Feb 2018 19:20:16 -0800 Subject: [PATCH 06/15] uiDateTimePicker Keep libui constructors at the end of the file --- darwin/datetimepicker.m | 60 +++++++++++++++++------------------ unix/datetimepicker.c | 64 +++++++++++++++++++------------------- windows/datetimepicker.cpp | 24 +++++++------- 3 files changed, 74 insertions(+), 74 deletions(-) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 54c53b4b..87ab0c3c 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -80,6 +80,36 @@ static void defaultOnChanged(uiDateTimePicker *d, void *data) // do nothing } +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ + time_t t; + struct tm tmbuf; + NSDate *date; + + date = [d->dp dateValue]; + t = (time_t) [date timeIntervalSince1970]; + + tmbuf = *localtime(&t); + memcpy(time, &tmbuf, sizeof(struct tm)); +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ + time_t t; + struct tm tmbuf; + + memcpy(&tmbuf, time, sizeof(struct tm)); + t = mktime(&tmbuf); + + [d->dp setDateValue:[NSDate dateWithTimeIntervalSince1970:t]]; +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ + d->onChanged = f; + d->onChangedData = data; +} + static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elements) { uiDateTimePicker *d; @@ -120,33 +150,3 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(NSHourMinuteSecondDatePickerElementFlag); } - -void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) -{ - time_t t; - struct tm tmbuf; - NSDate *date; - - date = [d->dp dateValue]; - t = (time_t) [date timeIntervalSince1970]; - - tmbuf = *localtime(&t); - memcpy(time, &tmbuf, sizeof(struct tm)); -} - -void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) -{ - time_t t; - struct tm tmbuf; - - memcpy(&tmbuf, time, sizeof(struct tm)); - t = mktime(&tmbuf); - - [d->dp setDateValue:[NSDate dateWithTimeIntervalSince1970:t]]; -} - -void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) -{ - d->onChanged = f; - d->onChangedData = data; -} diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 3e7b47c8..2fa9f956 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -560,6 +560,38 @@ static void defaultOnChanged(uiDateTimePicker *d, void *data) // do nothing } +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ + time_t t; + struct tm tmbuf; + GDateTime *dt; + + dt = selected(d->d); + t = g_date_time_to_unix(dt); + g_date_time_unref(dt); + + tmbuf = *localtime(&t); + memcpy(time, &tmbuf, sizeof(struct tm)); +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ + time_t t; + struct tm tmbuf; + + memcpy(&tmbuf, time, sizeof(struct tm)); + t = mktime(&tmbuf); + + dateTimePickerWidget_setTime(d->d, g_date_time_new_from_unix_local(t)); + dateTimeChanged(d->d); +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ + d->onChanged = f; + d->onChangedData = data; +} + static GtkWidget *newDTP(void) { GtkWidget *w; @@ -617,35 +649,3 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(newTP); } - -void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) -{ - time_t t; - struct tm tmbuf; - GDateTime *dt; - - dt = selected(d->d); - t = g_date_time_to_unix(dt); - g_date_time_unref(dt); - - tmbuf = *localtime(&t); - memcpy(time, &tmbuf, sizeof(struct tm)); -} - -void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) -{ - time_t t; - struct tm tmbuf; - - memcpy(&tmbuf, time, sizeof(struct tm)); - t = mktime(&tmbuf); - - dateTimePickerWidget_setTime(d->d, g_date_time_new_from_unix_local(t)); - dateTimeChanged(d->d); -} - -void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) -{ - d->onChanged = f; - d->onChangedData = data; -} diff --git a/windows/datetimepicker.cpp b/windows/datetimepicker.cpp index 40dfe7e9..7d8bea39 100644 --- a/windows/datetimepicker.cpp +++ b/windows/datetimepicker.cpp @@ -168,6 +168,18 @@ static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wPara return DefSubclassProc(hwnd, uMsg, wParam, lParam); } +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) +{ +} + uiDateTimePicker *uiNewDateTimePicker(void) { uiDateTimePicker *d; @@ -189,15 +201,3 @@ uiDateTimePicker *uiNewTimePicker(void) { return finishNewDateTimePicker(DTS_TIMEFORMAT); } - -void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) -{ -} - -void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) -{ -} - -void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) -{ -} From 5ec5ebdfae872a7b0b12c0e1ffbd5fc9dd46dc95 Mon Sep 17 00:00:00 2001 From: cody271 Date: Thu, 22 Feb 2018 19:56:57 -0800 Subject: [PATCH 07/15] uiDateTimePicker Emit proper GTK+ signal in dateTimePickerWidget --- unix/datetimepicker.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 2fa9f956..0c0dba8a 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -38,7 +38,6 @@ struct dateTimePickerWidget { GdkDevice *keyboard; GdkDevice *mouse; - uiDateTimePicker *control; }; struct dateTimePickerWidgetClass { @@ -120,12 +119,11 @@ static void setLabel(dateTimePickerWidget *d) g_date_time_unref(dt); } +static int changedSignal; + static void dateTimeChanged(dateTimePickerWidget *d) { - uiDateTimePicker *c; - - c = d->control; - (*(c->onChanged))(c, c->onChangedData); + g_signal_emit(d, changedSignal, 0); setLabel(d); } @@ -553,6 +551,13 @@ static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) { G_OBJECT_CLASS(class)->dispose = dateTimePickerWidget_dispose; G_OBJECT_CLASS(class)->finalize = dateTimePickerWidget_finalize; + + changedSignal = g_signal_new("changed", + G_TYPE_FROM_CLASS(class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); } static void defaultOnChanged(uiDateTimePicker *d, void *data) @@ -592,6 +597,14 @@ void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker * d->onChangedData = data; } +static void onChanged(dateTimePickerWidget *d, gpointer data) +{ + uiDateTimePicker *c; + + c = uiDateTimePicker(data); + (*(c->onChanged))(c, c->onChangedData); +} + static GtkWidget *newDTP(void) { GtkWidget *w; @@ -629,7 +642,7 @@ uiDateTimePicker *finishNewDateTimePicker(GtkWidget *(*fn)(void)) d->widget = (*fn)(); d->d = dateTimePickerWidget(d->widget); - d->d->control = d; + g_signal_connect(d->widget, "changed", G_CALLBACK(onChanged), d); uiDateTimePickerOnChanged(d, defaultOnChanged, NULL); return d; From 594e3a1ccc4c100bb4c6742e3266d29d365f7dda Mon Sep 17 00:00:00 2001 From: cody271 Date: Thu, 22 Feb 2018 20:13:55 -0800 Subject: [PATCH 08/15] uiDateTimePicker Move struct definition back --- unix/datetimepicker.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 0c0dba8a..94fa6b9a 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -46,16 +46,6 @@ struct dateTimePickerWidgetClass { G_DEFINE_TYPE(dateTimePickerWidget, dateTimePickerWidget, GTK_TYPE_TOGGLE_BUTTON) -struct uiDateTimePicker { - uiUnixControl c; - GtkWidget *widget; - dateTimePickerWidget *d; - void (*onChanged)(uiDateTimePicker *, void *); - void *onChangedData; -}; - -uiUnixControlAllDefaults(uiDateTimePicker) - static int realSpinValue(GtkSpinButton *spinButton) { GtkAdjustment *adj; @@ -560,6 +550,16 @@ static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) G_TYPE_NONE, 0); } +struct uiDateTimePicker { + uiUnixControl c; + GtkWidget *widget; + dateTimePickerWidget *d; + void (*onChanged)(uiDateTimePicker *, void *); + void *onChangedData; +}; + +uiUnixControlAllDefaults(uiDateTimePicker) + static void defaultOnChanged(uiDateTimePicker *d, void *data) { // do nothing From 0ac4ffdc87ab3d5e40467ecfd1246171c87cbc01 Mon Sep 17 00:00:00 2001 From: cody271 Date: Fri, 23 Feb 2018 16:02:39 -0800 Subject: [PATCH 09/15] Implement uiDateTimePickerTime() for Windows --- windows/datetimepicker.cpp | 83 ++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/windows/datetimepicker.cpp b/windows/datetimepicker.cpp index 7d8bea39..2ea366c2 100644 --- a/windows/datetimepicker.cpp +++ b/windows/datetimepicker.cpp @@ -4,6 +4,8 @@ struct uiDateTimePicker { uiWindowsControl c; HWND hwnd; + void(*onChanged)(uiDateTimePicker *, void *); + void *onChangedData; }; // utility functions @@ -103,6 +105,7 @@ static void uiDateTimePickerDestroy(uiControl *c) uiDateTimePicker *d = uiDateTimePicker(c); uiWindowsUnregisterReceiveWM_WININICHANGE(d->hwnd); + uiWindowsUnregisterWM_NOTIFYHandler(d->hwnd); uiWindowsEnsureDestroyWindow(d->hwnd); uiFreeControl(uiControl(d)); } @@ -131,6 +134,72 @@ static void uiDateTimePickerMinimumSize(uiWindowsControl *c, int *width, int *he *height = y; } +static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult) +{ + uiDateTimePicker *d = uiDateTimePicker(c); + + if (nmhdr->code != DTN_DATETIMECHANGE) + return FALSE; + (*(d->onChanged))(d, d->onChangedData); + *lResult = 0; + return TRUE; +} + +static void fromSystemTime(LPSYSTEMTIME systime, struct tm *time) +{ + memset(time, 0, sizeof(struct tm)); + time->tm_sec = systime->wSecond; + time->tm_min = systime->wMinute; + time->tm_hour = systime->wHour; + time->tm_mday = systime->wDay; + time->tm_mon = systime->wMonth - 1; + time->tm_year = systime->wYear - 1900; + time->tm_wday = systime->wDayOfWeek; + time->tm_isdst = -1; +} + +static void toSystemTime(const struct tm *time, LPSYSTEMTIME systime) +{ + memset(systime, 0, sizeof(SYSTEMTIME)); + systime->wYear = time->tm_year + 1900; + systime->wMonth = time->tm_mon + 1; + systime->wDayOfWeek = time->tm_wday; + systime->wDay = time->tm_mday; + systime->wHour = time->tm_hour; + systime->wMinute = time->tm_min; + systime->wSecond = time->tm_sec; +} + +static void defaultOnChanged(uiDateTimePicker *d, void *data) +{ + // do nothing +} + +void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) +{ + SYSTEMTIME systime; + + if (DateTime_GetSystemtime(d->hwnd, &systime) != GDT_VALID) + implbug("DTM_GETSYSTEMTIME message failed"); + fromSystemTime(&systime, time); +} + +void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) +{ + SYSTEMTIME systime; + + toSystemTime(time, &systime); + if (!DateTime_SetSystemtime(d->hwnd, GDT_VALID, &systime)) + implbug("DTM_SETSYSTEMTIME message failed"); + (*(d->onChanged))(d, d->onChangedData); +} + +void uiDateTimePickerOnChanged(uiDateTimePicker *d, void(*f)(uiDateTimePicker *, void *), void *data) +{ + d->onChanged = f; + d->onChangedData = data; +} + static uiDateTimePicker *finishNewDateTimePicker(DWORD style) { uiDateTimePicker *d; @@ -147,6 +216,8 @@ static uiDateTimePicker *finishNewDateTimePicker(DWORD style) // for the standard styles, this is in the date-time picker itself // for our date/time mode, we do it in a subclass assigned in uiNewDateTimePicker() uiWindowsRegisterReceiveWM_WININICHANGE(d->hwnd); + uiWindowsRegisterWM_NOTIFYHandler(d->hwnd, onWM_NOTIFY, uiControl(d)); + uiDateTimePickerOnChanged(d, defaultOnChanged, NULL); return d; } @@ -168,18 +239,6 @@ static LRESULT CALLBACK datetimepickerSubProc(HWND hwnd, UINT uMsg, WPARAM wPara return DefSubclassProc(hwnd, uMsg, wParam, lParam); } -void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) -{ -} - -void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) -{ -} - -void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data) -{ -} - uiDateTimePicker *uiNewDateTimePicker(void) { uiDateTimePicker *d; From 0b436a8c7432d3c71feb46d35799654a0fbe69d0 Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 24 Feb 2018 15:27:02 -0800 Subject: [PATCH 10/15] uiDateTimePicker Use proper Windows backend conventions --- windows/datetimepicker.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/windows/datetimepicker.cpp b/windows/datetimepicker.cpp index 2ea366c2..fc94c3e9 100644 --- a/windows/datetimepicker.cpp +++ b/windows/datetimepicker.cpp @@ -147,7 +147,7 @@ static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult) static void fromSystemTime(LPSYSTEMTIME systime, struct tm *time) { - memset(time, 0, sizeof(struct tm)); + ZeroMemory(time, sizeof(struct tm)); time->tm_sec = systime->wSecond; time->tm_min = systime->wMinute; time->tm_hour = systime->wHour; @@ -160,7 +160,7 @@ static void fromSystemTime(LPSYSTEMTIME systime, struct tm *time) static void toSystemTime(const struct tm *time, LPSYSTEMTIME systime) { - memset(systime, 0, sizeof(SYSTEMTIME)); + ZeroMemory(systime, sizeof(SYSTEMTIME)); systime->wYear = time->tm_year + 1900; systime->wMonth = time->tm_mon + 1; systime->wDayOfWeek = time->tm_wday; @@ -179,8 +179,8 @@ void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) { SYSTEMTIME systime; - if (DateTime_GetSystemtime(d->hwnd, &systime) != GDT_VALID) - implbug("DTM_GETSYSTEMTIME message failed"); + if (SendMessageW(d->hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM) &systime) != GDT_VALID) + logLastError(L"error getting date and time"); fromSystemTime(&systime, time); } @@ -189,8 +189,8 @@ void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) SYSTEMTIME systime; toSystemTime(time, &systime); - if (!DateTime_SetSystemtime(d->hwnd, GDT_VALID, &systime)) - implbug("DTM_SETSYSTEMTIME message failed"); + if (!SendMessageW(d->hwnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM) &systime)) + logLastError(L"error setting date and time"); (*(d->onChanged))(d, d->onChangedData); } From edd4127f8e14ffd4075d319ee77f571ddadd70f7 Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 5 May 2018 21:21:25 -0700 Subject: [PATCH 11/15] uiDateTimePicker Fix style consistency --- darwin/datetimepicker.m | 6 ++---- examples/datetime/main.c | 7 +++---- unix/datetimepicker.c | 3 ++- windows/datetimepicker.cpp | 12 ++++++------ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 87ab0c3c..7e9d6c6b 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -11,9 +11,7 @@ struct uiDateTimePicker { @interface datePickerDelegateClass : NSObject { struct mapTable *pickers; } -- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell - validateProposedDateValue:(NSDate **)proposedDateValue - timeInterval:(NSTimeInterval *)proposedTimeInterval; +- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell validateProposedDateValue:(NSDate **)proposedDateValue timeInterval:(NSTimeInterval *)proposedTimeInterval; - (void)doTimer:(NSTimer *)timer; - (void)registerPicker:(uiDateTimePicker *)b; - (void)unregisterPicker:(uiDateTimePicker *)b; @@ -53,7 +51,7 @@ struct uiDateTimePicker { { uiDateTimePicker *d; - d = (uiDateTimePicker*) [[timer userInfo] pointerValue]; + d = (uiDateTimePicker *) [((NSValue *)[timer userInfo]) pointerValue]; (*(d->onChanged))(d, d->onChangedData); } diff --git a/examples/datetime/main.c b/examples/datetime/main.c index a01dc889..e71b54a6 100644 --- a/examples/datetime/main.c +++ b/examples/datetime/main.c @@ -5,7 +5,7 @@ uiDateTimePicker *dtboth, *dtdate, *dttime; -const char * timeFormat(uiDateTimePicker *d) +const char *timeFormat(uiDateTimePicker *d) { const char *fmt; @@ -27,7 +27,7 @@ void onChanged(uiDateTimePicker *d, void *data) char buf[64]; uiDateTimePickerTime(d, &time); - strftime(buf, sizeof(buf), timeFormat(d), &time); + strftime(buf, sizeof (buf), timeFormat(d), &time); uiLabelSetText(uiLabel(data), buf); } @@ -46,8 +46,7 @@ void onClicked(uiButton *b, void *data) if (now) { uiDateTimePickerSetTime(dtdate, &tmbuf); uiDateTimePickerSetTime(dttime, &tmbuf); - } - else + } else uiDateTimePickerSetTime(dtboth, &tmbuf); } diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 94fa6b9a..c4c9decb 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -547,7 +547,8 @@ static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); + G_TYPE_NONE, + 0); } struct uiDateTimePicker { diff --git a/windows/datetimepicker.cpp b/windows/datetimepicker.cpp index fc94c3e9..26841dae 100644 --- a/windows/datetimepicker.cpp +++ b/windows/datetimepicker.cpp @@ -145,9 +145,9 @@ static BOOL onWM_NOTIFY(uiControl *c, HWND hwnd, NMHDR *nmhdr, LRESULT *lResult) return TRUE; } -static void fromSystemTime(LPSYSTEMTIME systime, struct tm *time) +static void fromSystemTime(SYSTEMTIME *systime, struct tm *time) { - ZeroMemory(time, sizeof(struct tm)); + ZeroMemory(time, sizeof (struct tm)); time->tm_sec = systime->wSecond; time->tm_min = systime->wMinute; time->tm_hour = systime->wHour; @@ -158,9 +158,9 @@ static void fromSystemTime(LPSYSTEMTIME systime, struct tm *time) time->tm_isdst = -1; } -static void toSystemTime(const struct tm *time, LPSYSTEMTIME systime) +static void toSystemTime(const struct tm *time, SYSTEMTIME *systime) { - ZeroMemory(systime, sizeof(SYSTEMTIME)); + ZeroMemory(systime, sizeof (SYSTEMTIME)); systime->wYear = time->tm_year + 1900; systime->wMonth = time->tm_mon + 1; systime->wDayOfWeek = time->tm_wday; @@ -179,7 +179,7 @@ void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) { SYSTEMTIME systime; - if (SendMessageW(d->hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM) &systime) != GDT_VALID) + if (SendMessageW(d->hwnd, DTM_GETSYSTEMTIME, 0, (LPARAM) (&systime)) != GDT_VALID) logLastError(L"error getting date and time"); fromSystemTime(&systime, time); } @@ -189,7 +189,7 @@ void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) SYSTEMTIME systime; toSystemTime(time, &systime); - if (!SendMessageW(d->hwnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM) &systime)) + if (SendMessageW(d->hwnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM) (&systime)) == 0) logLastError(L"error setting date and time"); (*(d->onChanged))(d, d->onChangedData); } From f3d0fee21a37eac29e880fc32dbec6cdf4deab83 Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 5 May 2018 21:28:19 -0700 Subject: [PATCH 12/15] uiDateTimePicker Use 'uipriv' convention --- darwin/datetimepicker.m | 8 ++-- unix/datetimepicker.c | 102 ++++++++++++++++++++-------------------- 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 7e9d6c6b..fadf94ca 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -8,7 +8,7 @@ struct uiDateTimePicker { void *onChangedData; }; -@interface datePickerDelegateClass : NSObject { +@interface uiprivDatePickerDelegateClass : NSObject { struct mapTable *pickers; } - (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell validateProposedDateValue:(NSDate **)proposedDateValue timeInterval:(NSTimeInterval *)proposedTimeInterval; @@ -17,7 +17,7 @@ struct uiDateTimePicker { - (void)unregisterPicker:(uiDateTimePicker *)b; @end -@implementation datePickerDelegateClass +@implementation uiprivDatePickerDelegateClass - (id)init { @@ -69,7 +69,7 @@ struct uiDateTimePicker { @end -static datePickerDelegateClass *datePickerDelegate = nil; +static uiprivDatePickerDelegateClass *datePickerDelegate = nil; uiDarwinControlAllDefaults(uiDateTimePicker, dp) @@ -125,7 +125,7 @@ static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elemen uiDarwinSetControlFont(d->dp, NSRegularControlSize); if (datePickerDelegate == nil) { - datePickerDelegate = [[datePickerDelegateClass new] autorelease]; + datePickerDelegate = [[uiprivDatePickerDelegateClass new] autorelease]; [delegates addObject:datePickerDelegate]; } [datePickerDelegate registerPicker:d]; diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index c4c9decb..46ea19e8 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -4,17 +4,17 @@ // LONGTERM imitate gnome-calendar's day/month/year entries above the calendar // LONGTERM allow entering a 24-hour hour in the hour spinbutton and adjust accordingly -#define dateTimePickerWidgetType (dateTimePickerWidget_get_type()) -#define dateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), dateTimePickerWidgetType, dateTimePickerWidget)) -#define isDateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), dateTimePickerWidgetType)) -#define dateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_CAST((class), dateTimePickerWidgetType, dateTimePickerWidgetClass)) -#define isDateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), dateTimePickerWidget)) -#define getDateTimePickerWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), dateTimePickerWidgetType, dateTimePickerWidgetClass)) +#define uiprivDateTimePickerWidgetType (uiprivDateTimePickerWidget_get_type()) +#define uiprivDateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), uiprivDateTimePickerWidgetType, uiprivDateTimePickerWidget)) +#define isDateTimePickerWidget(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), uiprivDateTimePickerWidgetType)) +#define uiprivDateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_CAST((class), uiprivDateTimePickerWidgetType, uiprivDateTimePickerWidgetClass)) +#define isDateTimePickerWidgetClass(class) (G_TYPE_CHECK_CLASS_TYPE((class), uiprivDateTimePickerWidget)) +#define getDateTimePickerWidgetClass(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), uiprivDateTimePickerWidgetType, uiprivDateTimePickerWidgetClass)) -typedef struct dateTimePickerWidget dateTimePickerWidget; -typedef struct dateTimePickerWidgetClass dateTimePickerWidgetClass; +typedef struct uiprivDateTimePickerWidget uiprivDateTimePickerWidget; +typedef struct uiprivDateTimePickerWidgetClass uiprivDateTimePickerWidgetClass; -struct dateTimePickerWidget { +struct uiprivDateTimePickerWidget { GtkToggleButton parent_instance; gulong toggledSignal; @@ -40,11 +40,11 @@ struct dateTimePickerWidget { GdkDevice *mouse; }; -struct dateTimePickerWidgetClass { +struct uiprivDateTimePickerWidgetClass { GtkToggleButtonClass parent_class; }; -G_DEFINE_TYPE(dateTimePickerWidget, dateTimePickerWidget, GTK_TYPE_TOGGLE_BUTTON) +G_DEFINE_TYPE(uiprivDateTimePickerWidget, uiprivDateTimePickerWidget, GTK_TYPE_TOGGLE_BUTTON) static int realSpinValue(GtkSpinButton *spinButton) { @@ -64,7 +64,7 @@ static void setRealSpinValue(GtkSpinButton *spinButton, int value, gulong block) g_signal_handler_unblock(spinButton, block); } -static GDateTime *selected(dateTimePickerWidget *d) +static GDateTime *selected(uiprivDateTimePickerWidget *d) { // choose a day for which all times are likely to be valid for the default date in case we're only dealing with time guint year = 1970, month = 1, day = 1; @@ -84,7 +84,7 @@ static GDateTime *selected(dateTimePickerWidget *d) return g_date_time_new_local(year, month, day, hour, minute, second); } -static void setLabel(dateTimePickerWidget *d) +static void setLabel(uiprivDateTimePickerWidget *d) { GDateTime *dt; char *fmt; @@ -111,14 +111,14 @@ static void setLabel(dateTimePickerWidget *d) static int changedSignal; -static void dateTimeChanged(dateTimePickerWidget *d) +static void dateTimeChanged(uiprivDateTimePickerWidget *d) { g_signal_emit(d, changedSignal, 0); setLabel(d); } // we don't want ::toggled to be sent again -static void setActive(dateTimePickerWidget *d, gboolean active) +static void setActive(uiprivDateTimePickerWidget *d, gboolean active) { g_signal_handler_block(d, d->toggledSignal); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d), active); @@ -126,7 +126,7 @@ static void setActive(dateTimePickerWidget *d, gboolean active) } // like startGrab() below, a lot of this is in the order that GtkComboBox does it -static void endGrab(dateTimePickerWidget *d) +static void endGrab(uiprivDateTimePickerWidget *d) { if (d->keyboard != NULL) gdk_device_ungrab(d->keyboard, GDK_CURRENT_TIME); @@ -136,7 +136,7 @@ static void endGrab(dateTimePickerWidget *d) d->mouse = NULL; } -static void hidePopup(dateTimePickerWidget *d) +static void hidePopup(uiprivDateTimePickerWidget *d) { endGrab(d); gtk_widget_hide(d->window); @@ -144,7 +144,7 @@ static void hidePopup(dateTimePickerWidget *d) } // this consolidates a good chunk of what GtkComboBox does -static gboolean startGrab(dateTimePickerWidget *d) +static gboolean startGrab(uiprivDateTimePickerWidget *d) { GdkDevice *dev; guint32 time; @@ -199,7 +199,7 @@ static gboolean startGrab(dateTimePickerWidget *d) } // based on gtk_combo_box_list_position() in the GTK+ source code -static void allocationToScreen(dateTimePickerWidget *d, gint *x, gint *y) +static void allocationToScreen(uiprivDateTimePickerWidget *d, gint *x, gint *y) { GdkWindow *window; GtkAllocation a; @@ -239,7 +239,7 @@ static void allocationToScreen(dateTimePickerWidget *d, gint *x, gint *y) *y = otherY; } -static void showPopup(dateTimePickerWidget *d) +static void showPopup(uiprivDateTimePickerWidget *d) { GtkWidget *toplevel; gint x, y; @@ -261,7 +261,7 @@ static void showPopup(dateTimePickerWidget *d) static void onToggled(GtkToggleButton *b, gpointer data) { - dateTimePickerWidget *d = dateTimePickerWidget(b); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(b); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(d))) showPopup(d); @@ -271,7 +271,7 @@ static void onToggled(GtkToggleButton *b, gpointer data) static gboolean grabBroken(GtkWidget *w, GdkEventGrabBroken *e, gpointer data) { - dateTimePickerWidget *d = dateTimePickerWidget(data); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(data); hidePopup(d); return TRUE; // this is what GtkComboBox does @@ -279,7 +279,7 @@ static gboolean grabBroken(GtkWidget *w, GdkEventGrabBroken *e, gpointer data) static gboolean buttonReleased(GtkWidget *w, GdkEventButton *e, gpointer data) { - dateTimePickerWidget *d = dateTimePickerWidget(data); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(data); int winx, winy; GtkAllocation wina; gboolean in; @@ -384,12 +384,12 @@ static gboolean ampmSpinboxOutput(GtkSpinButton *sb, gpointer data) static void spinboxChanged(GtkSpinButton *sb, gpointer data) { - dateTimePickerWidget *d = dateTimePickerWidget(data); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(data); dateTimeChanged(d); } -static GtkWidget *newSpinbox(dateTimePickerWidget *d, int min, int max, gint (*input)(GtkSpinButton *, gpointer, gpointer), gboolean (*output)(GtkSpinButton *, gpointer), gulong *block) +static GtkWidget *newSpinbox(uiprivDateTimePickerWidget *d, int min, int max, gint (*input)(GtkSpinButton *, gpointer, gpointer), gboolean (*output)(GtkSpinButton *, gpointer), gulong *block) { GtkWidget *sb; @@ -407,24 +407,24 @@ static GtkWidget *newSpinbox(dateTimePickerWidget *d, int min, int max, gint (*i static void dateChanged(GtkCalendar *c, gpointer data) { - dateTimePickerWidget *d = dateTimePickerWidget(data); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(data); dateTimeChanged(d); } -static void setDateOnly(dateTimePickerWidget *d) +static void setDateOnly(uiprivDateTimePickerWidget *d) { d->hasTime = FALSE; gtk_container_remove(GTK_CONTAINER(d->box), d->timebox); } -static void setTimeOnly(dateTimePickerWidget *d) +static void setTimeOnly(uiprivDateTimePickerWidget *d) { d->hasDate = FALSE; gtk_container_remove(GTK_CONTAINER(d->box), d->calendar); } -static void dateTimePickerWidget_setTime(dateTimePickerWidget *d, GDateTime *dt) +static void uiprivDateTimePickerWidget_setTime(uiprivDateTimePickerWidget *d, GDateTime *dt) { gint year, month, day; gint hour; @@ -453,7 +453,7 @@ static void dateTimePickerWidget_setTime(dateTimePickerWidget *d, GDateTime *dt) g_date_time_unref(dt); } -static void dateTimePickerWidget_init(dateTimePickerWidget *d) +static void uiprivDateTimePickerWidget_init(uiprivDateTimePickerWidget *d) { d->window = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_resizable(GTK_WINDOW(d->window), FALSE); @@ -518,29 +518,29 @@ static void dateTimePickerWidget_init(dateTimePickerWidget *d) d->hasDate = TRUE; // set the current date/time - dateTimePickerWidget_setTime(d, g_date_time_new_now_local()); + uiprivDateTimePickerWidget_setTime(d, g_date_time_new_now_local()); } -static void dateTimePickerWidget_dispose(GObject *obj) +static void uiprivDateTimePickerWidget_dispose(GObject *obj) { - dateTimePickerWidget *d = dateTimePickerWidget(obj); + uiprivDateTimePickerWidget *d = uiprivDateTimePickerWidget(obj); if (d->window != NULL) { gtk_widget_destroy(d->window); d->window = NULL; } - G_OBJECT_CLASS(dateTimePickerWidget_parent_class)->dispose(obj); + G_OBJECT_CLASS(uiprivDateTimePickerWidget_parent_class)->dispose(obj); } -static void dateTimePickerWidget_finalize(GObject *obj) +static void uiprivDateTimePickerWidget_finalize(GObject *obj) { - G_OBJECT_CLASS(dateTimePickerWidget_parent_class)->finalize(obj); + G_OBJECT_CLASS(uiprivDateTimePickerWidget_parent_class)->finalize(obj); } -static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) +static void uiprivDateTimePickerWidget_class_init(uiprivDateTimePickerWidgetClass *class) { - G_OBJECT_CLASS(class)->dispose = dateTimePickerWidget_dispose; - G_OBJECT_CLASS(class)->finalize = dateTimePickerWidget_finalize; + G_OBJECT_CLASS(class)->dispose = uiprivDateTimePickerWidget_dispose; + G_OBJECT_CLASS(class)->finalize = uiprivDateTimePickerWidget_finalize; changedSignal = g_signal_new("changed", G_TYPE_FROM_CLASS(class), @@ -554,7 +554,7 @@ static void dateTimePickerWidget_class_init(dateTimePickerWidgetClass *class) struct uiDateTimePicker { uiUnixControl c; GtkWidget *widget; - dateTimePickerWidget *d; + uiprivDateTimePickerWidget *d; void (*onChanged)(uiDateTimePicker *, void *); void *onChangedData; }; @@ -588,7 +588,7 @@ void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) memcpy(&tmbuf, time, sizeof(struct tm)); t = mktime(&tmbuf); - dateTimePickerWidget_setTime(d->d, g_date_time_new_from_unix_local(t)); + uiprivDateTimePickerWidget_setTime(d->d, g_date_time_new_from_unix_local(t)); dateTimeChanged(d->d); } @@ -598,7 +598,7 @@ void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker * d->onChangedData = data; } -static void onChanged(dateTimePickerWidget *d, gpointer data) +static void onChanged(uiprivDateTimePickerWidget *d, gpointer data) { uiDateTimePicker *c; @@ -610,8 +610,8 @@ static GtkWidget *newDTP(void) { GtkWidget *w; - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setLabel(dateTimePickerWidget(w)); + w = GTK_WIDGET(g_object_new(uiprivDateTimePickerWidgetType, "label", "", NULL)); + setLabel(uiprivDateTimePickerWidget(w)); return w; } @@ -619,9 +619,9 @@ static GtkWidget *newDP(void) { GtkWidget *w; - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setDateOnly(dateTimePickerWidget(w)); - setLabel(dateTimePickerWidget(w)); + w = GTK_WIDGET(g_object_new(uiprivDateTimePickerWidgetType, "label", "", NULL)); + setDateOnly(uiprivDateTimePickerWidget(w)); + setLabel(uiprivDateTimePickerWidget(w)); return w; } @@ -629,9 +629,9 @@ static GtkWidget *newTP(void) { GtkWidget *w; - w = GTK_WIDGET(g_object_new(dateTimePickerWidgetType, "label", "", NULL)); - setTimeOnly(dateTimePickerWidget(w)); - setLabel(dateTimePickerWidget(w)); + w = GTK_WIDGET(g_object_new(uiprivDateTimePickerWidgetType, "label", "", NULL)); + setTimeOnly(uiprivDateTimePickerWidget(w)); + setLabel(uiprivDateTimePickerWidget(w)); return w; } @@ -642,7 +642,7 @@ uiDateTimePicker *finishNewDateTimePicker(GtkWidget *(*fn)(void)) uiUnixNewControl(uiDateTimePicker, d); d->widget = (*fn)(); - d->d = dateTimePickerWidget(d->widget); + d->d = uiprivDateTimePickerWidget(d->widget); g_signal_connect(d->widget, "changed", G_CALLBACK(onChanged), d); uiDateTimePickerOnChanged(d, defaultOnChanged, NULL); From 266c6339725b84fb56bf142224a9224c94eb7f10 Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 5 May 2018 22:04:54 -0700 Subject: [PATCH 13/15] uiprivDateTimePickerWidget Fix calendarBlock GTK+ signal --- unix/datetimepicker.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index 46ea19e8..dc2a0328 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -31,6 +31,7 @@ struct uiprivDateTimePickerWidget { GtkWidget *seconds; GtkWidget *ampm; + gulong calendarBlock; gulong hoursBlock; gulong minutesBlock; gulong secondsBlock; @@ -428,17 +429,15 @@ static void uiprivDateTimePickerWidget_setTime(uiprivDateTimePickerWidget *d, GD { gint year, month, day; gint hour; - gulong calendarBlock; // notice how we block signals from firing if (d->hasDate) { - calendarBlock = g_signal_connect(d->calendar, "day-selected", G_CALLBACK(dateChanged), d); g_date_time_get_ymd(dt, &year, &month, &day); month--; // GDateTime/GtkCalendar differences - g_signal_handler_block(d->calendar, calendarBlock); + g_signal_handler_block(d->calendar, d->calendarBlock); gtk_calendar_select_month(GTK_CALENDAR(d->calendar), month, year); gtk_calendar_select_day(GTK_CALENDAR(d->calendar), day); - g_signal_handler_unblock(d->calendar, calendarBlock); + g_signal_handler_unblock(d->calendar, d->calendarBlock); } if (d->hasTime) { hour = g_date_time_get_hour(dt); @@ -472,6 +471,7 @@ static void uiprivDateTimePickerWidget_init(uiprivDateTimePickerWidget *d) gtk_container_add(GTK_CONTAINER(d->window), d->box); d->calendar = gtk_calendar_new(); + d->calendarBlock = g_signal_connect(d->calendar, "day-selected", G_CALLBACK(dateChanged), d); gtk_container_add(GTK_CONTAINER(d->box), d->calendar); d->timebox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); From 9aba97714d1e9c0413267c894284587376a350c5 Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 12 May 2018 20:03:20 -0700 Subject: [PATCH 14/15] uiDateTimePicker Add comments --- darwin/datetimepicker.m | 3 +++ ui.h | 1 + unix/datetimepicker.c | 3 +++ 3 files changed, 7 insertions(+) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index fadf94ca..3c09e72a 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -87,6 +87,8 @@ void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) date = [d->dp dateValue]; t = (time_t) [date timeIntervalSince1970]; + // Copy time to minimize a race condition + // time.h functions use global non-thread-safe data tmbuf = *localtime(&t); memcpy(time, &tmbuf, sizeof(struct tm)); } @@ -96,6 +98,7 @@ void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) time_t t; struct tm tmbuf; + // Copy time because mktime() modifies its argument memcpy(&tmbuf, time, sizeof(struct tm)); t = mktime(&tmbuf); diff --git a/ui.h b/ui.h index 765b7733..b5fb9a27 100644 --- a/ui.h +++ b/ui.h @@ -251,6 +251,7 @@ _UI_EXTERN uiRadioButtons *uiNewRadioButtons(void); struct tm; typedef struct uiDateTimePicker uiDateTimePicker; #define uiDateTimePicker(this) ((uiDateTimePicker *) (this)) +// TODO document that tm_wday and tm_yday are undefined, and tm_isdst should be -1 _UI_EXTERN void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time); _UI_EXTERN void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time); _UI_EXTERN void uiDateTimePickerOnChanged(uiDateTimePicker *d, void (*f)(uiDateTimePicker *, void *), void *data); diff --git a/unix/datetimepicker.c b/unix/datetimepicker.c index dc2a0328..5f052dca 100644 --- a/unix/datetimepicker.c +++ b/unix/datetimepicker.c @@ -576,6 +576,8 @@ void uiDateTimePickerTime(uiDateTimePicker *d, struct tm *time) t = g_date_time_to_unix(dt); g_date_time_unref(dt); + // Copy time to minimize a race condition + // time.h functions use global non-thread-safe data tmbuf = *localtime(&t); memcpy(time, &tmbuf, sizeof(struct tm)); } @@ -585,6 +587,7 @@ void uiDateTimePickerSetTime(uiDateTimePicker *d, const struct tm *time) time_t t; struct tm tmbuf; + // Copy time because mktime() modifies its argument memcpy(&tmbuf, time, sizeof(struct tm)); t = mktime(&tmbuf); From fd3b693ffe9ca7d1bcca1c5a386c8b28d836ae6e Mon Sep 17 00:00:00 2001 From: cody271 Date: Sat, 12 May 2018 21:40:47 -0700 Subject: [PATCH 15/15] uiDateTimePicker Use more 'uipriv' on OS X --- darwin/datetimepicker.m | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/darwin/datetimepicker.m b/darwin/datetimepicker.m index 3c09e72a..54c6ba38 100644 --- a/darwin/datetimepicker.m +++ b/darwin/datetimepicker.m @@ -9,7 +9,7 @@ struct uiDateTimePicker { }; @interface uiprivDatePickerDelegateClass : NSObject { - struct mapTable *pickers; + struct uiprivMap *pickers; } - (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell validateProposedDateValue:(NSDate **)proposedDateValue timeInterval:(NSTimeInterval *)proposedTimeInterval; - (void)doTimer:(NSTimer *)timer; @@ -23,13 +23,13 @@ struct uiDateTimePicker { { self = [super init]; if (self) - self->pickers = newMap(); + self->pickers = uiprivNewMap(); return self; } - (void)dealloc { - mapDestroy(self->pickers); + uiprivMapDestroy(self->pickers); [super dealloc]; } @@ -39,7 +39,7 @@ struct uiDateTimePicker { { uiDateTimePicker *d; - d = (uiDateTimePicker *) mapGet(self->pickers, aDatePickerCell); + d = (uiDateTimePicker *) uiprivMapGet(self->pickers, aDatePickerCell); [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(doTimer:) @@ -57,14 +57,14 @@ struct uiDateTimePicker { - (void)registerPicker:(uiDateTimePicker *)d { - mapSet(self->pickers, d->dp.cell, d); + uiprivMapSet(self->pickers, d->dp.cell, d); [d->dp setDelegate:self]; } - (void)unregisterPicker:(uiDateTimePicker *)d { [d->dp setDelegate:nil]; - mapDelete(self->pickers, d->dp.cell); + uiprivMapDelete(self->pickers, d->dp.cell); } @end @@ -129,7 +129,7 @@ static uiDateTimePicker *finishNewDateTimePicker(NSDatePickerElementFlags elemen if (datePickerDelegate == nil) { datePickerDelegate = [[uiprivDatePickerDelegateClass new] autorelease]; - [delegates addObject:datePickerDelegate]; + [uiprivDelegates addObject:datePickerDelegate]; } [datePickerDelegate registerPicker:d]; uiDateTimePickerOnChanged(d, defaultOnChanged, NULL);