BaseLayerPickerViewModel.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import defaultValue from '../../Core/defaultValue.js';
  2. import defined from '../../Core/defined.js';
  3. import defineProperties from '../../Core/defineProperties.js';
  4. import DeveloperError from '../../Core/DeveloperError.js';
  5. import EllipsoidTerrainProvider from '../../Core/EllipsoidTerrainProvider.js';
  6. import isArray from '../../Core/isArray.js';
  7. import knockout from '../../ThirdParty/knockout.js';
  8. import createCommand from '../createCommand.js';
  9. /**
  10. * The view model for {@link BaseLayerPicker}.
  11. * @alias BaseLayerPickerViewModel
  12. * @constructor
  13. *
  14. * @param {Object} options Object with the following properties:
  15. * @param {Globe} options.globe The Globe to use.
  16. * @param {ProviderViewModel[]} [options.imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery.
  17. * @param {ProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available imagery layer is used.
  18. * @param {ProviderViewModel[]} [options.terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain.
  19. * @param {ProviderViewModel} [options.selectedTerrainProviderViewModel] The view model for the current base terrain layer, if not supplied the first available terrain layer is used.
  20. *
  21. * @exception {DeveloperError} imageryProviderViewModels must be an array.
  22. * @exception {DeveloperError} terrainProviderViewModels must be an array.
  23. */
  24. function BaseLayerPickerViewModel(options) {
  25. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  26. var globe = options.globe;
  27. var imageryProviderViewModels = defaultValue(options.imageryProviderViewModels, []);
  28. var terrainProviderViewModels = defaultValue(options.terrainProviderViewModels, []);
  29. //>>includeStart('debug', pragmas.debug);
  30. if (!defined(globe)) {
  31. throw new DeveloperError('globe is required');
  32. }
  33. //>>includeEnd('debug');
  34. this._globe = globe;
  35. /**
  36. * Gets or sets an array of ProviderViewModel instances available for imagery selection.
  37. * This property is observable.
  38. * @type {ProviderViewModel[]}
  39. */
  40. this.imageryProviderViewModels = imageryProviderViewModels.slice(0);
  41. /**
  42. * Gets or sets an array of ProviderViewModel instances available for terrain selection.
  43. * This property is observable.
  44. * @type {ProviderViewModel[]}
  45. */
  46. this.terrainProviderViewModels = terrainProviderViewModels.slice(0);
  47. /**
  48. * Gets or sets whether the imagery selection drop-down is currently visible.
  49. * @type {Boolean}
  50. * @default false
  51. */
  52. this.dropDownVisible = false;
  53. knockout.track(this, ['imageryProviderViewModels', 'terrainProviderViewModels', 'dropDownVisible']);
  54. var imageryObservable = knockout.getObservable(this, 'imageryProviderViewModels');
  55. var imageryProviders = knockout.pureComputed(function() {
  56. var providers = imageryObservable();
  57. var categories = {};
  58. var i;
  59. for (i = 0; i < providers.length; i++) {
  60. var provider = providers[i];
  61. var category = provider.category;
  62. if (defined(categories[category])) {
  63. categories[category].push(provider);
  64. } else {
  65. categories[category] = [provider];
  66. }
  67. }
  68. var allCategoryNames = Object.keys(categories);
  69. var result = [];
  70. for (i = 0; i < allCategoryNames.length; i++) {
  71. var name = allCategoryNames[i];
  72. result.push({
  73. name: name,
  74. providers: categories[name]
  75. });
  76. }
  77. return result;
  78. });
  79. this._imageryProviders = imageryProviders;
  80. var terrainObservable = knockout.getObservable(this, 'terrainProviderViewModels');
  81. var terrainProviders = knockout.pureComputed(function() {
  82. var providers = terrainObservable();
  83. var categories = {};
  84. var i;
  85. for (i = 0; i < providers.length; i++) {
  86. var provider = providers[i];
  87. var category = provider.category;
  88. if (defined(categories[category])) {
  89. categories[category].push(provider);
  90. } else {
  91. categories[category] = [provider];
  92. }
  93. }
  94. var allCategoryNames = Object.keys(categories);
  95. var result = [];
  96. for (i = 0; i < allCategoryNames.length; i++) {
  97. var name = allCategoryNames[i];
  98. result.push({
  99. name: name,
  100. providers: categories[name]
  101. });
  102. }
  103. return result;
  104. });
  105. this._terrainProviders = terrainProviders;
  106. /**
  107. * Gets the button tooltip. This property is observable.
  108. * @type {String}
  109. */
  110. this.buttonTooltip = undefined;
  111. knockout.defineProperty(this, 'buttonTooltip', function() {
  112. var selectedImagery = this.selectedImagery;
  113. var selectedTerrain = this.selectedTerrain;
  114. var imageryTip = defined(selectedImagery) ? selectedImagery.name : undefined;
  115. var terrainTip = defined(selectedTerrain) ? selectedTerrain.name : undefined;
  116. if (defined(imageryTip) && defined(terrainTip)) {
  117. return imageryTip + '\n' + terrainTip;
  118. } else if (defined(imageryTip)) {
  119. return imageryTip;
  120. }
  121. return terrainTip;
  122. });
  123. /**
  124. * Gets the button background image. This property is observable.
  125. * @type {String}
  126. */
  127. this.buttonImageUrl = undefined;
  128. knockout.defineProperty(this, 'buttonImageUrl', function() {
  129. var selectedImagery = this.selectedImagery;
  130. if (defined(selectedImagery)) {
  131. return selectedImagery.iconUrl;
  132. }
  133. });
  134. /**
  135. * Gets or sets the currently selected imagery. This property is observable.
  136. * @type {ProviderViewModel}
  137. * @default undefined
  138. */
  139. this.selectedImagery = undefined;
  140. var selectedImageryViewModel = knockout.observable();
  141. this._currentImageryProviders = [];
  142. knockout.defineProperty(this, 'selectedImagery', {
  143. get : function() {
  144. return selectedImageryViewModel();
  145. },
  146. set : function(value) {
  147. if (selectedImageryViewModel() === value) {
  148. this.dropDownVisible = false;
  149. return;
  150. }
  151. var i;
  152. var currentImageryProviders = this._currentImageryProviders;
  153. var currentImageryProvidersLength = currentImageryProviders.length;
  154. var imageryLayers = this._globe.imageryLayers;
  155. var hadExistingBaseLayer = false;
  156. for (i = 0; i < currentImageryProvidersLength; i++) {
  157. var layersLength = imageryLayers.length;
  158. for ( var x = 0; x < layersLength; x++) {
  159. var layer = imageryLayers.get(x);
  160. if (layer.imageryProvider === currentImageryProviders[i]) {
  161. imageryLayers.remove(layer);
  162. hadExistingBaseLayer = true;
  163. break;
  164. }
  165. }
  166. }
  167. if (defined(value)) {
  168. var newProviders = value.creationCommand();
  169. if (isArray(newProviders)) {
  170. var newProvidersLength = newProviders.length;
  171. for (i = newProvidersLength - 1; i >= 0; i--) {
  172. imageryLayers.addImageryProvider(newProviders[i], 0);
  173. }
  174. this._currentImageryProviders = newProviders.slice(0);
  175. } else {
  176. this._currentImageryProviders = [newProviders];
  177. if (hadExistingBaseLayer) {
  178. imageryLayers.addImageryProvider(newProviders, 0);
  179. } else {
  180. var baseLayer = imageryLayers.get(0);
  181. if (defined(baseLayer)) {
  182. imageryLayers.remove(baseLayer);
  183. }
  184. imageryLayers.addImageryProvider(newProviders, 0);
  185. }
  186. }
  187. }
  188. selectedImageryViewModel(value);
  189. this.dropDownVisible = false;
  190. }
  191. });
  192. /**
  193. * Gets or sets the currently selected terrain. This property is observable.
  194. * @type {ProviderViewModel}
  195. * @default undefined
  196. */
  197. this.selectedTerrain = undefined;
  198. var selectedTerrainViewModel = knockout.observable();
  199. knockout.defineProperty(this, 'selectedTerrain', {
  200. get : function() {
  201. return selectedTerrainViewModel();
  202. },
  203. set : function(value) {
  204. if (selectedTerrainViewModel() === value) {
  205. this.dropDownVisible = false;
  206. return;
  207. }
  208. var newProvider;
  209. if (defined(value)) {
  210. newProvider = value.creationCommand();
  211. }
  212. this._globe.depthTestAgainstTerrain = !(newProvider instanceof EllipsoidTerrainProvider);
  213. this._globe.terrainProvider = newProvider;
  214. selectedTerrainViewModel(value);
  215. this.dropDownVisible = false;
  216. }
  217. });
  218. var that = this;
  219. this._toggleDropDown = createCommand(function() {
  220. that.dropDownVisible = !that.dropDownVisible;
  221. });
  222. this.selectedImagery = defaultValue(options.selectedImageryProviderViewModel, imageryProviderViewModels[0]);
  223. this.selectedTerrain = defaultValue(options.selectedTerrainProviderViewModel, terrainProviderViewModels[0]);
  224. }
  225. defineProperties(BaseLayerPickerViewModel.prototype, {
  226. /**
  227. * Gets the command to toggle the visibility of the drop down.
  228. * @memberof BaseLayerPickerViewModel.prototype
  229. *
  230. * @type {Command}
  231. */
  232. toggleDropDown : {
  233. get : function() {
  234. return this._toggleDropDown;
  235. }
  236. },
  237. /**
  238. * Gets the globe.
  239. * @memberof BaseLayerPickerViewModel.prototype
  240. *
  241. * @type {Globe}
  242. */
  243. globe : {
  244. get : function() {
  245. return this._globe;
  246. }
  247. }
  248. });
  249. export default BaseLayerPickerViewModel;