mirror of https://github.com/buggins/dlangui.git
underline main menu item shortcuts when alt is pressed or main menu is active
This commit is contained in:
parent
2719aecadb
commit
dd0527a698
|
|
@ -296,7 +296,13 @@ enum State : uint {
|
|||
Parent = 0x10000, // use parent's state
|
||||
}
|
||||
|
||||
|
||||
/// uppercase unicode character
|
||||
dchar dcharToUpper(dchar ch) {
|
||||
// TODO: support non-ascii letters
|
||||
if (ch >= 'a' && ch <= 'z')
|
||||
return ch - 'a' + 'A';
|
||||
return ch;
|
||||
}
|
||||
|
||||
version (Windows) {
|
||||
immutable char PATH_DELIMITER = '\\';
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ class Font : RefCountedObject {
|
|||
charsMeasured = i + 1;
|
||||
x = tabPosition;
|
||||
continue;
|
||||
} else if (ch == '&' && (textFlags & (TextFlag.UnderlineHotKeys | TextFlag.HotKeys))) {
|
||||
} else if (ch == '&' && (textFlags & (TextFlag.UnderlineHotKeys | TextFlag.HotKeys | TextFlag.UnderlineHotKeysWhenAltPressed))) {
|
||||
pwidths[i] = x;
|
||||
continue; // skip '&' in hot key when measuring
|
||||
}
|
||||
|
|
@ -319,8 +319,8 @@ class Font : RefCountedObject {
|
|||
int underlineY = y + _baseline + underlineHeight * 2;
|
||||
for (int i = 0; i < charsMeasured; i++) {
|
||||
dchar ch = text[i];
|
||||
if (ch == '&' && (textFlags & (TextFlag.UnderlineHotKeys | TextFlag.HotKeys))) {
|
||||
if (textFlags & TextFlag.UnderlineHotKeys)
|
||||
if (ch == '&' && (textFlags & (TextFlag.UnderlineHotKeys | TextFlag.HotKeys | TextFlag.UnderlineHotKeysWhenAltPressed))) {
|
||||
if (textFlags & (TextFlag.UnderlineHotKeys | TextFlag.UnderlineHotKeysWhenAltPressed))
|
||||
underline = true; // turn ON underline for hot key
|
||||
continue; // skip '&' in hot key when measuring
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,15 @@ private import dlangui.graphics.gldrawbuf;
|
|||
class Window {
|
||||
protected int _dx;
|
||||
protected int _dy;
|
||||
protected uint _keyboardModifiers;
|
||||
protected uint _backgroundColor;
|
||||
protected Widget _mainWidget;
|
||||
@property uint backgroundColor() { return _backgroundColor; }
|
||||
@property uint backgroundColor() const { return _backgroundColor; }
|
||||
@property void backgroundColor(uint color) { _backgroundColor = color; }
|
||||
@property int width() { return _dx; }
|
||||
@property int height() { return _dy; }
|
||||
@property Widget mainWidget() { return _mainWidget; }
|
||||
@property int width() const { return _dx; }
|
||||
@property int height() const { return _dy; }
|
||||
@property uint keyboardModifiers() const { return _keyboardModifiers; }
|
||||
@property Widget mainWidget() { return _mainWidget; }
|
||||
@property void mainWidget(Widget widget) {
|
||||
if (_mainWidget !is null)
|
||||
_mainWidget.window = null;
|
||||
|
|
@ -244,13 +246,24 @@ class Window {
|
|||
|
||||
/// dispatch keyboard event
|
||||
bool dispatchKeyEvent(KeyEvent event) {
|
||||
bool res = false;
|
||||
if (event.action == KeyAction.KeyDown || event.action == KeyAction.KeyUp) {
|
||||
_keyboardModifiers = event.flags;
|
||||
if (event.keyCode == KeyCode.ALT || event.keyCode == KeyCode.LALT || event.keyCode == KeyCode.RALT) {
|
||||
Log.d("ALT key: keyboardModifiers = ", _keyboardModifiers);
|
||||
if (_mainWidget) {
|
||||
_mainWidget.invalidate();
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event.action == KeyAction.Text) {
|
||||
// filter text
|
||||
if (event.text.length < 1)
|
||||
return false;
|
||||
return res;
|
||||
dchar ch = event.text[0];
|
||||
if (ch < ' ' || ch == 0x7F) // filter out control symbols
|
||||
return false;
|
||||
return res;
|
||||
}
|
||||
Widget focus = focusedWidget;
|
||||
if (focus !is null) {
|
||||
|
|
@ -258,8 +271,8 @@ class Window {
|
|||
return true; // processed by focused widget
|
||||
}
|
||||
if (_mainWidget)
|
||||
return dispatchKeyEvent(_mainWidget, event);
|
||||
return false;
|
||||
return dispatchKeyEvent(_mainWidget, event) || res;
|
||||
return res;
|
||||
}
|
||||
|
||||
protected bool dispatchMouseEvent(Widget root, MouseEvent event) {
|
||||
|
|
|
|||
|
|
@ -446,17 +446,17 @@ version(USE_SDL) {
|
|||
if (flags & KMOD_ALT)
|
||||
res |= KeyFlag.Alt;
|
||||
if (flags & KMOD_RCTRL)
|
||||
res |= KeyFlag.RControl;
|
||||
res |= KeyFlag.RControl | KeyFlag.Control;
|
||||
if (flags & KMOD_RSHIFT)
|
||||
res |= KeyFlag.RShift;
|
||||
res |= KeyFlag.RShift | KeyFlag.Shift;
|
||||
if (flags & KMOD_RALT)
|
||||
res |= KeyFlag.RAlt;
|
||||
res |= KeyFlag.RAlt | KeyFlag.Alt;
|
||||
if (flags & KMOD_LCTRL)
|
||||
res |= KeyFlag.LControl;
|
||||
res |= KeyFlag.LControl | KeyFlag.Control;
|
||||
if (flags & KMOD_LSHIFT)
|
||||
res |= KeyFlag.LShift;
|
||||
res |= KeyFlag.LShift | KeyFlag.Shift;
|
||||
if (flags & KMOD_LALT)
|
||||
res |= KeyFlag.LAlt;
|
||||
res |= KeyFlag.LAlt | KeyFlag.Alt;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -471,10 +471,45 @@ version(USE_SDL) {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
bool processKeyEvent(KeyAction action, uint keyCode, uint flags) {
|
||||
|
||||
bool processKeyEvent(KeyAction action, uint keyCode, uint flags) {
|
||||
Log.d("processKeyEvent ", action, " SDL key=0x", format("%08x", keyCode), " SDL flags=0x", format("%08x", flags));
|
||||
keyCode = convertKeyCode(keyCode);
|
||||
flags = convertKeyFlags(flags);
|
||||
if (action == KeyAction.KeyDown) {
|
||||
switch(keyCode) {
|
||||
case KeyCode.ALT:
|
||||
flags |= KeyFlag.Alt;
|
||||
break;
|
||||
case KeyCode.RALT:
|
||||
flags |= KeyFlag.Alt | KeyFlag.RAlt;
|
||||
break;
|
||||
case KeyCode.LALT:
|
||||
flags |= KeyFlag.Alt | KeyFlag.LAlt;
|
||||
break;
|
||||
case KeyCode.CONTROL:
|
||||
flags |= KeyFlag.Control;
|
||||
break;
|
||||
case KeyCode.RCONTROL:
|
||||
flags |= KeyFlag.Control | KeyFlag.RControl;
|
||||
break;
|
||||
case KeyCode.LCONTROL:
|
||||
flags |= KeyFlag.Control | KeyFlag.LControl;
|
||||
break;
|
||||
case KeyCode.SHIFT:
|
||||
flags |= KeyFlag.Shift;
|
||||
break;
|
||||
case KeyCode.RSHIFT:
|
||||
flags |= KeyFlag.Shift | KeyFlag.RShift;
|
||||
break;
|
||||
case KeyCode.LSHIFT:
|
||||
flags |= KeyFlag.Shift | KeyFlag.LShift;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("processKeyEvent ", action, " converted key=0x", format("%08x", keyCode), " converted flags=0x", format("%08x", flags));
|
||||
bool res = dispatchKeyEvent(new KeyEvent(action, keyCode, flags));
|
||||
// if ((keyCode & 0x10000) && (keyCode & 0xF000) != 0xF000) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,33 @@ class MenuItem {
|
|||
MenuItem subitem(int index) {
|
||||
return _subitems[index];
|
||||
}
|
||||
/// adds submenu item
|
||||
|
||||
/// get hotkey character from label (e.g. 'F' for item labeled "&File"), 0 if no hotkey
|
||||
dchar getHotkey() {
|
||||
dstring s = label;
|
||||
dchar ch = 0;
|
||||
for (int i = 0; i < s.length - 1; i++) {
|
||||
if (s[i] == '&') {
|
||||
ch = s[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dcharToUpper(ch);
|
||||
}
|
||||
|
||||
/// find subitem by hotkey character, returns subitem index, -1 if not found
|
||||
int findSubitemByHotkey(dchar ch) {
|
||||
if (!ch)
|
||||
return -1;
|
||||
ch = dcharToUpper(ch);
|
||||
for (int i = 0; i < _subitems.length; i++) {
|
||||
if (_subitems[i].getHotkey() == ch)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// adds submenu item
|
||||
MenuItem add(MenuItem subitem) {
|
||||
_subitems ~= subitem;
|
||||
return this;
|
||||
|
|
@ -85,6 +111,7 @@ class MenuItem {
|
|||
|
||||
/// widget to draw menu item
|
||||
class MenuItemWidget : WidgetGroup {
|
||||
protected bool _mainMenu;
|
||||
protected MenuItem _item;
|
||||
protected ImageWidget _icon;
|
||||
protected TextWidget _accel;
|
||||
|
|
@ -180,8 +207,9 @@ class MenuItemWidget : WidgetGroup {
|
|||
}
|
||||
}
|
||||
|
||||
this(MenuItem item) {
|
||||
this(MenuItem item, bool mainMenu) {
|
||||
id="menuitem";
|
||||
_mainMenu = mainMenu;
|
||||
_item = item;
|
||||
styleId = "MENU_ITEM";
|
||||
// icon
|
||||
|
|
@ -193,7 +221,7 @@ class MenuItemWidget : WidgetGroup {
|
|||
// label
|
||||
_label = new TextWidget("MENU_LABEL");
|
||||
_label.text = _item.label;
|
||||
_label.styleId = "MENU_LABEL";
|
||||
_label.styleId = _mainMenu ? "MAIN_MENU_LABEL" : "MENU_LABEL";
|
||||
addChild(_label);
|
||||
// accelerator
|
||||
dstring acc = _item.acceleratorText;
|
||||
|
|
@ -230,9 +258,10 @@ class MenuWidgetBase : ListWidget {
|
|||
WidgetListAdapter adapter = new WidgetListAdapter();
|
||||
for (int i=0; i < _item.subitemCount; i++) {
|
||||
MenuItem subitem = _item.subitem(i);
|
||||
MenuItemWidget widget = new MenuItemWidget(subitem);
|
||||
MenuItemWidget widget = new MenuItemWidget(subitem, orientation == Orientation.Horizontal);
|
||||
if (orientation == Orientation.Horizontal)
|
||||
widget.styleId = "MAIN_MENU_ITEM";
|
||||
widget.parent = this;
|
||||
adapter.widgets.add(widget);
|
||||
}
|
||||
ownAdapter = adapter;
|
||||
|
|
@ -444,7 +473,16 @@ class MainMenu : MenuWidgetBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected int _menuToggleState;
|
||||
/// get text flags (bit set of TextFlag enum values)
|
||||
@property override uint textFlags() {
|
||||
// override text flags for main menu
|
||||
if (activated)
|
||||
return TextFlag.UnderlineHotKeys | TextFlag.HotKeys;
|
||||
else
|
||||
return TextFlag.UnderlineHotKeysWhenAltPressed | TextFlag.HotKeys;
|
||||
}
|
||||
|
||||
protected int _menuToggleState;
|
||||
protected Widget _menuTogglePreviousFocus;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ immutable ubyte FONT_STYLE_ITALIC = 0x01;
|
|||
/// use as widget.layout() param to avoid applying of parent size
|
||||
immutable int SIZE_UNSPECIFIED = int.max;
|
||||
immutable uint TEXT_FLAGS_UNSPECIFIED = uint.max;
|
||||
immutable uint TEXT_FLAGS_USE_PARENT = uint.max - 1;
|
||||
|
||||
immutable int FILL_PARENT = int.max - 1;
|
||||
immutable int WRAP_CONTENT = int.max - 2;
|
||||
|
|
@ -60,8 +61,10 @@ enum TextFlag : uint {
|
|||
HotKeys = 1,
|
||||
/// underline hot key when drawing
|
||||
UnderlineHotKeys = 2,
|
||||
/// underline hot key when drawing
|
||||
UnderlineHotKeysWhenAltPressed = 4,
|
||||
/// underline text when drawing
|
||||
Underline = 4
|
||||
Underline = 8
|
||||
}
|
||||
|
||||
class DrawableAttribute {
|
||||
|
|
@ -747,7 +750,7 @@ Theme createDefaultTheme() {
|
|||
//res.dumpStats();
|
||||
|
||||
Style mainMenu = res.createSubstyle("MAIN_MENU").backgroundColor(0xEFEFF2).layoutWidth(FILL_PARENT);
|
||||
Style mainMenuItem = res.createSubstyle("MAIN_MENU_ITEM").setPadding(4,2,4,2).backgroundImageId("main_menu_item_background");
|
||||
Style mainMenuItem = res.createSubstyle("MAIN_MENU_ITEM").setPadding(4,2,4,2).backgroundImageId("main_menu_item_background").textFlags(TEXT_FLAGS_USE_PARENT);
|
||||
Style menuItem = res.createSubstyle("MENU_ITEM").setPadding(4,2,4,2); //.backgroundColor(0xE0E080) ;
|
||||
menuItem.createState(State.Focused, State.Focused).backgroundColor(0x40C0C000);
|
||||
menuItem.createState(State.Pressed, State.Pressed).backgroundColor(0x4080C000);
|
||||
|
|
@ -755,6 +758,7 @@ Theme createDefaultTheme() {
|
|||
menuItem.createState(State.Hovered, State.Hovered).backgroundColor(0xC0FFFF00);
|
||||
res.createSubstyle("MENU_ICON").setMargins(2,2,2,2).alignment(Align.VCenter|Align.Left);
|
||||
res.createSubstyle("MENU_LABEL").setMargins(4,2,4,2).alignment(Align.VCenter|Align.Left).textFlags(TextFlag.UnderlineHotKeys);
|
||||
res.createSubstyle("MAIN_MENU_LABEL").setMargins(4,2,4,2).alignment(Align.VCenter|Align.Left).textFlags(TEXT_FLAGS_USE_PARENT);
|
||||
res.createSubstyle("MENU_ACCEL").setMargins(4,2,4,2).alignment(Align.VCenter|Align.Left);
|
||||
|
||||
Style transparentButtonBackground = res.createSubstyle("TRANSPARENT_BUTTON_BACKGROUND").backgroundImageId("transparent_button_background").setPadding(4,2,4,2); //.backgroundColor(0xE0E080) ;
|
||||
|
|
|
|||
|
|
@ -300,12 +300,32 @@ class Widget {
|
|||
return this;
|
||||
}
|
||||
/// get text flags (bit set of TextFlag enum values)
|
||||
@property uint textFlags() const { return stateStyle.textFlags; }
|
||||
@property uint textFlags() {
|
||||
uint res = stateStyle.textFlags;
|
||||
if (res == TEXT_FLAGS_USE_PARENT)
|
||||
if (parent)
|
||||
res = parent.textFlags;
|
||||
else
|
||||
res = 0;
|
||||
if (res & TextFlag.UnderlineHotKeysWhenAltPressed) {
|
||||
uint modifiers = 0;
|
||||
if (window !is null)
|
||||
modifiers = window.keyboardModifiers;
|
||||
bool altPressed = (modifiers & (KeyFlag.Alt | KeyFlag.LAlt | KeyFlag.RAlt)) != 0;
|
||||
if (!altPressed) {
|
||||
res = (res & ~(TextFlag.UnderlineHotKeysWhenAltPressed | TextFlag.UnderlineHotKeys)) | TextFlag.HotKeys;
|
||||
} else {
|
||||
res |= TextFlag.UnderlineHotKeys;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
/// set text flags (bit set of TextFlag enum values)
|
||||
@property Widget textFlags(uint value) {
|
||||
ownStyle.textFlags = value;
|
||||
bool oldHotkeys = (ownStyle.textFlags & (TextFlag.HotKeys | TextFlag.UnderlineHotKeys)) != 0;
|
||||
bool newHotkeys = (value & (TextFlag.HotKeys | TextFlag.UnderlineHotKeys)) != 0;
|
||||
bool oldHotkeys = (ownStyle.textFlags & (TextFlag.HotKeys | TextFlag.UnderlineHotKeys | TextFlag.UnderlineHotKeysWhenAltPressed)) != 0;
|
||||
bool newHotkeys = (value & (TextFlag.HotKeys | TextFlag.UnderlineHotKeys | TextFlag.UnderlineHotKeysWhenAltPressed)) != 0;
|
||||
if (oldHotkeys != newHotkeys)
|
||||
requestLayout();
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in New Issue