/*******************************************************************************
 * Copyright (c) 2000, 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.draw2d;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;


/**
 * The ScrollPaneLayout is responsible for laying out the {@link Viewport} and 
 * {@link ScrollBar ScrollBars} of a {@link ScrollPane}.
 */
public class ScrollPaneLayout
	extends AbstractHintLayout
{

/** @see ScrollPane#NEVER */
protected static final int NEVER  = ScrollPane.NEVER;
/** @see ScrollPane#AUTOMATIC */
protected static final int AUTO   = ScrollPane.AUTOMATIC;
/** @see ScrollPane#ALWAYS */
protected static final int ALWAYS = ScrollPane.ALWAYS;

/**
 * @see AbstractHintLayout#calculateMinimumSize(IFigure, int, int)
 */
public Dimension calculateMinimumSize(IFigure figure, int w, int h) {
	ScrollPane scrollpane = (ScrollPane)figure;
	Insets insets = scrollpane.getInsets();
	Dimension d = scrollpane.getViewport().getMinimumSize(w, h);
	return d.getExpanded(insets.getWidth(), insets.getHeight());
}

/**
 * Calculates and returns the preferred size of the container based on the given hints.  
 * If the given ScrollPane's (<i>container</i>) horizontal and vertical scroll bar 
 * visibility is not {@link ScrollPane#NEVER}, then space for those bars is always 
 * deducted from the hints (whether or not we actually need the scroll bars).
 * 
 * @param container the ScrollPane whose preferred size needs to be calculated
 * @param wHint the width hint
 * @param hHint the height hint
 * @return the preferred size of the given container
 * @since	2.0
 */
protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
	ScrollPane scrollpane = (ScrollPane)container;
	ScrollBar hBar = scrollpane.getHorizontalScrollBar();
	ScrollBar vBar = scrollpane.getVerticalScrollBar();
	Insets insets = scrollpane.getInsets();

	int reservedWidth = insets.getWidth();
	int reservedHeight = insets.getHeight();

	if (scrollpane.getVerticalScrollBarVisibility() != ScrollPane.NEVER)
		reservedWidth += vBar.getPreferredSize().width;
	if (scrollpane.getHorizontalScrollBarVisibility() != ScrollPane.NEVER)
		reservedHeight += hBar.getPreferredSize().height;

	if (wHint > -1)
		wHint = Math.max(0, wHint - reservedWidth);
	if (hHint > -1)
		hHint = Math.max(0, hHint - reservedHeight);

	return scrollpane
		.getViewport()
		.getPreferredSize(wHint, hHint)
		.getExpanded(reservedWidth, reservedHeight);
}

/**
 * @see org.eclipse.draw2d.LayoutManager#layout(IFigure)
 */
public void layout(IFigure parent) {
	ScrollPane scrollpane = (ScrollPane)parent;
	Viewport viewport = scrollpane.getViewport();
	ScrollBar hBar = scrollpane.getHorizontalScrollBar(),
		      vBar = scrollpane.getVerticalScrollBar();
	
	ScrollPaneSolver.Result result = ScrollPaneSolver.solve(
					parent.getClientArea(), 
					viewport, 
					scrollpane.getHorizontalScrollBarVisibility(),
					scrollpane.getVerticalScrollBarVisibility(), 
					vBar.getPreferredSize().width, 
					hBar.getPreferredSize().height);
	
	if (result.showV) {
		vBar.setBounds(new Rectangle(
			result.viewportArea.right(),
			result.viewportArea.y,
			result.insets.right,
			result.viewportArea.height));
	}
	if (result.showH) {
		hBar.setBounds(new Rectangle(
			result.viewportArea.x,
			result.viewportArea.bottom(),
			result.viewportArea.width,
			result.insets.bottom));
	}
	vBar.setVisible(result.showV);
	hBar.setVisible(result.showH);
	
	int vStepInc = vBar.getStepIncrement();
	int vPageInc = vBar.getRangeModel().getExtent() - vStepInc;
	if (vPageInc < vStepInc)
		vPageInc = vStepInc;
	vBar.setPageIncrement(vPageInc);
	
	int hStepInc = hBar.getStepIncrement();
	int hPageInc = hBar.getRangeModel().getExtent() - hStepInc;
	if (hPageInc < hStepInc)
		hPageInc = hStepInc;
	hBar.setPageIncrement(hPageInc);
}

}
