Merge pull request #277 from cody271/timer

Adds a function uiTimer() that runs code on the main loop at certain intervals.

Original comment: Add Timer API
This commit is contained in:
Pietro Gagliardi 2018-04-18 20:52:59 -04:00 committed by GitHub
commit 85a4c6d35d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 175 additions and 1 deletions

View File

@ -242,3 +242,44 @@ void uiQueueMain(void (*f)(void *data), void *data)
// the signature of f matches dispatch_function_t
dispatch_async_f(dispatch_get_main_queue(), data, f);
}
@interface uiprivTimerDelegate : NSObject {
int (*f)(void *data);
void *data;
}
- (id)initWithCallback:(int (*)(void *))callback data:(void*)callbackData;
- (void)doTimer:(NSTimer *)timer;
@end
@implementation uiprivTimerDelegate
- (id)initWithCallback:(int (*)(void *))callback data:(void*)callbackData
{
self = [super init];
if (self) {
self->f = callback;
self->data = callbackData;
}
return self;
}
- (void)doTimer:(NSTimer *)timer
{
if (!self->f(self->data))
[timer invalidate];
}
@end
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
{
uiprivTimerDelegate *delegate;
delegate = [[uiprivTimerDelegate alloc] initWithCallback:f data:data];
[NSTimer scheduledTimerWithTimeInterval:milliseconds / 1000.0
target:delegate
selector:@selector(doTimer:)
userInfo:nil
repeats:YES];
[delegate release];
}

View File

@ -42,9 +42,15 @@ _add_example(drawtext
${_EXAMPLE_RESOURCES_RC}
)
_add_example(timer
timer/main.c
${_EXAMPLE_RESOURCES_RC}
)
add_custom_target(examples
DEPENDS
controlgallery
histogram
cpp-multithread
drawtext)
drawtext
timer)

64
examples/timer/main.c Normal file
View File

@ -0,0 +1,64 @@
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "../../ui.h"
uiMultilineEntry *e;
int sayTime(void *data)
{
time_t t;
char *s;
t = time(NULL);
s = ctime(&t);
uiMultilineEntryAppend(e, s);
return 1;
}
int onClosing(uiWindow *w, void *data)
{
uiQuit();
return 1;
}
void saySomething(uiButton *b, void *data)
{
uiMultilineEntryAppend(e, "Saying something\n");
}
int main(void)
{
uiInitOptions o;
uiWindow *w;
uiBox *b;
uiButton *btn;
memset(&o, 0, sizeof (uiInitOptions));
if (uiInit(&o) != NULL)
abort();
w = uiNewWindow("Hello", 320, 240, 0);
uiWindowSetMargined(w, 1);
b = uiNewVerticalBox();
uiBoxSetPadded(b, 1);
uiWindowSetChild(w, uiControl(b));
e = uiNewMultilineEntry();
uiMultilineEntrySetReadOnly(e, 1);
btn = uiNewButton("Say Something");
uiButtonOnClicked(btn, saySomething, NULL);
uiBoxAppend(b, uiControl(btn), 0);
uiBoxAppend(b, uiControl(e), 1);
uiTimer(1000, sayTime, NULL);
uiWindowOnClosing(w, onClosing, NULL);
uiControlShow(uiControl(w));
uiMain();
return 0;
}

2
ui.h
View File

@ -62,6 +62,8 @@ _UI_EXTERN void uiQuit(void);
_UI_EXTERN void uiQueueMain(void (*f)(void *data), void *data);
_UI_EXTERN void uiTimer(int milliseconds, int (*f)(void *data), void *data);
_UI_EXTERN void uiOnShouldQuit(int (*f)(void *data), void *data);
_UI_EXTERN void uiFreeText(char *text);

View File

@ -106,3 +106,30 @@ void uiQueueMain(void (*f)(void *data), void *data)
q->data = data;
gdk_threads_add_idle(doqueued, q);
}
struct timer {
int (*f)(void *);
void *data;
};
static gboolean dotimer(gpointer data)
{
struct timer *t = (struct timer *) data;
if((*(t->f))(t->data))
return TRUE;
else {
uiFree(t);
return FALSE;
}
}
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
{
struct timer *t;
t = uiNew(struct timer);
t->f = f;
t->data = data;
g_timeout_add(milliseconds, dotimer, t);
}

View File

@ -128,3 +128,12 @@ void uiQueueMain(void (*f)(void *data), void *data)
// LONGTERM this is likely not safe to call across threads (allocates memory)
logLastError(L"error queueing function to run on main thread");
}
void uiTimer(int milliseconds, int (*f)(void *data), void *data)
{
UINT_PTR timer;
timer = (UINT_PTR) new TimerHandler(f, data);
if (SetTimer(utilWindow, timer, milliseconds, NULL) == 0)
logLastError(L"SetTimer()");
}

View File

@ -95,6 +95,22 @@ extern const char *initUtilWindow(HICON hDefaultIcon, HCURSOR hDefaultCursor);
extern void uninitUtilWindow(void);
// main.cpp
struct TimerHandler {
public:
TimerHandler() : TimerHandler(NULL, NULL) {}
TimerHandler(int(*f)(void *data), void *data)
{
this->f = f;
this->data = data;
}
int operator()()
{
return this->f(this->data);
}
private:
int(*f)(void *data);
void *data;
};
extern int registerMessageFilter(void);
extern void unregisterMessageFilter(void);

View File

@ -18,6 +18,7 @@ static LRESULT CALLBACK utilWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
{
void (*qf)(void *);
LRESULT lResult;
TimerHandler *timer;
if (handleParentMessages(hwnd, uMsg, wParam, lParam, &lResult) != FALSE)
return lResult;
@ -36,6 +37,14 @@ static LRESULT CALLBACK utilWindowWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
qf = (void (*)(void *)) wParam;
(*qf)((void *) lParam);
return 0;
case WM_TIMER:
timer = (TimerHandler *) wParam;
if (!(*timer)()) {
if (!KillTimer(utilWindow, (UINT_PTR) timer))
logLastError(L"KillTimer()");
delete timer;
}
return 0;
}
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}