boing 0.4.0

A safe, lightweight wrapper over libui-ng-sys
Documentation
# Design

*libui-ng* (and *libui*) were apparently not designed with Rust in mind. 😉

To guarantee safety to the end user, both type-level and runtime decisions were made to restrict usage of the *libui-ng* API. As *libui-ng* lacks polished documentation at the time of writing, the following explanations will reference the source code directly.

## Initialization

`uiInit` must be called exactly once.

### Reasons

Calling `uinit` twice...
* ...on Windows returns `ERROR_CLASS_ALREADY_EXISTS` from `RegisterClassEx`.
* ...on macOS duplicates the app delegate and autorelease pool.

### Solution

*boing*'s `Ui::new` sets a global boolean when called for the first time, and aborts if the boolean is already set.

```rust
// OK.
let _ = ui.new()?;

// ERROR: *libui-ng* is already initialized.
let _ = ui.new()?;
```

## Widget Construction

Widget construction requires that `uiInit` has previously been called.

### Reasons

Constructing a widget before `uiInit` is called...
* ...on Windows bypasses calling `InitCommonControls`, causing WinAPI window functions to return `ERROR_CANNOT_FIND_WND_CLASS`.
* ...on macOS dereferences an uninitialized pointer.
* ...on Linux bypasses calling `gtk_init_with_args`.

### Solution

To be construted, *boing* widgets require access to a `Ui` object, which can only be obtained after `Ui::new` and, by extension, `uiInit`, are called.

```rust
// ERROR: This function doesn't exist!
let window = Window::new(/* ... */);

// OK.
let ui = Ui::new()?;
let window = ui.create_window(/* ... */);
```

## Main Loop

Although not explicitly stated, *libui-ng* seems to permit calling `uiMain` and `uiQuit` multiple times; it should likewise be possible to invoke the main loop multiple times from *boing*. Furthermore, widgets may be modified after `uiMain` or `uiQuit` are invoked.

### Solution

```rust
// OK.
let ui: Ui;
let window = ui.create_window(/* ... */);
ui.run();

// OK (but weird!).
ui.run();
window.set_fullscreen(true);
```

## Control Destruction

`uiControlDestroy` must be called on a given control exactly once, after which the control must no longer be accessed.

### Reasons

Destroying a control twice, as well as accessing a control after it has already been destroyed, causes a use-after-free on all platforms.

### Solution

*boing* controls feature a `Drop` implementation that destroys their *libui-ng* representation, ensuring not only that `uiControlDestroy` is called once and only once, but also that the controls may not be accessed after destruction.

```rust
// OK.
let window: Window;
drop(window);

// ERROR: `window` was already destroyed by its `Drop` implementation.
window.set_fullscreen(true);
drop(window);
```