29 #include <stdio.h> |
29 #include <stdio.h> |
30 #include <stdlib.h> |
30 #include <stdlib.h> |
31 |
31 |
32 #include "display.h" |
32 #include "display.h" |
33 #include "container.h" |
33 #include "container.h" |
34 #include <ucx/mempool.h> |
|
35 #include "../common/context.h" |
34 #include "../common/context.h" |
36 #include "../common/object.h" |
35 #include "../common/object.h" |
|
36 #include "../ui/display.h" |
|
37 |
|
38 #include <cx/printf.h> |
37 |
39 |
38 static void set_alignment(GtkWidget *widget, float xalign, float yalign) { |
40 static void set_alignment(GtkWidget *widget, float xalign, float yalign) { |
39 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16 |
41 #if GTK_MAJOR_VERSION >= 4 || (GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16) |
40 gtk_label_set_xalign(GTK_LABEL(widget), xalign); |
42 gtk_label_set_xalign(GTK_LABEL(widget), xalign); |
41 gtk_label_set_yalign(GTK_LABEL(widget), yalign); |
43 gtk_label_set_yalign(GTK_LABEL(widget), yalign); |
42 #else |
44 #else |
43 gtk_misc_set_alignment(GTK_MISC(widget), xalign, yalign); |
45 gtk_misc_set_alignment(GTK_MISC(widget), xalign, yalign); |
44 #endif |
46 #endif |
45 } |
47 } |
46 |
48 |
47 UIWIDGET ui_label(UiObject *obj, char *label) { |
49 UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) { |
48 GtkWidget *widget = gtk_label_new(label); |
50 UiObject* current = uic_current_obj(obj); |
49 |
51 |
50 UiContainer *ct = uic_get_current_container(obj); |
52 const char *css_class = NULL; |
51 ct->add(ct, widget, FALSE); |
53 char *markup = NULL; |
|
54 if(args.label) { |
|
55 #if GTK_MAJOR_VERSION < 3 |
|
56 switch(args.style) { |
|
57 case UI_LABEL_STYLE_DEFAULT: break; |
|
58 case UI_LABEL_STYLE_TITLE: { |
|
59 cxmutstr m = cx_asprintf("<b>%s</b>", args.label); |
|
60 markup = m.ptr; |
|
61 args.label = NULL; |
|
62 } |
|
63 case UI_LABEL_STYLE_SUBTITLE: { |
|
64 break; |
|
65 } |
|
66 case UI_LABEL_STYLE_DIM: { |
|
67 break; |
|
68 } |
|
69 } |
|
70 # else |
|
71 switch(args.style) { |
|
72 case UI_LABEL_STYLE_DEFAULT: break; |
|
73 case UI_LABEL_STYLE_TITLE: { |
|
74 css_class = "ui_label_title"; |
|
75 break; |
|
76 } |
|
77 case UI_LABEL_STYLE_SUBTITLE: { |
|
78 css_class = "subtitle"; |
|
79 break; |
|
80 } |
|
81 case UI_LABEL_STYLE_DIM: { |
|
82 css_class = "dim-label"; |
|
83 break; |
|
84 } |
|
85 } |
|
86 # endif |
|
87 } |
|
88 |
|
89 |
|
90 GtkWidget *widget = gtk_label_new(args.label); |
|
91 if(markup) { |
|
92 gtk_label_set_markup(GTK_LABEL(widget), markup); |
|
93 free(markup); |
|
94 } |
|
95 |
|
96 if(css_class) { |
|
97 WIDGET_ADD_CSS_CLASS(widget, css_class); |
|
98 } |
|
99 |
|
100 switch(args.align) { |
|
101 case UI_ALIGN_DEFAULT: break; |
|
102 case UI_ALIGN_LEFT: set_alignment(widget, 0, .5); break; |
|
103 case UI_ALIGN_RIGHT: set_alignment(widget, 1, .5); break; |
|
104 case UI_ALIGN_CENTER: break; // TODO |
|
105 } |
|
106 |
|
107 |
|
108 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); |
|
109 if(var) { |
|
110 UiString* value = (UiString*)var->value; |
|
111 value->obj = widget; |
|
112 value->get = ui_label_get; |
|
113 value->set = ui_label_set; |
|
114 } |
|
115 |
|
116 UI_APPLY_LAYOUT1(current, args); |
|
117 current->container->add(current->container, widget, FALSE); |
52 |
118 |
53 return widget; |
119 return widget; |
54 } |
120 } |
55 |
121 |
56 UIWIDGET ui_llabel(UiObject *obj, char *label) { |
122 UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) { |
57 UIWIDGET widget = ui_label(obj, label); |
123 args.align = UI_ALIGN_LEFT; |
58 set_alignment(widget, 0, .5); |
124 return ui_label_create(obj, args); |
59 return widget; |
125 } |
60 } |
126 |
61 |
127 UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) { |
62 UIWIDGET ui_rlabel(UiObject *obj, char *label) { |
128 args.align = UI_ALIGN_RIGHT; |
63 UIWIDGET widget = ui_label(obj, label); |
129 return ui_label_create(obj, args); |
64 //gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_RIGHT); |
130 } |
65 |
131 |
66 set_alignment(widget, 1, .5); |
132 char* ui_label_get(UiString *s) { |
67 return widget; |
133 if(s->value.ptr) { |
68 } |
134 s->value.free(s->value.ptr); |
69 |
135 } |
70 UIWIDGET ui_space(UiObject *obj) { |
136 s->value.ptr = g_strdup(gtk_label_get_text(GTK_LABEL(s->obj))); |
|
137 s->value.free = (ui_freefunc)g_free; |
|
138 return s->value.ptr; |
|
139 } |
|
140 |
|
141 void ui_label_set(UiString *s, const char *value) { |
|
142 gtk_label_set_text(GTK_LABEL(s->obj), value); |
|
143 if(s->value.ptr) { |
|
144 s->value.free(s->value.ptr); |
|
145 s->value.ptr = NULL; |
|
146 s->value.free = NULL; |
|
147 } |
|
148 } |
|
149 |
|
150 UIWIDGET ui_space_deprecated(UiObject *obj) { |
71 GtkWidget *widget = gtk_label_new(""); |
151 GtkWidget *widget = gtk_label_new(""); |
72 UiContainer *ct = uic_get_current_container(obj); |
152 UiContainer *ct = uic_get_current_container(obj); |
73 ct->add(ct, widget, TRUE); |
153 ct->add(ct, widget, TRUE); |
74 |
154 |
75 return widget; |
155 return widget; |
76 } |
156 } |
77 |
157 |
78 UIWIDGET ui_separator(UiObject *obj) { |
158 UIWIDGET ui_separator_deprecated(UiObject *obj) { |
79 #if UI_GTK3 |
159 #if GTK_MAJOR_VERSION >= 3 |
80 GtkWidget *widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); |
160 GtkWidget *widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); |
81 #else |
161 #else |
82 GtkWidget *widget = gtk_hseparator_new(); |
162 GtkWidget *widget = gtk_hseparator_new(); |
83 #endif |
163 #endif |
84 UiContainer *ct = uic_get_current_container(obj); |
164 UiContainer *ct = uic_get_current_container(obj); |
87 return widget; |
167 return widget; |
88 } |
168 } |
89 |
169 |
90 /* ------------------------- progress bar ------------------------- */ |
170 /* ------------------------- progress bar ------------------------- */ |
91 |
171 |
92 UIWIDGET ui_progressbar(UiObject *obj, UiDouble *value) { |
172 typedef struct UiProgressBarRange { |
93 UiVar *var = malloc(sizeof(UiVar)); |
173 double min; |
94 var->value = value; |
174 double max; |
95 var->type = UI_VAR_SPECIAL; |
175 } UiProgressBarRange; |
96 return ui_progressbar_var(obj, var); |
176 |
97 } |
177 UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) { |
98 |
178 UiObject* current = uic_current_obj(obj); |
99 UIWIDGET ui_progressbar_nv(UiObject *obj, char *varname) { |
179 |
100 UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_DOUBLE); |
|
101 return ui_progressbar_var(obj, var); |
|
102 } |
|
103 |
|
104 UIWIDGET ui_progressbar_var(UiObject *obj, UiVar *var) { |
|
105 GtkWidget *progressbar = gtk_progress_bar_new(); |
180 GtkWidget *progressbar = gtk_progress_bar_new(); |
|
181 if(args.max > args.min) { |
|
182 UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange)); |
|
183 range->min = args.min; |
|
184 range->max = args.max; |
|
185 g_signal_connect( |
|
186 progressbar, |
|
187 "destroy", |
|
188 G_CALLBACK(ui_destroy_userdata), |
|
189 range); |
|
190 g_object_set_data(G_OBJECT(progressbar), "ui_range", range); |
|
191 } |
|
192 |
|
193 |
|
194 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE); |
106 if(var && var->value) { |
195 if(var && var->value) { |
107 UiDouble *value = var->value; |
196 UiDouble *value = var->value; |
108 value->get = ui_progressbar_get; |
197 value->get = ui_progressbar_get; |
109 value->set = ui_progressbar_set; |
198 value->set = ui_progressbar_set; |
110 value->obj = progressbar; |
199 value->obj = progressbar; |
111 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), 0.5); |
200 ui_progressbar_set(value, value->value); |
112 } |
201 } |
113 |
202 |
114 UiContainer *ct = uic_get_current_container(obj); |
203 UI_APPLY_LAYOUT1(current, args); |
115 ct->add(ct, progressbar, FALSE); |
204 current->container->add(current->container, progressbar, FALSE); |
116 |
205 |
117 return progressbar; |
206 return progressbar; |
118 } |
207 } |
119 |
208 |
120 double ui_progressbar_get(UiDouble *d) { |
209 double ui_progressbar_get(UiDouble *d) { |
121 d->value = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj)); |
210 UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range"); |
|
211 double fraction = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj)); |
|
212 if(range) { |
|
213 fraction = range->min + (range->max - range->min) * fraction; |
|
214 } |
|
215 d->value = fraction; |
122 return d->value; |
216 return d->value; |
123 } |
217 } |
124 |
218 |
125 void ui_progressbar_set(UiDouble *d, double value) { |
219 void ui_progressbar_set(UiDouble *d, double value) { |
|
220 d->value = value; |
|
221 UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range"); |
|
222 if(range) { |
|
223 value = (value - range->min) / (range->max - range->min); |
|
224 } |
126 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(d->obj), value); |
225 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(d->obj), value); |
127 d->value = value; |
226 } |
128 } |
227 |
|
228 |
|
229 /* ------------------------- progress spinner ------------------------- */ |
|
230 |
|
231 UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) { |
|
232 UiObject* current = uic_current_obj(obj); |
|
233 |
|
234 GtkWidget *spinner = gtk_spinner_new(); |
|
235 |
|
236 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); |
|
237 if(var && var->value) { |
|
238 UiInteger *value = var->value; |
|
239 value->get = ui_spinner_get; |
|
240 value->set = ui_spinner_set; |
|
241 value->obj = spinner; |
|
242 ui_spinner_set(value, value->value); |
|
243 } |
|
244 |
|
245 UI_APPLY_LAYOUT1(current, args); |
|
246 current->container->add(current->container, spinner, FALSE); |
|
247 |
|
248 return spinner; |
|
249 } |
|
250 |
|
251 int64_t ui_spinner_get(UiInteger *i) { |
|
252 return i->value; |
|
253 } |
|
254 |
|
255 void ui_spinner_set(UiInteger *i, int64_t value) { |
|
256 i->value = value; |
|
257 if(i->obj) { |
|
258 GtkSpinner *spinner = GTK_SPINNER(i->obj); |
|
259 if(value != 0) { |
|
260 gtk_spinner_start(spinner); |
|
261 } else { |
|
262 gtk_spinner_stop(spinner); |
|
263 } |
|
264 } |
|
265 } |