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 animationActive = false;
if (checkUpdateNeeded(needDraw, needLayout, animationActive) || force) {
Log.d("Requesting update");
debug(DebugRedraw) Log.d("Requesting update");
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
abstract void invalidate();

View File

@ -341,10 +341,16 @@ class ListWidget : WidgetGroup, OnScrollHandler {
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() {
if (_selectedItemIndex != -1) {
if ((_adapter.itemState(_selectedItemIndex) & State.Focused) != (state & State.Focused)) {
if (state & State.Focused)
if ((_adapter.itemState(_selectedItemIndex) & State.Focused) != (overrideStateForItem & State.Focused)) {
if (overrideStateForItem & State.Focused)
_adapter.setItemState(_selectedItemIndex, State.Focused);
else
_adapter.resetItemState(_selectedItemIndex, State.Focused);
@ -472,7 +478,7 @@ class ListWidget : WidgetGroup, OnScrollHandler {
_selectedItemIndex = index;
if (_selectedItemIndex != -1) {
makeSelectionVisible();
_adapter.setItemState(_selectedItemIndex, State.Selected | (state & State.Focused));
_adapter.setItemState(_selectedItemIndex, State.Selected | (overrideStateForItem & State.Focused));
invalidate();
}
return true;

View File

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