ui/gtk/container.c

changeset 102
64ded9f6a6c6
parent 101
7b3a3130be44
equal deleted inserted replaced
101:7b3a3130be44 102:64ded9f6a6c6
50 return 0; 50 return 0;
51 } 51 }
52 return 1; 52 return 1;
53 } 53 }
54 54
55 UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) {
56 UiObject* current = uic_current_obj(obj);
57
58 UIWIDGET widget = create_widget(obj, args, userdata);
59
60 UI_APPLY_LAYOUT1(current, args);
61 current->container->add(current->container, widget, FALSE);
62
63 return widget;
64 }
65
55 GtkWidget* ui_gtk_vbox_new(int spacing) { 66 GtkWidget* ui_gtk_vbox_new(int spacing) {
56 #if GTK_MAJOR_VERSION >= 3 67 #if GTK_MAJOR_VERSION >= 3
57 return gtk_box_new(GTK_ORIENTATION_VERTICAL, spacing); 68 return gtk_box_new(GTK_ORIENTATION_VERTICAL, spacing);
58 #else 69 #else
59 return gtk_vbox_new(FALSE, spacing); 70 return gtk_vbox_new(FALSE, spacing);
94 break; 105 break;
95 } 106 }
96 case UI_CONTAINER_GRID: { 107 case UI_CONTAINER_GRID: {
97 sub = ui_create_grid_widget(columnspacing, rowspacing); 108 sub = ui_create_grid_widget(columnspacing, rowspacing);
98 add = ui_box_set_margin(sub, margin); 109 add = ui_box_set_margin(sub, margin);
99 newobj->container = ui_grid_container(newobj, sub); 110 newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
100 newobj->widget = sub; 111 newobj->widget = sub;
101 break; 112 break;
102 } 113 }
103 case UI_CONTAINER_NO_SUB: { 114 case UI_CONTAINER_NO_SUB: {
104 break; 115 break;
154 165
155 ui_reset_layout(ct->layout); 166 ui_reset_layout(ct->layout);
156 ct->current = widget; 167 ct->current = widget;
157 } 168 }
158 169
159 UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid) { 170 UiContainer* ui_grid_container(
171 UiObject *obj,
172 GtkWidget *grid,
173 UiBool def_hexpand,
174 UiBool def_vexpand,
175 UiBool def_hfill,
176 UiBool def_vfill)
177 {
160 UiGridContainer *ct = cxCalloc( 178 UiGridContainer *ct = cxCalloc(
161 obj->ctx->allocator, 179 obj->ctx->allocator,
162 1, 180 1,
163 sizeof(UiGridContainer)); 181 sizeof(UiGridContainer));
182 ct->def_hexpand = def_hexpand;
183 ct->def_vexpand = def_vexpand;
184 ct->def_hfill = def_hfill;
185 ct->def_vfill = def_vfill;
164 ct->container.widget = grid; 186 ct->container.widget = grid;
165 ct->container.add = ui_grid_container_add; 187 ct->container.add = ui_grid_container_add;
166 UI_GTK_V2(ct->width = 0); 188 UI_GTK_V2(ct->width = 0);
167 UI_GTK_V2(ct->height = 1); 189 UI_GTK_V2(ct->height = 1);
168 return (UiContainer*)ct; 190 return (UiContainer*)ct;
180 202
181 int hexpand = FALSE; 203 int hexpand = FALSE;
182 int vexpand = FALSE; 204 int vexpand = FALSE;
183 int hfill = FALSE; 205 int hfill = FALSE;
184 int vfill = FALSE; 206 int vfill = FALSE;
207 if(!ct->layout.override_defaults) {
208 if(grid->def_hexpand) {
209 hexpand = TRUE;
210 hfill = TRUE;
211 } else if(grid->def_hfill) {
212 hfill = TRUE;
213 }
214 if(grid->def_vexpand) {
215 vexpand = TRUE;
216 vfill = TRUE;
217 } else if(grid->def_vfill) {
218 vfill = TRUE;
219 }
220 }
221
185 if(ct->layout.fill != UI_LAYOUT_UNDEFINED) { 222 if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
186 fill = ui_lb2bool(ct->layout.fill); 223 fill = ui_lb2bool(ct->layout.fill);
187 } 224 }
188 if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) { 225 if(ct->layout.hexpand) {
189 hexpand = ct->layout.hexpand; 226 hexpand = TRUE;
190 hfill = TRUE; 227 hfill = TRUE;
191 } 228 } else if(ct->layout.hfill) {
192 if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) { 229 hfill = TRUE;
193 vexpand = ct->layout.vexpand; 230 }
231 if(ct->layout.vexpand) {
232 vexpand = TRUE;
233 vfill = TRUE;
234 } else if(ct->layout.vfill) {
194 vfill = TRUE; 235 vfill = TRUE;
195 } 236 }
196 if(fill) { 237 if(fill) {
197 hfill = TRUE; 238 hfill = TRUE;
198 vfill = TRUE; 239 vfill = TRUE;
228 ct->layout.newline = FALSE; 269 ct->layout.newline = FALSE;
229 } 270 }
230 271
231 int hexpand = FALSE; 272 int hexpand = FALSE;
232 int vexpand = FALSE; 273 int vexpand = FALSE;
233 if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) { 274 int hfill = FALSE;
234 hexpand = ct->layout.hexpand; 275 int vfill = FALSE;
235 } 276 if(!ct->layout.override_defaults) {
236 if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) { 277 if(grid->def_hexpand) {
237 vexpand = ct->layout.vexpand; 278 hexpand = TRUE;
238 } 279 hfill = TRUE;
239 GtkAttachOptions xoptions = hexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL; 280 } else if(grid->def_hfill) {
240 GtkAttachOptions yoptions = vexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL; 281 hfill = TRUE;
282 }
283 if(grid->def_vexpand) {
284 vexpand = TRUE;
285 vfill = TRUE;
286 } else if(grid->def_vfill) {
287 vfill = TRUE;
288 }
289 }
290
291 if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
292 fill = ui_lb2bool(ct->layout.fill);
293 }
294 if(ct->layout.hexpand) {
295 hexpand = TRUE;
296 hfill = TRUE;
297 } else if(ct->layout.hfill) {
298 hfill = TRUE;
299 }
300 if(ct->layout.vexpand) {
301 vexpand = TRUE;
302 vfill = TRUE;
303 } else if(ct->layout.vfill) {
304 vfill = TRUE;
305 }
306 if(fill) {
307 hfill = TRUE;
308 vfill = TRUE;
309 }
310
311 GtkAttachOptions xoptions = 0;
312 GtkAttachOptions yoptions = 0;
313 if(hexpand) {
314 xoptions = GTK_EXPAND;
315 }
316 if(hfill) {
317 xoptions |= GTK_FILL;
318 }
319 if(vexpand) {
320 yoptions = GTK_EXPAND;
321 }
322 if(vfill) {
323 yoptions |= GTK_FILL;
324 }
241 325
242 int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1; 326 int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1;
243 int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1; 327 int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1;
244 // TODO: use colspan/rowspan 328 // TODO: use colspan/rowspan
245 329
394 ui_set_name_and_style(grid, args.name, args.style_class); 478 ui_set_name_and_style(grid, args.name, args.style_class);
395 widget = ui_box_set_margin(grid, args.margin); 479 widget = ui_box_set_margin(grid, args.margin);
396 current->container->add(current->container, widget, TRUE); 480 current->container->add(current->container, widget, TRUE);
397 481
398 UiObject *newobj = uic_object_new(obj, grid); 482 UiObject *newobj = uic_object_new(obj, grid);
399 newobj->container = ui_grid_container(obj, grid); 483 newobj->container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill);
400 uic_obj_add(obj, newobj); 484 uic_obj_add(obj, newobj);
401 485
402 return widget; 486 return widget;
403 } 487 }
404 488
753 newobj->container = ui_box_container(newobj, sub, data->subcontainer); 837 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
754 break; 838 break;
755 } 839 }
756 case UI_CONTAINER_GRID: { 840 case UI_CONTAINER_GRID: {
757 sub = ui_create_grid_widget(data->columnspacing, data->rowspacing); 841 sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
758 newobj->container = ui_grid_container(newobj, sub); 842 newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
759 break; 843 break;
760 } 844 }
761 } 845 }
762 newobj->widget = sub; 846 newobj->widget = sub;
763 GtkWidget *widget = ui_box_set_margin(sub, data->margin); 847 GtkWidget *widget = ui_box_set_margin(sub, data->margin);
943 #endif 1027 #endif
944 return NULL; 1028 return NULL;
945 } 1029 }
946 1030
947 1031
1032
1033 static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs args) {
1034 UiObject* current = uic_current_obj(obj);
1035
1036 GtkWidget *pane0 = create_paned(orientation);
1037
1038 UI_APPLY_LAYOUT1(current, args);
1039 current->container->add(current->container, pane0, TRUE);
1040
1041 int max = args.max_panes == 0 ? 2 : args.max_panes;
1042
1043 UiObject *newobj = uic_object_new(obj, pane0);
1044 newobj->container = ui_splitpane_container(obj, pane0, orientation, max);
1045 uic_obj_add(obj, newobj);
1046
1047 return pane0;
1048 }
1049
1050 UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
1051 return splitpane_create(obj, UI_HORIZONTAL, args);
1052 }
1053
1054 UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
1055 return splitpane_create(obj, UI_VERTICAL, args);
1056 }
1057
1058 UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max) {
1059 UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer));
1060 ct->container.widget = pane;
1061 ct->container.add = ui_splitpane_container_add;
1062 ct->current_pane = pane;
1063 ct->orientation = orientation;
1064 ct->max = max;
1065 return (UiContainer*)ct;
1066 }
1067
1068 void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
1069 UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct;
1070
1071 if(s->nchildren >= s->max) {
1072 fprintf(stderr, "splitpane: maximum number of children reached\n");
1073 return;
1074 }
1075
1076 if(s->pos == 0) {
1077 gtk_paned_set_start_child(GTK_PANED(s->current_pane), widget);
1078 s->pos++;
1079 s->nchildren++;
1080 } else {
1081 if(s->nchildren+1 == s->max) {
1082 gtk_paned_set_end_child(GTK_PANED(s->current_pane), widget);
1083 } else {
1084 GtkWidget *pane = create_paned(s->orientation);
1085 gtk_paned_set_start_child(GTK_PANED(pane), widget);
1086 gtk_paned_set_end_child(GTK_PANED(s->current_pane), pane);
1087 s->current_pane = pane;
1088 }
1089
1090 s->pos = 0;
1091 s->nchildren++;
1092 }
1093 }
948 1094
949 /* -------------------- ItemList Container -------------------- */ 1095 /* -------------------- ItemList Container -------------------- */
950 1096
951 static void remove_item(void *data, void *item) { 1097 static void remove_item(void *data, void *item) {
952 UiGtkItemListContainer *ct = data; 1098 UiGtkItemListContainer *ct = data;
995 if(item_obj) { 1141 if(item_obj) {
996 // re-add previously created widget 1142 // re-add previously created widget
997 ui_box_container_add(ct->container, item_obj->widget, FALSE); 1143 ui_box_container_add(ct->container, item_obj->widget, FALSE);
998 } else { 1144 } else {
999 // create new widget and object for this list element 1145 // create new widget and object for this list element
1000 CxMempool *mp = cxBasicMempoolCreate(256); 1146 CxMempool *mp = cxMempoolCreateSimple(256);
1001 const CxAllocator *a = mp->allocator; 1147 const CxAllocator *a = mp->allocator;
1002 UiObject *obj = cxCalloc(a, 1, sizeof(UiObject)); 1148 UiObject *obj = cxCalloc(a, 1, sizeof(UiObject));
1003 obj->ctx = uic_context(obj, mp); 1149 obj->ctx = uic_context(obj, mp);
1004 obj->window = NULL; 1150 obj->window = NULL;
1005 obj->widget = ui_subcontainer_create( 1151 obj->widget = ui_subcontainer_create(
1100 void ui_layout_vfill(UiObject *obj, UiBool fill) { 1246 void ui_layout_vfill(UiObject *obj, UiBool fill) {
1101 UiContainer *ct = uic_get_current_container(obj); 1247 UiContainer *ct = uic_get_current_container(obj);
1102 ct->layout.vfill = fill; 1248 ct->layout.vfill = fill;
1103 } 1249 }
1104 1250
1251 UIEXPORT void ui_layout_override_defaults(UiObject *obj, UiBool d) {
1252 UiContainer *ct = uic_get_current_container(obj);
1253 ct->layout.override_defaults = d;
1254 }
1255
1105 void ui_layout_colspan(UiObject* obj, int cols) { 1256 void ui_layout_colspan(UiObject* obj, int cols) {
1106 UiContainer* ct = uic_get_current_container(obj); 1257 UiContainer* ct = uic_get_current_container(obj);
1107 ct->layout.colspan = cols; 1258 ct->layout.colspan = cols;
1108 } 1259 }
1109 1260

mercurial