Previous Page
Next Page

7.8. Auto-sizing Table Columns

Another nice enhancement to the Favorites view is for the columns in the table to be automatically resized to fit the current space. To do this, replace the table layout by adding the following to createTableViewer() just under the table variable assignment.

AutoResizeTableLayout layout = new AutoResizeTableLayout(table);
table.setLayout(layout);

Then create this class:

package com.qualityeclipse.favorites.util;

import ...

public class AutoResizeTableLayout extends TableLayout
   implements ControlListener {
   private final Table table;
   private List columns = new ArrayList();
   private boolean autosizing = false;

   public AutoResizeTableLayout(Table table) {
      this.table = table;
      table.addControlListener(this);
   }
   public void addColumnData(ColumnLayoutData data) {
      columns.add(data);
      super.addColumnData(data);
   }

   public void controlMoved(ControlEvent e) {
   }

   public void controlResized(ControlEvent e) {
      if (autosizing)
         return;
      autosizing = true;
      try {
         autoSizeColumns();
      }
      finally {
         autosizing = false;
      }
   }

   private void autoSizeColumns() {
      int width = table.getClientArea().width;

      // XXX: Layout is being called with an invalid value
      // the first time it is being called on Linux.
      // This method resets the layout to null,
      // so we run it only when the value is OK.
      if (width <= 1)
         return;

      TableColumn[] tableColumns = table.getColumns();
      int size = Math.min(columns.size(), tableColumns.length);
      int[] widths = new int[size];
      int fixedWidth = 0;
      int numberOfWeightColumns = 0;
      int totalWeight = 0;

      // First calculate space occupied by fixed columns.
      for (int i = 0; i < size; i++) {
         ColumnLayoutData col =
            (ColumnLayoutData) columns.get(i);
         if (col instanceof ColumnPixelData) {
            int pixels = ((ColumnPixelData) col).width;
            widths[i] = pixels;
            fixedWidth += pixels;
         } else if (col instanceof ColumnWeightData) {
            ColumnWeightData cw = (ColumnWeightData) col;
            numberOfWeightColumns++;
            int weight = cw.weight;
            totalWeight += weight;
         } else {
            throw new IllegalStateException(
               "Unknown column layout data");
         }
       }
      // Do we have columns that have a weight?
      if (numberOfWeightColumns > 0) {
         // Now, distribute the rest
         // to the columns with weight.
         int rest = width - fixedWidth;
         int totalDistributed = 0;
         for (int i = 0; i < size; i++) {
            ColumnLayoutData col =
               (ColumnLayoutData) columns.get(i);
            if (col instanceof ColumnWeightData) {
               ColumnWeightData cw = (ColumnWeightData) col;
               int weight = cw.weight;
               int pixels =
                  totalWeight == 0
                     ? 0
                     : weight * rest / totalWeight;
               if (pixels < cw.minimumWidth)
                  pixels = cw.minimumWidth;
               totalDistributed += pixels;
               widths[i] = pixels;
            }
         }

         // Distribute any remaining pixels
         // to columns with weight.
         int diff = rest - totalDistributed;
         for (int i = 0; diff > 0; i++) {
            if (i == size)
               i = 0;
            ColumnLayoutData col =
               (ColumnLayoutData) columns.get(i);
            if (col instanceof ColumnWeightData) {
               ++widths[i];
               --diff;
            }
         }
      }

      for (int i = 0; i < size; i++) {
         if (tableColumns[i].getWidth() != widths[i])
            tableColumns[i].setWidth(widths[i]);
      }
   }
}

For each column, you will need to supply additional layout information. For example:

// fixed width column
layout.addColumnData(new ColumnPixelData(18));

// weighted column
layout.addColumnData(new ColumnWeightData(50));

The Favorites view can use the AutoResizeTableLayout class by modifying the code shown in Section 7.2.2, View controls, on page 264, after which the columns in the view will automatically be resized when the view is resized.

TableColumn typeColumn = new TableColumn(table, SWT.LEFT);
typeColumn.setText("");
//typeColumn.setWidth(18);
layout.addColumnData(new ColumnPixelData(18));

TableColumn nameColumn = new TableColumn(table, SWT.LEFT);
nameColumn.setText("Name");
//nameColumn.setWidth(200);
layout.addColumnData(new ColumnWeightData(200));

TableColumn locationColumn = new TableColumn(table, SWT.LEFT);
locationColumn.setText("Location");
//locationColumn.setWidth(450);
layout.addColumnData(new ColumnWeightData(200));


Previous Page
Next Page