6.2.4. Kapseln eines nativen Widgets durch eine Jo Widget Schnittstelle

Man definiert zum Beispiel für das komplexe native Widget W_SWT, welches man in sein Modul X einbetten möchte, eine Widgets Schnittstelle (API_Y) inklusive Setup, bzw. BluePrint wie in Erstellung eigener Widget Bibliotheken gezeigt.

Gegen diese API_Y kann man dann im Modul X implementieren, ohne Abhängigkeiten auf die native UI Technologie SWT haben zu müssen.

Man erstellt zusätzlich für die API_Y ein Impl_Y_SWT Modul, welches die nativen UI Abhängigkeiten beinhalten, und die Widget Schnittstelle mit Hilfe von Widget W_SWT adaptiert.

Will man das Modul X später mit anderen UI Technologien verwenden, muss man nur eine weitere Implementierung z.B. Impl_Y_SWING für API_Y anbieten, ohne dass man Modul X nochmal anfassen muss.

Je öfter man das native Widget W_SWT einbetten möchte, desto mehr rechtfertigt dies das im ersten Schritte aufwändigere Vorgehen.

Will man beispielsweise für das native Widget W_SWT von vornherein für Swing und Swt eine Implementierung haben haben, ohne Wigdet W_SWT neu mit Swing zu Implementieren, kann man dazu auch die Swt-Awt Bridge Widgets verwenden.

Das Addon Browser Widget

Das Browser Addon Widget IBrowser kann dabei als Beispiel dienen. Es besteht aus vier Modulen:

  • org.jowidgets.addons.widgets.browser.api beinhaltet die API für ein Browser Widget

  • org.jowidgets.addons.widgets.browser.impl.swt.common beinhalten eine Implementierung, welche die Browser Widget Schnittstellen der API mit Hilfe des nativen Swt Browser implementiert.

  • org.jowidgets.addons.widgets.browser.impl.swt beinhaltet einen Toolkit Interceptor, welcher das Browser Widget aus dem ...impl.swt.common Modul in der Generic Widget Factory registriert.

  • org.jowidgets.addons.widgets.browser.impl.swing beinhaltet einen Toolkit Interceptor, welcher das Browser Widget aus dem ...impl.swt.common Modul mit Hilfe des AwtSwtControl nach Swing bridged und es in der Generic Widget Factory registriert.

Der folgende Code zeigt die BrowserFactory aus org.jowidgets.addons.widgets.browser.impl.swt:

  1  final class BrowserFactory implements IWidgetFactory<IBrowser, IBrowserBluePrint> {
  2  
  3      @Override
  4      public IBrowser create(final Object parentUiReference, final IBrowserBluePrint bluePrint) {
  5          final IComposite composite = Toolkit.getWidgetFactory().create(
  6              parentUiReference,
  7              BPF.composite());
  8          return SwtBrowserFactory.createBrowser(
  9              composite, 
 10              (Composite) composite.getUiReference(), 
 11              bluePrint);
 12      }
 13  }

Der folgende Code zeigt die BrowserFactory aus org.jowidgets.addons.widgets.browser.impl.swing:

  1  final class BrowserFactory implements IWidgetFactory<IBrowser, IBrowserBluePrint> {
  2  
  3      @Override
  4      public IBrowser create(final Object parentUiReference, final IBrowserBluePrint bluePrint) {
  5          final IAwtSwtControl awtSwtControl 
  6              = AwtSwtControlFactory.getInstance().createAwtSwtControl(parentUiReference);
  7          return SwtBrowserFactory.createBrowser(
  8              awtSwtControl, 
  9              awtSwtControl.getSwtComposite(), 
 10              bluePrint);
 11      }
 12  
 13  }

In beiden Fällen wird das Widget wie folgt mittels eines IToolkitInterceptor registriert:

  1  final class BrowserToolkitInterceptor implements IToolkitInterceptor {
  2  
  3      @Override
  4      public void onToolkitCreate(final IToolkit toolkit) {
  5          final IGenericWidgetFactory widgetFactory = toolkit.getWidgetFactory();
  6          widgetFactory.register(IBrowserBluePrint.class, new BrowserFactory());
  7          toolkit.getBluePrintProxyFactory().addDefaultsInitializer(
  8              IBrowserSetupBuilder.class, 
  9              new BrowserDefaults());
 10      }
 11  }
Definition der Schnittstelle bei Verwendung der SWT - AWT Bridge

Wenn man ein natives Widget mit Hilfe der Swt-Awt Bridge Widgets integrieren möchte, sollte man bei der Definition der Schnittstelle darauf achten, den Anteil, der gebridget wird, möglichst minmal zu halten. Dies soll an einem Beispiel verdeutlicht werden:

In einem SWT Projekt soll der legacy Text Editor MyEditorPanel, der in Swing Implementiert ist, verwendet werden. Das MyEditorPanel hat eine Toolbar, mit der bestimmte Aktion ausgeführt werden können, wie zum Beispiel dem Ändern der Textfarbe oder Schriftart. Der komplexe Anteil der Implementierung steckt jedoch MyEditorTextPane, welches das JTextPane erweitert, und komplexe Textdekorierungen umsetzt. Dann wäre es eventuell sinnvoll, nur für das MyEditorTextPane die Jo Widget Schnittstelle IMyEditorTextPane zu definieren und für die Implementierung die SwtAwtBridge zu verwenden. Anschließend könnte man die Schnittstelle IMyEditorPanel definieren, wodurch der Toolbar Aspekt und eventuell weitere hinzukommen. Dieses Widget müsste man dann nur ein Mal implementieren und könnte dafür die Schnittstelle IMyEditorTextPane verwenden, wodurch man dann insbesondere keine Abhängigkeiten zu Swing hat. Dieses Vorgehen hat zwei Vorteile:

  1. Die Toolbar wir nicht gebridged. Das bedeutet, die Toolbar Buttons sind unter Swing JButtons und unter Swt SwtButtons. Ein JTextPane sieht unter Swt weniger wie ein Fremdkörper aus, als zum Beispiel ein JButton oder eine JComboBox.

  2. Will man später auf die Bridge verzichten, und die Funktion nativ für Swt portieren, muss man nur das MyEditorTextPane portieren, und nicht das MyEditorPanel mit der Toolbar und evetuell noch weiteren, UI unabhängigen Funktionen. Zieht man sowieso eine spätere Portierung in Betracht, kann man auch gleich richtig schneiden.


Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation