package com.griddynamics.jagger.webclient.client.components; import com.google.gwt.dom.client.Style; import com.google.gwt.user.client.ui.*; import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Panel that allows to represent child elements with one or two columns * @param <M> Type of child widgets. To make control from outside more comfortably */ public class DynamicLayoutPanel<M extends Widget> extends VerticalLayoutContainer { private Layout layout = Layout.ONE_COLUMN; private double childHeight = 150; // additional height space for child private double additionalHeightForChild = 0; public void setChildHeight(double childHeight) { this.childHeight = childHeight; } public void setAdditionalHeightForChild(double additionalHeightForChild) { this.additionalHeightForChild = additionalHeightForChild; } public Layout getLayout() { return layout; } private final Widget stub; { Label label = new Label(); label.setPixelSize(0, 0); label.setVisible(false); this.stub = label; } /** * Change layout by circle * @param layout - possible layout of DynamicLayoutPanel */ @SuppressWarnings("unchecked") public void changeLayout(Layout layout) { if (this.layout == layout) // no need to change anything return; this.layout = layout; List<M> widgets = new ArrayList<M>(); for (int i = 0; i < getWidgetCount(); i++) { LayoutPanel hp = (LayoutPanel) getWidget(i); for (int j = 0; j < hp.getWidgetCount(); j++) { Widget widget = hp.getWidget(j); if (widget != stub) { // only widgets with type M can appear here widgets.add((M)widget); } } } clear(); for (M widget : widgets) { addChild(widget); } } /** * Add child widget * @param widget - child widget */ public void addChild(M widget) { switch (layout) { case TWO_COLUMNS: addChildTwoColumns(widget); break; default: addChildOneColumn(widget); } } /** * Add child widget that will take all width of DynamicLayoutPanel * @param widget - child widget */ private void addChildOneColumn(M widget) { LayoutPanel newHp = new LayoutPanel(); newHp.setHeight(String.valueOf(childHeight + additionalHeightForChild) + "px"); newHp.add(widget); this.add(newHp); } /** * Add child widget that will half width of DynamicLayoutPanel * @param widget - child widget */ private void addChildTwoColumns(Widget widget) { int totalCount = this.getWidgetCount(); if (totalCount != 0) { LayoutPanel hp = (LayoutPanel) getWidget(totalCount - 1); // get last layout Panel if (hp.getWidgetCount() == 2 && stub == hp.getWidget(1)) { hp.remove(stub); hp.add(widget); hp.setWidgetLeftRight(widget, 50, Style.Unit.PCT, 0, Style.Unit.PCT); return; } } LayoutPanel newHp = new LayoutPanel(); newHp.setHeight(String.valueOf(childHeight + additionalHeightForChild) + "px"); newHp.add(widget); newHp.setWidgetLeftRight(widget, 0, Style.Unit.PCT, 50, Style.Unit.PCT); newHp.add(stub); newHp.setWidgetLeftRight(stub, 50, Style.Unit.PCT, 0, Style.Unit.PCT); this.add(newHp); } /** * Set childHeight for all children * @param plotContainerHeight - childHeight to set */ public void changeChildrenHeight(double plotContainerHeight) { childHeight = plotContainerHeight; for (int i = 0; i < getWidgetCount(); i ++) { LayoutPanel hp = (LayoutPanel) getWidget(i); hp.setHeight(String.valueOf(plotContainerHeight + additionalHeightForChild) + "px"); for (int j = 0; j < hp.getWidgetCount(); j ++) { Widget widget = hp.getWidget(j); widget.setHeight(plotContainerHeight + "px"); } } } /** * @param ids ids of widget to remove (ids of plot container) */ @SuppressWarnings("unchecked") public void removeChildren(Collection<String> ids) { if (layout == Layout.ONE_COLUMN) { for (String id : ids) { for (int i = 0; i < getWidgetCount(); i ++) { LayoutPanel hp = (LayoutPanel) getWidget(i); if (id.equals(hp.getWidget(0).getElement().getId())) { remove(i); break; } } } } else { List<M> containers = new ArrayList<M>(); for (int i = 0; i < getWidgetCount(); i ++) { LayoutPanel hp = (LayoutPanel) getWidget(i); for (int j = 0; j < hp.getWidgetCount(); j++) { Widget widget = hp.getWidget(j); if (!ids.contains(widget.getElement().getId()) && widget != stub) { // only widgets with type M can appear here, except stub. containers.add((M)widget); } } } clear(); for (M pc : containers) { addChild(pc); } } } /** * Check if element with certain id contains in DynamicLayoutPanel * @param plotId - id of element to look for * @return - true if element was found, false - otherwise */ public boolean containsElementWithId(String plotId) { for (int i = 0; i < getWidgetCount(); i ++) { LayoutPanel hp = (LayoutPanel) getWidget(i); for (int j = 0; j < hp.getWidgetCount(); j++) { if (plotId.equals(hp.getWidget(j).getElement().getId())) { return true; } } } return false; } /** * Get all children of DynamicLayoutPanel * @return All widgets with <M> type*/ @SuppressWarnings("unchecked") public List<M> getAllChildren() { List<M> result = new ArrayList<M>(); for (int i = 0; i < getWidgetCount(); i ++) { LayoutPanel hp = (LayoutPanel) getWidget(i); for (int j = 0; j < hp.getWidgetCount(); j++) { Widget widget = hp.getWidget(j); if (widget != stub) { // only widgets with type M can appear here result.add((M)widget); } } } return result; } /** * Get first child of DynamicLayoutPanel * @return first child if contains, null if do not contains any */ @SuppressWarnings("unchecked") public M getFirstChild() { if (getWidgetCount() == 0) return null; LayoutPanel hp = (LayoutPanel) getWidget(0); // only widgets with type M can appear here return (M) hp.getWidget(0); } /** * Enum of possible layouts of DynamicLayoutPanel*/ public static enum Layout { ONE_COLUMN , TWO_COLUMNS; /** * @return next value of Layout enum by circle */ Layout getNext() { return Layout.values()[(this.ordinal() + 1) % Layout.values().length]; } } }