From a33829db9b4dbd38bd5293e7c21aa2ff68019188 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 11 Apr 2019 20:55:07 +0000 Subject: Fix [ce470f20fd]: ttk::treeview allows dragging the right edge of the rightmost heading --- library/ttk/treeview.tcl | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 1ed87db..2675a67 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -106,7 +106,12 @@ proc ttk::treeview::Motion {w x y} { set activeHeading {} switch -- [$w identify region $x $y] { - separator { set cursor hresize } + separator { + if {[ttk::treeview::LastDisplayColumn $w] ne + [$w identify column $x $y]} { + set cursor hresize + } + } heading { set activeHeading [$w identify column $x $y] } } @@ -201,7 +206,9 @@ proc ttk::treeview::resize.press {w x y} { proc ttk::treeview::resize.drag {w x} { variable State - $w drag $State(resizeColumn) $x + if {[ttk::treeview::LastDisplayColumn $w] ne $State(resizeColumn)} { + $w drag $State(resizeColumn) $x + } } proc ttk::treeview::resize.release {w x} { @@ -360,4 +367,16 @@ proc ttk::treeview::BrowseTo {w item} { $w selection set [list $item] } +## LastDisplayColumn -- return the data column identifier of the column +# displayed rightmost, in the form #n +# +proc ttk::treeview::LastDisplayColumn {w} { + set dc [$w cget -displaycolumns] + if {$dc eq "#all"} { + return #[llength [$w cget -columns]] + } else { + return #[llength $dc] + } +} + #*EOF* -- cgit v0.12 From 4fd05535bc46d88f567bf8505127560b96e41768 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 11 Apr 2019 21:00:11 +0000 Subject: Fix indentation --- library/ttk/treeview.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 2675a67..149ecdc 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -108,7 +108,7 @@ proc ttk::treeview::Motion {w x y} { switch -- [$w identify region $x $y] { separator { if {[ttk::treeview::LastDisplayColumn $w] ne - [$w identify column $x $y]} { + [$w identify column $x $y]} { set cursor hresize } } -- cgit v0.12 From 7a5c4c251176f7d527f292f21e9048da93fbc4c9 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 13 Apr 2019 11:39:17 +0000 Subject: Fix another issue reported in [ce470f20fd]: dragging of separators shall not be allowed to escape out of the treeview area. --- generic/ttk/ttkTreeview.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 68a9b6d..fcf9992 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2885,9 +2885,23 @@ static int TreeviewDragCommand( TreeColumn *c = tv->tree.displayColumns[i]; int right = left + c->width; if (c == column) { - DragColumn(tv, i, newx - right); - /* ASSERT: SLACKINVARIANT */ - TtkRedisplayWidget(&tv->core); + /* The limit not to exceed at the right is given by the tree width + minus the sum of the min widths of the columns at the right of + the one being resized (and don't forget possible x scrolling!). + */ + int newxRightLimit = tv->tree.treeArea.x - tv->tree.xscroll.first + + tv->tree.treeArea.width; + int j = i + 1; + while (j < tv->tree.nDisplayColumns) { + TreeColumn *cr = tv->tree.displayColumns[j]; + newxRightLimit -= cr->minWidth; + ++j; + } + if (newx <= newxRightLimit) { + DragColumn(tv, i, newx - right); + /* ASSERT: SLACKINVARIANT */ + TtkRedisplayWidget(&tv->core); + } return TCL_OK; } left = right; -- cgit v0.12 From dd01abc1045a974f417f5d4f39018ae36b7b87d2 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 13 Apr 2019 20:54:50 +0000 Subject: Add test treeview-ce470f20fd checking for non-regression regarding [ce470f20fd] --- tests/ttk/treeview.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test index aa7e64a..b9fcd1e 100644 --- a/tests/ttk/treeview.test +++ b/tests/ttk/treeview.test @@ -636,4 +636,14 @@ test treeview-3085489-2 "tag remove, no -tags" -setup { destroy .tv } -result [list] +test treeview-ce470f20fd "dragging further than the right edge of the treeview is forbidden" -setup { + pack [ttk::treeview .tv] + .tv heading #0 -text "Drag my right edge -->" + update +} -body { + set res [.tv column #0 -width] + .tv drag #0 400 + lappend res [expr {[.tv column #0 -width] > $res}] +} -result {200 0} + tcltest::cleanupTests -- cgit v0.12 From 8f121b652e2b474b1877c35a443918a8f4759e7a Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 4 May 2019 13:16:41 +0000 Subject: ttk::treeview: when there is at least one stretchable column then there should be no slack at the right (slack should be distributed among the stretchable columns) --- generic/ttk/ttkTreeview.c | 15 +++++++++++++++ library/ttk/treeview.tcl | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index fcf9992..ec85380 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2913,6 +2913,20 @@ static int TreeviewDragCommand( return TCL_ERROR; } +static int TreeviewDropCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Treeview *tv = recordPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "drop"); + return TCL_ERROR; + } + ResizeColumns(tv, TreeWidth(tv)); + TtkRedisplayWidget(&tv->core); + return TCL_OK; +} + /*------------------------------------------------------------------------ * +++ Widget commands -- focus and selection */ @@ -3262,6 +3276,7 @@ static const Ttk_Ensemble TreeviewCommands[] = { { "delete", TreeviewDeleteCommand,0 }, { "detach", TreeviewDetachCommand,0 }, { "drag", TreeviewDragCommand,0 }, + { "drop", TreeviewDropCommand,0 }, { "exists", TreeviewExistsCommand,0 }, { "focus", TreeviewFocusCommand,0 }, { "heading", TreeviewHeadingCommand,0 }, diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index 149ecdc..e458558 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -212,7 +212,7 @@ proc ttk::treeview::resize.drag {w x} { } proc ttk::treeview::resize.release {w x} { - # no-op + $w drop } ### Heading activation. -- cgit v0.12 From ab2a29422052037b0344d50033fe0b16676aa9b4 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sat, 4 May 2019 13:19:36 +0000 Subject: Revert [d70ef6ed] and [fa9b6483]. ttk::treeview again allows dragging the right edge of the rightmost heading, which is not special in any respect. --- library/ttk/treeview.tcl | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/library/ttk/treeview.tcl b/library/ttk/treeview.tcl index e458558..a6bdb74 100644 --- a/library/ttk/treeview.tcl +++ b/library/ttk/treeview.tcl @@ -106,12 +106,7 @@ proc ttk::treeview::Motion {w x y} { set activeHeading {} switch -- [$w identify region $x $y] { - separator { - if {[ttk::treeview::LastDisplayColumn $w] ne - [$w identify column $x $y]} { - set cursor hresize - } - } + separator { set cursor hresize } heading { set activeHeading [$w identify column $x $y] } } @@ -206,9 +201,7 @@ proc ttk::treeview::resize.press {w x y} { proc ttk::treeview::resize.drag {w x} { variable State - if {[ttk::treeview::LastDisplayColumn $w] ne $State(resizeColumn)} { - $w drag $State(resizeColumn) $x - } + $w drag $State(resizeColumn) $x } proc ttk::treeview::resize.release {w x} { @@ -367,16 +360,4 @@ proc ttk::treeview::BrowseTo {w item} { $w selection set [list $item] } -## LastDisplayColumn -- return the data column identifier of the column -# displayed rightmost, in the form #n -# -proc ttk::treeview::LastDisplayColumn {w} { - set dc [$w cget -displaycolumns] - if {$dc eq "#all"} { - return #[llength [$w cget -columns]] - } else { - return #[llength $dc] - } -} - #*EOF* -- cgit v0.12 From 3f9a6cdf9f72f70de3975b8dadc0680feeb90d00 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 May 2019 10:14:46 +0000 Subject: When changing the -stretch value for a column, columns size must be recomputed before the treeview is redisplayed (at idle time) --- generic/ttk/ttkTreeview.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index ec85380..7bed8e0 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -282,7 +282,7 @@ static Tk_OptionSpec ColumnOptionSpecs[] = { 0,0,0 }, {TK_OPTION_BOOLEAN, "-stretch", "stretch", "Stretch", "1", -1, Tk_Offset(TreeColumn,stretch), - 0,0,0 }, + 0,0,GEOMETRY_CHANGED }, {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", "w", Tk_Offset(TreeColumn,anchorObj), -1, /* <> */ 0,0,0 }, @@ -1234,6 +1234,7 @@ static int ConfigureColumn( TtkResizeWidget(&tv->core); } RecomputeSlack(tv); + ResizeColumns(tv, TreeWidth(tv)); } TtkRedisplayWidget(&tv->core); -- cgit v0.12 From d3976c34aa0da0b7c7232f381311938111be0946 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 May 2019 12:21:55 +0000 Subject: Add treeview tests checking for non-regression (the last added test already passed in core-8-6-branch) --- tests/ttk/treeview.test | 80 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test index b9fcd1e..22d978c 100644 --- a/tests/ttk/treeview.test +++ b/tests/ttk/treeview.test @@ -636,7 +636,7 @@ test treeview-3085489-2 "tag remove, no -tags" -setup { destroy .tv } -result [list] -test treeview-ce470f20fd "dragging further than the right edge of the treeview is forbidden" -setup { +test treeview-ce470f20fd-1 "dragging further than the right edge of the treeview is forbidden" -setup { pack [ttk::treeview .tv] .tv heading #0 -text "Drag my right edge -->" update @@ -644,6 +644,84 @@ test treeview-ce470f20fd "dragging further than the right edge of the treeview i set res [.tv column #0 -width] .tv drag #0 400 lappend res [expr {[.tv column #0 -width] > $res}] +} -cleanup { + destroy .tv } -result {200 0} +proc nostretch {tv} { + foreach col [$tv cget -columns] { + $tv column $col -stretch 0 + } + $tv column #0 -stretch 0 + update idletasks ; # redisplay $tv +} + +test treeview-ce470f20fd-2 "changing -stretch resizes columns" -setup { + pack [ttk::treeview .tv -columns {bar colA colB colC foo}] + foreach col [.tv cget -columns] { + .tv heading $col -text $col + } + nostretch .tv + .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created + update idletasks ; # redisplay treeview +} -body { + # when no column is stretchable and one of them becomes stretchable + # the stretchable column takes the slack and the widget is redisplayed + # automatically at idle time + set res [.tv column colA -width] + .tv column colA -stretch 1 + update idletasks ; # no slack anymore, widget redisplayed + lappend res [expr {[.tv column colA -width] > $res}] +} -cleanup { + destroy .tv +} -result {50 1} + +test treeview-ce470f20fd-3 "changing -stretch resizes columns" -setup { + pack [ttk::treeview .tv -columns {bar colA colB colC foo}] + foreach col [.tv cget -columns] { + .tv heading $col -text $col + } + .tv configure -displaycolumns {colB colA colC} + nostretch .tv + .tv column colA -width 50 ; .tv column colB -width 50 ; # slack created + update idletasks ; # redisplay treeview +} -body { + # only some columns are displayed (and in a different order than declared + # in -columns), a displayed column becomes stretchable --> the stretchable + # column expands + set res [.tv column colA -width] + .tv column colA -stretch 1 + update idletasks ; # no slack anymore, widget redisplayed + lappend res [expr {[.tv column colA -width] > $res}] +} -cleanup { + destroy .tv +} -result {50 1} + +test treeview-ce470f20fd-4 "changing -stretch resizes columns" -setup { + pack [ttk::treeview .tv -columns {bar colA colB colC foo}] + foreach col [.tv cget -columns] { + .tv heading $col -text $col + } + .tv configure -displaycolumns {colB colA colC} + nostretch .tv + .tv column colA -width 50 ; .tv column bar -width 60 ; # slack created + update idletasks ; # redisplay treeview +} -body { + # only some columns are displayed (and in a different order than declared + # in -columns), a non-displayed column becomes stretchable --> nothing + # happens + set origTreeWidth [winfo width .tv] + set res [list [.tv column bar -width] [.tv column colA -width]] + .tv column bar -stretch 1 + update idletasks ; # no change, widget redisplayed + lappend res [.tv column bar -width] [.tv column colA -width] + # this column becomes visible --> widget resizes + .tv configure -displaycolumns {bar colC colA colB} + update idletasks ; # no slack anymore because the widget resizes (shrinks) + lappend res [.tv column bar -width] [.tv column colA -width] \ + [expr {[winfo width .tv] < $origTreeWidth}] +} -cleanup { + destroy .tv +} -result {60 50 60 50 60 50 1} + tcltest::cleanupTests -- cgit v0.12 From a0d58f325fba501fcb57d9d64592a668409e66fa Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 8 May 2019 12:40:35 +0000 Subject: Remove ASSERT: SLACKINVARIANT comments --- generic/ttk/ttkTreeview.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index 7bed8e0..f08ed38 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -1238,8 +1238,6 @@ static int ConfigureColumn( } TtkRedisplayWidget(&tv->core); - /* ASSERT: SLACKINVARIANT */ - Tk_FreeSavedOptions(&savedOptions); return TCL_OK; @@ -1616,13 +1614,10 @@ static void TreeviewDoLayout(void *clientData) Treeview *tv = clientData; int visibleRows; - /* ASSERT: SLACKINVARIANT */ - Ttk_PlaceLayout(tv->core.layout,tv->core.state,Ttk_WinBox(tv->core.tkwin)); tv->tree.treeArea = Ttk_ClientRegion(tv->core.layout, "treearea"); ResizeColumns(tv, tv->tree.treeArea.width); - /* ASSERT: SLACKINVARIANT */ TtkScrolled(tv->tree.xscrollHandle, tv->tree.xscroll.first, @@ -2900,7 +2895,6 @@ static int TreeviewDragCommand( } if (newx <= newxRightLimit) { DragColumn(tv, i, newx - right); - /* ASSERT: SLACKINVARIANT */ TtkRedisplayWidget(&tv->core); } return TCL_OK; -- cgit v0.12 From a6d8b926167e1d1b3e68c57a10d5898ae4839af3 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 9 May 2019 09:12:58 +0000 Subject: Fix bug when dragging a column separator: when columns at the right of the separator are not stretchable, use their width instead of their minwidth to compute the maximum x drag position. This prevents the user from resizing columns such that the treeview would no longer fit in its allotted width. --- generic/ttk/ttkTreeview.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c index f08ed38..5e52f01 100644 --- a/generic/ttk/ttkTreeview.c +++ b/generic/ttk/ttkTreeview.c @@ -2884,13 +2884,19 @@ static int TreeviewDragCommand( /* The limit not to exceed at the right is given by the tree width minus the sum of the min widths of the columns at the right of the one being resized (and don't forget possible x scrolling!). + For stretchable columns, this min width really is the minWidth, + for non-stretchable columns, this is the column width. */ int newxRightLimit = tv->tree.treeArea.x - tv->tree.xscroll.first + tv->tree.treeArea.width; int j = i + 1; while (j < tv->tree.nDisplayColumns) { TreeColumn *cr = tv->tree.displayColumns[j]; - newxRightLimit -= cr->minWidth; + if (cr->stretch) { + newxRightLimit -= cr->minWidth; + } else { + newxRightLimit -= cr->width; + } ++j; } if (newx <= newxRightLimit) { -- cgit v0.12 From 3092b520d216d7e37baa5f60db86e7de2ede6b90 Mon Sep 17 00:00:00 2001 From: fvogel Date: Thu, 9 May 2019 09:14:05 +0000 Subject: Improve clarity and completeness of ttk::treeview man page for columns options --- doc/ttk_treeview.n | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/doc/ttk_treeview.n b/doc/ttk_treeview.n index 96565a3..ba39a60 100644 --- a/doc/ttk_treeview.n +++ b/doc/ttk_treeview.n @@ -133,25 +133,29 @@ The column name. This is a read-only option. For example, [\fI$pathname \fBcolumn #\fIn \fB\-id\fR] returns the data column associated with display column #\fIn\fR. .TP -\fB\-anchor\fR +\fB\-anchor \fIanchor\fR Specifies how the text in this column should be aligned -with respect to the cell. One of +with respect to the cell. \fIAnchor\fR is one of \fBn\fR, \fBne\fR, \fBe\fR, \fBse\fR, \fBs\fR, \fBsw\fR, \fBw\fR, \fBnw\fR, or \fBcenter\fR. .TP -\fB\-minwidth\fR +\fB\-minwidth \fIminwidth\fR The minimum width of the column in pixels. The treeview widget will not make the column any smaller than \fB\-minwidth\fR when the widget is resized or the user drags a +column separator. Default is 20 pixels. +.TP +\fB\-stretch \fIboolean\fR +Specifies whether or not the column width should be adjusted +when the widget is resized or the user drags a column separator. +\fIBoolean\fR may have any of the forms accepted by \fBTcl_GetBoolean\fR. +By default columns are stretchable. +.TP +\fB\-width \fIwidth\fR +The width of the column in pixels. Default is 200 pixels. The specified +column width may be changed by Tk in order to honor \fB\-stretch\fR +and/or \fB\-minwidth\fR, or when the widget is resized or the user drags a column separator. -.TP -\fB\-stretch\fR -Specifies whether or not the column's width should be adjusted -when the widget is resized. -.TP -\fB\-width \fIw\fR -The width of the column in pixels. Default is something reasonable, -probably 200 or so. .PP Use \fIpathname column #0\fR to configure the tree column. .RE -- cgit v0.12