Merge pull request #9863 from ctrlaltdavid/21209

Port Avatar > Attachments to tablet
This commit is contained in:
Seth Alves 2017-03-14 05:32:18 -08:00 committed by GitHub
commit e0562e27d4
21 changed files with 699 additions and 524 deletions

View file

@ -120,7 +120,7 @@ TableView {
}
rowDelegate: Rectangle {
height: (styleData.selected ? 1.2 : 1) * hifi.dimensions.tableRowHeight
height: hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: tableView.isLightColorScheme

View file

@ -25,6 +25,8 @@ Original.CheckBox {
readonly property int checkSize: Math.max(boxSize - 8, 10)
readonly property int checkRadius: 2
activeFocusOnPress: true
style: CheckBoxStyle {
indicator: Rectangle {
id: box

View file

@ -14,7 +14,6 @@ import QtQuick.Controls.Styles 1.4
import "../styles-uit"
import "../controls-uit" as HifiControls
import "." as VrControls
FocusScope {
id: root
@ -25,6 +24,7 @@ FocusScope {
readonly property alias currentText: comboBox.currentText;
property alias currentIndex: comboBox.currentIndex;
property int dropdownHeight: 480
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property string label: ""
@ -32,6 +32,8 @@ FocusScope {
readonly property ComboBox control: comboBox
property bool isDesktop: true
signal accepted();
implicitHeight: comboBox.height;
@ -119,11 +121,17 @@ FocusScope {
}
function showList() {
var r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
var r;
if (isDesktop) {
r = desktop.mapFromItem(root, 0, 0, root.width, root.height);
} else {
r = mapFromItem(root, 0, 0, root.width, root.height);
}
var y = r.y + r.height;
var bottom = y + scrollView.height;
if (bottom > desktop.height) {
y -= bottom - desktop.height + 8;
var height = isDesktop ? desktop.height : tabletRoot.height;
if (bottom > height) {
y -= bottom - height + 8;
}
scrollView.x = r.x;
scrollView.y = y;
@ -141,9 +149,9 @@ FocusScope {
FocusScope {
id: popup
parent: desktop
parent: isDesktop ? desktop : root
anchors.fill: parent
z: desktop.zLevels.menu
z: isDesktop ? desktop.zLevels.menu : 12
visible: false
focus: true
@ -166,7 +174,7 @@ FocusScope {
ScrollView {
id: scrollView
height: 480
height: root.dropdownHeight
width: root.width + 4
property bool hoverEnabled: false;
@ -178,18 +186,18 @@ FocusScope {
visible: false
}
scrollBarBackground: Rectangle{
implicitWidth: 14
implicitWidth: 20
color: hifi.colors.baseGray
}
handle:
Rectangle {
implicitWidth: 8
implicitWidth: 16
anchors.left: parent.left
anchors.leftMargin: 3
anchors.top: parent.top
anchors.bottom: parent.bottom
radius: 3
radius: 6
color: hifi.colors.lightGrayText
}
}
@ -233,4 +241,8 @@ FocusScope {
anchors.bottomMargin: 4
visible: label != ""
}
Component.onCompleted: {
isDesktop = (typeof desktop !== "undefined");
}
}

View file

@ -1,211 +0,0 @@
//
// ComboBox.qml
//
// Created by Dante Ruiz on 13 Feb 2017
// 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 "../styles-uit"
import "../controls-uit" as HifiControls
FocusScope {
id: root
HifiConstants { id: hifi }
property alias model: comboBox.model;
property alias comboBox: comboBox
readonly property alias currentText: comboBox.currentText;
property alias currentIndex: comboBox.currentIndex;
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property string label: ""
property real controlHeight: height + (comboBoxLabel.visible ? comboBoxLabel.height + comboBoxLabel.anchors.bottomMargin : 0)
readonly property ComboBox control: comboBox
signal accepted();
implicitHeight: comboBox.height;
focus: true
Rectangle {
id: background
gradient: Gradient {
GradientStop {
position: 0.2
color: popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightStart : hifi.colors.dropDownDarkStart)
}
GradientStop {
position: 1.0
color: popup.visible
? (isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
: (isLightColorScheme ? hifi.colors.dropDownLightFinish : hifi.colors.dropDownDarkFinish)
}
}
anchors.fill: parent
}
SystemPalette { id: palette }
ComboBox {
id: comboBox
anchors.fill: parent
visible: false
height: hifi.fontSizes.textFieldInput + 13 // Match height of TextField control.
}
FiraSansSemiBold {
id: textField
anchors {
left: parent.left
leftMargin: hifi.dimensions.textPadding
right: dropIcon.left
verticalCenter: parent.verticalCenter
}
size: hifi.fontSizes.textFieldInput
text: comboBox.currentText
elide: Text.ElideRight
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText )
}
Item {
id: dropIcon
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
height: background.height
width: height
Rectangle {
width: 1
height: parent.height
anchors.top: parent.top
anchors.left: parent.left
color: isLightColorScheme ? hifi.colors.faintGray : hifi.colors.baseGray
}
HiFiGlyphs {
anchors {
top: parent.top
topMargin: -11
horizontalCenter: parent.horizontalCenter
}
size: hifi.dimensions.spinnerSize
text: hifi.glyphs.caratDn
color: controlHover.containsMouse || popup.visible ? hifi.colors.baseGray : (isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText)
}
}
MouseArea {
id: controlHover
hoverEnabled: true
anchors.fill: parent
onClicked: toggleList();
}
function toggleList() {
if (popup.visible) {
hideList();
} else {
showList();
}
}
function showList() {
var r = mapFromItem(root, 0, 0, root.width, root.height);
var y = r.y + r.height;
var bottom = y + scrollView.height;
if (bottom > 720) {
y -= bottom - tabletRoot.height + 8;
}
scrollView.x = r.x;
scrollView.y = y;
popup.visible = true;
popup.forceActiveFocus();
listView.currentIndex = root.currentIndex;
scrollView.hoverEnabled = true;
}
function hideList() {
popup.visible = false;
scrollView.hoverEnabled = false;
root.accepted();
}
FocusScope {
id: popup
z: 12
parent: parent
anchors.fill: parent
visible: false
focus: true
MouseArea {
anchors.fill: parent
onClicked: hideList();
}
function previousItem() { listView.currentIndex = (listView.currentIndex + listView.count - 1) % listView.count; }
function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; }
function selectCurrentItem() { root.currentIndex = listView.currentIndex; hideList(); }
function selectSpecificItem(index) { root.currentIndex = index; hideList(); }
Keys.onUpPressed: previousItem();
Keys.onDownPressed: nextItem();
Keys.onSpacePressed: selectCurrentItem();
Keys.onRightPressed: selectCurrentItem();
Keys.onReturnPressed: selectCurrentItem();
Keys.onEscapePressed: hideList();
ScrollView {
id: scrollView
height: 480
width: root.width + 4
property bool hoverEnabled: false;
ListView {
id: listView
height: textField.height * count * 1.4
model: root.model
delegate: Rectangle {
width: root.width + 4
height: popupText.implicitHeight * 1.4
color: (listView.currentIndex === index) ? hifi.colors.primaryHighlight :
(isLightColorScheme ? hifi.colors.dropDownPressedLight : hifi.colors.dropDownPressedDark)
FiraSansSemiBold {
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.textPadding
anchors.verticalCenter: parent.verticalCenter
id: popupText
text: listView.model[index] ? listView.model[index] : ""
size: hifi.fontSizes.textFieldInput
color: hifi.colors.baseGray
}
MouseArea {
id: popupHover
anchors.fill: parent;
hoverEnabled: scrollView.hoverEnabled;
onEntered: listView.currentIndex = index;
onClicked: popup.selectSpecificItem(index);
}
}
}
}
}
HifiControls.Label {
id: comboBoxLabel
text: root.label
colorScheme: root.colorScheme
anchors.left: parent.left
anchors.bottom: parent.top
anchors.bottomMargin: 4
visible: label != ""
}
}

View file

@ -0,0 +1,35 @@
//
// TabletHeader.qml
//
// Created by David Rowe on 11 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import "../styles-uit"
Rectangle {
property string title: ""
HifiConstants { id: hifi }
height: hifi.dimensions.tabletMenuHeader
z: 100
color: hifi.colors.darkGray
RalewayBold {
text: title
size: 26
color: hifi.colors.white
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.contentMargin.x
}
}

View file

@ -205,7 +205,7 @@ TabletModalWindow {
// }
}
ControlsUIT.TabletComboBox {
ControlsUIT.ComboBox {
id: comboBoxField;
label: root.comboBox.label;
focus: Boolean(root.comboBox);

View file

@ -149,7 +149,7 @@ TabletModalWindow {
}
}
TabletComboBox {
ComboBox {
id: pathSelector
z: 10
anchors {

View file

@ -109,7 +109,7 @@ TabletModalWindow {
}
}
TabletComboBox {
ComboBox {
id: comboBox
label: root.label
focus: true

View file

@ -1,13 +1,20 @@
//
// AttachmentsDialog.qml
//
// Created by David Rowe on 9 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://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 QtQuick.Controls.Styles 1.4
import "../../styles-uit"
import "../../controls-uit" as HifiControls
import "../../windows"
import "attachments"
import "content"
ScrollingWindow {
id: root
@ -21,9 +28,6 @@ ScrollingWindow {
HifiConstants { id: hifi }
readonly property var originalAttachments: MyAvatar.getAttachmentsVariant();
property var attachments: [];
property var settings: Settings {
category: "AttachmentsDialog"
property alias x: root.x
@ -32,198 +36,9 @@ ScrollingWindow {
property alias height: root.height
}
Component.onCompleted: {
for (var i = 0; i < originalAttachments.length; ++i) {
var attachment = originalAttachments[i];
root.attachments.push(attachment);
listView.model.append({});
}
function closeDialog() {
root.destroy();
}
Column {
width: pane.contentWidth
Rectangle {
width: parent.width
height: root.height - (keyboardEnabled && keyboardRaised ? 200 : 0)
radius: 4
color: hifi.colors.baseGray
Rectangle {
id: attachmentsBackground
anchors {
left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top;
margins: hifi.dimensions.contentMargin.x
bottomMargin: hifi.dimensions.contentSpacing.y
}
color: hifi.colors.baseGrayShadow
radius: 4
ScrollView {
id: scrollView
anchors.fill: parent
anchors.margins: 4
style: ScrollViewStyle {
padding {
top: 0
right: 0
bottom: 0
}
decrementControl: Item {
visible: false
}
incrementControl: Item {
visible: false
}
scrollBarBackground: Rectangle{
implicitWidth: 14
color: hifi.colors.baseGray
radius: 4
Rectangle {
// Make top left corner of scrollbar appear square
width: 8
height: 4
color: hifi.colors.baseGray
anchors.top: parent.top
anchors.horizontalCenter: parent.left
}
}
handle:
Rectangle {
implicitWidth: 8
anchors {
left: parent.left
leftMargin: 3
top: parent.top
topMargin: 3
bottom: parent.bottom
bottomMargin: 4
}
radius: 4
color: hifi.colors.lightGrayText
}
}
ListView {
id: listView
model: ListModel {}
delegate: Item {
id: attachmentDelegate
implicitHeight: attachmentView.height + 8;
implicitWidth: attachmentView.width
Attachment {
id: attachmentView
width: scrollView.width
attachment: root.attachments[index]
onDeleteAttachment: {
attachments.splice(index, 1);
listView.model.remove(index, 1);
}
onUpdateAttachment: MyAvatar.setAttachmentsVariant(attachments);
}
}
onCountChanged: MyAvatar.setAttachmentsVariant(attachments);
}
function scrollBy(delta) {
flickableItem.contentY += delta;
}
}
}
HifiControls.Button {
id: newAttachmentButton
anchors {
left: parent.left
right: parent.right
bottom: buttonRow.top
margins: hifi.dimensions.contentMargin.x;
topMargin: hifi.dimensions.contentSpacing.y
bottomMargin: hifi.dimensions.contentSpacing.y
}
text: "New Attachment"
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
onClicked: {
var template = {
modelUrl: "",
translation: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
scale: 1,
jointName: MyAvatar.jointNames[0],
soft: false
};
attachments.push(template);
listView.model.append({});
MyAvatar.setAttachmentsVariant(attachments);
}
}
Row {
id: buttonRow
spacing: 8
anchors {
right: parent.right
bottom: parent.bottom
margins: hifi.dimensions.contentMargin.x
topMargin: hifi.dimensions.contentSpacing.y
bottomMargin: hifi.dimensions.contentSpacing.y
}
HifiControls.Button {
action: okAction
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
}
HifiControls.Button {
action: cancelAction
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
}
}
Action {
id: cancelAction
text: "Cancel"
onTriggered: {
MyAvatar.setAttachmentsVariant(originalAttachments);
root.destroy()
}
}
Action {
id: okAction
text: "OK"
onTriggered: {
for (var i = 0; i < attachments.length; ++i) {
console.log("Attachment " + i + ": " + attachments[i]);
}
MyAvatar.setAttachmentsVariant(attachments);
root.destroy()
}
}
}
}
onKeyboardRaisedChanged: {
if (keyboardEnabled && keyboardRaised) {
// Scroll to item with focus if necessary.
var footerHeight = newAttachmentButton.height + buttonRow.height + 3 * hifi.dimensions.contentSpacing.y;
var delta = activator.mouseY
- (activator.height + activator.y - 200 - footerHeight - hifi.dimensions.controlLineHeight);
if (delta > 0) {
scrollView.scrollBy(delta);
} else {
// HACK: Work around for case where are 100% scrolled; stops window from erroneously scrolling to 100% when show keyboard.
scrollView.scrollBy(-1);
scrollView.scrollBy(1);
}
}
}
AttachmentsContent { }
}

View file

@ -1,92 +1,36 @@
//
// ModelBrowserDialog.qml
//
// Created by David Rowe on 11 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.XmlListModel 2.0
import QtQuick.Controls.Styles 1.4
import "../../windows"
import "../../js/Utils.js" as Utils
import "../models"
import "../../styles-uit"
import "../../controls-uit" as HifiControls
import "../../windows"
import "content"
ScrollingWindow {
id: root
objectName: "ModelBrowserDialog"
title: "Attachment Model"
resizable: true
width: 600
height: 480
closable: false
property var result;
//HifiConstants { id: hifi }
signal selected(var modelUrl);
signal canceled();
property var result
HifiConstants {id: hifi}
signal selected(var modelUrl)
signal canceled()
Column {
width: pane.contentWidth
Rectangle {
width: parent.width
height: root.height - (keyboardEnabled && keyboardRaised ? 200 : 0)
radius: 4
color: hifi.colors.baseGray
HifiControls.TextField {
id: filterEdit
anchors { left: parent.left; right: parent.right; top: parent.top ; margins: 8}
placeholderText: "filter"
onTextChanged: tableView.model.filter = text
colorScheme: hifi.colorSchemes.dark
}
HifiControls.AttachmentsTable {
id: tableView
anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; bottom: buttonRow.top; margins: 8; }
colorScheme: hifi.colorSchemes.dark
onCurrentRowChanged: {
if (currentRow == -1) {
root.result = null;
return;
}
result = model.baseUrl + "/" + model.get(tableView.currentRow).key;
}
}
Row {
id: buttonRow
spacing: 8
anchors { right: parent.right; rightMargin: 8; bottom: parent.bottom; bottomMargin: 8; }
HifiControls.Button { action: acceptAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
HifiControls.Button { action: cancelAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
}
Action {
id: acceptAction
text: qsTr("OK")
enabled: root.result ? true : false
shortcut: Qt.Key_Return
onTriggered: {
root.selected(root.result);
root.destroy();
}
}
Action {
id: cancelAction
text: qsTr("Cancel")
shortcut: Qt.Key_Escape
onTriggered: {
root.canceled();
root.destroy();
}
}
}
ModelBrowserContent {
id: modelBrowserContent
}
}

View file

@ -6,6 +6,7 @@ import Qt.labs.settings 1.0
import "."
import ".."
import "../../tablet"
import "../../../styles-uit"
import "../../../controls-uit" as HifiControls
import "../../../windows"
@ -17,10 +18,24 @@ Item {
HifiConstants { id: hifi }
signal selectAttachment();
signal deleteAttachment(var attachment);
signal updateAttachment();
property bool completed: false;
function doSelectAttachment(control, focus) {
if (focus) {
selectAttachment();
// Refocus control after possibly changing focus to attachment.
if (control.setControlFocus !== undefined) {
control.setControlFocus();
} else {
control.focus = true;
}
}
}
Rectangle { color: hifi.colors.baseGray; anchors.fill: parent; radius: 4 }
Component.onCompleted: {
@ -50,6 +65,7 @@ Item {
updateAttachment();
}
}
onFocusChanged: doSelectAttachment(this, focus);
}
HifiControls.Button {
id: modelChooserButton;
@ -61,17 +77,37 @@ Item {
id: modelBrowserBuilder;
ModelBrowserDialog {}
}
Component {
id: tabletModelBrowserBuilder;
TabletModelBrowserDialog {}
}
onClicked: {
var browser = modelBrowserBuilder.createObject(desktop);
browser.selected.connect(function(newModelUrl){
modelUrl.text = newModelUrl;
})
var browser;
if (typeof desktop !== "undefined") {
browser = modelBrowserBuilder.createObject(desktop);
browser.selected.connect(function(newModelUrl){
modelUrl.text = newModelUrl;
});
} else {
browser = tabletModelBrowserBuilder.createObject(tabletRoot);
browser.selected.connect(function(newModelUrl){
modelUrl.text = newModelUrl;
tabletRoot.openModal = null;
});
browser.canceled.connect(function() {
tabletRoot.openModal = null;
});
// Make dialog modal.
tabletRoot.openModal = browser;
}
}
}
}
Item {
z: 1000
height: jointChooser.height + jointLabel.height + 4
anchors { left: parent.left; right: parent.right; }
HifiControls.Label {
@ -82,6 +118,7 @@ Item {
}
HifiControls.ComboBox {
id: jointChooser;
dropdownHeight: (typeof desktop !== "undefined") ? 480 : 206
anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
colorScheme: hifi.colorSchemes.dark
currentIndex: attachment ? model.indexOf(attachment.jointName) : -1
@ -91,6 +128,7 @@ Item {
updateAttachment();
}
}
onFocusChanged: doSelectAttachment(this, focus);
}
}
@ -108,6 +146,7 @@ Item {
updateAttachment();
}
}
onControlFocusChanged: doSelectAttachment(this, controlFocus);
}
}
@ -125,6 +164,7 @@ Item {
updateAttachment();
}
}
onControlFocusChanged: doSelectAttachment(this, controlFocus);
}
}
@ -153,6 +193,7 @@ Item {
updateAttachment();
}
}
onFocusChanged: doSelectAttachment(this, focus);
}
}
@ -178,6 +219,7 @@ Item {
updateAttachment();
}
}
onFocusChanged: doSelectAttachment(this, focus);
}
}
}

View file

@ -15,9 +15,37 @@ Item {
property real stepSize: 1
property real maximumValue: 99
property real minimumValue: 0
property bool controlFocus: false; // True if one of the ordinate controls has focus.
property var controlFocusControl: undefined
signal valueChanged();
function setControlFocus() {
if (controlFocusControl) {
controlFocusControl.focus = true;
// The controlFocus value is updated via onFocusChanged.
}
}
function setFocus(control, focus) {
if (focus) {
controlFocusControl = control;
setControlFocusTrue.start(); // After any subsequent false from previous control.
} else {
controlFocus = false;
}
}
Timer {
id: setControlFocusTrue
interval: 50
repeat: false
running: false
onTriggered: {
controlFocus = true;
}
}
HifiConstants { id: hifi }
HifiControls.SpinBox {
@ -38,6 +66,7 @@ Item {
root.valueChanged();
}
}
onFocusChanged: setFocus(this, focus);
}
HifiControls.SpinBox {
@ -58,6 +87,7 @@ Item {
root.valueChanged();
}
}
onFocusChanged: setFocus(this, focus);
}
HifiControls.SpinBox {
@ -78,6 +108,6 @@ Item {
root.valueChanged();
}
}
onFocusChanged: setFocus(this, focus);
}
}

View file

@ -0,0 +1,260 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs
import QtQuick.Controls.Styles 1.4
import "../../../styles-uit"
import "../../../controls-uit" as HifiControls
import "../../../windows"
import "../attachments"
Item {
id: content
readonly property var originalAttachments: MyAvatar.getAttachmentsVariant();
property var attachments: [];
Component.onCompleted: {
for (var i = 0; i < originalAttachments.length; ++i) {
var attachment = originalAttachments[i];
content.attachments.push(attachment);
listView.model.append({});
}
}
Column {
width: pane.width
Rectangle {
width: parent.width
height: root.height - (keyboardEnabled && keyboardRaised ? 200 : 0)
color: hifi.colors.baseGray
Rectangle {
id: attachmentsBackground
anchors {
left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top;
margins: hifi.dimensions.contentMargin.x
bottomMargin: hifi.dimensions.contentSpacing.y
}
color: hifi.colors.baseGrayShadow
radius: 4
ListView {
id: listView
anchors {
top: parent.top
left: parent.left
right: scrollBar.left
bottom: parent.bottom
margins: 4
}
clip: true
snapMode: ListView.SnapToItem
model: ListModel {}
delegate: Item {
id: attachmentDelegate
implicitHeight: attachmentView.height + 8;
implicitWidth: attachmentView.width
MouseArea {
// User can click on whitespace to select item.
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
listView.currentIndex = index;
attachmentsBackground.forceActiveFocus(); // Unfocus from any control.
mouse.accepted = false;
}
}
Attachment {
id: attachmentView
width: listView.width
attachment: content.attachments[index]
onSelectAttachment: {
listView.currentIndex = index;
}
onDeleteAttachment: {
attachments.splice(index, 1);
listView.model.remove(index, 1);
}
onUpdateAttachment: MyAvatar.setAttachmentsVariant(attachments);
}
}
onCountChanged: MyAvatar.setAttachmentsVariant(attachments);
/*
// DEBUG
highlight: Rectangle { color: "#40ffff00" }
highlightFollowsCurrentItem: true
*/
onHeightChanged: {
// Keyboard has been raised / lowered.
positionViewAtIndex(listView.currentIndex, ListView.SnapPosition);
}
onCurrentIndexChanged: {
if (!yScrollTimer.running) {
scrollSlider.y = currentIndex * (scrollBar.height - scrollSlider.height) / (listView.count - 1);
}
}
onContentYChanged: {
// User may have dragged content up/down.
yScrollTimer.restart();
}
Timer {
id: yScrollTimer
interval: 200
repeat: false
running: false
onTriggered: {
var index = (listView.count - 1) * listView.contentY / (listView.contentHeight - scrollBar.height);
index = Math.round(index);
listView.currentIndex = index;
scrollSlider.y = index * (scrollBar.height - scrollSlider.height) / (listView.count - 1);
}
}
}
Rectangle {
id: scrollBar
property bool scrolling: listView.contentHeight > listView.height
anchors {
top: parent.top
right: parent.right
bottom: parent.bottom
topMargin: 4
bottomMargin: 4
}
width: scrolling ? 18 : 0
radius: attachmentsBackground.radius
color: hifi.colors.baseGrayShadow
MouseArea {
anchors.fill: parent
onClicked: {
var index = listView.currentIndex;
index = index + (mouse.y <= scrollSlider.y ? -1 : 1);
if (index < 0) {
index = 0;
}
if (index > listView.count - 1) {
index = listView.count - 1;
}
listView.currentIndex = index;
}
}
Rectangle {
id: scrollSlider
anchors {
right: parent.right
rightMargin: 3
}
width: 16
height: (listView.height / listView.contentHeight) * listView.height
radius: width / 2
color: hifi.colors.lightGray
visible: scrollBar.scrolling;
onYChanged: {
var index = y * (listView.count - 1) / (scrollBar.height - scrollSlider.height);
index = Math.round(index);
listView.currentIndex = index;
}
MouseArea {
anchors.fill: parent
drag.target: scrollSlider
drag.axis: Drag.YAxis
drag.minimumY: 0
drag.maximumY: scrollBar.height - scrollSlider.height
}
}
}
}
HifiControls.Button {
id: newAttachmentButton
anchors {
left: parent.left
right: parent.right
bottom: buttonRow.top
margins: hifi.dimensions.contentMargin.x;
topMargin: hifi.dimensions.contentSpacing.y
bottomMargin: hifi.dimensions.contentSpacing.y
}
text: "New Attachment"
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
onClicked: {
var template = {
modelUrl: "",
translation: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
scale: 1,
jointName: MyAvatar.jointNames[0],
soft: false
};
attachments.push(template);
listView.model.append({});
MyAvatar.setAttachmentsVariant(attachments);
}
}
Row {
id: buttonRow
spacing: 8
anchors {
right: parent.right
bottom: parent.bottom
margins: hifi.dimensions.contentMargin.x
topMargin: hifi.dimensions.contentSpacing.y
bottomMargin: hifi.dimensions.contentSpacing.y
}
HifiControls.Button {
action: okAction
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
}
HifiControls.Button {
action: cancelAction
color: hifi.buttons.black
colorScheme: hifi.colorSchemes.dark
}
}
Action {
id: cancelAction
text: "Cancel"
onTriggered: {
MyAvatar.setAttachmentsVariant(originalAttachments);
closeDialog();
}
}
Action {
id: okAction
text: "OK"
onTriggered: {
for (var i = 0; i < attachments.length; ++i) {
console.log("Attachment " + i + ": " + attachments[i]);
}
MyAvatar.setAttachmentsVariant(attachments);
closeDialog();
}
}
}
}
}

View file

@ -0,0 +1,64 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import "../../../controls-uit" as HifiControls
Column {
width: pane.contentWidth
Rectangle {
width: parent.width
height: root.height - (keyboardEnabled && keyboardRaised ? 200 : 0)
color: hifi.colors.baseGray
HifiControls.TextField {
id: filterEdit
anchors { left: parent.left; right: parent.right; top: parent.top ; margins: 8}
placeholderText: "filter"
onTextChanged: tableView.model.filter = text
colorScheme: hifi.colorSchemes.dark
}
HifiControls.AttachmentsTable {
id: tableView
anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; bottom: buttonRow.top; margins: 8; }
colorScheme: hifi.colorSchemes.dark
onCurrentRowChanged: {
if (currentRow == -1) {
root.result = null;
return;
}
result = model.baseUrl + "/" + model.get(tableView.currentRow).key;
}
}
Row {
id: buttonRow
spacing: 8
anchors { right: parent.right; rightMargin: 8; bottom: parent.bottom; bottomMargin: 8; }
HifiControls.Button { action: acceptAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
HifiControls.Button { action: cancelAction ; color: hifi.buttons.black; colorScheme: hifi.colorSchemes.dark }
}
Action {
id: acceptAction
text: qsTr("OK")
enabled: root.result ? true : false
shortcut: Qt.Key_Return
onTriggered: {
root.selected(root.result);
root.destroy();
}
}
Action {
id: cancelAction
text: qsTr("Cancel")
shortcut: Qt.Key_Escape
onTriggered: {
root.canceled();
root.destroy();
}
}
}
}

View file

@ -107,7 +107,7 @@ Rectangle {
font.pixelSize: 12
}
TabletComboBox {
ComboBox {
id: collisionType
width: 200
z: 100

View file

@ -0,0 +1,105 @@
//
// TabletAttachmentsDialog.qml
//
// Created by David Rowe on 9 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import "../../controls-uit" as HifiControls
import "../../styles-uit"
import "../dialogs/content"
Item {
id: root
objectName: "AttachmentsDialog"
property string title: "Avatar Attachments"
property bool keyboardEnabled: false
property bool keyboardRaised: false
property bool punctuationMode: false
property var eventBridge;
signal sendToScript(var message);
anchors.fill: parent
HifiConstants { id: hifi }
Rectangle {
id: pane // Surrogate for ScrollingWindow's pane.
anchors.fill: parent
}
function closeDialog() {
Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen();
}
anchors.topMargin: hifi.dimensions.tabletMenuHeader // Space for header.
HifiControls.TabletHeader {
id: header
title: root.title
anchors {
left: parent.left
right: parent.right
bottom: parent.top
}
}
AttachmentsContent {
id: attachments
anchors {
top: header.bottom
left: parent.left
right: parent.right
bottom: keyboard.top
}
MouseArea {
// Defocuses any current control so that the keyboard gets hidden.
id: defocuser
anchors.fill: parent
propagateComposedEvents: true
acceptedButtons: Qt.AllButtons
onPressed: {
parent.forceActiveFocus();
mouse.accepted = false;
}
}
}
HifiControls.Keyboard {
id: keyboard
raised: parent.keyboardEnabled && parent.keyboardRaised
numeric: parent.punctuationMode
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
}
MouseArea {
id: activator
anchors.fill: parent
propagateComposedEvents: true
enabled: true
acceptedButtons: Qt.AllButtons
onPressed: {
mouse.accepted = false;
}
}
Component.onCompleted: {
keyboardEnabled = HMD.active;
}
}

View file

@ -0,0 +1,87 @@
//
// TabletModelBrowserDialog.qml
//
// Created by David Rowe on 11 Mar 2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
import QtQuick.Controls 1.4
import "../../controls-uit" as HifiControls
import "../../styles-uit"
import "../dialogs/content"
Item {
id: root
objectName: "ModelBrowserDialog"
property string title: "Attachment Model"
property var result
signal selected(var modelUrl)
signal canceled()
property bool keyboardEnabled: false
property bool keyboardRaised: false
property bool punctuationMode: false
anchors.fill: parent
Rectangle {
id: pane // Surrogate for ScrollingWindow's pane.
anchors.fill: parent
}
anchors.topMargin: hifi.dimensions.tabletMenuHeader // Space for header.
HifiControls.TabletHeader {
id: header
title: parent.title
anchors {
left: parent.left
right: parent.right
bottom: parent.top
}
}
ModelBrowserContent {
anchors {
top: header.bottom
left: parent.left
right: parent.right
bottom: keyboard.top
}
}
HifiControls.Keyboard {
id: keyboard
raised: parent.keyboardEnabled && parent.keyboardRaised
numeric: parent.punctuationMode
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
}
MouseArea {
id: activator
anchors.fill: parent
propagateComposedEvents: true
enabled: true
acceptedButtons: Qt.AllButtons
onPressed: {
mouse.accepted = false;
}
}
Component.onCompleted: {
keyboardEnabled = HMD.active;
}
}

View file

@ -145,7 +145,7 @@ Item {
}
}
TabletComboBox {
ComboBox {
id: pathSelector
anchors {
top: parent.top

View file

@ -31,7 +31,6 @@ Item {
property bool keyboardEnabled: false
property bool keyboardRaised: false
property bool punctuationMode: false
property var tablet;
@ -59,25 +58,15 @@ Item {
Tablet.getTablet("com.highfidelity.interface.tablet.system").gotoHomeScreen();
}
Rectangle {
HifiControls.TabletHeader {
id: header
height: 90
title: parent.title
anchors {
top: parent.top
left: parent.left
right: parent.right
}
z: 100
color: hifi.colors.darkGray
RalewayBold {
text: title
size: 26
color: hifi.colors.white
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: hifi.dimensions.contentMargin.x
}
}
Rectangle {
@ -90,7 +79,7 @@ Item {
}
color: hifi.colors.baseGray
Flickable {
id: scrollView
width: parent.width
@ -184,7 +173,7 @@ Item {
left: parent.left
right: parent.right
}
color: hifi.colors.baseGray
Row {

View file

@ -171,10 +171,10 @@ Menu::Menu() {
// Avatar > Attachments...
auto action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments);
connect(action, &QAction::triggered, [] {
DependencyManager::get<OffscreenUi>()->show(QString("hifi/dialogs/AttachmentsDialog.qml"), "AttachmentsDialog");
qApp->showDialog(QString("hifi/dialogs/AttachmentsDialog.qml"),
QString("../../hifi/tablet/TabletAttachmentsDialog.qml"), "AttachmentsDialog");
});
// Avatar > Size
MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size");

View file

@ -180,6 +180,7 @@ void Web3DOverlay::loadSourceURL() {
_webSurface->getRootContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
_webSurface->getRootContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
_webSurface->getRootContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getRootContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
_webSurface->getRootContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
_webSurface->getRootContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());