From 173388fdff84d1ed1ac21d78c597958417c68df3 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Thu, 22 Jan 2015 17:57:52 +0300 Subject: [PATCH] fix crash on action handling --- examples/example1/src/example1.d | 6 ++--- src/dlangui/platforms/common/platform.d | 32 +++++++++++++++++++------ src/dlangui/widgets/appframe.d | 6 +++++ src/dlangui/widgets/editors.d | 30 +++++++++++------------ src/dlangui/widgets/grid.d | 16 ++++++------- src/dlangui/widgets/widget.d | 17 +++++++++---- 6 files changed, 68 insertions(+), 39 deletions(-) diff --git a/examples/example1/src/example1.d b/examples/example1/src/example1.d index 1b1db13a..a2b63d97 100644 --- a/examples/example1/src/example1.d +++ b/examples/example1/src/example1.d @@ -341,10 +341,8 @@ extern (C) int UIAppMain(string[] args) { }; dlg.show(); return true; - } else if (window.focusedWidget) - return window.focusedWidget.handleAction(a); - else - return contentLayout.handleAction(a); + } else + return contentLayout.dispatchAction(a); } return false; }; diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 22c24e5c..ab161591 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -489,14 +489,32 @@ class Window { } /// dispatch action to main widget - bool dispatchAction(const Action action) { - Widget focus = focusedWidget; - // first, offer action to focused widget - if (focus && focus.handleAction(action)) + bool dispatchAction(const Action action, Widget sourceWidget = null) { + // try to handle by source widget + if(sourceWidget && isChild(sourceWidget)) { + if (sourceWidget.handleAction(action)) return true; - // if not processed by focused widget, pass to main widget - if (_mainWidget !is null) - return _mainWidget.handleAction(action); + sourceWidget = sourceWidget.parent; + } + Widget focus = focusedWidget; + // then offer action to focused widget + if (focus && isChild(focus)) { + if (focus.handleAction(action)) + return true; + focus = focus.parent; + } + // then offer to parent chain of source widget + while (sourceWidget && isChild(sourceWidget)) { + if (sourceWidget.handleAction(action)) + return true; + sourceWidget = sourceWidget.parent; + } + // then offer to parent chain of focused widget + while (focus && isChild(focus)) { + if (focus.handleAction(action)) + return true; + focus = focus.parent; + } return false; } diff --git a/src/dlangui/widgets/appframe.d b/src/dlangui/widgets/appframe.d index d2cf83d8..bd763600 100644 --- a/src/dlangui/widgets/appframe.d +++ b/src/dlangui/widgets/appframe.d @@ -98,4 +98,10 @@ class AppFrame : VerticalLayout, MenuItemClickHandler, MenuItemActionHandler { res.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT); return res; } + + /// override to handle specific actions + override bool handleAction(const Action a) { + return false; + } + } diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index 1d1c2077..493faa57 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -1275,7 +1275,7 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction /// override bool onMenuItemAction(const Action action) { - return handleAction(action); + return dispatchAction(action); } /// returns true if widget can show popup (e.g. by mouse right click at point x,y) @@ -2084,16 +2084,16 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction uint keyFlags = event.flags & (MouseFlag.Shift | MouseFlag.Control | MouseFlag.Alt); if (event.wheelDelta < 0) { if (keyFlags == MouseFlag.Shift) - return handleAction(new Action(EditorActions.ScrollRight)); + return dispatchAction(new Action(EditorActions.ScrollRight)); if (keyFlags == MouseFlag.Control) - return handleAction(new Action(EditorActions.ZoomOut)); - return handleAction(new Action(EditorActions.ScrollLineDown)); + return dispatchAction(new Action(EditorActions.ZoomOut)); + return dispatchAction(new Action(EditorActions.ScrollLineDown)); } else if (event.wheelDelta > 0) { if (keyFlags == MouseFlag.Shift) - return handleAction(new Action(EditorActions.ScrollLeft)); + return dispatchAction(new Action(EditorActions.ScrollLeft)); if (keyFlags == MouseFlag.Control) - return handleAction(new Action(EditorActions.ZoomIn)); - return handleAction(new Action(EditorActions.ScrollLineUp)); + return dispatchAction(new Action(EditorActions.ZoomIn)); + return dispatchAction(new Action(EditorActions.ScrollLineUp)); } } return super.onMouseEvent(event); @@ -2402,13 +2402,13 @@ class EditBox : EditWidgetBase { invalidate(); } } else if (event.action == ScrollAction.PageUp) { - handleAction(new Action(EditorActions.ScrollLeft)); + dispatchAction(new Action(EditorActions.ScrollLeft)); } else if (event.action == ScrollAction.PageDown) { - handleAction(new Action(EditorActions.ScrollRight)); + dispatchAction(new Action(EditorActions.ScrollRight)); } else if (event.action == ScrollAction.LineUp) { - handleAction(new Action(EditorActions.ScrollLeft)); + dispatchAction(new Action(EditorActions.ScrollLeft)); } else if (event.action == ScrollAction.LineDown) { - handleAction(new Action(EditorActions.ScrollRight)); + dispatchAction(new Action(EditorActions.ScrollRight)); } return true; } @@ -2422,13 +2422,13 @@ class EditBox : EditWidgetBase { invalidate(); } } else if (event.action == ScrollAction.PageUp) { - handleAction(new Action(EditorActions.ScrollPageUp)); + dispatchAction(new Action(EditorActions.ScrollPageUp)); } else if (event.action == ScrollAction.PageDown) { - handleAction(new Action(EditorActions.ScrollPageDown)); + dispatchAction(new Action(EditorActions.ScrollPageDown)); } else if (event.action == ScrollAction.LineUp) { - handleAction(new Action(EditorActions.ScrollLineUp)); + dispatchAction(new Action(EditorActions.ScrollLineUp)); } else if (event.action == ScrollAction.LineDown) { - handleAction(new Action(EditorActions.ScrollLineDown)); + dispatchAction(new Action(EditorActions.ScrollLineDown)); } return true; } diff --git a/src/dlangui/widgets/grid.d b/src/dlangui/widgets/grid.d index f80e683c..d4c3cf33 100644 --- a/src/dlangui/widgets/grid.d +++ b/src/dlangui/widgets/grid.d @@ -535,13 +535,13 @@ class GridWidgetBase : ScrollWidgetBase { int col = colByAbsoluteX(event.position + _fullScrollableArea.left); scrollTo(col, _scrollRow + _headerRows + _fixedRows); } else if (event.action == ScrollAction.PageUp) { - handleAction(new Action(GridActions.ScrollPageLeft)); + dispatchAction(new Action(GridActions.ScrollPageLeft)); } else if (event.action == ScrollAction.PageDown) { - handleAction(new Action(GridActions.ScrollPageRight)); + dispatchAction(new Action(GridActions.ScrollPageRight)); } else if (event.action == ScrollAction.LineUp) { - handleAction(new Action(GridActions.ScrollLeft)); + dispatchAction(new Action(GridActions.ScrollLeft)); } else if (event.action == ScrollAction.LineDown) { - handleAction(new Action(GridActions.ScrollRight)); + dispatchAction(new Action(GridActions.ScrollRight)); } return true; } @@ -552,13 +552,13 @@ class GridWidgetBase : ScrollWidgetBase { int row = rowByAbsoluteY(event.position + _fullScrollableArea.top); scrollTo(_scrollCol + _headerCols + _fixedCols, row); } else if (event.action == ScrollAction.PageUp) { - handleAction(new Action(GridActions.ScrollPageUp)); + dispatchAction(new Action(GridActions.ScrollPageUp)); } else if (event.action == ScrollAction.PageDown) { - handleAction(new Action(GridActions.ScrollPageDown)); + dispatchAction(new Action(GridActions.ScrollPageDown)); } else if (event.action == ScrollAction.LineUp) { - handleAction(new Action(GridActions.ScrollUp)); + dispatchAction(new Action(GridActions.ScrollUp)); } else if (event.action == ScrollAction.LineDown) { - handleAction(new Action(GridActions.ScrollDown)); + dispatchAction(new Action(GridActions.ScrollDown)); } return true; } diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 59a88bf9..2e444988 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -901,18 +901,25 @@ class Widget { /// override to handle specific actions bool handleAction(const Action a) { - if (parent) // by default, pass to parent widget - return parent.handleAction(a); return false; } + /// call to dispatch action + bool dispatchAction(const Action a) { + if (window) + return window.dispatchAction(a, this); + else + return handleAction(a); + } + // called to process click and notify listeners protected bool handleClick() { bool res = false; if (onClickListener.assigned) res = onClickListener(this); - else if (_action) - res = handleAction(_action); + else if (_action) { + return dispatchAction(_action); + } return res; } @@ -929,7 +936,7 @@ class Widget { if (event.action == KeyAction.KeyDown) { Action action = findKeyAction(event.keyCode, event.flags & (KeyFlag.Shift | KeyFlag.Alt | KeyFlag.Control)); if (action !is null) { - return handleAction(action); + return dispatchAction(action); } } // handle focus navigation using keys