diff --git a/CHANGES.md b/CHANGES.md index c39547570e85..01580d82fe94 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,15 @@ Beta Releases * `TilingScheme.extentToNativeRectangle` -> `TilingScheme.rectangleToNativeRectangle` * `TilingScheme.tileXYToNativeExtent` -> `TilingScheme.tileXYToNativeRectangle` * `TilingScheme.tileXYToExtent` -> `TilingScheme.tileXYToRectangle` + * `BaseLayerPicker` has been extended to support terrain selection. + * The `BaseLayerPicker` constructor function now takes the container element and an options object instead of a CentralBody and ImageryLayerCollection. + * The `BaseLayerPickerViewModel` constructor function now takes an options object instead of a CentralBody and ImageryLayerCollection. + * `ImageryProviderViewModel` -> `ProviderViewModel` + * `BaseLayerPickerViewModel.selectedName` -> `BaseLayerPickerViewModel.buttonTooltip` + * `BaseLayerPickerViewModel.selectedIconUrl` -> `BaseLayerPickerViewModel.buttonImageUrl` + * `BaseLayerPickerViewModel.selectedItem` -> `BaseLayerPickerViewModel.selectedImagery` + * `BaseLayerPickerViewModel.imageryLayers`has been removed and replaced with `BaseLayerPickerViewModel.centralBody` + * See [#1607](https://github.com/AnalyticalGraphicsInc/cesium/pull/1607) for full details. * `TimeIntervalCollection.clear` renamed to `TimeIntervalColection.removeAll` * `Context` is now private * Removed `Scene.context`: replaced by adding `drawingBufferWidth`, `drawingBufferHeight`, `maximumAliasedLineWidth` properties and `createTextureAtlas` function to `Scene`. diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.css b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.css index 0787882a08f2..ac0052aac628 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.css +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.css @@ -28,7 +28,7 @@ position: absolute; top: auto; right: 0; - width: 240px; + width: 320px; max-height: 500px; margin-top: 5px; background-color: rgba(38, 38, 38, 0.75); @@ -40,6 +40,21 @@ user-select: none; } +.cesium-baseLayerPicker-sectionTitle { + display: block; + font-family: sans-serif; + font-size: 16pt; + text-align: left; + color: #edffff; +} + +.cesium-baseLayerPicker-choices { + display: block; + position: relative; + top: auto; + right: 0; +} + .cesium-baseLayerPicker-item { display: inline-block; vertical-align: top; diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js index 6e2e6d51a542..3904a85f010d 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPicker.js @@ -23,23 +23,27 @@ define([ *
BaseLayerPicker with its drop-panel open. * *

- * The BaseLayerPicker is a single button widget that displays a panel of available imagery - * providers. When an item is selected, the corresponding imagery layer is created and inserted - * as the base layer of the imagery collection; removing the existing base. Each item in the - * available providers list contains a name, a representative icon, and a tooltip to display more - * information when hovered. The list is initially empty, and must be configured before use, as - * illustrated in the below example. + * The BaseLayerPicker is a single button widget that displays a panel of available imagery and + * terrain providers. When imagery is selected, the corresponding imagery layer is created and inserted + * as the base layer of the imagery collection; removing the existing base. When terrain is selected, + * it replaces the current terrain provider. Each item in the available providers list contains a name, + * a representative icon, and a tooltip to display more information when hovered. The list is initially + * empty, and must be configured before use, as illustrated in the below example. * * @alias BaseLayerPicker * @constructor * * @param {Element} container The parent HTML container node for this widget. - * @param {ImageryLayerCollection} imageryLayers The imagery layer collection to use. + * @param {CentralBody} options.centralBody The CentralBody to use. + * @param {ProviderViewModel[]} [options.imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery. + * @param {ProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available imagery layer is used. + * @param {ProviderViewModel[]} [options.terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain. + * @param {ProviderViewModel} [options.selectedTerrainProviderViewModel] The view model for the current base terrain layer, if not supplied the first available terrain layer is used. * * @exception {DeveloperError} Element with id "container" does not exist in the document. * + * @see TerrainProvider * @see ImageryProvider - * @see ImageryProviderViewModel * @see ImageryLayerCollection * * @example @@ -49,8 +53,8 @@ define([ * * //Create the list of available providers we would like the user to select from. * //This example uses 3, OpenStreetMap, The Black Marble, and a single, non-streaming world image. - * var providerViewModels = []; - * providerViewModels.push(new Cesium.ImageryProviderViewModel({ + * var imageryViewModels = []; + * imageryViewModels.push(new Cesium.ProviderViewModel({ * name : 'Open\u00adStreet\u00adMap', * iconUrl : Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/openStreetMap.png'), * tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable \ @@ -62,7 +66,7 @@ define([ * } * })); * - * providerViewModels.push(new Cesium.ImageryProviderViewModel({ + * imageryViewModels.push(new Cesium.ProviderViewModel({ * name : 'Black Marble', * iconUrl : Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/blackMarble.png'), * tooltip : 'The lights of cities and villages trace the outlines of civilization \ @@ -76,7 +80,7 @@ define([ * } * })); * - * providerViewModels.push(new Cesium.ImageryProviderViewModel({ + * imageryViewModels.push(new Cesium.ProviderViewModel({ * name : 'Natural Earth\u00a0II', * iconUrl : Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/naturalEarthII.png'), * tooltip : 'Natural Earth II, darkened for contrast.\nhttp://www.naturalearthdata.com/', @@ -92,30 +96,27 @@ define([ * * //Finally, create the baseLayerPicker widget using our view models. * var layers = cesiumWidget.centralBody.imageryLayers; - * var baseLayerPicker = new Cesium.BaseLayerPicker('baseLayerPickerContainer', layers, providerViewModels); + * var baseLayerPicker = new Cesium.BaseLayerPicker('baseLayerPickerContainer', layers, imageryViewModels); * * //Use the first item in the list as the current selection. - * baseLayerPicker.viewModel.selectedItem = providerViewModels[0]; + * baseLayerPicker.viewModel.selectedItem = imageryViewModels[0]; */ - var BaseLayerPicker = function(container, imageryLayers, imageryProviderViewModels) { + var BaseLayerPicker = function(container, options) { //>>includeStart('debug', pragmas.debug); if (!defined(container)) { throw new DeveloperError('container is required.'); } - if (!defined(imageryLayers)) { - throw new DeveloperError('imageryLayers is required.'); - } //>>includeEnd('debug'); container = getElement(container); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, imageryProviderViewModels); + var viewModel = new BaseLayerPickerViewModel(options); var element = document.createElement('button'); element.type = 'button'; element.className = 'cesium-button cesium-toolbar-button'; element.setAttribute('data-bind', '\ -attr: { title: selectedName },\ +attr: { title: buttonTooltip },\ click: toggleDropDown'); container.appendChild(element); @@ -123,47 +124,88 @@ click: toggleDropDown'); imgElement.setAttribute('draggable', 'false'); imgElement.className = 'cesium-baseLayerPicker-selected'; imgElement.setAttribute('data-bind', '\ -attr: { src: selectedIconUrl }'); +attr: { src: buttonImageUrl }'); element.appendChild(imgElement); - var choices = document.createElement('div'); - choices.className = 'cesium-baseLayerPicker-dropDown'; - choices.setAttribute('data-bind', '\ + var dropPanel = document.createElement('div'); + dropPanel.className = 'cesium-baseLayerPicker-dropDown'; + dropPanel.setAttribute('data-bind', '\ css: { "cesium-baseLayerPicker-visible" : dropDownVisible,\ - "cesium-baseLayerPicker-hidden" : !dropDownVisible },\ -foreach: imageryProviderViewModels'); - container.appendChild(choices); - - var provider = document.createElement('div'); - provider.className = 'cesium-baseLayerPicker-item'; - provider.setAttribute('data-bind', '\ -css: { "cesium-baseLayerPicker-selectedItem" : $data === $parent.selectedItem },\ + "cesium-baseLayerPicker-hidden" : !dropDownVisible }'); + container.appendChild(dropPanel); + + var imageryTitle = document.createElement('div'); + imageryTitle.className = 'cesium-baseLayerPicker-sectionTitle'; + imageryTitle.setAttribute('data-bind', 'visible: imageryProviderViewModels.length > 0'); + imageryTitle.innerHTML = 'Imagery
'; + dropPanel.appendChild(imageryTitle); + + var imageryChoices = document.createElement('div'); + imageryChoices.className = 'cesium-baseLayerPicker-choices'; + imageryChoices.setAttribute('data-bind', 'foreach: imageryProviderViewModels'); + dropPanel.appendChild(imageryChoices); + + var imageryProvider = document.createElement('div'); + imageryProvider.className = 'cesium-baseLayerPicker-item'; + imageryProvider.setAttribute('data-bind', '\ +css: { "cesium-baseLayerPicker-selectedItem" : $data === $parent.selectedImagery },\ attr: { title: tooltip },\ visible: creationCommand.canExecute,\ -click: function($data) { $parent.selectedItem = $data; }'); - choices.appendChild(provider); +click: function($data) { $parent.selectedImagery = $data; }'); + imageryChoices.appendChild(imageryProvider); var providerIcon = document.createElement('img'); providerIcon.className = 'cesium-baseLayerPicker-itemIcon'; providerIcon.setAttribute('data-bind', 'attr: { src: iconUrl }'); providerIcon.setAttribute('draggable', 'false'); - provider.appendChild(providerIcon); + imageryProvider.appendChild(providerIcon); var providerLabel = document.createElement('div'); providerLabel.className = 'cesium-baseLayerPicker-itemLabel'; providerLabel.setAttribute('data-bind', 'text: name'); - provider.appendChild(providerLabel); + imageryProvider.appendChild(providerLabel); + + var terrainTitle = document.createElement('div'); + terrainTitle.className = 'cesium-baseLayerPicker-sectionTitle'; + terrainTitle.setAttribute('data-bind', 'visible: terrainProviderViewModels.length > 0'); + terrainTitle.innerHTML = 'Terrain
'; + dropPanel.appendChild(terrainTitle); + + var terrainChoices = document.createElement('div'); + terrainChoices.className = 'cesium-baseLayerPicker-choices'; + terrainChoices.setAttribute('data-bind', 'foreach: terrainProviderViewModels'); + dropPanel.appendChild(terrainChoices); + + var terrainProvider = document.createElement('div'); + terrainProvider.className = 'cesium-baseLayerPicker-item'; + terrainProvider.setAttribute('data-bind', '\ +css: { "cesium-baseLayerPicker-selectedItem" : $data === $parent.selectedTerrain },\ +attr: { title: tooltip },\ +visible: creationCommand.canExecute,\ +click: function($data) { $parent.selectedTerrain = $data; }'); + terrainChoices.appendChild(terrainProvider); + + var terrainProviderIcon = document.createElement('img'); + terrainProviderIcon.className = 'cesium-baseLayerPicker-itemIcon'; + terrainProviderIcon.setAttribute('data-bind', 'attr: { src: iconUrl }'); + terrainProviderIcon.setAttribute('draggable', 'false'); + terrainProvider.appendChild(terrainProviderIcon); + + var terrainProviderLabel = document.createElement('div'); + terrainProviderLabel.className = 'cesium-baseLayerPicker-itemLabel'; + terrainProviderLabel.setAttribute('data-bind', 'text: name'); + terrainProvider.appendChild(terrainProviderLabel); knockout.applyBindings(viewModel, element); - knockout.applyBindings(viewModel, choices); + knockout.applyBindings(viewModel, dropPanel); this._viewModel = viewModel; this._container = container; this._element = element; - this._choices = choices; + this._dropPanel = dropPanel; this._closeDropDown = function(e) { - if (!(element.contains(e.target) || choices.contains(e.target))) { + if (!(element.contains(e.target) || dropPanel.contains(e.target))) { viewModel.dropDownVisible = false; } }; @@ -215,9 +257,9 @@ click: function($data) { $parent.selectedItem = $data; }'); document.removeEventListener('mousedown', this._closeDropDown, true); document.removeEventListener('touchstart', this._closeDropDown, true); knockout.cleanNode(this._element); - knockout.cleanNode(this._choices); + knockout.cleanNode(this._dropPanel); this._container.removeChild(this._element); - this._container.removeChild(this._choices); + this._container.removeChild(this._dropPanel); return destroyObject(this); }; diff --git a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js index 3cd862ce3985..697b508729b4 100644 --- a/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js +++ b/Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js @@ -1,16 +1,20 @@ /*global define*/ define([ + '../../Core/defaultValue', '../../Core/defined', '../../Core/defineProperties', '../../Core/DeveloperError', '../../Core/isArray', + '../../Scene/EllipsoidTerrainProvider', '../createCommand', '../../ThirdParty/knockout' ], function( + defaultValue, defined, defineProperties, DeveloperError, isArray, + EllipsoidTerrainProvider, createCommand, knockout) { "use strict"; @@ -20,37 +24,44 @@ define([ * @alias BaseLayerPickerViewModel * @constructor * - * @param {ImageryLayerCollection} imageryLayers The imagery layer collection to use. - * @param {Array} [imageryProviderViewModels=[]] The array of ImageryProviderViewModel instances to use. + * @param {CentralBody} options.centralBody The CentralBody to use. + * @param {ProviderViewModel[]} [options.imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery. + * @param {ProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available imagery layer is used. + * @param {ProviderViewModel[]} [options.terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain. + * @param {ProviderViewModel} [options.selectedTerrainProviderViewModel] The view model for the current base terrain layer, if not supplied the first available terrain layer is used. * * @exception {DeveloperError} imageryProviderViewModels must be an array. - * - * @see ImageryProviderViewModel + * @exception {DeveloperError} terrainProviderViewModels must be an array. */ - var BaseLayerPickerViewModel = function(imageryLayers, imageryProviderViewModels) { + var BaseLayerPickerViewModel = function(options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + var centralBody = options.centralBody; + var imageryProviderViewModels = defaultValue(options.imageryProviderViewModels, []); + var terrainProviderViewModels = defaultValue(options.terrainProviderViewModels, []); + //>>includeStart('debug', pragmas.debug); - if (!defined(imageryLayers)) { - throw new DeveloperError('imageryLayers is required'); + if (!defined(centralBody)) { + throw new DeveloperError('centralBody is required'); } //>>includeEnd('debug'); - if (!defined(imageryProviderViewModels)) { - imageryProviderViewModels = []; - } else if (!isArray(imageryProviderViewModels)) { - throw new DeveloperError('imageryProviderViewModels must be an array'); - } - - var that = this; - - this._imageryLayers = imageryLayers; + this._centralBody = centralBody; /** - * Gets or sets an array of ImageryProviderViewModel instances available for selection. + * Gets or sets an array of ProviderViewModel instances available for imagery selection. * This property is observable. * @type {Array} */ this.imageryProviderViewModels = imageryProviderViewModels.slice(0); + /** + * Gets or sets an array of ProviderViewModel instances available for terrain selection. + * This property is observable. + * @type {Array} + */ + this.terrainProviderViewModels = terrainProviderViewModels.slice(0); + /** * Gets or sets whether the imagery selection drop-down is currently visible. * @type {Boolean} @@ -58,50 +69,66 @@ define([ */ this.dropDownVisible = false; - knockout.track(this, ['imageryProviderViewModels', 'dropDownVisible']); + knockout.track(this, ['imageryProviderViewModels', 'terrainProviderViewModels', 'dropDownVisible']); /** - * Gets the currently selected item name. This property is observable. + * Gets the button tooltip. This property is observable. * @type {String} */ - this.selectedName = undefined; - knockout.defineProperty(this, 'selectedName', function() { - var selected = that.selectedItem; - return defined(selected) ? selected.name : undefined; + this.buttonTooltip = undefined; + knockout.defineProperty(this, 'buttonTooltip', function() { + var selectedImagery = this.selectedImagery; + var selectedTerrain = this.selectedTerrain; + + var imageryTip = defined(selectedImagery) ? selectedImagery.name : undefined; + var terrainTip = defined(selectedTerrain) ? selectedTerrain.name : undefined; + + if (defined(imageryTip) && defined(terrainTip)) { + return imageryTip + '\n' + terrainTip; + } else if (defined(imageryTip)) { + return imageryTip; + } + return terrainTip; }); /** - * Gets the image url of the currently selected item. This property is observable. + * Gets the button background image. This property is observable. * @type {String} */ - this.selectedIconUrl = undefined; - knockout.defineProperty(this, 'selectedIconUrl', function() { - var viewModel = that.selectedItem; + this.buttonImageUrl = undefined; + knockout.defineProperty(this, 'buttonImageUrl', function() { + var viewModel = this.selectedImagery; return defined(viewModel) ? viewModel.iconUrl : undefined; }); /** - * Gets or sets the currently selected item. This property is observable. - * @type {ImageryProviderViewModel} + * Gets or sets the currently selected imagery. This property is observable. + * @type {ProviderViewModel} * @default undefined */ - this.selectedItem = undefined; - var selectedViewModel = knockout.observable(); + this.selectedImagery = undefined; + var selectedImageryViewModel = knockout.observable(); - this._currentProviders = []; - knockout.defineProperty(this, 'selectedItem', { + this._currentImageryProviders = []; + knockout.defineProperty(this, 'selectedImagery', { get : function() { - return selectedViewModel(); + return selectedImageryViewModel(); }, set : function(value) { + if (selectedImageryViewModel() === value) { + this.dropDownVisible = false; + return; + } + var i; - var currentProviders = that._currentProviders; - var currentProvidersLength = currentProviders.length; - for (i = 0; i < currentProvidersLength; i++) { + var currentImageryProviders = this._currentImageryProviders; + var currentImageryProvidersLength = currentImageryProviders.length; + var imageryLayers = this._centralBody.imageryLayers; + for (i = 0; i < currentImageryProvidersLength; i++) { var layersLength = imageryLayers.length; for ( var x = 0; x < layersLength; x++) { var layer = imageryLayers.get(x); - if (layer.imageryProvider === currentProviders[i]) { + if (layer.imageryProvider === currentImageryProviders[i]) { imageryLayers.remove(layer); break; } @@ -115,21 +142,54 @@ define([ for (i = newProvidersLength - 1; i >= 0; i--) { imageryLayers.addImageryProvider(newProviders[i], 0); } - that._currentProviders = newProviders.slice(0); + this._currentImageryProviders = newProviders.slice(0); } else { - that._currentProviders = [newProviders]; + this._currentImageryProviders = [newProviders]; imageryLayers.addImageryProvider(newProviders, 0); } + } + selectedImageryViewModel(value); + this.dropDownVisible = false; + } + }); + + /** + * Gets or sets the currently selected terrain. This property is observable. + * @type {ProviderViewModel} + * @default undefined + */ + this.selectedTerrain = undefined; + var selectedTerrainViewModel = knockout.observable(); - selectedViewModel(value); + knockout.defineProperty(this, 'selectedTerrain', { + get : function() { + return selectedTerrainViewModel(); + }, + set : function(value) { + if (selectedTerrainViewModel() === value) { + this.dropDownVisible = false; + return; + } + + var newProvider; + if (defined(value)) { + newProvider = value.creationCommand(); } - that.dropDownVisible = false; + + this._centralBody.depthTestAgainstTerrain = !(newProvider instanceof EllipsoidTerrainProvider); + this._centralBody.terrainProvider = newProvider; + selectedTerrainViewModel(value); + this.dropDownVisible = false; } }); + var that = this; this._toggleDropDown = createCommand(function() { that.dropDownVisible = !that.dropDownVisible; }); + + this.selectedImagery = defaultValue(options.selectedImageryProviderViewModel, imageryProviderViewModels[0]); + this.selectedTerrain = defaultValue(options.selectedTerrainProviderViewModel, terrainProviderViewModels[0]); }; defineProperties(BaseLayerPickerViewModel.prototype, { @@ -146,14 +206,14 @@ define([ }, /** - * Gets the imagery layer collection. + * Gets the centralBody. * @memberof BaseLayerPickerViewModel.prototype * - * @type {ImageryLayerCollection} + * @type {CentralBody} */ - imageryLayers : { + centralBody : { get : function() { - return this._imageryLayers; + return this._centralBody; } } }); diff --git a/Source/Widgets/BaseLayerPicker/ImageryProviderViewModel.js b/Source/Widgets/BaseLayerPicker/ProviderViewModel.js similarity index 91% rename from Source/Widgets/BaseLayerPicker/ImageryProviderViewModel.js rename to Source/Widgets/BaseLayerPicker/ProviderViewModel.js index 5a362d97805d..a3f610bb3bfd 100644 --- a/Source/Widgets/BaseLayerPicker/ImageryProviderViewModel.js +++ b/Source/Widgets/BaseLayerPicker/ProviderViewModel.js @@ -16,7 +16,7 @@ define([ /** * A view model that represents each item in the BaseLayerPicker. * - * @alias ImageryProviderViewModel + * @alias ProviderViewModel * @constructor * * @param {Object} description The object containing all parameters. @@ -28,7 +28,7 @@ define([ * @see BaseLayerPicker * @see ImageryProvider */ - var ImageryProviderViewModel = function(description) { + var ProviderViewModel = function(description) { //>>includeStart('debug', pragmas.debug); if (!defined(description.name)) { throw new DeveloperError('description.name is required.'); @@ -72,11 +72,11 @@ define([ knockout.track(this, ['name', 'tooltip', 'iconUrl']); }; - defineProperties(ImageryProviderViewModel.prototype, { + defineProperties(ProviderViewModel.prototype, { /** * Gets the Command called to create the imagery provider or array of * imagery providers to be added to the bottom of the layer collection. - * @memberof ImageryProviderViewModel.prototype + * @memberof ProviderViewModel.prototype * * @type {Command} */ @@ -87,5 +87,5 @@ define([ } }); - return ImageryProviderViewModel; + return ProviderViewModel; }); diff --git a/Source/Widgets/BaseLayerPicker/createDefaultBaseLayers.js b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js similarity index 89% rename from Source/Widgets/BaseLayerPicker/createDefaultBaseLayers.js rename to Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js index c0c5783a6402..fbea6ab6b38a 100644 --- a/Source/Widgets/BaseLayerPicker/createDefaultBaseLayers.js +++ b/Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js @@ -1,6 +1,6 @@ /*global define*/ define([ - '../BaseLayerPicker/ImageryProviderViewModel', + '../BaseLayerPicker/ProviderViewModel', '../../Core/buildModuleUrl', '../../Scene/BingMapsImageryProvider', '../../Scene/BingMapsStyle', @@ -8,7 +8,7 @@ define([ '../../Scene/OpenStreetMapImageryProvider', '../../Scene/TileMapServiceImageryProvider' ], function( - ImageryProviderViewModel, + ProviderViewModel, buildModuleUrl, BingMapsImageryProvider, BingMapsStyle, @@ -20,9 +20,9 @@ define([ /** * @private */ - function createDefaultBaseLayers() { + function createDefaultImageryProviderViewModels() { var providerViewModels = []; - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Bing Maps Aerial', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/bingAerial.png'), tooltip : 'Bing Maps aerial imagery \nhttp://www.bing.com/maps', @@ -34,7 +34,7 @@ define([ } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Bing Maps Aerial with Labels', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/bingAerialLabels.png'), tooltip : 'Bing Maps aerial imagery with label overlays \nhttp://www.bing.com/maps', @@ -46,7 +46,7 @@ define([ } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Bing Maps Roads', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/bingRoads.png'), tooltip : 'Bing Maps standard road maps\nhttp://www.bing.com/maps', @@ -58,7 +58,7 @@ define([ } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'ESRI World Imagery', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/esriWorldImagery.png'), tooltip : '\ @@ -76,7 +76,7 @@ contributed by the GIS User Community.\nhttp://www.esri.com', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'ESRI World Street Map', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/esriWorldStreetMap.png'), tooltip : '\ @@ -91,7 +91,7 @@ http://www.esri.com', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'ESRI National Geographic', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/esriNationalGeographic.png'), tooltip : '\ @@ -105,7 +105,7 @@ mapping applications.\nhttp://www.esri.com', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Open\u00adStreet\u00adMap', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/openStreetMap.png'), tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable map \ @@ -117,7 +117,7 @@ of the world.\nhttp://www.openstreetmap.org', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Stamen Watercolor', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/stamenWatercolor.png'), tooltip : 'Reminiscent of hand drawn maps, Stamen watercolor maps apply raster effect \ @@ -130,7 +130,7 @@ area washes and organic edges over a paper texture to add warm pop to any map.\n } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Stamen Toner', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/stamenToner.png'), tooltip : 'A high contrast black and white map.\nhttp://maps.stamen.com', @@ -142,7 +142,7 @@ area washes and organic edges over a paper texture to add warm pop to any map.\n } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'MapQuest Open\u00adStreet\u00adMap', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png'), tooltip : 'OpenStreetMap (OSM) is a collaborative project to create a free editable \ @@ -154,7 +154,7 @@ map of the world.\nhttp://www.openstreetmap.org', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'The Black Marble', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/blackMarble.png'), tooltip : 'The lights of cities and villages trace the outlines of civilization in this global view of the \ @@ -168,7 +168,7 @@ Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.', } })); - providerViewModels.push(new ImageryProviderViewModel({ + providerViewModels.push(new ProviderViewModel({ name : 'Natural Earth\u00a0II', iconUrl : buildModuleUrl('Widgets/Images/ImageryProviders/naturalEarthII.png'), tooltip : 'Natural Earth II, darkened for contrast.\nhttp://www.naturalearthdata.com/', @@ -182,5 +182,5 @@ Earth at night as seen by NASA/NOAA\'s Suomi NPP satellite.', return providerViewModels; } - return createDefaultBaseLayers; + return createDefaultImageryProviderViewModels; }); \ No newline at end of file diff --git a/Source/Widgets/BaseLayerPicker/createDefaultTerrainProviderViewModels.js b/Source/Widgets/BaseLayerPicker/createDefaultTerrainProviderViewModels.js new file mode 100644 index 000000000000..5e4c3e1eae93 --- /dev/null +++ b/Source/Widgets/BaseLayerPicker/createDefaultTerrainProviderViewModels.js @@ -0,0 +1,59 @@ +/*global define*/ +define([ + '../BaseLayerPicker/ProviderViewModel', + '../../Core/buildModuleUrl', + '../../Scene/ArcGisImageServerTerrainProvider', + '../../Scene/CesiumTerrainProvider', + '../../Scene/EllipsoidTerrainProvider' + ], function( + ProviderViewModel, + buildModuleUrl, + ArcGisImageServerTerrainProvider, + CesiumTerrainProvider, + EllipsoidTerrainProvider) { + "use strict"; + + /** + * @private + */ + function createDefaultTerrainProviderViewModels() { + var providerViewModels = []; + providerViewModels.push(new ProviderViewModel({ + name : 'WGS84 Ellipsoid', + iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/Ellipsoid.png'), + tooltip : 'WGS84 standard ellipsoid, also known as EPSG:4326', + creationFunction : function() { + return new EllipsoidTerrainProvider(); + } + })); + + + providerViewModels.push(new ProviderViewModel({ + name : 'STK World Terrain meshes', + iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/STK.png'), + tooltip : 'High-resolution, mesh-based terrain for the entire globe. Free for use on the Internet. Closed-network options are available.\nhttp://www.agi.com', + creationFunction : function() { + return new CesiumTerrainProvider({ + url : '//cesiumjs.org/stk-terrain/tilesets/world/tiles', + credit : 'Terrain data courtesy Analytical Graphics, Inc.' + }); + } + })); + + providerViewModels.push(new ProviderViewModel({ + name : 'Small Terrain heightmaps and water mask', + iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/STK.png'), + tooltip : 'Medium-resolution, heightmap-based terrain for the entire globe. This tileset also includes a water mask. Free for use on the Internet.\nhttp://www.agi.com', + creationFunction : function() { + return new CesiumTerrainProvider({ + url : '//cesiumjs.org/smallterrain', + credit : 'Terrain data courtesy Analytical Graphics, Inc.' + }); + } + })); + + return providerViewModels; + } + + return createDefaultTerrainProviderViewModels; +}); \ No newline at end of file diff --git a/Source/Widgets/BaseLayerPicker/lighter.css b/Source/Widgets/BaseLayerPicker/lighter.css index a3e4231eab09..4b0d7094420c 100644 --- a/Source/Widgets/BaseLayerPicker/lighter.css +++ b/Source/Widgets/BaseLayerPicker/lighter.css @@ -6,6 +6,10 @@ background-color: rgba(240, 240, 240, 0.75); } +.cesium-lighter .cesium-baseLayerPicker-sectionTitle { + color: black; +} + .cesium-lighter .cesium-baseLayerPicker-itemLabel { color: black; } diff --git a/Source/Widgets/Images/TerrainProviders/Ellipsoid.png b/Source/Widgets/Images/TerrainProviders/Ellipsoid.png new file mode 100644 index 000000000000..a36259bbecd3 Binary files /dev/null and b/Source/Widgets/Images/TerrainProviders/Ellipsoid.png differ diff --git a/Source/Widgets/Images/TerrainProviders/STK.png b/Source/Widgets/Images/TerrainProviders/STK.png new file mode 100644 index 000000000000..1eadbf9dd052 Binary files /dev/null and b/Source/Widgets/Images/TerrainProviders/STK.png differ diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index 53345402d78b..34b2c55f1a54 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -14,7 +14,8 @@ define([ '../Animation/Animation', '../Animation/AnimationViewModel', '../BaseLayerPicker/BaseLayerPicker', - '../BaseLayerPicker/createDefaultBaseLayers', + '../BaseLayerPicker/createDefaultImageryProviderViewModels', + '../BaseLayerPicker/createDefaultTerrainProviderViewModels', '../CesiumWidget/CesiumWidget', '../ClockViewModel', '../FullscreenButton/FullscreenButton', @@ -42,7 +43,8 @@ define([ Animation, AnimationViewModel, BaseLayerPicker, - createDefaultBaseLayers, + createDefaultImageryProviderViewModels, + createDefaultTerrainProviderViewModels, CesiumWidget, ClockViewModel, FullscreenButton, @@ -114,8 +116,10 @@ define([ * @param {Boolean} [options.sceneModePicker=true] If set to false, the SceneModePicker widget will not be created. * @param {Boolean} [options.selectionIndicator=true] If set to false, the SelectionIndicator widget will not be created. * @param {Boolean} [options.timeline=true] If set to false, the Timeline widget will not be created. - * @param {ImageryProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available base layer is used. This value is only valid if options.baseLayerPicker is set to true. - * @param {Array} [options.imageryProviderViewModels=createDefaultBaseLayers()] The array of ImageryProviderViewModels to be selectable from the BaseLayerPicker. This value is only valid if options.baseLayerPicker is set to true. + * @param {ProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available base layer is used. This value is only valid if options.baseLayerPicker is set to true. + * @param {Array} [options.imageryProviderViewModels=createDefaultImageryProviderViewModels()] The array of ProviderViewModels to be selectable from the BaseLayerPicker. This value is only valid if options.baseLayerPicker is set to true. + * @param {ProviderViewModel} [options.selectedTerrainProviderViewModel] The view model for the current base terrain layer, if not supplied the first available base layer is used. This value is only valid if options.baseLayerPicker is set to true. + * @param {Array} [options.terrainProviderViewModels=createDefaultTerrainProviderViewModels()] The array of ProviderViewModels to be selectable from the BaseLayerPicker. This value is only valid if options.baseLayerPicker is set to true. * @param {ImageryProvider} [options.imageryProvider=new BingMapsImageryProvider()] The imagery provider to use. This value is only valid if options.baseLayerPicker is set to false. * @param {TerrainProvider} [options.terrainProvider=new EllipsoidTerrainProvider()] The terrain provider to use * @param {SkyBox} [options.skyBox] The skybox used to render the stars. When undefined, the default stars are used. @@ -128,7 +132,9 @@ define([ * * @exception {DeveloperError} Element with id "container" does not exist in the document. * @exception {DeveloperError} options.imageryProvider is not available when using the BaseLayerPicker widget, specify options.selectedImageryProviderViewModel instead. + * @exception {DeveloperError} options.terrainProvider is not available when using the BaseLayerPicker widget, specify options.selectedTerrainProviderViewModel instead. * @exception {DeveloperError} options.selectedImageryProviderViewModel is not available when not using the BaseLayerPicker widget, specify options.imageryProvider instead. + * @exception {DeveloperError} options.selectedTerrainProviderViewModel is not available when not using the BaseLayerPicker widget, specify options.terrainProvider instead. * * @see Animation * @see BaseLayerPicker @@ -194,7 +200,6 @@ define([ var createBaseLayerPicker = !defined(options.baseLayerPicker) || options.baseLayerPicker !== false; //>>includeStart('debug', pragmas.debug); - //If using BaseLayerPicker, imageryProvider is an invalid option if (createBaseLayerPicker && defined(options.imageryProvider)) { throw new DeveloperError('options.imageryProvider is not available when using the BaseLayerPicker widget. \ @@ -206,6 +211,18 @@ Either specify options.selectedImageryProviderViewModel instead or set options.b throw new DeveloperError('options.selectedImageryProviderViewModel is not available when not using the BaseLayerPicker widget. \ Either specify options.imageryProvider instead or set options.baseLayerPicker to true.'); } + + //If using BaseLayerPicker, terrainProvider is an invalid option + if (createBaseLayerPicker && defined(options.terrainProvider)) { + throw new DeveloperError('options.terrainProvider is not available when using the BaseLayerPicker widget. \ +Either specify options.selectedTerrainProviderViewModel instead or set options.baseLayerPicker to false.'); + } + + //If not using BaseLayerPicker, selectedTerrainProviderViewModel is an invalid option + if (!createBaseLayerPicker && defined(options.selectedTerrainProviderViewModel)) { + throw new DeveloperError('options.selectedTerrainProviderViewModel is not available when not using the BaseLayerPicker widget. \ +Either specify options.terrainProvider instead or set options.baseLayerPicker to true.'); + } //>>includeEnd('debug') var viewerContainer = document.createElement('div'); @@ -296,9 +313,16 @@ Either specify options.imageryProvider instead or set options.baseLayerPicker to //BaseLayerPicker var baseLayerPicker; if (createBaseLayerPicker) { - var providerViewModels = defaultValue(options.imageryProviderViewModels, createDefaultBaseLayers()); - baseLayerPicker = new BaseLayerPicker(toolbar, cesiumWidget.centralBody.imageryLayers, providerViewModels); - baseLayerPicker.viewModel.selectedItem = defaultValue(options.selectedImageryProviderViewModel, providerViewModels[0]); + var imageryProviderViewModels = defaultValue(options.imageryProviderViewModels, createDefaultImageryProviderViewModels()); + var terrainProviderViewModels = defaultValue(options.terrainProviderViewModels, createDefaultTerrainProviderViewModels()); + + baseLayerPicker = new BaseLayerPicker(toolbar, { + centralBody : cesiumWidget.centralBody, + imageryProviderViewModels : imageryProviderViewModels, + selectedImageryProviderViewModel : options.selectedImageryProviderViewModel, + terrainProviderViewModels : terrainProviderViewModels, + selectedTerrainProviderViewModel : options.selectedTerrainProviderViewModel + }); //Grab the dropdown for resize code. var elements = toolbar.getElementsByClassName('cesium-baseLayerPicker-dropDown'); diff --git a/Specs/Widgets/BaseLayerPicker/BaseLayerPickerSpec.js b/Specs/Widgets/BaseLayerPicker/BaseLayerPickerSpec.js index 2cafe4a05e13..39862647dfa4 100644 --- a/Specs/Widgets/BaseLayerPicker/BaseLayerPickerSpec.js +++ b/Specs/Widgets/BaseLayerPicker/BaseLayerPickerSpec.js @@ -2,24 +2,32 @@ defineSuite([ 'Widgets/BaseLayerPicker/BaseLayerPicker', 'Scene/ImageryLayerCollection', + 'Scene/EllipsoidTerrainProvider', 'Specs/EventHelper' ], function( BaseLayerPicker, ImageryLayerCollection, + EllipsoidTerrainProvider, EventHelper) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + var MockCentralBody = function(){ + this.imageryLayers = new ImageryLayerCollection(); + this.terrainProvider = new EllipsoidTerrainProvider(); + }; + it('can create and destroy', function() { var container = document.createElement('div'); container.id = 'testContainer'; document.body.appendChild(container); - var layers = new ImageryLayerCollection(); - - var widget = new BaseLayerPicker('testContainer', layers); + var centralBody = new MockCentralBody(); + var widget = new BaseLayerPicker('testContainer', { + centralBody : centralBody + }); expect(widget.container).toBe(container); - expect(widget.viewModel.imageryLayers).toBe(layers); + expect(widget.viewModel.centralBody).toBe(centralBody); expect(widget.isDestroyed()).toEqual(false); widget.destroy(); expect(widget.isDestroyed()).toEqual(true); @@ -32,7 +40,9 @@ defineSuite([ container.id = 'testContainer'; document.body.appendChild(container); - var widget = new BaseLayerPicker('testContainer', new ImageryLayerCollection()); + var widget = new BaseLayerPicker('testContainer', { + centralBody : new MockCentralBody() + }); widget.viewModel.dropDownVisible = true; EventHelper.fireMouseDown(document.body); @@ -51,7 +61,9 @@ defineSuite([ container.id = 'testContainer'; document.body.appendChild(container); - var widget = new BaseLayerPicker('testContainer', new ImageryLayerCollection()); + var widget = new BaseLayerPicker('testContainer', { + centralBody : new MockCentralBody() + }); widget.viewModel.dropDownVisible = true; @@ -75,13 +87,17 @@ defineSuite([ it('constructor throws with no element', function() { expect(function() { - return new BaseLayerPicker(undefined, new ImageryLayerCollection()); + return new BaseLayerPicker(undefined, { + centralBody : new MockCentralBody() + }); }).toThrowDeveloperError(); }); it('constructor throws with string element that does not exist', function() { expect(function() { - return new BaseLayerPicker('does not exist', new ImageryLayerCollection()); + return new BaseLayerPicker('does not exist', { + centralBody : new MockCentralBody() + }); }).toThrowDeveloperError(); }); }); \ No newline at end of file diff --git a/Specs/Widgets/BaseLayerPicker/BaseLayerPickerViewModelSpec.js b/Specs/Widgets/BaseLayerPicker/BaseLayerPickerViewModelSpec.js index dbd1c68bdbda..5b3fc6ab9df3 100644 --- a/Specs/Widgets/BaseLayerPicker/BaseLayerPickerViewModelSpec.js +++ b/Specs/Widgets/BaseLayerPicker/BaseLayerPickerViewModelSpec.js @@ -1,15 +1,22 @@ /*global defineSuite*/ defineSuite([ 'Widgets/BaseLayerPicker/BaseLayerPickerViewModel', - 'Widgets/BaseLayerPicker/ImageryProviderViewModel', + 'Widgets/BaseLayerPicker/ProviderViewModel', + 'Scene/EllipsoidTerrainProvider', 'Scene/ImageryLayerCollection' ], function( BaseLayerPickerViewModel, - ImageryProviderViewModel, + ProviderViewModel, + EllipsoidTerrainProvider, ImageryLayerCollection) { "use strict"; /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/ + var MockCentralBody = function() { + this.imageryLayers = new ImageryLayerCollection(); + this.terrainProvider = new EllipsoidTerrainProvider(); + }; + var testProvider = { isReady : function() { return false; @@ -28,7 +35,7 @@ defineSuite([ } }; - var testProviderViewModel = new ImageryProviderViewModel({ + var testProviderViewModel = new ProviderViewModel({ name : 'name', tooltip : 'tooltip', iconUrl : 'url', @@ -37,74 +44,138 @@ defineSuite([ } }); - var testProviderViewModel2 = new ImageryProviderViewModel({ - name : 'name', - tooltip : 'tooltip', - iconUrl : 'url', + var testProviderViewModel2 = new ProviderViewModel({ + name : 'name2', + tooltip : 'tooltip2', + iconUrl : 'url2', creationFunction : function() { return [testProvider, testProvider2]; } }); + var testProviderViewModel3 = new ProviderViewModel({ + name : 'name3', + tooltip : 'tooltip3', + iconUrl : 'url3', + creationFunction : function() { + return testProvider3; + } + }); + it('constructor sets expected values', function() { - var array = []; - var imageryLayers = new ImageryLayerCollection(); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, array); - expect(viewModel.imageryLayers).toBe(imageryLayers); - expect(viewModel.imageryProviderViewModels).toEqual(array); + var imageryViewModels = []; + var terrainViewModels = []; + + var centralBody = new MockCentralBody(); + + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels, + terrainProviderViewModels : terrainViewModels + }); + expect(viewModel.centralBody).toBe(centralBody); + expect(viewModel.imageryProviderViewModels).toEqual(imageryViewModels); + expect(viewModel.terrainProviderViewModels).toEqual(terrainViewModels); + }); + + it('selecting imagery closes the dropDown', function() { + var imageryViewModels = [testProviderViewModel]; + var centralBody = new MockCentralBody(); + var imageryLayers = centralBody.imageryLayers; + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels + }); + + viewModel.dropDownVisible = true; + viewModel.selectedImagery = testProviderViewModel; + expect(viewModel.dropDownVisible).toEqual(false); }); - it('selecting an item closes the dropDown', function() { - var array = [testProviderViewModel]; - var imageryLayers = new ImageryLayerCollection(); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, array); + it('selecting terrain closes the dropDown', function() { + var imageryViewModels = [testProviderViewModel]; + var centralBody = new MockCentralBody(); + var imageryLayers = centralBody.imageryLayers; + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels + }); viewModel.dropDownVisible = true; - viewModel.selectedItem = testProviderViewModel; + viewModel.selectedTerrain = testProviderViewModel; expect(viewModel.dropDownVisible).toEqual(false); }); - it('selectedName, selectedIconUrl, and selectedItem all return expected values', function() { - var array = [testProviderViewModel]; - var imageryLayers = new ImageryLayerCollection(); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, array); + it('tooltip, buttonImageUrl, and selectedImagery all return expected values', function() { + var imageryViewModels = [testProviderViewModel]; + var terrainViewModels = [testProviderViewModel3]; + var centralBody = new MockCentralBody(); + var imageryLayers = centralBody.imageryLayers; + + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels, + terrainProviderViewModels : terrainViewModels + }); - expect(viewModel.selectedName).toBeUndefined(); - expect(viewModel.selectedIconUrl).toBeUndefined(); - expect(viewModel.selectedItem).toBeUndefined(); + viewModel.selectedImagery = testProviderViewModel; + expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name + '\n' + testProviderViewModel3.name); - viewModel.selectedItem = testProviderViewModel; + viewModel.selectedImagery = undefined; + expect(viewModel.buttonTooltip).toEqual(testProviderViewModel3.name); - expect(viewModel.selectedName).toEqual(testProviderViewModel.name); - expect(viewModel.selectedIconUrl).toEqual(testProviderViewModel.iconUrl); - expect(viewModel.selectedItem).toBe(testProviderViewModel); + viewModel.selectedImagery = testProviderViewModel; + viewModel.selectedTerrain = undefined; + expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name); + + expect(viewModel.buttonImageUrl).toEqual(testProviderViewModel.iconUrl); }); - it('selectedItem actually sets base layer', function() { - var array = [testProviderViewModel]; - var imageryLayers = new ImageryLayerCollection(); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, array); + it('selectedImagery actually sets base layer', function() { + var imageryViewModels = [testProviderViewModel]; + var centralBody = new MockCentralBody(); + var imageryLayers = centralBody.imageryLayers; + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels + }); - expect(imageryLayers.length).toEqual(0); + expect(imageryLayers.length).toEqual(1); - viewModel.selectedItem = testProviderViewModel; + viewModel.selectedImagery = testProviderViewModel; expect(imageryLayers.length).toEqual(1); expect(imageryLayers.get(0).imageryProvider).toBe(testProvider); - viewModel.selectedItem = testProviderViewModel2; + viewModel.selectedImagery = testProviderViewModel2; expect(imageryLayers.length).toEqual(2); expect(imageryLayers.get(0).imageryProvider).toBe(testProvider); expect(imageryLayers.get(1).imageryProvider).toBe(testProvider2); }); - it('settings selectedItem only removes layers added by view model', function() { - var array = [testProviderViewModel]; - var imageryLayers = new ImageryLayerCollection(); - var viewModel = new BaseLayerPickerViewModel(imageryLayers, array); + it('selectedTerrain actually sets terrainPRovider', function() { + var terrainProviderViewModels = [testProviderViewModel, testProviderViewModel3]; + var centralBody = new MockCentralBody(); + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + terrainProviderViewModels : terrainProviderViewModels + }); - expect(imageryLayers.length).toEqual(0); + viewModel.selectedTerrain = testProviderViewModel3; + expect(centralBody.terrainProvider).toBe(testProvider3); + }); + + it('settings selectedImagery only removes layers added by view model', function() { + var imageryViewModels = [testProviderViewModel]; + var centralBody = new MockCentralBody(); + var imageryLayers = centralBody.imageryLayers; + var viewModel = new BaseLayerPickerViewModel({ + centralBody : centralBody, + imageryProviderViewModels : imageryViewModels + }); - viewModel.selectedItem = testProviderViewModel2; + expect(imageryLayers.length).toEqual(1); + + viewModel.selectedImagery = testProviderViewModel2; expect(imageryLayers.length).toEqual(2); expect(imageryLayers.get(0).imageryProvider).toBe(testProvider); expect(imageryLayers.get(1).imageryProvider).toBe(testProvider2); @@ -112,15 +183,16 @@ defineSuite([ imageryLayers.addImageryProvider(testProvider3, 1); imageryLayers.remove(imageryLayers.get(0)); - viewModel.selectedItem = undefined; + viewModel.selectedImagery = undefined; expect(imageryLayers.length).toEqual(1); expect(imageryLayers.get(0).imageryProvider).toBe(testProvider3); }); - it('dropDownVisible and toggleDropDown work', function() { - var viewModel = new BaseLayerPickerViewModel(new ImageryLayerCollection()); + var viewModel = new BaseLayerPickerViewModel({ + centralBody : new MockCentralBody() + }); expect(viewModel.dropDownVisible).toEqual(false); viewModel.toggleDropDown(); @@ -129,16 +201,9 @@ defineSuite([ expect(viewModel.dropDownVisible).toEqual(false); }); - it('constructor throws with no layer collection', function() { - expect(function() { - return new BaseLayerPickerViewModel(undefined); - }).toThrowDeveloperError(); - }); - - it('constructor throws if viewModels argument is not an array', function() { - var imageryLayers = new ImageryLayerCollection(); + it('constructor throws with no centralBody', function() { expect(function() { - return new BaseLayerPickerViewModel(imageryLayers, {}); + return new BaseLayerPickerViewModel({}); }).toThrowDeveloperError(); }); }); \ No newline at end of file diff --git a/Specs/Widgets/BaseLayerPicker/ImageryProviderViewModelSpec.js b/Specs/Widgets/BaseLayerPicker/ProviderViewModelSpec.js similarity index 85% rename from Specs/Widgets/BaseLayerPicker/ImageryProviderViewModelSpec.js rename to Specs/Widgets/BaseLayerPicker/ProviderViewModelSpec.js index 4ddf2cefd663..47911b14a982 100644 --- a/Specs/Widgets/BaseLayerPicker/ImageryProviderViewModelSpec.js +++ b/Specs/Widgets/BaseLayerPicker/ProviderViewModelSpec.js @@ -1,10 +1,10 @@ /*global defineSuite*/ defineSuite([ - 'Widgets/BaseLayerPicker/ImageryProviderViewModel', + 'Widgets/BaseLayerPicker/ProviderViewModel', 'Widgets/createCommand', 'ThirdParty/knockout' ], function( - ImageryProviderViewModel, + ProviderViewModel, createCommand, knockout) { "use strict"; @@ -24,7 +24,7 @@ defineSuite([ creationFunction : createCommand(spyCreationFunction) }; - var viewModel = new ImageryProviderViewModel(description); + var viewModel = new ProviderViewModel(description); expect(viewModel.name).toBe(description.name()); expect(viewModel.tooltip).toBe(description.tooltip()); expect(viewModel.iconUrl).toBe(description.iconUrl()); @@ -42,7 +42,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -54,7 +54,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -66,7 +66,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -78,7 +78,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); }); @@ -92,7 +92,7 @@ defineSuite([ creationFunction : spyCreationFunction }; - var viewModel = new ImageryProviderViewModel(description); + var viewModel = new ProviderViewModel(description); expect(viewModel.name).toEqual(description.name); expect(viewModel.tooltip).toEqual(description.tooltip); expect(viewModel.iconUrl).toEqual(description.iconUrl); @@ -110,7 +110,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -122,7 +122,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -134,7 +134,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); @@ -146,7 +146,7 @@ defineSuite([ }; expect(function() { - return new ImageryProviderViewModel(description); + return new ProviderViewModel(description); }).toThrowDeveloperError(); }); }); diff --git a/Specs/Widgets/Viewer/ViewerSpec.js b/Specs/Widgets/Viewer/ViewerSpec.js index 216dd8ae9325..27e11dfad6b4 100644 --- a/Specs/Widgets/Viewer/ViewerSpec.js +++ b/Specs/Widgets/Viewer/ViewerSpec.js @@ -3,7 +3,7 @@ defineSuite([ 'Widgets/Viewer/Viewer', 'Widgets/Animation/Animation', 'Widgets/BaseLayerPicker/BaseLayerPicker', - 'Widgets/BaseLayerPicker/ImageryProviderViewModel', + 'Widgets/BaseLayerPicker/ProviderViewModel', 'Widgets/CesiumWidget/CesiumWidget', 'Widgets/FullscreenButton/FullscreenButton', 'Widgets/HomeButton/HomeButton', @@ -24,7 +24,7 @@ defineSuite([ Viewer, Animation, BaseLayerPicker, - ImageryProviderViewModel, + ProviderViewModel, CesiumWidget, FullscreenButton, HomeButton, @@ -50,7 +50,7 @@ defineSuite([ } }; - var testProviderViewModel = new ImageryProviderViewModel({ + var testProviderViewModel = new ProviderViewModel({ name : 'name', tooltip : 'tooltip', iconUrl : 'url', @@ -265,6 +265,7 @@ defineSuite([ var provider = new EllipsoidTerrainProvider(); viewer = new Viewer(container, { + baseLayerPicker : false, terrainProvider : provider }); expect(viewer.centralBody.terrainProvider).toBe(provider); @@ -323,7 +324,7 @@ defineSuite([ }); expect(viewer.centralBody.imageryLayers.length).toEqual(1); expect(viewer.centralBody.imageryLayers.get(0).imageryProvider).toBe(testProvider); - expect(viewer.baseLayerPicker.viewModel.selectedItem).toBe(testProviderViewModel); + expect(viewer.baseLayerPicker.viewModel.selectedImagery).toBe(testProviderViewModel); }); it('can set imageryProvider when BaseLayerPicker is disabled', function() { @@ -343,7 +344,7 @@ defineSuite([ }); expect(viewer.centralBody.imageryLayers.length).toEqual(1); expect(viewer.centralBody.imageryLayers.get(0).imageryProvider).toBe(testProvider); - expect(viewer.baseLayerPicker.viewModel.selectedItem).toBe(testProviderViewModel); + expect(viewer.baseLayerPicker.viewModel.selectedImagery).toBe(testProviderViewModel); expect(viewer.baseLayerPicker.viewModel.imageryProviderViewModels).toEqual(models); });