From 3d8df56baa140aebd58bb31862768536a86d8c36 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 12 Feb 2016 10:13:06 +1300 Subject: [PATCH] Copy bare minimum of files as start of restyling Running Scripts dialog And add license headers to files. --- .../qml/controls-uit/FontAwesome.qml | 26 +++ .../resources/qml/controls-uit/TextField.qml | 17 ++ .../qml/hifi/dialogs/RunningScripts.qml | 16 +- .../qml/styles-uit/HifiConstants.qml | 70 ++++++ .../qml/windows-uit/DefaultFrame.qml | 79 +++++++ .../resources/qml/windows-uit/Fadable.qml | 61 ++++++ interface/resources/qml/windows-uit/Frame.qml | 101 +++++++++ .../resources/qml/windows-uit/Window.qml | 201 ++++++++++++++++++ 8 files changed, 568 insertions(+), 3 deletions(-) create mode 100644 interface/resources/qml/controls-uit/FontAwesome.qml create mode 100644 interface/resources/qml/controls-uit/TextField.qml create mode 100644 interface/resources/qml/styles-uit/HifiConstants.qml create mode 100644 interface/resources/qml/windows-uit/DefaultFrame.qml create mode 100644 interface/resources/qml/windows-uit/Fadable.qml create mode 100644 interface/resources/qml/windows-uit/Frame.qml create mode 100644 interface/resources/qml/windows-uit/Window.qml diff --git a/interface/resources/qml/controls-uit/FontAwesome.qml b/interface/resources/qml/controls-uit/FontAwesome.qml new file mode 100644 index 0000000000..5c03ef09b2 --- /dev/null +++ b/interface/resources/qml/controls-uit/FontAwesome.qml @@ -0,0 +1,26 @@ +// +// FontAwesome.qml +// +// Created by Bradley Austin Davis on 24 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +Text { + id: root + FontLoader { id: iconFont; source: "../../fonts/fontawesome-webfont.ttf"; } + property int size: 32 + width: size + height: size + font.pixelSize: size + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + font.family: iconFont.name +} + diff --git a/interface/resources/qml/controls-uit/TextField.qml b/interface/resources/qml/controls-uit/TextField.qml new file mode 100644 index 0000000000..6d5b08e430 --- /dev/null +++ b/interface/resources/qml/controls-uit/TextField.qml @@ -0,0 +1,17 @@ +// +// TextField.qml +// +// Created by Bradley Austin Davis on 4 Feb 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 + +TextField { + style: TextFieldStyle { renderType: Text.QtRendering } +} diff --git a/interface/resources/qml/hifi/dialogs/RunningScripts.qml b/interface/resources/qml/hifi/dialogs/RunningScripts.qml index 8834c1d8bc..01f21f2c2a 100644 --- a/interface/resources/qml/hifi/dialogs/RunningScripts.qml +++ b/interface/resources/qml/hifi/dialogs/RunningScripts.qml @@ -1,11 +1,21 @@ +// +// RunningScripts.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.Dialogs 1.2 as OriginalDialogs import Qt.labs.settings 1.0 -import "../../styles" as Hifi -import "../../controls" as HifiControls -import "../../windows" +import "../../styles-uit" as Hifi +import "../../controls-uit" as HifiControls +import "../../windows-uit" Window { id: root diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml new file mode 100644 index 0000000000..055f06d60b --- /dev/null +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -0,0 +1,70 @@ +// +// HiFiConstants.qml +// +// Created by Bradley Austin Davis on 28 Apr 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +Item { + SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } + readonly property alias colors: colors + readonly property alias layout: layout + readonly property alias fonts: fonts + readonly property alias styles: styles + readonly property alias effects: effects + + Item { + id: colors + readonly property color hifiBlue: "#0e7077" + readonly property color window: sysPalette.window + readonly property color dialogBackground: sysPalette.window + readonly property color inputBackground: "white" + readonly property color background: sysPalette.dark + readonly property color text: "#202020" + readonly property color disabledText: "gray" + readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2 + readonly property color light: sysPalette.light + readonly property alias activeWindow: activeWindow + readonly property alias inactiveWindow: inactiveWindow + QtObject { + id: activeWindow + readonly property color headerBackground: "white" + readonly property color headerText: "black" + } + QtObject { + id: inactiveWindow + readonly property color headerBackground: "gray" + readonly property color headerText: "black" + } + } + + QtObject { + id: fonts + readonly property string fontFamily: "Arial" // Available on both Windows and OSX + readonly property real pixelSize: 22 // Logical pixel size; works on Windows and OSX at varying physical DPIs + readonly property real headerPixelSize: 32 + } + + QtObject { + id: layout + property int spacing: 8 + property int rowHeight: 40 + property int windowTitleHeight: 48 + } + + QtObject { + id: styles + readonly property int borderWidth: 5 + readonly property int borderRadius: borderWidth * 2 + } + + QtObject { + id: effects + readonly property int fadeInDuration: 300 + } +} diff --git a/interface/resources/qml/windows-uit/DefaultFrame.qml b/interface/resources/qml/windows-uit/DefaultFrame.qml new file mode 100644 index 0000000000..df632236a2 --- /dev/null +++ b/interface/resources/qml/windows-uit/DefaultFrame.qml @@ -0,0 +1,79 @@ +// +// 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 "." +import "../controls-uit" + +Frame { + id: frame + + property bool wideTopMargin: (window && (window.closable || window.title)); + + Rectangle { + anchors { margins: -iconSize; topMargin: -iconSize * (wideTopMargin ? 2 : 1); } + anchors.fill: parent; + color: "#7f7f7f7f"; + radius: 3; + + // Allow dragging of the window + MouseArea { + anchors.fill: parent + drag.target: window + } + + 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" + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + onClicked: { frame.pin(); mouse.accepted = false; } + } + } + FontAwesome { + visible: window ? window.closable : false + text: closeClickArea.containsMouse ? "\uf057" : "\uf05c" + style: Text.Outline; + styleColor: "white" + color: closeClickArea.containsMouse ? "red" : "black" + size: frame.iconSize + MouseArea { + id: closeClickArea + anchors.fill: parent + hoverEnabled: true + onClicked: window.visible = false; + } + } + } + + Text { + id: titleText + anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } + text: window ? window.title : "" + elide: Text.ElideRight + font.bold: true + color: (window && window.focus) ? "white" : "gray" + style: Text.Outline; + styleColor: "black" + } + } + +} + diff --git a/interface/resources/qml/windows-uit/Fadable.qml b/interface/resources/qml/windows-uit/Fadable.qml new file mode 100644 index 0000000000..bf3a6aa2b4 --- /dev/null +++ b/interface/resources/qml/windows-uit/Fadable.qml @@ -0,0 +1,61 @@ +// +// 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-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); + } +} diff --git a/interface/resources/qml/windows-uit/Frame.qml b/interface/resources/qml/windows-uit/Frame.qml new file mode 100644 index 0000000000..9654143cd8 --- /dev/null +++ b/interface/resources/qml/windows-uit/Frame.qml @@ -0,0 +1,101 @@ +// +// 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 "../controls-uit" +import "../js/Utils.js" as Utils + +Item { + id: frame + // 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: [ + 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 + } + + 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 + } + + MouseArea { + id: sizeDrag + width: iconSize + height: iconSize + enabled: window ? window.resizable : false + x: window ? window.width : 0 + y: window ? window.height : 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) { + window.content.visible = true + hid = false; + } + } + onPositionChanged: { + if (pressed) { + if (window.content.visible) { + window.content.visible = false; + hid = true; + } + var delta = Qt.vector2d(mouseX, mouseY).minus(pressOrigin); + frame.deltaSize(delta.x, delta.y) + } + } + FontAwesome { + visible: sizeDrag.enabled + rotation: -45 + anchors { centerIn: parent } + horizontalAlignment: Text.AlignHCenter + text: "\uf07d" + size: iconSize / 3 * 2 + style: Text.Outline; styleColor: "white" + } + } + +} diff --git a/interface/resources/qml/windows-uit/Window.qml b/interface/resources/qml/windows-uit/Window.qml new file mode 100644 index 0000000000..435d8bdb15 --- /dev/null +++ b/interface/resources/qml/windows-uit/Window.qml @@ -0,0 +1,201 @@ +// +// 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 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: -1; y: -1 + 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 vector2d minSize: Qt.vector2d(100, 100) + property vector2d maxSize: Qt.vector2d(1280, 720) + + // The content to place inside the window, determined by the client + default property var content + + 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.margins + y: frame.decoration.anchors.topMargin + propagateComposedEvents: true + hoverEnabled: 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.margins + 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 { } + + + children: [ swallower, frame, content, activator ] + + Component.onCompleted: raise(); + Component.onDestruction: windowDestroyed(); + onParentChanged: raise(); + + onVisibleChanged: { + if (!visible && destroyOnInvisible) { + destroy(); + return; + } + if (visible) { + raise(); + } + enabled = visible + } + + 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; + } + } +}