diff options
author | csaba <csaba> | 2023-01-31 19:53:27 (GMT) |
---|---|---|
committer | csaba <csaba> | 2023-01-31 19:53:27 (GMT) |
commit | 78b317b274c134bd778015cfffac2288ee6ef075 (patch) | |
tree | ccb3057a589027b15db93a0ad0a7bfbfbda0c9e5 /generic | |
parent | c41c244e7701ad4fb83800220a56e05b9bd5e645 (diff) | |
download | tk-78b317b274c134bd778015cfffac2288ee6ef075.zip tk-78b317b274c134bd778015cfffac2288ee6ef075.tar.gz tk-78b317b274c134bd778015cfffac2288ee6ef075.tar.bz2 |
Made the ttk::checkbutton and ttk::radiobutton indicators of the alt theme scaling-aware, preserving their 3D look
Diffstat (limited to 'generic')
-rw-r--r-- | generic/ttk/ttkDefaultTheme.c | 364 |
1 files changed, 212 insertions, 152 deletions
diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c index 1acdcbc..7be808b 100644 --- a/generic/ttk/ttkDefaultTheme.c +++ b/generic/ttk/ttkDefaultTheme.c @@ -375,8 +375,11 @@ static const Ttk_ElementSpec FieldElementSpec = { /*------------------------------------------------------------------------ * Indicators -- * - * Code derived (probably incorrectly) from TIP 109 implementation, - * unix/tkUnixButton.c r 1.15. + * The SVG images used here are partly based on some icons provided by + * the official open source SVG icon library for the Bootstrap project, + * licensed under the MIT license (https://opensource.org/licenses/MIT). + * + * See https://github.com/twbs/icons. */ /* @@ -385,28 +388,11 @@ static const Ttk_ElementSpec FieldElementSpec = { typedef struct { int width; /* Width of each image */ int height; /* Height of each image */ - int nimages; /* #images / row */ - const char *const *pixels; /* array[height] of char[width*nimage] */ + const char *offDataPtr; + const char *onDataPtr; const Ttk_StateTable *map;/* used to look up image index by state */ } IndicatorSpec; -#if 0 -/*XPM*/ -static const char *const button_images[] = { - /* width height ncolors chars_per_pixel */ - "52 13 8 1", - /* colors */ - "A c #808000000000 s shadow", - "B c #000080800000 s highlight", - "C c #808080800000 s 3dlight", - "D c #000000008080 s window", - "E c #808000008080 s 3ddark", - "F c #000080808080 s frame", - "G c #000000000000 s foreground", - "H c #000080800000 s disabledfg", -}; -#endif - static const Ttk_StateTable checkbutton_states[] = { { 0, 0, TTK_STATE_SELECTED|TTK_STATE_DISABLED }, { 1, TTK_STATE_SELECTED, TTK_STATE_DISABLED }, @@ -415,25 +401,33 @@ static const Ttk_StateTable checkbutton_states[] = { { 0, 0, 0 } }; -static const char *const checkbutton_pixels[] = { - "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB", - "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB", - "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", - "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB", - "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB", - "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB", - "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB", - "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB", - "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB", - "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB", - "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", - "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB", - "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", -}; +static const char *const checkbtnOffData = "\ + <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n\ + <g>\n\ + <path d='m0 0v15h1v-14h14v-1z' fill='#888888'/>\n\ + <path d='m1 1v13h1v-12h12v-1z' fill='#414141'/>\n\ + <path d='m14 1v13h-13v1h14v-14z' fill='#d9d9d9'/>\n\ + <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\n\ + <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\n\ + </g>\n\ + </svg>"; + +static const char *const checkbtnOnData = "\ + <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n\ + <g>\n\ + <path d='m0 0v15h1v-14h14v-1z' fill='#888888'/>\n\ + <path d='m1 1v13h1v-12h12v-1z' fill='#414141'/>\n\ + <path d='m14 1v13h-13v1h14v-14z' fill='#d9d9d9'/>\n\ + <path d='m15 0v15h-15v1h16v-16z' fill='#eeeeee'/>\n\ + <rect x='2' y='2' width='12' height='12' fill='#ffffff'/>\n\ + <path d='m10.803 4.969a0.75002 0.75002 0 0 1 1.071 1.05l-3.992 4.9901a0.75002 0.75002 0 0 1-1.08 0.01999l-2.645-2.646a0.75002 0.75002 0 1 1 1.06-1.06l2.094 2.093 3.473-4.4251a0.235 0.235 0 0 1 0.01999-0.021997z' fill='#000000'/>\n\ + </g>\n\ + </svg>"; static IndicatorSpec checkbutton_spec = { - 13, 13, 4, /* width, height, nimages */ - checkbutton_pixels, + 16, 16, + checkbtnOffData, + checkbtnOnData, checkbutton_states }; @@ -445,25 +439,45 @@ static const Ttk_StateTable radiobutton_states[] = { { 0, 0, 0 } }; -static const char *const radiobutton_pixels[] = { - "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF", - "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF", - "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF", - "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", - "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", - "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", - "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", - "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", - "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", - "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF", - "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF", - "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", -}; +static const char *const radiobtnOffData = "\ + <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n\ + <defs>\n\ + <linearGradient id='linearGradient1319' x1='7' x2='9' y1='8' y2='8' gradientTransform='rotate(45,8,8)' gradientUnits='userSpaceOnUse'>\n\ + <stop stop-color='#888888' offset='0'/>\n\ + <stop stop-color='#eeeeee' offset='1'/>\n\ + </linearGradient>\n\ + <linearGradient id='linearGradient2819' x1='7' x2='9' y1='8' y2='8' gradientTransform='rotate(45,8,8)' gradientUnits='userSpaceOnUse'>\n\ + <stop stop-color='#414141' offset='0'/>\n\ + <stop stop-color='#d9d9d9' offset='1'/>\n\ + </linearGradient>\n\ + </defs>\n\ + <path d='m7.6149 14.979c-0.95143-0.052435-1.8251-0.28345-2.6955-0.71278-1.2049-0.59425-2.1287-1.4307-2.865-2.5939-0.17549-0.27726-0.48912-0.91628-0.60706-1.2369-0.78448-2.1325-0.50124-4.4748 0.76831-6.3538 1.0215-1.5118 2.623-2.5782 4.4077-2.9349 1.8284-0.36541 3.7204 0.011412 5.2659 1.0488 1.5781 1.0592 2.6631 2.7202 2.993 4.5816 0.13747 0.77566 0.13747 1.6696 0 2.4452-0.44509 2.5113-2.2593 4.6096-4.6777 5.4101-0.82562 0.2733-1.7275 0.39395-2.5897 0.34644z' fill='#ffffff' stroke-width='.019254'/>\n\ + <path d='m3.0503 12.95a7 7 0 1 1 9.8995-9.8995 7 7 0 0 1-9.8995 9.8995zm-0.70711 0.70711a8 8 0 1 0 11.314-11.314 8 8 0 0 0-11.314 11.314z' fill='url(#linearGradient1319)'/>\n\ + <path d='m12.95 3.0503c-2.7294-2.7294-7.1701-2.7294-9.8995 0s-2.7294 7.1701 0 9.8995 7.1701 2.7294 9.8995 0 2.7294-7.1701 0-9.8995zm-0.70711 0.70711c2.3476 2.3476 2.3476 6.1377 0 8.4853s-6.1377 2.3476-8.4853 0-2.3476-6.1377 0-8.4853 6.1377-2.3476 8.4853 0z' fill='url(#linearGradient2819)'/>\n\ + </svg>"; + +static const char *const radiobtnOnData = "\ + <svg width='16' height='16' version='1.1' xmlns='http://www.w3.org/2000/svg'>\n\ + <defs>\n\ + <linearGradient id='linearGradient1319' x1='7' x2='9' y1='8' y2='8' gradientTransform='rotate(45,8,8)' gradientUnits='userSpaceOnUse'>\n\ + <stop stop-color='#888888' offset='0'/>\n\ + <stop stop-color='#eeeeee' offset='1'/>\n\ + </linearGradient>\n\ + <linearGradient id='linearGradient2819' x1='7' x2='9' y1='8' y2='8' gradientTransform='rotate(45,8,8)' gradientUnits='userSpaceOnUse'>\n\ + <stop stop-color='#414141' offset='0'/>\n\ + <stop stop-color='#d9d9d9' offset='1'/>\n\ + </linearGradient>\n\ + </defs>\n\ + <path d='m7.6149 14.979c-0.95143-0.052435-1.8251-0.28345-2.6955-0.71278-1.2049-0.59425-2.1287-1.4307-2.865-2.5939-0.17549-0.27726-0.48912-0.91628-0.60706-1.2369-0.78448-2.1325-0.50124-4.4748 0.76831-6.3538 1.0215-1.5118 2.623-2.5782 4.4077-2.9349 1.8284-0.36541 3.7204 0.011412 5.2659 1.0488 1.5781 1.0592 2.6631 2.7202 2.993 4.5816 0.13747 0.77566 0.13747 1.6696 0 2.4452-0.44509 2.5113-2.2593 4.6096-4.6777 5.4101-0.82562 0.2733-1.7275 0.39395-2.5897 0.34644z' fill='#ffffff' stroke-width='.019254'/>\n\ + <path d='m3.0503 12.95a7 7 0 1 1 9.8995-9.8995 7 7 0 0 1-9.8995 9.8995zm-0.70711 0.70711a8 8 0 1 0 11.314-11.314 8 8 0 0 0-11.314 11.314z' fill='url(#linearGradient1319)'/>\n\ + <path d='m12.95 3.0503c-2.7294-2.7294-7.1701-2.7294-9.8995 0s-2.7294 7.1701 0 9.8995 7.1701 2.7294 9.8995 0 2.7294-7.1701 0-9.8995zm-0.70711 0.70711c2.3476 2.3476 2.3476 6.1377 0 8.4853s-6.1377 2.3476-8.4853 0-2.3476-6.1377 0-8.4853 6.1377-2.3476 8.4853 0z' fill='url(#linearGradient2819)'/>\n\ + <path d='m11 8a3 3 0 1 1-6 0 3 3 0 0 1 6 0z' fill='#000000'/>\n\ + </svg>"; static IndicatorSpec radiobutton_spec = { - 13, 13, 4, /* width, height, nimages */ - radiobutton_pixels, + 16, 16, + radiobtnOffData, + radiobtnOnData, radiobutton_states }; @@ -500,38 +514,87 @@ static void IndicatorElementSize( int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { IndicatorSpec *spec = (IndicatorSpec *)clientData; + Tcl_Interp *interp = Tk_Interp(tkwin); + const char *scalingPctPtr; + double scalingFactor; IndicatorElement *indicator = (IndicatorElement *)elementRecord; Ttk_Padding margins; (void)paddingPtr; + /* + * Retrieve the scaling factor (1.0, 1.25, 1.5, ...) + */ + scalingPctPtr = Tcl_GetVar(interp, "::tk::scalingPct", TCL_GLOBAL_ONLY); + scalingFactor = atof(scalingPctPtr) / 100; + Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins); - *widthPtr = spec->width + Ttk_PaddingWidth(margins); - *heightPtr = spec->height + Ttk_PaddingHeight(margins); + *widthPtr = spec->width * scalingFactor + Ttk_PaddingWidth(margins); + *heightPtr = spec->height * scalingFactor + Ttk_PaddingHeight(margins); +} + +static void ColorToStr( + const XColor *colorPtr, char *colorStr) /* in the format "RRGGBB" */ +{ + char str[13]; + + snprintf(str, sizeof(str), "%04x%04x%04x", + colorPtr->red, colorPtr->green, colorPtr->blue); + snprintf(colorStr, 7, "%.2s%.2s%.2s", str, str + 4, str + 8); +} + +static void ImageChanged( /* to be passed to Tk_GetImage() */ + ClientData clientData, + int x, int y, int width, int height, + int imageWidth, int imageHeight) +{ + (void)clientData; + (void)x; (void)y; (void)width; (void)height; + (void)imageWidth; (void)imageHeight; } static void IndicatorElementDraw( void *clientData, void *elementRecord, Tk_Window tkwin, Drawable d, Ttk_Box b, unsigned int state) { - IndicatorSpec *spec = (IndicatorSpec *)clientData; IndicatorElement *indicator = (IndicatorElement *)elementRecord; - Display *display = Tk_Display(tkwin); Ttk_Padding padding; - XColor *fgColor, *frameColor, *shadeColor, *indicatorColor, *borderColor; + Tcl_Interp *interp = Tk_Interp(tkwin); + const char *scalingPctPtr; + double scalingFactor; + IndicatorSpec *spec = (IndicatorSpec *)clientData; - int index, ix, iy; - XGCValues gcValues; - GC copyGC; - unsigned long imgColors[8]; - XImage *img = NULL; + int index; + const char *svgDataPtr; + char bgColorStr[7], fgColorStr[7], indicatorColorStr[7], + shadeColorStr[7], borderColorStr[7]; + char imgName[70]; + Tk_Image img; + + size_t svgDataLen; + char *svgDataCopy; + char *shadeColorPtr, *highlightColorPtr, *borderColorPtr, *bgColorPtr, + *indicatorColorPtr, *fgColorPtr; + const char *cmdFmt; + size_t scriptSize; + char *script; + int code; Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding); b = Ttk_PadBox(b, padding); + /* + * Retrieve the scaling factor (1.0, 1.25, 1.5, ...) + */ + scalingPctPtr = Tcl_GetVar(interp, "::tk::scalingPct", TCL_GLOBAL_ONLY); + scalingFactor = atof(scalingPctPtr) / 100; + + /* + * Sanity check + */ if ( b.x < 0 || b.y < 0 - || Tk_Width(tkwin) < b.x + spec->width - || Tk_Height(tkwin) < b.y + spec->height) + || Tk_Width(tkwin) < b.x + spec->width * scalingFactor + || Tk_Height(tkwin) < b.y + spec->height * scalingFactor) { /* Oops! not enough room to display the image. * Don't draw anything. @@ -540,106 +603,103 @@ static void IndicatorElementDraw( } /* - * Fill in imgColors palette: - * - * (SHOULD: take light and shade colors from the border object, - * but Tk doesn't provide easy access to these in the public API.) + * Determine the SVG data to use for the photo image */ - fgColor = Tk_GetColorFromObj(tkwin, indicator->foregroundObj); - frameColor = Tk_GetColorFromObj(tkwin, indicator->backgroundObj); - shadeColor = Tk_GetColorFromObj(tkwin, indicator->shadeColorObj); - indicatorColor = Tk_GetColorFromObj(tkwin, indicator->colorObj); - borderColor = Tk_GetColorFromObj(tkwin, indicator->borderColorObj); - - imgColors[0 /*A*/] = shadeColor->pixel; - imgColors[1 /*B*/] = indicatorColor->pixel; - imgColors[2 /*C*/] = frameColor->pixel; - imgColors[3 /*D*/] = indicatorColor->pixel; - imgColors[4 /*E*/] = borderColor->pixel; - imgColors[5 /*F*/] = frameColor->pixel; - imgColors[6 /*G*/] = fgColor->pixel; - imgColors[7 /*H*/] = fgColor->pixel; - - /* - * Create a scratch buffer to store the image: - */ - -#if defined(IGNORES_VISUAL) + index = Ttk_StateTableLookup(spec->map, state); + svgDataPtr = (index % 2 == 0 ? spec->offDataPtr : spec->onDataPtr); /* - * Platforms which ignore the VisualInfo can use XCreateImage to get the - * scratch image. This is essential on macOS, where it is not safe to call - * XGetImage in a display procedure. + * Construct the color strings bgColorStr, fgColorStr, + * indicatorColorStr, shadeColorStr, and borderColorStr */ - - img = XCreateImage(display, NULL, 32, ZPixmap, 0, NULL, - (unsigned int)spec->width, (unsigned int)spec->height, - 0, 0); -#else + ColorToStr(Tk_GetColorFromObj(tkwin, indicator->backgroundObj), + bgColorStr); + ColorToStr(Tk_GetColorFromObj(tkwin, indicator->foregroundObj), + fgColorStr); + ColorToStr(Tk_GetColorFromObj(tkwin, indicator->colorObj), + indicatorColorStr); + ColorToStr(Tk_GetColorFromObj(tkwin, indicator->shadeColorObj), + shadeColorStr); + ColorToStr(Tk_GetColorFromObj(tkwin, indicator->borderColorObj), + borderColorStr); /* - * This trick allows creating the scratch XImage without having to - * construct a VisualInfo. + * Check whether there is an SVG image for the indicator's + * type (0 = checkbtn, 1 = radiobtn) and these color strings */ - - img = XGetImage(display, d, 0, 0, - (unsigned int)spec->width, (unsigned int)spec->height, - AllPlanes, ZPixmap); -#endif - + snprintf(imgName, sizeof(imgName), + "::tk::icons::alt_indicator%d_%s_%s_%s_%s_%s", + spec->offDataPtr == radiobtnOffData, + shadeColorStr, indicatorColorStr, borderColorStr, bgColorStr, + index % 2 == 1 ? fgColorStr : "XXXXXX"); + img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL); if (img == NULL) { - return; - } - -#if defined(IGNORES_VISUAL) - - img->data = (char *)ckalloc(img->bytes_per_line * img->height); - if (img->data == NULL) { - XDestroyImage(img); - return; - } + /* + * Copy the string pointed to by svgDataPtr to a newly allocated memory + * area svgDataCopy and assign the latter's address to svgDataPtr + */ + svgDataLen = strlen(svgDataPtr); + svgDataCopy = (char *)attemptckalloc(svgDataLen + 1); + if (svgDataCopy == NULL) { + return; + } + memcpy(svgDataCopy, svgDataPtr, svgDataLen); + svgDataCopy[svgDataLen] = '\0'; + svgDataPtr = svgDataCopy; -#endif + /* + * Update the colors within svgDataCopy + */ - /* - * Create the image, painting it into the XImage one pixel at a time. - */ + shadeColorPtr = strstr(svgDataPtr, "888888"); + highlightColorPtr = strstr(svgDataPtr, "eeeeee"); + borderColorPtr = strstr(svgDataPtr, "414141"); + bgColorPtr = strstr(svgDataPtr, "d9d9d9"); + indicatorColorPtr = strstr(svgDataPtr, "ffffff"); + fgColorPtr = strstr(svgDataPtr, "000000"); + + assert(shadeColorPtr); + assert(highlightColorPtr); + assert(borderColorPtr); + assert(bgColorPtr); + assert(indicatorColorPtr); + + memcpy(shadeColorPtr, shadeColorStr, 6); + memcpy(highlightColorPtr, indicatorColorStr, 6); + memcpy(borderColorPtr, borderColorStr, 6); + memcpy(bgColorPtr, bgColorStr, 6); + memcpy(indicatorColorPtr, indicatorColorStr, 6); + if (fgColorPtr != NULL) { + memcpy(fgColorPtr, fgColorStr, 6); + } - index = Ttk_StateTableLookup(spec->map, state); - for (iy=0 ; iy<spec->height ; iy++) { - for (ix=0 ; ix<spec->width ; ix++) { - XPutPixel(img, ix, iy, - imgColors[spec->pixels[iy][index*spec->width+ix] - 'A'] ); + /* + * Create an SVG photo image from svgDataCopy + */ + cmdFmt = "image create photo %s -format $::tk::svgFmt -data {%s}"; + scriptSize = strlen(cmdFmt) + strlen(imgName) + svgDataLen; + script = (char *)attemptckalloc(scriptSize); + if (script == NULL) { + ckfree(svgDataCopy); + return; } + snprintf(script, scriptSize, cmdFmt, imgName, svgDataCopy); + ckfree(svgDataCopy); + code = Tcl_EvalEx(interp, script, -1, TCL_EVAL_GLOBAL); + ckfree(script); + if (code != TCL_OK) { + Tcl_BackgroundException(interp, code); + return; + } + img = Tk_GetImage(interp, tkwin, imgName, ImageChanged, NULL); } /* - * Copy the image onto our target drawable surface. - */ - - memset(&gcValues, 0, sizeof(gcValues)); - copyGC = Tk_GetGC(tkwin, 0, &gcValues); - TkPutImage(NULL, 0, display, d, copyGC, img, 0, 0, b.x, b.y, - spec->width, spec->height); - - /* - * Tidy up. + * Display the image */ - - Tk_FreeGC(display, copyGC); - - /* - * Protect against the possibility that some future platform might - * not use the Tk memory manager in its implementation of XDestroyImage, - * even though that would be an extremely strange thing to do. - */ - -#if defined(IGNORES_VISUAL) - ckfree(img->data); - img->data = NULL; -#endif - - XDestroyImage(img); + Tk_RedrawImage(img, 0, 0, spec->width * scalingFactor, + spec->height * scalingFactor, d, b.x, b.y); + Tk_FreeImage(img); } static const Ttk_ElementSpec IndicatorElementSpec = { @@ -1017,7 +1077,7 @@ typedef struct { static const Ttk_ElementOptionSpec SliderElementOptions[] = { { "-sliderlength", TK_OPTION_PIXELS, offsetof(SliderElement,lengthObj), - "15" }, + "11.25p" }, { "-sliderthickness",TK_OPTION_PIXELS, offsetof(SliderElement,thicknessObj), "15" }, { "-sliderrelief", TK_OPTION_RELIEF, offsetof(SliderElement,reliefObj), |