Okay, I won't even bother with the overview until I figure out how events will work in the final API, because I legitimately cannot decide how to write this.

This commit is contained in:
Pietro Gagliardi 2020-05-09 00:35:38 -04:00
parent dea7b52605
commit c0e73c67f4
1 changed files with 1 additions and 68 deletions

View File

@ -4,74 +4,7 @@
## Overview
In order to use libui, you must first initialize it. All initialization is done through the `uiInit()` function. This is usually one of the first things you do in your program.
The thread you call `uiInit()` on becomes the "GUI thread". This is the thread that all your UI is done on from the perspective of the operating system, so it is absolutely essential that you do **not** call any other function of libui from any other thread that you create (except for `uiQueueMain()`, which is discussed later).
Furthermore, on some systems, this thread must also be the thread that `main()` is called on; macOS is the notable example here. Therefore, to be safe, you should only call `uiInit()` from `main()`, or from a function that runs on the same thread as `main()`. If you are using a language binding, that binding may provide further instruction on how to do so in that language.
`uiInit()` *can* fail, in which case it will provide information about that failure in a special variable of type `uiInitError` that you provide it. The most useful member of this struct is `Message`, which contains a human-readable error message you can use to diagnose problems initializing libui. If you are using a language binding, the language binding may abstract this away and provide the error to you in a langauge-specific form.
Here is an example of correct use of `uiInit()` in C:
```c
int main(void)
{
uiInitError err;
memset(&err, 0, sizeof (uiInitError));
err.Size = sizeof (uiInitError);
if (!uiInit(NULL, &err)) {
fprintf(stderr, "error initializing libui: %s\n", err.Message);
return 1;
}
// ...
}
```
Note that if `uiInit()` fails, you **cannot** use libui's message box functions to report the error.
Once you have called `uiInit()`, you should set up the initial UI for your program. Once that is done, you start the program event loop by calling `uiMain()`. `uiMain()` runs the *main event loop*, which processes all events for the GUI and dispatches them to the event handlers you write. As this function does everything for you, all you need to do is call it:
```c
int main(void)
{
// ...
uiMain();
return 0;
}
```
`uiMain()` will not return until one of your event handlers calls `uiQuit()`. `uiQuit()` informs `uiMain()` that it should return, but it won't actually return until the current event handler has finished being processed. Once it does return, you will be dropped back into `main()`.
Event handlers can be more than just actions in response to user action to a control, such as clicking a button. The OS can use events to tell your program things that happen outside your program, such as "the user wants to close your application from within a program list/taskbar/dock". libui provides methods of catching and handling these. You can also schedule code to run when there is no event pending, or on a timed loop. While these scheduled code paths are not technically events per se, they operate exactly like event handlers.
TODO should quit
The simplest way to schedule code to run the next time no event is pending is to use `uiQueueMain()`. `uiQueueMain()` takes a function and some data to pass to that function, and returns immediately, so you can continue working. When `uiMain()` goes to get the next event, it will notice that your function is ready to run, and if there are no events that need to be handled, will do so.
`uiQueueMain()` is special in that it is the only function in libui that you can call from any thread, not just the UI thread. This is intentional: `uiQueueMain()` allows you to communicate between the UI thread and another thread, as all code that is scheduled by `uiQueueMain()` is run on the UI thread. For example, if you are downloading assets in a background thread and want to update a progressbar, you can do so:
```c
void updateProgressBar(void *data)
{
uiProgressBar *p = uiProgressBar(data);
uiProgressBarSetValue(p, uiProgressBarValue(p) + 1);
}
extern uiProgressBar *progressbar;
void backgroundThread(void)
{
while (fileIsDownloading())
uiQueueMain(updateProgressBar, progressbar);
}
```
If you want to wait for the function in `uiQueueMain()` to be called, you will need to provide some synchronization method yourself. Be careful not to do this if you call `uiQueueMain()` on the UI thread, to avoid deadlocking your program!
TODO timers
TODO
## Reference