mirror of https://github.com/buggins/dlangui.git
tree widget: selection movement
This commit is contained in:
parent
9fd29770a9
commit
c1614f9f72
|
@ -159,6 +159,10 @@ struct Rect {
|
||||||
bool isInsideOf(Rect rc) {
|
bool isInsideOf(Rect rc) {
|
||||||
return left >= rc.left && right <= rc.right && top >= rc.top && bottom <= rc.bottom;
|
return left >= rc.left && right <= rc.right && top >= rc.top && bottom <= rc.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool opEquals(Rect rc) {
|
||||||
|
return left == rc.left && right == rc.right && top == rc.top && bottom == rc.bottom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// character glyph
|
/// character glyph
|
||||||
|
|
|
@ -193,6 +193,21 @@ class ScrollWidgetBase : WidgetGroup, OnScrollHandler {
|
||||||
updateScrollBars();
|
updateScrollBars();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void makeRectVisible(Rect rc, bool alignHorizontally = true, bool alignVertically = true) {
|
||||||
|
if (rc.isInsideOf(_visibleScrollableArea))
|
||||||
|
return;
|
||||||
|
Rect oldRect = _visibleScrollableArea;
|
||||||
|
if (alignHorizontally && rc.right > _visibleScrollableArea.right)
|
||||||
|
_visibleScrollableArea.offset(rc.right - _visibleScrollableArea.right, 0);
|
||||||
|
if (alignVertically && rc.bottom > _visibleScrollableArea.bottom)
|
||||||
|
_visibleScrollableArea.offset(0, rc.bottom - _visibleScrollableArea.bottom);
|
||||||
|
if (alignHorizontally && rc.left < _visibleScrollableArea.left)
|
||||||
|
_visibleScrollableArea.offset(rc.left - _visibleScrollableArea.left, 0);
|
||||||
|
if (alignVertically && rc.top < _visibleScrollableArea.top)
|
||||||
|
_visibleScrollableArea.offset(0, rc.top - _visibleScrollableArea.top);
|
||||||
|
if (_visibleScrollableArea != oldRect)
|
||||||
|
requestLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,6 +273,7 @@ class ScrollWidget : ScrollWidgetBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@property Point scrollPos() {
|
@property Point scrollPos() {
|
||||||
return Point(_visibleScrollableArea.left - _fullScrollableArea.left, _visibleScrollableArea.top - _fullScrollableArea.top);
|
return Point(_visibleScrollableArea.left - _fullScrollableArea.left, _visibleScrollableArea.top - _fullScrollableArea.top);
|
||||||
}
|
}
|
||||||
|
@ -309,4 +325,14 @@ class ScrollWidget : ScrollWidgetBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void makeWidgetVisible(Widget widget, bool alignHorizontally = true, bool alignVertically = true) {
|
||||||
|
if (!widget || !widget.visibility == Visibility.Gone)
|
||||||
|
return;
|
||||||
|
if (!_contentWidget || !_contentWidget.isChild(widget))
|
||||||
|
return;
|
||||||
|
Rect wpos = widget.pos;
|
||||||
|
Rect cpos = _contentWidget.pos;
|
||||||
|
wpos.offset(-cpos.left, -cpos.top);
|
||||||
|
makeRectVisible(wpos, alignHorizontally, alignVertically);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,6 +172,32 @@ class TreeItem {
|
||||||
protected void activateItem(TreeItem item) {
|
protected void activateItem(TreeItem item) {
|
||||||
root.activateItem(item);
|
root.activateItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected TreeItem nextVisible(TreeItem item, ref bool found) {
|
||||||
|
if (this is item)
|
||||||
|
found = true;
|
||||||
|
else if (found && isVisible)
|
||||||
|
return this;
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TreeItem res = child(i).nextVisible(item, found);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TreeItem prevVisible(TreeItem item, ref TreeItem prevFoundVisible) {
|
||||||
|
if (this is item)
|
||||||
|
return prevFoundVisible;
|
||||||
|
else if (isVisible)
|
||||||
|
prevFoundVisible = this;
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TreeItem res = child(i).prevVisible(item, prevFoundVisible);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnTreeContentChangeListener {
|
interface OnTreeContentChangeListener {
|
||||||
|
@ -237,6 +263,25 @@ class TreeItems : TreeItem {
|
||||||
return _selectedItem;
|
return _selectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void selectNext() {
|
||||||
|
if (!hasChildren)
|
||||||
|
return;
|
||||||
|
if (!_selectedItem)
|
||||||
|
selectItem(child(0));
|
||||||
|
bool found = false;
|
||||||
|
TreeItem next = nextVisible(_selectedItem, found);
|
||||||
|
if (next)
|
||||||
|
selectItem(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
void selectPrevious() {
|
||||||
|
if (!hasChildren)
|
||||||
|
return;
|
||||||
|
TreeItem found = null;
|
||||||
|
TreeItem prev = prevVisible(_selectedItem, found);
|
||||||
|
if (prev)
|
||||||
|
selectItem(prev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// grid control action codes
|
/// grid control action codes
|
||||||
|
@ -319,6 +364,10 @@ class TreeItemWidget : HorizontalLayout {
|
||||||
ImageWidget _icon;
|
ImageWidget _icon;
|
||||||
TextWidget _label;
|
TextWidget _label;
|
||||||
long lastClickTime;
|
long lastClickTime;
|
||||||
|
|
||||||
|
@property TreeItem item() { return _item; }
|
||||||
|
|
||||||
|
|
||||||
this(TreeItem item) {
|
this(TreeItem item) {
|
||||||
super(item.id);
|
super(item.id);
|
||||||
styleId = "TREE_ITEM";
|
styleId = "TREE_ITEM";
|
||||||
|
@ -434,19 +483,20 @@ class TreeWidgetBase : ScrollWidget, OnTreeContentChangeListener, OnTreeStateCh
|
||||||
_tree = new TreeItems();
|
_tree = new TreeItems();
|
||||||
_tree.contentListener = this;
|
_tree.contentListener = this;
|
||||||
_tree.stateListener = this;
|
_tree.stateListener = this;
|
||||||
|
_tree.selectionListener = this;
|
||||||
_needUpdateWidgets = true;
|
_needUpdateWidgets = true;
|
||||||
_needUpdateWidgetStates = true;
|
_needUpdateWidgetStates = true;
|
||||||
acceleratorMap.add( [
|
acceleratorMap.add( [
|
||||||
new Action(TreeActions.Up, KeyCode.UP, 0),
|
new Action(TreeActions.Up, KeyCode.UP, 0),
|
||||||
new Action(TreeActions.Down, KeyCode.DOWN, 0),
|
new Action(TreeActions.Down, KeyCode.DOWN, 0),
|
||||||
new Action(TreeActions.Left, KeyCode.LEFT, 0),
|
new Action(TreeActions.ScrollLeft, KeyCode.LEFT, 0),
|
||||||
new Action(TreeActions.Right, KeyCode.RIGHT, 0),
|
new Action(TreeActions.ScrollRight, KeyCode.RIGHT, 0),
|
||||||
new Action(TreeActions.LineBegin, KeyCode.HOME, 0),
|
//new Action(TreeActions.LineBegin, KeyCode.HOME, 0),
|
||||||
new Action(TreeActions.LineEnd, KeyCode.END, 0),
|
//new Action(TreeActions.LineEnd, KeyCode.END, 0),
|
||||||
new Action(TreeActions.PageUp, KeyCode.PAGEUP, 0),
|
new Action(TreeActions.PageUp, KeyCode.PAGEUP, 0),
|
||||||
new Action(TreeActions.PageDown, KeyCode.PAGEDOWN, 0),
|
new Action(TreeActions.PageDown, KeyCode.PAGEDOWN, 0),
|
||||||
new Action(TreeActions.PageBegin, KeyCode.PAGEUP, KeyFlag.Control),
|
//new Action(TreeActions.PageBegin, KeyCode.PAGEUP, KeyFlag.Control),
|
||||||
new Action(TreeActions.PageEnd, KeyCode.PAGEDOWN, KeyFlag.Control),
|
//new Action(TreeActions.PageEnd, KeyCode.PAGEDOWN, KeyFlag.Control),
|
||||||
new Action(TreeActions.ScrollTop, KeyCode.HOME, KeyFlag.Control),
|
new Action(TreeActions.ScrollTop, KeyCode.HOME, KeyFlag.Control),
|
||||||
new Action(TreeActions.ScrollBottom, KeyCode.END, KeyFlag.Control),
|
new Action(TreeActions.ScrollBottom, KeyCode.END, KeyFlag.Control),
|
||||||
new Action(TreeActions.ScrollPageUp, KeyCode.PAGEUP, KeyFlag.Control),
|
new Action(TreeActions.ScrollPageUp, KeyCode.PAGEUP, KeyFlag.Control),
|
||||||
|
@ -539,11 +589,32 @@ class TreeWidgetBase : ScrollWidget, OnTreeContentChangeListener, OnTreeStateCh
|
||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TreeItemWidget findItemWidget(TreeItem item) {
|
||||||
|
for (int i = 0; i < _contentWidget.childCount; i++) {
|
||||||
|
TreeItemWidget child = cast(TreeItemWidget) _contentWidget.child(i);
|
||||||
|
if (child && child.item is item)
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
override void onTreeItemSelected(TreeItems source, TreeItem selectedItem, bool activated) {
|
override void onTreeItemSelected(TreeItems source, TreeItem selectedItem, bool activated) {
|
||||||
|
TreeItemWidget selected = findItemWidget(selectedItem);
|
||||||
|
if (selected && selected.visibility == Visibility.Visible) {
|
||||||
|
selected.setFocus();
|
||||||
|
makeWidgetVisible(selected, false, true);
|
||||||
|
}
|
||||||
if (selectionListener.assigned)
|
if (selectionListener.assigned)
|
||||||
selectionListener(source, selectedItem, activated);
|
selectionListener(source, selectedItem, activated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void makeItemVisible(TreeItem item) {
|
||||||
|
TreeItemWidget widget = findItemWidget(item);
|
||||||
|
if (widget && widget.visibility == Visibility.Visible) {
|
||||||
|
makeWidgetVisible(widget, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override protected bool handleAction(const Action a) {
|
override protected bool handleAction(const Action a) {
|
||||||
Log.d("tree.handleAction ", a.id);
|
Log.d("tree.handleAction ", a.id);
|
||||||
switch (a.id) {
|
switch (a.id) {
|
||||||
|
@ -571,6 +642,16 @@ class TreeWidgetBase : ScrollWidget, OnTreeContentChangeListener, OnTreeStateCh
|
||||||
if (_vscrollbar)
|
if (_vscrollbar)
|
||||||
_vscrollbar.sendScrollEvent(ScrollAction.PageDown);
|
_vscrollbar.sendScrollEvent(ScrollAction.PageDown);
|
||||||
break;
|
break;
|
||||||
|
case TreeActions.Up:
|
||||||
|
_tree.selectPrevious();
|
||||||
|
break;
|
||||||
|
case TreeActions.Down:
|
||||||
|
_tree.selectNext();
|
||||||
|
break;
|
||||||
|
case TreeActions.PageUp:
|
||||||
|
break;
|
||||||
|
case TreeActions.PageDown:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return super.handleAction(a);
|
return super.handleAction(a);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue