bare-gtk 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +16 -2
- package/README.md +35 -1
- package/binding.c +350 -1
- package/index.d.ts +65 -0
- package/index.js +32 -0
- package/lib/adjustment.d.ts +21 -0
- package/lib/adjustment.h +112 -0
- package/lib/adjustment.js +24 -0
- package/lib/bridging.h +347 -0
- package/lib/clipboard.d.ts +22 -0
- package/lib/clipboard.h +176 -0
- package/lib/clipboard.js +18 -0
- package/lib/constants.d.ts +40 -0
- package/lib/constants.js +51 -0
- package/lib/css-provider.d.ts +13 -0
- package/lib/css-provider.h +56 -0
- package/lib/css-provider.js +14 -0
- package/lib/cursor.d.ts +35 -0
- package/lib/cursor.h +220 -0
- package/lib/cursor.js +45 -0
- package/lib/device.d.ts +13 -0
- package/lib/device.h +35 -0
- package/lib/device.js +8 -0
- package/lib/dialog.d.ts +41 -0
- package/lib/dialog.js +37 -0
- package/lib/display.d.ts +25 -0
- package/lib/display.h +86 -0
- package/lib/display.js +23 -0
- package/lib/editable.h +160 -0
- package/lib/entry.d.ts +93 -0
- package/lib/entry.h +340 -0
- package/lib/entry.js +118 -0
- package/lib/event-controller-focus.d.ts +17 -0
- package/lib/event-controller-focus.h +55 -0
- package/lib/event-controller-focus.js +13 -0
- package/lib/event-controller-motion.d.ts +18 -0
- package/lib/event-controller-motion.h +66 -0
- package/lib/event-controller-motion.js +14 -0
- package/lib/event-controller.d.ts +17 -0
- package/lib/event-controller.h +103 -0
- package/lib/event-controller.js +22 -0
- package/lib/events.js +23 -0
- package/lib/fixed.d.ts +10 -0
- package/lib/fixed.h +28 -0
- package/lib/fixed.js +8 -0
- package/lib/frame-fixed.d.ts +10 -0
- package/lib/frame-fixed.js +12 -0
- package/lib/frame-layout-child.d.ts +17 -0
- package/lib/frame-layout-child.js +16 -0
- package/lib/frame-layout.d.ts +27 -0
- package/lib/frame-layout.h +291 -0
- package/lib/frame-layout.js +19 -0
- package/lib/gesture-click.d.ts +19 -0
- package/lib/gesture-click.h +66 -0
- package/lib/gesture-click.js +14 -0
- package/lib/gesture-drag.d.ts +25 -0
- package/lib/gesture-drag.h +165 -0
- package/lib/gesture-drag.js +23 -0
- package/lib/gesture-single.d.ts +13 -0
- package/lib/gesture-single.js +12 -0
- package/lib/gesture.d.ts +13 -0
- package/lib/gesture.h +73 -0
- package/lib/gesture.js +8 -0
- package/lib/handle.d.ts +5 -0
- package/lib/handle.js +6 -0
- package/lib/label.d.ts +36 -0
- package/lib/label.h +269 -0
- package/lib/label.js +78 -0
- package/lib/layout-child.d.ts +13 -0
- package/lib/layout-child.h +35 -0
- package/lib/layout-child.js +10 -0
- package/lib/layout-manager.d.ts +15 -0
- package/lib/layout-manager.h +42 -0
- package/lib/layout-manager.js +15 -0
- package/lib/message-dialog.d.ts +26 -0
- package/lib/message-dialog.h +190 -0
- package/lib/message-dialog.js +22 -0
- package/lib/monitor.d.ts +32 -0
- package/lib/monitor.h +143 -0
- package/lib/monitor.js +40 -0
- package/lib/native.h +31 -0
- package/lib/object.d.ts +18 -0
- package/lib/object.js +38 -0
- package/lib/paintable.d.ts +10 -0
- package/lib/paintable.js +3 -0
- package/lib/picture.d.ts +22 -0
- package/lib/picture.h +127 -0
- package/lib/picture.js +35 -0
- package/lib/reachable.js +11 -0
- package/lib/runtime.c +21 -4
- package/lib/scrolled-window.d.ts +22 -0
- package/lib/scrolled-window.h +142 -0
- package/lib/scrolled-window.js +37 -0
- package/lib/settings.d.ts +25 -0
- package/lib/settings.h +163 -0
- package/lib/settings.js +34 -0
- package/lib/spinner.d.ts +12 -0
- package/lib/spinner.h +61 -0
- package/lib/spinner.js +22 -0
- package/lib/style-context.d.ts +15 -0
- package/lib/style-context.h +67 -0
- package/lib/style-context.js +9 -0
- package/lib/surface.d.ts +19 -0
- package/lib/surface.h +61 -0
- package/lib/surface.js +22 -0
- package/lib/switch.d.ts +19 -0
- package/lib/switch.h +114 -0
- package/lib/switch.js +30 -0
- package/lib/text-buffer.d.ts +31 -0
- package/lib/text-buffer.h +246 -0
- package/lib/text-buffer.js +33 -0
- package/lib/text-view.d.ts +39 -0
- package/lib/text-view.h +247 -0
- package/lib/text-view.js +63 -0
- package/lib/text.d.ts +18 -0
- package/lib/text.h +189 -0
- package/lib/text.js +31 -0
- package/lib/texture.d.ts +20 -0
- package/lib/texture.h +100 -0
- package/lib/texture.js +17 -0
- package/lib/viewport.d.ts +22 -0
- package/lib/viewport.h +151 -0
- package/lib/viewport.js +38 -0
- package/lib/widget.d.ts +102 -0
- package/lib/widget.h +695 -17
- package/lib/widget.js +176 -11
- package/lib/window.d.ts +31 -0
- package/lib/window.h +142 -61
- package/lib/window.js +32 -11
- package/lib/wrap.js +7 -0
- package/package.json +12 -3
- package/prebuilds/linux-arm64/bare +2 -2
- package/prebuilds/linux-arm64/bare-gtk.bare +0 -0
- package/prebuilds/linux-x64/bare +2 -2
- package/prebuilds/linux-x64/bare-gtk.bare +0 -0
package/lib/text-view.h
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
#ifndef BARE_GTK_TEXT_VIEW_H
|
|
2
|
+
#define BARE_GTK_TEXT_VIEW_H
|
|
3
|
+
|
|
4
|
+
#include <assert.h>
|
|
5
|
+
#include <js.h>
|
|
6
|
+
#include <utf.h>
|
|
7
|
+
|
|
8
|
+
#include <gtk/gtk.h>
|
|
9
|
+
|
|
10
|
+
#include "bridging.h"
|
|
11
|
+
|
|
12
|
+
enum {
|
|
13
|
+
bare_gtk_text_view_event_has_focus = 1 << 0,
|
|
14
|
+
bare_gtk_text_view_event_is_focus = 1 << 1,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
typedef struct {
|
|
18
|
+
GtkTextView handle;
|
|
19
|
+
|
|
20
|
+
bare_gtk_state_t *state;
|
|
21
|
+
|
|
22
|
+
uint32_t events;
|
|
23
|
+
|
|
24
|
+
gulong on_has_focus;
|
|
25
|
+
gulong on_is_focus;
|
|
26
|
+
} BareTextView;
|
|
27
|
+
|
|
28
|
+
typedef struct {
|
|
29
|
+
GtkTextViewClass parent;
|
|
30
|
+
} BareTextViewClass;
|
|
31
|
+
|
|
32
|
+
G_DEFINE_TYPE(BareTextView, bare_text_view, GTK_TYPE_TEXT_VIEW)
|
|
33
|
+
|
|
34
|
+
static void
|
|
35
|
+
bare_text_view_init(BareTextView *self) {}
|
|
36
|
+
|
|
37
|
+
static void
|
|
38
|
+
bare_text_view_class_init(BareTextViewClass *class) {}
|
|
39
|
+
|
|
40
|
+
BareTextView *
|
|
41
|
+
bare_text_view_new(void) {
|
|
42
|
+
return g_object_new(bare_text_view_get_type(), NULL);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static void
|
|
46
|
+
bare_gtk_text_view__on_has_focus(GObject *object, GParamSpec *spec, gpointer data) {
|
|
47
|
+
BareTextView *self = (BareTextView *) object;
|
|
48
|
+
|
|
49
|
+
bare_gtk__emit(self->state, object, "has-focus", 1, (const double[]) {gtk_widget_has_focus(GTK_WIDGET(object)) ? 1 : 0});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Whether this is the focus widget of its window, which is not the same as
|
|
53
|
+
// having the keyboard.
|
|
54
|
+
static void
|
|
55
|
+
bare_gtk_text_view__on_is_focus(GObject *object, GParamSpec *spec, gpointer data) {
|
|
56
|
+
BareTextView *self = (BareTextView *) object;
|
|
57
|
+
|
|
58
|
+
bare_gtk__emit(self->state, object, "is-focus", 1, (const double[]) {gtk_widget_is_focus(GTK_WIDGET(object)) ? 1 : 0});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static js_value_t *
|
|
62
|
+
bare_gtk_text_view_init(js_env_t *env, js_callback_info_t *info) {
|
|
63
|
+
int err;
|
|
64
|
+
|
|
65
|
+
bare_gtk_state_t *state;
|
|
66
|
+
err = js_get_callback_info(env, info, NULL, NULL, NULL, (void **) &state);
|
|
67
|
+
assert(err == 0);
|
|
68
|
+
|
|
69
|
+
BareTextView *view = bare_text_view_new();
|
|
70
|
+
|
|
71
|
+
view->state = state;
|
|
72
|
+
|
|
73
|
+
js_value_t *result;
|
|
74
|
+
err = js_create_uint32(env, bare_gobject_tag(state->registry, view), &result);
|
|
75
|
+
assert(err == 0);
|
|
76
|
+
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static js_value_t *
|
|
81
|
+
bare_gtk_text_view_event_mask(js_env_t *env, js_callback_info_t *info) {
|
|
82
|
+
int err;
|
|
83
|
+
|
|
84
|
+
size_t argc = 2;
|
|
85
|
+
js_value_t *argv[2];
|
|
86
|
+
|
|
87
|
+
bare_gtk_state_t *state;
|
|
88
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
89
|
+
assert(err == 0);
|
|
90
|
+
|
|
91
|
+
assert(argc == 2);
|
|
92
|
+
|
|
93
|
+
BareTextView *view;
|
|
94
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "textView", (gpointer *) &view);
|
|
95
|
+
if (err < 0) return NULL;
|
|
96
|
+
|
|
97
|
+
uint32_t events;
|
|
98
|
+
err = bare_gtk__read_uint32(env, argv[1], "events", &events);
|
|
99
|
+
if (err < 0) return NULL;
|
|
100
|
+
|
|
101
|
+
uint32_t changed = view->events ^ events;
|
|
102
|
+
|
|
103
|
+
view->events = events;
|
|
104
|
+
|
|
105
|
+
#define V(bit, field, signal, callback) \
|
|
106
|
+
if ((changed & (bit)) != 0) { \
|
|
107
|
+
if ((events & (bit)) != 0) { \
|
|
108
|
+
view->field = g_signal_connect(view, signal, G_CALLBACK(callback), state); \
|
|
109
|
+
} else { \
|
|
110
|
+
g_signal_handler_disconnect(view, view->field); \
|
|
111
|
+
} \
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
V(bare_gtk_text_view_event_has_focus, on_has_focus, "notify::has-focus", bare_gtk_text_view__on_has_focus)
|
|
115
|
+
V(bare_gtk_text_view_event_is_focus, on_is_focus, "notify::is-focus", bare_gtk_text_view__on_is_focus)
|
|
116
|
+
#undef V
|
|
117
|
+
|
|
118
|
+
return NULL;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static js_value_t *
|
|
122
|
+
bare_gtk_text_view_buffer(js_env_t *env, js_callback_info_t *info) {
|
|
123
|
+
int err;
|
|
124
|
+
|
|
125
|
+
size_t argc = 1;
|
|
126
|
+
js_value_t *argv[1];
|
|
127
|
+
|
|
128
|
+
bare_gtk_state_t *state;
|
|
129
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
130
|
+
assert(err == 0);
|
|
131
|
+
|
|
132
|
+
assert(argc == 1);
|
|
133
|
+
|
|
134
|
+
GtkTextView *view;
|
|
135
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "textView", (gpointer *) &view);
|
|
136
|
+
if (err < 0) return NULL;
|
|
137
|
+
|
|
138
|
+
return bare_gtk__create_tag(env, state, gtk_text_view_get_buffer(view));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static js_value_t *
|
|
142
|
+
bare_gtk_text_view_editable(js_env_t *env, js_callback_info_t *info) {
|
|
143
|
+
int err;
|
|
144
|
+
|
|
145
|
+
size_t argc = 2;
|
|
146
|
+
js_value_t *argv[2];
|
|
147
|
+
|
|
148
|
+
bare_gtk_state_t *state;
|
|
149
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
150
|
+
assert(err == 0);
|
|
151
|
+
|
|
152
|
+
assert(argc == 1 || argc == 2);
|
|
153
|
+
|
|
154
|
+
GtkTextView *view;
|
|
155
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "textView", (gpointer *) &view);
|
|
156
|
+
if (err < 0) return NULL;
|
|
157
|
+
|
|
158
|
+
js_value_t *result = NULL;
|
|
159
|
+
|
|
160
|
+
if (argc == 1) {
|
|
161
|
+
err = js_get_boolean(env, gtk_text_view_get_editable(view), &result);
|
|
162
|
+
assert(err == 0);
|
|
163
|
+
} else {
|
|
164
|
+
bool editable;
|
|
165
|
+
err = bare_gtk__read_bool(env, argv[1], "editable", &editable);
|
|
166
|
+
if (err < 0) return NULL;
|
|
167
|
+
|
|
168
|
+
gtk_text_view_set_editable(view, editable);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
#define BARE_GTK_TEXT_VIEW_ENUM(name, getter, setter, type) \
|
|
175
|
+
static js_value_t * \
|
|
176
|
+
bare_gtk_text_view_##name(js_env_t *env, js_callback_info_t *info) { \
|
|
177
|
+
int err; \
|
|
178
|
+
\
|
|
179
|
+
size_t argc = 2; \
|
|
180
|
+
js_value_t *argv[2]; \
|
|
181
|
+
\
|
|
182
|
+
bare_gtk_state_t *state; \
|
|
183
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state); \
|
|
184
|
+
assert(err == 0); \
|
|
185
|
+
\
|
|
186
|
+
assert(argc == 1 || argc == 2); \
|
|
187
|
+
\
|
|
188
|
+
GtkTextView *view; \
|
|
189
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "textView", (gpointer *) &view); \
|
|
190
|
+
if (err < 0) return NULL; \
|
|
191
|
+
\
|
|
192
|
+
js_value_t *result = NULL; \
|
|
193
|
+
\
|
|
194
|
+
if (argc == 1) { \
|
|
195
|
+
err = js_create_int32(env, (int32_t) getter(view), &result); \
|
|
196
|
+
assert(err == 0); \
|
|
197
|
+
} else { \
|
|
198
|
+
int32_t value; \
|
|
199
|
+
err = bare_gtk__read_int32(env, argv[1], #name, &value); \
|
|
200
|
+
if (err < 0) return NULL; \
|
|
201
|
+
\
|
|
202
|
+
setter(view, (type) value); \
|
|
203
|
+
} \
|
|
204
|
+
\
|
|
205
|
+
return result; \
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
BARE_GTK_TEXT_VIEW_ENUM(wrap_mode, gtk_text_view_get_wrap_mode, gtk_text_view_set_wrap_mode, GtkWrapMode)
|
|
209
|
+
BARE_GTK_TEXT_VIEW_ENUM(input_purpose, gtk_text_view_get_input_purpose, gtk_text_view_set_input_purpose, GtkInputPurpose)
|
|
210
|
+
BARE_GTK_TEXT_VIEW_ENUM(input_hints, gtk_text_view_get_input_hints, gtk_text_view_set_input_hints, GtkInputHints)
|
|
211
|
+
#undef BARE_GTK_TEXT_VIEW_ENUM
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
static js_value_t *
|
|
215
|
+
bare_gtk_text_view_justification(js_env_t *env, js_callback_info_t *info) {
|
|
216
|
+
int err;
|
|
217
|
+
|
|
218
|
+
size_t argc = 2;
|
|
219
|
+
js_value_t *argv[2];
|
|
220
|
+
|
|
221
|
+
bare_gtk_state_t *state;
|
|
222
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
223
|
+
assert(err == 0);
|
|
224
|
+
|
|
225
|
+
assert(argc == 1 || argc == 2);
|
|
226
|
+
|
|
227
|
+
GtkTextView *text_view;
|
|
228
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "textView", (gpointer *) &text_view);
|
|
229
|
+
if (err < 0) return NULL;
|
|
230
|
+
|
|
231
|
+
js_value_t *result = NULL;
|
|
232
|
+
|
|
233
|
+
if (argc == 1) {
|
|
234
|
+
err = js_create_int32(env, gtk_text_view_get_justification(text_view), &result);
|
|
235
|
+
assert(err == 0);
|
|
236
|
+
} else {
|
|
237
|
+
int32_t justification;
|
|
238
|
+
err = bare_gtk__read_int32(env, argv[1], "justification", &justification);
|
|
239
|
+
if (err < 0) return NULL;
|
|
240
|
+
|
|
241
|
+
gtk_text_view_set_justification(text_view, justification);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
#endif // BARE_GTK_TEXT_VIEW_H
|
package/lib/text-view.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const binding = require('../binding')
|
|
2
|
+
const wrap = require('./wrap')
|
|
3
|
+
const GTKTextBuffer = require('./text-buffer')
|
|
4
|
+
const GTKWidget = require('./widget')
|
|
5
|
+
|
|
6
|
+
module.exports = exports = class GTKTextView extends GTKWidget {
|
|
7
|
+
static _events = {
|
|
8
|
+
'has-focus': binding.TEXT_VIEW_EVENT_HAS_FOCUS,
|
|
9
|
+
'is-focus': binding.TEXT_VIEW_EVENT_IS_FOCUS
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_init(opts) {
|
|
13
|
+
return binding.textViewInit()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
_eventMask(mask) {
|
|
17
|
+
binding.textViewEventMask(this._tag, mask)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get buffer() {
|
|
21
|
+
return wrap(GTKTextBuffer, binding.textViewBuffer(this._tag))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get editable() {
|
|
25
|
+
return binding.textViewEditable(this._tag)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set editable(value) {
|
|
29
|
+
binding.textViewEditable(this._tag, value)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get wrapMode() {
|
|
33
|
+
return binding.textViewWrapMode(this._tag)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set wrapMode(value) {
|
|
37
|
+
binding.textViewWrapMode(this._tag, value)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get inputPurpose() {
|
|
41
|
+
return binding.textViewInputPurpose(this._tag)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set inputPurpose(value) {
|
|
45
|
+
binding.textViewInputPurpose(this._tag, value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get inputHints() {
|
|
49
|
+
return binding.textViewInputHints(this._tag)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
set inputHints(value) {
|
|
53
|
+
binding.textViewInputHints(this._tag, value)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get justification() {
|
|
57
|
+
return binding.textViewJustification(this._tag)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
set justification(value) {
|
|
61
|
+
binding.textViewJustification(this._tag, value)
|
|
62
|
+
}
|
|
63
|
+
}
|
package/lib/text.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Measurement {
|
|
2
|
+
width: number
|
|
3
|
+
height: number
|
|
4
|
+
lines: number
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Measure `text` as a label would show it, wrapped at `width` pixels, which defaults to
|
|
9
|
+
* `Infinity`. `style.size` is in pixels, and 0 means the default size. Results are cached.
|
|
10
|
+
*/
|
|
11
|
+
export function measure(
|
|
12
|
+
text: string,
|
|
13
|
+
style?: { family?: string | null; size?: number },
|
|
14
|
+
width?: number
|
|
15
|
+
): Measurement
|
|
16
|
+
|
|
17
|
+
/** Measure Pango markup as a label would show it, wrapped at `width` pixels. */
|
|
18
|
+
export function measureMarkup(markup: string, width?: number): Measurement
|
package/lib/text.h
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#ifndef BARE_GTK_TEXT_H
|
|
2
|
+
#define BARE_GTK_TEXT_H
|
|
3
|
+
|
|
4
|
+
#include <assert.h>
|
|
5
|
+
#include <js.h>
|
|
6
|
+
#include <math.h>
|
|
7
|
+
|
|
8
|
+
#include <gtk/gtk.h>
|
|
9
|
+
|
|
10
|
+
#include "bridging.h"
|
|
11
|
+
|
|
12
|
+
static PangoContext *
|
|
13
|
+
bare_gtk_text__context(bare_gtk_state_t *state) {
|
|
14
|
+
if (state->text_probe) return gtk_widget_get_pango_context(state->text_probe);
|
|
15
|
+
|
|
16
|
+
state->text_probe = g_object_ref_sink(gtk_label_new("Mg"));
|
|
17
|
+
|
|
18
|
+
PangoContext *context = gtk_widget_get_pango_context(state->text_probe);
|
|
19
|
+
|
|
20
|
+
PangoLayout *layout = pango_layout_new(context);
|
|
21
|
+
pango_layout_set_text(layout, "Mg", -1);
|
|
22
|
+
|
|
23
|
+
int width, height;
|
|
24
|
+
pango_layout_get_pixel_size(layout, &width, &height);
|
|
25
|
+
|
|
26
|
+
g_object_unref(layout);
|
|
27
|
+
|
|
28
|
+
int minimum, natural;
|
|
29
|
+
|
|
30
|
+
gtk_widget_measure(state->text_probe, GTK_ORIENTATION_HORIZONTAL, -1, &minimum, &natural, NULL, NULL);
|
|
31
|
+
state->text_inset_width = natural - width;
|
|
32
|
+
|
|
33
|
+
gtk_widget_measure(state->text_probe, GTK_ORIENTATION_VERTICAL, -1, &minimum, &natural, NULL, NULL);
|
|
34
|
+
state->text_inset_height = natural - height;
|
|
35
|
+
|
|
36
|
+
return context;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static js_value_t *
|
|
40
|
+
bare_gtk_text_measure(js_env_t *env, js_callback_info_t *info) {
|
|
41
|
+
int err;
|
|
42
|
+
|
|
43
|
+
size_t argc = 4;
|
|
44
|
+
js_value_t *argv[4];
|
|
45
|
+
|
|
46
|
+
bare_gtk_state_t *state;
|
|
47
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
48
|
+
assert(err == 0);
|
|
49
|
+
|
|
50
|
+
assert(argc == 4);
|
|
51
|
+
|
|
52
|
+
g_autofree char *text = NULL;
|
|
53
|
+
err = bare_gtk__read_string(env, argv[0], "text", &text);
|
|
54
|
+
if (err < 0) return NULL;
|
|
55
|
+
|
|
56
|
+
g_autofree char *family = NULL;
|
|
57
|
+
err = bare_gtk__read_string_or_null(env, argv[1], "family", &family);
|
|
58
|
+
if (err < 0) return NULL;
|
|
59
|
+
|
|
60
|
+
double size;
|
|
61
|
+
err = bare_gtk__read_double(env, argv[2], "size", &size);
|
|
62
|
+
if (err < 0) return NULL;
|
|
63
|
+
|
|
64
|
+
double available;
|
|
65
|
+
err = bare_gtk__read_double(env, argv[3], "width", &available);
|
|
66
|
+
if (err < 0) return NULL;
|
|
67
|
+
|
|
68
|
+
PangoContext *context = bare_gtk_text__context(state);
|
|
69
|
+
|
|
70
|
+
PangoLayout *layout = pango_layout_new(context);
|
|
71
|
+
|
|
72
|
+
pango_layout_set_text(layout, text, -1);
|
|
73
|
+
|
|
74
|
+
if (family || size > 0) {
|
|
75
|
+
PangoFontDescription *font = pango_font_description_copy(pango_context_get_font_description(context));
|
|
76
|
+
|
|
77
|
+
if (family) pango_font_description_set_family(font, family);
|
|
78
|
+
|
|
79
|
+
// Absolute, so the size is in device pixels and not scaled by the context
|
|
80
|
+
// resolution. A label matches this with a CSS font size in px.
|
|
81
|
+
if (size > 0) pango_font_description_set_absolute_size(font, size * PANGO_SCALE);
|
|
82
|
+
|
|
83
|
+
pango_layout_set_font_description(layout, font);
|
|
84
|
+
|
|
85
|
+
pango_font_description_free(font);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
|
89
|
+
|
|
90
|
+
pango_layout_set_width(
|
|
91
|
+
layout,
|
|
92
|
+
isfinite(available) && available >= 0 && available < (double) (G_MAXINT / PANGO_SCALE)
|
|
93
|
+
? (int) (available * PANGO_SCALE)
|
|
94
|
+
: -1
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
int width, height;
|
|
98
|
+
pango_layout_get_pixel_size(layout, &width, &height);
|
|
99
|
+
|
|
100
|
+
int lines = pango_layout_get_line_count(layout);
|
|
101
|
+
|
|
102
|
+
g_object_unref(layout);
|
|
103
|
+
|
|
104
|
+
js_value_t *result;
|
|
105
|
+
err = js_create_array_with_length(env, 3, &result);
|
|
106
|
+
assert(err == 0);
|
|
107
|
+
|
|
108
|
+
#define V(i, d) \
|
|
109
|
+
{ \
|
|
110
|
+
js_value_t *val; \
|
|
111
|
+
err = js_create_double(env, d, &val); \
|
|
112
|
+
assert(err == 0); \
|
|
113
|
+
err = js_set_element(env, result, i, val); \
|
|
114
|
+
assert(err == 0); \
|
|
115
|
+
}
|
|
116
|
+
V(0, width + state->text_inset_width)
|
|
117
|
+
V(1, height + state->text_inset_height)
|
|
118
|
+
V(2, lines)
|
|
119
|
+
#undef V
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Measured from the same markup a label is given, so both use one font
|
|
125
|
+
// description.
|
|
126
|
+
static js_value_t *
|
|
127
|
+
bare_gtk_text_measure_markup(js_env_t *env, js_callback_info_t *info) {
|
|
128
|
+
int err;
|
|
129
|
+
|
|
130
|
+
size_t argc = 2;
|
|
131
|
+
js_value_t *argv[2];
|
|
132
|
+
|
|
133
|
+
bare_gtk_state_t *state;
|
|
134
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
135
|
+
assert(err == 0);
|
|
136
|
+
|
|
137
|
+
assert(argc == 2);
|
|
138
|
+
|
|
139
|
+
g_autofree char *markup = NULL;
|
|
140
|
+
err = bare_gtk__read_string(env, argv[0], "markup", &markup);
|
|
141
|
+
if (err < 0) return NULL;
|
|
142
|
+
|
|
143
|
+
double available;
|
|
144
|
+
err = bare_gtk__read_double(env, argv[1], "width", &available);
|
|
145
|
+
if (err < 0) return NULL;
|
|
146
|
+
|
|
147
|
+
PangoContext *context = bare_gtk_text__context(state);
|
|
148
|
+
|
|
149
|
+
PangoLayout *layout = pango_layout_new(context);
|
|
150
|
+
|
|
151
|
+
pango_layout_set_markup(layout, markup, -1);
|
|
152
|
+
|
|
153
|
+
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
|
|
154
|
+
|
|
155
|
+
pango_layout_set_width(
|
|
156
|
+
layout,
|
|
157
|
+
isfinite(available) && available >= 0 && available < (double) (G_MAXINT / PANGO_SCALE)
|
|
158
|
+
? (int) (available * PANGO_SCALE)
|
|
159
|
+
: -1
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
int width, height;
|
|
163
|
+
pango_layout_get_pixel_size(layout, &width, &height);
|
|
164
|
+
|
|
165
|
+
int lines = pango_layout_get_line_count(layout);
|
|
166
|
+
|
|
167
|
+
g_object_unref(layout);
|
|
168
|
+
|
|
169
|
+
js_value_t *result;
|
|
170
|
+
err = js_create_array_with_length(env, 3, &result);
|
|
171
|
+
assert(err == 0);
|
|
172
|
+
|
|
173
|
+
#define V(i, d) \
|
|
174
|
+
{ \
|
|
175
|
+
js_value_t *val; \
|
|
176
|
+
err = js_create_double(env, d, &val); \
|
|
177
|
+
assert(err == 0); \
|
|
178
|
+
err = js_set_element(env, result, i, val); \
|
|
179
|
+
assert(err == 0); \
|
|
180
|
+
}
|
|
181
|
+
V(0, width + state->text_inset_width)
|
|
182
|
+
V(1, height + state->text_inset_height)
|
|
183
|
+
V(2, lines)
|
|
184
|
+
#undef V
|
|
185
|
+
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
#endif // BARE_GTK_TEXT_H
|
package/lib/text.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const binding = require('../binding')
|
|
2
|
+
|
|
3
|
+
const cache = new Map()
|
|
4
|
+
|
|
5
|
+
const CACHE_LIMIT = 4096
|
|
6
|
+
|
|
7
|
+
exports.measure = function measure(text, style = {}, width = Infinity) {
|
|
8
|
+
const { family = null, size = 0 } = style
|
|
9
|
+
|
|
10
|
+
const key = `${family}\u0000${size}\u0000${width}\u0000${text}`
|
|
11
|
+
|
|
12
|
+
let result = cache.get(key)
|
|
13
|
+
|
|
14
|
+
if (result === undefined) {
|
|
15
|
+
const [w, h, lines] = binding.textMeasure(text, family, size, width)
|
|
16
|
+
|
|
17
|
+
if (cache.size === CACHE_LIMIT) cache.delete(cache.keys().next().value)
|
|
18
|
+
|
|
19
|
+
cache.set(key, (result = { width: w, height: h, lines }))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return result
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Not cached, because the markup carries its own style and there is nothing to
|
|
26
|
+
// share a cache on.
|
|
27
|
+
exports.measureMarkup = function measureMarkup(markup, width = Infinity) {
|
|
28
|
+
const [w, h, lines] = binding.textMeasureMarkup(markup, width)
|
|
29
|
+
|
|
30
|
+
return { width: w, height: h, lines }
|
|
31
|
+
}
|
package/lib/texture.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import GDKPaintable = require('./paintable')
|
|
2
|
+
|
|
3
|
+
/** An image in memory, as a `GdkTexture`. */
|
|
4
|
+
interface GDKTexture extends GDKPaintable {
|
|
5
|
+
readonly width: number
|
|
6
|
+
|
|
7
|
+
readonly height: number
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare class GDKTexture {
|
|
11
|
+
protected constructor()
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load an image file.
|
|
15
|
+
* @throws When the file cannot be read or is not an image.
|
|
16
|
+
*/
|
|
17
|
+
static newFromFilename(path: string): GDKTexture
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export = GDKTexture
|
package/lib/texture.h
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#ifndef BARE_GTK_TEXTURE_H
|
|
2
|
+
#define BARE_GTK_TEXTURE_H
|
|
3
|
+
|
|
4
|
+
#include <assert.h>
|
|
5
|
+
#include <js.h>
|
|
6
|
+
#include <utf.h>
|
|
7
|
+
|
|
8
|
+
#include <gtk/gtk.h>
|
|
9
|
+
|
|
10
|
+
#include "bridging.h"
|
|
11
|
+
|
|
12
|
+
// A new texture is not floating, so the registry takes its own reference and
|
|
13
|
+
// the one from this call is dropped.
|
|
14
|
+
static js_value_t *
|
|
15
|
+
bare_gtk_texture_new_from_filename(js_env_t *env, js_callback_info_t *info) {
|
|
16
|
+
int err;
|
|
17
|
+
|
|
18
|
+
size_t argc = 1;
|
|
19
|
+
js_value_t *argv[1];
|
|
20
|
+
|
|
21
|
+
bare_gtk_state_t *state;
|
|
22
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
23
|
+
assert(err == 0);
|
|
24
|
+
|
|
25
|
+
assert(argc == 1);
|
|
26
|
+
|
|
27
|
+
char *path;
|
|
28
|
+
err = bare_gtk__read_string(env, argv[0], "path", &path);
|
|
29
|
+
if (err < 0) return NULL;
|
|
30
|
+
|
|
31
|
+
GError *error = NULL;
|
|
32
|
+
|
|
33
|
+
GdkTexture *texture = gdk_texture_new_from_filename(path, &error);
|
|
34
|
+
|
|
35
|
+
g_free(path);
|
|
36
|
+
|
|
37
|
+
if (texture == NULL) {
|
|
38
|
+
bare_gtk__throw(env, error);
|
|
39
|
+
|
|
40
|
+
return NULL;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
js_value_t *result;
|
|
44
|
+
err = js_create_uint32(env, bare_gobject_tag(state->registry, texture), &result);
|
|
45
|
+
assert(err == 0);
|
|
46
|
+
|
|
47
|
+
g_object_unref(texture);
|
|
48
|
+
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static js_value_t *
|
|
53
|
+
bare_gtk_texture_width(js_env_t *env, js_callback_info_t *info) {
|
|
54
|
+
int err;
|
|
55
|
+
|
|
56
|
+
size_t argc = 1;
|
|
57
|
+
js_value_t *argv[1];
|
|
58
|
+
|
|
59
|
+
bare_gtk_state_t *state;
|
|
60
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
61
|
+
assert(err == 0);
|
|
62
|
+
|
|
63
|
+
assert(argc == 1);
|
|
64
|
+
|
|
65
|
+
GdkTexture *texture;
|
|
66
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "texture", (gpointer *) &texture);
|
|
67
|
+
if (err < 0) return NULL;
|
|
68
|
+
|
|
69
|
+
js_value_t *result;
|
|
70
|
+
err = js_create_int32(env, gdk_texture_get_width(texture), &result);
|
|
71
|
+
assert(err == 0);
|
|
72
|
+
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static js_value_t *
|
|
77
|
+
bare_gtk_texture_height(js_env_t *env, js_callback_info_t *info) {
|
|
78
|
+
int err;
|
|
79
|
+
|
|
80
|
+
size_t argc = 1;
|
|
81
|
+
js_value_t *argv[1];
|
|
82
|
+
|
|
83
|
+
bare_gtk_state_t *state;
|
|
84
|
+
err = js_get_callback_info(env, info, &argc, argv, NULL, (void **) &state);
|
|
85
|
+
assert(err == 0);
|
|
86
|
+
|
|
87
|
+
assert(argc == 1);
|
|
88
|
+
|
|
89
|
+
GdkTexture *texture;
|
|
90
|
+
err = bare_gobject_read_tag(env, state->registry, argv[0], "texture", (gpointer *) &texture);
|
|
91
|
+
if (err < 0) return NULL;
|
|
92
|
+
|
|
93
|
+
js_value_t *result;
|
|
94
|
+
err = js_create_int32(env, gdk_texture_get_height(texture), &result);
|
|
95
|
+
assert(err == 0);
|
|
96
|
+
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#endif // BARE_GTK_TEXTURE_H
|
package/lib/texture.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const binding = require('../binding')
|
|
2
|
+
const wrap = require('./wrap')
|
|
3
|
+
const GDKPaintable = require('./paintable')
|
|
4
|
+
|
|
5
|
+
module.exports = exports = class GDKTexture extends GDKPaintable {
|
|
6
|
+
static newFromFilename(path) {
|
|
7
|
+
return wrap(GDKTexture, binding.textureNewFromFilename(path))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
get width() {
|
|
11
|
+
return binding.textureWidth(this._tag)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
get height() {
|
|
15
|
+
return binding.textureHeight(this._tag)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import GTKWidget = require('./widget')
|
|
2
|
+
|
|
3
|
+
/** Lets a widget that cannot scroll by itself be put in a `GTKScrolledWindow`, as a `GtkViewport`. */
|
|
4
|
+
interface GTKViewport extends GTKWidget {
|
|
5
|
+
child: GTKWidget | null
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Whether the child gets its minimum width or the width it asks for, as a `SCROLL_*` constant.
|
|
9
|
+
*/
|
|
10
|
+
hscrollPolicy: number
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Whether the child gets its minimum height or the height it asks for, as a `SCROLL_*` constant.
|
|
14
|
+
*/
|
|
15
|
+
vscrollPolicy: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare class GTKViewport {
|
|
19
|
+
constructor()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export = GTKViewport
|