Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extensions/widgets/treeview/notes/21570.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# [21570] Add option to select new elements automatically
23 changes: 23 additions & 0 deletions extensions/widgets/treeview/notes/feature-scroll_into_view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Properties

The tree view widget now has the ability to automatically select a new
row when it is added.

The tree view widget now has the ability to scroll the selected row into
view. If `true`, this will happen when setting the **arrayData**,
setting the **hilitedElement**, and when adding a new row
(when **hiliteNewElement** is `true`).

Two properties have been added to achieve these options:
* **hiliteNewElement**: either `true` or `false`
* **scrollHilitedElementIntoView**: either `true` or `false`

The default values for both are `false` to match the behavior of previous
versions of the widget.

When selecting a row that is partially visible, the view will be
adjusted so that the full row is visible.

When changing the **readOnly** property, the view will only change
position if the value is being set to `true` and the `Add new element`
row is currently visible.
134 changes: 115 additions & 19 deletions extensions/widgets/treeview/treeview.lcb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ use com.livecode.library.widgetutils
use com.livecode.foreign

metadata author is "LiveCode"
metadata version is "2.0.3"
metadata version is "2.1.0"
metadata title is "Tree View"
metadata svgicon is "M152.4,249.7c-6.4,0-11.8,4.3-13.5,10.1h-10v-26.7h10c1.7,5.8,7.1,10.1,13.5,10.1c7.8,0,14.1-6.3,14.1-14.1s-6.3-14.1-14.1-14.1c-6.4,0-11.8,4.3-13.5,10.1h-10v-16.1c8.4-1.8,14.8-9.3,14.8-18.3c0-10.4-8.4-18.8-18.8-18.8s-18.8,8.4-18.8,18.8c0,9,6.3,16.5,14.7,18.3v58.8h18c1.7,5.8,7.1,10.1,13.5,10.1c7.8,0,14.1-6.3,14.1-14.1S160.2,249.7,152.4,249.7z M128.7,202h-7.5v-7.5h-7.5V187h7.5v-7.5h7.5v7.5h7.5v7.5h-7.5V202z"
metadata _ide is "true"
Expand Down Expand Up @@ -124,6 +124,39 @@ of the widget, to select a row corresponding to tArray["key1"]["subkey2"]["subsu
property hilitedElement get getSelectedElement set setSelectedElement
metadata hilitedElement.label is "Hilited element"

/**
Syntax: set the hiliteNewElement of <widget> to {true|false}
Syntax: get the hiliteNewElement of <widget>

Summary: Automatically select new elements when created interactively.

Description:
If the <readOnly> property is false and the <hiliteNewElement> property is true,
then when new array elements are added, they will be automatically selected.

References: readOnly (property)
**/

property hiliteNewElement get mHiliteNewElement set mHiliteNewElement
metadata hiliteNewElement.label is "Hilite new element"

/**
Syntax: set the scrollHilitedElementIntoView of <widget> to {true|false}
Syntax: get the scrollHilitedElementIntoView of <widget>

Summary: Automatically scroll selected row into view.

Description:
If the <scrollHilitedElementIntoView> property is true, then when the
<hilitedElement> property changes the view will be scrolled such that the
selected row is visible.

References: hilitedElement (property)
**/

property scrollHilitedElementIntoView get mScrollHilitedElementIntoView set mScrollHilitedElementIntoView
metadata scrollHilitedElementIntoView.label is "Scroll hilited element into view"

/**
Name: foreColor

Expand Down Expand Up @@ -404,6 +437,9 @@ private variable mFrameBorder as Boolean

private variable mSelectedElement as optional List
private variable mFoldState as Array
private variable mLastKeyAdded as optional String
private variable mHiliteNewElement as Boolean
private variable mScrollHilitedElementIntoView as Boolean

private variable mFoldedArrowPath as Path
private variable mUnfoldedArrowPath as Path
Expand Down Expand Up @@ -472,7 +508,7 @@ public handler OnCreate() returns nothing
initialiseScrollbar()

put false into mReadOnly
put false into mArrayStyle
put false into mArrayStyle

put true into mSortNumeric
put true into mSortAscending
Expand All @@ -489,7 +525,9 @@ public handler OnCreate() returns nothing
put false into mSeparatorDragging

put the empty array into mFoldState
put the empty array into mData
put the empty array into mData
put false into mHiliteNewElement
put false into mScrollHilitedElementIntoView
end handler

public handler OnSave(out rProperties as Array)
Expand All @@ -499,6 +537,8 @@ public handler OnSave(out rProperties as Array)
put mArrayStyle into rProperties["array style"]
put mSortAscending into rProperties["sort ascending"]
put mSortNumeric into rProperties["sort numeric"]
put mHiliteNewElement into rProperties["hilite new element"]
put mScrollHilitedElementIntoView into rProperties["scroll hilited element into view"]

put mShowSeparator into rProperties["show separator"]
put mSeparatorRatio into rProperties["separator ratio"]
Expand All @@ -520,6 +560,14 @@ public handler OnLoad(in pProperties as Array)
put pProperties["sort numeric"] into mSortNumeric
end if

if "hilite new element" is among the keys of pProperties then
put pProperties["hilite new element"] into mHiliteNewElement
end if

if "scroll hilited element into view" is among the keys of pProperties then
put pProperties["scroll hilited element into view"] into mScrollHilitedElementIntoView
end if

if "show separator" is among the keys of pProperties then
put pProperties["show separator"] into mShowSeparator
end if
Expand Down Expand Up @@ -1036,7 +1084,7 @@ end handler
// Clamp mViewTopPosition
private handler ensureViewTopPosition()
variable tMinTop as Real
put 0 into tMinTop
put 0 into tMinTop

// Make sure we don't try to scroll above 0
if mViewTopPosition < tMinTop then
Expand All @@ -1046,7 +1094,27 @@ private handler ensureViewTopPosition()
put mDataHeight - mViewHeight into mViewTopPosition
else if mDataHeight < mViewHeight then
put tMinTop into mViewTopPosition
end if
end if
end handler

// Adjust mViewTopPosition to ensure pListElt is visible
private handler ensureElementInView(in pListElt as Integer)
variable tViewCount as Integer
put the ceiling of (mViewHeight / mRowHeight) into tViewCount
if mReadOnly then
subtract 1 from pListElt
subtract 1 from mFirstDataItem
end if
if pListElt <= mFirstDataItem then
put (pListElt - 1) * mRowHeight into mViewTopPosition
else if pListElt >= (mFirstDataItem + tViewCount - 1) then
variable tTopOffset
put mViewHeight mod mRowHeight into tTopOffset
put (pListElt - tViewCount + 1) * mRowHeight - tTopOffset into mViewTopPosition
put 0 into mHoverRow
put "" into mHoverIcon
end if
updateParameters()
end handler

// Calculate mFirstDataItem from the view position
Expand All @@ -1055,9 +1123,9 @@ private handler updateFirstDataItem()
if mFirstDataItem < 1 then
put 1 into mFirstDataItem
end if
if mReadOnly then
add 1 to mFirstDataItem
end if
if mReadOnly then
add 1 to mFirstDataItem
end if
end handler

-- This is called before painting if the private variable
Expand Down Expand Up @@ -1474,6 +1542,9 @@ end handler
private handler selectKey(in pListElt as Integer, in pPath as List, in pLevel as Integer, inout xList as List, inout xArray as Array)
put true into xList[pListElt]["selected"]
put pPath into mSelectedElement
if mScrollHilitedElementIntoView then
ensureElementInView(pListElt)
end if
end handler

// A handler of type NodeApply to pass into 'applyToNode' - removes the key on the given path
Expand All @@ -1494,12 +1565,20 @@ private handler createNewKey(inout xArray as Array)
end repeat
put tNew formatted as string into tNewKey
put "" into xArray[tNewKey]
put tNewKey into mLastKeyAdded
end handler

private handler addBaseLevelElement()
createNewKey(mData)
setArrayData(mData)
if mHiliteNewElement then
put the empty list into mSelectedElement
push mLastKeyAdded onto mSelectedElement
end if
setArrayData(mData)
post "dataChanged"
if mHiliteNewElement then
post "hiliteChanged"
end if
end handler

// A handler of type NodeApply to pass into 'applyToNode' - adds a new key below the given path
Expand Down Expand Up @@ -1533,6 +1612,7 @@ private handler addKey(in pListElt as Integer, in pPath as List, in pLevel as In
put tElement into tArray[1 formatted as string]
put tArray into xArray[pPath[pLevel + 1]]
put false into xList[pListElt]["leaf"]
put 1 formatted as string into mLastKeyAdded
end if

unfoldKey(pListElt, pPath, pLevel, xList, xArray)
Expand Down Expand Up @@ -1589,7 +1669,12 @@ private handler addUnderPath(in pPath as List)
post "dataChanged"
put true into mRecalculate
put true into mUpdateSeparator
redraw all
if mHiliteNewElement then
push mLastKeyAdded onto pPath
selectPath(pPath)
else
redraw all
end if
end if
end handler

Expand All @@ -1615,16 +1700,22 @@ end handler

// Select the key at the target path
private handler selectPath(in pPath as List)
variable tPathNotAlreadySelected as Boolean
put mSelectedElement is not pPath into tPathNotAlreadySelected

// Unselect the existing selection if applicable
if mSelectedElement is not nothing and mSelectedElement is not pPath then
if mSelectedElement is not nothing and tPathNotAlreadySelected then
applyToNode(unselectKey, mSelectedElement, 0, 1, mDataList, mData)
end if

if mSelectedElement is nothing or mSelectedElement is not pPath then
if mSelectedElement is nothing or tPathNotAlreadySelected or \
mScrollHilitedElementIntoView then
if not applyToNode(selectKey, pPath, 0, 1, mDataList, mData) then
put nothing into mSelectedElement
end if
post "hiliteChanged"
end if
if tPathNotAlreadySelected then
post "hiliteChanged"
end if
redraw all
end if
end handler
Expand Down Expand Up @@ -1791,11 +1882,16 @@ private handler getSelectedElement() returns String
end handler

private handler setReadOnly(in pReadOnly as Boolean)
if pReadOnly is not mReadOnly then
put pReadOnly into mReadOnly
put true into mRecalculate
redraw all
end if
if pReadOnly is not mReadOnly then
put pReadOnly into mReadOnly
put true into mRecalculate
if pReadOnly then
subtract mRowHeight from mViewTopPosition
else
add mRowHeight to mViewTopPosition
end if
redraw all
end if
end handler

private handler setArrayStyle(in pArrayStyle as Boolean)
Expand Down