blob: 6e5f6cd07472b66e1be9fdad7783abb3ef877665 [file] [log] [blame]
package org.eclipse.ui.internal;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import java.util.ArrayList;
import org.eclipse.ui.IPageLayout;
/**
* Implementation of a tree node. The node represents a
* sash and it allways has two children.
*/
public class LayoutTreeNode extends LayoutTree {
/* The node children witch may be another node or a leaf */
private LayoutTree children[] = new LayoutTree[2];
/* The sash's width when vertical and hight on horizontal */
private final static int SASH_WIDTH = 3;
/**
* Initialize this tree with its sash.
*/
public LayoutTreeNode(LayoutPartSash sash) {
super(sash);
}
/**
* Determine the left, right, top and bottom sashes
* that bound the layout part within the tree. It is
* possible that some maybe null.
*/
protected void boundingSashes(LayoutTree tree, LayoutPartSash sashes[]) {
if (children[0] == tree && children[1].isVisible()) {
if (getSash().isHorizontal()) {
if (sashes[BOTTOM_SASH] == null) {
sashes[BOTTOM_SASH] = getSash();
}
} else {
if (sashes[RIGHT_SASH] == null) {
sashes[RIGHT_SASH] = getSash();
}
}
}
if (children[1] == tree && children[0].isVisible()) {
if (getSash().isHorizontal()) {
if (sashes[TOP_SASH] == null) {
sashes[TOP_SASH] = getSash();
}
} else {
if (sashes[LEFT_SASH] == null) {
sashes[LEFT_SASH] = getSash();
}
}
}
if (parent != null) {
parent.boundingSashes(this, sashes);
}
}
/**
* Add the relation ship between the children in the list
* and returns the left children.
*/
public LayoutPart computeRelation(ArrayList relations) {
PartSashContainer.RelationshipInfo r = new PartSashContainer.RelationshipInfo();
r.relative = children[0].computeRelation(relations);
r.part = children[1].computeRelation(relations);
r.ratio = getSash().getRatio();
r.relationship = getSash().isVertical()?IPageLayout.RIGHT:IPageLayout.BOTTOM;
relations.add(0,r);
return r.relative;
}
/**
* Dispose all Sashs in this tree
*/
public void disposeSashes() {
children[0].disposeSashes();
children[1].disposeSashes();
getSash().dispose();
}
/**
* Find a LayoutPart in the tree and return its sub-tree. Returns
* null if the child is not found.
*/
public LayoutTree find(LayoutPart child) {
LayoutTree node = children[0].find(child);
if(node != null) return node;
node = children[1].find(child);
return node;
}
/**
* Find the part that is in the bottom rigth possition.
*/
public LayoutPart findBottomRigth() {
if(children[1].isVisible())
return children[1].findBottomRigth();
return children[0].findBottomRigth();
}
/**
* Go up in the tree finding a parent that is common of both children.
* Return the subtree.
*/
public LayoutTreeNode findCommonParent(LayoutPart child1, LayoutPart child2) {
return findCommonParent(child1,child2,false,false);
}
/**
* Go up in the tree finding a parent that is common of both children.
* Return the subtree.
*/
LayoutTreeNode findCommonParent(LayoutPart child1, LayoutPart child2,boolean foundChild1,boolean foundChild2) {
if(!foundChild1)
foundChild1 = find(child1) != null;
if(!foundChild2)
foundChild2 = find(child2) != null;
if(foundChild1 && foundChild2)
return this;
if(parent == null)
return null;
return parent.findCommonParent(child1,child2,foundChild1,foundChild2);
}
/**
* Find a sash in the tree and return its sub-tree. Returns
* null if the sash is not found.
*/
public LayoutTreeNode findSash(LayoutPartSash sash) {
if(this.getSash() == sash)
return this;
LayoutTreeNode node = children[0].findSash(sash);
if(node != null) return node;
node = children[1].findSash(sash);
if(node != null) return node;
return null;
}
/**
* Return the bounds of this tree which is the rectangle that
* contains all Controls in this tree.
*/
public Rectangle getBounds() {
if(!children[0].isVisible())
return children[1].getBounds();
if(!children[1].isVisible())
return children[0].getBounds();
Rectangle leftBounds = children[0].getBounds();
Rectangle rightBounds = children[1].getBounds();
Rectangle sashBounds = getSash().getBounds();
Rectangle result = new Rectangle(leftBounds.x,leftBounds.y,leftBounds.width,leftBounds.height);
if(getSash().isVertical()) {
result.width = rightBounds.width + leftBounds.width + sashBounds.width;
} else {
result.height = rightBounds.height + leftBounds.height + sashBounds.height;
}
return result;
}
/**
* Returns the sash of this node.
*/
public LayoutPartSash getSash() {
return (LayoutPartSash)part;
}
/**
* Returns true if this tree has visible parts otherwise returns false.
*/
public boolean isVisible() {
return children[0].isVisible() || children[1].isVisible();
}
/**
* Recompute the ratios in this tree.
*/
public void recomputeRatio() {
children[0].recomputeRatio();
children[1].recomputeRatio();
if(children[0].isVisible() && children[1].isVisible()) {
if(getSash().isVertical()) {
float left = children[0].getBounds().width;
float right = children[1].getBounds().width;
getSash().setRatio(left/(right+left+SASH_WIDTH));
} else {
float left = children[0].getBounds().height;
float right = children[1].getBounds().height;
getSash().setRatio(left/(right+left+SASH_WIDTH));
}
}
}
/**
* Remove the child and this node from the tree
*/
LayoutTree remove(LayoutTree child) {
getSash().dispose();
if(parent == null) {
//This is the root. Return the other child to be the new root.
if(children[0] == child) {
children[1].setParent(null);
return children[1];
}
children[0].setParent(null);
return children[0];
}
LayoutTreeNode oldParent = parent;
if(children[0] == child)
oldParent.replaceChild(this,children[1]);
else
oldParent.replaceChild(this,children[0]);
return oldParent;
}
/**
* Replace a child with a new child and sets the new child's parent.
*/
void replaceChild(LayoutTree oldChild,LayoutTree newChild) {
if(children[0] == oldChild)
children[0] = newChild;
else if(children[1] == oldChild)
children[1] = newChild;
newChild.setParent(this);
if(!children[0].isVisible() || ! children[0].isVisible())
getSash().dispose();
}
/**
* Go up from the subtree and return true if all the sash are
* in the direction specified by <code>isVertical</code>
*/
public boolean sameDirection(boolean isVertical,LayoutTreeNode subTree) {
boolean treeVertical = getSash().isVertical();
if (treeVertical != isVertical)
return false;
while(subTree != null) {
if(this == subTree)
return true;
if(subTree.children[0].isVisible() && subTree.children[1].isVisible())
if(subTree.getSash().isVertical() != isVertical)
return false;
subTree = subTree.getParent();
}
return true;
}
/**
* Resize the parts on this tree to fit in <code>bounds</code>.
*/
public void setBounds(Rectangle bounds) {
if(!children[0].isVisible()) {
children[1].setBounds(bounds);
return;
}
if(!children[1].isVisible()) {
children[0].setBounds(bounds);
return;
}
Rectangle leftBounds = new Rectangle(bounds.x,bounds.y,bounds.width,bounds.height);
Rectangle rightBounds = new Rectangle(bounds.x,bounds.y,bounds.width,bounds.height);
Rectangle sashBounds = new Rectangle(bounds.x,bounds.y,bounds.width,bounds.height);
if(getSash().isVertical()) {
//Work on x and width
leftBounds.width = (int)(getSash().getRatio() * bounds.width);
sashBounds.x = leftBounds.x + leftBounds.width;
sashBounds.width = SASH_WIDTH;
rightBounds.x = sashBounds.x + sashBounds.width;
rightBounds.width = bounds.width - leftBounds.width - sashBounds.width;
} else {
//Work on y and height
leftBounds.height = (int)(getSash().getRatio() * bounds.height);
sashBounds.y = leftBounds.y + leftBounds.height;
sashBounds.height = SASH_WIDTH;
rightBounds.y = sashBounds.y + sashBounds.height;
rightBounds.height = bounds.height - leftBounds.height - sashBounds.height;
}
getSash().setBounds(sashBounds);
children[0].setBounds(leftBounds);
children[1].setBounds(rightBounds);
}
/**
* Sets a child in this node
*/
void setChild(boolean left,LayoutPart part) {
LayoutTree child = new LayoutTree(part);
setChild(left,child);
}
/**
* Sets a child in this node
*/
void setChild(boolean left,LayoutTree child) {
int index = left?0:1;
children[index] = child;
child.setParent(this);
}
/**
* Returns a string representation of this object.
*/
public String toString() {
String s = "<null>\n";//$NON-NLS-1$
if(part.getControl() != null)
s = "<@" + part.getControl().hashCode() + ">\n";//$NON-NLS-2$//$NON-NLS-1$
String result = "["; //$NON-NLS-1$
if(children[0].getParent() != this)
result = result + "{" + children[0] + "}" + s;//$NON-NLS-2$//$NON-NLS-1$
else
result = result + children[0] + s;
if(children[1].getParent() != this)
result = result + "{" + children[1] + "}]";//$NON-NLS-2$//$NON-NLS-1$
else
result = result + children[1] + "]";//$NON-NLS-1$
return result;
}
/**
* Create the sashes if the children are visible
* and dispose it if they are not.
*/
public void updateSashes(Composite parent) {
if(parent == null) return;
children[0].updateSashes(parent);
children[1].updateSashes(parent);
if(children[0].isVisible() && children[1].isVisible())
getSash().createControl(parent);
else
getSash().dispose();
}
}