diff --git a/extensions/widgets/treeview/notes/21570.md b/extensions/widgets/treeview/notes/21570.md new file mode 100644 index 00000000000..8198a418dbe --- /dev/null +++ b/extensions/widgets/treeview/notes/21570.md @@ -0,0 +1 @@ +# [21570] Add option to select new elements automatically \ No newline at end of file diff --git a/extensions/widgets/treeview/notes/feature-scroll_into_view.md b/extensions/widgets/treeview/notes/feature-scroll_into_view.md new file mode 100644 index 00000000000..9f10e47a481 --- /dev/null +++ b/extensions/widgets/treeview/notes/feature-scroll_into_view.md @@ -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. \ No newline at end of file diff --git a/extensions/widgets/treeview/treeview.lcb b/extensions/widgets/treeview/treeview.lcb index 460f7548a3f..646c93caec9 100644 --- a/extensions/widgets/treeview/treeview.lcb +++ b/extensions/widgets/treeview/treeview.lcb @@ -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" @@ -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 to {true|false} +Syntax: get the hiliteNewElement of + +Summary: Automatically select new elements when created interactively. + +Description: +If the property is false and the 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 to {true|false} +Syntax: get the scrollHilitedElementIntoView of + +Summary: Automatically scroll selected row into view. + +Description: +If the property is true, then when the + 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 @@ -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 @@ -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 @@ -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) @@ -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"] @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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 @@ -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)