DataSourceCollection.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. import defaultValue from "../Core/defaultValue.js";
  2. import defined from "../Core/defined.js";
  3. import destroyObject from "../Core/destroyObject.js";
  4. import DeveloperError from "../Core/DeveloperError.js";
  5. import Event from "../Core/Event.js";
  6. import CesiumMath from "../Core/Math.js";
  7. import when from "../ThirdParty/when.js";
  8. /**
  9. * A collection of {@link DataSource} instances.
  10. * @alias DataSourceCollection
  11. * @constructor
  12. */
  13. function DataSourceCollection() {
  14. this._dataSources = [];
  15. this._dataSourceAdded = new Event();
  16. this._dataSourceRemoved = new Event();
  17. this._dataSourceMoved = new Event();
  18. }
  19. Object.defineProperties(DataSourceCollection.prototype, {
  20. /**
  21. * Gets the number of data sources in this collection.
  22. * @memberof DataSourceCollection.prototype
  23. * @type {Number}
  24. * @readonly
  25. */
  26. length: {
  27. get: function () {
  28. return this._dataSources.length;
  29. },
  30. },
  31. /**
  32. * An event that is raised when a data source is added to the collection.
  33. * Event handlers are passed the data source that was added.
  34. * @memberof DataSourceCollection.prototype
  35. * @type {Event}
  36. * @readonly
  37. */
  38. dataSourceAdded: {
  39. get: function () {
  40. return this._dataSourceAdded;
  41. },
  42. },
  43. /**
  44. * An event that is raised when a data source is removed from the collection.
  45. * Event handlers are passed the data source that was removed.
  46. * @memberof DataSourceCollection.prototype
  47. * @type {Event}
  48. * @readonly
  49. */
  50. dataSourceRemoved: {
  51. get: function () {
  52. return this._dataSourceRemoved;
  53. },
  54. },
  55. /**
  56. * An event that is raised when a data source changes position in the collection. Event handlers are passed the data source
  57. * that was moved, its new index after the move, and its old index prior to the move.
  58. * @memberof DataSourceCollection.prototype
  59. * @type {Event}
  60. * @readonly
  61. */
  62. dataSourceMoved: {
  63. get: function () {
  64. return this._dataSourceMoved;
  65. },
  66. },
  67. });
  68. /**
  69. * Adds a data source to the collection.
  70. *
  71. * @param {DataSource|Promise.<DataSource>} dataSource A data source or a promise to a data source to add to the collection.
  72. * When passing a promise, the data source will not actually be added
  73. * to the collection until the promise resolves successfully.
  74. * @returns {Promise.<DataSource>} A Promise that resolves once the data source has been added to the collection.
  75. */
  76. DataSourceCollection.prototype.add = function (dataSource) {
  77. //>>includeStart('debug', pragmas.debug);
  78. if (!defined(dataSource)) {
  79. throw new DeveloperError("dataSource is required.");
  80. }
  81. //>>includeEnd('debug');
  82. var that = this;
  83. var dataSources = this._dataSources;
  84. return when(dataSource, function (value) {
  85. //Only add the data source if removeAll has not been called
  86. //Since it was added.
  87. if (dataSources === that._dataSources) {
  88. that._dataSources.push(value);
  89. that._dataSourceAdded.raiseEvent(that, value);
  90. }
  91. return value;
  92. });
  93. };
  94. /**
  95. * Removes a data source from this collection, if present.
  96. *
  97. * @param {DataSource} dataSource The data source to remove.
  98. * @param {Boolean} [destroy=false] Whether to destroy the data source in addition to removing it.
  99. * @returns {Boolean} true if the data source was in the collection and was removed,
  100. * false if the data source was not in the collection.
  101. */
  102. DataSourceCollection.prototype.remove = function (dataSource, destroy) {
  103. destroy = defaultValue(destroy, false);
  104. var index = this._dataSources.indexOf(dataSource);
  105. if (index !== -1) {
  106. this._dataSources.splice(index, 1);
  107. this._dataSourceRemoved.raiseEvent(this, dataSource);
  108. if (destroy && typeof dataSource.destroy === "function") {
  109. dataSource.destroy();
  110. }
  111. return true;
  112. }
  113. return false;
  114. };
  115. /**
  116. * Removes all data sources from this collection.
  117. *
  118. * @param {Boolean} [destroy=false] whether to destroy the data sources in addition to removing them.
  119. */
  120. DataSourceCollection.prototype.removeAll = function (destroy) {
  121. destroy = defaultValue(destroy, false);
  122. var dataSources = this._dataSources;
  123. for (var i = 0, len = dataSources.length; i < len; ++i) {
  124. var dataSource = dataSources[i];
  125. this._dataSourceRemoved.raiseEvent(this, dataSource);
  126. if (destroy && typeof dataSource.destroy === "function") {
  127. dataSource.destroy();
  128. }
  129. }
  130. this._dataSources = [];
  131. };
  132. /**
  133. * Checks to see if the collection contains a given data source.
  134. *
  135. * @param {DataSource} dataSource The data source to check for.
  136. * @returns {Boolean} true if the collection contains the data source, false otherwise.
  137. */
  138. DataSourceCollection.prototype.contains = function (dataSource) {
  139. return this.indexOf(dataSource) !== -1;
  140. };
  141. /**
  142. * Determines the index of a given data source in the collection.
  143. *
  144. * @param {DataSource} dataSource The data source to find the index of.
  145. * @returns {Number} The index of the data source in the collection, or -1 if the data source does not exist in the collection.
  146. */
  147. DataSourceCollection.prototype.indexOf = function (dataSource) {
  148. return this._dataSources.indexOf(dataSource);
  149. };
  150. /**
  151. * Gets a data source by index from the collection.
  152. *
  153. * @param {Number} index the index to retrieve.
  154. * @returns {DataSource} The data source at the specified index.
  155. */
  156. DataSourceCollection.prototype.get = function (index) {
  157. //>>includeStart('debug', pragmas.debug);
  158. if (!defined(index)) {
  159. throw new DeveloperError("index is required.");
  160. }
  161. //>>includeEnd('debug');
  162. return this._dataSources[index];
  163. };
  164. /**
  165. * Gets a data source by name from the collection.
  166. *
  167. * @param {String} name The name to retrieve.
  168. * @returns {DataSource[]} A list of all data sources matching the provided name.
  169. */
  170. DataSourceCollection.prototype.getByName = function (name) {
  171. //>>includeStart('debug', pragmas.debug);
  172. if (!defined(name)) {
  173. throw new DeveloperError("name is required.");
  174. }
  175. //>>includeEnd('debug');
  176. return this._dataSources.filter(function (dataSource) {
  177. return dataSource.name === name;
  178. });
  179. };
  180. function getIndex(dataSources, dataSource) {
  181. //>>includeStart('debug', pragmas.debug);
  182. if (!defined(dataSource)) {
  183. throw new DeveloperError("dataSource is required.");
  184. }
  185. //>>includeEnd('debug');
  186. var index = dataSources.indexOf(dataSource);
  187. //>>includeStart('debug', pragmas.debug);
  188. if (index === -1) {
  189. throw new DeveloperError("dataSource is not in this collection.");
  190. }
  191. //>>includeEnd('debug');
  192. return index;
  193. }
  194. function swapDataSources(collection, i, j) {
  195. var arr = collection._dataSources;
  196. var length = arr.length - 1;
  197. i = CesiumMath.clamp(i, 0, length);
  198. j = CesiumMath.clamp(j, 0, length);
  199. if (i === j) {
  200. return;
  201. }
  202. var temp = arr[i];
  203. arr[i] = arr[j];
  204. arr[j] = temp;
  205. collection.dataSourceMoved.raiseEvent(temp, j, i);
  206. }
  207. /**
  208. * Raises a data source up one position in the collection.
  209. *
  210. * @param {DataSource} dataSource The data source to move.
  211. *
  212. * @exception {DeveloperError} dataSource is not in this collection.
  213. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  214. */
  215. DataSourceCollection.prototype.raise = function (dataSource) {
  216. var index = getIndex(this._dataSources, dataSource);
  217. swapDataSources(this, index, index + 1);
  218. };
  219. /**
  220. * Lowers a data source down one position in the collection.
  221. *
  222. * @param {DataSource} dataSource The data source to move.
  223. *
  224. * @exception {DeveloperError} dataSource is not in this collection.
  225. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  226. */
  227. DataSourceCollection.prototype.lower = function (dataSource) {
  228. var index = getIndex(this._dataSources, dataSource);
  229. swapDataSources(this, index, index - 1);
  230. };
  231. /**
  232. * Raises a data source to the top of the collection.
  233. *
  234. * @param {DataSource} dataSource The data source to move.
  235. *
  236. * @exception {DeveloperError} dataSource is not in this collection.
  237. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  238. */
  239. DataSourceCollection.prototype.raiseToTop = function (dataSource) {
  240. var index = getIndex(this._dataSources, dataSource);
  241. if (index === this._dataSources.length - 1) {
  242. return;
  243. }
  244. this._dataSources.splice(index, 1);
  245. this._dataSources.push(dataSource);
  246. this.dataSourceMoved.raiseEvent(
  247. dataSource,
  248. this._dataSources.length - 1,
  249. index
  250. );
  251. };
  252. /**
  253. * Lowers a data source to the bottom of the collection.
  254. *
  255. * @param {DataSource} dataSource The data source to move.
  256. *
  257. * @exception {DeveloperError} dataSource is not in this collection.
  258. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  259. */
  260. DataSourceCollection.prototype.lowerToBottom = function (dataSource) {
  261. var index = getIndex(this._dataSources, dataSource);
  262. if (index === 0) {
  263. return;
  264. }
  265. this._dataSources.splice(index, 1);
  266. this._dataSources.splice(0, 0, dataSource);
  267. this.dataSourceMoved.raiseEvent(dataSource, 0, index);
  268. };
  269. /**
  270. * Returns true if this object was destroyed; otherwise, false.
  271. * If this object was destroyed, it should not be used; calling any function other than
  272. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  273. *
  274. * @returns {Boolean} true if this object was destroyed; otherwise, false.
  275. *
  276. * @see DataSourceCollection#destroy
  277. */
  278. DataSourceCollection.prototype.isDestroyed = function () {
  279. return false;
  280. };
  281. /**
  282. * Destroys the resources held by all data sources in this collection. Explicitly destroying this
  283. * object allows for deterministic release of WebGL resources, instead of relying on the garbage
  284. * collector. Once this object is destroyed, it should not be used; calling any function other than
  285. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  286. * assign the return value (<code>undefined</code>) to the object as done in the example.
  287. *
  288. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  289. *
  290. *
  291. * @example
  292. * dataSourceCollection = dataSourceCollection && dataSourceCollection.destroy();
  293. *
  294. * @see DataSourceCollection#isDestroyed
  295. */
  296. DataSourceCollection.prototype.destroy = function () {
  297. this.removeAll(true);
  298. return destroyObject(this);
  299. };
  300. export default DataSourceCollection;