Merge pull request #9343 from druiz17/menuApp

Moved the context menu to the tablet
This commit is contained in:
Anthony Thibault 2017-01-10 13:34:44 -08:00 committed by GitHub
commit e7a88b5a3c
13 changed files with 118 additions and 84 deletions

View file

@ -12,7 +12,6 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import "../dialogs"
import "../menus"
import "../js/Utils.js" as Utils
// This is our primary 'desktop' object to which all VR dialogs and windows are childed.
@ -465,32 +464,7 @@ FocusScope {
Component { id: fileDialogBuilder; FileDialog { } }
function fileDialog(properties) {
return fileDialogBuilder.createObject(desktop, properties);
}
MenuMouseHandler { id: menuPopperUpper }
function popupMenu(point) {
menuPopperUpper.popup(desktop, rootMenu.items, point);
}
function toggleMenu(point) {
menuPopperUpper.toggle(desktop, rootMenu.items, point);
}
Keys.onEscapePressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
Keys.onLeftPressed: {
if (menuPopperUpper.closeLastMenu()) {
event.accepted = true;
return;
}
event.accepted = false;
}
}
function unfocusWindows() {
// First find the active focus item, and unfocus it, all the way

View file

@ -0,0 +1,27 @@
import QtQuick 2.5
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.4
import QtQml 2.2
import "."
Item {
id: tabletMenu
objectName: "tabletMenu"
width: parent.width
height: parent.height
property var rootMenu: Menu { objectName:"rootMenu" }
property var point: Qt.point(50, 50)
TabletMouseHandler { id: menuPopperUpper }
function setRootMenu(menu) {
tabletMenu.rootMenu = menu
buildMenu()
}
function buildMenu() {
menuPopperUpper.popup(tabletMenu, rootMenu.items)
}
}

View file

@ -12,8 +12,8 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../controls-uit"
import "../styles-uit"
import "../../controls-uit"
import "../../styles-uit"
Item {
id: root

View file

@ -12,7 +12,7 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import "../styles-uit"
import "../../styles-uit"
FocusScope {
id: root
@ -38,8 +38,8 @@ FocusScope {
ListView {
id: listView
x: 8; y: 8
width: 128
height: count * 32
width: parent.width
height: parent.height
topMargin: hifi.dimensions.menuPadding.y
onEnabledChanged: recalcSize();
onVisibleChanged: recalcSize();
@ -57,7 +57,7 @@ FocusScope {
color: hifi.colors.white
}
delegate: VrMenuItem {
delegate: TabletMenuItem {
text: name
source: item
onImplicitHeightChanged: listView.recalcSize()

View file

@ -16,11 +16,11 @@ import "."
Item {
id: root
anchors.fill: parent
objectName: "MouseMenuHandlerItem"
objectName: "tabletMenuHandlerItem"
MouseArea {
id: menuRoot;
objectName: "MouseMenuHandlerMouseArea"
objectName: "tabletMenuHandlerMouseArea"
anchors.fill: parent
enabled: d.topMenu !== null
onClicked: {
@ -34,7 +34,7 @@ Item {
property var topMenu: null;
property var modelMaker: Component { ListModel { } }
property var menuViewMaker: Component {
VrMenuView {
TabletMenuView {
id: subMenu
onSelected: d.handleSelection(subMenu, currentItem, item)
}
@ -54,10 +54,11 @@ Item {
}
function toModel(items) {
var result = modelMaker.createObject(desktop);
var result = modelMaker.createObject(tabletMenu);
for (var i = 0; i < items.length; ++i) {
var item = items[i];
if (!item.visible) continue;
console.log(item.title)
switch (item.type) {
case MenuItemType.Menu:
result.append({"name": item.title, "item": item})
@ -82,7 +83,7 @@ Item {
topMenu.focus = true;
} else {
topMenu = null;
offscreenFlags.navigationFocused = false;
//offscreenFlags.navigationFocused = false;
menuRoot.enabled = false;
}
}
@ -91,7 +92,7 @@ Item {
menuStack.push(newMenu);
topMenu = newMenu;
topMenu.focus = true;
offscreenFlags.navigationFocused = true;
//offscreenFlags.navigationFocused = true;
}
function clearMenus() {
@ -118,12 +119,7 @@ Item {
function buildMenu(items, targetPosition) {
var model = toModel(items);
// Menus must be childed to desktop for Z-ordering
var newMenu = menuViewMaker.createObject(desktop, { model: model, z: topMenu ? topMenu.z + 1 : desktop.zLevels.menu, isSubMenu: topMenu !== null });
if (targetPosition) {
newMenu.x = targetPosition.x
newMenu.y = targetPosition.y - newMenu.height / 3 * 1
}
clampMenuPosition(newMenu);
var newMenu = menuViewMaker.createObject(tabletMenu, { model: model, isSubMenu: topMenu !== null });
pushMenu(newMenu);
return newMenu;
}
@ -150,20 +146,12 @@ Item {
}
function popup(parent, items, point) {
function popup(parent, items) {
d.clearMenus();
menuRoot.enabled = true;
d.buildMenu(items, point);
}
function toggle(parent, items, point) {
if (d.topMenu) {
d.clearMenus();
return;
}
popup(parent, items, point);
}
function closeLastMenu() {
if (d.menuStack.length) {
d.popMenu();

View file

@ -1059,10 +1059,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
DependencyManager::get<AudioClient>()->toggleMute();
} else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) {
cycleCamera();
} else if (action == controller::toInt(controller::Action::UI_NAV_SELECT)) {
if (!offscreenUi->navigationFocused()) {
toggleMenuUnderReticle();
}
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
toggleTabletUI();
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
@ -1580,17 +1576,6 @@ QString Application::getUserAgent() {
return userAgent;
}
void Application::toggleMenuUnderReticle() const {
// In HMD, if the menu is near the mouse but not under it, the reticle can be at a significantly
// different depth. When you focus on the menu, the cursor can appear to your crossed eyes as both
// on the menu and off.
// Even in 2D, it is arguable whether the user would want the menu to be to the side.
const float X_LEFT_SHIFT = 50.0;
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto reticlePosition = getApplicationCompositor().getReticlePosition();
offscreenUi->toggleMenu(QPoint(reticlePosition.x - X_LEFT_SHIFT, reticlePosition.y));
}
uint64_t lastTabletUIToggle { 0 };
const uint64_t toggleTabletUILockout { 500000 };
void Application::toggleTabletUI() const {
@ -2931,10 +2916,6 @@ void Application::keyPressEvent(QKeyEvent* event) {
void Application::keyReleaseEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) {
toggleMenuUnderReticle();
}
_keysPressed.remove(event->key());
_controllerScriptingInterface->emitKeyReleaseEvent(event); // send events to any registered scripts

View file

@ -484,7 +484,6 @@ private:
static void dragEnterEvent(QDragEnterEvent* event);
void maybeToggleMenuVisible(QMouseEvent* event) const;
void toggleMenuUnderReticle() const;
void toggleTabletUI() const;
MainWindow* _window;

View file

@ -14,6 +14,8 @@
#include <PathUtils.h>
#include <RegisteredMetaTypes.h>
#include "ScriptEngineLogging.h"
#include "DependencyManager.h"
#include "OffscreenUi.h"
TabletScriptingInterface::TabletScriptingInterface() {
qmlRegisterType<SoundEffect>("Hifi", 1, 0, "SoundEffect");
@ -56,6 +58,7 @@ void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qm
static const char* TABLET_SOURCE_URL = "Tablet.qml";
static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml";
static const char* LOADER_SOURCE_PROPERTY_NAME = "LoaderSource";
static const char* VRMENU_SOURCE_URL = "TabletMenu.qml";
TabletProxy::TabletProxy(QString name) : _name(name) {
;
@ -95,6 +98,15 @@ void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscr
}
}
void TabletProxy::gotoMenuScreen() {
if (_qmlTabletRoot) {
_qmlTabletRoot->setProperty(LOADER_SOURCE_PROPERTY_NAME, VRMENU_SOURCE_URL);
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToMenuScreen()));
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(VRMENU_SOURCE_URL)));
}
}
void TabletProxy::gotoHomeScreen() {
if (_qmlTabletRoot) {
QString tabletSource = _qmlTabletRoot->property(LOADER_SOURCE_PROPERTY_NAME).toString();
@ -160,7 +172,7 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) {
void TabletProxy::updateAudioBar(const double micLevel) {
auto tablet = getQmlTablet();
if (!tablet) {
qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
//qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
} else {
QMetaObject::invokeMethod(tablet, "setMicLevel", Qt::AutoConnection, Q_ARG(QVariant, QVariant(micLevel)));
}
@ -186,6 +198,27 @@ void TabletProxy::addButtonsToHomeScreen() {
QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
}
void TabletProxy::addButtonsToMenuScreen() {
if (!_qmlTabletRoot) {
return;
}
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
if (!loader) {
return;
}
QQuickItem* VrMenu = loader->findChild<QQuickItem*>("tabletMenu");
if (!VrMenu) {
qDebug() << "----------> could not find vr menu";
return;
}
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QObject* menu = offscreenUi->getRootMenu();
QMetaObject::invokeMethod(VrMenu, "setRootMenu", Qt::AutoConnection, Q_ARG(QVariant, QVariant::fromValue(menu)));
}
void TabletProxy::removeButtonsFromHomeScreen() {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
for (auto& buttonProxy : _tabletButtonProxies) {

View file

@ -65,6 +65,8 @@ public:
void setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface);
Q_INVOKABLE void gotoMenuScreen();
/**jsdoc
* transition to the home screen
* @function TabletProxy#gotoHomeScreen
@ -120,6 +122,7 @@ signals:
private slots:
void addButtonsToHomeScreen();
void addButtonsToMenuScreen();
protected:
void removeButtonsFromHomeScreen();
QQuickItem* getQmlTablet() const;

View file

@ -524,6 +524,10 @@ QQuickItem* OffscreenUi::getDesktop() {
return _desktop;
}
QObject* OffscreenUi::getRootMenu() {
return getRootItem()->findChild<QObject*>("rootMenu");
}
QQuickItem* OffscreenUi::getToolWindow() {
return _toolWindow;
}
@ -533,11 +537,6 @@ void OffscreenUi::unfocusWindows() {
Q_ASSERT(invokeResult);
}
void OffscreenUi::toggleMenu(const QPoint& screenPosition) { // caller should already have mapped using getReticlePosition
emit showDesktop(); // we really only want to do this if you're showing the menu, but for now this works
QMetaObject::invokeMethod(_desktop, "toggleMenu", Q_ARG(QVariant, screenPosition));
}
class FileDialogListener : public ModalDialogListener {
Q_OBJECT

View file

@ -45,12 +45,11 @@ public:
bool navigationFocused();
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();
void setConstrainToolbarToCenterX(bool constrained);
@ -59,7 +58,7 @@ public:
QObject* getFlags();
QQuickItem* getDesktop();
QQuickItem* getToolWindow();
QObject* getRootMenu();
enum Icon {
ICON_NONE = 0,
ICON_QUESTION,

View file

@ -35,7 +35,8 @@ var DEFAULT_SCRIPTS = [
"system/snapshot.js",
"system/help.js",
"system/bubble.js",
"system/tablet-ui/tabletUI.js"
"system/tablet-ui/tabletUI.js",
"system/menu.js"
];
// add a menu item for debugging

30
scripts/system/menu.js Normal file
View file

@ -0,0 +1,30 @@
//
// menu.js
// scripts/system/
//
// Created by Dante Ruiz on 5 Jun 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
//
(function() {
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
icon: "icons/tablet-icons/menu-i.svg",
text: "Menu"
});
function onClicked() {
tablet.gotoMenuScreen();
}
button.clicked.connect(onClicked);
Script.scriptEnding.connect(function () {
button.clicked.disconnect(onClicked);
tablet.removeButton(button);
})
}());