UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2024 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 32 #include "label.h" 33 #include "container.h" 34 #include "../common/context.h" 35 #include "../common/object.h" 36 37 #include "Grid.h" 38 39 static UIWIDGET label_create(UiObject *obj, UiLabelArgs args, int align) { 40 Arg xargs[16]; 41 int n = 0; 42 43 UiContainerPrivate *ctn = ui_obj_container(obj); 44 UI_APPLY_LAYOUT(ctn->layout, args); 45 46 Widget parent = ctn->prepare(ctn, xargs, &n); 47 48 XtSetArg(xargs[n], XmNalignment, align); n++; 49 XmString label = NULL; 50 if(args.label) { 51 label = XmStringCreateLocalized((char*)args.label); 52 XtSetArg(xargs[n], XmNlabelString, label); n++; 53 } 54 55 char *name = args.name ? (char*)args.name : "label"; 56 Widget w = XmCreateLabel(parent, name, xargs, n); 57 XtManageChild(w); 58 ctn->add(ctn, w); 59 60 XmStringFree(label); 61 return w; 62 } 63 64 UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs args) { 65 return label_create(obj, args, XmALIGNMENT_CENTER); 66 } 67 68 UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) { 69 return label_create(obj, args, XmALIGNMENT_BEGINNING); 70 } 71 72 UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) { 73 return label_create(obj, args, XmALIGNMENT_END); 74 } 75 76 77 /* -------------------------- progressbar/spiner -------------------------- */ 78 79 static void ui_destroy_progressbar(Widget w, UiProgressBar *pb, XtPointer d) { 80 // TODO: free other stuff 81 free(pb); 82 } 83 84 static void ui_progressbar_expose(Widget widget, UiProgressBar *pb, XtPointer c) { 85 Display *dp = XtDisplay(widget); 86 Window w = XtWindow(widget); 87 if(w == 0) { 88 return; 89 } 90 if(!pb->gc) { 91 XGCValues gcvals; 92 gcvals.foreground = pb->color; 93 pb->gc = XCreateGC(dp, w, (GCForeground), &gcvals); 94 } 95 96 Dimension width = widget->core.width; 97 Dimension height = widget->core.height; 98 99 double value = (pb->value - pb->min) / (pb->max - pb->min); 100 Dimension valueW = (double)width * value; 101 102 XClearArea(dp, w, 0, 0, width, height, False); 103 XFillRectangle(dp, w, pb->gc, 0, 0, valueW, widget->core.height); 104 } 105 106 UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) { 107 Arg xargs[16]; 108 int n = 0; 109 110 UiContainerPrivate *ctn = ui_obj_container(obj); 111 UI_APPLY_LAYOUT(ctn->layout, args); 112 113 Widget parent = ctn->prepare(ctn, xargs, &n); 114 115 char *name = args.name ? (char*)args.name : "progressbar"; 116 Widget frame = XmCreateFrame(parent, name, xargs, n); 117 118 // create a button and get some informations about the height, shadow, highlight, .... 119 // we want the frame to have the same dimensions as a normal button 120 Widget test = XmCreatePushButton(frame, "button", NULL, 0); 121 XtManageChild(test); 122 Dimension h, highlightThickness, shadowThickness; 123 Pixel highlightColor; 124 XtVaGetValues(test, XmNheight, &h, XmNhighlightThickness, &highlightThickness, 125 XmNshadowThickness, &shadowThickness, XmNhighlightColor, &highlightColor, NULL); 126 XtDestroyWidget(test); 127 128 // adjust frame 129 XtVaSetValues(frame, XmNshadowThickness, shadowThickness, gridMarginLeft, highlightThickness, 130 gridMarginRight, highlightThickness, gridMarginTop, highlightThickness, 131 gridMarginBottom, highlightThickness, NULL); 132 133 // create drawing area 134 Dimension da_height = h - 2*highlightThickness - 2*shadowThickness; 135 n = 0; 136 XtSetArg(xargs[n], XmNheight, da_height); n++; 137 Widget drawingArea = XmCreateDrawingArea(frame, "progressbar_drawingarea", xargs, n); 138 XtManageChild(drawingArea); 139 140 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_DOUBLE); 141 142 UiProgressBar *progressbarData = malloc(sizeof(UiProgressBar)); 143 progressbarData->widget = drawingArea; 144 progressbarData->min = args.min; 145 progressbarData->max = args.max == 0 ? 100 : args.max; 146 progressbarData->value = 50; 147 progressbarData->var = var; 148 progressbarData->color = highlightColor; 149 progressbarData->gc = NULL; // initialize on first expose 150 151 if(var) { 152 UiDouble *d = var->value; 153 progressbarData->value = d->value; 154 d->obj = progressbarData; 155 d->get = ui_progressbar_get; 156 d->set = ui_progressbar_set; 157 } 158 159 XtAddCallback( 160 drawingArea, 161 XmNexposeCallback, 162 (XtCallbackProc)ui_progressbar_expose, 163 progressbarData); 164 XtAddCallback( 165 drawingArea, 166 XmNresizeCallback, 167 (XtCallbackProc)ui_progressbar_expose, 168 progressbarData); 169 170 171 XtManageChild(frame); 172 return frame; 173 } 174 175 double ui_progressbar_get(UiDouble *d) { 176 UiProgressBar *pb = d->obj; 177 d->value = pb->value; 178 return d->value; 179 } 180 181 void ui_progressbar_set(UiDouble *d, double value) { 182 UiProgressBar *pb = d->obj; 183 d->value = value; 184 pb->value = value; 185 ui_progressbar_expose(pb->widget, pb, NULL); 186 } 187 188 189 UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) { 190 Arg xargs[16]; 191 int n = 0; 192 193 UiContainerPrivate *ctn = ui_obj_container(obj); 194 UI_APPLY_LAYOUT(ctn->layout, args); 195 196 Widget parent = ctn->prepare(ctn, xargs, &n); 197 198 XmString label = XmStringCreateSimple(""); 199 XtSetArg(xargs[n], XmNlabelString, label); n++; 200 XtSetArg(xargs[n], XmNalignment, XmALIGNMENT_END); n++; 201 XtSetArg(xargs[n], gridMinWidth, 40); n++; 202 203 char *name = args.name ? (char*)args.name : "progresss_spinner"; 204 Widget w = XmCreateLabel(parent, name, xargs, n); 205 XtManageChild(w); 206 ctn->add(ctn, w); 207 208 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); 209 if(var) { 210 UiInteger *value = var->value; 211 value->obj = w; 212 value->get = ui_progressspinner_get; 213 value->set = ui_progressspinner_set; 214 215 if(value->value) { 216 ui_progressspinner_set(value, 1); 217 } 218 } 219 220 221 XmStringFree(label); 222 return w; 223 } 224 225 int64_t ui_progressspinner_get(UiInteger *i) { 226 return i->value; 227 } 228 229 void ui_progressspinner_set(UiInteger *i, int64_t value) { 230 Widget w = i->obj; 231 XmString label; 232 if(value) { 233 char str[4]; 234 snprintf(str, 4, "%c", 150); 235 label = XmStringCreateSimple(str); 236 } else { 237 label = XmStringCreateSimple(""); 238 } 239 XtVaSetValues(w, XmNlabelString, label, NULL); 240 XmStringFree(label); 241 i->value = value; 242 } 243