File: README.md

package info (click to toggle)
lsp-plugins 1.2.21-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 120,408 kB
  • sloc: cpp: 589,849; xml: 74,078; makefile: 13,396; php: 1,268; sh: 185
file content (334 lines) | stat: -rw-r--r-- 11,312 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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# lsp-tk-lib

Graphical toolkit library used by Linux Studio Plugins Project.

![Indicator widget](res/doc/indicator.png)

## Key features

* Supported platforms:
  * FreeBSD (X11/Cairo);
  * GNU/Linux (X11/Cairo);
  * Windows (WinAPI/D2D1).
* Pretty leightweight, only about 2 MB of compiled code.
* Almost minimum global state (used only in case when underlying API requires global variables),
  all operations are performed on `tk::Display` main object and objects derived from `tk::Widget`.
  This makes possible to have multiple versions of library for instances in the same runtime under
  certain circumstances.
* Basic styling support. Style schema can be loaded from the XML file and updated in runtime.
* Automatic space and widget layout allocation.
* Dynamic widget scaling is supported for High DPI displays.
* Multilingual support, languages may be switched in runtime without need of application reload.
  There is also a flexible way to manage access to the dicionary data.
* All widgets provide set of object properties which change the appearance and
  behaviour of the widget in runtime.
* Slots (one publisher - multiple subscribers) for handling UI events.

## Overall list of widgets

This library provides set of widgets useful for creating user interfaces of plugins.

The full list of provided widgets:
* 3D rendering:
  * Area3D - the 3D scene rendering widget which supports different rendering backends
    which implement [R3D interfaces](https://github.com/sadko4u/lsp-r3d-iface.git).
* Compound widgets:
  * ComboBox - widget with drop-down list.
  * ComboGroup - widget group with drop-down list for selection of currently visible widget.
  * ListBox - list of selectable items.
  * Menu - popup menu.
* Widget containers:
  * Align - widget alignment among the surrounding container.
  * Box - container for packaging widgets into a single horizontal row or vertical column.
  * Grid - container for packaging widgets into table.
  * Group - container for surrounding widgets into a distinguishable group.
  * MultiLabel - widget that allows to implement overlay of multiple labels on the same area.
  * ScrollArea - container that allows to package widget into limited rectangular space.
  * TabControl - container that allows to organize widgets as a set of tabs.
  * TabGroup - container that behaves similar to ComboGroup but uses tabs insetad of combo box.
  * Window - window widget.
* Dialogs:
  * FileDialog - widget for selecting files for load/save operations.
  * MessageBox - widget for displaying popup messages.
* 2D graph widgets for rendering graphs and plots:
  * Graph - widget for rendering 2D graphical data (graphs and plots).
  * GraphAxis - axis on a graph widget.
  * GraphDot - dot on a graph widget.
  * GraphFrameBuffer - frame buffer for drawing on the graph widget.
  * GraphLineSegment - grap line segment defined by two points.
  * GraphMarker - marker on the graph widget.
  * GraphMesh - widget for drawing meshes on the graph widget.
  * GraphOrigin - widget for defining origins within the graph widget.
* Simple widgets:
  * Bevel - simple widget that allows to draw bevels/facets in the UI.
  * Button - simple button which can operate in different modes.
  * CheckBox - squared single on/off toggle.
  * Edit - single line text edit widget.
  * Fader - fader widget.
  * Hyperlink - hyperlink widget.
  * Indicator - 7-segment LED indicator.
  * Knob - single rotating knob.
  * Label - single/multiline text.
  * Led - led widget.
  * ListBoxItem - single item of the ListBox widget.
  * MenuItem - menu item widget used by Menu widget.
  * ProgressBar - widget for displaying progress of some long lasting process.
  * RadioButton - rounded single on/off toggle.
  * ScrollBar - single scroll bar.
  * Separator - separator widget to visually separate space allocated in widget containers.
  * Void - void widget which can be used for filling empty area.
* Specifific widgets
  * AudioChannel - single audio channel oscillogram.
  * AudioSample - oscillogram of audio sample with multiple audio channels.
  * FileButton - button of 1.44" disk form for loading/saving files.
  * Fraction - music fraction with numerator and denominator.
  * LedMeter - led level/peak meter with multiple channels.
  * LedMeterChannel - single-channel level/peak meter.

## Styling system

Styling system allows to apply different styles to the same widgets:

Standard theme:

![Indicator widget](res/doc/filedialog-standard.png)

LSP theme:

![Indicator widget](res/doc/filedialog-lsp.png)

Drak flat theme:

![Indicator widget](res/doc/filedialog-dark.png)

## Multilingual support

Each string is associated with a dot-separated text key which defines the corresponding
path in the dictionary to access the localized string nb. All dictionaries for the same language
are stored as JSON files in a directory with the symbolic name of the language (for example, `en`).
All possible languages are stored in a single localization directory which is passed to the
toolkit. Additional fallback `default` directory is also considered for searching keys which
are not present in the current language.

Example of a dictionary `actions.json`:
```
{
	"cancel": "Cancel",
	"nav": {
		"go": "Go",
		"up": "Up"
	},
	"to_bookmarks": "+Bookmarks",
	"dlg": {
		"open": "Open dialog",
		"save": "Save dialog"
	},
	"open": "Open",
	"save": "Save",
	"link": {
		"follow": "Follow link",
		"copy": "Copy link"
	},
	"edit": {
		"delete": "Delete",
		"move_first": "Move first",
		"move_last": "Move last",
		"move_up": "Move up",
		"move_down": "Move down",
		"cut": "Cut",
		"copy": "Copy",
		"paste": "Paste"
	},
	"confirm": {
		"yes": "Yes",
		"no": "No"
	},
	"ok": "OK"
}
```

The string `Open dialog` from the localization data can be accessed in the toolkit by specifying
path `actions.dlg.open`. Additionally, there is a way to manage access to the localization data
in case when bundles are organized in some other way or stored as built-in into application resources.


## Example

```C++

#include <stdio.h>
#include <lsp-plug.in/tk/tk.h>

// Handle the window close request event
static lsp::status_t slot_close(lsp::tk::Widget *sender, void *ptr, void *data)
{
    // Obtain the display and leave the main loop
    sender->display()->quit_main();
    return lsp::STATUS_OK;
}

// Handle the key release event
static lsp::status_t slot_key_up(lsp::tk::Widget *sender, void *ptr, void *data)
{
    // Obtain the toplevel widget (window)
    lsp::tk::Window *wnd = lsp::tk::widget_cast<lsp::tk::Window>(sender->toplevel());
    lsp::ws::event_t *ev = static_cast<lsp::ws::event_t *>(data);

    if ((wnd != NULL) && (ev != NULL) && (ev->nType == lsp::ws::UIE_KEY_UP))
    {
        printf("Key up: %c (0x%x)\n", (char)ev->nCode, int(ev->nCode));

        // Get current scaling
        float scaling = wnd->style()->schema()->scaling()->get();

        // Change the scaling
        switch (ev->nCode)
        {
            case '+':
            case lsp::ws::WSK_KEYPAD_ADD:
                scaling     = lsp::lsp_max(0.25f, scaling + 0.25f);
                break;
            case '-':
            case lsp::ws::WSK_KEYPAD_SUBTRACT:
                scaling     = lsp::lsp_max(0.25f, scaling - 0.25f);
                break;
            default:
                break;
        }

        // Update scaling of the window
        wnd->style()->schema()->scaling()->set(scaling);
    }
    return lsp::STATUS_OK;
}

static lsp::status_t slot_ok_submitted(lsp::tk::Widget *sender, void *ptr, void *data)
{
    // Avoid widget destroy in event handlers,
    // query widget for removal at the end of main loop iteration
    lsp::tk::MessageBox *mbox = lsp::tk::widget_ptrcast<lsp::tk::MessageBox>(ptr);
    mbox->display()->queue_destroy(mbox);
    return lsp::STATUS_OK;
}

static lsp::status_t slot_btn_submit(lsp::tk::Widget *sender, void *ptr, void *data)
{
    // Create message box
    lsp::tk::MessageBox *mbox = new lsp::tk::MessageBox(sender->display());
    mbox->init();
    mbox->title()->set("Message");
    mbox->heading()->set_raw("Information");
    mbox->message()->set("Button has been clicked");
    mbox->add("OK", slot_ok_submitted, mbox);
    mbox->button_layout()->set_halign(1.0f);

    mbox->button_constraints()->set_fixed(64, 16);

    mbox->show(sender);
    return lsp::STATUS_OK;
}

int main(int argc, const char *argv[])
{
    // Initialize the tookit
    lsp::tk::init(0, NULL);

    // Create the display
    lsp::tk::Display *dpy = new lsp::tk::Display();

    // Initialize the display
    if (dpy->init(0, NULL) != lsp::STATUS_OK)
        return -1;

    // Create widgets
    lsp::tk::Window *wnd     = new lsp::tk::Window(dpy);
    lsp::tk::Box *box        = new lsp::tk::Box(dpy);
    lsp::tk::Label *label    = new lsp::tk::Label(dpy);
    lsp::tk::Button *btn     = new lsp::tk::Button(dpy);

    // Initialize widgets
    wnd->init();
    box->init();
    label->init();
    btn->init();

    // Initialize widgets
    wnd->title()->set_raw("Example window");
    wnd->role()->set_raw("example-window");
    wnd->bg_color()->set_rgb(0.75f, 1.0f, 1.0f);
    wnd->actions()->set_actions(lsp::ws::WA_MOVE | lsp::ws::WA_RESIZE | lsp::ws::WA_CLOSE);
    wnd->border_style()->set(lsp::ws::BS_DIALOG);
    wnd->constraints()->set(160, 100, 640, 400);
    wnd->size()->set(320, 200);
    wnd->pointer()->set(lsp::ws::MP_TABLE_CELL);
    wnd->layout()->set(0.0f, 0.0f, 1.0f, 1.0f);
    wnd->padding()->set(16);

    box->orientation()->set(lsp::tk::O_VERTICAL);
    box->spacing()->set(4);

    label->font()->set_size(16.0f);
    label->font()->set_bold(true);
    label->text()->set_raw("Example\nLabel");
    label->allocation()->set_vexpand(true);

    btn->text()->set("Button");
    btn->color()->set("#008800");
    btn->text_color()->set("#ffff00");
    btn->constraints()->set(96, 24, 96, -1);

    // Initialize widget structure
    wnd->add(box);
    box->add(label);
    box->add(btn);

    // Initialize event handlers
    wnd->slot(lsp::tk::SLOT_CLOSE)->bind(slot_close, NULL);
    wnd->slot(lsp::tk::SLOT_KEY_UP)->bind(slot_key_up, NULL);
    btn->slot(lsp::tk::SLOT_KEY_UP)->bind(slot_key_up, NULL);
    label->slot(lsp::tk::SLOT_KEY_UP)->bind(slot_key_up, NULL);
    box->slot(lsp::tk::SLOT_KEY_UP)->bind(slot_key_up, NULL);
    btn->slot(lsp::tk::SLOT_SUBMIT)->bind(slot_btn_submit, NULL);

    // Show window at the center of screen
    ssize_t sw = 0, sh = 0;
    lsp::ws::rectangle_t wsz;
    dpy->screen_size(0, &sw, &sh);
    wnd->size()->compute(&wsz, wnd->scaling()->get());
    wnd->position()->set((sw - wsz.nWidth)/2, (sh - wsz.nHeight)/2);
    wnd->visibility()->set(true);

    // Enter the main event loop
    dpy->main();

    // Destroy widgets
    btn->destroy();
    label->destroy();
    box->destroy();
    wnd->destroy();

    // Delete widget objects
    delete btn;
    delete label;
    delete box;
    delete wnd;

    // Destroy display
    dpy->destroy();
    delete dpy;

    return 0;
}

```

The result of this example:

![Indicator widget](res/doc/example.png)

![Indicator widget](res/doc/example-msg.png)

## SAST Tools

* [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.