3.14.8. Eigene Icon Bibliotheken - Trennung von API und Implementierung

Im folgenden soll beschrieben werden, wie man eine Icon Bibliothek erstellt, bei der die Definition der Image Konstanten (API) und die Bereitstellung der konkreten Icons (Implementierung) getrennt ist.

Dieser Ansatz eignet sich sowohl für die Erstellung logischer-, als auch für die Erstellung konkreter Icon Bibliotheken. Die Trennung könnte wie folgt motiviert sein:

Definition der Icon Konstanten

Das folgende Beispiel zeigt die Definition der Icons für eine Audio Player Widget Bibliothek.

  1  public enum AudioIcons implements IImageConstant {
  2  
  3      PLAY,
  4      STOP,
  5      PAUSE,
  6      FORWARD,
  7      REWIND,
  8  
  9      NEXT,
 10      PREVIOUS,
 11      FIRST,
 12      LAST,
 13  
 14      MUTED,
 15      NOT_MUTED,
 16  
 17      LOUDSPEAKER,
 18      EDIT_AUDIO_SETTINGS
 19  
 20  }

Die Icon Konstanten können dann für das Default Setup der Widgets und / oder innerhalb der Implementierung verwendet werden.

Registrierung der konkreten Icons

Die folgende Klasse verwendet die Klasse AbstractResourceImageInitializer für die Registrierung der konkreten Icons:

  1  package org.mycompany.audio.impl;
  2  
  3  import org.jowidgets.common.image.IImageRegistry;
  4  import org.jowidgets.tools.image.AbstractResourceImageInitializer;
  5  
  6  public final class AudioIconsInitializer extends AbstractResourceImageInitializer {
  7  
  8      public AudioIconsInitializer(final IImageRegistry registry) {
  9          super(AudioIconsInitializer.class, registry, "org/mycompany/audio/impl/icons/");
 10      }
 11  
 12      @Override
 13      public void doRegistration() {
 14          registerResourceImage(AudioIcons.PLAY, "play.png");
 15          registerResourceImage(AudioIcons.STOP, "stop.png");
 16          registerResourceImage(AudioIcons.PAUSE, "pause.png");
 17          registerResourceImage(AudioIcons.FORWARD, "forward.png");
 18          registerResourceImage(AudioIcons.REWIND, "rewind.png");
 19  
 20          registerResourceImage(AudioIcons.NEXT, "next.png");
 21          registerResourceImage(AudioIcons.PREVIOUS, "previous.png");
 22          registerResourceImage(AudioIcons.FIRST, "first.png");
 23          registerResourceImage(AudioIcons.LAST, "last.png");
 24  
 25          registerResourceImage(AudioIcons.MUTED, "muted.png");
 26          registerResourceImage(AudioIcons.NOT_MUTED, "not_muted.png");
 27  
 28          registerResourceImage(AudioIcons.LOUDSPEAKER, "loudspeaker.png");
 29          registerResourceImage(AudioIcons.EDIT_AUDIO_SETTINGS, "edit_audio_settings.png");
 30  
 31          //do this, if your are assuming that this initializer should initialize all icons
 32          checkEnumAvailability(AudioIcons.class);
 33      }
 34  
 35  }

Der Test in Zeile 32 ist optional und würde für den Fall, dass man z.B. vergessen hätte, ein Icon zu registrieren, eine IllegalStateException werfen. Wenn man zum Beispiel die Konstanten der Bibliothek erweitert, und die konkrete Registrierung vergisst, oder z.B. aus Versehen zwei mal den gleichen key für unterschiedliche Icons verwendet, tritt der Fehler bereits beim Starten der Applikation auf, was z.B. für einen Smoketest hilfreich ist, und nicht erst später, wenn das fehlende Icon verwendet wird.

Die folgende Abbildung zeigt die zugehörigen Icon Dateien innerhalb der Resourcen der Implementierung:

Abbildung 37. Audio Icon Resourcen

Audio Icon Resourcen

Registrierung mittels Toolkit Interceptor

Um sicher zu Stellen, dass die Icons vor der ersten Verwendung registriert sind, wird empfohlen, die Registrierung innerhalb eines Toolkit Interceptors durchzuführen. Das folgende Beispiel nutzt dazu die abstrakte Klasse AbstractToolkitInterceptorHolder:

  1  package org.mycompany.audio.impl;
  2  
  3  import org.jowidgets.api.toolkit.IToolkit;
  4  import org.jowidgets.api.toolkit.IToolkitInterceptor;
  5  import org.jowidgets.tools.toolkit.AbstractToolkitInterceptorHolder;
  6  
  7  public final class AudioIconsInitializerToolkitInterceptor 
  8      extends AbstractToolkitInterceptorHolder {
  9  
 10      @Override
 11      protected IToolkitInterceptor createToolkitInterceptor() {
 12          return new IToolkitInterceptor() {
 13              @Override
 14              public void onToolkitCreate(final IToolkit toolkit) {
 15                  final AudioIconsInitializer initializer 
 16                      = new AudioIconsInitializer(toolkit.getImageRegistry());
 17                  initializer.doRegistration();
 18              }
 19          };
 20      }
 21  
 22  }

Um diesen mit Hilfe des Java ServiceLoader Mechanismus zu registrieren, kann man unter META-INF/services eine Datei mit dem Namen org.jowidgets.api.toolkit.IToolkitInterceptorHolder und dem Inhalt:

org.jowidgets.helloworld.common.AudioIconsInitializerToolkitInterceptor

ablegen. Die folgende Abbildung soll das verdeutlichen:

Abbildung 38. Icon Toolkit Interceptor

Icon Toolkit Interceptor

Dadurch werden die Icons automatisch registriert, wenn man das Modul org.mycompany.audio.impl im Classpath hat, und zwar bevor das jowidgets Toolkit verwendet wird, da der Interceptor bei der Erzeugung des Toolkit ausgeführt wird.


Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation