Dienstag, 11. Oktober 2016

ResponsiveGridLayout - a responsive grad based Layout for SWT

I have implemented a grid based responsive SWT layout for my Document Management Software.
I believe it could be quite useful for other project and release it under the Eclipse Public License (EPL).

The layout arranges components in a grid where all cells have equal dimensions. Number of columns and column width adapts repsonsive to the available width.
Row height adapt to column width using a configurable ratio.

To see it in action please take a look at the demo video:



Here comes the source code. Please leave the header with the license and copyright information

 package biz.pinnau.dms.rcp;  
   
   
 import org.eclipse.swt.SWT;  
 import org.eclipse.swt.graphics.Point;  
 import org.eclipse.swt.widgets.Composite;  
 import org.eclipse.swt.widgets.Control;  
 import org.eclipse.swt.widgets.Layout;  
   
 /**  
  * Released under Eclipse Public License (EPL) 1.0  
  *   
  * Copyright: Peter Pinnau (peter@pinnau.biz)  
  *   
  * Gridbased SWT Layout  
  *   
  * 1. All cells have equal dimensions  
  * 2. Cell widths increases/decreases automatically and adjusts to   
  *  available width of the container  
  * 3. Cell height is calculated with a ratio + offset from calculated  
  *  cell width: height = width * ratio + offset  
  * 4. Column count can be automatically calculated according to available width  
  *   
  * @author Peter Pinnau (peter@pinnau.biz)  
  * @version 1.0  
  *   
  * Last modified: 2016-10-11  
  *   
  * Class was implemented for System Concept DMS  
  *   
  * System Concept DMS - Das papierlose Büro  
  *   
  * www.pinnau.biz/dms.html  
  *  
  */  
 public class ResponsiveGridLayout extends Layout {  
   
      /**  
       * Fixed number if columns. Default = 0 => adaptive number of columns  
       */  
      private int fixedNumColumns = 0;  
   
      /**  
       * Mimimum column width  
       */  
      private int minColumnWidth;  
        
      /**  
       * ratio to calculate row height  
       */  
      public float ratio = 1f;  
        
      /**  
       * Offset for row height calculation  
       */  
      public int offset = 0;  
        
      /**  
       * margin around grid  
       */  
      public int margin = 0;  
        
      /**  
       * spacing between cells  
       */  
      public int spacing = 10;  
             
      /**  
       * Creates an instance of the layout using a fixed number of columns  
       *   
       * @param numColumns  
       */  
      public ResponsiveGridLayout(int numColumns, int minimumColumnWidth) {  
           this.fixedNumColumns = numColumns;            
           this.minColumnWidth = minimumColumnWidth;  
      }  
        
      /**  
       * Creates an instance of the layout with adaptive number of columns depending  
       * on available width and minColumnWidth  
       *   
       * @param columnCounts  
       */  
      public ResponsiveGridLayout(int minimumColumnWidth) {  
           this.minColumnWidth = minimumColumnWidth;  
      }       
        
      private int getBoxHeight(int boxWidth) {  
           return (int) (boxWidth * ratio) + offset;  
      }  
        
      private int getNumColumns(int availableWidth) {  
           // Fixed number of columns  
           if (fixedNumColumns > 0) return fixedNumColumns;  
             
           // No available width specified  
           if (availableWidth == SWT.DEFAULT) {  
                // assume 1 column  
                return 1;  
           }  
             
           // Start with width of 1 column  
           int totalWidth = minColumnWidth + 2 * margin;  
           int numColumns = 0;  
             
           // Increase column count until totalWidth exceeds avaiblableWidth  
           while (totalWidth < availableWidth) {  
                // Add spacing + minColumnWidth (1 new column)  
                totalWidth = totalWidth + spacing + minColumnWidth;  
                                 
                numColumns++;  
           }  
             
           if (numColumns == 0) numColumns = 1;  
             
           return numColumns;            
      }  
        
      @Override  
      protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {  
           Point size = new Point(0, 0);  
             
           // Get number of columns  
           int numColumns = getNumColumns(wHint);  
           int boxWidth = getAvailableBoxWidth(wHint, numColumns);  
                       
           int componentCount = composite.getChildren().length;  
           int rows = (int) Math.ceil(componentCount / (double) numColumns);  
             
           if (rows == 0) rows = 1;  
             
           size.x = numColumns * boxWidth + (numColumns-1) * spacing + 2 * margin;  
           size.y = rows * getBoxHeight(boxWidth) + (rows-1) * spacing + 2 * margin;  
             
           return size;  
      }  
        
      /**  
       * Calculates the available cell width  
       *   
       * @param width  
       * @param numColumns  
       * @return  
       */  
      private int getAvailableBoxWidth(int width, int numColumns) {  
           if (width == SWT.DEFAULT) return minColumnWidth;  
             
           int boxWidth = (width - 2 * margin - (numColumns * spacing)) / numColumns;  
             
           if (boxWidth < minColumnWidth) return minColumnWidth;  
             
           return boxWidth;  
      }  
             
      @Override  
      protected void layout(Composite composite, boolean flushCache) {  
           Control[] children = composite.getChildren();  
        
           // Get number of columns  
           int numColumns = getNumColumns(composite.getClientArea().width);  
             
           int boxWidth = getAvailableBoxWidth(composite.getSize().x, numColumns);  
           int boxHeight = getBoxHeight(boxWidth);  
             
           // Build the grid  
           int x = margin;  
           int y = margin;  
             
           for (int i=0; i<children.length; i++) {  
                if (i % numColumns == 0) {  
                     x = margin;  
                       
                     if (i > 0) {  
                          y = y + spacing + boxHeight;   
                     } else {  
                          y = margin;  
                     }  
                } else {  
                     x = x + boxWidth + spacing;                      
                }  
                                 
                children[i].setSize(boxWidth, boxHeight);  
                children[i].setLocation(x, y);                                
           }  
      }  
 }  
   



The following example shows how to use the layout together with a ScrolledComposite.


 scroll = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL );  
   
container = new Composite(scroll, SWT.None);  
               
// Create adaptive Grid  
layout = new ResponsiveGridLayout(150);  
layout.offset = 50;  
layout.ratio = 1.5f;  
layout.margin = 5;  
layout.spacing = 5;  
               
container.setLayout(layout);              
                           
// Set the child as the scrolled content of the ScrolledComposite  
scroll.setContent(container);  
               
// Expand both horizontally and vertically  
scroll.setExpandHorizontal(true);  
scroll.setExpandVertical(true);  
               
scroll.addListener(SWT.Resize, new Listener() {                    
      @Override  
      public void handleEvent(Event event) {  
            scroll.setMinSize(container.computeSize(scroll.getClientArea().width, SWT.DEFAULT));  
      }  
});  
               
// Add some controls to container ...  

Keine Kommentare:

Kommentar veröffentlichen