# Windows

The window management part of the UI library is built around windows, containers, frames, and dialogs. In the context of the UI library, a window is a rectangle on the screen. It is typically embedded inside another window to represent some component, such as a button. A container is a window that may contain other child windows. A frame is a container that has a border, and can be used as a top-level window. As such, the root of a window hierarchy is typically a frame, not a window. Finally, a dialog is a frame that might have a parent frame (i.e. it is displayed "on top of" another window).

The terminology above follows the naming in the Windows API (which is what the UI library was initially developed for). Gtk uses other terms. Gtk uses the term widget for what the UI library calls a window.

Each of these central classes are documented in more detail below. This page of the manual then concludes with an overview of the different UI components.

## Threading

All operations on windows happen on the `ui.Ui` thread. All components described in this section are thereby actors that are tied to this thread.

The `ui.Ui` thread is in charge of interfacing with the operating system. As such, it is a good idea to not block the `Ui` thread if possible. In Basic Storm, this is fairly easy by using the `spawn` keyword to create another thread. It is generally sufficient if the thread that called a callback function returns to the caller quickly, even if another UThread is spawned on the same OS thread. However, care should be taken not to execute heavy computations on the `Ui` thread without periodically calling `yield` to let the UI library process messages from the operating system. Computationally expensive operations are therefore typically better to delegate to other OS threads entirely.

## Usage

The UI library is designed with the intent that the core classes (i.e. `Window`, `Container`, `Frame`, and `Dialog`) should be subclassed to create custom windows. As such, most events from the windowing system are notified in the form of overloaded functions. Other components (e.g. `Button`) are not designed to be subclassed, and instead provide callbacks in the form of function pointers. This means that creating a custom window or dialog typically involves creating a subclass to `Frame` or `Dialog` as desired, and let the subclass create all child components, and listen for callbacks from them using callbacks from function pointers.

## Creation of Windows

Due to restrictions in the underlying APIs, it is not always possible to create individual windows without first creating their parents. In order to not restrict the UI library needlessly, the UI library does not impose such restrictions (e.g. it is possible to create a `Button` without first creating a parent `Window`). This does, however, mean that the UI library creates the actual windows lazily, whenever the classes are attached to a parent.

In most cases, this is transparent to the user. It does, however, mean that some features (such as focus management) may not be fully functional until the windows have actually been created (Gtk uses the term realized to describe this). It also means that some care needs to be taken for top-level windows, since they do not have a parent. The UI library thus requires top-level windows to be explicitly created by calling the `create` member. This creates the entire window in one operation, and has the benefit that it lets the underlying system present the window as a unit, and avoid partially drawn windows as far as possible.

This model also means that the system can clean up any resources associated with the created windows as soon as the top-level window is closed. It is therefore not necessary to explicitly destroy windows, as long as the top-level window is closed.

## Window

As mentioned above, a `ui.Window` is a rectangular region on the screen. By itself it represents a window that has to be embedded inside another window. However, the subclass `ui.Frame` lifts this restriction.

Coordinates in a window are always relative to the top-left edge of the window. The exception is the coordinates returned by `pos`, which are relative to the window's parent.

The `Window` class has the following members:

- `init()`

  Create an empty window.

- `core.Maybe<ui.ContainerBase> parent()`

  Get the parent window. Null for frames.

- `core.Maybe<ui.Frame> rootFrame()`

  Get the frame that is in the root of the hierarchy. Returns ourself for frames, returns `null` before attached.

- `core.Bool visible()`

  Check if the window is visible.

- `void visible(core.Bool show)`

  Set if the window is visible or not. Assignment function, so `visible` can be used as a member variable.

- `core.Bool enabled()`

  Check if the window is enabled.

- `void enabled(core.Bool enable)`

  Set if the window is enabled. Generally only interesting to do for leaf windows. Assignment function, so it can be used as a member variable.

- `core.Str text()`

  Get the window text. How this text is used depends on the window.

- `void text(core.Str str)`

  Set the window text. Assignment function, so it can be used as a member variable.

- `core.geometry.Rect pos()`

  Get the window position. Always relative to the client area of the parent (even in Frames).

- `void pos(core.geometry.Rect r)`

  Set the window position.

- `core.geometry.Size minSize()`

  Get the minimum size for this window. Note: This does not consider the size and position of any child windows in case this is a container. This function is mostly useful for determining the preferred size for various windows.

- `ui.Font font()`

  Get the current font.

- `void font(ui.Font font)`

  Set the current font. Assignment function, so it can be used as a member variable.

- `void focus()`

  Set focus to this window.

- `void update()`

  Update the window (ie repaint it) right now.

- `void repaint()`

  Repaint the window when we have time.

- `void resized(core.geometry.Size size)`

  Called when the window is resized.

- `void resized()`

  Convenience function to trigger uptade of layouts easily.

- `void painter(core.Maybe<ui.BasicPainter> to)`

  Set window contents (custom drawing).

- `core.Maybe<ui.BasicPainter> painter()`

  Get the current painter.

- `void setTimer(core.Duration interval)`

  Set the window timer. Causes `onTimer` to be called regularly.

- `void clearTimer()`

  Stop timer.

The `Window` class also has a number of callbacks that are called when certain events occur. These are member functions that can be overloaded by a subclass. Many of the functions return a boolean. This indicates if the handler recognized the event, and signals to the UI library that the event should not be processed further (e.g. by parent windows).

- `core.Bool onKey(core.Bool pressed, ui.Key keycode, ui.Modifiers modifiers)`

  Called when a key is pressed or released (depending on `pressed`). Should return `true` if the keypress was recognized and should not propagate further.

- `core.Bool onChar(core.Nat charCode)`

  Called when a key has been typed. Note that this is sometimes different from a key press event. A typical example is a dead key. The dead key will produce `onKey` events as usual, but will not produce a `onChar` event until the next keypress, when it might be combined with the next character. Another example is when using an IME.

- `core.Bool onClick(core.Bool pressed, core.geometry.Point at, ui.MouseButton button)`

  Called when a mouse button has been pressed or released (depending on `pressed`) at the location `at` in the window.

- `core.Bool onDblClick(core.geometry.Point at, ui.MouseButton button)`

  Called when a mouse button has been double-clicked in the window.

- `core.Bool onMouseMove(core.geometry.Point at)`

  Called whenever the mouse is moved in the window.

- `void onMouseEnter()`

  Called when the mouse entered this window. The mouse is considered to be inside the window only for as long as the mouse is directly on top of the window. For example, if the mouse moves over a child window, the mouse is no longer considered to be inside of this window.

- `void onMouseLeave()`

  Called when the mouse has left this window.

- `core.Bool onMouseVScroll(core.geometry.Point at, core.Float delta)`

  Called when the mouse has been scrolled in the vertical direction.

- `core.Bool onMouseHScroll(core.geometry.Point at, core.Float delta)`

  Called when the mouse has been scrolled in the horizontal direction.

- `void onTimer()`

  Called regularly if the `setTimer` has been called to start the timer.

## Container

The `ui.Container` class is a subclass of the `Window` class and represents a window that may contain child windows. To achieve this, the `Container` class provides the following additional functions:

- `void add(ui.Window child)`

  Add a child window. This may actually create it!

- `void remove(ui.Window child)`

  Remove a child window. Silently fails if the child does not already exist.

## Frame

The `ui.Frame` class represents a top-level window that can be a parent of a window hierarchy. It inherits from the `Container` class and may therefore contain sub-windows. Since the frame does not have a parent, it needs to be created manually. This is achieved with the `create` function.

The `Frame` provides the following member functions:

- `init(core.Str title)`

  Create a frame, specifying a window title. Note: `create` must be called to create the frame.

- `init(core.Str title, core.geometry.Size size)`

  Create a frame, specifying a window title and an initial size. Note: `create` must be called to create the frame.

- `void create()`

  Create the frame and show it.

- `void close()`

  Close this frame.

- `void waitForClose()`

  Wait until this frame is closed.

- `void size(core.geometry.Size s)`

  Set the size of the frame.

- `void fullscreen(core.Bool f)`

  Set fullscreen mode.

- `core.Bool fullscreen()`

  Get fullscreen mode.

- `void cursorVisible(core.Bool v)`

  Set if the cursor is visible when over this frame.

- `core.Bool cursorVisible()`

  Get if the cursor is visible when over this frame.

- `ui.Accelerators accelerators()`

  Get the accelerator table for this window.

- `void menu(core.Maybe<ui.MenuBar> menu)`

  Set the menu for this window.

- `core.Maybe<ui.MenuBar> menu()`

  Get the menu for this window.

- `void popupMenu(ui.PopupMenu menu)`

  Show a popup menu at the cursor position. This menu may be a part of another menu.

- `core.Bool minimized()`

  Check if the window is minimized (note that the window is still considered visible if minimized).

- `core.Maybe<ui.Icon> icon()`

  Get/set the current icon. If null, we use the default icon set in the application itself.

- `void icon(core.Maybe<ui.Icon> icon)`

  Get/set the current icon. If null, we use the default icon set in the application itself.

- `void icon(graphics.ImageSet icon)`

  Get/set the current icon. If null, we use the default icon set in the application itself.

- `core.Bool inhibitScreenSaver()`

  Inhibit the screen saver while this window is visible on the screen (= not minimized). Useful for applications that e.g. play video, where the screen should stay on even though not much user interaction is expected.

- `void inhibitScreenSaver(core.Bool inhibit)`

  Inhibit the screen saver while this window is visible on the screen (= not minimized). Useful for applications that e.g. play video, where the screen should stay on even though not much user interaction is expected.

A note on icons: The global `ui.App` instance (accessible by calling `ui.App app()`) allows setting a default icon for the entire application. That way one can avoid setting icons on individual windows manually. When loading icons, prefer to use `loadSet` and `ImageSet` whenever possible, so that the windowing system can pick an appropriate size based on where the icon will appear. The Graphics library automatically loads `.ico` files into the name tree, so that the application's icon can be conveniently stored alongside its source code and be easily accessible by the application.

## Dialog

The class `ui.Dialog` class represents a frame that acts as a dialog. This means two things: first, a dialog may have a default behavior for the enter and escape keys (typically OK and Cancel respectively). Secondly, the dialog may be a modal dialog that blocks access to another window.

It provides the following members:

- `init(core.Str title)`

  Create the dialog. As with `Frame`s, the dialog is not shown until `show` is called.

- `init(core.Str title, core.geometry.Size size)`

  Create the dialog. As with `Frame`s, the dialog is not shown until `show` is called.

- `core.Int show(ui.Frame parent)`

  Show the dialog as a modal window. Don't call `create` before calling `show`, that is handled internally. Returns whatever is passed to `close` by the implementation, or -1 if the dialog was closed (or cancelled by a default button).

- `void close(core.Int result)`

  Call when the window is shown to close the dialog with a particular code.

- `void close()`

  Override the default behavior to return -1.

- `void defaultChoice(ui.Button button)`

  Set the button that acts as the default choice in this dialog. This button will be activated whenever "enter" is pressed. The button's handler will also be set by the implementation to return 1, but this may be overridden by the user at a later point if desired.

- `void onDestroy(core.Int code)`

  Called when the dialog is about to be closed to give the implementation time to save things before they are destroyed.

## Other Components

The UI library provides a number of UI components as follows:

- `ui.Label`

  A simple piece of text displayed in the window.

- `ui.Edit`

  A simple box that allows simple text editing.

- `ui.Button`

  A button that can be pressed by the user.

- `ui.CheckButton`

  A checkmark that can be selected or deselected.

- `ui.RadioButton`

  A button that can be associated with a group of similar buttons. Only allows one button in the group to be selected at any one time.

- `ui.ListView`

  A component that shows a scrollable list. The list may contain columns with different contents.

- `ui.ScrollWindow`

  Provides a viewport to another window, where the user can scroll the contents of the other window.

- `ui.TabView`

  Provides a set of tabs, where the user can select one out of many possible views.

- `ui.Group`

  A box that draws a box around its contents, optionally with a label. Used to group other components together.

- `ui.HSeparator`, `ui.VSeparator`

  Horizontal and vertical separator lines.

Additionally, the UI library provides the following convenience interfaces:

- `ui.FilePicker`

  Provides access to the operating system's default open/save dialogs.

- `ui.MessageDialog`

  Default message dialogs. Use any of the following functions to easily create message dialogs:

  - `void showMessage(ui.Frame parent, core.Str title, core.Str message)`

    Show a notification. I.e. a box with only OK.

  - `ui.MessageResponse showYesNoQuestion(ui.Frame parent, core.Str title, core.Str message, core.Str yes, core.Str no)`

    Show a yes-no question.

  - `ui.MessageResponse showYesNoCancelQuestion(ui.Frame parent, core.Str title, core.Str message, core.Str yes, core.Str no, core.Str cancel)`

    Show a yes-no-cancel question.

- `void ui.showLicenseDialog(ui.Frame owner, ui.ProgramInfo info)`

  Show a default dialog that contains the licenses of all currently used libraries. Useful to conveniently comply with requirements in license agreements for GUI applications.