| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| /** |
| * @unrestricted |
| */ |
| export default class SensorsView extends UI.VBox { |
| constructor() { |
| super(true); |
| this.registerRequiredCSS('emulation/sensors.css'); |
| this.contentElement.classList.add('sensors-view'); |
| |
| this._geolocationSetting = Common.settings.createSetting('emulation.geolocationOverride', ''); |
| this._geolocation = SDK.EmulationModel.Geolocation.parseSetting(this._geolocationSetting.get()); |
| this._geolocationOverrideEnabled = false; |
| this._createGeolocationSection(this._geolocation); |
| |
| this.contentElement.createChild('div').classList.add('panel-section-separator'); |
| |
| this._deviceOrientationSetting = Common.settings.createSetting('emulation.deviceOrientationOverride', ''); |
| this._deviceOrientation = SDK.EmulationModel.DeviceOrientation.parseSetting(this._deviceOrientationSetting.get()); |
| this._deviceOrientationOverrideEnabled = false; |
| this._createDeviceOrientationSection(); |
| |
| this.contentElement.createChild('div').classList.add('panel-section-separator'); |
| |
| this._appendTouchControl(); |
| } |
| |
| /** |
| * @return {!SensorsView} |
| */ |
| static instance() { |
| if (!SensorsView._instanceObject) { |
| SensorsView._instanceObject = new SensorsView(); |
| } |
| return SensorsView._instanceObject; |
| } |
| |
| /** |
| * @param {!SDK.EmulationModel.Geolocation} geolocation |
| */ |
| _createGeolocationSection(geolocation) { |
| const geogroup = this.contentElement.createChild('section', 'sensors-group'); |
| const geogroupTitle = UI.createLabel(ls`Geolocation`, 'sensors-group-title'); |
| geogroup.appendChild(geogroupTitle); |
| const fields = geogroup.createChild('div', 'geo-fields'); |
| |
| const noOverrideOption = {title: Common.UIString('No override'), location: NonPresetOptions.NoOverride}; |
| |
| this._locationSelectElement = fields.createChild('select', 'chrome-select'); |
| UI.ARIAUtils.bindLabelToControl(geogroupTitle, this._locationSelectElement); |
| |
| // No override |
| this._locationSelectElement.appendChild(new Option(noOverrideOption.title, noOverrideOption.location)); |
| |
| // Locations |
| this._customLocationsGroup = this._locationSelectElement.createChild('optgroup'); |
| this._customLocationsGroup.label = ls`Overrides`; |
| const customGeolocations = Common.moduleSetting('emulation.geolocations'); |
| const manageButton = UI.createTextButton(ls`Manage`, () => Common.Revealer.reveal(customGeolocations)); |
| UI.ARIAUtils.setAccessibleName(manageButton, ls`Manage the list of geolocations`); |
| fields.appendChild(manageButton); |
| const fillCustomSettings = () => { |
| this._customLocationsGroup.removeChildren(); |
| for (const geolocation of customGeolocations.get()) { |
| this._customLocationsGroup.appendChild(new Option(geolocation.title, JSON.stringify(geolocation))); |
| } |
| }; |
| customGeolocations.addChangeListener(fillCustomSettings); |
| fillCustomSettings(); |
| |
| // Other location |
| const customLocationOption = {title: Common.UIString('Other\u2026'), location: NonPresetOptions.Custom}; |
| this._locationSelectElement.appendChild(new Option(customLocationOption.title, customLocationOption.location)); |
| |
| // Error location. |
| const group = this._locationSelectElement.createChild('optgroup'); |
| group.label = ls`Error`; |
| group.appendChild(new Option(ls`Location unavailable`, NonPresetOptions.Unavailable)); |
| |
| this._locationSelectElement.selectedIndex = 0; |
| this._locationSelectElement.addEventListener('change', this._geolocationSelectChanged.bind(this)); |
| |
| // Validated input fieldset. |
| this._fieldsetElement = fields.createChild('fieldset'); |
| this._fieldsetElement.disabled = !this._geolocationOverrideEnabled; |
| this._fieldsetElement.id = 'geolocation-override-section'; |
| |
| const latitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group'); |
| const longitudeGroup = this._fieldsetElement.createChild('div', 'latlong-group'); |
| const timezoneGroup = this._fieldsetElement.createChild('div', 'latlong-group'); |
| |
| const cmdOrCtrl = Host.isMac() ? '\u2318' : 'Ctrl'; |
| const modifierKeyMessage = ls`Adjust with mousewheel or up/down keys. ${cmdOrCtrl}: ±10, Shift: ±1, Alt: ±0.01`; |
| |
| this._latitudeInput = UI.createInput('', 'number'); |
| latitudeGroup.appendChild(this._latitudeInput); |
| this._latitudeInput.setAttribute('step', 'any'); |
| this._latitudeInput.value = 0; |
| this._latitudeSetter = UI.bindInput( |
| this._latitudeInput, this._applyGeolocationUserInput.bind(this), |
| SDK.EmulationModel.Geolocation.latitudeValidator, true, 0.1); |
| this._latitudeSetter(String(geolocation.latitude)); |
| this._latitudeInput.title = modifierKeyMessage; |
| latitudeGroup.appendChild(UI.createLabel(ls`Latitude`, 'latlong-title', this._latitudeInput)); |
| |
| this._longitudeInput = UI.createInput('', 'number'); |
| longitudeGroup.appendChild(this._longitudeInput); |
| this._longitudeInput.setAttribute('step', 'any'); |
| this._longitudeInput.value = 0; |
| this._longitudeSetter = UI.bindInput( |
| this._longitudeInput, this._applyGeolocationUserInput.bind(this), |
| SDK.EmulationModel.Geolocation.longitudeValidator, true, 0.1); |
| this._longitudeSetter(String(geolocation.longitude)); |
| this._longitudeInput.title = modifierKeyMessage; |
| longitudeGroup.appendChild(UI.createLabel(ls`Longitude`, 'latlong-title', this._longitudeInput)); |
| |
| this._timezoneInput = UI.createInput('', 'text'); |
| timezoneGroup.appendChild(this._timezoneInput); |
| this._timezoneInput.value = 'Europe/Berlin'; |
| this._timezoneSetter = UI.bindInput( |
| this._timezoneInput, this._applyGeolocationUserInput.bind(this), |
| SDK.EmulationModel.Geolocation.timezoneIdValidator, false); |
| this._timezoneSetter(String(geolocation.timezoneId)); |
| timezoneGroup.appendChild(UI.createLabel(ls`Timezone ID`, 'timezone-title', this._timezoneInput)); |
| this._timezoneError = timezoneGroup.createChild('div', 'timezone-error'); |
| } |
| |
| _geolocationSelectChanged() { |
| this._fieldsetElement.disabled = false; |
| this._timezoneError.textContent = ''; |
| const value = this._locationSelectElement.options[this._locationSelectElement.selectedIndex].value; |
| if (value === NonPresetOptions.NoOverride) { |
| this._geolocationOverrideEnabled = false; |
| this._fieldsetElement.disabled = true; |
| } else if (value === NonPresetOptions.Custom) { |
| this._geolocationOverrideEnabled = true; |
| const geolocation = SDK.EmulationModel.Geolocation.parseUserInput( |
| this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim()); |
| if (!geolocation) { |
| return; |
| } |
| this._geolocation = geolocation; |
| } else if (value === NonPresetOptions.Unavailable) { |
| this._geolocationOverrideEnabled = true; |
| this._geolocation = new SDK.EmulationModel.Geolocation(0, 0, '', true); |
| } else { |
| this._geolocationOverrideEnabled = true; |
| const coordinates = JSON.parse(value); |
| this._geolocation = |
| new SDK.EmulationModel.Geolocation(coordinates.lat, coordinates.long, coordinates.timezoneId, false); |
| this._latitudeSetter(coordinates.lat); |
| this._longitudeSetter(coordinates.long); |
| this._timezoneSetter(coordinates.timezoneId); |
| } |
| |
| this._applyGeolocation(); |
| if (value === NonPresetOptions.Custom) { |
| this._latitudeInput.focus(); |
| } |
| } |
| |
| _applyGeolocationUserInput() { |
| const geolocation = SDK.EmulationModel.Geolocation.parseUserInput( |
| this._latitudeInput.value.trim(), this._longitudeInput.value.trim(), this._timezoneInput.value.trim()); |
| if (!geolocation) { |
| return; |
| } |
| |
| this._timezoneError.textContent = ''; |
| |
| this._setSelectElementLabel(this._locationSelectElement, NonPresetOptions.Custom); |
| this._geolocation = geolocation; |
| this._applyGeolocation(); |
| } |
| |
| _applyGeolocation() { |
| if (this._geolocationOverrideEnabled) { |
| this._geolocationSetting.set(this._geolocation.toSetting()); |
| } |
| for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) { |
| emulationModel.emulateGeolocation(this._geolocationOverrideEnabled ? this._geolocation : null).catch(err => { |
| switch (err.type) { |
| case 'emulation-set-timezone': |
| this._timezoneError.textContent = err.message; |
| break; |
| } |
| }); |
| } |
| } |
| |
| _createDeviceOrientationSection() { |
| const orientationGroup = this.contentElement.createChild('section', 'sensors-group'); |
| const orientationTitle = UI.createLabel(ls`Orientation`, 'sensors-group-title'); |
| orientationGroup.appendChild(orientationTitle); |
| const orientationContent = orientationGroup.createChild('div', 'orientation-content'); |
| const fields = orientationContent.createChild('div', 'orientation-fields'); |
| |
| const orientationOffOption = {title: Common.UIString('Off'), orientation: NonPresetOptions.NoOverride}; |
| const customOrientationOption = { |
| title: Common.UIString('Custom orientation...'), |
| orientation: NonPresetOptions.Custom |
| }; |
| this._orientationSelectElement = this.contentElement.createChild('select', 'chrome-select'); |
| UI.ARIAUtils.bindLabelToControl(orientationTitle, this._orientationSelectElement); |
| this._orientationSelectElement.appendChild( |
| new Option(orientationOffOption.title, orientationOffOption.orientation)); |
| this._orientationSelectElement.appendChild( |
| new Option(customOrientationOption.title, customOrientationOption.orientation)); |
| |
| const orientationGroups = PresetOrientations; |
| for (let i = 0; i < orientationGroups.length; ++i) { |
| const groupElement = this._orientationSelectElement.createChild('optgroup'); |
| groupElement.label = orientationGroups[i].title; |
| const group = orientationGroups[i].value; |
| for (let j = 0; j < group.length; ++j) { |
| groupElement.appendChild(new Option(group[j].title, group[j].orientation)); |
| } |
| } |
| this._orientationSelectElement.selectedIndex = 0; |
| fields.appendChild(this._orientationSelectElement); |
| this._orientationSelectElement.addEventListener('change', this._orientationSelectChanged.bind(this)); |
| |
| this._deviceOrientationFieldset = this._createDeviceOrientationOverrideElement(this._deviceOrientation); |
| |
| this._stageElement = orientationContent.createChild('div', 'orientation-stage'); |
| this._orientationLayer = this._stageElement.createChild('div', 'orientation-layer'); |
| this._boxElement = this._orientationLayer.createChild('section', 'orientation-box orientation-element'); |
| |
| this._boxElement.createChild('section', 'orientation-front orientation-element'); |
| this._boxElement.createChild('section', 'orientation-top orientation-element'); |
| this._boxElement.createChild('section', 'orientation-back orientation-element'); |
| this._boxElement.createChild('section', 'orientation-left orientation-element'); |
| this._boxElement.createChild('section', 'orientation-right orientation-element'); |
| this._boxElement.createChild('section', 'orientation-bottom orientation-element'); |
| |
| UI.installDragHandle( |
| this._stageElement, this._onBoxDragStart.bind(this), this._onBoxDrag.bind(this), null, '-webkit-grabbing', |
| '-webkit-grab'); |
| |
| fields.appendChild(this._deviceOrientationFieldset); |
| this._enableOrientationFields(true); |
| this._setBoxOrientation(this._deviceOrientation, false); |
| } |
| |
| /** |
| * @param {?boolean} disable |
| */ |
| _enableOrientationFields(disable) { |
| if (disable) { |
| this._deviceOrientationFieldset.disabled = true; |
| this._stageElement.classList.add('disabled'); |
| this._stageElement.title = ls`Enable orientation to rotate`; |
| } else { |
| this._deviceOrientationFieldset.disabled = false; |
| this._stageElement.classList.remove('disabled'); |
| this._stageElement.title = ls`Shift+drag horizontally to rotate around the y-axis`; |
| } |
| } |
| |
| _orientationSelectChanged() { |
| const value = this._orientationSelectElement.options[this._orientationSelectElement.selectedIndex].value; |
| this._enableOrientationFields(false); |
| |
| if (value === NonPresetOptions.NoOverride) { |
| this._deviceOrientationOverrideEnabled = false; |
| this._enableOrientationFields(true); |
| } else if (value === NonPresetOptions.Custom) { |
| this._deviceOrientationOverrideEnabled = true; |
| this._alphaElement.focus(); |
| } else { |
| const parsedValue = JSON.parse(value); |
| this._deviceOrientationOverrideEnabled = true; |
| this._deviceOrientation = |
| new SDK.EmulationModel.DeviceOrientation(parsedValue[0], parsedValue[1], parsedValue[2]); |
| this._setDeviceOrientation(this._deviceOrientation, DeviceOrientationModificationSource.SelectPreset); |
| } |
| } |
| |
| _applyDeviceOrientation() { |
| if (this._deviceOrientationOverrideEnabled) { |
| this._deviceOrientationSetting.set(this._deviceOrientation.toSetting()); |
| } |
| for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) { |
| emulationModel.emulateDeviceOrientation(this._deviceOrientationOverrideEnabled ? this._deviceOrientation : null); |
| } |
| } |
| |
| /** |
| * @param {!Element} selectElement |
| * @param {string} labelValue |
| */ |
| _setSelectElementLabel(selectElement, labelValue) { |
| const optionValues = Array.prototype.map.call(selectElement.options, x => x.value); |
| selectElement.selectedIndex = optionValues.indexOf(labelValue); |
| } |
| |
| _applyDeviceOrientationUserInput() { |
| this._setDeviceOrientation( |
| SDK.EmulationModel.DeviceOrientation.parseUserInput( |
| this._alphaElement.value.trim(), this._betaElement.value.trim(), this._gammaElement.value.trim()), |
| DeviceOrientationModificationSource.UserInput); |
| this._setSelectElementLabel(this._orientationSelectElement, NonPresetOptions.Custom); |
| } |
| |
| _resetDeviceOrientation() { |
| this._setDeviceOrientation( |
| new SDK.EmulationModel.DeviceOrientation(0, 90, 0), DeviceOrientationModificationSource.ResetButton); |
| this._setSelectElementLabel(this._orientationSelectElement, '[0, 90, 0]'); |
| } |
| |
| /** |
| * @param {?SDK.EmulationModel.DeviceOrientation} deviceOrientation |
| * @param {!DeviceOrientationModificationSource} modificationSource |
| */ |
| _setDeviceOrientation(deviceOrientation, modificationSource) { |
| if (!deviceOrientation) { |
| return; |
| } |
| |
| /** |
| * @param {number} angle |
| * @return {number} |
| */ |
| function roundAngle(angle) { |
| return Math.round(angle * 10000) / 10000; |
| } |
| |
| if (modificationSource !== DeviceOrientationModificationSource.UserInput) { |
| this._alphaSetter(roundAngle(deviceOrientation.alpha)); |
| this._betaSetter(roundAngle(deviceOrientation.beta)); |
| this._gammaSetter(roundAngle(deviceOrientation.gamma)); |
| } |
| |
| const animate = modificationSource !== DeviceOrientationModificationSource.UserDrag; |
| this._setBoxOrientation(deviceOrientation, animate); |
| |
| this._deviceOrientation = deviceOrientation; |
| this._applyDeviceOrientation(); |
| |
| UI.ARIAUtils.alert( |
| ls`Device orientation set to alpha: ${deviceOrientation.alpha}, beta: ${deviceOrientation.beta}, gamma: ${ |
| deviceOrientation.gamma}`, |
| this._orientationSelectElement); |
| } |
| |
| /** |
| * @param {!Element} parentElement |
| * @param {!Element} input |
| * @param {string} label |
| * @return {function(string)} |
| */ |
| _createAxisInput(parentElement, input, label) { |
| const div = parentElement.createChild('div', 'orientation-axis-input-container'); |
| div.appendChild(input); |
| div.appendChild(UI.createLabel(label, /* className */ '', input)); |
| input.type = 'number'; |
| return UI.bindInput( |
| input, this._applyDeviceOrientationUserInput.bind(this), SDK.EmulationModel.DeviceOrientation.validator, true); |
| } |
| |
| /** |
| * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation |
| * @return {!Element} |
| */ |
| _createDeviceOrientationOverrideElement(deviceOrientation) { |
| const fieldsetElement = createElement('fieldset'); |
| fieldsetElement.classList.add('device-orientation-override-section'); |
| const cellElement = fieldsetElement.createChild('td', 'orientation-inputs-cell'); |
| |
| this._alphaElement = UI.createInput(); |
| this._alphaElement.setAttribute('step', 'any'); |
| this._alphaSetter = this._createAxisInput(cellElement, this._alphaElement, Common.UIString('\u03B1 (alpha)')); |
| this._alphaSetter(String(deviceOrientation.alpha)); |
| |
| this._betaElement = UI.createInput(); |
| this._betaElement.setAttribute('step', 'any'); |
| this._betaSetter = this._createAxisInput(cellElement, this._betaElement, Common.UIString('\u03B2 (beta)')); |
| this._betaSetter(String(deviceOrientation.beta)); |
| |
| this._gammaElement = UI.createInput(); |
| this._gammaElement.setAttribute('step', 'any'); |
| this._gammaSetter = this._createAxisInput(cellElement, this._gammaElement, Common.UIString('\u03B3 (gamma)')); |
| this._gammaSetter(String(deviceOrientation.gamma)); |
| |
| const resetButton = UI.createTextButton( |
| Common.UIString('Reset'), this._resetDeviceOrientation.bind(this), 'orientation-reset-button'); |
| UI.ARIAUtils.setAccessibleName(resetButton, ls`Reset device orientation`); |
| resetButton.setAttribute('type', 'reset'); |
| cellElement.appendChild(resetButton); |
| return fieldsetElement; |
| } |
| |
| /** |
| * @param {!SDK.EmulationModel.DeviceOrientation} deviceOrientation |
| * @param {boolean} animate |
| */ |
| _setBoxOrientation(deviceOrientation, animate) { |
| if (animate) { |
| this._stageElement.classList.add('is-animating'); |
| } else { |
| this._stageElement.classList.remove('is-animating'); |
| } |
| |
| // The CSS transform should not depend on matrix3d, which does not interpolate well. |
| const matrix = new WebKitCSSMatrix(); |
| this._boxMatrix = matrix.rotate(-deviceOrientation.beta, deviceOrientation.gamma, -deviceOrientation.alpha); |
| const eulerAngles = |
| new UI.Geometry.EulerAngles(deviceOrientation.alpha, deviceOrientation.beta, deviceOrientation.gamma); |
| this._orientationLayer.style.transform = eulerAngles.toRotate3DString(); |
| } |
| |
| /** |
| * @param {!MouseEvent} event |
| * @return {boolean} |
| */ |
| _onBoxDrag(event) { |
| const mouseMoveVector = this._calculateRadiusVector(event.x, event.y); |
| if (!mouseMoveVector) { |
| return true; |
| } |
| |
| event.consume(true); |
| let axis, angle; |
| if (event.shiftKey) { |
| axis = new UI.Geometry.Vector(0, 0, -1); |
| angle = (this._mouseDownVector.x - mouseMoveVector.x) * ShiftDragOrientationSpeed; |
| } else { |
| axis = UI.Geometry.crossProduct(this._mouseDownVector, mouseMoveVector); |
| angle = UI.Geometry.calculateAngle(this._mouseDownVector, mouseMoveVector); |
| } |
| |
| // The mouse movement vectors occur in the screen space, which is offset by 90 degrees from |
| // the actual device orientation. |
| let currentMatrix = new WebKitCSSMatrix(); |
| currentMatrix = currentMatrix.rotate(-90, 0, 0) |
| .rotateAxisAngle(axis.x, axis.y, axis.z, angle) |
| .rotate(90, 0, 0) |
| .multiply(this._originalBoxMatrix); |
| |
| const eulerAngles = UI.Geometry.EulerAngles.fromRotationMatrix(currentMatrix); |
| const newOrientation = |
| new SDK.EmulationModel.DeviceOrientation(-eulerAngles.alpha, -eulerAngles.beta, eulerAngles.gamma); |
| this._setDeviceOrientation(newOrientation, DeviceOrientationModificationSource.UserDrag); |
| this._setSelectElementLabel(this._orientationSelectElement, NonPresetOptions.Custom); |
| return false; |
| } |
| |
| /** |
| * @param {!MouseEvent} event |
| * @return {boolean} |
| */ |
| _onBoxDragStart(event) { |
| if (!this._deviceOrientationOverrideEnabled) { |
| return false; |
| } |
| |
| this._mouseDownVector = this._calculateRadiusVector(event.x, event.y); |
| this._originalBoxMatrix = this._boxMatrix; |
| |
| if (!this._mouseDownVector) { |
| return false; |
| } |
| |
| event.consume(true); |
| return true; |
| } |
| |
| /** |
| * @param {number} x |
| * @param {number} y |
| * @return {?UI.Geometry.Vector} |
| */ |
| _calculateRadiusVector(x, y) { |
| const rect = this._stageElement.getBoundingClientRect(); |
| const radius = Math.max(rect.width, rect.height) / 2; |
| const sphereX = (x - rect.left - rect.width / 2) / radius; |
| const sphereY = (y - rect.top - rect.height / 2) / radius; |
| const sqrSum = sphereX * sphereX + sphereY * sphereY; |
| if (sqrSum > 0.5) { |
| return new UI.Geometry.Vector(sphereX, sphereY, 0.5 / Math.sqrt(sqrSum)); |
| } |
| |
| return new UI.Geometry.Vector(sphereX, sphereY, Math.sqrt(1 - sqrSum)); |
| } |
| |
| _appendTouchControl() { |
| const groupElement = this.contentElement.createChild('div', 'sensors-group'); |
| const title = UI.createLabel(ls`Touch`, 'sensors-group-title'); |
| groupElement.appendChild(title); |
| const fieldsElement = groupElement.createChild('div', 'sensors-group-fields'); |
| |
| const select = fieldsElement.createChild('select', 'chrome-select'); |
| UI.ARIAUtils.bindLabelToControl(title, select); |
| select.appendChild(new Option(Common.UIString('Device-based'), 'auto')); |
| select.appendChild(new Option(Common.UIString('Force enabled'), 'enabled')); |
| select.addEventListener('change', applyTouch, false); |
| |
| const reloadWarning = groupElement.createChild('div', 'reload-warning hidden'); |
| reloadWarning.textContent = Common.UIString('*Requires reload'); |
| UI.ARIAUtils.markAsAlert(reloadWarning); |
| |
| function applyTouch() { |
| for (const emulationModel of SDK.targetManager.models(SDK.EmulationModel)) { |
| emulationModel.overrideEmulateTouch(select.value === 'enabled'); |
| } |
| reloadWarning.classList.remove('hidden'); |
| const resourceTreeModel = SDK.targetManager.models(SDK.ResourceTreeModel)[0]; |
| if (resourceTreeModel) { |
| resourceTreeModel.once(SDK.ResourceTreeModel.Events.MainFrameNavigated) |
| .then(() => reloadWarning.classList.add('hidden')); |
| } |
| } |
| } |
| } |
| |
| /** @enum {string} */ |
| export const DeviceOrientationModificationSource = { |
| UserInput: 'userInput', |
| UserDrag: 'userDrag', |
| ResetButton: 'resetButton', |
| SelectPreset: 'selectPreset' |
| }; |
| |
| /** {string} */ |
| export const NonPresetOptions = { |
| NoOverride: 'noOverride', |
| Custom: 'custom', |
| Unavailable: 'unavailable' |
| }; |
| |
| /** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */ |
| export const PresetOrientations = [{ |
| title: ls`Presets`, |
| value: [ |
| {title: Common.UIString('Portrait'), orientation: '[0, 90, 0]'}, |
| {title: Common.UIString('Portrait upside down'), orientation: '[180, -90, 0]'}, |
| {title: Common.UIString('Landscape left'), orientation: '[0, 90, -90]'}, |
| {title: Common.UIString('Landscape right'), orientation: '[0, 90, 90]'}, |
| {title: Common.UIString('Display up'), orientation: '[0, 0, 0]'}, |
| {title: Common.UIString('Display down'), orientation: '[0, 180, 0]'} |
| ] |
| }]; |
| |
| /** |
| * @implements {UI.ActionDelegate} |
| * @unrestricted |
| */ |
| export class ShowActionDelegate { |
| /** |
| * @override |
| * @param {!UI.Context} context |
| * @param {string} actionId |
| * @return {boolean} |
| */ |
| handleAction(context, actionId) { |
| UI.viewManager.showView('sensors'); |
| return true; |
| } |
| } |
| |
| export const ShiftDragOrientationSpeed = 16; |
| |
| /* Legacy exported object */ |
| self.Emulation = self.Emulation || {}; |
| |
| /* Legacy exported object */ |
| Emulation = Emulation || {}; |
| |
| /** |
| * @constructor |
| */ |
| Emulation.SensorsView = SensorsView; |
| |
| /** @enum {string} */ |
| Emulation.SensorsView.DeviceOrientationModificationSource = DeviceOrientationModificationSource; |
| |
| /** {string} */ |
| Emulation.SensorsView.NonPresetOptions = NonPresetOptions; |
| |
| /** @type {!Array.<{title: string, value: !Array.<{title: string, orientation: string}>}>} */ |
| Emulation.SensorsView.PresetOrientations = PresetOrientations; |
| |
| /** |
| * @constructor |
| */ |
| Emulation.SensorsView.ShowActionDelegate = ShowActionDelegate; |
| Emulation.SensorsView.ShiftDragOrientationSpeed = ShiftDragOrientationSpeed; |