3.9.2. Custom Layouts

Bevor die vordefinierten Layouts von jowidgets vorgestellt werden, soll vorab die ILayouter Schnittstelle besprochen werden, um ein besseres Verständnis zu schaffen, was beim Layouten eines Containers passiert.

Um einen eigenes (custom) Layout zu verwenden, muss diese Schnittstelle implementiert werden:

  1  public interface ILayouter extends ILayoutDescriptor {
  2  
  3      void layout();
  4  
  5      Dimension getMinSize();
  6  
  7      Dimension getPreferredSize();
  8  
  9      Dimension getMaxSize();
 10  
 11      void invalidate();
 12  
 13  }

Die Methode layout() ist dafür zuständig, auf den Controls eines Containers die Größe und die Position zu setzen.

Die ClientArea ist der Bereich des Containers, welcher für das Zeichnen der Controls zur Verfügung steht. Die DecoratedSize ist die gesamte Größe des Containers bei einer gegebenen ClientArea Größe. Bei einem Fenster kommen zum Beispiel bei der DecoratedSize noch der Rahmen oder ein eventuelles Menü hinzu.

Die Methoden getMinSize(), getPreferredSize() und getMaxSize() geben die minimale, bevorzugte und maximale Größe des Containers zum aktuellen Zeitpunkt zurück, die der Layouter benötigt, um seine Controls zu layouten. Die zurückgegebenen Größen beziehen sich dabei auf die DecoratedSize und nicht auf die Größe der ClientArea.

Die Methode invalidate() wird aufgerufen, wenn sich die Struktur des Layouts geändert haben könnte. Dies kann ein guter Zeitpunkt sein, um gecachte Werte zu löschen.

Die Verwendung der Schnittstelle soll Anhand eines Beispiels verdeutlicht werden. Es wird ein vereinfachtes Fill Layout implementiert. Ein Fill Layout zeichnet das erste sichtbare Control eines Containers so, dass es die ClientArea voll ausfüllt. Eine Implementierung könnte wie folgt aussehen:

  1  final class FillLayout implements ILayouter {
  2  
  3      private final IContainer container;
  4  
  5      private Dimension minSize;
  6      private Dimension preferredSize;
  7  
  8      FillLayout(final IContainer container) {
  9          this.container = container;
 10      }
 11  
 12      @Override
 13      public void layout() {
 14          final IControl control = getFirstVisibleControl();
 15          if (control != null) {
 16              final Rectangle clientArea = container.getClientArea();
 17              control.setPosition(clientArea.getPosition());
 18              control.setSize(clientArea.getSize());
 19          }
 20      }
 21  
 22      @Override
 23      public Dimension getMinSize() {
 24          if (minSize == null) {
 25              this.minSize = calcMinSize();
 26          }
 27          return minSize;
 28      }
 29  
 30      @Override
 31      public Dimension getPreferredSize() {
 32          if (preferredSize == null) {
 33              this.preferredSize = calcPreferredSize();
 34          }
 35          return preferredSize;
 36      }
 37  
 38      @Override
 39      public Dimension getMaxSize() {
 40          return Dimension.MAX;
 41      }
 42  
 43      @Override
 44      public void invalidate() {
 45          minSize = null;
 46          preferredSize = null;
 47      }
 48  
 49      private Dimension calcMinSize() {
 50          final IControl control = getFirstVisibleControl();
 51          if (control != null) {
 52              return container.computeDecoratedSize(control.getMinSize());
 53          }
 54          else {
 55              return container.computeDecoratedSize(new Dimension(0, 0));
 56          }
 57      }
 58  
 59      private Dimension calcPreferredSize() {
 60          final IControl control = getFirstVisibleControl();
 61          if (control != null) {
 62              return container.computeDecoratedSize(control.getPreferredSize());
 63          }
 64          else {
 65              return container.computeDecoratedSize(new Dimension(0, 0));
 66          }
 67      }
 68      
 69      private IControl getFirstVisibleControl() {
 70          for (final IControl control : container.getChildren()) {
 71              if (control.isVisible()) {
 72                  return control;
 73              }
 74          }
 75          return null;
 76      }
 77  }

Folgendes ist dabei zu beachten:

Um einen eigenen (custom) Layouter zu implementieren, ist es eventuell hilfreich, den Source Code der vordefinierten Layout Manager zu studieren. Dieser findet sich unter anderem hier.


Siehe auch PDF Version dieses Dokuments, Jowidgets API Spezifikation