@@ -9,6 +9,7 @@ var features = {};
99var featureCapabilities = { } ;
1010var fileReaders = { } ;
1111var rendererLayerAdjustments = { } ;
12+ var annotations = { } ;
1213var util = { } ;
1314
1415//////////////////////////////////////////////////////////////////////////////
@@ -65,7 +66,7 @@ util.createRenderer = function (name, layer, canvas, options) {
6566 * that would support those features.
6667 *
6768 * @params {string|null} name name of the desired renderer
68- * @params {boolean} noFallack if true, don't recommend a fallback
69+ * @params {boolean} noFallback if true, don't recommend a fallback
6970 * @return {string|null|false } the name of the renderer that should be used
7071 * or false if no valid renderer can be determined.
7172 */
@@ -168,6 +169,8 @@ util.rendererForFeatures = function (featureList) {
168169 * and image quads that support full transformations. The capabailities
169170 * should be defined in the base feature in a capabilities object so that
170171 * they can be referenced by that rather than an explicit string.
172+ * @returns {object } if this feature replaces an existing one, this was the
173+ * feature that was replaced. In this case, a warning is issued.
171174 */
172175//////////////////////////////////////////////////////////////////////////////
173176util . registerFeature = function ( category , name , func , capabilities ) {
@@ -176,9 +179,13 @@ util.registerFeature = function (category, name, func, capabilities) {
176179 featureCapabilities [ category ] = { } ;
177180 }
178181
179- // TODO Add warning if the name already exists
182+ var old = features [ category ] [ name ] ;
183+ if ( old ) {
184+ console . warn ( 'The ' + category + '.' + name + ' feature is already registered' ) ;
185+ }
180186 features [ category ] [ name ] = func ;
181187 featureCapabilities [ category ] [ name ] = capabilities ;
188+ return old ;
182189} ;
183190
184191//////////////////////////////////////////////////////////////////////////////
@@ -207,15 +214,22 @@ util.createFeature = function (name, layer, renderer, arg) {
207214//////////////////////////////////////////////////////////////////////////////
208215/**
209216 * Register a layer adjustment.
217+ *
218+ * @returns {object } if this layer adjustment replaces an existing one, this
219+ * was the value that was replaced. In this case, a warning is issued.
210220 */
211221//////////////////////////////////////////////////////////////////////////////
212222util . registerLayerAdjustment = function ( category , name , func ) {
213223 if ( ! ( category in rendererLayerAdjustments ) ) {
214224 rendererLayerAdjustments [ category ] = { } ;
215225 }
216226
217- // TODO Add warning if the name already exists
227+ var old = rendererLayerAdjustments [ category ] [ name ] ;
228+ if ( old ) {
229+ console . warn ( 'The ' + category + '.' + name + ' layer adjustment is already registered' ) ;
230+ }
218231 rendererLayerAdjustments [ category ] [ name ] = func ;
232+ return old ;
219233} ;
220234
221235//////////////////////////////////////////////////////////////////////////////
@@ -276,15 +290,22 @@ util.createLayer = function (name, map, arg) {
276290//////////////////////////////////////////////////////////////////////////////
277291/**
278292 * Register a new widget type
293+ *
294+ * @returns {object } if this widget replaces an existing one, this was the
295+ * value that was replaced. In this case, a warning is issued.
279296 */
280297//////////////////////////////////////////////////////////////////////////////
281298util . registerWidget = function ( category , name , func ) {
282299 if ( ! ( category in widgets ) ) {
283300 widgets [ category ] = { } ;
284301 }
285302
286- // TODO Add warning if the name already exists
303+ var old = widgets [ category ] [ name ] ;
304+ if ( old ) {
305+ console . warn ( 'The ' + category + '.' + name + ' widget is already registered' ) ;
306+ }
287307 widgets [ category ] [ name ] = func ;
308+ return old ;
288309} ;
289310
290311//////////////////////////////////////////////////////////////////////////////
@@ -308,4 +329,97 @@ util.createWidget = function (name, layer, arg) {
308329 throw new Error ( 'Cannot create unknown widget ' + name ) ;
309330} ;
310331
332+ //////////////////////////////////////////////////////////////////////////////
333+ /**
334+ * Register a new annotation type
335+ *
336+ * @param {string } name The annotation name
337+ * @param {function } func A function to call to create the annotation.
338+ * @param {object|undefined } features A map of features that are used by this
339+ * annotation. Each key is a feature that is used. If the value is true,
340+ * the that feature is always needed. If a list, then it is the set of
341+ * annotation states for which that feature is required. These can be
342+ * used to pick an pparopriate renderer when creating an annotation layer.
343+ * @returns {object } if this annotation replaces an existing one, this was the
344+ * value that was replaced. In this case, a warning is issued.
345+ */
346+ //////////////////////////////////////////////////////////////////////////////
347+ util . registerAnnotation = function ( name , func , features ) {
348+ var old = annotations [ name ] ;
349+ if ( old ) {
350+ console . warn ( 'The ' + name + ' annotation is already registered' ) ;
351+ }
352+ annotations [ name ] = { func : func , features : features || { } } ;
353+ return old ;
354+ } ;
355+
356+ //////////////////////////////////////////////////////////////////////////////
357+ /**
358+ * Get a list of registered annotation types.
359+ *
360+ * @return {array } a list of registered annotations.
361+ */
362+ //////////////////////////////////////////////////////////////////////////////
363+ util . listAnnotations = function ( ) {
364+ return Object . keys ( annotations ) ;
365+ } ;
366+
367+ //////////////////////////////////////////////////////////////////////////////
368+ /**
369+ * Get a list of required features for a set of annotations.
370+ *
371+ * @param {array|object|undefined } annotationList A list of annotations that
372+ * will be used. Instead of a list, if this is an object, the keys are the
373+ * annotation names, and the values are each a list of modes that will be
374+ * used with that annotation. For example, ['polygon', 'rectangle'] lists
375+ * features required to show those annotations in any mode, whereas
376+ * {polygon: [annotationState.done], rectangle: [annotationState.done]} only
377+ * lists features thatre are needed to show the completed annotations.
378+ * @return {array } a list of features needed for the specified annotations.
379+ * There may be duplicates in the list.
380+ */
381+ //////////////////////////////////////////////////////////////////////////////
382+ util . featuresForAnnotations = function ( annotationList ) {
383+ var features = [ ] ;
384+
385+ var annList = Array . isArray ( annotationList ) ? annotationList : Object . keys ( annotationList ) ;
386+ annList . forEach ( function ( ann ) {
387+ if ( ! annotations [ ann ] ) {
388+ return ;
389+ }
390+ Object . keys ( annotations [ ann ] . features ) . forEach ( function ( feature ) {
391+ if ( Array . isArray ( annotationList ) || annotationList [ ann ] === true ||
392+ ! Array . isArray ( annotations [ ann ] . features [ feature ] ) ) {
393+ features . push ( feature ) ;
394+ } else {
395+ annotationList [ ann ] . forEach ( function ( state ) {
396+ if ( $ . inArray ( state , annotations [ ann ] . features [ feature ] ) >= 0 ) {
397+ features . push ( feature ) ;
398+ }
399+ } ) ;
400+ }
401+ } ) ;
402+ } ) ;
403+ return features ;
404+ } ;
405+
406+ //////////////////////////////////////////////////////////////////////////////
407+ /**
408+ * Check if there is a renderer that is supported and supports a list of
409+ * annotations. If not, display a warning. This generates a list of required
410+ * features, then picks the first renderer that supports all of thse features.
411+ *
412+ * @param {array|object|undefined } annotationList A list of annotations that
413+ * will be used with this renderer. Instead of a list, if this is an object,
414+ * the keys are the annotation names, and the values are each a list of modes
415+ * that will be used with that annotation. See featuresForAnnotations for
416+ * more details.
417+ * @return {string|null|false } the name of the renderer that should be used or
418+ * false if no valid renderer can be determined.
419+ */
420+ //////////////////////////////////////////////////////////////////////////////
421+ util . rendererForAnnotations = function ( annotationList ) {
422+ return util . rendererForFeatures ( util . featuresForAnnotations ( annotationList ) ) ;
423+ } ;
424+
311425module . exports = util ;
0 commit comments