Merge pull request #9219 from hyperlogic/tablet-ui

Can now remove and edit buttons on the Tablet
This commit is contained in:
Anthony Thibault 2016-12-16 10:46:05 -08:00 committed by GitHub
commit c6d7894f52
6 changed files with 129 additions and 44 deletions

View file

@ -10,25 +10,42 @@ Item {
width: 480 width: 480
height: 720 height: 720
// used to look up a button by its uuid
function findButtonIndex(uuid) {
if (!uuid) {
return -1;
}
for (var i in flowMain.children) {
var child = flowMain.children[i];
if (child.uuid === uuid) {
return i;
}
}
return -1;
}
// called by C++ code when a button should be added to the tablet // called by C++ code when a button should be added to the tablet
function addButtonProxy(properties) { function addButtonProxy(properties) {
var component = Qt.createComponent("TabletButton.qml"); var component = Qt.createComponent("TabletButton.qml");
var button = component.createObject(flowMain); var button = component.createObject(flowMain);
if (properties.icon) {
button.icon = properties.icon; // copy all properites to button
} var keys = Object.keys(properties).forEach(function (key) {
if (properties.color) { button[key] = properties[key];
button.color = properties.color; });
}
if (properties.text) {
button.text = properties.text;
}
return button; return button;
} }
// called by C++ code when a button should be removed from the tablet // called by C++ code when a button should be removed from the tablet
function removeButtonProxy(properties) { function removeButtonProxy(properties) {
console.log("TABLET_UI_HACK: removeButtonProxy, NOT IMPLEMENTED!, properties = " + JSON.stringify(properties)); var index = findButtonIndex(properties.uuid);
if (index < 0) {
console.log("Warning: Tablet.qml could not find button with uuid = " + properties.uuid);
} else {
flowMain.children[index].destroy();
}
} }
Rectangle { Rectangle {

View file

@ -6,11 +6,16 @@ Item {
property string color: "#1080B8" property string color: "#1080B8"
property string text: "EDIT" property string text: "EDIT"
property string icon: "icons/edit-icon.svg" property string icon: "icons/edit-icon.svg"
property var uuid;
width: 132 width: 132
height: 132 height: 132
signal clicked() signal clicked()
function changeProperty(key, value) {
tabletButton[key] = value;
}
Rectangle { Rectangle {
id: buttonBg id: buttonBg
color: tabletButton.color color: tabletButton.color

View file

@ -361,6 +361,13 @@ void RenderableWebEntityItem::destroyWebSurface() {
--_currentWebCount; --_currentWebCount;
QQuickItem* rootItem = _webSurface->getRootItem(); QQuickItem* rootItem = _webSurface->getRootItem();
// TABLET_UI_HACK: move this to overlays as well!
if (rootItem && rootItem->objectName() == "tablet") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
tabletScriptingInterface->setQmlTablet("com.highfidelity.interface.tablet.system", nullptr);
}
if (rootItem) { if (rootItem) {
QObject* obj = rootItem->findChild<QObject*>("webEngineView"); QObject* obj = rootItem->findChild<QObject*>("webEngineView");
if (obj) { if (obj) {

View file

@ -12,7 +12,7 @@
QObject* TabletScriptingInterface::getTablet(const QString& tabletId) { QObject* TabletScriptingInterface::getTablet(const QString& tabletId) {
std::lock_guard<std::mutex> guard(_tabletProxiesMutex); std::lock_guard<std::mutex> guard(_mutex);
// look up tabletId in the map. // look up tabletId in the map.
auto iter = _tabletProxies.find(tabletId); auto iter = _tabletProxies.find(tabletId);
@ -36,7 +36,6 @@ void TabletScriptingInterface::setQmlTablet(QString tabletId, QQuickItem* qmlTab
} }
} }
// //
// TabletProxy // TabletProxy
// //
@ -64,24 +63,27 @@ static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy*
return; return;
} }
QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot())); QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot()));
buttonProxy->setQmlButton(qobject_cast<QQuickItem*>(qmlButton));
} }
void TabletProxy::setQmlTablet(QQuickItem* qmlTablet) { void TabletProxy::setQmlTablet(QQuickItem* qmlTablet) {
std::lock_guard<std::mutex> guard(_mutex);
if (qmlTablet) { if (qmlTablet) {
_qmlTablet = qmlTablet; _qmlTablet = qmlTablet;
std::lock_guard<std::mutex> guard(_tabletButtonProxiesMutex);
for (auto& buttonProxy : _tabletButtonProxies) { for (auto& buttonProxy : _tabletButtonProxies) {
addButtonProxyToQmlTablet(_qmlTablet, buttonProxy.data()); addButtonProxyToQmlTablet(_qmlTablet, buttonProxy.data());
} }
} else { } else {
for (auto& buttonProxy : _tabletButtonProxies) {
buttonProxy->setQmlButton(nullptr);
}
_qmlTablet = nullptr; _qmlTablet = nullptr;
} }
} }
QObject* TabletProxy::addButton(const QVariant& properties) { QObject* TabletProxy::addButton(const QVariant& properties) {
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
std::lock_guard<std::mutex> guard(_tabletButtonProxiesMutex); std::lock_guard<std::mutex> guard(_mutex);
_tabletButtonProxies.push_back(tabletButtonProxy); _tabletButtonProxies.push_back(tabletButtonProxy);
if (_qmlTablet) { if (_qmlTablet) {
addButtonProxyToQmlTablet(_qmlTablet, tabletButtonProxy.data()); addButtonProxyToQmlTablet(_qmlTablet, tabletButtonProxy.data());
@ -90,11 +92,12 @@ QObject* TabletProxy::addButton(const QVariant& properties) {
} }
void TabletProxy::removeButton(QObject* tabletButtonProxy) { void TabletProxy::removeButton(QObject* tabletButtonProxy) {
std::lock_guard<std::mutex> guard(_tabletButtonProxiesMutex); std::lock_guard<std::mutex> guard(_mutex);
auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy);
if (iter != _tabletButtonProxies.end()) { if (iter != _tabletButtonProxies.end()) {
if (_qmlTablet) { if (_qmlTablet) {
QMetaObject::invokeMethod(_qmlTablet, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); (*iter)->setQmlButton(nullptr);
QMetaObject::invokeMethod(_qmlTablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties()));
} }
_tabletButtonProxies.erase(iter); _tabletButtonProxies.erase(iter);
} else { } else {
@ -106,28 +109,33 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) {
// TabletButtonProxy // TabletButtonProxy
// //
TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : _properties(properties) { const QString UUID_KEY = "uuid";
;
TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : _uuid(QUuid::createUuid()), _properties(properties) {
// this is used to uniquely identify this button.
_properties[UUID_KEY] = _uuid;
} }
void TabletButtonProxy::setInitRequestHandler(const QScriptValue& handler) { void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) {
_initRequestHandler = handler; std::lock_guard<std::mutex> guard(_mutex);
_qmlButton = qmlButton;
} }
// TABLET_UI_HACK remove QVariantMap TabletButtonProxy::getProperties() const {
/* std::lock_guard<std::mutex> guard(_mutex);
static QString IMAGE_URL_KEY = "imageUrl"; return _properties;
static QString IMAGE_URL_DEFAULT = "";
QString TabletButtonProxy::getImageUrl() const {
std::lock_guard<std::mutex> guard(_propertiesMutex);
return _properties.value(IMAGE_URL_KEY, IMAGE_URL_DEFAULT).toString();
} }
void TabletButtonProxy::setImageUrl(QString imageUrl) { void TabletButtonProxy::editProperties(QVariantMap properties) {
std::lock_guard<std::mutex> guard(_propertiesMutex); std::lock_guard<std::mutex> guard(_mutex);
_properties[IMAGE_URL_KEY] = imageUrl; QVariantMap::const_iterator iter = properties.constBegin();
while (iter != properties.constEnd()) {
_properties[iter.key()] = iter.value();
if (_qmlButton) {
QMetaObject::invokeMethod(_qmlButton, "changeProperty", Qt::AutoConnection, Q_ARG(QVariant, QVariant(iter.key())), Q_ARG(QVariant, iter.value()));
}
++iter;
}
} }
*/
#include "TabletScriptingInterface.moc" #include "TabletScriptingInterface.moc"

View file

@ -11,10 +11,11 @@
#include <mutex> #include <mutex>
#include <QtCore/QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include <QScriptValue> #include <QScriptValue>
#include <QQuickItem> #include <QQuickItem>
#include <QUuid>
#include <DependencyManager.h> #include <DependencyManager.h>
@ -39,7 +40,7 @@ public:
void setQmlTablet(QString tabletId, QQuickItem* qmlTablet); void setQmlTablet(QString tabletId, QQuickItem* qmlTablet);
protected: protected:
std::mutex _tabletProxiesMutex; std::mutex _mutex;
std::map<QString, QSharedPointer<TabletProxy>> _tabletProxies; std::map<QString, QSharedPointer<TabletProxy>> _tabletProxies;
}; };
@ -73,7 +74,7 @@ public:
QString getName() const { return _name; } QString getName() const { return _name; }
protected: protected:
QString _name; QString _name;
std::mutex _tabletButtonProxiesMutex; std::mutex _mutex;
std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies; std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
QQuickItem* _qmlTablet { nullptr }; QQuickItem* _qmlTablet { nullptr };
}; };
@ -87,13 +88,21 @@ class TabletButtonProxy : public QObject {
public: public:
TabletButtonProxy(const QVariantMap& properties); TabletButtonProxy(const QVariantMap& properties);
/**jsdoc void setQmlButton(QQuickItem* qmlButton);
* @function TabletButtonProxy#setInitRequestHandler
* @param handler {Function} A function used by the system to request the current button state from JavaScript.
*/
Q_INVOKABLE void setInitRequestHandler(const QScriptValue& handler);
const QVariantMap& getProperties() const { return _properties; } /**jsdoc
* Returns the current value of this button's properties
* @function TabletButtonProxy#getProperties
* @returns {object}
*/
Q_INVOKABLE QVariantMap getProperties() const;
/**jsdoc
* Replace the values of some of this button's properties
* @function TabletButtonProxy#editProperties
* @param properties {object} set of properties to change
*/
Q_INVOKABLE void editProperties(QVariantMap properties);
public slots: public slots:
void clickedSlot() { emit clicked(); } void clickedSlot() { emit clicked(); }
@ -107,9 +116,10 @@ signals:
void clicked(); void clicked();
protected: protected:
mutable std::mutex _propertiesMutex; QUuid _uuid;
mutable std::mutex _mutex;
QQuickItem* _qmlButton { nullptr };
QVariantMap _properties; QVariantMap _properties;
QScriptValue _initRequestHandler;
}; };
#endif // hifi_TabletScriptingInterface_h #endif // hifi_TabletScriptingInterface_h

View file

@ -0,0 +1,38 @@
//
// tabletTest.js
//
// Created by Anthony J. Thibault on 2016-12-15
// 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
//
// Adds a BAM! button to the tablet ui.
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
icon: "https://s3.amazonaws.com/hifi-public/tony/icons/hat-up.svg",
color: "#ff6f6f",
text: "BAM!!!"
});
// change the color and name every second...
var colors = ["#ff6f6f", "#6fff6f", "#6f6fff"];
var names = ["BAM!", "BAM!!", "BAM!!!"];
var colorIndex = 0;
Script.setInterval(function () {
colorIndex = (colorIndex + 1) % colors.length;
button.editProperties({
color: colors[colorIndex],
text: names[colorIndex]
});
}, 1000);
button.clicked.connect(function () {
print("AJT: BAMM!!! CLICK from JS!");
});
Script.scriptEnding.connect(function () {
tablet.removeButton(button);
});