fix Ui keyboard navigation

various fixes to allow some support for keyboard navigation in message boxes and dialogs
This commit is contained in:
Triplelexx 2018-01-10 22:30:43 +00:00
parent ac1c398b9d
commit 24f1fc3546
6 changed files with 83 additions and 26 deletions

View file

@ -57,7 +57,7 @@ Original.Button {
hifi.buttons.disabledColorStart[control.colorScheme] hifi.buttons.disabledColorStart[control.colorScheme]
} else if (control.pressed) { } else if (control.pressed) {
hifi.buttons.pressedColor[control.color] hifi.buttons.pressedColor[control.color]
} else if (control.hovered) { } else if (control.hovered || control.focus) {
hifi.buttons.hoveredColor[control.color] hifi.buttons.hoveredColor[control.color]
} else { } else {
hifi.buttons.colorStart[control.color] hifi.buttons.colorStart[control.color]
@ -71,7 +71,7 @@ Original.Button {
hifi.buttons.disabledColorFinish[control.colorScheme] hifi.buttons.disabledColorFinish[control.colorScheme]
} else if (control.pressed) { } else if (control.pressed) {
hifi.buttons.pressedColor[control.color] hifi.buttons.pressedColor[control.color]
} else if (control.hovered) { } else if (control.hovered || control.focus) {
hifi.buttons.hoveredColor[control.color] hifi.buttons.hoveredColor[control.color]
} else { } else {
hifi.buttons.colorFinish[control.color] hifi.buttons.colorFinish[control.color]

View file

@ -704,7 +704,7 @@ ModalWindow {
KeyNavigation.up: selectionType KeyNavigation.up: selectionType
KeyNavigation.left: openButton KeyNavigation.left: openButton
KeyNavigation.right: fileTableView.contentItem KeyNavigation.right: fileTableView.contentItem
Keys.onReturnPressed: { canceled(); root.enabled = false } Keys.onReturnPressed: { cancelAction.trigger() }
} }
} }

View file

@ -37,6 +37,16 @@ ModalWindow {
return OffscreenUi.waitForMessageBoxResult(root); return OffscreenUi.waitForMessageBoxResult(root);
} }
Keys.onRightPressed: if(defaultButton === OriginalDialogs.StandardButton.Yes) {
yesButton.forceActiveFocus()
} else if(defaultButton === OriginalDialogs.StandardButton.Ok) {
okButton.forceActiveFocus()
}
Keys.onTabPressed: if(defaultButton === OriginalDialogs.StandardButton.Yes) {
yesButton.forceActiveFocus()
} else if(defaultButton === OriginalDialogs.StandardButton.Ok) {
okButton.forceActiveFocus()
}
property alias detailedText: detailedText.text property alias detailedText: detailedText.text
property alias text: mainTextContainer.text property alias text: mainTextContainer.text
property alias informativeText: informativeTextContainer.text property alias informativeText: informativeTextContainer.text
@ -47,7 +57,6 @@ ModalWindow {
onIconChanged: updateIcon(); onIconChanged: updateIcon();
property int defaultButton: OriginalDialogs.StandardButton.NoButton; property int defaultButton: OriginalDialogs.StandardButton.NoButton;
property int clickedButton: OriginalDialogs.StandardButton.NoButton; property int clickedButton: OriginalDialogs.StandardButton.NoButton;
focus: defaultButton === OriginalDialogs.StandardButton.NoButton
property int titleWidth: 0 property int titleWidth: 0
onTitleWidthChanged: d.resize(); onTitleWidthChanged: d.resize();
@ -134,16 +143,35 @@ ModalWindow {
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; } MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; } MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; } MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; } MessageDialogButton {
id: noButton
dialog: root
text: qsTr("No")
button: OriginalDialogs.StandardButton.No
KeyNavigation.left: yesButton
KeyNavigation.backtab: yesButton
}
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; } MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; } MessageDialogButton {
id: yesButton
dialog: root
text: qsTr("Yes")
button: OriginalDialogs.StandardButton.Yes
KeyNavigation.right: noButton
KeyNavigation.tab: noButton
}
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; } MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; } MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; } MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; } MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; } MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; } MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; } MessageDialogButton {
id: okButton
dialog: root
text: qsTr("OK")
button: OriginalDialogs.StandardButton.Ok
}
Button { Button {
id: moreButton id: moreButton
@ -230,12 +258,6 @@ ModalWindow {
event.accepted = true event.accepted = true
root.click(OriginalDialogs.StandardButton.Cancel) root.click(OriginalDialogs.StandardButton.Cancel)
break break
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true
root.click(root.defaultButton)
break
} }
} }
} }

View file

@ -95,19 +95,19 @@ ModalWindow {
TextField { TextField {
id: textResult id: textResult
label: root.label label: root.label
focus: items ? false : true
visible: items ? false : true visible: items ? false : true
anchors { anchors {
left: parent.left; left: parent.left;
right: parent.right; right: parent.right;
bottom: parent.bottom bottom: parent.bottom
} }
KeyNavigation.down: acceptButton
KeyNavigation.tab: acceptButton
} }
ComboBox { ComboBox {
id: comboBox id: comboBox
label: root.label label: root.label
focus: true
visible: items ? true : false visible: items ? true : false
anchors { anchors {
left: parent.left left: parent.left
@ -115,6 +115,8 @@ ModalWindow {
bottom: parent.bottom bottom: parent.bottom
} }
model: items ? items : [] model: items ? items : []
KeyNavigation.down: acceptButton
KeyNavigation.tab: acceptButton
} }
} }
@ -135,7 +137,6 @@ ModalWindow {
Flow { Flow {
id: buttons id: buttons
focus: true
spacing: hifi.dimensions.contentSpacing.x spacing: hifi.dimensions.contentSpacing.x
onHeightChanged: d.resize(); onWidthChanged: d.resize(); onHeightChanged: d.resize(); onWidthChanged: d.resize();
layoutDirection: Qt.RightToLeft layoutDirection: Qt.RightToLeft
@ -145,8 +146,21 @@ ModalWindow {
margins: 0 margins: 0
bottomMargin: hifi.dimensions.contentSpacing.y bottomMargin: hifi.dimensions.contentSpacing.y
} }
Button { action: cancelAction } Button {
Button { action: acceptAction } id: cancelButton
action: cancelAction
KeyNavigation.left: acceptButton
KeyNavigation.up: items ? comboBox : textResult
KeyNavigation.backtab: acceptButton
}
Button {
id: acceptButton
action: acceptAction
KeyNavigation.right: cancelButton
KeyNavigation.up: items ? comboBox : textResult
KeyNavigation.tab: cancelButton
KeyNavigation.backtab: items ? comboBox : textResult
}
} }
Action { Action {
@ -184,7 +198,13 @@ ModalWindow {
case Qt.Key_Return: case Qt.Key_Return:
case Qt.Key_Enter: case Qt.Key_Enter:
acceptAction.trigger() if (acceptButton.focus) {
acceptAction.trigger()
} else if(cancelButton.focus) {
cancelAction.trigger()
} else if(comboBox.focus || comboBox.popup.focus) {
comboBox.showList()
}
event.accepted = true; event.accepted = true;
break; break;
} }
@ -194,6 +214,10 @@ ModalWindow {
keyboardEnabled = HMD.active; keyboardEnabled = HMD.active;
updateIcon(); updateIcon();
d.resize(); d.resize();
textResult.forceActiveFocus(); if (items) {
comboBox.forceActiveFocus()
} else {
textResult.forceActiveFocus()
}
} }
} }

View file

@ -16,10 +16,21 @@ import "../../controls-uit"
Button { Button {
property var dialog; property var dialog;
property int button: StandardButton.NoButton; property int button: StandardButton.Ok;
color: dialog.defaultButton === button ? hifi.buttons.blue : hifi.buttons.white color: focus ? hifi.buttons.blue : hifi.buttons.white
focus: dialog.defaultButton === button
onClicked: dialog.click(button) onClicked: dialog.click(button)
visible: dialog.buttons & button visible: dialog.buttons & button
Keys.onPressed: {
if (!focus) {
return
}
switch (event.key) {
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true
dialog.click(button)
break
}
}
} }

View file

@ -103,14 +103,14 @@ void WindowScriptingInterface::raiseMainWindow() {
/// \param const QString& message message to display /// \param const QString& message message to display
/// \return QScriptValue::UndefinedValue /// \return QScriptValue::UndefinedValue
void WindowScriptingInterface::alert(const QString& message) { void WindowScriptingInterface::alert(const QString& message) {
OffscreenUi::asyncWarning("", message); OffscreenUi::asyncWarning("", message, QMessageBox::Ok, QMessageBox::Ok);
} }
/// Display a confirmation box with the options 'Yes' and 'No' /// Display a confirmation box with the options 'Yes' and 'No'
/// \param const QString& message message to display /// \param const QString& message message to display
/// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise /// \return QScriptValue `true` if 'Yes' was clicked, `false` otherwise
QScriptValue WindowScriptingInterface::confirm(const QString& message) { QScriptValue WindowScriptingInterface::confirm(const QString& message) {
return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No))); return QScriptValue((QMessageBox::Yes == OffscreenUi::question("", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)));
} }
/// Display a prompt with a text box /// Display a prompt with a text box
@ -353,7 +353,7 @@ QScriptValue WindowScriptingInterface::browseAssets(const QString& title, const
return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result); return result.isEmpty() ? QScriptValue::NullValue : QScriptValue(result);
} }
/// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid /// Display a select asset dialog that lets the user select an asset from the Asset Server. If `directory` is an invalid
/// directory the browser will start at the root directory. /// directory the browser will start at the root directory.
/// \param const QString& title title of the window /// \param const QString& title title of the window
/// \param const QString& directory directory to start the asset browser at /// \param const QString& directory directory to start the asset browser at