mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 14:42:19 +02:00
Pinned UI support
This commit is contained in:
parent
068a462901
commit
8c13ff4ee1
50 changed files with 1003 additions and 1469 deletions
|
@ -20,9 +20,10 @@ Window {
|
|||
|
||||
objectName: "AddressBarDialog"
|
||||
frame: HiddenFrame {}
|
||||
hideBackground: true
|
||||
|
||||
visible: false
|
||||
destroyOnInvisible: false
|
||||
shown: false
|
||||
destroyOnHidden: false
|
||||
resizable: false
|
||||
scale: 1.25 // Make this dialog a little larger than normal
|
||||
|
||||
|
@ -145,14 +146,14 @@ Window {
|
|||
if (addressLine.text !== "") {
|
||||
addressBarDialog.loadAddress(addressLine.text)
|
||||
}
|
||||
root.visible = false;
|
||||
root.shown = false;
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
root.visible = false
|
||||
root.shown = false
|
||||
event.accepted = true
|
||||
break
|
||||
case Qt.Key_Enter:
|
||||
|
|
|
@ -15,7 +15,7 @@ import Qt.labs.settings 1.0
|
|||
|
||||
import "styles-uit"
|
||||
import "controls-uit" as HifiControls
|
||||
import "windows-uit"
|
||||
import "windows"
|
||||
import "dialogs"
|
||||
|
||||
Window {
|
||||
|
@ -23,7 +23,7 @@ Window {
|
|||
objectName: "AssetServer"
|
||||
title: "Asset Browser"
|
||||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
implicitWidth: 384; implicitHeight: 640
|
||||
minSize: Qt.vector2d(200, 300)
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@ Window {
|
|||
HifiConstants { id: hifi }
|
||||
title: "Browser"
|
||||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
width: 800
|
||||
height: 600
|
||||
property alias webView: webview
|
||||
|
||||
Component.onCompleted: {
|
||||
visible = true
|
||||
shown = true
|
||||
addressBar.text = webview.url
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import QtQuick 2.5
|
|||
import Hifi 1.0 as Hifi
|
||||
|
||||
import "controls-uit"
|
||||
import "windows-uit" as Windows
|
||||
import "windows" as Windows
|
||||
|
||||
Windows.Window {
|
||||
id: root
|
||||
|
|
|
@ -22,8 +22,9 @@ Window {
|
|||
width: loginDialog.implicitWidth
|
||||
// FIXME make movable
|
||||
anchors.centerIn: parent
|
||||
destroyOnInvisible: false
|
||||
visible: false
|
||||
destroyOnHidden: false
|
||||
hideBackground: true
|
||||
shown: false
|
||||
|
||||
LoginDialog {
|
||||
id: loginDialog
|
||||
|
@ -268,8 +269,8 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
onShownChanged: {
|
||||
if (!shown) {
|
||||
username.text = ""
|
||||
password.text = ""
|
||||
loginDialog.statusText = ""
|
||||
|
@ -282,7 +283,7 @@ Window {
|
|||
switch (event.key) {
|
||||
case Qt.Key_Escape:
|
||||
case Qt.Key_Back:
|
||||
root.visible = false;
|
||||
root.shown = false;
|
||||
event.accepted = true;
|
||||
break;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import QtQuick.Controls 1.4
|
|||
import QtWebEngine 1.1
|
||||
import QtWebChannel 1.0
|
||||
|
||||
import "windows-uit" as Windows
|
||||
import "windows" as Windows
|
||||
import "controls-uit" as Controls
|
||||
import "styles-uit"
|
||||
|
||||
|
@ -22,7 +22,7 @@ Windows.Window {
|
|||
HifiConstants { id: hifi }
|
||||
title: "WebWindow"
|
||||
resizable: true
|
||||
visible: false
|
||||
shown: false
|
||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||
destroyOnCloseButton: false
|
||||
property alias source: webview.url
|
||||
|
|
|
@ -14,7 +14,7 @@ Windows.Window {
|
|||
HifiConstants { id: hifi }
|
||||
title: "QmlWindow"
|
||||
resizable: true
|
||||
visible: false
|
||||
shown: false
|
||||
focus: true
|
||||
property var channel;
|
||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||
|
|
|
@ -15,7 +15,7 @@ import QtWebEngine 1.1
|
|||
import QtWebChannel 1.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
import "windows-uit"
|
||||
import "windows"
|
||||
import "controls-uit"
|
||||
import "styles-uit"
|
||||
|
||||
|
@ -24,9 +24,9 @@ Window {
|
|||
resizable: true
|
||||
objectName: "ToolWindow"
|
||||
destroyOnCloseButton: false
|
||||
destroyOnInvisible: false
|
||||
destroyOnHidden: false
|
||||
closable: true
|
||||
visible: false
|
||||
shown: false
|
||||
title: "Edit"
|
||||
property alias tabView: tabView
|
||||
implicitWidth: 520; implicitHeight: 695
|
||||
|
@ -142,7 +142,7 @@ Window {
|
|||
return;
|
||||
}
|
||||
}
|
||||
visible = false;
|
||||
shown = false;
|
||||
}
|
||||
|
||||
function findIndexForUrl(source) {
|
||||
|
@ -172,7 +172,7 @@ Window {
|
|||
|
||||
var tab = tabView.getTab(index);
|
||||
if (newVisible) {
|
||||
toolWindow.visible = true
|
||||
toolWindow.shown = true
|
||||
tab.enabled = true
|
||||
} else {
|
||||
tab.enabled = false;
|
||||
|
|
|
@ -15,7 +15,7 @@ import QtQuick.XmlListModel 2.0
|
|||
|
||||
import "../styles-uit"
|
||||
import "../controls-uit" as HifiControls
|
||||
import "../windows-uit"
|
||||
import "../windows"
|
||||
import "../hifi/models"
|
||||
|
||||
TableView {
|
||||
|
|
|
@ -52,6 +52,7 @@ FocusScope {
|
|||
readonly property real menu: 8000
|
||||
}
|
||||
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
|
@ -93,6 +94,17 @@ FocusScope {
|
|||
return item;
|
||||
}
|
||||
|
||||
function findMatchingChildren(item, predicate) {
|
||||
var results = [];
|
||||
for (var i in item.children) {
|
||||
var child = item.children[i];
|
||||
if (predicate(child)) {
|
||||
results.push(child);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
function isTopLevelWindow(item) {
|
||||
return item.topLevelWindow;
|
||||
}
|
||||
|
@ -106,19 +118,9 @@ FocusScope {
|
|||
}
|
||||
|
||||
function getTopLevelWindows(predicate) {
|
||||
var currentWindows = [];
|
||||
if (!desktop) {
|
||||
console.log("Could not find desktop for " + item)
|
||||
return currentWindows;
|
||||
}
|
||||
|
||||
for (var i = 0; i < desktop.children.length; ++i) {
|
||||
var child = desktop.children[i];
|
||||
if (isTopLevelWindow(child) && (!predicate || predicate(child))) {
|
||||
currentWindows.push(child)
|
||||
}
|
||||
}
|
||||
return currentWindows;
|
||||
return findMatchingChildren(desktop, function(child) {
|
||||
return (isTopLevelWindow(child) && (!predicate || predicate(child)));
|
||||
});
|
||||
}
|
||||
|
||||
function getDesktopWindow(item) {
|
||||
|
@ -227,19 +229,9 @@ FocusScope {
|
|||
}
|
||||
|
||||
function getRepositionChildren(predicate) {
|
||||
var currentWindows = [];
|
||||
if (!desktop) {
|
||||
console.log("Could not find desktop");
|
||||
return currentWindows;
|
||||
}
|
||||
|
||||
for (var i = 0; i < desktop.children.length; ++i) {
|
||||
var child = desktop.children[i];
|
||||
if (child.shouldReposition === true && (!predicate || predicate(child))) {
|
||||
currentWindows.push(child)
|
||||
}
|
||||
}
|
||||
return currentWindows;
|
||||
return findMatchingChildren(desktop, function(child) {
|
||||
return (child.shouldReposition === true && (!predicate || predicate(child)));
|
||||
});
|
||||
}
|
||||
|
||||
function repositionAll() {
|
||||
|
@ -265,6 +257,35 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
property bool pinned: false
|
||||
property var hiddenChildren: []
|
||||
|
||||
function togglePinned() {
|
||||
pinned = !pinned
|
||||
}
|
||||
|
||||
onPinnedChanged: {
|
||||
|
||||
if (pinned) {
|
||||
hiddenChildren = d.findMatchingChildren(desktop, function(child){
|
||||
return !d.isTopLevelWindow(child) && child.visible;
|
||||
});
|
||||
|
||||
hiddenChildren.forEach(function(child){
|
||||
child.visible = false;
|
||||
});
|
||||
} else {
|
||||
hiddenChildren.forEach(function(child){
|
||||
if (child) {
|
||||
child.visible = true;
|
||||
}
|
||||
});
|
||||
hiddenChildren = [];
|
||||
}
|
||||
}
|
||||
|
||||
onShowDesktop: pinned = false
|
||||
|
||||
function raise(item) {
|
||||
var targetWindow = d.getDesktopWindow(item);
|
||||
if (!targetWindow) {
|
||||
|
@ -422,7 +443,6 @@ FocusScope {
|
|||
event.accepted = false;
|
||||
}
|
||||
|
||||
|
||||
function unfocusWindows() {
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
|
|
|
@ -18,7 +18,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
|
|||
import ".."
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows-uit"
|
||||
import "../windows"
|
||||
|
||||
import "fileDialog"
|
||||
|
||||
|
@ -724,7 +724,7 @@ ModalWindow {
|
|||
Action {
|
||||
id: cancelAction
|
||||
text: "Cancel"
|
||||
onTriggered: { canceled(); root.visible = false; }
|
||||
onTriggered: { canceled(); root.shown = false; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
|
|||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows-uit"
|
||||
import "../windows"
|
||||
|
||||
import "messageDialog"
|
||||
|
||||
|
@ -24,7 +24,7 @@ ModalWindow {
|
|||
implicitWidth: 640
|
||||
implicitHeight: 320
|
||||
destroyOnCloseButton: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
visible: true
|
||||
|
||||
signal selected(int button);
|
||||
|
|
|
@ -13,14 +13,14 @@ import QtQuick.Controls 1.4
|
|||
|
||||
import "../controls-uit" as HifiControls
|
||||
import "../styles-uit"
|
||||
import "../windows-uit"
|
||||
import "../windows"
|
||||
import "preferences"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
title: "Preferences"
|
||||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
width: 500
|
||||
height: 577
|
||||
property var sections: []
|
||||
|
|
|
@ -14,7 +14,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
|
|||
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
import "../windows-uit"
|
||||
import "../windows"
|
||||
|
||||
ModalWindow {
|
||||
id: root
|
||||
|
|
|
@ -12,7 +12,7 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.4
|
||||
import QtWebEngine 1.1
|
||||
|
||||
import "../../windows-uit" as Windows
|
||||
import "../../windows" as Windows
|
||||
import "../../controls-uit" as Controls
|
||||
import "../../styles-uit"
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import QtQuick.Controls.Styles 1.4
|
|||
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows-uit"
|
||||
import "../../windows"
|
||||
import "attachments"
|
||||
|
||||
Window {
|
||||
|
@ -16,7 +16,7 @@ Window {
|
|||
width: 600
|
||||
height: 600
|
||||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
minSize: Qt.vector2d(400, 500)
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
|
|
@ -9,7 +9,7 @@ import "../models"
|
|||
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows-uit"
|
||||
import "../../windows"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
|
|
@ -15,14 +15,14 @@ import Qt.labs.settings 1.0
|
|||
|
||||
import "../../styles-uit"
|
||||
import "../../controls-uit" as HifiControls
|
||||
import "../../windows-uit"
|
||||
import "../../windows"
|
||||
|
||||
Window {
|
||||
id: root
|
||||
objectName: "RunningScripts"
|
||||
title: "Running Scripts"
|
||||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
destroyOnHidden: true
|
||||
implicitWidth: 400
|
||||
implicitHeight: isHMD ? 695 : 728
|
||||
minSize: Qt.vector2d(200, 300)
|
||||
|
@ -34,6 +34,9 @@ Window {
|
|||
property var runningScriptsModel: ListModel { }
|
||||
property bool isHMD: false
|
||||
|
||||
onVisibleChanged: console.log("Running scripts visible changed to " + visible)
|
||||
onShownChanged: console.log("Running scripts visible changed to " + visible)
|
||||
|
||||
Settings {
|
||||
category: "Overlay.RunningScripts"
|
||||
property alias x: root.x
|
||||
|
|
|
@ -8,7 +8,7 @@ import "."
|
|||
import ".."
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControls
|
||||
import "../../../windows-uit"
|
||||
import "../../../windows"
|
||||
|
||||
Item {
|
||||
height: column.height + 2 * 8
|
||||
|
|
|
@ -3,7 +3,7 @@ import QtQuick.Controls 1.4
|
|||
|
||||
import "../../../styles-uit"
|
||||
import "../../../controls-uit" as HifiControls
|
||||
import "../../../windows-uit"
|
||||
import "../../../windows"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
//
|
||||
// DefaultFrame.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "."
|
||||
import "../styles-uit"
|
||||
|
||||
Frame {
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Rectangle {
|
||||
// Dialog frame
|
||||
id: frameContent
|
||||
|
||||
readonly property int iconSize: hifi.dimensions.frameIconSize
|
||||
readonly property int frameMargin: 9
|
||||
readonly property int frameMarginLeft: frameMargin
|
||||
readonly property int frameMarginRight: frameMargin
|
||||
readonly property int frameMarginTop: 2 * frameMargin + iconSize
|
||||
readonly property int frameMarginBottom: iconSize + 11
|
||||
|
||||
anchors {
|
||||
topMargin: -frameMarginTop
|
||||
leftMargin: -frameMarginLeft
|
||||
rightMargin: -frameMarginRight
|
||||
bottomMargin: -frameMarginBottom
|
||||
}
|
||||
anchors.fill: parent
|
||||
color: hifi.colors.baseGrayHighlight40
|
||||
border {
|
||||
width: hifi.dimensions.borderWidth
|
||||
color: hifi.colors.faintGray50
|
||||
}
|
||||
radius: hifi.dimensions.borderRadius
|
||||
|
||||
// Enable dragging of the window
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: window
|
||||
}
|
||||
|
||||
Row {
|
||||
id: controlsRow
|
||||
anchors {
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
topMargin: frameContent.frameMargin + 1 // Move down a little to visually align with the title
|
||||
rightMargin: frameContent.frameMarginRight;
|
||||
}
|
||||
spacing: frameContent.iconSize / 4
|
||||
|
||||
HiFiGlyphs {
|
||||
// "Pin" button
|
||||
visible: false
|
||||
text: (frame.pinned && !pinClickArea.containsMouse) || (!frame.pinned && pinClickArea.containsMouse) ? hifi.glyphs.pinInverted : hifi.glyphs.pin
|
||||
color: pinClickArea.containsMouse && !pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: frameContent.iconSize
|
||||
MouseArea {
|
||||
id: pinClickArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
onClicked: { frame.pin(); mouse.accepted = false; }
|
||||
}
|
||||
}
|
||||
|
||||
HiFiGlyphs {
|
||||
// "Close" button
|
||||
visible: window ? window.closable : false
|
||||
text: closeClickArea.containsPress ? hifi.glyphs.closeInverted : hifi.glyphs.close
|
||||
color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: frameContent.iconSize
|
||||
MouseArea {
|
||||
id: closeClickArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: window.visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RalewayRegular {
|
||||
// Title
|
||||
id: titleText
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: frameContent.frameMarginLeft + hifi.dimensions.contentMargin.x
|
||||
right: controlsRow.left
|
||||
rightMargin: frameContent.iconSize
|
||||
top: parent.top
|
||||
topMargin: frameContent.frameMargin
|
||||
}
|
||||
text: window ? window.title : ""
|
||||
color: hifi.colors.white
|
||||
size: hifi.fontSizes.overlayTitle
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
source: titleText
|
||||
anchors.fill: titleText
|
||||
horizontalOffset: 2
|
||||
verticalOffset: 2
|
||||
samples: 2
|
||||
color: hifi.colors.baseGrayShadow60
|
||||
visible: (window && window.focus)
|
||||
cached: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
//
|
||||
// Fadable.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 15 Jan 2016
|
||||
// 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
|
||||
import QtQuick.Controls 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
// Enable window visibility transitions
|
||||
FocusScope {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Component.onCompleted: {
|
||||
fadeTargetProperty = visible ? 1.0 : 0.0
|
||||
}
|
||||
|
||||
// The target property to animate, usually scale or opacity
|
||||
property alias fadeTargetProperty: root.opacity
|
||||
// always start the property at 0 to enable fade in on creation
|
||||
fadeTargetProperty: 0
|
||||
// DO NOT set visible to false or when derived types override it it
|
||||
// will short circuit the fade in on initial visibility
|
||||
// visible: false <--- NO
|
||||
|
||||
// Some dialogs should be destroyed when they become
|
||||
// invisible, so handle that
|
||||
onVisibleChanged: {
|
||||
// If someone directly set the visibility to false
|
||||
// toggle it back on and use the targetVisible flag to transition
|
||||
// via fading.
|
||||
if ((!visible && fadeTargetProperty != 0.0) || (visible && fadeTargetProperty == 0.0)) {
|
||||
var target = visible;
|
||||
visible = !visible;
|
||||
fadeTargetProperty = target ? 1.0 : 0.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The actual animator
|
||||
Behavior on fadeTargetProperty {
|
||||
NumberAnimation {
|
||||
duration: hifi.effects.fadeInDuration
|
||||
easing.type: Easing.InOutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Once we're transparent, disable the dialog's visibility
|
||||
onFadeTargetPropertyChanged: {
|
||||
visible = (fadeTargetProperty != 0.0);
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
//
|
||||
// Frame.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
import "../js/Utils.js" as Utils
|
||||
|
||||
Item {
|
||||
id: frame
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
default property var decoration
|
||||
|
||||
property bool gradientsSupported: desktop.gradientsSupported
|
||||
|
||||
readonly property int frameMarginLeft: frameContent.frameMarginLeft
|
||||
readonly property int frameMarginRight: frameContent.frameMarginRight
|
||||
readonly property int frameMarginTop: frameContent.frameMarginTop
|
||||
readonly property int frameMarginBottom: frameContent.frameMarginBottom
|
||||
|
||||
// Frames always fill their parents, but their decorations may extend
|
||||
// beyond the window via negative margin sizes
|
||||
anchors.fill: parent
|
||||
|
||||
children: [
|
||||
focusShadow,
|
||||
decoration,
|
||||
sizeOutline,
|
||||
debugZ,
|
||||
sizeDrag
|
||||
]
|
||||
|
||||
Text {
|
||||
id: debugZ
|
||||
visible: DebugQML
|
||||
text: window ? "Z: " + window.z : ""
|
||||
y: window ? window.height + 4 : 0
|
||||
}
|
||||
|
||||
function deltaSize(dx, dy) {
|
||||
var newSize = Qt.vector2d(window.width + dx, window.height + dy);
|
||||
newSize = Utils.clampVector(newSize, window.minSize, window.maxSize);
|
||||
window.width = newSize.x
|
||||
window.height = newSize.y
|
||||
}
|
||||
|
||||
RadialGradient {
|
||||
id: focusShadow
|
||||
width: 1.66 * window.width
|
||||
height: 1.66 * window.height
|
||||
x: (window.width - width) / 2
|
||||
y: window.height / 2 - 0.375 * height
|
||||
visible: gradientsSupported && window && window.focus && pane.visible
|
||||
gradient: Gradient {
|
||||
// GradientStop position 0.5 is at full circumference of circle that fits inside the square.
|
||||
GradientStop { position: 0.0; color: "#ff000000" } // black, 100% opacity
|
||||
GradientStop { position: 0.333; color: "#1f000000" } // black, 12% opacity
|
||||
GradientStop { position: 0.5; color: "#00000000" } // black, 0% opacity
|
||||
GradientStop { position: 1.0; color: "#00000000" }
|
||||
}
|
||||
cached: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sizeOutline
|
||||
x: -frameMarginLeft
|
||||
y: -frameMarginTop
|
||||
width: window ? window.width + frameMarginLeft + frameMarginRight + 2 : 0
|
||||
height: window ? window.height + frameMarginTop + frameMarginBottom + 2 : 0
|
||||
color: hifi.colors.baseGrayHighlight15
|
||||
border.width: 3
|
||||
border.color: hifi.colors.white50
|
||||
radius: hifi.dimensions.borderRadius
|
||||
visible: window ? !pane.visible : false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
// Resize handle
|
||||
id: sizeDrag
|
||||
width: hifi.dimensions.frameIconSize
|
||||
height: hifi.dimensions.frameIconSize
|
||||
enabled: window ? window.resizable : false
|
||||
hoverEnabled: true
|
||||
x: window ? window.width + frameMarginRight - hifi.dimensions.frameIconSize : 0
|
||||
y: window ? window.height + 4 : 0
|
||||
property vector2d pressOrigin
|
||||
property vector2d sizeOrigin
|
||||
property bool hid: false
|
||||
onPressed: {
|
||||
//console.log("Pressed on size")
|
||||
pressOrigin = Qt.vector2d(mouseX, mouseY)
|
||||
sizeOrigin = Qt.vector2d(window.content.width, window.content.height)
|
||||
hid = false;
|
||||
}
|
||||
onReleased: {
|
||||
if (hid) {
|
||||
pane.visible = true
|
||||
frameContent.visible = true
|
||||
hid = false;
|
||||
}
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (pressed) {
|
||||
if (pane.visible) {
|
||||
pane.visible = false;
|
||||
frameContent.visible = false
|
||||
hid = true;
|
||||
}
|
||||
var delta = Qt.vector2d(mouseX, mouseY).minus(pressOrigin);
|
||||
frame.deltaSize(delta.x, delta.y)
|
||||
}
|
||||
}
|
||||
HiFiGlyphs {
|
||||
visible: sizeDrag.enabled
|
||||
x: -11 // Move a little to visually align
|
||||
y: window.modality == Qt.ApplicationModal ? -6 : -4
|
||||
text: hifi.glyphs.resizeHandle
|
||||
size: hifi.dimensions.frameIconSize + 10
|
||||
color: sizeDrag.containsMouse || sizeDrag.pressed
|
||||
? hifi.colors.white
|
||||
: (window.colorScheme == hifi.colorSchemes.dark ? hifi.colors.white50 : hifi.colors.lightGrayText80)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
//
|
||||
// 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 {
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Rectangle {
|
||||
id: frameContent
|
||||
|
||||
readonly property bool hasTitle: window.title != ""
|
||||
|
||||
readonly property int frameMarginLeft: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginRight: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginTop: hifi.dimensions.modalDialogMargin.y + (frameContent.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0)
|
||||
readonly property int frameMarginBottom: hifi.dimensions.modalDialogMargin.y
|
||||
|
||||
signal frameClicked();
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: -frameMarginTop
|
||||
leftMargin: -frameMarginLeft
|
||||
rightMargin: -frameMarginRight
|
||||
bottomMargin: -frameMarginBottom
|
||||
}
|
||||
|
||||
border {
|
||||
width: hifi.dimensions.borderWidth
|
||||
color: hifi.colors.lightGrayText80
|
||||
}
|
||||
radius: hifi.dimensions.borderRadius
|
||||
color: hifi.colors.faintGray
|
||||
|
||||
// Enable dragging of the window
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: window
|
||||
enabled: window.draggable
|
||||
onClicked: window.frameClicked();
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: frameContent.hasTitle
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
topMargin: -parent.anchors.topMargin
|
||||
leftMargin: -parent.anchors.leftMargin
|
||||
rightMargin: -parent.anchors.rightMargin
|
||||
}
|
||||
|
||||
Item {
|
||||
width: title.width + (icon.text !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0)
|
||||
x: (parent.width - width) / 2
|
||||
|
||||
onWidthChanged: window.titleWidth = width
|
||||
|
||||
HiFiGlyphs {
|
||||
id: icon
|
||||
text: window.iconText ? window.iconText : ""
|
||||
size: window.iconSize ? window.iconSize : 30
|
||||
color: hifi.colors.lightGray
|
||||
visible: text != ""
|
||||
anchors.verticalCenter: title.verticalCenter
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
modality: Qt.ApplicationModal
|
||||
destroyOnCloseButton: true
|
||||
destroyOnInvisible: true
|
||||
frame: ModalFrame { }
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
property bool draggable: false
|
||||
|
||||
signal frameClicked();
|
||||
|
||||
anchors.centerIn: draggable ? undefined : parent
|
||||
}
|
|
@ -1,343 +0,0 @@
|
|||
//
|
||||
// Window.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "."
|
||||
import "../styles-uit"
|
||||
|
||||
// FIXME how do I set the initial position of a window without
|
||||
// overriding places where the a individual client of the window
|
||||
// might be setting the position with a Settings{} element?
|
||||
|
||||
// FIXME how to I enable dragging without allowing the window to lay outside
|
||||
// of the desktop? How do I ensure when the desktop resizes all the windows
|
||||
// are still at least partially visible?
|
||||
Fadable {
|
||||
id: window
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
// The Window size is the size of the content, while the frame
|
||||
// decorations can extend outside it.
|
||||
implicitHeight: content ? content.height : 0
|
||||
implicitWidth: content ? content.width : 0
|
||||
x: desktop.invalid_position; y: desktop.invalid_position;
|
||||
enabled: visible
|
||||
|
||||
signal windowDestroyed();
|
||||
|
||||
property int modality: Qt.NonModal
|
||||
readonly property bool topLevelWindow: true
|
||||
property string title
|
||||
// Should the window be closable control?
|
||||
property bool closable: true
|
||||
// Should the window try to remain on top of other windows?
|
||||
property bool alwaysOnTop: false
|
||||
// Should hitting the close button hide or destroy the window?
|
||||
property bool destroyOnCloseButton: true
|
||||
// Should hiding the window destroy it or just hide it?
|
||||
property bool destroyOnInvisible: false
|
||||
// FIXME support for pinned / unpinned pending full design
|
||||
// property bool pinnable: false
|
||||
// property bool pinned: false
|
||||
property bool resizable: false
|
||||
property bool gradientsSupported: desktop.gradientsSupported
|
||||
property int colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
property vector2d minSize: Qt.vector2d(100, 100)
|
||||
property vector2d maxSize: Qt.vector2d(1280, 800)
|
||||
|
||||
// The content to place inside the window, determined by the client
|
||||
default property var content
|
||||
|
||||
property var footer: Item { } // Optional static footer at the bottom of the dialog.
|
||||
|
||||
function setDefaultFocus() {} // Default function; can be overridden by dialogs.
|
||||
|
||||
property var rectifier: Timer {
|
||||
property bool executing: false;
|
||||
interval: 100
|
||||
repeat: false
|
||||
running: false
|
||||
|
||||
onTriggered: {
|
||||
executing = true;
|
||||
x = Math.floor(x);
|
||||
y = Math.floor(y);
|
||||
executing = false;
|
||||
}
|
||||
|
||||
function begin() {
|
||||
if (!executing) {
|
||||
restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
onXChanged: rectifier.begin();
|
||||
onYChanged: rectifier.begin();
|
||||
|
||||
// This mouse area serves to raise the window. To function, it must live
|
||||
// in the window and have a higher Z-order than the content, but follow
|
||||
// the position and size of frame decoration
|
||||
property var activator: MouseArea {
|
||||
width: frame.decoration.width
|
||||
height: frame.decoration.height
|
||||
x: frame.decoration.anchors.leftMargin
|
||||
y: frame.decoration.anchors.topMargin
|
||||
propagateComposedEvents: true
|
||||
acceptedButtons: Qt.AllButtons
|
||||
enabled: window.visible
|
||||
onPressed: {
|
||||
//console.log("Pressed on activator area");
|
||||
window.raise();
|
||||
mouse.accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
// This mouse area serves to swallow mouse events while the mouse is over the window
|
||||
// to prevent things like mouse wheel events from reaching the application and changing
|
||||
// the camera if the user is scrolling through a list and gets to the end.
|
||||
property var swallower: MouseArea {
|
||||
width: frame.decoration.width
|
||||
height: frame.decoration.height
|
||||
x: frame.decoration.anchors.leftMargin
|
||||
y: frame.decoration.anchors.topMargin
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.AllButtons
|
||||
enabled: window.visible
|
||||
onClicked: {}
|
||||
onDoubleClicked: {}
|
||||
onPressAndHold: {}
|
||||
onReleased: {}
|
||||
onWheel: {}
|
||||
}
|
||||
|
||||
// Default to a standard frame. Can be overriden to provide custom
|
||||
// frame styles, like a full desktop frame to simulate a modal window
|
||||
property var frame: DefaultFrame { }
|
||||
|
||||
// Scrollable window content.
|
||||
property var pane: Item {
|
||||
property bool isScrolling: scrollView.height < scrollView.contentItem.height
|
||||
property int contentWidth: scrollView.width - (isScrolling ? 10 : 0)
|
||||
property int scrollHeight: scrollView.height
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: isScrolling ? 11 : 0
|
||||
|
||||
Rectangle {
|
||||
id: contentBackground
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.isScrolling ? 11 : 0
|
||||
color: hifi.colors.baseGray
|
||||
visible: modality != Qt.ApplicationModal
|
||||
}
|
||||
|
||||
LinearGradient {
|
||||
visible: gradientsSupported && modality != Qt.ApplicationModal
|
||||
anchors.top: contentBackground.bottom
|
||||
anchors.left: contentBackground.left
|
||||
width: contentBackground.width - 1
|
||||
height: 4
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(0, 4)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.darkGray }
|
||||
GradientStop { position: 1.0; color: hifi.colors.darkGray0 }
|
||||
}
|
||||
cached: true
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
contentItem: content
|
||||
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.isScrolling ? 1 : 0
|
||||
anchors.bottomMargin: footer.height > 0 ? footerPane.height : 0
|
||||
|
||||
style: ScrollViewStyle {
|
||||
|
||||
padding.right: -7 // Move to right away from content.
|
||||
|
||||
handle: Item {
|
||||
implicitWidth: 8
|
||||
Rectangle {
|
||||
radius: 4
|
||||
color: hifi.colors.white30
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: 2 // Finesse size and position.
|
||||
topMargin: 1
|
||||
bottomMargin: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scrollBarBackground: Item {
|
||||
implicitWidth: 10
|
||||
Rectangle {
|
||||
color: hifi.colors.darkGray30
|
||||
radius: 4
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: -1 // Finesse size
|
||||
bottomMargin: -2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
incrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
|
||||
decrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// Optional non-scrolling footer.
|
||||
id: footerPane
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
width: parent.contentWidth
|
||||
height: footer.height + 2 * hifi.dimensions.contentSpacing.y + 3
|
||||
color: hifi.colors.baseGray
|
||||
visible: footer.height > 0
|
||||
|
||||
Item {
|
||||
// Horizontal rule.
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 1 // Stop displaying content just above horizontal rule/=.
|
||||
color: hifi.colors.baseGrayShadow
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 2
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 3 // Horizontal rule.
|
||||
children: [ footer ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
children: [ swallower, frame, pane, activator ]
|
||||
|
||||
Component.onCompleted: {
|
||||
window.parentChanged.connect(raise);
|
||||
raise();
|
||||
setDefaultFocus();
|
||||
centerOrReposition();
|
||||
}
|
||||
Component.onDestruction: {
|
||||
window.parentChanged.disconnect(raise); // Prevent warning on shutdown
|
||||
windowDestroyed();
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible && destroyOnInvisible) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
if (visible) {
|
||||
raise();
|
||||
}
|
||||
enabled = visible
|
||||
|
||||
if (visible && parent) {
|
||||
centerOrReposition();
|
||||
}
|
||||
}
|
||||
|
||||
function centerOrReposition() {
|
||||
if (x == desktop.invalid_position && y == desktop.invalid_position) {
|
||||
desktop.centerOnVisible(window);
|
||||
} else {
|
||||
desktop.repositionOnVisible(window);
|
||||
}
|
||||
}
|
||||
|
||||
function raise() {
|
||||
if (visible && parent) {
|
||||
desktop.raise(window)
|
||||
}
|
||||
}
|
||||
|
||||
function pin() {
|
||||
// pinned = ! pinned
|
||||
}
|
||||
|
||||
// our close function performs the same way as the OffscreenUI class:
|
||||
// don't do anything but manipulate the targetVisible flag and let the other
|
||||
// mechanisms decide if the window should be destroyed after the close
|
||||
// animation completes
|
||||
// FIXME using this close function messes up the visibility signals received by the
|
||||
// type and it's derived types
|
||||
// function close() {
|
||||
// console.log("Closing " + window)
|
||||
// if (destroyOnCloseButton) {
|
||||
// destroyOnInvisible = true
|
||||
// }
|
||||
// visible = false;
|
||||
// }
|
||||
|
||||
function framedRect() {
|
||||
if (!frame || !frame.decoration) {
|
||||
return Qt.rect(0, 0, window.width, window.height)
|
||||
}
|
||||
return Qt.rect(frame.decoration.anchors.leftMargin, frame.decoration.anchors.topMargin,
|
||||
window.width - frame.decoration.anchors.leftMargin - frame.decoration.anchors.rightMargin,
|
||||
window.height - frame.decoration.anchors.topMargin - frame.decoration.anchors.bottomMargin)
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_Control:
|
||||
case Qt.Key_Shift:
|
||||
case Qt.Key_Meta:
|
||||
case Qt.Key_Alt:
|
||||
break;
|
||||
|
||||
case Qt.Key_W:
|
||||
if (window.closable && (event.modifiers === Qt.ControlModifier)) {
|
||||
visible = false
|
||||
event.accepted = true
|
||||
}
|
||||
// fall through
|
||||
|
||||
default:
|
||||
// Consume unmodified keyboard entries while the window is focused, to prevent them
|
||||
// from propagating to the application
|
||||
if (event.modifiers === Qt.NoModifier) {
|
||||
event.accepted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,48 @@
|
|||
//
|
||||
// DefaultFrame.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "."
|
||||
import "../controls"
|
||||
import "../styles-uit"
|
||||
|
||||
Frame {
|
||||
id: frame
|
||||
|
||||
property bool wideTopMargin: (window && (window.closable || window.title));
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Rectangle {
|
||||
anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); }
|
||||
anchors.fill: parent;
|
||||
color: "#7f7f7f7f";
|
||||
radius: 3;
|
||||
// Dialog frame
|
||||
id: frameContent
|
||||
|
||||
// Allow dragging of the window
|
||||
readonly property int iconSize: hifi.dimensions.frameIconSize
|
||||
readonly property int frameMargin: 9
|
||||
readonly property int frameMarginLeft: frameMargin
|
||||
readonly property int frameMarginRight: frameMargin
|
||||
readonly property int frameMarginTop: 2 * frameMargin + iconSize
|
||||
readonly property int frameMarginBottom: iconSize + 11
|
||||
|
||||
anchors {
|
||||
topMargin: -frameMarginTop
|
||||
leftMargin: -frameMarginLeft
|
||||
rightMargin: -frameMarginRight
|
||||
bottomMargin: -frameMarginBottom
|
||||
}
|
||||
anchors.fill: parent
|
||||
color: hifi.colors.baseGrayHighlight40
|
||||
border {
|
||||
width: hifi.dimensions.borderWidth
|
||||
color: hifi.colors.faintGray50
|
||||
}
|
||||
radius: hifi.dimensions.borderRadius
|
||||
|
||||
// Enable dragging of the window
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: window
|
||||
|
@ -22,48 +50,70 @@ Frame {
|
|||
|
||||
Row {
|
||||
id: controlsRow
|
||||
anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; }
|
||||
spacing: iconSize / 4
|
||||
FontAwesome {
|
||||
visible: false
|
||||
text: "\uf08d"
|
||||
style: Text.Outline; styleColor: "white"
|
||||
size: frame.iconSize
|
||||
rotation: !frame.parent ? 90 : frame.parent.pinned ? 0 : 90
|
||||
color: frame.pinned ? "red" : "black"
|
||||
anchors {
|
||||
right: parent.right;
|
||||
top: parent.top;
|
||||
topMargin: frameContent.frameMargin + 1 // Move down a little to visually align with the title
|
||||
rightMargin: frameContent.frameMarginRight;
|
||||
}
|
||||
spacing: frameContent.iconSize / 4
|
||||
|
||||
HiFiGlyphs {
|
||||
// "Pin" button
|
||||
visible: window.pinnable
|
||||
text: window.pinned ? hifi.glyphs.pinInverted : hifi.glyphs.pin
|
||||
color: pinClickArea.pressed ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: frameContent.iconSize
|
||||
MouseArea {
|
||||
id: pinClickArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
propagateComposedEvents: true
|
||||
onClicked: { frame.pin(); mouse.accepted = false; }
|
||||
onClicked: window.pinned = !window.pinned;
|
||||
}
|
||||
}
|
||||
FontAwesome {
|
||||
|
||||
HiFiGlyphs {
|
||||
// "Close" button
|
||||
visible: window ? window.closable : false
|
||||
text: closeClickArea.containsMouse ? "\uf057" : "\uf05c"
|
||||
style: Text.Outline;
|
||||
styleColor: "white"
|
||||
color: closeClickArea.containsMouse ? "red" : "black"
|
||||
size: frame.iconSize
|
||||
text: closeClickArea.containsPress ? hifi.glyphs.closeInverted : hifi.glyphs.close
|
||||
color: closeClickArea.containsMouse ? hifi.colors.redHighlight : hifi.colors.white
|
||||
size: frameContent.iconSize
|
||||
MouseArea {
|
||||
id: closeClickArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: window.visible = false;
|
||||
onClicked: window.shown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
RalewayRegular {
|
||||
// Title
|
||||
id: titleText
|
||||
anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; }
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: frameContent.frameMarginLeft + hifi.dimensions.contentMargin.x
|
||||
right: controlsRow.left
|
||||
rightMargin: frameContent.iconSize
|
||||
top: parent.top
|
||||
topMargin: frameContent.frameMargin
|
||||
}
|
||||
text: window ? window.title : ""
|
||||
elide: Text.ElideRight
|
||||
font.bold: true
|
||||
color: (window && window.focus) ? "white" : "gray"
|
||||
style: Text.Outline;
|
||||
styleColor: "black"
|
||||
color: hifi.colors.white
|
||||
size: hifi.fontSizes.overlayTitle
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
source: titleText
|
||||
anchors.fill: titleText
|
||||
horizontalOffset: 2
|
||||
verticalOffset: 2
|
||||
samples: 2
|
||||
color: hifi.colors.baseGrayShadow60
|
||||
visible: (window && window.focus)
|
||||
cached: true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
//
|
||||
// Fadable.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 15 Jan 2016
|
||||
// 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
|
||||
import QtQuick.Controls 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
import "."
|
||||
import "../styles"
|
||||
|
||||
import "../styles-uit"
|
||||
|
||||
// Enable window visibility transitions
|
||||
FocusScope {
|
||||
|
@ -13,6 +23,7 @@ FocusScope {
|
|||
fadeTargetProperty = visible ? 1.0 : 0.0
|
||||
}
|
||||
|
||||
property var completionCallback;
|
||||
// The target property to animate, usually scale or opacity
|
||||
property alias fadeTargetProperty: root.opacity
|
||||
// always start the property at 0 to enable fade in on creation
|
||||
|
@ -33,6 +44,13 @@ FocusScope {
|
|||
fadeTargetProperty = target ? 1.0 : 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Now handle completions
|
||||
if (completionCallback) {
|
||||
completionCallback();
|
||||
completionCallback = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The actual animator
|
||||
|
@ -43,8 +61,17 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
// Once we're transparent, disable the dialog's visibility
|
||||
onFadeTargetPropertyChanged: {
|
||||
visible = (fadeTargetProperty != 0.0);
|
||||
}
|
||||
|
||||
function fadeIn(callback) {
|
||||
completionCallback = callback;
|
||||
fadeTargetProperty = 1.0;
|
||||
}
|
||||
|
||||
function fadeOut(callback) {
|
||||
completionCallback = callback;
|
||||
fadeTargetProperty = 0.0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,42 @@
|
|||
import QtQuick 2.5
|
||||
//
|
||||
// Frame.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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 "../controls"
|
||||
import QtQuick 2.5
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../styles-uit"
|
||||
import "../js/Utils.js" as Utils
|
||||
|
||||
Item {
|
||||
id: frame
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
default property var decoration
|
||||
|
||||
property bool gradientsSupported: desktop.gradientsSupported
|
||||
|
||||
readonly property int frameMarginLeft: frameContent.frameMarginLeft
|
||||
readonly property int frameMarginRight: frameContent.frameMarginRight
|
||||
readonly property int frameMarginTop: frameContent.frameMarginTop
|
||||
readonly property int frameMarginBottom: frameContent.frameMarginBottom
|
||||
|
||||
// Frames always fill their parents, but their decorations may extend
|
||||
// beyond the window via negative margin sizes
|
||||
anchors.fill: parent
|
||||
|
||||
// Convenience accessor for the window
|
||||
property alias window: frame.parent
|
||||
readonly property int iconSize: 24
|
||||
default property var decoration;
|
||||
|
||||
children: [
|
||||
focusShadow,
|
||||
decoration,
|
||||
sizeOutline,
|
||||
debugZ,
|
||||
sizeDrag,
|
||||
sizeDrag
|
||||
]
|
||||
|
||||
Text {
|
||||
|
@ -35,57 +53,81 @@ Item {
|
|||
window.height = newSize.y
|
||||
}
|
||||
|
||||
RadialGradient {
|
||||
id: focusShadow
|
||||
width: 1.66 * window.width
|
||||
height: 1.66 * window.height
|
||||
x: (window.width - width) / 2
|
||||
y: window.height / 2 - 0.375 * height
|
||||
visible: gradientsSupported && window && window.focus && pane.visible
|
||||
gradient: Gradient {
|
||||
// GradientStop position 0.5 is at full circumference of circle that fits inside the square.
|
||||
GradientStop { position: 0.0; color: "#ff000000" } // black, 100% opacity
|
||||
GradientStop { position: 0.333; color: "#1f000000" } // black, 12% opacity
|
||||
GradientStop { position: 0.5; color: "#00000000" } // black, 0% opacity
|
||||
GradientStop { position: 1.0; color: "#00000000" }
|
||||
}
|
||||
cached: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sizeOutline
|
||||
width: window ? window.width : 0
|
||||
height: window ? window.height : 0
|
||||
color: "#00000000"
|
||||
border.width: 4
|
||||
radius: 10
|
||||
visible: window ? !window.content.visible : false
|
||||
x: -frameMarginLeft
|
||||
y: -frameMarginTop
|
||||
width: window ? window.width + frameMarginLeft + frameMarginRight + 2 : 0
|
||||
height: window ? window.height + frameMarginTop + frameMarginBottom + 2 : 0
|
||||
color: hifi.colors.baseGrayHighlight15
|
||||
border.width: 3
|
||||
border.color: hifi.colors.white50
|
||||
radius: hifi.dimensions.borderRadius
|
||||
visible: window ? !pane.visible : false
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
// Resize handle
|
||||
id: sizeDrag
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
width: hifi.dimensions.frameIconSize
|
||||
height: hifi.dimensions.frameIconSize
|
||||
enabled: window ? window.resizable : false
|
||||
x: window ? window.width : 0
|
||||
y: window ? window.height : 0
|
||||
hoverEnabled: true
|
||||
x: window ? window.width + frameMarginRight - hifi.dimensions.frameIconSize : 0
|
||||
y: window ? window.height + 4 : 0
|
||||
property vector2d pressOrigin
|
||||
property vector2d sizeOrigin
|
||||
property bool hid: false
|
||||
onPressed: {
|
||||
console.log("Pressed on size")
|
||||
//console.log("Pressed on size")
|
||||
pressOrigin = Qt.vector2d(mouseX, mouseY)
|
||||
sizeOrigin = Qt.vector2d(window.content.width, window.content.height)
|
||||
hid = false;
|
||||
}
|
||||
onReleased: {
|
||||
if (hid) {
|
||||
window.content.visible = true
|
||||
pane.visible = true
|
||||
frameContent.visible = true
|
||||
hid = false;
|
||||
}
|
||||
}
|
||||
onPositionChanged: {
|
||||
if (pressed) {
|
||||
if (window.content.visible) {
|
||||
window.content.visible = false;
|
||||
if (pane.visible) {
|
||||
pane.visible = false;
|
||||
frameContent.visible = false
|
||||
hid = true;
|
||||
}
|
||||
var delta = Qt.vector2d(mouseX, mouseY).minus(pressOrigin);
|
||||
frame.deltaSize(delta.x, delta.y)
|
||||
}
|
||||
}
|
||||
FontAwesome {
|
||||
HiFiGlyphs {
|
||||
visible: sizeDrag.enabled
|
||||
rotation: -45
|
||||
anchors { centerIn: parent }
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: "\uf07d"
|
||||
size: iconSize / 3 * 2
|
||||
style: Text.Outline; styleColor: "white"
|
||||
x: -11 // Move a little to visually align
|
||||
y: window.modality == Qt.ApplicationModal ? -6 : -4
|
||||
text: hifi.glyphs.resizeHandle
|
||||
size: hifi.dimensions.frameIconSize + 10
|
||||
color: sizeDrag.containsMouse || sizeDrag.pressed
|
||||
? hifi.colors.white
|
||||
: (window.colorScheme == hifi.colorSchemes.dark ? hifi.colors.white50 : hifi.colors.lightGrayText80)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import QtQuick 2.5
|
|||
|
||||
import "."
|
||||
|
||||
Frame {
|
||||
Item {
|
||||
id: frame
|
||||
|
||||
Item { anchors.fill: parent }
|
||||
|
|
|
@ -1,36 +1,98 @@
|
|||
//
|
||||
// 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"
|
||||
import "../controls-uit"
|
||||
import "../styles-uit"
|
||||
|
||||
Frame {
|
||||
id: frame
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
Rectangle {
|
||||
id: frameContent
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
anchors.margins: -4096
|
||||
visible: window.visible
|
||||
color: "#7f7f7f7f";
|
||||
radius: 3;
|
||||
readonly property bool hasTitle: window.title != ""
|
||||
|
||||
readonly property int frameMarginLeft: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginRight: hifi.dimensions.modalDialogMargin.x
|
||||
readonly property int frameMarginTop: hifi.dimensions.modalDialogMargin.y + (frameContent.hasTitle ? hifi.dimensions.modalDialogTitleHeight + 10 : 0)
|
||||
readonly property int frameMarginBottom: hifi.dimensions.modalDialogMargin.y
|
||||
|
||||
signal frameClicked();
|
||||
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: -frameMarginTop
|
||||
leftMargin: -frameMarginLeft
|
||||
rightMargin: -frameMarginRight
|
||||
bottomMargin: -frameMarginBottom
|
||||
}
|
||||
|
||||
Text {
|
||||
y: -implicitHeight - iconSize / 2
|
||||
text: window.title
|
||||
elide: Text.ElideRight
|
||||
font.bold: true
|
||||
color: window.focus ? "white" : "gray"
|
||||
style: Text.Outline;
|
||||
styleColor: "black"
|
||||
border {
|
||||
width: hifi.dimensions.borderWidth
|
||||
color: hifi.colors.lightGrayText80
|
||||
}
|
||||
radius: hifi.dimensions.borderRadius
|
||||
color: hifi.colors.faintGray
|
||||
|
||||
// Enable dragging of the window
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
drag.target: window
|
||||
enabled: window.draggable
|
||||
onClicked: window.frameClicked();
|
||||
}
|
||||
|
||||
Item {
|
||||
visible: frameContent.hasTitle
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
topMargin: -parent.anchors.topMargin
|
||||
leftMargin: -parent.anchors.leftMargin
|
||||
rightMargin: -parent.anchors.rightMargin
|
||||
}
|
||||
|
||||
Item {
|
||||
width: title.width + (icon.text !== "" ? icon.width + hifi.dimensions.contentSpacing.x : 0)
|
||||
x: (parent.width - width) / 2
|
||||
|
||||
onWidthChanged: window.titleWidth = width
|
||||
|
||||
HiFiGlyphs {
|
||||
id: icon
|
||||
text: window.iconText ? window.iconText : ""
|
||||
size: window.iconSize ? window.iconSize : 30
|
||||
color: hifi.colors.lightGray
|
||||
visible: text != ""
|
||||
anchors.verticalCenter: title.verticalCenter
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
//
|
||||
// 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: root
|
||||
anchors.centerIn: parent
|
||||
id: window
|
||||
modality: Qt.ApplicationModal
|
||||
destroyOnCloseButton: true
|
||||
destroyOnInvisible: true
|
||||
frame: ModalFrame{}
|
||||
frame: ModalFrame { }
|
||||
|
||||
property int colorScheme: hifi.colorSchemes.light
|
||||
property bool draggable: false
|
||||
|
||||
signal frameClicked();
|
||||
|
||||
anchors.centerIn: draggable ? undefined : parent
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
//
|
||||
// Window.qml
|
||||
//
|
||||
// Created by Bradley Austin Davis on 12 Jan 2016
|
||||
// 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
|
||||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "."
|
||||
import "../styles"
|
||||
import "../styles-uit"
|
||||
|
||||
// FIXME how do I set the initial position of a window without
|
||||
// overriding places where the a individual client of the window
|
||||
|
@ -15,16 +26,36 @@ import "../styles"
|
|||
Fadable {
|
||||
id: window
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
//
|
||||
// Signals
|
||||
//
|
||||
signal windowDestroyed();
|
||||
|
||||
//
|
||||
// Native properties
|
||||
//
|
||||
|
||||
// The Window size is the size of the content, while the frame
|
||||
// decorations can extend outside it.
|
||||
implicitHeight: content ? content.height : 0
|
||||
implicitWidth: content ? content.width : 0
|
||||
x: desktop.invalid_position; y: desktop.invalid_position;
|
||||
enabled: visible
|
||||
children: [ swallower, frame, pane, activator ]
|
||||
|
||||
signal windowDestroyed();
|
||||
//
|
||||
// Custom properties
|
||||
//
|
||||
|
||||
property int modality: Qt.NonModal
|
||||
// Corresponds to the window shown / hidden state AS DISTINCT from window visibility.
|
||||
// Window visibility should NOT be used as a proxy for any other behavior.
|
||||
property bool shown: true
|
||||
// FIXME workaround to deal with the face that some visual items are defined here,
|
||||
// when they should be moved to a frame derived type
|
||||
property bool hideBackground: false
|
||||
visible: shown
|
||||
enabled: visible
|
||||
readonly property bool topLevelWindow: true
|
||||
property string title
|
||||
// Should the window be closable control?
|
||||
|
@ -34,17 +65,23 @@ Fadable {
|
|||
// Should hitting the close button hide or destroy the window?
|
||||
property bool destroyOnCloseButton: true
|
||||
// Should hiding the window destroy it or just hide it?
|
||||
property bool destroyOnInvisible: false
|
||||
// FIXME support for pinned / unpinned pending full design
|
||||
// property bool pinnable: false
|
||||
// property bool pinned: false
|
||||
property bool destroyOnHidden: false
|
||||
property bool pinnable: true
|
||||
property bool pinned: false
|
||||
property bool resizable: false
|
||||
property bool gradientsSupported: desktop.gradientsSupported
|
||||
property int colorScheme: hifi.colorSchemes.dark
|
||||
|
||||
property vector2d minSize: Qt.vector2d(100, 100)
|
||||
property vector2d maxSize: Qt.vector2d(1280, 720)
|
||||
property vector2d maxSize: Qt.vector2d(1280, 800)
|
||||
|
||||
// The content to place inside the window, determined by the client
|
||||
default property var content
|
||||
|
||||
property var footer: Item { } // Optional static footer at the bottom of the dialog.
|
||||
|
||||
function setDefaultFocus() {} // Default function; can be overridden by dialogs.
|
||||
|
||||
property var rectifier: Timer {
|
||||
property bool executing: false;
|
||||
interval: 100
|
||||
|
@ -65,20 +102,15 @@ Fadable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
onXChanged: rectifier.begin();
|
||||
onYChanged: rectifier.begin();
|
||||
|
||||
// This mouse area serves to raise the window. To function, it must live
|
||||
// in the window and have a higher Z-order than the content, but follow
|
||||
// the position and size of frame decoration
|
||||
property var activator: MouseArea {
|
||||
width: frame.decoration.width
|
||||
height: frame.decoration.height
|
||||
x: frame.decoration.anchors.margins
|
||||
x: frame.decoration.anchors.leftMargin
|
||||
y: frame.decoration.anchors.topMargin
|
||||
propagateComposedEvents: true
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.AllButtons
|
||||
enabled: window.visible
|
||||
onPressed: {
|
||||
|
@ -94,7 +126,7 @@ Fadable {
|
|||
property var swallower: MouseArea {
|
||||
width: frame.decoration.width
|
||||
height: frame.decoration.height
|
||||
x: frame.decoration.anchors.margins
|
||||
x: frame.decoration.anchors.leftMargin
|
||||
y: frame.decoration.anchors.topMargin
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.AllButtons
|
||||
|
@ -106,71 +138,241 @@ Fadable {
|
|||
onWheel: {}
|
||||
}
|
||||
|
||||
|
||||
// Default to a standard frame. Can be overriden to provide custom
|
||||
// frame styles, like a full desktop frame to simulate a modal window
|
||||
property var frame: DefaultFrame { }
|
||||
|
||||
// Scrollable window content.
|
||||
// FIXME this should not define any visual content in this type. The base window
|
||||
// type should only consist of logic sized areas, with nothing drawn (although the
|
||||
// default value for the frame property does include visual decorations)
|
||||
property var pane: Item {
|
||||
property bool isScrolling: scrollView.height < scrollView.contentItem.height
|
||||
property int contentWidth: scrollView.width - (isScrolling ? 10 : 0)
|
||||
property int scrollHeight: scrollView.height
|
||||
|
||||
children: [ swallower, frame, content, activator ]
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: isScrolling ? 11 : 0
|
||||
|
||||
Rectangle {
|
||||
id: contentBackground
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.isScrolling ? 11 : 0
|
||||
color: hifi.colors.baseGray
|
||||
visible: !window.hideBackground && modality != Qt.ApplicationModal
|
||||
}
|
||||
|
||||
|
||||
LinearGradient {
|
||||
visible: !window.hideBackground && gradientsSupported && modality != Qt.ApplicationModal
|
||||
anchors.top: contentBackground.bottom
|
||||
anchors.left: contentBackground.left
|
||||
width: contentBackground.width - 1
|
||||
height: 4
|
||||
start: Qt.point(0, 0)
|
||||
end: Qt.point(0, 4)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: hifi.colors.darkGray }
|
||||
GradientStop { position: 1.0; color: hifi.colors.darkGray0 }
|
||||
}
|
||||
cached: true
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: scrollView
|
||||
contentItem: content
|
||||
horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff
|
||||
verticalScrollBarPolicy: Qt.ScrollBarAsNeeded
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.isScrolling ? 1 : 0
|
||||
anchors.bottomMargin: footer.height > 0 ? footerPane.height : 0
|
||||
|
||||
style: ScrollViewStyle {
|
||||
|
||||
padding.right: -7 // Move to right away from content.
|
||||
|
||||
handle: Item {
|
||||
implicitWidth: 8
|
||||
Rectangle {
|
||||
radius: 4
|
||||
color: hifi.colors.white30
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: 2 // Finesse size and position.
|
||||
topMargin: 1
|
||||
bottomMargin: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scrollBarBackground: Item {
|
||||
implicitWidth: 10
|
||||
Rectangle {
|
||||
color: hifi.colors.darkGray30
|
||||
radius: 4
|
||||
anchors {
|
||||
fill: parent
|
||||
topMargin: -1 // Finesse size
|
||||
bottomMargin: -2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
incrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
|
||||
decrementControl: Item {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
// Optional non-scrolling footer.
|
||||
id: footerPane
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
}
|
||||
width: parent.contentWidth
|
||||
height: footer.height + 2 * hifi.dimensions.contentSpacing.y + 3
|
||||
color: hifi.colors.baseGray
|
||||
visible: footer.height > 0
|
||||
|
||||
Item {
|
||||
// Horizontal rule.
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 1 // Stop displaying content just above horizontal rule/=.
|
||||
color: hifi.colors.baseGrayShadow
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
y: 2
|
||||
color: hifi.colors.baseGrayHighlight
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 3 // Horizontal rule.
|
||||
children: [ footer ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handlers
|
||||
//
|
||||
Component.onCompleted: {
|
||||
window.parentChanged.connect(raise);
|
||||
raise();
|
||||
centerOrReposition();
|
||||
setDefaultFocus();
|
||||
d.centerOrReposition();
|
||||
d.updateVisibility(shown);
|
||||
}
|
||||
Component.onDestruction: {
|
||||
window.parentChanged.disconnect(raise); // Prevent warning on shutdown
|
||||
windowDestroyed();
|
||||
}
|
||||
|
||||
function centerOrReposition() {
|
||||
if (x == desktop.invalid_position && y == desktop.invalid_position) {
|
||||
desktop.centerOnVisible(window);
|
||||
} else {
|
||||
desktop.repositionOnVisible(window);
|
||||
}
|
||||
}
|
||||
onXChanged: rectifier.begin();
|
||||
onYChanged: rectifier.begin();
|
||||
|
||||
onShownChanged: d.updateVisibility(shown)
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible && destroyOnInvisible) {
|
||||
destroy();
|
||||
return;
|
||||
}
|
||||
if (visible) {
|
||||
raise();
|
||||
}
|
||||
enabled = visible
|
||||
|
||||
if (visible && parent) {
|
||||
centerOrReposition();
|
||||
d.centerOrReposition();
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property alias pinned: window.pinned
|
||||
readonly property alias shown: window.shown
|
||||
readonly property alias modality: window.modality;
|
||||
|
||||
function getTargetVisibility() {
|
||||
if (!window.shown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modality !== Qt.NonModal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pinned) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (desktop && !desktop.pinned) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The force flag causes all windows to fade back in, because a window was shown
|
||||
readonly property alias visible: window.visible
|
||||
function updateVisibility(force) {
|
||||
if (force && !pinned && desktop.pinned) {
|
||||
// Change the pinned state (which in turn will call us again)
|
||||
desktop.pinned = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var targetVisibility = getTargetVisibility();
|
||||
if (targetVisibility === visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetVisibility) {
|
||||
fadeIn(function() {
|
||||
if (force) {
|
||||
window.raise();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fadeOut(function() {
|
||||
if (!window.shown && window.destroyOnHidden) {
|
||||
window.destroy();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function centerOrReposition() {
|
||||
if (x == desktop.invalid_position && y == desktop.invalid_position) {
|
||||
desktop.centerOnVisible(window);
|
||||
} else {
|
||||
desktop.repositionOnVisible(window);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// When the desktop pinned state changes, automatically handle the current windows
|
||||
Connections { target: desktop; onPinnedChanged: d.updateVisibility() }
|
||||
|
||||
|
||||
function raise() {
|
||||
if (visible && parent) {
|
||||
desktop.raise(window)
|
||||
}
|
||||
}
|
||||
|
||||
function pin() {
|
||||
// pinned = ! pinned
|
||||
function setPinned() {
|
||||
pinned = !pinned
|
||||
}
|
||||
|
||||
// our close function performs the same way as the OffscreenUI class:
|
||||
// don't do anything but manipulate the targetVisible flag and let the other
|
||||
// mechanisms decide if the window should be destroyed after the close
|
||||
// animation completes
|
||||
// FIXME using this close function messes up the visibility signals received by the
|
||||
// type and it's derived types
|
||||
// function close() {
|
||||
// console.log("Closing " + window)
|
||||
// if (destroyOnCloseButton) {
|
||||
// destroyOnInvisible = true
|
||||
// }
|
||||
// visible = false;
|
||||
// }
|
||||
|
||||
function framedRect() {
|
||||
if (!frame || !frame.decoration) {
|
||||
return Qt.rect(0, 0, window.width, window.height)
|
||||
|
@ -180,7 +382,6 @@ Fadable {
|
|||
window.height - frame.decoration.anchors.topMargin - frame.decoration.anchors.bottomMargin)
|
||||
}
|
||||
|
||||
|
||||
Keys.onPressed: {
|
||||
switch(event.key) {
|
||||
case Qt.Key_Control:
|
||||
|
@ -189,10 +390,9 @@ Fadable {
|
|||
case Qt.Key_Alt:
|
||||
break;
|
||||
|
||||
|
||||
case Qt.Key_W:
|
||||
if (window.closable && (event.modifiers === Qt.ControlModifier)) {
|
||||
visible = false
|
||||
shown = false
|
||||
event.accepted = true
|
||||
}
|
||||
// fall through
|
||||
|
|
|
@ -2057,7 +2057,8 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
case Qt::Key_X:
|
||||
if (isShifted && isMeta) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->getRootContext()->engine()->clearComponentCache();
|
||||
offscreenUi->togglePinned();
|
||||
//offscreenUi->getRootContext()->engine()->clearComponentCache();
|
||||
//OffscreenUi::information("Debugging", "Component cache cleared");
|
||||
// placeholder for dialogs being converted to QML.
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ void OverlayConductor::updateMode() {
|
|||
myAvatar->reset(true, false, false);
|
||||
}
|
||||
if (_wantsOverlays) {
|
||||
setEnabled(!nowDriving, false);
|
||||
setEnabled(!nowDriving);
|
||||
}
|
||||
_driving = nowDriving;
|
||||
} // Else haven't accumulated enough time in new mode, but keep timing.
|
||||
|
@ -114,18 +114,14 @@ void OverlayConductor::updateMode() {
|
|||
case SITTING: {
|
||||
// enter the SITTING state
|
||||
// place the overlay at origin
|
||||
Transform identity;
|
||||
qApp->getApplicationCompositor().setModelTransform(identity);
|
||||
qApp->getApplicationCompositor().setModelTransform(Transform());
|
||||
break;
|
||||
}
|
||||
case STANDING: { // STANDING mode is not currently used.
|
||||
// enter the STANDING state
|
||||
// place the overlay at the current hmd position in world space
|
||||
auto camMat = cancelOutRollAndPitch(myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose());
|
||||
Transform t;
|
||||
t.setTranslation(extractTranslation(camMat));
|
||||
t.setRotation(glm::quat_cast(camMat));
|
||||
qApp->getApplicationCompositor().setModelTransform(t);
|
||||
qApp->getApplicationCompositor().setModelTransform(Transform(camMat));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -139,54 +135,21 @@ void OverlayConductor::updateMode() {
|
|||
|
||||
}
|
||||
|
||||
void OverlayConductor::setEnabled(bool enabled, bool toggleQmlEvents) {
|
||||
|
||||
void OverlayConductor::setEnabled(bool enabled) {
|
||||
if (enabled == _enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (toggleQmlEvents) { // Could recurse on us with the wrong toggleQmlEvents flag, and not need in the !toggleQmlEvent case anyway.
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::Overlays, enabled);
|
||||
}
|
||||
|
||||
_enabled = enabled; // set the new value
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->setPinned(!_enabled);
|
||||
// if the new state is visible/enabled...
|
||||
if (_enabled) {
|
||||
// alpha fadeIn the overlay mesh.
|
||||
qApp->getApplicationCompositor().fadeIn();
|
||||
|
||||
// enable mouse clicks from script
|
||||
qApp->getOverlays().enable();
|
||||
|
||||
// enable QML events
|
||||
if (toggleQmlEvents) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->getRootItem()->setEnabled(true);
|
||||
}
|
||||
|
||||
if (_mode == STANDING) {
|
||||
// place the overlay at the current hmd position in world space
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
auto camMat = cancelOutRollAndPitch(myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose());
|
||||
Transform t;
|
||||
t.setTranslation(extractTranslation(camMat));
|
||||
t.setRotation(glm::quat_cast(camMat));
|
||||
qApp->getApplicationCompositor().setModelTransform(t);
|
||||
}
|
||||
} else { // other wise, if the new state is hidden/not enabled
|
||||
// alpha fadeOut the overlay mesh.
|
||||
qApp->getApplicationCompositor().fadeOut();
|
||||
|
||||
// disable mouse clicks from script
|
||||
qApp->getOverlays().disable();
|
||||
|
||||
// disable QML events
|
||||
if (toggleQmlEvents) { // I'd really rather always do this, but it looses drive state. bugzid:501
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->getRootItem()->setEnabled(false);
|
||||
}
|
||||
}
|
||||
if (_enabled && _mode == STANDING) {
|
||||
// place the overlay at the current hmd position in world space
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
auto camMat = cancelOutRollAndPitch(myAvatar->getSensorToWorldMatrix() * qApp->getHMDSensorPose());
|
||||
qApp->getApplicationCompositor().setModelTransform(Transform(camMat));
|
||||
}
|
||||
}
|
||||
|
||||
bool OverlayConductor::getEnabled() const {
|
||||
|
|
|
@ -17,7 +17,7 @@ public:
|
|||
~OverlayConductor();
|
||||
|
||||
void update(float dt);
|
||||
void setEnabled(bool enable, bool toggleQmlEvents = true);
|
||||
void setEnabled(bool enable);
|
||||
bool getEnabled() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -346,7 +346,7 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c
|
|||
auto relativePosition = vec3(relativePosition4) / relativePosition4.w;
|
||||
auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction;
|
||||
|
||||
float uiRadius = _oculusUIRadius; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale
|
||||
float uiRadius = _hmdUIRadius; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale
|
||||
|
||||
float instersectionDistance;
|
||||
if (raySphereIntersect(relativeDirection, relativePosition, uiRadius, &instersectionDistance)){
|
||||
|
@ -407,60 +407,6 @@ void CompositorHelper::updateTooltips() {
|
|||
//}
|
||||
}
|
||||
|
||||
static const float FADE_DURATION = 500.0f;
|
||||
static const float FADE_IN_ALPHA = 1.0f;
|
||||
static const float FADE_OUT_ALPHA = 0.0f;
|
||||
|
||||
void CompositorHelper::startFadeFailsafe(float endValue) {
|
||||
_fadeStarted = usecTimestampNow();
|
||||
_fadeFailsafeEndValue = endValue;
|
||||
|
||||
const int SLIGHT_DELAY = 10;
|
||||
QTimer::singleShot(FADE_DURATION + SLIGHT_DELAY, [this]{
|
||||
checkFadeFailsafe();
|
||||
});
|
||||
}
|
||||
|
||||
void CompositorHelper::checkFadeFailsafe() {
|
||||
auto elapsedInFade = usecTimestampNow() - _fadeStarted;
|
||||
if (elapsedInFade > FADE_DURATION) {
|
||||
setAlpha(_fadeFailsafeEndValue);
|
||||
}
|
||||
}
|
||||
|
||||
void CompositorHelper::fadeIn() {
|
||||
_fadeInAlpha = true;
|
||||
|
||||
_alphaPropertyAnimation->setDuration(FADE_DURATION);
|
||||
_alphaPropertyAnimation->setStartValue(_alpha);
|
||||
_alphaPropertyAnimation->setEndValue(FADE_IN_ALPHA);
|
||||
_alphaPropertyAnimation->start();
|
||||
|
||||
// Sometimes, this "QPropertyAnimation" fails to complete the animation, and we end up with a partially faded
|
||||
// state. So we will also have this fail-safe, where we record the timestamp of the fadeRequest, and the target
|
||||
// value of the fade, and if after that time we still haven't faded all the way, we will kick it to the final
|
||||
// fade value
|
||||
startFadeFailsafe(FADE_IN_ALPHA);
|
||||
}
|
||||
|
||||
void CompositorHelper::fadeOut() {
|
||||
_fadeInAlpha = false;
|
||||
|
||||
_alphaPropertyAnimation->setDuration(FADE_DURATION);
|
||||
_alphaPropertyAnimation->setStartValue(_alpha);
|
||||
_alphaPropertyAnimation->setEndValue(FADE_OUT_ALPHA);
|
||||
_alphaPropertyAnimation->start();
|
||||
startFadeFailsafe(FADE_OUT_ALPHA);
|
||||
}
|
||||
|
||||
void CompositorHelper::toggle() {
|
||||
if (_fadeInAlpha) {
|
||||
fadeOut();
|
||||
} else {
|
||||
fadeIn();
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const glm::vec3& headPosition) const {
|
||||
glm::mat4 result;
|
||||
if (isHMD()) {
|
||||
|
|
|
@ -38,7 +38,6 @@ const float MAGNIFY_MULT = 2.0f;
|
|||
class CompositorHelper : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(float alpha READ getAlpha WRITE setAlpha)
|
||||
Q_PROPERTY(bool reticleOverDesktop READ getReticleOverDesktop WRITE setReticleOverDesktop)
|
||||
public:
|
||||
static const uvec2 VIRTUAL_SCREEN_SIZE;
|
||||
|
@ -75,13 +74,6 @@ public:
|
|||
void setModelTransform(const Transform& transform) { _modelTransform = transform; }
|
||||
const Transform& getModelTransform() const { return _modelTransform; }
|
||||
|
||||
void fadeIn();
|
||||
void fadeOut();
|
||||
void toggle();
|
||||
|
||||
float getAlpha() const { return _alpha; }
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
|
||||
bool getReticleVisible() const { return _reticleVisible; }
|
||||
void setReticleVisible(bool visible) { _reticleVisible = visible; }
|
||||
|
||||
|
@ -113,7 +105,7 @@ public:
|
|||
void setReticleOverDesktop(bool value) { _isOverDesktop = value; }
|
||||
|
||||
void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; }
|
||||
void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; _currentFrame = frame; }
|
||||
void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; }
|
||||
|
||||
signals:
|
||||
void allowMouseCaptureChanged();
|
||||
|
@ -127,7 +119,6 @@ private:
|
|||
|
||||
DisplayPluginPointer _currentDisplayPlugin;
|
||||
glm::mat4 _currentCamera;
|
||||
uint32_t _currentFrame { 0 };
|
||||
QWidget* _renderingWidget{ nullptr };
|
||||
|
||||
//// Support for hovering and tooltips
|
||||
|
@ -143,17 +134,7 @@ private:
|
|||
float _textureFov { VIRTUAL_UI_TARGET_FOV.y };
|
||||
float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO };
|
||||
|
||||
float _alpha { 1.0f };
|
||||
float _prevAlpha { 1.0f };
|
||||
float _fadeInAlpha { true };
|
||||
float _oculusUIRadius { 1.0f };
|
||||
|
||||
quint64 _fadeStarted { 0 };
|
||||
float _fadeFailsafeEndValue { 1.0f };
|
||||
void checkFadeFailsafe();
|
||||
void startFadeFailsafe(float endValue);
|
||||
|
||||
int _reticleQuad;
|
||||
float _hmdUIRadius { 1.0f };
|
||||
|
||||
int _previousBorderWidth { -1 };
|
||||
int _previousBorderHeight { -1 };
|
||||
|
|
|
@ -445,25 +445,18 @@ void OpenGLDisplayPlugin::compositeOverlay() {
|
|||
|
||||
useProgram(_program);
|
||||
// check the alpha
|
||||
auto overlayAlpha = compositorHelper->getAlpha();
|
||||
if (overlayAlpha > 0.0f) {
|
||||
// set the alpha
|
||||
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
||||
|
||||
// Overlay draw
|
||||
if (isStereo()) {
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mat4());
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
drawUnitQuad();
|
||||
});
|
||||
} else {
|
||||
// Overlay draw
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mat4());
|
||||
// Overlay draw
|
||||
if (isStereo()) {
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mat4());
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
drawUnitQuad();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Overlay draw
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mat4());
|
||||
drawUnitQuad();
|
||||
}
|
||||
Uniform<float>(*_program, _alphaUniform).Set(1.0);
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositePointer() {
|
||||
|
@ -471,24 +464,16 @@ void OpenGLDisplayPlugin::compositePointer() {
|
|||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
|
||||
useProgram(_program);
|
||||
// check the alpha
|
||||
auto overlayAlpha = compositorHelper->getAlpha();
|
||||
if (overlayAlpha > 0.0f) {
|
||||
// set the alpha
|
||||
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
||||
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(compositorHelper->getReticleTransform(glm::mat4()));
|
||||
if (isStereo()) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
drawUnitQuad();
|
||||
});
|
||||
} else {
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(compositorHelper->getReticleTransform(glm::mat4()));
|
||||
if (isStereo()) {
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
drawUnitQuad();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
drawUnitQuad();
|
||||
}
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mat4());
|
||||
Uniform<float>(*_program, _alphaUniform).Set(1.0);
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::compositeScene() {
|
||||
|
|
|
@ -254,23 +254,15 @@ void HmdDisplayPlugin::compositeOverlay() {
|
|||
using namespace oglplus;
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
|
||||
// check the alpha
|
||||
useProgram(_program);
|
||||
auto overlayAlpha = compositorHelper->getAlpha();
|
||||
if (overlayAlpha > 0.0f) {
|
||||
// set the alpha
|
||||
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
||||
|
||||
_sphereSection->Use();
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye));
|
||||
auto mvp = _eyeProjections[eye] * modelView;
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||
_sphereSection->Draw();
|
||||
});
|
||||
}
|
||||
Uniform<float>(*_program, _alphaUniform).Set(1.0);
|
||||
_sphereSection->Use();
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye));
|
||||
auto mvp = _eyeProjections[eye] * modelView;
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||
_sphereSection->Draw();
|
||||
});
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::compositePointer() {
|
||||
|
@ -280,25 +272,19 @@ void HmdDisplayPlugin::compositePointer() {
|
|||
|
||||
// check the alpha
|
||||
useProgram(_program);
|
||||
auto overlayAlpha = compositorHelper->getAlpha();
|
||||
if (overlayAlpha > 0.0f) {
|
||||
// set the alpha
|
||||
Uniform<float>(*_program, _alphaUniform).Set(overlayAlpha);
|
||||
|
||||
// Mouse pointer
|
||||
_plane->Use();
|
||||
// Reconstruct the headpose from the eye poses
|
||||
auto headPosition = vec3(_currentPresentFrameInfo.presentPose[3]);
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
auto eyePose = _currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye);
|
||||
auto reticleTransform = compositorHelper->getReticleTransform(eyePose, headPosition);
|
||||
auto mvp = _eyeProjections[eye] * reticleTransform;
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||
_plane->Draw();
|
||||
});
|
||||
}
|
||||
Uniform<float>(*_program, _alphaUniform).Set(1.0);
|
||||
// Mouse pointer
|
||||
_plane->Use();
|
||||
// Reconstruct the headpose from the eye poses
|
||||
auto headPosition = vec3(_currentPresentFrameInfo.presentPose[3]);
|
||||
for_each_eye([&](Eye eye) {
|
||||
eyeViewport(eye);
|
||||
auto eyePose = _currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye);
|
||||
auto reticleTransform = compositorHelper->getReticleTransform(eyePose, headPosition);
|
||||
auto mvp = _eyeProjections[eye] * reticleTransform;
|
||||
Uniform<glm::mat4>(*_program, _mvpUniform).Set(mvp);
|
||||
_plane->Draw();
|
||||
});
|
||||
}
|
||||
|
||||
void HmdDisplayPlugin::internalPresent() {
|
||||
|
|
|
@ -22,10 +22,6 @@ QString ErrorDialog::text() const {
|
|||
return _text;
|
||||
}
|
||||
|
||||
void ErrorDialog::setVisible(bool v) {
|
||||
OffscreenQmlDialog::setVisible(v);
|
||||
}
|
||||
|
||||
void ErrorDialog::setText(const QString& arg) {
|
||||
if (arg != _text) {
|
||||
_text = arg;
|
||||
|
|
|
@ -30,7 +30,6 @@ public:
|
|||
QString text() const;
|
||||
|
||||
public slots:
|
||||
virtual void setVisible(bool v);
|
||||
void setText(const QString& arg);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -17,7 +17,7 @@ OffscreenQmlDialog::~OffscreenQmlDialog() {
|
|||
}
|
||||
|
||||
void OffscreenQmlDialog::hide() {
|
||||
static_cast<QQuickItem*>(parent())->setVisible(false);
|
||||
parent()->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, false);
|
||||
}
|
||||
|
||||
QString OffscreenQmlDialog::title() const {
|
||||
|
|
|
@ -121,32 +121,28 @@ void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(
|
|||
load(url, f);
|
||||
item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
item->setVisible(true);
|
||||
QQmlProperty(item, OFFSCREEN_VISIBILITY_PROPERTY).write(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
// Already loaded?
|
||||
if (item) {
|
||||
emit showDesktop();
|
||||
item->setVisible(!item->isVisible());
|
||||
if (!item) {
|
||||
show(url, name, f);
|
||||
return;
|
||||
}
|
||||
|
||||
load(url, f);
|
||||
item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
if (item && !item->isVisible()) {
|
||||
emit showDesktop();
|
||||
item->setVisible(true);
|
||||
}
|
||||
// Already loaded, so just flip the bit
|
||||
QQmlProperty shownProperty(item, OFFSCREEN_VISIBILITY_PROPERTY);
|
||||
shownProperty.write(!shownProperty.read().toBool());
|
||||
}
|
||||
|
||||
void OffscreenUi::hide(const QString& name) {
|
||||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
if (item) {
|
||||
item->setVisible(false);
|
||||
QQmlProperty(item, OFFSCREEN_VISIBILITY_PROPERTY).write(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,6 +341,20 @@ QVariant OffscreenUi::inputDialog(const Icon icon, const QString& title, const Q
|
|||
return waitForInputDialogResult(createInputDialog(icon, title, label, current));
|
||||
}
|
||||
|
||||
void OffscreenUi::togglePinned() {
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "togglePinned");
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to toggle window visibility";
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenUi::setPinned(bool pinned) {
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "setPinned", Q_ARG(QVariant, pinned));
|
||||
if (!invokeResult) {
|
||||
qWarning() << "Failed to set window visibility";
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenUi::addMenuInitializer(std::function<void(VrMenu*)> f) {
|
||||
if (!_vrMenu) {
|
||||
_queuedMenuInitializers.push_back(f);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
class VrMenu;
|
||||
|
||||
#define OFFSCREEN_VISIBILITY_PROPERTY "shown"
|
||||
|
||||
class OffscreenUi : public OffscreenQmlSurface, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -44,6 +46,13 @@ public:
|
|||
void setNavigationFocused(bool focused);
|
||||
void unfocusWindows();
|
||||
void toggleMenu(const QPoint& screenCoordinates);
|
||||
|
||||
|
||||
// Setting pinned to true will hide all overlay elements on the desktop that don't have a pinned flag
|
||||
void setPinned(bool pinned = true);
|
||||
|
||||
void togglePinned();
|
||||
|
||||
bool eventFilter(QObject* originalDestination, QEvent* event) override;
|
||||
void addMenuInitializer(std::function<void(VrMenu*)> f);
|
||||
|
||||
|
|
|
@ -163,8 +163,7 @@ void QmlWindowClass::setVisible(bool visible) {
|
|||
QMetaObject::invokeMethod(targetWindow, "showTabForUrl", Qt::QueuedConnection, Q_ARG(QVariant, _source), Q_ARG(QVariant, visible));
|
||||
} else {
|
||||
DependencyManager::get<OffscreenUi>()->executeOnUiThread([=] {
|
||||
targetWindow->setVisible(visible);
|
||||
//emit visibilityChanged(visible);
|
||||
targetWindow->setProperty(OFFSCREEN_VISIBILITY_PROPERTY, visible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,6 @@ void Tooltip::setImageURL(const QString& imageURL) {
|
|||
}
|
||||
}
|
||||
|
||||
void Tooltip::setVisible(bool visible) {
|
||||
QQuickItem::setVisible(visible);
|
||||
}
|
||||
|
||||
QString Tooltip::showTip(const QString& title, const QString& description) {
|
||||
const QString newTipId = QUuid().createUuid().toString();
|
||||
|
||||
|
|
|
@ -39,8 +39,6 @@ public:
|
|||
static void closeTip(const QString& tipId);
|
||||
|
||||
public slots:
|
||||
virtual void setVisible(bool v);
|
||||
|
||||
void setTitle(const QString& title);
|
||||
void setDescription(const QString& description);
|
||||
void setImageURL(const QString& imageURL);
|
||||
|
|
|
@ -5,7 +5,7 @@ import Qt.labs.settings 1.0
|
|||
|
||||
import "../../../interface/resources/qml"
|
||||
//import "../../../interface/resources/qml/windows"
|
||||
import "../../../interface/resources/qml/windows-uit"
|
||||
import "../../../interface/resources/qml/windows"
|
||||
import "../../../interface/resources/qml/dialogs"
|
||||
import "../../../interface/resources/qml/hifi"
|
||||
import "../../../interface/resources/qml/hifi/dialogs"
|
||||
|
@ -17,6 +17,267 @@ ApplicationWindow {
|
|||
width: 1280
|
||||
height: 800
|
||||
title: qsTr("Scratch App")
|
||||
toolBar: Row {
|
||||
id: testButtons
|
||||
anchors { margins: 8; left: parent.left; top: parent.top }
|
||||
spacing: 8
|
||||
property int count: 0
|
||||
|
||||
property var tabs: [];
|
||||
property var urls: [];
|
||||
|
||||
// Window visibility
|
||||
|
||||
Button {
|
||||
text: "restore all"
|
||||
onClicked: {
|
||||
for (var i = 0; i < desktop.windows.length; ++i) {
|
||||
desktop.windows[i].shown = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "toggle blue visible"
|
||||
onClicked: {
|
||||
blue.shown = !blue.shown
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "toggle blue enabled"
|
||||
onClicked: {
|
||||
blue.enabled = !blue.enabled
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "toggle desktop"
|
||||
onClicked: desktop.toggleVisible()
|
||||
}
|
||||
|
||||
// Error alerts
|
||||
/*
|
||||
Button {
|
||||
// Message without title.
|
||||
text: "Show Error"
|
||||
onClicked: {
|
||||
var messageBox = desktop.messageBox({
|
||||
text: "Diagnostic cycle will be complete in 30 seconds",
|
||||
icon: hifi.icons.critical,
|
||||
});
|
||||
messageBox.selected.connect(function(button) {
|
||||
console.log("You clicked " + button)
|
||||
})
|
||||
}
|
||||
}
|
||||
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: hifi.icons.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"
|
||||
});
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// query
|
||||
/*
|
||||
// There is no such desktop.queryBox() function; may need to update test to cover QueryDialog.qml?
|
||||
Button {
|
||||
text: "Show Query"
|
||||
onClicked: {
|
||||
var queryBox = desktop.queryBox({
|
||||
text: "Have you stopped beating your wife?",
|
||||
placeholderText: "Are you sure?",
|
||||
// icon: hifi.icons.critical,
|
||||
});
|
||||
queryBox.selected.connect(function(result) {
|
||||
console.log("User responded with " + result);
|
||||
});
|
||||
|
||||
queryBox.canceled.connect(function() {
|
||||
console.log("User cancelled query box ");
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// file dialog
|
||||
|
||||
Button {
|
||||
text: "Open Directory"
|
||||
property var builder: Component {
|
||||
FileDialog { selectDirectory: true }
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var fileDialog = builder.createObject(desktop);
|
||||
fileDialog.canceled.connect(function(){
|
||||
console.log("Cancelled")
|
||||
})
|
||||
fileDialog.selectedFile.connect(function(file){
|
||||
console.log("Selected " + file)
|
||||
})
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Open File"
|
||||
property var builder: Component {
|
||||
FileDialog {
|
||||
title: "Open File"
|
||||
filter: "All Files (*.*)"
|
||||
//filter: "HTML files (*.html);;Other(*.png)"
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var fileDialog = builder.createObject(desktop);
|
||||
fileDialog.canceled.connect(function(){
|
||||
console.log("Cancelled")
|
||||
})
|
||||
fileDialog.selectedFile.connect(function(file){
|
||||
console.log("Selected " + file)
|
||||
})
|
||||
}
|
||||
}
|
||||
/*
|
||||
*/
|
||||
|
||||
// tabs
|
||||
/*
|
||||
Button {
|
||||
text: "Add Tab"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo" });
|
||||
desktop.toolWindow.showTabForUrl("Foo", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Add Tab 2"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo 2" });
|
||||
desktop.toolWindow.showTabForUrl("Foo 2", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Add Tab 3"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo 3" });
|
||||
desktop.toolWindow.showTabForUrl("Foo 3", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Destroy Tab"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.removeTabForUrl("Foo");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Hifi specific stuff
|
||||
/*
|
||||
Button {
|
||||
// Shows the dialog with preferences sections but not each section's preference items
|
||||
// because Preferences.preferencesByCategory() method is not stubbed out.
|
||||
text: "Settings > General..."
|
||||
property var builder: Component {
|
||||
GeneralPreferencesDialog { }
|
||||
}
|
||||
onClicked: {
|
||||
var runningScripts = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Running Scripts"
|
||||
property var builder: Component {
|
||||
RunningScripts { }
|
||||
}
|
||||
onClicked: {
|
||||
var runningScripts = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Attachments"
|
||||
property var builder: Component {
|
||||
AttachmentsDialog { }
|
||||
}
|
||||
onClicked: {
|
||||
var attachmentsDialog = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
Button {
|
||||
// Replicates message box that pops up after selecting new avatar. Includes title.
|
||||
text: "Confirm Avatar"
|
||||
onClicked: {
|
||||
var messageBox = desktop.messageBox({
|
||||
title: "Set Avatar",
|
||||
text: "Would you like to use 'Albert' for your avatar?",
|
||||
icon: hifi.icons.question, // Test question icon
|
||||
//icon: hifi.icons.information, // Test informaton icon
|
||||
//icon: hifi.icons.warning, // Test warning icon
|
||||
//icon: hifi.icons.critical, // Test critical icon
|
||||
//icon: hifi.icons.none, // Test no icon
|
||||
buttons: OriginalDialogs.StandardButton.Ok + OriginalDialogs.StandardButton.Cancel,
|
||||
defaultButton: OriginalDialogs.StandardButton.Ok
|
||||
});
|
||||
messageBox.selected.connect(function(button) {
|
||||
console.log("You clicked " + button)
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
// bookmarks
|
||||
/*
|
||||
Button {
|
||||
text: "Bookmark Location"
|
||||
onClicked: {
|
||||
desktop.inputDialog({
|
||||
title: "Bookmark Location",
|
||||
icon: hifi.icons.placemark,
|
||||
label: "Name"
|
||||
});
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Delete Bookmark"
|
||||
onClicked: {
|
||||
desktop.inputDialog({
|
||||
title: "Delete Bookmark",
|
||||
icon: hifi.icons.placemark,
|
||||
label: "Select the bookmark to delete",
|
||||
items: ["Bookmark A", "Bookmark B", "Bookmark C"]
|
||||
});
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Duplicate Bookmark"
|
||||
onClicked: {
|
||||
desktop.messageBox({
|
||||
title: "Duplicate Bookmark",
|
||||
icon: hifi.icons.warning,
|
||||
text: "The bookmark name you entered alread exists in yoru list.",
|
||||
informativeText: "Would you like to overwrite it?",
|
||||
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
|
||||
defaultButton: OriginalDialogs.StandardButton.Yes
|
||||
});
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
@ -35,249 +296,12 @@ ApplicationWindow {
|
|||
}
|
||||
*/
|
||||
|
||||
Row {
|
||||
id: testButtons
|
||||
anchors { margins: 8; left: parent.left; top: parent.top }
|
||||
spacing: 8
|
||||
property int count: 0
|
||||
|
||||
property var tabs: [];
|
||||
property var urls: [];
|
||||
|
||||
Button {
|
||||
// Shows the dialog with preferences sections but not each section's preference items
|
||||
// because Preferences.preferencesByCategory() method is not stubbed out.
|
||||
text: "Settings > General..."
|
||||
property var builder: Component {
|
||||
GeneralPreferencesDialog { }
|
||||
}
|
||||
onClicked: {
|
||||
var runningScripts = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Running Scripts"
|
||||
property var builder: Component {
|
||||
RunningScripts { }
|
||||
}
|
||||
onClicked: {
|
||||
var runningScripts = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Attachments"
|
||||
property var builder: Component {
|
||||
AttachmentsDialog { }
|
||||
}
|
||||
onClicked: {
|
||||
var attachmentsDialog = builder.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Button {
|
||||
text: "restore all"
|
||||
onClicked: {
|
||||
for (var i = 0; i < desktop.windows.length; ++i) {
|
||||
desktop.windows[i].visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "toggle blue visible"
|
||||
onClicked: {
|
||||
blue.visible = !blue.visible
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "toggle blue enabled"
|
||||
onClicked: {
|
||||
blue.enabled = !blue.enabled
|
||||
}
|
||||
}
|
||||
*/
|
||||
Button {
|
||||
// Replicates message box that pops up after selecting new avatar. Includes title.
|
||||
text: "Confirm Avatar"
|
||||
onClicked: {
|
||||
var messageBox = desktop.messageBox({
|
||||
title: "Set Avatar",
|
||||
text: "Would you like to use 'Albert' for your avatar?",
|
||||
icon: hifi.icons.question, // Test question icon
|
||||
//icon: hifi.icons.information, // Test informaton icon
|
||||
//icon: hifi.icons.warning, // Test warning icon
|
||||
//icon: hifi.icons.critical, // Test critical icon
|
||||
//icon: hifi.icons.none, // 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({
|
||||
text: "Diagnostic cycle will be complete in 30 seconds",
|
||||
icon: hifi.icons.critical,
|
||||
});
|
||||
messageBox.selected.connect(function(button) {
|
||||
console.log("You clicked " + button)
|
||||
})
|
||||
}
|
||||
}
|
||||
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: hifi.icons.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"
|
||||
});
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Bookmark Location"
|
||||
onClicked: {
|
||||
desktop.inputDialog({
|
||||
title: "Bookmark Location",
|
||||
icon: hifi.icons.placemark,
|
||||
label: "Name"
|
||||
});
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Delete Bookmark"
|
||||
onClicked: {
|
||||
desktop.inputDialog({
|
||||
title: "Delete Bookmark",
|
||||
icon: hifi.icons.placemark,
|
||||
label: "Select the bookmark to delete",
|
||||
items: ["Bookmark A", "Bookmark B", "Bookmark C"]
|
||||
});
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Duplicate Bookmark"
|
||||
onClicked: {
|
||||
desktop.messageBox({
|
||||
title: "Duplicate Bookmark",
|
||||
icon: hifi.icons.warning,
|
||||
text: "The bookmark name you entered alread exists in yoru list.",
|
||||
informativeText: "Would you like to overwrite it?",
|
||||
buttons: OriginalDialogs.StandardButton.Yes + OriginalDialogs.StandardButton.No,
|
||||
defaultButton: OriginalDialogs.StandardButton.Yes
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
// There is no such desktop.queryBox() function; may need to update test to cover QueryDialog.qml?
|
||||
Button {
|
||||
text: "Show Query"
|
||||
onClicked: {
|
||||
var queryBox = desktop.queryBox({
|
||||
text: "Have you stopped beating your wife?",
|
||||
placeholderText: "Are you sure?",
|
||||
// icon: hifi.icons.critical,
|
||||
});
|
||||
queryBox.selected.connect(function(result) {
|
||||
console.log("User responded with " + result);
|
||||
});
|
||||
|
||||
queryBox.canceled.connect(function() {
|
||||
console.log("User cancelled query box ");
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
Button {
|
||||
text: "Open Directory"
|
||||
property var builder: Component {
|
||||
FileDialog { selectDirectory: true }
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var fileDialog = builder.createObject(desktop);
|
||||
fileDialog.canceled.connect(function(){
|
||||
console.log("Cancelled")
|
||||
})
|
||||
fileDialog.selectedFile.connect(function(file){
|
||||
console.log("Selected " + file)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Open File"
|
||||
property var builder: Component {
|
||||
FileDialog {
|
||||
title: "Open File"
|
||||
filter: "All Files (*.*)"
|
||||
//filter: "HTML files (*.html);;Other(*.png)"
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
var fileDialog = builder.createObject(desktop);
|
||||
fileDialog.canceled.connect(function(){
|
||||
console.log("Cancelled")
|
||||
})
|
||||
fileDialog.selectedFile.connect(function(file){
|
||||
console.log("Selected " + file)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Add Tab"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo" });
|
||||
desktop.toolWindow.showTabForUrl("Foo", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Add Tab 2"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo 2" });
|
||||
desktop.toolWindow.showTabForUrl("Foo 2", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Add Tab 3"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.addWebTab({ source: "Foo 3" });
|
||||
desktop.toolWindow.showTabForUrl("Foo 3", true);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Destroy Tab"
|
||||
onClicked: {
|
||||
console.log(desktop.toolWindow);
|
||||
desktop.toolWindow.removeTabForUrl("Foo");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
Window {
|
||||
id: blue
|
||||
closable: true
|
||||
visible: true
|
||||
resizable: true
|
||||
destroyOnInvisible: false
|
||||
destroyOnHidden: false
|
||||
|
||||
width: 100; height: 100
|
||||
x: 1280 / 2; y: 720 / 2
|
||||
|
@ -296,32 +320,33 @@ ApplicationWindow {
|
|||
Component.onDestruction: console.log("Blue destroyed")
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
|
||||
|
||||
Rectangle { width: 100; height: 100; x: 100; y: 100; color: "#00f" }
|
||||
|
||||
Window {
|
||||
id: green
|
||||
alwaysOnTop: true
|
||||
frame: HiddenFrame{}
|
||||
hideBackground: true
|
||||
closable: true
|
||||
visible: true
|
||||
resizable: false
|
||||
x: 1280 / 2; y: 720 / 2
|
||||
Settings {
|
||||
category: "TestWindow.Green"
|
||||
property alias x: green.x
|
||||
property alias y: green.y
|
||||
property alias width: green.width
|
||||
property alias height: green.height
|
||||
}
|
||||
width: 100; height: 100
|
||||
Rectangle { anchors.fill: parent; color: "green" }
|
||||
Rectangle {
|
||||
color: "#0f0"
|
||||
width: green.width;
|
||||
height: green.height;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Window {
|
||||
id: yellow
|
||||
objectName: "Yellow"
|
||||
closable: true
|
||||
visible: true
|
||||
resizable: true
|
||||
x: 100; y: 100
|
||||
width: 100; height: 100
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
@ -329,7 +354,7 @@ ApplicationWindow {
|
|||
color: "yellow"
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
Action {
|
||||
|
|
|
@ -18,6 +18,7 @@ DISTFILES += \
|
|||
qml/*.qml \
|
||||
../../interface/resources/qml/*.qml \
|
||||
../../interface/resources/qml/controls/*.qml \
|
||||
../../interface/resources/qml/controls-uit/*.qml \
|
||||
../../interface/resources/qml/dialogs/*.qml \
|
||||
../../interface/resources/qml/dialogs/fileDialog/*.qml \
|
||||
../../interface/resources/qml/dialogs/preferences/*.qml \
|
||||
|
@ -25,9 +26,9 @@ DISTFILES += \
|
|||
../../interface/resources/qml/desktop/*.qml \
|
||||
../../interface/resources/qml/menus/*.qml \
|
||||
../../interface/resources/qml/styles/*.qml \
|
||||
../../interface/resources/qml/styles-uit/*.qml \
|
||||
../../interface/resources/qml/windows/*.qml \
|
||||
../../interface/resources/qml/hifi/*.qml \
|
||||
../../interface/resources/qml/hifi/dialogs/*.qml \
|
||||
../../interface/resources/qml/hifi/dialogs/preferences/*.qml \
|
||||
../../interface/resources/qml/hifi/overlays/*.qml
|
||||
|
||||
|
|
Loading…
Reference in a new issue