File: 01-Windows.md

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (260 lines) | stat: -rw-r--r-- 9,058 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
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 [stormname:ui.Ui] thread. All components described in this
section are thereby actors that are tied to this thread.

The [stormname: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 [stormname: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
[stormname: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:

```stormdoc
@ui.Window
- .__init()
- .parent()
- .rootFrame()
- .visible(*)
- .enabled(*)
- .text(*)
- .pos(*)
- .minSize()
- .font(*)
- .focus()
- .update()
- .repaint()
- .resized(*)
- .painter(*)
- .setTimer(*)
- .clearTimer()
```

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).

```stormdoc
@ui.Window
- .onKey(*)
- .onChar(*)
- .onClick(*)
- .onDblClick(*)
- .onMouseMove(*)
- .onMouseEnter()
- .onMouseLeave()
- .onMouseVScroll(*)
- .onMouseHScroll(*)
- .onTimer()
```


Container
---------

The [stormname: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:

```stormdoc
@ui.Container
- .add(*)
- .remove(*)
```


Frame
-----

The [stormname: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:

```stormdoc
@ui.Frame
- .__init(Str)
- .__init(Str, core.geometry.Size)
- .create()
- .close()
- .waitForClose()
- .size(*)
- .fullscreen(*)
- .cursorVisible(*)
- .accelerators()
- .menu(*)
- .popupMenu(*)
- .minimized(*)
- .icon(*)
- .inhibitScreenSaver(*)
```

A note on icons: The global [stormname:ui.App] instance (accessible by calling [stormname:ui.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](md://Library_Reference/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 [stormname: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:

```stormdoc
@ui.Dialog
- .__init(Str)
- .__init(Str, core.geometry.Size)
- .show(*)
- .close(*)
- .defaultChoice(*)
- .onDestroy(*)
```


Other Components
----------------

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

- [stormname:ui.Label]

  A simple piece of text displayed in the window.

- [stormname:ui.Edit]

  A simple box that allows simple text editing.

- [stormname:ui.Button]

  A button that can be pressed by the user.

- [stormname:ui.CheckButton]

  A checkmark that can be selected or deselected.

- [stormname: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.

- [stormname:ui.ListView]

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

- [stormname:ui.ScrollWindow]

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

- [stormname:ui.TabView]

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

- [stormname:ui.Group]

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

- [stormname:ui.HSeparator], [stormname:ui.VSeparator]

  Horizontal and vertical separator lines.


Additionally, the UI library provides the following convenience interfaces:

- [stormname:ui.FilePicker]

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

- [stormname:ui.MessageDialog]

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

  ```stormdoc
  @ui
  - .showMessage(*)
  - .showYesNoQuestion(*)
  - .showYesNoCancelQuestion(*)
  ```

- [stormname:full:ui.showLicenseDialog(ui.Frame, ui.ProgramInfo)]

  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.