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.
Files changed (135) hide show
  1. package/CMakeLists.txt +16 -2
  2. package/README.md +35 -1
  3. package/binding.c +350 -1
  4. package/index.d.ts +65 -0
  5. package/index.js +32 -0
  6. package/lib/adjustment.d.ts +21 -0
  7. package/lib/adjustment.h +112 -0
  8. package/lib/adjustment.js +24 -0
  9. package/lib/bridging.h +347 -0
  10. package/lib/clipboard.d.ts +22 -0
  11. package/lib/clipboard.h +176 -0
  12. package/lib/clipboard.js +18 -0
  13. package/lib/constants.d.ts +40 -0
  14. package/lib/constants.js +51 -0
  15. package/lib/css-provider.d.ts +13 -0
  16. package/lib/css-provider.h +56 -0
  17. package/lib/css-provider.js +14 -0
  18. package/lib/cursor.d.ts +35 -0
  19. package/lib/cursor.h +220 -0
  20. package/lib/cursor.js +45 -0
  21. package/lib/device.d.ts +13 -0
  22. package/lib/device.h +35 -0
  23. package/lib/device.js +8 -0
  24. package/lib/dialog.d.ts +41 -0
  25. package/lib/dialog.js +37 -0
  26. package/lib/display.d.ts +25 -0
  27. package/lib/display.h +86 -0
  28. package/lib/display.js +23 -0
  29. package/lib/editable.h +160 -0
  30. package/lib/entry.d.ts +93 -0
  31. package/lib/entry.h +340 -0
  32. package/lib/entry.js +118 -0
  33. package/lib/event-controller-focus.d.ts +17 -0
  34. package/lib/event-controller-focus.h +55 -0
  35. package/lib/event-controller-focus.js +13 -0
  36. package/lib/event-controller-motion.d.ts +18 -0
  37. package/lib/event-controller-motion.h +66 -0
  38. package/lib/event-controller-motion.js +14 -0
  39. package/lib/event-controller.d.ts +17 -0
  40. package/lib/event-controller.h +103 -0
  41. package/lib/event-controller.js +22 -0
  42. package/lib/events.js +23 -0
  43. package/lib/fixed.d.ts +10 -0
  44. package/lib/fixed.h +28 -0
  45. package/lib/fixed.js +8 -0
  46. package/lib/frame-fixed.d.ts +10 -0
  47. package/lib/frame-fixed.js +12 -0
  48. package/lib/frame-layout-child.d.ts +17 -0
  49. package/lib/frame-layout-child.js +16 -0
  50. package/lib/frame-layout.d.ts +27 -0
  51. package/lib/frame-layout.h +291 -0
  52. package/lib/frame-layout.js +19 -0
  53. package/lib/gesture-click.d.ts +19 -0
  54. package/lib/gesture-click.h +66 -0
  55. package/lib/gesture-click.js +14 -0
  56. package/lib/gesture-drag.d.ts +25 -0
  57. package/lib/gesture-drag.h +165 -0
  58. package/lib/gesture-drag.js +23 -0
  59. package/lib/gesture-single.d.ts +13 -0
  60. package/lib/gesture-single.js +12 -0
  61. package/lib/gesture.d.ts +13 -0
  62. package/lib/gesture.h +73 -0
  63. package/lib/gesture.js +8 -0
  64. package/lib/handle.d.ts +5 -0
  65. package/lib/handle.js +6 -0
  66. package/lib/label.d.ts +36 -0
  67. package/lib/label.h +269 -0
  68. package/lib/label.js +78 -0
  69. package/lib/layout-child.d.ts +13 -0
  70. package/lib/layout-child.h +35 -0
  71. package/lib/layout-child.js +10 -0
  72. package/lib/layout-manager.d.ts +15 -0
  73. package/lib/layout-manager.h +42 -0
  74. package/lib/layout-manager.js +15 -0
  75. package/lib/message-dialog.d.ts +26 -0
  76. package/lib/message-dialog.h +190 -0
  77. package/lib/message-dialog.js +22 -0
  78. package/lib/monitor.d.ts +32 -0
  79. package/lib/monitor.h +143 -0
  80. package/lib/monitor.js +40 -0
  81. package/lib/native.h +31 -0
  82. package/lib/object.d.ts +18 -0
  83. package/lib/object.js +38 -0
  84. package/lib/paintable.d.ts +10 -0
  85. package/lib/paintable.js +3 -0
  86. package/lib/picture.d.ts +22 -0
  87. package/lib/picture.h +127 -0
  88. package/lib/picture.js +35 -0
  89. package/lib/reachable.js +11 -0
  90. package/lib/runtime.c +21 -4
  91. package/lib/scrolled-window.d.ts +22 -0
  92. package/lib/scrolled-window.h +142 -0
  93. package/lib/scrolled-window.js +37 -0
  94. package/lib/settings.d.ts +25 -0
  95. package/lib/settings.h +163 -0
  96. package/lib/settings.js +34 -0
  97. package/lib/spinner.d.ts +12 -0
  98. package/lib/spinner.h +61 -0
  99. package/lib/spinner.js +22 -0
  100. package/lib/style-context.d.ts +15 -0
  101. package/lib/style-context.h +67 -0
  102. package/lib/style-context.js +9 -0
  103. package/lib/surface.d.ts +19 -0
  104. package/lib/surface.h +61 -0
  105. package/lib/surface.js +22 -0
  106. package/lib/switch.d.ts +19 -0
  107. package/lib/switch.h +114 -0
  108. package/lib/switch.js +30 -0
  109. package/lib/text-buffer.d.ts +31 -0
  110. package/lib/text-buffer.h +246 -0
  111. package/lib/text-buffer.js +33 -0
  112. package/lib/text-view.d.ts +39 -0
  113. package/lib/text-view.h +247 -0
  114. package/lib/text-view.js +63 -0
  115. package/lib/text.d.ts +18 -0
  116. package/lib/text.h +189 -0
  117. package/lib/text.js +31 -0
  118. package/lib/texture.d.ts +20 -0
  119. package/lib/texture.h +100 -0
  120. package/lib/texture.js +17 -0
  121. package/lib/viewport.d.ts +22 -0
  122. package/lib/viewport.h +151 -0
  123. package/lib/viewport.js +38 -0
  124. package/lib/widget.d.ts +102 -0
  125. package/lib/widget.h +695 -17
  126. package/lib/widget.js +176 -11
  127. package/lib/window.d.ts +31 -0
  128. package/lib/window.h +142 -61
  129. package/lib/window.js +32 -11
  130. package/lib/wrap.js +7 -0
  131. package/package.json +12 -3
  132. package/prebuilds/linux-arm64/bare +2 -2
  133. package/prebuilds/linux-arm64/bare-gtk.bare +0 -0
  134. package/prebuilds/linux-x64/bare +2 -2
  135. package/prebuilds/linux-x64/bare-gtk.bare +0 -0
@@ -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
@@ -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
+ }
@@ -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