Merge pull request #7164 from ctrlaltdavid/20809

Restyle message box modal dialogs
This commit is contained in:
Brad Hefta-Gaub 2016-02-24 13:47:00 -08:00
commit 568fd3e77f
13 changed files with 303 additions and 106 deletions

View file

@ -0,0 +1,25 @@
//
// TextEdit.qml
//
// Created by Bradley Austin Davis on 24 Apr 2015
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../styles-uit"
TextEdit {
property real size: 32
FontLoader { id: ralewaySemibold; source: "../../fonts/Raleway-Semibold.ttf"; }
font.family: ralewaySemibold.name
font.pointSize: size
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}

View file

@ -1,13 +1,21 @@
//
// Desktop.qml
//
// Created by Bradley Austin Davis on 15 Apr 2015
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs;
import "../dialogs"
import "../menus"
import "../js/Utils.js" as Utils
// This is our primary 'desktop' object to which all VR dialogs and
// windows will be childed.
// This is our primary 'desktop' object to which all VR dialogs and windows are childed.
FocusScope {
id: desktop
objectName: "desktop"
@ -323,6 +331,3 @@ FocusScope {
}
}

View file

@ -1,3 +1,13 @@
//
// FocusHack.qml
//
// Created by Bradley Austin Davis on 21 Jan 2015
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
FocusScope {
@ -22,6 +32,3 @@ FocusScope {
focusTimer.running = true;
}
}

View file

@ -1,13 +1,23 @@
//
// Desktop.qml
//
// Created by Bradley Austin Davis on 25 Apr 2015
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs
import "../controls"
import "../styles"
import "../windows"
import "../controls-uit"
import "../styles-uit"
import "../windows-uit"
import "messageDialog"
// FIXME respect default button functionality
ModalWindow {
id: root
HifiConstants { id: hifi }
@ -32,96 +42,91 @@ ModalWindow {
property alias detailedText: detailedText.text
property alias text: mainTextContainer.text
property alias informativeText: informativeTextContainer.text
onIconChanged: iconHolder.updateIcon();
onIconChanged: updateIcon();
property int buttons: OriginalDialogs.StandardButton.Ok
property int icon: OriginalDialogs.StandardIcon.NoIcon
property string iconText: ""
property int defaultButton: OriginalDialogs.StandardButton.NoButton;
property int clickedButton: OriginalDialogs.StandardButton.NoButton;
focus: defaultButton === OriginalDialogs.StandardButton.NoButton
Rectangle {
function updateIcon() {
if (!root) {
return;
}
switch (root.icon) {
case OriginalDialogs.StandardIcon.Information:
iconText = "\uF05A";
break;
case OriginalDialogs.StandardIcon.Question:
iconText = "\uF059"
break;
case OriginalDialogs.StandardIcon.Warning:
iconText = "\uF071"
break;
case OriginalDialogs.StandardIcon.Critical:
iconText = "\uF057"
break;
default:
iconText = ""
}
}
Item {
id: messageBox
clip: true
anchors.fill: parent
radius: 4
color: "white"
width: pane.width
height: pane.height
QtObject {
id: d
readonly property real spacing: hifi.layout.spacing
readonly property real outerSpacing: hifi.layout.spacing * 2
readonly property real spacing: hifi.dimensions.contentSpacing.x
readonly property real outerSpacing: hifi.dimensions.contentSpacing.y
readonly property int minWidth: 480
readonly property int maxWdith: 1280
readonly property int minHeight: 160
readonly property int minHeight: 120
readonly property int maxHeight: 720
function resize() {
var targetWidth = iconHolder.width + mainTextContainer.width + d.spacing * 6
var targetHeight = mainTextContainer.implicitHeight + informativeTextContainer.implicitHeight + d.spacing * 8 + buttons.height + details.height
var targetWidth = mainTextContainer.width
var targetHeight = mainTextContainer.height + 3 * hifi.dimensions.contentSpacing.y
+ (informativeTextContainer.text != "" ? informativeTextContainer.contentHeight + 3 * hifi.dimensions.contentSpacing.y : 0)
+ buttons.height
+ (content.state === "expanded" ? details.implicitHeight + hifi.dimensions.contentSpacing.y : 0)
root.width = (targetWidth < d.minWidth) ? d.minWidth : ((targetWidth > d.maxWdith) ? d.maxWidth : targetWidth)
root.height = (targetHeight < d.minHeight) ? d.minHeight: ((targetHeight > d.maxHeight) ? d.maxHeight : targetHeight)
}
}
FontAwesome {
id: iconHolder
size: 48
anchors {
left: parent.left
top: parent.top
margins: d.spacing * 2
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
style: Text.Outline; styleColor: "black"
Component.onCompleted: updateIcon();
function updateIcon() {
if (!root) {
return;
}
switch (root.icon) {
case OriginalDialogs.StandardIcon.Information:
text = "\uF05A";
color = "blue";
break;
case OriginalDialogs.StandardIcon.Question:
text = "\uF059"
color = "blue";
break;
case OriginalDialogs.StandardIcon.Warning:
text = "\uF071"
color = "yellow";
break;
case OriginalDialogs.StandardIcon.Critical:
text = "\uF057"
color = "red"
break;
default:
text = ""
}
visible = (text != "");
}
}
Text {
RalewaySemibold {
id: mainTextContainer
onHeightChanged: d.resize(); onWidthChanged: d.resize();
wrapMode: Text.WordWrap
font { pointSize: 14; weight: Font.Bold }
anchors { left: iconHolder.right; top: parent.top; margins: d.spacing * 2 }
size: hifi.fontSizes.menuItem
color: hifi.colors.baseGrayHighlight
anchors {
top: parent.top;
left: parent.left;
margins: 0
topMargin: hifi.dimensions.contentSpacing.y
}
lineHeight: 2
lineHeightMode: Text.ProportionalHeight
}
Text {
RalewaySemibold {
id: informativeTextContainer
onHeightChanged: d.resize(); onWidthChanged: d.resize();
wrapMode: Text.WordWrap
font.pointSize: 11
anchors { top: mainTextContainer.bottom; right: parent.right; left: iconHolder.right; margins: d.spacing * 2 }
size: hifi.fontSizes.menuItem
color: hifi.colors.baseGrayHighlight
anchors {
top: mainTextContainer.bottom
left: parent.left
right: parent.right
margins: 0
topMargin: text != "" ? hifi.dimensions.contentSpacing.y : 0
}
}
Flow {
@ -130,29 +135,35 @@ ModalWindow {
spacing: d.spacing
onHeightChanged: d.resize(); onWidthChanged: d.resize();
layoutDirection: Qt.RightToLeft
anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 }
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; }
MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; }
MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; }
anchors {
top: informativeTextContainer.text == "" ? mainTextContainer.bottom : informativeTextContainer.bottom
horizontalCenter: parent.horizontalCenter
margins: 0
topMargin: 2 * hifi.dimensions.contentSpacing.y
}
MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; }
MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; }
MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; }
MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; }
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("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
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("Retry"); button: OriginalDialogs.StandardButton.Retry; }
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("Open"); button: OriginalDialogs.StandardButton.Open; }
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
Button {
id: moreButton
text: qsTr("Show Details...")
onClicked: { content.state = (content.state === "" ? "expanded" : "")
}
width: 160
onClicked: { content.state = (content.state === "" ? "expanded" : "") }
visible: detailedText && detailedText.length > 0
}
MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; }
@ -161,10 +172,16 @@ ModalWindow {
Item {
id: details
width: parent.width
implicitHeight: detailedText.implicitHeight + root.spacing
implicitHeight: detailedText.implicitHeight
height: 0
clip: true
anchors { bottom: parent.bottom; left: parent.left; right: parent.right; margins: d.spacing * 2 }
anchors {
top: buttons.bottom
left: parent.left;
right: parent.right;
margins: 0
topMargin: hifi.dimensions.contentSpacing.y
}
Flickable {
id: flickable
contentHeight: detailedText.height
@ -173,10 +190,13 @@ ModalWindow {
anchors.bottomMargin: root.outerSpacing
TextEdit {
id: detailedText
size: hifi.fontSizes.menuItem
color: hifi.colors.baseGrayHighlight
width: details.width
wrapMode: Text.WordWrap
readOnly: true
selectByMouse: true
anchors.margins: 0
}
}
}
@ -190,6 +210,7 @@ ModalWindow {
}
]
Component.onCompleted: updateIcon();
onStateChanged: d.resize()
}

View file

@ -1,11 +1,24 @@
//
// MessageDialogButton.qml
//
// Created by Bradley Austin Davis on 29 Jan 2016
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import "../../controls-uit"
Button {
property var dialog;
property int button: StandardButton.NoButton;
color: dialog.defaultButton === button ? hifi.buttons.blue : hifi.buttons.white
focus: dialog.defaultButton === button
onClicked: dialog.click(button)
visible: dialog.buttons & button

View file

@ -43,6 +43,7 @@ Item {
readonly property color baseGrayShadow60: "#99252525"
readonly property color baseGrayHighlight40: "#66575757"
readonly property color baseGrayHighlight15: "#26575757"
readonly property color lightGrayText80: "#ccafafaf"
readonly property color faintGray50: "#80e3e3e3"
// Other colors
@ -78,6 +79,8 @@ Item {
readonly property real textPadding: 8
readonly property real tablePadding: 12
readonly property real tableRowHeight: largeScreen ? 26 : 23
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
readonly property real modalDialogTitleHeight: 40
}
Item {

View file

@ -18,7 +18,6 @@ Item {
id: frame
HifiConstants { id: hifi }
property alias window: frame.parent // Convenience accessor for the window
default property var decoration
readonly property int iconSize: 22

View file

@ -0,0 +1,75 @@
//
// ModalFrame.qml
//
// Created by Bradley Austin Davis on 15 Jan 2016
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "."
import "../controls-uit"
import "../styles-uit"
Frame {
Item {
id: modalFrame
anchors.fill: parent
anchors.margins: 0
readonly property bool hasTitle: window.title != ""
Rectangle {
anchors {
topMargin: -hifi.dimensions.modalDialogMargin.y - (modalFrame.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0)
leftMargin: -hifi.dimensions.modalDialogMargin.x
rightMargin: -hifi.dimensions.modalDialogMargin.x
bottomMargin: -hifi.dimensions.modalDialogMargin.y
fill: parent
}
border {
width: hifi.dimensions.borderWidth
color: hifi.colors.lightGrayText80
}
radius: hifi.dimensions.borderRadius
color: hifi.colors.faintGray
}
Item {
visible: modalFrame.hasTitle
width: title.width + (window.iconText !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0)
x: (parent.width - width) / 2
FontAwesome {
id: icon
text: window.iconText
size: 30
color: hifi.colors.lightGrayText
visible: text != ""
y: -hifi.dimensions.modalDialogTitleHeight - 5
anchors.left: parent.left
}
RalewayRegular {
id: title
text: window.title
elide: Text.ElideRight
color: hifi.colors.baseGrayHighlight
size: hifi.fontSizes.overlayTitle
y: -hifi.dimensions.modalDialogTitleHeight
anchors.right: parent.right
}
}
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
height: 1
color: hifi.colors.lightGray
visible: modalFrame.hasTitle
}
}
}

View file

@ -0,0 +1,22 @@
//
// ModalWindow.qml
//
// Created by Bradley Austin Davis on 22 Jan 2016
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import "."
Window {
id: window
anchors.centerIn: parent
modality: Qt.ApplicationModal
destroyOnCloseButton: true
destroyOnInvisible: true
frame: ModalFrame{}
}

View file

@ -58,6 +58,8 @@ Fadable {
// The content to place inside the window, determined by the client
default property var content
function setDefaultFocus() {} // Default function; can be overridden by dialogs.
property var rectifier: Timer {
property bool executing: false;
interval: 100
@ -133,12 +135,13 @@ Fadable {
anchors.fill: parent
anchors.rightMargin: parent.isScrolling ? 11 : 0
color: hifi.colors.baseGray
visible: modality != Qt.ApplicationModal
}
LinearGradient {
// FIXME: Alpha gradients display as fuschia under QtQuick 2.5 on OSX.
// Check again when have a later version of QtQuick.
visible: Qt.platform.os != "osx"
visible: modality != Qt.ApplicationModal && Qt.platform.os != "osx"
anchors.top: contentBackground.bottom
anchors.left: contentBackground.left
width: contentBackground.width - 1
@ -201,7 +204,6 @@ Fadable {
}
}
}
children: [ swallower, frame, pane, activator ]
Component.onCompleted: { raise(); setDefaultFocus(); }

View file

@ -4312,7 +4312,7 @@ bool Application::askToSetAvatarUrl(const QString& url) {
case FSTReader::HEAD_AND_BODY_MODEL:
ok = QMessageBox::Ok == OffscreenUi::question("Set Avatar",
"Would you like to use '" + modelName + "' for your avatar?",
QMessageBox::Ok | QMessageBox::Cancel);
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
break;
default:

View file

@ -81,17 +81,27 @@ ApplicationWindow {
}
*/
Button {
text: "Show Long Error"
// Replicates message box that pops up after selecting new avatar. Includes title.
text: "Confirm Avatar"
onClicked: {
desktop.messageBox({
informativeText: "Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds ",
text: "Baloney",
icon: OriginalDialogs.StandardIcon.Warning,
detailedText: "sakjd;laskj dksa;dl jka;lsd j;lkjas ;dlkaj s;dlakjd ;alkjda; slkjda; lkjda;lksjd ;alksjd; alksjd ;alksjd; alksjd; alksdjas;ldkjas;lkdja ;kj ;lkasjd; lkj as;dlka jsd;lka jsd;laksjd a"
var messageBox = desktop.messageBox({
title: "Set Avatar",
text: "Would you like to use 'Albert' for your avatar?",
icon: OriginalDialogs.StandardIcon.Question, // Test question icon
//icon: OriginalDialogs.StandardIcon.Information, // Test informaton icon
//icon: OriginalDialogs.StandardIcon.Warning, // Test warning icon
//icon: OriginalDialogs.StandardIcon.Critical, // Test critical icon
//icon: OriginalDialogs.StandardIcon.NoIcon, // Test no icon
buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel,
defaultButton: OriginalDialogs.StandardButton.Ok
});
messageBox.selected.connect(function(button) {
console.log("You clicked " + button)
})
}
}
Button {
// Message without title.
text: "Show Error"
onClicked: {
var messageBox = desktop.messageBox({
@ -103,6 +113,20 @@ ApplicationWindow {
})
}
}
Button {
// detailedText is not currently used anywhere in Interface but it is easier to leave in and style good enough.
text: "Show Long Error"
onClicked: {
desktop.messageBox({
informativeText: "Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds Diagnostic cycle will be complete in 30 seconds ",
text: "Baloney",
icon: OriginalDialogs.StandardIcon.Warning,
detailedText: "sakjd;laskj dksa;dl jka;lsd j;lkjas ;dlkaj s;dlakjd ;alkjda; slkjda; lkjda;lksjd ;alksjd; alksjd ;alksjd; alksjd; alksdjas;ldkjas;lkdja ;kj ;lkasjd; lkj as;dlka jsd;lka jsd;laksjd a"
});
}
}
/*
// There is no such desktop.queryBox() function; may need to update test to cover QueryDialog.qml?
Button {
text: "Show Query"
onClicked: {
@ -120,6 +144,7 @@ ApplicationWindow {
})
}
}
*/
Button {
text: "Open Directory"
property var builder: Component {