/*
This file is part of the software framework JStatCom,
a library for building applications for data based analysis.
Copyright (C) 2000-2005 Markus Kraetzig
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
package com.jstatcom.equation;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JComponent;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
/**
* Special layout to be used with EqPanel. It manges the
* visibility of scrollbars of a parent scrollpane, the adjustment of the
* equation components and the dimension of the underlying EqPanel.
*
* @author Alexander Benkwitz, Markus Kraetzig
*/
public final class EqLayout extends FlowLayout {
/**
* The number of left hand side terms. Managed by EqPanel.add.
*/
protected int numberLHS = 0;
private int indentRHS = 20;
private JScrollPane enclosingScrollPane = null;
/**
* Constructor.
*/
public EqLayout() {
super(LEFT, 0, 5);
}
/**
* Manages visibility of scrollbar.
*
* @param scrollBar
*/
private void adjustScrollBar(JScrollBar scrollBar) {
if (scrollBar == null)
return;
if (scrollBar.isVisible()) {
int max = scrollBar.getMaximum();
int visibleAmount = scrollBar.getVisibleAmount();
scrollBar.setVisible(visibleAmount != max);
}
}
/**
* Centers the elements in the specified row, if there is any slack.
*
* @param target
* the component which needs to be moved
* @param x
* the x coordinate
* @param y
* the y coordinate
* @param width
* the width dimensions
* @param height
* the height dimensions
* @param rowStart
* the beginning of the row
* @param rowEnd
* the the ending of the row
*/
private void centerComponents(Container target, int rowHeight,
int rowStart, int rowEnd) {
Point p = new Point();
for (int i = rowStart; i < rowEnd; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
p = m.getLocation(p);
m.setLocation(p.x, p.y + (rowHeight - m.getHeight()) / 2);
}
}
}
/**
* Adds component listeners to all child components.
*
* @param target
* the specified component being laid out
* @param scrollPane
* the parent scrollPane
*/
private void initializeScrollPaneListener(final Container target,
JScrollPane scrollPane) {
scrollPane.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
((JComponent) target).revalidate();
}
});
}
/**
* Manages the layout for the target container and its child components.
*
* @param target
* the specified component being laid out.
* @see java.awt.Container#doLayout
*/
public void layoutContainer(Container target) {
synchronized (target.getTreeLock()) {
boolean leadingSignVisible = false;
Insets insets = target.getInsets();
int hgap = getHgap();
int vgap = getVgap();
int maxwidth = target.getWidth() - (insets.right + hgap);
int nmembers = target.getComponentCount();
int x = insets.left + hgap, y = insets.top + vgap;
// LHS
int rowHeight = 0;
for (int i = 0; i < Math.min(numberLHS, nmembers); i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
m.setLocation(x, y);
x += d.width + hgap;
rowHeight = Math.max(rowHeight, d.height);
}
}
int indent = x;
int membersTreated = Math.min(numberLHS, nmembers);
// rest of row 0
for (int i = membersTreated; i < nmembers; i++, membersTreated++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
if (m instanceof EqTerm) {
((EqTerm) m).setLeadingSignVisible(leadingSignVisible);
leadingSignVisible = true;
}
Dimension d = m.getPreferredSize();
if ((x + d.width) <= maxwidth) {
m.setSize(d.width, d.height);
m.setLocation(x, y);
x += d.width + hgap;
rowHeight = Math.max(rowHeight, d.height);
} else {
leadingSignVisible = !(membersTreated == numberLHS);
break;
}
}
}
centerComponents(target, rowHeight, 0, membersTreated);
//
if (membersTreated == numberLHS)
indent = indentRHS;
// indent += insets.left + hgap;
// row 1,...,N
int firstItem = membersTreated;
// int counter = 1;
while (membersTreated < nmembers) {
firstItem = membersTreated;
Component m = target.getComponent(membersTreated++);
if (m.isVisible()) {
x = indent;
y += rowHeight + vgap;
rowHeight = 0;
if (m instanceof EqTerm) {
((EqTerm) m).setLeadingSignVisible(leadingSignVisible);
leadingSignVisible = true;
}
Dimension d = m.getPreferredSize();
m.setSize(d.width, d.height);
m.setLocation(x, y);
x += d.width;
rowHeight = d.height;
for (int i = membersTreated; i < nmembers; i++, membersTreated++) {
Component comp = target.getComponent(i);
if (comp.isVisible()) {
if (comp instanceof EqTerm) {
((EqTerm) comp).setLeadingSignVisible(true);
}
Dimension compPrefSize = comp.getPreferredSize();
if ((x + hgap + compPrefSize.width) <= maxwidth) {
comp.setSize(compPrefSize.width,
compPrefSize.height);
comp.setLocation(hgap + x, y);
x += compPrefSize.width;
rowHeight = Math.max(rowHeight,
compPrefSize.height);
} else {
membersTreated = i;
centerComponents(target, rowHeight, firstItem,
membersTreated);
break;
}
}
}
}
}
centerComponents(target, rowHeight, firstItem, membersTreated);
//
if (enclosingScrollPane != null
&& enclosingScrollPane.getVerticalScrollBarPolicy() == ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED) {
adjustScrollBar(enclosingScrollPane.getVerticalScrollBar());
}
}
}
/**
* Returns the maximum dimensions needed to layout the components contained
* in the specified target container.
*
* @param target
* the component which needs to be laid out
* @return the maximum dimensions to lay out the subcomponents of the
* specified container.
*/
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
/**
* Returns the minimum dimensions needed to layout the components contained
* in the specified target container.
*
* @param target
* the component which needs to be laid out
* @return the minimum dimensions to lay out the subcomponents of the
* specified container.
*/
public Dimension minimumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
/**
* Wrappes component childs if there is a parent component of class
* JScrollPane.
*
* @param target
* the component which needs to be laid out
* @return the preferred dimensions to lay out the subcomponents of the
* specified container.
*/
public Dimension preferredLayoutSize(Container target) {
if (enclosingScrollPane == null) {
Container parent = target.getParent();
while (parent != null) {
if (parent instanceof JScrollPane) {
enclosingScrollPane = (JScrollPane) parent;
break;
}
parent = parent.getParent();
}
if (enclosingScrollPane != null)
initializeScrollPaneListener(target, enclosingScrollPane);
}
if (enclosingScrollPane == null)
return super.preferredLayoutSize(target);
synchronized (target.getTreeLock()) {
boolean leadingSignVisible = false;
Dimension prefSize = preferredLayoutSizeLHS(target);
int indent = prefSize.width;
int hgap = getHgap();
int vgap = getVgap();
// we maybe share the JScrollPane with other components
Dimension viewSize = enclosingScrollPane.getViewport().getSize();
Point point = SwingUtilities.convertPoint(target, 0, 0,
enclosingScrollPane.getViewport());
Insets insets = target.getInsets();
int maxWidth = viewSize.width - point.x
- (insets.left + insets.right + hgap * 2);
// rest of row 0
int nmembers = target.getComponentCount();
int membersTreated = numberLHS;
for (int i = numberLHS; i < nmembers; i++, membersTreated++) {
Component comp = target.getComponent(i);
if (comp.isVisible()) {
if (comp instanceof EqTerm) {
((EqTerm) comp)
.setLeadingSignVisible(leadingSignVisible);
leadingSignVisible = true;
}
Dimension compPrefSize = comp.getPreferredSize();
if ((prefSize.width + hgap + compPrefSize.width) <= maxWidth) {
prefSize.width += hgap + compPrefSize.width;
prefSize.height = Math.max(prefSize.height,
compPrefSize.height);
} else {
membersTreated = i;
leadingSignVisible = !(membersTreated == numberLHS);
break;
}
}
}
// row 1,...,N
if (indent == prefSize.width) {
indent = indentRHS;
}
while (membersTreated < nmembers) {
Component comp = target.getComponent(membersTreated++);
if (comp.isVisible()) {
if (comp instanceof EqTerm) {
((EqTerm) comp)
.setLeadingSignVisible(leadingSignVisible);
leadingSignVisible = true;
}
Dimension compPrefSize = comp.getPreferredSize();
int rowWidth = indent + compPrefSize.width;
int rowHeight = compPrefSize.height;
for (int i = membersTreated; i < nmembers; i++, membersTreated++) {
comp = target.getComponent(i);
if (comp.isVisible()) {
if (comp instanceof EqTerm) {
((EqTerm) comp)
.setLeadingSignVisible(leadingSignVisible);
}
compPrefSize = comp.getPreferredSize();
if ((rowWidth + hgap + compPrefSize.width) <= maxWidth) {
rowWidth += hgap + compPrefSize.width;
rowHeight = Math.max(rowHeight,
compPrefSize.height);
} else {
membersTreated = i;
break;
}
}
}
prefSize.height += vgap + rowHeight;
prefSize.width = Math.max(prefSize.width, rowWidth);
}
}
prefSize.width += insets.left + insets.right + hgap * 2;
prefSize.height += insets.top + insets.bottom + vgap * 2;
return prefSize;
}
}
/**
* Returns the preferred dimensions for this layout given the components in
* the specified target container.
*
* @param target
* the component which needs to be laid out
* @return the preferred dimensions to lay out the subcomponents of the
* specified container.
* @see Container
* @see #minimumLayoutSize
* @see java.awt.Container#getPreferredSize
*/
private Dimension preferredLayoutSizeLHS(Container target) {
Dimension dim = new Dimension(0, 0);
int nmembers = Math.min(numberLHS, target.getComponentCount());
for (int i = 0; i < nmembers; i++) {
Component m = target.getComponent(i);
if (m.isVisible()) {
Dimension d = m.getPreferredSize();
dim.height = Math.max(dim.height, d.height);
if (i > 0) {
dim.width += getHgap();
}
dim.width += d.width;
}
}
return dim;
}
}
Ads help maintain this website.