| /******************************************************************************* |
| * Copyright (c) 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jface.layout; |
| import org.eclipse.jface.util.Geometry; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Layout; |
| import org.eclipse.swt.widgets.Scrollable; |
| |
| /* package */class LayoutGenerator { |
| |
| /** |
| * Default size for controls with varying contents |
| */ |
| private static final Point defaultSize = new Point(150, 150); |
| |
| /** |
| * Default wrapping size for wrapped labels |
| */ |
| private static final int wrapSize = 350; |
| |
| private static final GridDataFactory nonWrappingLabelData = GridDataFactory.fillDefaults().align(SWT.BEGINNING, SWT.CENTER).grab(false, false); |
| |
| private static boolean hasStyle(Control c, int style) { |
| return (c.getStyle() & style) != 0; |
| } |
| |
| /** |
| * Generates a GridLayout for the given composite by examining its child |
| * controls and attaching layout data to any immediate children that do not |
| * already have layout data. |
| * |
| * @param toGenerate |
| * composite to generate a layout for |
| * @param columns |
| * number of columns for the layout |
| */ |
| public static void generateLayout(Composite toGenerate) { |
| Control[] children = toGenerate.getChildren(); |
| |
| for (int i = 0; i < children.length; i++) { |
| Control control = children[i]; |
| |
| // Skip any children that already have layout data |
| if (control.getLayoutData() != null) { |
| continue; |
| } |
| |
| applyLayoutDataTo(control); |
| } |
| } |
| |
| private static void applyLayoutDataTo(Control control) { |
| if (control instanceof Button) { |
| Button button = (Button) control; |
| |
| if (hasStyle(button, SWT.CHECK)) { |
| nonWrappingLabelData.applyTo(button); |
| } else { |
| GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).hint(Geometry.max(button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true), LayoutConstants.getMinButtonSize())) |
| .applyTo(button); |
| } |
| return; |
| } |
| |
| // if (control instanceof Label) { |
| // Label label = (Label) control; |
| // |
| // if (hasStyle(label, SWT.WRAP)) { |
| // wrappingLabelData.applyTo(label); |
| // } else { |
| // nonWrappingLabelData.applyTo(label); |
| // } |
| // return; |
| // } |
| |
| if (control instanceof Scrollable) { |
| Scrollable scrollable = (Scrollable) control; |
| |
| if (scrollable instanceof Composite) { |
| Composite composite = (Composite) scrollable; |
| |
| Layout theLayout = composite.getLayout(); |
| if (theLayout instanceof GridLayout) { |
| boolean growsHorizontally = false; |
| boolean growsVertically = false; |
| |
| Control[] children = composite.getChildren(); |
| for (int i = 0; i < children.length; i++) { |
| Control child = children[i]; |
| |
| GridData data = (GridData) child.getLayoutData(); |
| |
| if (data != null) { |
| if (data.grabExcessHorizontalSpace) { |
| growsHorizontally = true; |
| } |
| if (data.grabExcessVerticalSpace) { |
| growsVertically = true; |
| } |
| } |
| } |
| |
| GridDataFactory.fillDefaults().grab(growsHorizontally, growsVertically).applyTo(control); |
| return; |
| } |
| } |
| } |
| |
| boolean wrapping = hasStyle(control, SWT.WRAP); |
| |
| // Assume any control with the H_SCROLL or V_SCROLL flags are |
| // horizontally or vertically |
| // scrollable, respectively. |
| boolean hScroll = hasStyle(control, SWT.H_SCROLL); |
| boolean vScroll = hasStyle(control, SWT.V_SCROLL); |
| |
| boolean containsText = hasMethod(control, "setText", new Class[] { String.class }); //$NON-NLS-1$ |
| |
| // If the control has a setText method, an addModifyListener method, and |
| // does not have |
| // the SWT.READ_ONLY flag, assume it contains user-editable text. |
| boolean userEditable = !hasStyle(control, SWT.READ_ONLY) && containsText && hasMethod(control, "addModifyListener", new Class[] { ModifyListener.class }); //$NON-NLS-1$ |
| |
| // For controls containing user-editable text... |
| if (userEditable) { |
| if (hasStyle(control, SWT.MULTI)) { |
| vScroll = true; |
| } |
| |
| if (!wrapping) { |
| hScroll = true; |
| } |
| } |
| |
| // Compute the horizontal hint |
| int hHint = SWT.DEFAULT; |
| boolean grabHorizontal = hScroll; |
| |
| // For horizontally-scrollable controls, override their horizontal |
| // preferred size |
| // with a constant |
| if (hScroll) { |
| hHint = defaultSize.x; |
| } else { |
| // For wrapping controls, there are two cases. |
| // 1. For controls that contain text (like wrapping labels, |
| // read-only text boxes, |
| // etc.) override their preferred size with the preferred wrapping |
| // point and |
| // make them grab horizontal space. |
| // 2. For non-text controls (like wrapping toolbars), assume that |
| // their non-wrapped |
| // size is best. |
| |
| if (wrapping) { |
| if (containsText) { |
| hHint = wrapSize; |
| grabHorizontal = true; |
| } |
| } |
| } |
| |
| int vAlign = SWT.FILL; |
| |
| // Heuristic for labels: Controls that contain non-wrapping read-only |
| // text should be |
| // center-aligned rather than fill-aligned |
| if (!vScroll && !wrapping && !userEditable && containsText) { |
| vAlign = SWT.CENTER; |
| } |
| |
| GridDataFactory.fillDefaults().grab(grabHorizontal, vScroll).align(SWT.FILL, vAlign).hint(hHint, vScroll ? defaultSize.y : SWT.DEFAULT).applyTo(control); |
| return; |
| } |
| |
| private static boolean hasMethod(Control control, String name, Class[] parameterTypes) { |
| Class c = control.getClass(); |
| try { |
| return c.getMethod(name, parameterTypes) != null; |
| } catch (SecurityException e) { |
| return false; |
| } catch (NoSuchMethodException e) { |
| return false; |
| } |
| } |
| } |