Merge pull request #9319 from howard-stearns/edit-button-to-select-in-pal

Edit button to select in pal
This commit is contained in:
Howard Stearns 2017-01-06 13:17:29 -08:00 committed by GitHub
commit 36c99a604b
7 changed files with 128 additions and 103 deletions

View file

@ -0,0 +1,52 @@
//
// LetterboxMessage.qml
// qml/hifi
//
// Created by Zach Fox and Howard Stearns on 1/5/2017
// Copyright 2017 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 "../styles-uit"
Item {
property alias text: popupText.text
property real radius: hifi.dimensions.borderRadius
visible: false
id: letterbox
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.5
radius: radius
}
Rectangle {
width: Math.max(parent.width * 0.75, 400)
height: popupText.contentHeight*1.5
anchors.centerIn: parent
radius: radius
color: "white"
FiraSansSemiBold {
id: popupText
size: hifi.fontSizes.textFieldInput
color: hifi.colors.darkGray
horizontalAlignment: Text.AlignHCenter
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
wrapMode: Text.WordWrap
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
letterbox.visible = false
}
}
}

View file

@ -11,21 +11,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
/* TODO:
prototype:
- only show kick/mute when canKick
- margins everywhere
- column head centering
- column head font
- proper button .svg on toolbar
mvp:
- Show all participants, including ignored, and populate initial ignore/mute status.
- If name is elided, hover should scroll name left so the full name can be read.
*/
import QtQuick 2.5 import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import "../styles-uit" import "../styles-uit"
@ -326,6 +311,11 @@ Item {
visible: iAmAdmin visible: iAmAdmin
color: hifi.colors.lightGrayText color: hifi.colors.lightGrayText
} }
function letterbox(message) {
letterboxMessage.text = message;
letterboxMessage.visible = true
}
// This Rectangle refers to the [?] popup button next to "NAMES" // This Rectangle refers to the [?] popup button next to "NAMES"
Rectangle { Rectangle {
color: hifi.colors.tableBackgroundLight color: hifi.colors.tableBackgroundLight
@ -349,7 +339,9 @@ Item {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
hoverEnabled: true hoverEnabled: true
onClicked: namesPopup.visible = true onClicked: letterbox("Bold names in the list are Avatar Display Names.\n" +
"If a Display Name isn't set, a unique Session Display Name is assigned." +
"\n\nAdministrators of this domain can also see the Username or Machine ID associated with each avatar present.")
onEntered: helpText.color = hifi.colors.baseGrayHighlight onEntered: helpText.color = hifi.colors.baseGrayHighlight
onExited: helpText.color = hifi.colors.darkGray onExited: helpText.color = hifi.colors.darkGray
} }
@ -378,87 +370,14 @@ Item {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
hoverEnabled: true hoverEnabled: true
onClicked: adminPopup.visible = true onClicked: letterbox('Silencing a user mutes their microphone. Silenced users can unmute themselves by clicking the "UNMUTE" button on their HUD.\n\n' +
"Banning a user will remove them from this domain and prevent them from returning. You can un-ban users from your domain's settings page.)")
onEntered: adminHelpText.color = "#94132e" onEntered: adminHelpText.color = "#94132e"
onExited: adminHelpText.color = hifi.colors.redHighlight onExited: adminHelpText.color = hifi.colors.redHighlight
} }
} }
// Explanitory popup upon clicking "[?]" next to "NAMES" LetterboxMessage {
Item { id: letterboxMessage
visible: false
id: namesPopup
anchors.fill: pal
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.5
radius: hifi.dimensions.borderRadius
}
Rectangle {
width: Math.max(parent.width * 0.75, 400)
height: popupText.contentHeight*1.5
anchors.centerIn: parent
radius: hifi.dimensions.borderRadius
color: "white"
FiraSansSemiBold {
id: popupText
text: "Bold names in the list are Avatar Display Names.\n" +
"If a Display Name isn't set, a unique Session Display Name is assigned." +
"\n\nAdministrators of this domain can also see the Username or Machine ID associated with each avatar present."
size: hifi.fontSizes.textFieldInput
color: hifi.colors.darkGray
horizontalAlignment: Text.AlignHCenter
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
wrapMode: Text.WordWrap
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
namesPopup.visible = false
}
}
}
// Explanitory popup upon clicking "[?]" next to "ADMIN"
Item {
visible: false
id: adminPopup
anchors.fill: pal
Rectangle {
anchors.fill: parent
color: "black"
opacity: 0.5
radius: hifi.dimensions.borderRadius
}
Rectangle {
width: Math.max(parent.width * 0.75, 400)
height: adminPopupText.contentHeight*1.5
anchors.centerIn: parent
radius: hifi.dimensions.borderRadius
color: "white"
FiraSansSemiBold {
id: adminPopupText
text: 'Silencing a user mutes their microphone. Silenced users can unmute themselves by clicking the "UNMUTE" button on their HUD.\n\n' +
"Banning a user will remove them from this domain and prevent them from returning. You can un-ban users from your domain's settings page."
size: hifi.fontSizes.textFieldInput
color: hifi.colors.darkGray
horizontalAlignment: Text.AlignHCenter
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
wrapMode: Text.WordWrap
}
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked: {
adminPopup.visible = false
}
}
} }
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
@ -495,14 +414,20 @@ Item {
sortModel(); sortModel();
break; break;
case 'select': case 'select':
var sessionId = message.params[0]; var sessionIds = message.params[0];
var selected = message.params[1]; var selected = message.params[1];
var userIndex = findSessionIndex(sessionId); var userIndex = findSessionIndex(sessionIds[0]);
if (selected) { if (sessionIds.length > 1) {
table.selection.clear(); // for now, no multi-select letterbox('Only one user can be selected at a time.');
table.selection.select(userIndex); } else if (userIndex < 0) {
letterbox('The last editor is not among this list of users.');
} else { } else {
table.selection.deselect(userIndex); if (selected) {
table.selection.clear(); // for now, no multi-select
table.selection.select(userIndex);
} else {
table.selection.deselect(userIndex);
}
} }
break; break;
// Received an "updateUsername()" request from the JS // Received an "updateUsername()" request from the JS

View file

@ -25,6 +25,7 @@
<input type="button" id="visible" class="glyph" value="&#xe007;" /> <input type="button" id="visible" class="glyph" value="&#xe007;" />
</div> </div>
<input type="button" id="teleport" value="Jump To Selection" /> <input type="button" id="teleport" value="Jump To Selection" />
<input type="button" id="pal" class="glyph" value="&#xe00c;" />
<input type="button" class="red" id="delete" value="Delete" /> <input type="button" class="red" id="delete" value="Delete" />
</div> </div>
<div id="entity-list"> <div id="entity-list">
@ -94,4 +95,4 @@
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View file

@ -39,6 +39,7 @@ function loaded() {
elInView = document.getElementById("in-view") elInView = document.getElementById("in-view")
elRadius = document.getElementById("radius"); elRadius = document.getElementById("radius");
elTeleport = document.getElementById("teleport"); elTeleport = document.getElementById("teleport");
elPal = document.getElementById("pal");
elEntityTable = document.getElementById("entity-table"); elEntityTable = document.getElementById("entity-table");
elInfoToggle = document.getElementById("info-toggle"); elInfoToggle = document.getElementById("info-toggle");
elInfoToggleGlyph = elInfoToggle.firstChild; elInfoToggleGlyph = elInfoToggle.firstChild;
@ -274,6 +275,9 @@ function loaded() {
elTeleport.onclick = function () { elTeleport.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' })); EventBridge.emitWebEvent(JSON.stringify({ type: 'teleport' }));
} }
elPal.onclick = function () {
EventBridge.emitWebEvent(JSON.stringify({ type: 'pal' }));
}
elDelete.onclick = function() { elDelete.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
refreshEntities(); refreshEntities();

View file

@ -98,7 +98,6 @@ EntityListTool = function(opts) {
webView.emitScriptEvent(JSON.stringify(data)); webView.emitScriptEvent(JSON.stringify(data));
} }
webView.webEventReceived.connect(function(data) { webView.webEventReceived.connect(function(data) {
data = JSON.parse(data); data = JSON.parse(data);
if (data.type == "selectionUpdate") { if (data.type == "selectionUpdate") {
@ -120,6 +119,23 @@ EntityListTool = function(opts) {
if (selectionManager.hasSelection()) { if (selectionManager.hasSelection()) {
MyAvatar.position = selectionManager.worldPosition; MyAvatar.position = selectionManager.worldPosition;
} }
} else if (data.type == "pal") {
var sessionIds = {}; // Collect the sessionsIds of all selected entitities, w/o duplicates.
selectionManager.selections.forEach(function (id) {
var lastEditedBy = Entities.getEntityProperties(id, 'lastEditedBy').lastEditedBy;
if (lastEditedBy) {
sessionIds[lastEditedBy] = true;
}
});
var dedupped = Object.keys(sessionIds);
if (!selectionManager.selections.length) {
Window.alert('No objects selected.');
} else if (!dedupped.length) {
Window.alert('There were no recent users of the ' + selectionManager.selections.length + ' selected objects.');
} else {
// No need to subscribe if we're just sending.
Messages.sendMessage('com.highfidelity.pal', JSON.stringify({method: 'select', params: [dedupped, true]}), 'local');
}
} else if (data.type == "delete") { } else if (data.type == "delete") {
deleteSelectedEntities(); deleteSelectedEntities();
} else if (data.type == "toggleLocked") { } else if (data.type == "toggleLocked") {
@ -140,4 +156,4 @@ EntityListTool = function(opts) {
}); });
return that; return that;
}; };

View file

@ -321,7 +321,7 @@ function removeOverlays() {
function handleClick(pickRay) { function handleClick(pickRay) {
ExtendedOverlay.applyPickRay(pickRay, function (overlay) { ExtendedOverlay.applyPickRay(pickRay, function (overlay) {
// Don't select directly. Tell qml, who will give us back a list of ids. // Don't select directly. Tell qml, who will give us back a list of ids.
var message = {method: 'select', params: [overlay.key, !overlay.selected]}; var message = {method: 'select', params: [[overlay.key], !overlay.selected]};
pal.sendToQml(message); pal.sendToQml(message);
return true; return true;
}); });
@ -392,6 +392,31 @@ function onClicked() {
pal.setVisible(!pal.visible); pal.setVisible(!pal.visible);
} }
//
// Message from other scripts, such as edit.js
//
var CHANNEL = 'com.highfidelity.pal';
function receiveMessage(channel, messageString, senderID) {
if ((channel !== CHANNEL) ||
(senderID !== MyAvatar.sessionUUID)) {
return;
}
var message = JSON.parse(messageString);
switch (message.method) {
case 'select':
if (!pal.visible) {
onClicked();
}
pal.sendToQml(message); // Accepts objects, not just strings.
break;
default:
print('Unrecognized PAL message', messageString);
}
}
Messages.subscribe(CHANNEL);
Messages.messageReceived.connect(receiveMessage);
var AVERAGING_RATIO = 0.05; var AVERAGING_RATIO = 0.05;
var LOUDNESS_FLOOR = 11.0; var LOUDNESS_FLOOR = 11.0;
var LOUDNESS_SCALE = 2.8 / 5.0; var LOUDNESS_SCALE = 2.8 / 5.0;
@ -471,6 +496,8 @@ Script.scriptEnding.connect(function () {
Users.usernameFromIDReply.disconnect(usernameFromIDReply); Users.usernameFromIDReply.disconnect(usernameFromIDReply);
Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL); Window.domainChanged.disconnect(clearIgnoredInQMLAndClosePAL);
Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL); Window.domainConnectionRefused.disconnect(clearIgnoredInQMLAndClosePAL);
Messages.unsubscribe(CHANNEL);
Messages.messageReceived.disconnect(receiveMessage);
off(); off();
}); });