Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend BaseLayerPicker to support terrain #1607

Merged
merged 12 commits into from
Apr 11, 2014
Prev Previous commit
Next Next commit
Changes after review.
1. BaseLayerPicker now takes an options object instead of individual parameters.
2. Minor styling fix to dropdown width so that 4 items fit when vertical scroll bar is visible.
3. Add selectedImageryProviderViewModel/selectedTerrainProviderViewModel options to BaseLayerPickerViewModel
4. Fix tooltips for default terrain providers.
mramato committed Apr 10, 2014
commit b94f851ea04f3cc4dfa6188a6b67ecfed8bcda35
2 changes: 1 addition & 1 deletion Source/Widgets/BaseLayerPicker/BaseLayerPicker.css
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
position: absolute;
top: auto;
right: 0;
width: 300px;
width: 320px;
max-height: 500px;
margin-top: 5px;
background-color: rgba(38, 38, 38, 0.75);
15 changes: 7 additions & 8 deletions Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
Original file line number Diff line number Diff line change
@@ -34,9 +34,11 @@ define([
* @constructor
*
* @param {Element} container The parent HTML container node for this widget.
* @param {CentralBody} centralBody The CentralBody to use.
* @param {ProviderViewModel[]} [imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery.
* @param {ProviderViewModel[]} [terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain.
* @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 base layer is used. This value is only valid if options.baseLayerPicker is set to true.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is only valid if options.baseLayerPicker is set to true.

In this class, I don't think this comment makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh, my bad.

* @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 base layer is used. This value is only valid if options.baseLayerPicker is set to true.
*
* @exception {DeveloperError} Element with id "container" does not exist in the document.
*
@@ -99,19 +101,16 @@ define([
* //Use the first item in the list as the current selection.
* baseLayerPicker.viewModel.selectedItem = imageryViewModels[0];
*/
var BaseLayerPicker = function(container, centralBody, imageryProviderViewModels, terrainProviderViewModels) {
var BaseLayerPicker = function(container, options) {
//>>includeStart('debug', pragmas.debug);
if (!defined(container)) {
throw new DeveloperError('container is required.');
}
if (!defined(centralBody)) {
throw new DeveloperError('centralBody is required.');
}
//>>includeEnd('debug');

container = getElement(container);

var viewModel = new BaseLayerPickerViewModel(centralBody, imageryProviderViewModels, terrainProviderViewModels);
var viewModel = new BaseLayerPickerViewModel(options);

var element = document.createElement('button');
element.type = 'button';
43 changes: 27 additions & 16 deletions Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*global define*/
define([
'../../Core/defaultValue',
'../../Core/defined',
'../../Core/defineProperties',
'../../Core/DeveloperError',
@@ -8,6 +9,7 @@ define([
'../createCommand',
'../../ThirdParty/knockout'
], function(
defaultValue,
defined,
defineProperties,
DeveloperError,
@@ -22,32 +24,28 @@ define([
* @alias BaseLayerPickerViewModel
* @constructor
*
* @param {CentralBody} centralBody The CentralBody to use.
* @param {ProviderViewModel[]} [imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery.
* @param {ProviderViewModel[]} [terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain.
* @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 base layer is used. This value is only valid if options.baseLayerPicker is set to true.
* @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 base layer is used. This value is only valid if options.baseLayerPicker is set to true.
*
* @exception {DeveloperError} imageryProviderViewModels must be an array.
* @exception {DeveloperError} terrainProviderViewModels must be an array.
*/
var BaseLayerPickerViewModel = function(centralBody, imageryProviderViewModels, terrainProviderViewModels) {
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(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');
}

if (!defined(terrainProviderViewModels)) {
terrainProviderViewModels = [];
} else if (!isArray(terrainProviderViewModels)) {
throw new DeveloperError('terrainProviderViewModels must be an array');
}

this._centralBody = centralBody;

/**
@@ -117,6 +115,11 @@ define([
return selectedImageryViewModel();
},
set : function(value) {
if (selectedImageryViewModel() === value) {
this.dropDownVisible = false;
return;
}

var i;
var currentImageryProviders = this._currentImageryProviders;
var currentImageryProvidersLength = currentImageryProviders.length;
@@ -163,6 +166,11 @@ define([
return selectedTerrainViewModel();
},
set : function(value) {
if (selectedTerrainViewModel() === value) {
this.dropDownVisible = false;
return;
}

var newProvider;
if (defined(value)) {
newProvider = value.creationCommand();
@@ -179,6 +187,9 @@ define([
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, {
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ define([
providerViewModels.push(new ProviderViewModel({
name : 'WGS84 Ellipsoid',
iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/Ellipsoid.png'),
tooltip : 'EllipsoidTerrainProvider',
tooltip : 'WGS84 standard ellipsoid, also known as EPSG:4326',
creationFunction : function() {
return new EllipsoidTerrainProvider();
}
@@ -31,7 +31,7 @@ define([
providerViewModels.push(new ProviderViewModel({
name : 'STK World Terrain meshes',
iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/STK.png'),
tooltip : 'CesiumTerrainProvider',
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',
@@ -43,7 +43,7 @@ define([
providerViewModels.push(new ProviderViewModel({
name : 'Small Terrain heightmaps and water mask',
iconUrl : buildModuleUrl('Widgets/Images/TerrainProviders/STK.png'),
tooltip : 'CesiumTerrainProvider',
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',
11 changes: 8 additions & 3 deletions Source/Widgets/Viewer/Viewer.js
Original file line number Diff line number Diff line change
@@ -315,9 +315,14 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to
if (createBaseLayerPicker) {
var imageryProviderViewModels = defaultValue(options.imageryProviderViewModels, createDefaultImageryProviderViewModels());
var terrainProviderViewModels = defaultValue(options.terrainProviderViewModels, createDefaultTerrainProviderViewModels());
baseLayerPicker = new BaseLayerPicker(toolbar, cesiumWidget.centralBody, imageryProviderViewModels, terrainProviderViewModels);
baseLayerPicker.viewModel.selectedImagery = defaultValue(options.selectedImageryProviderViewModel, imageryProviderViewModels[0]);
baseLayerPicker.viewModel.selectedTerrain = defaultValue(options.selectedTerrainProviderViewModel, terrainProviderViewModels[0]);

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');
20 changes: 15 additions & 5 deletions Specs/Widgets/BaseLayerPicker/BaseLayerPickerSpec.js
Original file line number Diff line number Diff line change
@@ -23,7 +23,9 @@ defineSuite([
document.body.appendChild(container);

var centralBody = new MockCentralBody();
var widget = new BaseLayerPicker('testContainer', centralBody);
var widget = new BaseLayerPicker('testContainer', {
centralBody : centralBody
});
expect(widget.container).toBe(container);
expect(widget.viewModel.centralBody).toBe(centralBody);
expect(widget.isDestroyed()).toEqual(false);
@@ -38,7 +40,9 @@ defineSuite([
container.id = 'testContainer';
document.body.appendChild(container);

var widget = new BaseLayerPicker('testContainer', new MockCentralBody());
var widget = new BaseLayerPicker('testContainer', {
centralBody : new MockCentralBody()
});

widget.viewModel.dropDownVisible = true;
EventHelper.fireMouseDown(document.body);
@@ -57,7 +61,9 @@ defineSuite([
container.id = 'testContainer';
document.body.appendChild(container);

var widget = new BaseLayerPicker('testContainer', new MockCentralBody());
var widget = new BaseLayerPicker('testContainer', {
centralBody : new MockCentralBody()
});

widget.viewModel.dropDownVisible = true;

@@ -81,13 +87,17 @@ defineSuite([

it('constructor throws with no element', function() {
expect(function() {
return new BaseLayerPicker(undefined, new MockCentralBody());
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 MockCentralBody());
return new BaseLayerPicker('does not exist', {
centralBody : new MockCentralBody()
});
}).toThrowDeveloperError();
});
});
75 changes: 43 additions & 32 deletions Specs/Widgets/BaseLayerPicker/BaseLayerPickerViewModelSpec.js
Original file line number Diff line number Diff line change
@@ -68,28 +68,38 @@ defineSuite([

var centralBody = new MockCentralBody();

var viewModel = new BaseLayerPickerViewModel(centralBody, imageryViewModels, terrainViewModels);
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 array = [testProviderViewModel];
var imageryViewModels = [testProviderViewModel];
var centralBody = new MockCentralBody();
var imageryLayers = centralBody.imageryLayers;
var viewModel = new BaseLayerPickerViewModel(centralBody, array);
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
imageryProviderViewModels : imageryViewModels
});

viewModel.dropDownVisible = true;
viewModel.selectedImagery = testProviderViewModel;
expect(viewModel.dropDownVisible).toEqual(false);
});

it('selecting terrain closes the dropDown', function() {
var array = [testProviderViewModel];
var imageryViewModels = [testProviderViewModel];
var centralBody = new MockCentralBody();
var imageryLayers = centralBody.imageryLayers;
var viewModel = new BaseLayerPickerViewModel(centralBody, array);
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
imageryProviderViewModels : imageryViewModels
});

viewModel.dropDownVisible = true;
viewModel.selectedTerrain = testProviderViewModel;
@@ -102,35 +112,35 @@ defineSuite([
var centralBody = new MockCentralBody();
var imageryLayers = centralBody.imageryLayers;

var viewModel = new BaseLayerPickerViewModel(centralBody, imageryViewModels, terrainViewModels);

expect(viewModel.buttonTooltip).toBeUndefined();
expect(viewModel.buttonImageUrl).toBeUndefined();
expect(viewModel.selectedImagery).toBeUndefined();
expect(viewModel.selectedTerrain).toBeUndefined();
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
imageryProviderViewModels : imageryViewModels,
terrainProviderViewModels : terrainViewModels
});

viewModel.selectedImagery = testProviderViewModel;
expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name);
expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name + '\n' + testProviderViewModel3.name);

viewModel.selectedImagery = undefined;
viewModel.selectedTerrain = testProviderViewModel3;
expect(viewModel.buttonTooltip).toEqual(testProviderViewModel3.name);

viewModel.selectedImagery = testProviderViewModel;
expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name + '\n' + testProviderViewModel3.name);
viewModel.selectedTerrain = undefined;
expect(viewModel.buttonTooltip).toEqual(testProviderViewModel.name);

expect(viewModel.buttonImageUrl).toEqual(testProviderViewModel.iconUrl);
expect(viewModel.selectedImagery).toBe(testProviderViewModel);
expect(viewModel.selectedTerrain).toBe(testProviderViewModel3);
});

it('selectedImagery actually sets base layer', function() {
var array = [testProviderViewModel];
var imageryViewModels = [testProviderViewModel];
var centralBody = new MockCentralBody();
var imageryLayers = centralBody.imageryLayers;
var viewModel = new BaseLayerPickerViewModel(centralBody, array);
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
imageryProviderViewModels : imageryViewModels
});

expect(imageryLayers.length).toEqual(0);
expect(imageryLayers.length).toEqual(1);

viewModel.selectedImagery = testProviderViewModel;
expect(imageryLayers.length).toEqual(1);
@@ -145,19 +155,25 @@ defineSuite([
it('selectedTerrain actually sets terrainPRovider', function() {
var terrainProviderViewModels = [testProviderViewModel, testProviderViewModel3];
var centralBody = new MockCentralBody();
var viewModel = new BaseLayerPickerViewModel(centralBody, [], terrainProviderViewModels);
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
terrainProviderViewModels : terrainProviderViewModels
});

viewModel.selectedTerrain = testProviderViewModel3;
expect(centralBody.terrainProvider).toBe(testProvider3);
});

it('settings selectedImagery only removes layers added by view model', function() {
var array = [testProviderViewModel];
var imageryViewModels = [testProviderViewModel];
var centralBody = new MockCentralBody();
var imageryLayers = centralBody.imageryLayers;
var viewModel = new BaseLayerPickerViewModel(centralBody, array);
var viewModel = new BaseLayerPickerViewModel({
centralBody : centralBody,
imageryProviderViewModels : imageryViewModels
});

expect(imageryLayers.length).toEqual(0);
expect(imageryLayers.length).toEqual(1);

viewModel.selectedImagery = testProviderViewModel2;
expect(imageryLayers.length).toEqual(2);
@@ -174,7 +190,9 @@ defineSuite([
});

it('dropDownVisible and toggleDropDown work', function() {
var viewModel = new BaseLayerPickerViewModel(new MockCentralBody());
var viewModel = new BaseLayerPickerViewModel({
centralBody : new MockCentralBody()
});

expect(viewModel.dropDownVisible).toEqual(false);
viewModel.toggleDropDown();
@@ -185,14 +203,7 @@ defineSuite([

it('constructor throws with no centralBody', function() {
expect(function() {
return new BaseLayerPickerViewModel(undefined);
}).toThrowDeveloperError();
});

it('constructor throws if viewModels argument is not an array', function() {
var centralBody = new MockCentralBody();
expect(function() {
return new BaseLayerPickerViewModel(centralBody, {});
return new BaseLayerPickerViewModel({});
}).toThrowDeveloperError();
});
});