summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjenglish <jenglish@flightlab.com>2011-08-16 17:03:20 (GMT)
committerjenglish <jenglish@flightlab.com>2011-08-16 17:03:20 (GMT)
commit9a046cd669466105bb9bd4d137b8b227ff958448 (patch)
tree05b9d1df2025423ae5e6126bdb4947449db7a3fb
parentdff96aa27cdba340f38ae9fe05fd4ebb46f767c6 (diff)
downloadtk-9a046cd669466105bb9bd4d137b8b227ff958448.zip
tk-9a046cd669466105bb9bd4d137b8b227ff958448.tar.gz
tk-9a046cd669466105bb9bd4d137b8b227ff958448.tar.bz2
ttk::range widget implementation, contributed by Goodwin Lawlor [SF#3391905]ttk_range_widget
-rw-r--r--generic/ttk/ttkClamTheme.c2
-rw-r--r--generic/ttk/ttkDefaultTheme.c2
-rw-r--r--generic/ttk/ttkElements.c2
-rw-r--r--generic/ttk/ttkInit.c2
-rw-r--r--generic/ttk/ttkRange.c762
-rw-r--r--library/ttk/altTheme.tcl3
-rw-r--r--library/ttk/classicTheme.tcl3
-rw-r--r--library/ttk/defaults.tcl2
-rw-r--r--library/ttk/range.tcl135
-rw-r--r--library/ttk/ttk.tcl1
-rw-r--r--library/ttk/vistaTheme.tcl32
-rw-r--r--library/ttk/winTheme.tcl2
-rw-r--r--unix/Makefile.in8
-rw-r--r--win/makefile.vc1
-rw-r--r--win/ttkWinXPTheme.c32
15 files changed, 987 insertions, 2 deletions
diff --git a/generic/ttk/ttkClamTheme.c b/generic/ttk/ttkClamTheme.c
index 572f630..c182f01 100644
--- a/generic/ttk/ttkClamTheme.c
+++ b/generic/ttk/ttkClamTheme.c
@@ -955,6 +955,8 @@ TtkClamTheme_Init(Tcl_Interp *interp)
Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "minslider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "maxslider", &SliderElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
diff --git a/generic/ttk/ttkDefaultTheme.c b/generic/ttk/ttkDefaultTheme.c
index d2deee8..850a476 100644
--- a/generic/ttk/ttkDefaultTheme.c
+++ b/generic/ttk/ttkDefaultTheme.c
@@ -1104,6 +1104,8 @@ MODULE_SCOPE int TtkAltTheme_Init(Tcl_Interp *interp)
Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "minslider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "maxslider", &SliderElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "uparrow",
&ArrowElementSpec, &ArrowElements[0]);
diff --git a/generic/ttk/ttkElements.c b/generic/ttk/ttkElements.c
index 22af1d6..7d0497a 100644
--- a/generic/ttk/ttkElements.c
+++ b/generic/ttk/ttkElements.c
@@ -1258,6 +1258,8 @@ void TtkElements_Init(Tcl_Interp *interp)
Ttk_RegisterElement(interp, theme, "trough", &TroughElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "thumb", &ThumbElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "minslider", &SliderElementSpec, NULL);
+ Ttk_RegisterElement(interp, theme, "maxslider", &SliderElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
Ttk_RegisterElement(interp, theme, "separator",
diff --git a/generic/ttk/ttkInit.c b/generic/ttk/ttkInit.c
index be30ee7..59d8705 100644
--- a/generic/ttk/ttkInit.c
+++ b/generic/ttk/ttkInit.c
@@ -213,6 +213,7 @@ extern void TtkFrame_Init(Tcl_Interp *);
extern void TtkNotebook_Init(Tcl_Interp *);
extern void TtkPanedwindow_Init(Tcl_Interp *);
extern void TtkProgressbar_Init(Tcl_Interp *);
+extern void TtkRange_Init(Tcl_Interp *);
extern void TtkScale_Init(Tcl_Interp *);
extern void TtkScrollbar_Init(Tcl_Interp *);
extern void TtkSeparator_Init(Tcl_Interp *);
@@ -230,6 +231,7 @@ static void RegisterWidgets(Tcl_Interp *interp)
TtkNotebook_Init(interp);
TtkPanedwindow_Init(interp);
TtkProgressbar_Init(interp);
+ TtkRange_Init(interp);
TtkScale_Init(interp);
TtkScrollbar_Init(interp);
TtkSeparator_Init(interp);
diff --git a/generic/ttk/ttkRange.c b/generic/ttk/ttkRange.c
new file mode 100644
index 0000000..618b432
--- /dev/null
+++ b/generic/ttk/ttkRange.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright (C) 2011 Goodwin Lawlor goodwin.lawlor@gmail.com
+ *
+ * ttk::range widget.
+ */
+
+#include <tk.h>
+#include <string.h>
+#include <stdio.h>
+#include "ttkTheme.h"
+#include "ttkWidget.h"
+
+#define DEF_RANGE_LENGTH "100"
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+/*
+ * Range widget record
+ */
+typedef struct
+{
+ /* slider element options */
+ Tcl_Obj *fromObj; /* from value - lower bound*/
+ Tcl_Obj *toObj; /* to value - upper bound*/
+ Tcl_Obj *minvalueObj; /* min value */
+ Tcl_Obj *maxvalueObj; /* max value */
+ Tcl_Obj *lengthObj; /* length of the long axis of the range */
+ Tcl_Obj *orientObj; /* widget orientation */
+ int orient;
+
+ /* widget options */
+ Tcl_Obj *commandObj;
+ Tcl_Obj *minvariableObj;
+ Tcl_Obj *maxvariableObj;
+
+ /* internal state */
+ Ttk_TraceHandle *minvariableTrace;
+ Ttk_TraceHandle *maxvariableTrace;
+
+} RangePart;
+
+typedef struct
+{
+ WidgetCore core;
+ RangePart range;
+} Range;
+
+static Tk_OptionSpec RangeOptionSpecs[] =
+{
+ WIDGET_TAKES_FOCUS,
+
+ {TK_OPTION_STRING, "-command", "command", "Command", "",
+ Tk_Offset(Range,range.commandObj), -1,
+ TK_OPTION_NULL_OK,0,0},
+ {TK_OPTION_STRING, "-minvariable", "minvariable", "Minvariable", "",
+ Tk_Offset(Range,range.minvariableObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING, "-maxvariable", "maxvariable", "Maxvariable", "",
+ Tk_Offset(Range,range.maxvariableObj), -1,
+ 0,0,0},
+ {TK_OPTION_STRING_TABLE, "-orient", "orient", "Orient", "horizontal",
+ Tk_Offset(Range,range.orientObj),
+ Tk_Offset(Range,range.orient), 0,
+ (ClientData)ttkOrientStrings, STYLE_CHANGED },
+
+ {TK_OPTION_DOUBLE, "-from", "from", "From", "0",
+ Tk_Offset(Range,range.fromObj), -1, 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-to", "to", "To", "1.0",
+ Tk_Offset(Range,range.toObj), -1, 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-minvalue", "minvalue", "Minvalue", "0",
+ Tk_Offset(Range,range.minvalueObj), -1, 0, 0, 0},
+ {TK_OPTION_DOUBLE, "-maxvalue", "maxvalue", "Maxvalue", "1.0",
+ Tk_Offset(Range,range.maxvalueObj), -1, 0, 0, 0},
+ {TK_OPTION_PIXELS, "-length", "length", "Length",
+ DEF_RANGE_LENGTH, Tk_Offset(Range,range.lengthObj), -1, 0, 0,
+ GEOMETRY_CHANGED},
+
+ WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs)
+};
+
+static XPoint ValueToPoint(Range *rangePtr, double value);
+static double PointToValue(Range *rangePtr, int x, int y);
+
+/* RangeMinVariableChanged --
+ * Variable trace procedure for range -variable;
+ * Updates the range's value.
+ * If the linked variable is not a valid double,
+ * sets the 'invalid' state.
+ */
+static void RangeMinVariableChanged(void *recordPtr, const char *minvalue)
+{
+ Range *range = recordPtr;
+ double v;
+
+ if (minvalue == NULL || Tcl_GetDouble(0, minvalue, &v) != TCL_OK) {
+ TtkWidgetChangeState(&range->core, TTK_STATE_INVALID, 0);
+ } else {
+ Tcl_Obj *minvalueObj = Tcl_NewDoubleObj(v);
+ Tcl_IncrRefCount(minvalueObj);
+ Tcl_DecrRefCount(range->range.minvalueObj);
+ range->range.minvalueObj = minvalueObj;
+ TtkWidgetChangeState(&range->core, 0, TTK_STATE_INVALID);
+ }
+ TtkRedisplayWidget(&range->core);
+}
+
+/* RangeMaxVariableChanged --
+ * Variable trace procedure for range -variable;
+ * Updates the range's value.
+ * If the linked variable is not a valid double,
+ * sets the 'invalid' state.
+ */
+static void RangeMaxVariableChanged(void *recordPtr, const char *maxvalue)
+{
+ Range *range = recordPtr;
+ double v;
+
+ if (maxvalue == NULL || Tcl_GetDouble(0, maxvalue, &v) != TCL_OK) {
+ TtkWidgetChangeState(&range->core, TTK_STATE_INVALID, 0);
+ } else {
+ Tcl_Obj *maxvalueObj = Tcl_NewDoubleObj(v);
+ Tcl_IncrRefCount(maxvalueObj);
+ Tcl_DecrRefCount(range->range.maxvalueObj);
+ range->range.maxvalueObj = maxvalueObj;
+ TtkWidgetChangeState(&range->core, 0, TTK_STATE_INVALID);
+ }
+ TtkRedisplayWidget(&range->core);
+}
+
+/* RangeInitialize --
+ * Range widget initialization hook.
+ */
+static void RangeInitialize(Tcl_Interp *interp, void *recordPtr)
+{
+ Range *rangePtr = recordPtr;
+ TtkTrackElementState(&rangePtr->core);
+
+}
+
+static void RangeCleanup(void *recordPtr)
+{
+ Range *range = recordPtr;
+
+ if (range->range.minvariableTrace) {
+ Ttk_UntraceVariable(range->range.minvariableTrace);
+ range->range.minvariableTrace = 0;
+ }
+
+ if (range->range.maxvariableTrace) {
+ Ttk_UntraceVariable(range->range.maxvariableTrace);
+ range->range.maxvariableTrace = 0;
+ }
+}
+
+/* RangeConfigure --
+ * Configuration hook.
+ */
+static int RangeConfigure(Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Range *range = recordPtr;
+ Tcl_Obj *minvarName = range->range.minvariableObj;
+ Tcl_Obj *maxvarName = range->range.maxvariableObj;
+ Ttk_TraceHandle *minvt = 0;
+ Ttk_TraceHandle *maxvt = 0;
+
+ if (minvarName != NULL && *Tcl_GetString(minvarName) != '\0') {
+ minvt = Ttk_TraceVariable(interp,minvarName, RangeMinVariableChanged,recordPtr);
+ if (!minvt) return TCL_ERROR;
+ }
+
+ if (maxvarName != NULL && *Tcl_GetString(maxvarName) != '\0') {
+ maxvt = Ttk_TraceVariable(interp,maxvarName, RangeMaxVariableChanged,recordPtr);
+ if (!maxvt) return TCL_ERROR;
+ }
+
+ if (TtkCoreConfigure(interp, recordPtr, mask) != TCL_OK) {
+ if (minvt) Ttk_UntraceVariable(minvt);
+ if (maxvt) Ttk_UntraceVariable(maxvt);
+ return TCL_ERROR;
+ }
+
+ if (range->range.minvariableTrace) {
+ Ttk_UntraceVariable(range->range.minvariableTrace);
+ }
+ range->range.minvariableTrace = minvt;
+
+ if (range->range.maxvariableTrace) {
+ Ttk_UntraceVariable(range->range.maxvariableTrace);
+ }
+ range->range.maxvariableTrace = maxvt;
+
+ return TCL_OK;
+}
+
+/* RangePostConfigure --
+ * Post-configuration hook.
+ */
+static int RangePostConfigure(
+ Tcl_Interp *interp, void *recordPtr, int mask)
+{
+ Range *range = recordPtr;
+ int minstatus = TCL_OK;
+ int maxstatus = TCL_OK;
+
+ if (range->range.minvariableTrace) {
+ minstatus = Ttk_FireTrace(range->range.minvariableTrace);
+ if (WidgetDestroyed(&range->core)) {
+ return TCL_ERROR;
+ }
+ if (minstatus != TCL_OK) {
+ /* Unset -variable: */
+ Ttk_UntraceVariable(range->range.minvariableTrace);
+ Tcl_DecrRefCount(range->range.minvariableObj);
+ range->range.minvariableTrace = 0;
+ range->range.minvariableObj = NULL;
+ minstatus = TCL_ERROR;
+ }
+ }
+
+ if (range->range.maxvariableTrace) {
+ maxstatus = Ttk_FireTrace(range->range.maxvariableTrace);
+ if (WidgetDestroyed(&range->core)) {
+ return TCL_ERROR;
+ }
+ if (maxstatus != TCL_OK) {
+ /* Unset -variable: */
+ Ttk_UntraceVariable(range->range.maxvariableTrace);
+ Tcl_DecrRefCount(range->range.maxvariableObj);
+ range->range.maxvariableTrace = 0;
+ range->range.maxvariableObj = NULL;
+ maxstatus = TCL_ERROR;
+ }
+ }
+ if (minstatus != TCL_OK || maxstatus != TCL_OK) {
+ return TCL_ERROR;
+ } else {
+ return TCL_OK;
+ }
+
+}
+
+/* RangeGetLayout --
+ * getLayout hook.
+ */
+static Ttk_Layout
+RangeGetLayout(Tcl_Interp *interp, Ttk_Theme theme, void *recordPtr)
+{
+ Range *rangePtr = recordPtr;
+ return TtkWidgetGetOrientedLayout(
+ interp, theme, recordPtr, rangePtr->range.orientObj);
+}
+
+/*
+ * TroughBox --
+ * Returns the inner area of the trough element.
+ */
+static Ttk_Box TroughBox(Range *rangePtr)
+{
+ return Ttk_ClientRegion(rangePtr->core.layout, "trough");
+}
+
+/*
+ * TroughRange --
+ * Return the value area of the trough element, adjusted
+ * for slider size.
+ */
+static Ttk_Box TroughRange(Range *rangePtr)
+{
+ Ttk_Box troughBox = TroughBox(rangePtr);
+ Ttk_Element slider = Ttk_FindElement(rangePtr->core.layout,"minslider");
+
+ /*
+ * If this is a range widget, adjust range for slider:
+ */
+ if (slider) {
+ Ttk_Box sliderBox = Ttk_ElementParcel(slider);
+ if (rangePtr->range.orient == TTK_ORIENT_HORIZONTAL) {
+ troughBox.x += sliderBox.width / 2;
+ troughBox.width -= sliderBox.width;
+ } else {
+ troughBox.y += sliderBox.height / 2;
+ troughBox.height -= sliderBox.height;
+ }
+ }
+
+ return troughBox;
+}
+
+/*
+ * RangeFraction --
+ */
+static double RangeFraction(Range *rangePtr, double value)
+{
+ double from = 0, to = 1, fraction;
+
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.fromObj, &from);
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.toObj, &to);
+
+ if (from == to) {
+ return 1.0;
+ }
+
+ fraction = (value - from) / (to - from);
+
+ return fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;
+}
+
+/* $range get ?x y? --
+ * Returns the current value of the range widget, or if $x and
+ * $y are specified, the value represented by point @x,y.
+ */
+static int
+RangeGetCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ int x, y, r = TCL_OK;
+ double value = 0;
+
+ if (objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "get ?x y?");
+ return TCL_ERROR;
+ }
+
+ r = Tcl_GetIntFromObj(interp, objv[2], &x);
+ if (r == TCL_OK)
+ r = Tcl_GetIntFromObj(interp, objv[3], &y);
+ if (r == TCL_OK) {
+ value = PointToValue(rangePtr, x, y);
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(value));
+ }
+
+ return r;
+}
+
+static int
+RangeGetMinCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "getmin");
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, rangePtr->range.minvalueObj);
+
+ return TCL_OK;
+}
+
+static int
+RangeGetMaxCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "getmax");
+ return TCL_ERROR;
+ }
+
+ Tcl_SetObjResult(interp, rangePtr->range.maxvalueObj);
+
+ return TCL_OK;
+}
+
+/* $range setmin $newValue
+ */
+static int
+RangeSetMinCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ double from = 0.0, to = 1.0, minvalue, maxvalue;
+ int result = TCL_OK;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "setmin value");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &minvalue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (rangePtr->core.state & TTK_STATE_DISABLED) {
+ return TCL_OK;
+ }
+
+ /* ASSERT: fromObj and toObj are valid doubles.
+ */
+ Tcl_GetDoubleFromObj(interp, rangePtr->range.fromObj, &from);
+ Tcl_GetDoubleFromObj(interp, rangePtr->range.toObj, &to);
+
+ /* Limit new value to between 'from' and 'to':
+ */
+ if (from < to) {
+ minvalue = minvalue < from ? from : minvalue > to ? to : minvalue;
+ } else {
+ minvalue = minvalue < to ? to : minvalue > from ? from : minvalue;
+ }
+
+ // Must be <= maxvalue too.
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.maxvalueObj, &maxvalue);
+ minvalue = minvalue < maxvalue ? minvalue : maxvalue;
+
+ /*
+ * Set value:
+ */
+ Tcl_DecrRefCount(rangePtr->range.minvalueObj);
+ rangePtr->range.minvalueObj = Tcl_NewDoubleObj(minvalue);
+ Tcl_IncrRefCount(rangePtr->range.minvalueObj);
+ TtkRedisplayWidget(&rangePtr->core);
+
+ /*
+ * Set attached variable, if any:
+ */
+ if (rangePtr->range.minvariableObj != NULL) {
+ Tcl_ObjSetVar2(interp, rangePtr->range.minvariableObj, NULL,
+ rangePtr->range.minvalueObj, TCL_GLOBAL_ONLY);
+ }
+ if (WidgetDestroyed(&rangePtr->core)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Invoke -command, if any:
+ */
+ if (rangePtr->range.commandObj != NULL) {
+ Tcl_Obj *cmdObj = Tcl_DuplicateObj(rangePtr->range.commandObj);
+ Tcl_IncrRefCount(cmdObj);
+ Tcl_AppendToObj(cmdObj, " ", 1);
+ Tcl_AppendObjToObj(cmdObj, rangePtr->range.minvalueObj);
+ Tcl_AppendToObj(cmdObj, " ", 1);
+ Tcl_AppendObjToObj(cmdObj, rangePtr->range.maxvalueObj);
+ result = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(cmdObj);
+ }
+
+ return result;
+}
+
+/* $range setmax $newValue
+ */
+static int
+RangeSetMaxCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ double from = 0.0, to = 1.0, minvalue, maxvalue;
+ int result = TCL_OK;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "setmax value");
+ return TCL_ERROR;
+ }
+
+ if (Tcl_GetDoubleFromObj(interp, objv[2], &maxvalue) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (rangePtr->core.state & TTK_STATE_DISABLED) {
+ return TCL_OK;
+ }
+
+ /* ASSERT: fromObj and toObj are valid doubles.
+ */
+ Tcl_GetDoubleFromObj(interp, rangePtr->range.fromObj, &from);
+ Tcl_GetDoubleFromObj(interp, rangePtr->range.toObj, &to);
+
+ /* Limit new value to between 'from' and 'to':
+ */
+ if (from < to) {
+ maxvalue = maxvalue < from ? from : maxvalue > to ? to : maxvalue;
+ } else {
+ maxvalue = maxvalue < to ? to : maxvalue > from ? from : maxvalue;
+ }
+
+ // Must be >= minvalue too.
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.minvalueObj, &minvalue);
+ maxvalue = maxvalue > minvalue ? maxvalue : minvalue;
+
+ /*
+ * Set value:
+ */
+ Tcl_DecrRefCount(rangePtr->range.maxvalueObj);
+ rangePtr->range.maxvalueObj = Tcl_NewDoubleObj(maxvalue);
+ Tcl_IncrRefCount(rangePtr->range.maxvalueObj);
+ TtkRedisplayWidget(&rangePtr->core);
+
+ /*
+ * Set attached variable, if any:
+ */
+ if (rangePtr->range.maxvariableObj != NULL) {
+ Tcl_ObjSetVar2(interp, rangePtr->range.maxvariableObj, NULL,
+ rangePtr->range.maxvalueObj, TCL_GLOBAL_ONLY);
+ }
+ if (WidgetDestroyed(&rangePtr->core)) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Invoke -command, if any:
+ */
+ if (rangePtr->range.commandObj != NULL) {
+ Tcl_Obj *cmdObj = Tcl_DuplicateObj(rangePtr->range.commandObj);
+ Tcl_IncrRefCount(cmdObj);
+ Tcl_AppendToObj(cmdObj, " ", 1);
+ Tcl_AppendObjToObj(cmdObj, rangePtr->range.minvalueObj);
+ Tcl_AppendToObj(cmdObj, " ", 1);
+ Tcl_AppendObjToObj(cmdObj, rangePtr->range.maxvalueObj);
+ result = Tcl_EvalObjEx(interp, cmdObj, TCL_EVAL_GLOBAL);
+ Tcl_DecrRefCount(cmdObj);
+ }
+
+ return result;
+}
+
+static int
+RangeCoordsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ double value;
+ int r = TCL_OK;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "coords ?value?");
+ return TCL_ERROR;
+ }
+
+ r = Tcl_GetDoubleFromObj(interp, objv[2], &value);
+
+ if (r == TCL_OK) {
+ Tcl_Obj *point[2];
+ XPoint pt = ValueToPoint(rangePtr, value);
+ point[0] = Tcl_NewIntObj(pt.x);
+ point[1] = Tcl_NewIntObj(pt.y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, point));
+ }
+ return r;
+}
+
+static int
+RangeMinCoordsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ double value;
+ int r = TCL_OK;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "mincoords");
+ return TCL_ERROR;
+ }
+
+ r = Tcl_GetDoubleFromObj(interp, rangePtr->range.minvalueObj, &value);
+
+ if (r == TCL_OK) {
+ Tcl_Obj *point[2];
+ XPoint pt = ValueToPoint(rangePtr, value);
+ point[0] = Tcl_NewIntObj(pt.x);
+ point[1] = Tcl_NewIntObj(pt.y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, point));
+ }
+ return r;
+}
+
+static int
+RangeMaxCoordsCommand(
+ void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+{
+ Range *rangePtr = recordPtr;
+ double value;
+ int r = TCL_OK;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "maxcoords");
+ return TCL_ERROR;
+ }
+
+ r = Tcl_GetDoubleFromObj(interp, rangePtr->range.maxvalueObj, &value);
+
+ if (r == TCL_OK) {
+ Tcl_Obj *point[2];
+ XPoint pt = ValueToPoint(rangePtr, value);
+ point[0] = Tcl_NewIntObj(pt.x);
+ point[1] = Tcl_NewIntObj(pt.y);
+ Tcl_SetObjResult(interp, Tcl_NewListObj(2, point));
+ }
+ return r;
+}
+
+static void RangeDoLayout(void *clientData)
+{
+ WidgetCore *corePtr = clientData;
+ Ttk_Element minslider = Ttk_FindElement(corePtr->layout, "minslider");
+ Ttk_Element maxslider = Ttk_FindElement(corePtr->layout, "maxslider");
+
+ Ttk_PlaceLayout(corePtr->layout,corePtr->state,Ttk_WinBox(corePtr->tkwin));
+
+ /* Adjust the slider position:
+ */
+ if (minslider && maxslider) {
+ Range *rangePtr = clientData;
+ Ttk_Box troughBox = TroughBox(rangePtr);
+ Ttk_Box minsliderBox = Ttk_ElementParcel(minslider);
+ Ttk_Box maxsliderBox = Ttk_ElementParcel(maxslider);
+ double minvalue = 0.0, maxvalue = 1.0;
+ double minfraction, maxfraction;
+ int range, offset;
+
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.minvalueObj, &minvalue);
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.maxvalueObj, &maxvalue);
+ minfraction = RangeFraction(rangePtr, minvalue);
+ maxfraction = RangeFraction(rangePtr, maxvalue);
+
+ if (rangePtr->range.orient == TTK_ORIENT_HORIZONTAL) {
+ range = troughBox.width - minsliderBox.width;
+ offset = minsliderBox.x;
+ minsliderBox.x = offset + (int)(minfraction * range);
+ maxsliderBox.x = offset + (int)(maxfraction * range);
+ } else {
+ range = troughBox.height - minsliderBox.height;
+ offset = minsliderBox.y;
+ minsliderBox.y = offset + (int)(minfraction * range);
+ maxsliderBox.y = offset + (int)(maxfraction * range);
+ }
+
+ Ttk_PlaceElement(corePtr->layout, minslider, minsliderBox);
+ Ttk_PlaceElement(corePtr->layout, maxslider, maxsliderBox);
+
+ }
+}
+
+/*
+ * RangeSize --
+ * Compute requested size of range.
+ */
+static int RangeSize(void *clientData, int *widthPtr, int *heightPtr)
+{
+ WidgetCore *corePtr = clientData;
+ Range *rangePtr = clientData;
+ int length;
+
+ Ttk_LayoutSize(corePtr->layout, corePtr->state, widthPtr, heightPtr);
+
+ /* Assert the -length configuration option */
+ Tk_GetPixelsFromObj(NULL, corePtr->tkwin,
+ rangePtr->range.lengthObj, &length);
+ if (rangePtr->range.orient == TTK_ORIENT_VERTICAL) {
+ *heightPtr = MAX(*heightPtr, length);
+ } else {
+ *widthPtr = MAX(*widthPtr, length);
+ }
+
+ return 1;
+}
+
+static double
+PointToValue(Range *rangePtr, int x, int y)
+{
+ Ttk_Box troughBox = TroughRange(rangePtr);
+ double from = 0, to = 1, fraction;
+
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.fromObj, &from);
+ Tcl_GetDoubleFromObj(NULL, rangePtr->range.toObj, &to);
+
+ if (rangePtr->range.orient == TTK_ORIENT_HORIZONTAL) {
+ fraction = (double)(x - troughBox.x) / (double)troughBox.width;
+ } else {
+ fraction = (double)(y - troughBox.y) / (double)troughBox.height;
+ }
+
+ fraction = fraction < 0 ? 0 : fraction > 1 ? 1 : fraction;
+
+ return from + fraction * (to-from);
+}
+
+/*
+ * Return the center point in the widget corresponding to the given
+ * value. This point can be used to center the slider.
+ */
+
+static XPoint
+ValueToPoint(Range *rangePtr, double value)
+{
+ Ttk_Box troughBox = TroughRange(rangePtr);
+ double fraction = RangeFraction(rangePtr, value);
+ XPoint pt = {0, 0};
+
+ if (rangePtr->range.orient == TTK_ORIENT_HORIZONTAL) {
+ pt.x = troughBox.x + (int)(fraction * troughBox.width);
+ pt.y = troughBox.y + troughBox.height / 2;
+ } else {
+ pt.x = troughBox.x + troughBox.width / 2;
+ pt.y = troughBox.y + (int)(fraction * troughBox.height);
+ }
+ return pt;
+}
+
+static const Ttk_Ensemble RangeCommands[] = {
+ { "configure", TtkWidgetConfigureCommand,0 },
+ { "cget", TtkWidgetCgetCommand,0 },
+ { "state", TtkWidgetStateCommand,0 },
+ { "instate", TtkWidgetInstateCommand,0 },
+ { "identify", TtkWidgetIdentifyCommand,0 },
+ { "setmin", RangeSetMinCommand,0 },
+ { "setmax", RangeSetMaxCommand,0 },
+ { "get", RangeGetCommand,0 },
+ { "getmin", RangeGetMinCommand,0 },
+ { "getmax", RangeGetMaxCommand,0 },
+ { "coords", RangeCoordsCommand,0 },
+ { "mincoords", RangeMinCoordsCommand,0 },
+ { "maxcoords", RangeMaxCoordsCommand,0 },
+ { 0,0,0 }
+};
+
+static WidgetSpec RangeWidgetSpec =
+{
+ "TRange", /* Class name */
+ sizeof(Range), /* record size */
+ RangeOptionSpecs, /* option specs */
+ RangeCommands, /* widget commands */
+ RangeInitialize, /* initialization proc */
+ RangeCleanup, /* cleanup proc */
+ RangeConfigure, /* configure proc */
+ RangePostConfigure, /* postConfigure */
+ RangeGetLayout, /* getLayoutProc */
+ RangeSize, /* sizeProc */
+ RangeDoLayout, /* layoutProc */
+ TtkWidgetDisplay /* displayProc */
+};
+
+TTK_BEGIN_LAYOUT(VerticalRangeLayout)
+ TTK_GROUP("Vertical.Range.trough", TTK_FILL_BOTH,
+ TTK_NODE("Vertical.Range.minslider", TTK_PACK_TOP)
+ TTK_NODE("Vertical.Range.maxslider", TTK_PACK_BOTTOM) )
+TTK_END_LAYOUT
+
+TTK_BEGIN_LAYOUT(HorizontalRangeLayout)
+ TTK_GROUP("Horizontal.Range.trough", TTK_FILL_BOTH,
+ TTK_NODE("Horizontal.Range.minslider", TTK_PACK_LEFT)
+ TTK_NODE("Horizontal.Range.maxslider", TTK_PACK_RIGHT) )
+TTK_END_LAYOUT
+
+/*
+ * Initialization.
+ */
+MODULE_SCOPE
+void TtkRange_Init(Tcl_Interp *interp)
+{
+ Ttk_Theme theme = Ttk_GetDefaultTheme(interp);
+
+ Ttk_RegisterLayout(theme, "Vertical.TRange", VerticalRangeLayout);
+ Ttk_RegisterLayout(theme, "Horizontal.TRange", HorizontalRangeLayout);
+
+ RegisterWidget(interp, "ttk::range", &RangeWidgetSpec);
+}
+
diff --git a/library/ttk/altTheme.tcl b/library/ttk/altTheme.tcl
index d57227c..20bde48 100644
--- a/library/ttk/altTheme.tcl
+++ b/library/ttk/altTheme.tcl
@@ -95,6 +95,9 @@ namespace eval ttk::theme::alt {
ttk::style configure TScale \
-groovewidth 4 -troughrelief sunken \
-sliderwidth raised -borderwidth 2
+ ttk::style configure TRange \
+ -groovewidth 4 -troughrelief sunken \
+ -sliderwidth raised -borderwidth 2
ttk::style configure TProgressbar \
-background $colors(-selectbg) -borderwidth 0
}
diff --git a/library/ttk/classicTheme.tcl b/library/ttk/classicTheme.tcl
index 7e3eff5..5c1f91c 100644
--- a/library/ttk/classicTheme.tcl
+++ b/library/ttk/classicTheme.tcl
@@ -82,6 +82,9 @@ namespace eval ttk::theme::classic {
ttk::style configure TScale -sliderrelief raised
ttk::style map TScale -sliderrelief {{pressed !disabled} sunken}
+
+ ttk::style configure TRange -sliderrelief raised
+ ttk::style map TRange -sliderrelief {{pressed !disabled} sunken}
ttk::style configure TProgressbar -background SteelBlue
ttk::style configure TNotebook.Tab \
diff --git a/library/ttk/defaults.tcl b/library/ttk/defaults.tcl
index 05a46bd..42032b4 100644
--- a/library/ttk/defaults.tcl
+++ b/library/ttk/defaults.tcl
@@ -79,6 +79,8 @@ namespace eval ttk::theme::default {
ttk::style configure TScale \
-sliderrelief raised
+ ttk::style configure TRange \
+ -sliderrelief raised
ttk::style configure TProgressbar \
-background $colors(-selectbg)
diff --git a/library/ttk/range.tcl b/library/ttk/range.tcl
new file mode 100644
index 0000000..1608dfb
--- /dev/null
+++ b/library/ttk/range.tcl
@@ -0,0 +1,135 @@
+# range.tcl - Copyright (C) 2011 Goodwin Lawlor
+#
+# Bindings for the TRange widget
+
+namespace eval ttk::range {
+ variable State
+ array set State {
+ dragging 0
+ }
+}
+
+bind TRange <ButtonPress-1> { ttk::range::Press %W %x %y }
+bind TRange <B1-Motion> { ttk::range::Drag %W %x %y }
+bind TRange <ButtonRelease-1> { ttk::range::Release %W %x %y }
+
+bind TRange <ButtonPress-2> { ttk::range::Jump %W %x %y }
+bind TRange <B2-Motion> { ttk::range::Drag %W %x %y }
+bind TRange <ButtonRelease-2> { ttk::range::Release %W %x %y }
+
+bind TRange <ButtonPress-3> { ttk::range::Jump %W %x %y }
+bind TRange <B3-Motion> { ttk::range::Drag %W %x %y }
+bind TRange <ButtonRelease-3> { ttk::range::Release %W %x %y }
+
+bind TRange <Left> { ttk::range::Increment %W -1 }
+bind TRange <Up> { ttk::range::Increment %W -1 }
+bind TRange <Right> { ttk::range::Increment %W 1 }
+bind TRange <Down> { ttk::range::Increment %W 1 }
+bind TRange <Control-Left> { ttk::range::Increment %W -10 }
+bind TRange <Control-Up> { ttk::range::Increment %W -10 }
+bind TRange <Control-Right> { ttk::range::Increment %W 10 }
+bind TRange <Control-Down> { ttk::range::Increment %W 10 }
+bind TRange <Home> { %W set [%W cget -from] }
+bind TRange <End> { %W set [%W cget -to] }
+
+proc ttk::range::Press {w x y} {
+ variable State
+ set State(dragging) 0
+
+ switch -glob -- [$w identify $x $y] {
+ *track -
+ *trough {
+ set val [$w get $x $y]
+ set min [$w getmin]
+ set max [$w getmax]
+ if {$val < $min} {
+ #increment min
+ ttk::Repeatedly IncrementMin $w -0.1
+ } elseif {$val > $max} {
+ #increment max
+ ttk::Repeatedly IncrementMax $w +0.1
+ } else {
+ set State(dragging) 3
+ set State(initial) [$w get $x $y]
+ }
+ }
+ *minslider {
+ set State(dragging) 1
+ set State(initial) [$w getmin]
+ }
+ *maxslider {
+ # hack to prevent minslider hidding under the maxslider
+ # when both are at the "to" value
+ if {[$w getmin] == [$w cget -to]} {
+ set State(dragging) 1
+ } else {
+ set State(dragging) 2
+ }
+
+ set State(initial) [$w getmax]
+ }
+ }
+}
+
+# range::Jump -- ButtonPress-2/3 binding for range acts like
+# Press except that clicking in the trough jumps to the
+# clicked position.
+proc ttk::range::Jump {w x y} {
+ variable State
+ set State(dragging) 0
+
+ switch -glob -- [$w identify $x $y] {
+ *track -
+ *trough {
+ set val [$w get $x $y]
+ set min [$w getmin]
+ set max [$w getmax]
+ if {$val < $min} {
+ #jump min
+ $w setmin $val
+ set State(initial) [$w get $x $y]
+ } elseif {$val > $max} {
+ #jump max
+ $w setmax $val
+ set State(initial) [$w get $x $y]
+ } else {
+ set State(dragging) 3
+ set State(initial) [$w get $x $y]
+ }
+ }
+ *slider {
+ Press $w $x $y
+ }
+ }
+}
+
+proc ttk::range::Drag {w x y} {
+ variable State
+ if {$State(dragging) eq 1} {
+ $w setmin [$w get $x $y]
+ } elseif {$State(dragging) eq 2} {
+ $w setmax [$w get $x $y]
+ } else {
+ set v [$w get $x $y]
+ set dv [expr $v - $State(initial)]
+ $w setmin [expr [$w getmin] + $dv]
+ $w setmax [expr [$w getmax] + $dv]
+ set State(initial) $v
+ }
+}
+
+proc ttk::range::Release {w x y} {
+ variable State
+ set State(dragging) 0
+ ttk::CancelRepeat
+}
+
+proc ttk::range::IncrementMin {w delta} {
+ if {![winfo exists $w]} return
+ $w setmin [expr {[$w getmin] + $delta}]
+}
+
+proc ttk::range::IncrementMax {w delta} {
+ if {![winfo exists $w]} return
+ $w setmax [expr {[$w getmax] + $delta}]
+}
diff --git a/library/ttk/ttk.tcl b/library/ttk/ttk.tcl
index 7bae211..04ac959 100644
--- a/library/ttk/ttk.tcl
+++ b/library/ttk/ttk.tcl
@@ -109,6 +109,7 @@ source [file join $::ttk::library combobox.tcl] ;# dependency: entry.tcl
source [file join $::ttk::library spinbox.tcl] ;# dependency: entry.tcl
source [file join $::ttk::library treeview.tcl]
source [file join $::ttk::library sizegrip.tcl]
+source [file join $::ttk::library range.tcl]
## Label and Labelframe bindings:
# (not enough to justify their own file...)
diff --git a/library/ttk/vistaTheme.tcl b/library/ttk/vistaTheme.tcl
index 99410cb..749042f 100644
--- a/library/ttk/vistaTheme.tcl
+++ b/library/ttk/vistaTheme.tcl
@@ -215,6 +215,38 @@ namespace eval ttk::theme::vista {
}
}
}
+
+ # Range
+ ttk::style element create Horizontal.Range.minslider vsapi \
+ TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 6 -height 12
+ ttk::style element create Horizontal.Range.maxslider vsapi \
+ TRACKBAR 3 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 6 -height 12
+ ttk::style layout Horizontal.TRange {
+ Range.focus -expand 1 -sticky nswe -children {
+ Horizontal.Range.trough -expand 1 -sticky nswe -children {
+ Horizontal.Range.track -sticky we
+ Horizontal.Range.minslider -side left -sticky {}
+ Horizontal.Range.maxslider -side right -sticky {}
+ }
+ }
+ }
+ ttk::style element create Vertical.Range.minslider vsapi \
+ TRACKBAR 6 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 12 -height 6
+ ttk::style element create Vertical.Range.maxslider vsapi \
+ TRACKBAR 6 {disabled 5 focus 4 pressed 3 active 2 {} 1} \
+ -width 12 -height 6
+ ttk::style layout Vertical.TRange {
+ Range.focus -expand 1 -sticky nswe -children {
+ Vertical.Range.trough -expand 1 -sticky nswe -children {
+ Vertical.Range.track -sticky ns
+ Vertical.Range.maxslider -side top -sticky {}
+ Vertical.Range.minslider -side bottom -sticky {}
+ }
+ }
+ }
# Treeview
ttk::style configure Item -padding {4 0 0 0}
diff --git a/library/ttk/winTheme.tcl b/library/ttk/winTheme.tcl
index 55367bc..909e82f 100644
--- a/library/ttk/winTheme.tcl
+++ b/library/ttk/winTheme.tcl
@@ -62,6 +62,8 @@ namespace eval ttk::theme::winnative {
{disabled flat selected sunken pressed sunken active raised}
ttk::style configure TScale -groovewidth 4
+
+ ttk::style configure TRange groovewidth 4
ttk::style configure TNotebook -tabmargins {2 2 2 0}
ttk::style configure TNotebook.Tab -padding {3 1} -borderwidth 1
diff --git a/unix/Makefile.in b/unix/Makefile.in
index a38ff74..23d6056 100644
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -374,8 +374,8 @@ TTK_OBJS = \
ttkBlink.o ttkButton.o ttkCache.o ttkClamTheme.o ttkClassicTheme.o \
ttkDefaultTheme.o ttkElements.o ttkEntry.o ttkFrame.o ttkImage.o \
ttkInit.o ttkLabel.o ttkLayout.o ttkManager.o ttkNotebook.o \
- ttkPanedwindow.o ttkProgress.o ttkScale.o ttkScrollbar.o ttkScroll.o \
- ttkSeparator.o ttkSquare.o ttkState.o \
+ ttkPanedwindow.o ttkProgress.o ttkRange.o ttkScale.o ttkScrollbar.o \
+ ttkScroll.o ttkSeparator.o ttkSquare.o ttkState.o \
ttkTagSet.o ttkTheme.o ttkTrace.o ttkTrack.o ttkTreeview.o \
ttkWidget.o ttkStubInit.o
@@ -475,6 +475,7 @@ TTK_SRCS = \
$(TTK_DIR)/ttkNotebook.c \
$(TTK_DIR)/ttkPanedwindow.c \
$(TTK_DIR)/ttkProgress.c \
+ $(TTK_DIR)/ttkRange.c \
$(TTK_DIR)/ttkScale.c \
$(TTK_DIR)/ttkScrollbar.c \
$(TTK_DIR)/ttkScroll.c \
@@ -1383,6 +1384,9 @@ ttkPanedwindow.o: $(TTK_DIR)/ttkPanedwindow.c
ttkProgress.o: $(TTK_DIR)/ttkProgress.c
$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkProgress.c
+ttkRange.o: $(TTK_DIR)/ttkRange.c
+ $(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkRange.c
+
ttkScale.o: $(TTK_DIR)/ttkScale.c
$(CC) -c $(CC_SWITCHES) $(TTK_DIR)/ttkScale.c
diff --git a/win/makefile.vc b/win/makefile.vc
index 14dc2d0..3e76985 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -385,6 +385,7 @@ TTK_OBJS = \
$(TMP_DIR)\ttkNotebook.obj \
$(TMP_DIR)\ttkPanedwindow.obj \
$(TMP_DIR)\ttkProgress.obj \
+ $(TMP_DIR)\ttkRange.obj \
$(TMP_DIR)\ttkScale.obj \
$(TMP_DIR)\ttkScrollbar.obj \
$(TMP_DIR)\ttkScroll.obj \
diff --git a/win/ttkWinXPTheme.c b/win/ttkWinXPTheme.c
index af6103b..33f44d0 100644
--- a/win/ttkWinXPTheme.c
+++ b/win/ttkWinXPTheme.c
@@ -339,6 +339,15 @@ static Ttk_StateTable scale_statemap[] =
{ TUS_NORMAL, 0, 0 }
};
+static Ttk_StateTable range_statemap[] =
+{
+ { TUS_DISABLED, TTK_STATE_DISABLED, 0 },
+ { TUS_PRESSED, TTK_STATE_PRESSED, 0 },
+ { TUS_FOCUSED, TTK_STATE_FOCUS, 0 },
+ { TUS_HOT, TTK_STATE_ACTIVE, 0 },
+ { TUS_NORMAL, 0, 0 }
+};
+
static Ttk_StateTable tabitem_statemap[] =
{
{ TIS_DISABLED, TTK_STATE_DISABLED, 0 },
@@ -932,6 +941,20 @@ TTK_LAYOUT("Vertical.TScale",
TTK_NODE("Vertical.Scale.track", TTK_FILL_Y)
TTK_NODE("Vertical.Scale.slider", TTK_PACK_TOP) )))
+TTK_LAYOUT("Horizontal.TRange",
+ TTK_GROUP("Range.focus", TTK_EXPAND|TTK_FILL_BOTH,
+ TTK_GROUP("Horizontal.Range.trough", TTK_EXPAND|TTK_FILL_BOTH,
+ TTK_NODE("Horizontal.Range.track", TTK_FILL_X)
+ TTK_NODE("Horizontal.Range.minslider", TTK_PACK_LEFT)
+ TTK_NODE("Horizontal.Range.maxslider", TTK_PACK_RIGHT) )))
+
+TTK_LAYOUT("Vertical.TRange",
+ TTK_GROUP("Range.focus", TTK_EXPAND|TTK_FILL_BOTH,
+ TTK_GROUP("Vertical.Range.trough", TTK_EXPAND|TTK_FILL_BOTH,
+ TTK_NODE("Vertical.Range.track", TTK_FILL_Y)
+ TTK_NODE("Vertical.Range.minslider", TTK_PACK_TOP)
+ TTK_NODE("Vertical.Range.maxslider", TTK_PACK_BOTTOM) )))
+
TTK_END_LAYOUT_TABLE
/*----------------------------------------------------------------------
@@ -991,6 +1014,14 @@ static ElementInfo ElementInfoTable[] = {
TKP_TRACK, scale_statemap, NOPAD, 0 },
{ "Vertical.Scale.track", &GenericElementSpec, L"TRACKBAR",
TKP_TRACKVERT, scale_statemap, NOPAD, 0 },
+ { "Horizontal.Range.slider", &GenericElementSpec, L"TRACKBAR",
+ TKP_THUMB, range_statemap, NOPAD, 0 },
+ { "Vertical.Range.slider", &GenericElementSpec, L"TRACKBAR",
+ TKP_THUMBVERT, range_statemap, NOPAD, 0 },
+ { "Horizontal.Range.track", &GenericElementSpec, L"TRACKBAR",
+ TKP_TRACK, range_statemap, NOPAD, 0 },
+ { "Vertical.Range.track", &GenericElementSpec, L"TRACKBAR",
+ TKP_TRACKVERT, range_statemap, NOPAD, 0 },
/* ttk::progressbar elements */
{ "Horizontal.Progressbar.pbar", &PbarElementSpec, L"PROGRESS",
PP_CHUNK, null_statemap, NOPAD, 0 },
@@ -1309,6 +1340,7 @@ MODULE_SCOPE int TtkXPTheme_Init(Tcl_Interp *interp, HWND hwnd)
}
Ttk_RegisterElementSpec(themePtr, "Scale.trough", &ttkNullElementSpec, 0);
+ Ttk_RegisterElementSpec(themePtr, "Range.trough", &ttkNullElementSpec, 0);
/*
* Layouts: