RadialLayout.java Source code

Java tutorial

Introduction

Here is the source code for RadialLayout.java

Source

/*
SWT/JFace in Action
GUI Design with Eclipse 3.0
Matthew Scarpino, Stephen Holder, Stanford Ng, and Laurent Mihalkovic
    
ISBN: 1932394273
    
Publisher: Manning
*/

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;

public class RadialLayout extends Layout {
    public RadialLayout() {
        super();
    }

    protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
        Point maxDimensions = calculateMaxDimensions(composite.getChildren());
        int stepsPerHemisphere = stepsPerHemisphere(composite.getChildren().length);

        int maxWidth = maxDimensions.x;
        int maxHeight = maxDimensions.y;

        int dimensionMultiplier = (stepsPerHemisphere + 1);
        int controlWidth = maxWidth * dimensionMultiplier;
        int controlHeight = maxHeight * dimensionMultiplier;
        int diameter = Math.max(controlWidth, controlHeight);
        Point preferredSize = new Point(diameter, diameter);

        if (wHint != SWT.DEFAULT) {
            if (preferredSize.x > wHint) {
                preferredSize.x = wHint;
            }
        }

        if (hHint != SWT.DEFAULT) {
            if (preferredSize.y > hHint) {
                preferredSize.y = hHint;
            }
        }

        return preferredSize;
    }

    protected void layout(Composite composite, boolean flushCache) {
        Point[] positions = calculateControlPositions(composite);
        Control[] controls = composite.getChildren();
        for (int i = 0; i < controls.length; i++) {
            Point preferredSize = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
            controls[i].setBounds(positions[i].x, positions[i].y, preferredSize.x, preferredSize.y);
        }
    }

    private Point[] calculateControlPositions(Composite composite) {
        int controlCount = composite.getChildren().length;
        int stepsPerHemisphere = stepsPerHemisphere(controlCount);
        Point[] positions = new Point[controlCount];

        Point maxControlDimensions = calculateMaxDimensions(composite.getChildren());
        int maxControlWidth = maxControlDimensions.x;

        Rectangle clientArea = composite.getClientArea();
        int smallestDimension = Math.min(clientArea.width, clientArea.height);
        int radius = (smallestDimension / 2) - maxControlWidth;
        Point center = new Point(clientArea.width / 2, clientArea.height / 2);
        long radiusSquared = radius * radius;

        int stepXDistance = calculateStepDistance(radius * 2, stepsPerHemisphere);

        int signMultiplier = 1;
        int x = -radius;
        int y;
        Control[] controls = composite.getChildren();
        for (int i = 0; i < controlCount; i++) {
            Point currSize = controls[i].getSize();
            long xSquared = x * x;

            int sqrRoot = (int) Math.sqrt(radiusSquared - xSquared);
            y = signMultiplier * sqrRoot;
            int translatedX = x + center.x;
            int translatedY = y + center.y;
            positions[i] = new Point(translatedX - (currSize.x / 2), translatedY - (currSize.y / 2));

            x = x + (signMultiplier * stepXDistance);
            //we've finished the upper hemisphere, now do the lower
            if (x >= radius) {
                x = radius - (x - radius);
                signMultiplier = -1;
            }
        }

        return positions;
    }

    private Point calculateMaxDimensions(Control[] controls) {
        Point maxes = new Point(0, 0);

        for (int i = 0; i < controls.length; i++) {
            Point controlSize = controls[i].computeSize(SWT.DEFAULT, SWT.DEFAULT);
            maxes.x = Math.max(maxes.x, controlSize.x);
            maxes.y = Math.max(maxes.y, controlSize.y);
        }

        return maxes;
    }

    private int stepsPerHemisphere(int totalObjects) {
        return (totalObjects / 2) - 1;
    }

    private int calculateStepDistance(int clientAreaDimensionSize, int stepCount) {
        return clientAreaDimensionSize / (stepCount + 1);
    }

}