package org.gwtoolbox.widget.client.panel.layout;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.*;
import org.gwtoolbox.widget.client.panel.LayoutUtils;
import org.gwtoolbox.widget.client.panel.layout.VerticalLayoutData;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static org.gwtoolbox.widget.client.panel.LayoutUtils.*;
/**
* @author Uri Boness
*/
public class VerticalLayout extends Panel implements RequiresResize, ProvidesResize {
private Impl impl = GWT.create(Impl.class);
private Element container;
private List<Element> elements = new ArrayList<Element>();
private List<Widget> widgets = new ArrayList<Widget>();
private List<VerticalLayoutData> layoutDatas = new ArrayList<VerticalLayoutData>();
public VerticalLayout() {
setElement(DOM.createDiv());
addRelativePositoning(getElement());
impl.init(this);
container = preventBoxStyles(DOM.createDiv());
DOM.appendChild(getElement(), container);
expandToFitParent(container);
addRelativePositoning(container);
}
@Override
public void add(Widget widget) {
addWidget(widget, new VerticalLayoutData().setHeight("*").setOverflow("visible"));
}
public void addWidget(Widget widget) {
VerticalLayoutData data = new VerticalLayoutData();
addWidget(widget, data);
}
public void addWidget(Widget widget, VerticalLayoutData data) {
addWidget(elements.size(), widget, data);
}
public Widget addGap(String height) {
Label label = new Label();
addWidget(label, new VerticalLayoutData().setHeight(height));
return label;
}
public boolean remove(Widget child) {
int index = widgets.indexOf(child);
if (index < 0) {
return false;
}
Element parent = elements.remove(index);
orphan(child);
DOM.removeChild(parent, child.getElement());
DOM.removeChild(container, parent);
return true;
}
public Iterator<Widget> iterator() {
return widgets.iterator();
}
@Override
protected void onLoad() {
impl.onAttach();
}
@Override
protected void onUnload() {
impl.onDetach();
}
public void onResize() {
GWT.log("here", null);
impl.layout();
}
//================================================ Helper Methods ==================================================
private void addWidget(int index, Widget widget, VerticalLayoutData data) {
assert widget != null;
// creating the containing parent
Element parent = preventBoxStyles(DOM.createDiv());
addAbsolutePositoning(parent);
setTop(parent, "0px");
expandToFitParentHorizontally(parent);
elements.add(index, parent);
layoutDatas.add(data);
if (data.getOverflow() != null) {
DOM.setStyleAttribute(parent, "overflow", data.getOverflow());
}
// Detach the new child.
widget.removeFromParent();
// Logical detach old / attach new.
widgets.add(index, widget);
// Physical attach new.
DOM.appendChild(parent, widget.getElement());
if (data.isExpandToFit()) {
expandToFitParent(widget.getElement());
}
DOM.appendChild(container, parent);
// Adopt new.
adopt(widget);
if (isAttached()) {
impl.layout();
}
}
public com.google.gwt.dom.client.Element getWidgetContainer(Widget widget) {
if (!widgets.contains(widget)) {
throw new IllegalArgumentException("This FixedVerticalPanel doesn't contain the given widget");
}
return widget.getElement().getParentElement();
}
//================================================= Inner Classes ==================================================
private static class Impl {
protected VerticalLayout panel;
public void init(VerticalLayout panel) {
this.panel = panel;
}
public void onAttach() {
DeferredCommand.addCommand(new Command() {
public void execute() {
layout();
}
});
}
public void onDetach() {
}
public void layout() {
expandToFitParent(panel.container);
int containerHeight = LayoutUtils.getOffsetHeight(panel.container);
if (containerHeight == 0) {
return;
}
int dynamicElementCount = 0;
int usedHeight = 0;
int i = 0;
for (Element element : panel.elements) {
if (!isVisible(element.getFirstChildElement())) {
i++;
continue;
}
VerticalLayoutData data = panel.layoutDatas.get(i);
expandToFitParentHorizontally(element);
String height = data.getHeight();
if (!"*".equals(height)) {
setElementHeight(element, height);
int offsetHeight = LayoutUtils.getOffsetHeight(element);
usedHeight += offsetHeight;
} else {
dynamicElementCount++;
}
i++;
}
int dynamicHeight = containerHeight - usedHeight;
int height = (dynamicElementCount > 0) ? dynamicHeight / dynamicElementCount : 0;
if (height < 0) {
height = 0;
}
int top = 0;
i = 0;
for (Element element : panel.elements) {
if (!isVisible(element.getFirstChildElement())) {
i++;
continue;
}
setTop(element, top + "px");
VerticalLayoutData data = panel.layoutDatas.get(i);
if ("*".equals(data.getHeight())) {
setElementHeight(element, height + "px");
top += height;
} else {
int currentHeight = LayoutUtils.getOffsetHeight(element);
top += currentHeight;
}
i++;
}
for (Widget widget : panel.widgets) {
if (widget instanceof RequiresResize) {
((RequiresResize) widget).onResize();
}
}
}
public void setElementHeight(Element element, String height) {
LayoutUtils.setHeight(element, height);
}
}
private static class ImplOpera extends Impl {
@Override
public void setElementHeight(Element element, String height) {
LayoutUtils.setHeight(element, height);
LayoutUtils.setBottom((Element) element.getChildNodes().getItem(0), "0px");
LayoutUtils.setHeight((Element) element.getChildNodes().getItem(0), height);
}
}
}