Menu fixes

This commit is contained in:
Vadim Lopatin 2015-01-15 12:11:01 +03:00
parent 6efd603d17
commit fbeef1b15d
3 changed files with 85 additions and 16 deletions

View File

@ -594,10 +594,10 @@ class Window {
bool needLayout = false; bool needLayout = false;
bool animationActive = false; bool animationActive = false;
if (checkUpdateNeeded(needDraw, needLayout, animationActive) || force) { if (checkUpdateNeeded(needDraw, needLayout, animationActive) || force) {
Log.d("Requesting update"); debug(DebugRedraw) Log.d("Requesting update");
invalidate(); invalidate();
} }
Log.d("checkUpdateNeeded returned needDraw=", needDraw, " needLayout=", needLayout, " animationActive=", animationActive); debug(DebugRedraw) Log.d("checkUpdateNeeded returned needDraw=", needDraw, " needLayout=", needLayout, " animationActive=", animationActive);
} }
/// request window redraw /// request window redraw
abstract void invalidate(); abstract void invalidate();

View File

@ -341,10 +341,16 @@ class ListWidget : WidgetGroup, OnScrollHandler {
onItemClickListener(this, index); onItemClickListener(this, index);
} }
/// allow to override state for updating of items
// currently used to treat main menu items with opened submenu as focused
@property protected uint overrideStateForItem() {
return state;
}
protected void updateSelectedItemFocus() { protected void updateSelectedItemFocus() {
if (_selectedItemIndex != -1) { if (_selectedItemIndex != -1) {
if ((_adapter.itemState(_selectedItemIndex) & State.Focused) != (state & State.Focused)) { if ((_adapter.itemState(_selectedItemIndex) & State.Focused) != (overrideStateForItem & State.Focused)) {
if (state & State.Focused) if (overrideStateForItem & State.Focused)
_adapter.setItemState(_selectedItemIndex, State.Focused); _adapter.setItemState(_selectedItemIndex, State.Focused);
else else
_adapter.resetItemState(_selectedItemIndex, State.Focused); _adapter.resetItemState(_selectedItemIndex, State.Focused);
@ -472,7 +478,7 @@ class ListWidget : WidgetGroup, OnScrollHandler {
_selectedItemIndex = index; _selectedItemIndex = index;
if (_selectedItemIndex != -1) { if (_selectedItemIndex != -1) {
makeSelectionVisible(); makeSelectionVisible();
_adapter.setItemState(_selectedItemIndex, State.Selected | (state & State.Focused)); _adapter.setItemState(_selectedItemIndex, State.Selected | (overrideStateForItem & State.Focused));
invalidate(); invalidate();
} }
return true; return true;

View File

@ -26,6 +26,9 @@ import dlangui.widgets.layouts;
import dlangui.widgets.lists; import dlangui.widgets.lists;
import dlangui.widgets.popup; import dlangui.widgets.popup;
// define DebugMenus for menu debug messages
//debug = DebugMenus;
/// menu item type /// menu item type
enum MenuItemType { enum MenuItemType {
/// normal menu item /// normal menu item
@ -418,6 +421,7 @@ class MenuWidgetBase : ListWidget {
} }
protected void onPopupClosed(PopupWidget p) { protected void onPopupClosed(PopupWidget p) {
debug(DebugMenus) Log.d("menu ", id, " onPopupClosed selectionChanging=", _selectionChangingInProgress);
if (_openedPopup) { if (_openedPopup) {
if (_openedPopup is p) { if (_openedPopup is p) {
_openedMenu.onPopupClosed(p); _openedMenu.onPopupClosed(p);
@ -429,13 +433,19 @@ class MenuWidgetBase : ListWidget {
//} //}
if (!isMainMenu) if (!isMainMenu)
window.setFocus(this); window.setFocus(this);
//else
// performUndoSelection();
if (isMainMenu && !_selectionChangingInProgress)
close();
} else if (thisPopup is p) { } else if (thisPopup is p) {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null;
} }
} }
} }
protected void openSubmenu(int index, MenuItemWidget itemWidget, bool selectFirstItem) { protected void openSubmenu(int index, MenuItemWidget itemWidget, bool selectFirstItem) {
debug(DebugMenus) Log.d("menu", id, " open submenu ", index);
if (_openedPopup !is null) { if (_openedPopup !is null) {
if (_openedPopupIndex == index) { if (_openedPopupIndex == index) {
if (selectFirstItem) { if (selectFirstItem) {
@ -445,6 +455,7 @@ class MenuWidgetBase : ListWidget {
return; return;
} else { } else {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null;
} }
} }
PopupMenu popupMenu = new PopupMenu(itemWidget.item, this); PopupMenu popupMenu = new PopupMenu(itemWidget.item, this);
@ -454,32 +465,41 @@ class MenuWidgetBase : ListWidget {
_openedPopup = popup; _openedPopup = popup;
_openedMenu = popupMenu; _openedMenu = popupMenu;
_openedPopupIndex = index; _openedPopupIndex = index;
_selectedItemIndex = index;
if (selectFirstItem) { if (selectFirstItem) {
debug(DebugMenus) Log.d("menu: selecting first item");
window.setFocus(popupMenu); window.setFocus(popupMenu);
_openedMenu.selectItem(0); _openedMenu.selectItem(0);
} }
} }
protected bool _selectionChangingInProgress;
/// override to handle change of selection /// override to handle change of selection
override protected void selectionChanged(int index, int previouslySelectedItem = -1) { override protected void selectionChanged(int index, int previouslySelectedItem = -1) {
debug Log.d("menu.selectionChanged ", index, ", ", previouslySelectedItem, " _selectedItemIndex=", _selectedItemIndex); debug(DebugMenus) Log.d("menu ", id, " selectionChanged ", index, ", ", previouslySelectedItem, " _selectedItemIndex=", _selectedItemIndex);
_selectionChangingInProgress = true;
if (index >= 0) if (index >= 0)
setFocus(); setFocus();
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null; MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
MenuItemWidget prevWidget = previouslySelectedItem >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(previouslySelectedItem) : null; MenuItemWidget prevWidget = previouslySelectedItem >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(previouslySelectedItem) : null;
bool popupWasOpen = false;
if (prevWidget !is null) { if (prevWidget !is null) {
if (_openedPopup !is null) if (_openedPopup !is null) {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null;
popupWasOpen = true;
}
} }
if (itemWidget !is null) { if (itemWidget !is null) {
if (itemWidget.item.isSubmenu()) { if (itemWidget.item.isSubmenu()) {
if (_selectOnHover) { if (_selectOnHover || popupWasOpen) {
openSubmenu(index, itemWidget, _orientation == Orientation.Horizontal); // for main menu, select first item openSubmenu(index, itemWidget, _orientation == Orientation.Horizontal); // for main menu, select first item
} }
} else { } else {
// normal item // normal item
} }
} }
_selectionChangingInProgress = false;
} }
protected void handleMenuItemClick(MenuItem item) { protected void handleMenuItemClick(MenuItem item) {
@ -496,7 +516,7 @@ class MenuWidgetBase : ListWidget {
} }
protected void onMenuItem(MenuItem item) { protected void onMenuItem(MenuItem item) {
debug Log.d("onMenuItem ", item.action.label); debug(DebugMenus) Log.d("onMenuItem ", item.action.label);
if (_openedPopup !is null) { if (_openedPopup !is null) {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null; _openedPopup = null;
@ -539,10 +559,16 @@ class MenuWidgetBase : ListWidget {
override protected void itemClicked(int index) { override protected void itemClicked(int index) {
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null; MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
if (itemWidget !is null) { if (itemWidget !is null) {
Log.d("Menu Item clicked ", itemWidget.item.action.id); debug(DebugMenus) Log.d("Menu ", id, " Item clicked ", itemWidget.item.action.id);
if (itemWidget.item.isSubmenu()) { if (itemWidget.item.isSubmenu()) {
// submenu clicked // submenu clicked
if (_clickOnButtonDown && _openedPopup !is null && _openedMenu._item is itemWidget.item) { if (_clickOnButtonDown && _openedPopup !is null && _openedMenu._item is itemWidget.item) {
if (_selectedItemIndex == index) {
_openedMenu.setFocus();
return;
}
// second click on main menu opened item // second click on main menu opened item
_openedPopup.close(); _openedPopup.close();
_openedPopup = null; _openedPopup = null;
@ -571,6 +597,12 @@ class MenuWidgetBase : ListWidget {
override bool onKeyEvent(KeyEvent event) { override bool onKeyEvent(KeyEvent event) {
if (orientation == Orientation.Horizontal) { if (orientation == Orientation.Horizontal) {
// no special processing // no special processing
if (event.action == KeyAction.KeyDown) {
if (event.keyCode == KeyCode.ESCAPE) {
close();
return true;
}
}
} else { } else {
// for vertical (popup) menu // for vertical (popup) menu
if (!focused) if (!focused)
@ -604,6 +636,9 @@ class MenuWidgetBase : ListWidget {
return true; return true;
} }
return true; return true;
} else if (event.keyCode == KeyCode.ESCAPE) {
close();
return true;
} }
} else if (event.action == KeyAction.KeyUp) { } else if (event.action == KeyAction.KeyUp) {
if (event.keyCode == KeyCode.LEFT || event.keyCode == KeyCode.RIGHT) { if (event.keyCode == KeyCode.LEFT || event.keyCode == KeyCode.RIGHT) {
@ -622,7 +657,13 @@ class MenuWidgetBase : ListWidget {
itemClicked(_selectedItemIndex); itemClicked(_selectedItemIndex);
return true; return true;
} }
return super.onKeyEvent(event); bool res = super.onKeyEvent(event);
return res;
}
/// closes this menu - handle ESC key
void close() {
if (thisPopup !is null)
thisPopup.close();
} }
} }
@ -634,6 +675,7 @@ class MainMenu : MenuWidgetBase {
id = "MAIN_MENU"; id = "MAIN_MENU";
styleId = STYLE_MAIN_MENU; styleId = STYLE_MAIN_MENU;
_clickOnButtonDown = true; _clickOnButtonDown = true;
selectOnHover = false;
} }
/// override and return true to track key events even when not focused /// override and return true to track key events even when not focused
@ -654,7 +696,7 @@ class MainMenu : MenuWidgetBase {
protected Widget _menuTogglePreviousFocus; protected Widget _menuTogglePreviousFocus;
override protected void onMenuItem(MenuItem item) { override protected void onMenuItem(MenuItem item) {
debug Log.d("MainMenu.onMenuItem ", item.action.label); debug(DebugMenus) Log.d("MainMenu.onMenuItem ", item.action.label);
// copy menu item click listeners // copy menu item click listeners
Signal!MenuItemClickHandler onMenuItemClickListenerCopy = onMenuItemClickListener; Signal!MenuItemClickHandler onMenuItemClickListenerCopy = onMenuItemClickListener;
@ -683,9 +725,19 @@ class MainMenu : MenuWidgetBase {
deactivate(); deactivate();
} }
/// closes this menu - ESC handling
override void close() {
debug(DebugMenus) Log.d("menu ", id, " close called");
if (_openedPopup !is null) {
_openedPopup.close();
_openedPopup = null;
} else
deactivate();
}
/// bring focus to main menu, if not yet activated /// bring focus to main menu, if not yet activated
void activate() { void activate() {
debug Log.d("activating main menu"); debug(DebugMenus) Log.d("activating main menu");
if (activated) if (activated)
return; return;
window.setFocus(this); window.setFocus(this);
@ -694,11 +746,13 @@ class MainMenu : MenuWidgetBase {
/// close and remove focus, if activated /// close and remove focus, if activated
void deactivate(bool force = false) { void deactivate(bool force = false) {
debug Log.d("deactivating main menu"); debug(DebugMenus) Log.d("deactivating main menu");
if (!activated && !force) if (!activated && !force)
return; return;
if (_openedPopup !is null) if (_openedPopup !is null) {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null;
}
selectItem(-1); selectItem(-1);
setHoverItem(-1); setHoverItem(-1);
selectOnHover = false; selectOnHover = false;
@ -721,12 +775,14 @@ class MainMenu : MenuWidgetBase {
/// override to handle focus changes /// override to handle focus changes
override protected void handleFocusChange(bool focused) { override protected void handleFocusChange(bool focused) {
debug(DebugMenus) Log.d("menu ", id, "handling focus change to ", focused);
if (focused && _openedPopup is null) { if (focused && _openedPopup is null) {
// activating! // activating!
_menuTogglePreviousFocus = window.focusedWidget; _menuTogglePreviousFocus = window.focusedWidget;
} }
super.handleFocusChange(focused); super.handleFocusChange(focused);
} }
/// list navigation using keys /// list navigation using keys
override bool onKeyEvent(KeyEvent event) { override bool onKeyEvent(KeyEvent event) {
// handle MainMenu activation / deactivation (Alt, Esc...) // handle MainMenu activation / deactivation (Alt, Esc...)
@ -743,7 +799,6 @@ class MainMenu : MenuWidgetBase {
int index = _item.findSubitemByHotkey(ch); int index = _item.findSubitemByHotkey(ch);
if (index >= 0) { if (index >= 0) {
activate(); activate();
//selectItem(index);
itemClicked(index); itemClicked(index);
return true; return true;
} else { } else {
@ -772,6 +827,14 @@ class MainMenu : MenuWidgetBase {
} }
return super.onKeyEvent(event); return super.onKeyEvent(event);
} }
override @property protected uint overrideStateForItem() {
uint res = state;
if (_openedPopup)
res |= State.Focused; // main menu with opened popup as focused for items display
return res;
}
} }