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
9 changes: 9 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -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`.
17 changes: 16 additions & 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: 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;
124 changes: 83 additions & 41 deletions Source/Widgets/BaseLayerPicker/BaseLayerPicker.js
Original file line number Diff line number Diff line change
@@ -23,23 +23,27 @@ define([
* <br />BaseLayerPicker with its drop-panel open.
* </span>
* <br /><br />
* 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,78 +96,116 @@ 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);

var imgElement = document.createElement('img');
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<hr>';
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<hr>';
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);
};

Loading