package org.sigmah.client.ui.widget.panel; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.util.ArrayList; import java.util.Iterator; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; /** * A FoldPanel contains a header and a body.<br> * <br> * This widget can have one of the 3 following states : * <ul> * <li>Expanded : the full content of the FoldPanel is displayed</li> * <li>Folded : only the header of the FoldPanel and of its contained FoldPanels are displayed</li> * <li>Collapsed : only the header of the FoldPanel is displayed</li> * </ul> * This widget can hide and show RichTextElements without making them crash in Firefox and Webkit. * * @author Raphaƫl Calabro (rcalabro@ideia.fr) (v1.3) * @author Mehdi Benabdeslam (mehdi.benabdeslam@netapsys.fr) (v2.0) * @author Denis Colliot (dcolliot@ideia.fr) (v2.0) */ public class FoldPanel extends FlowPanel { private final ArrayList<Widget> list = new ArrayList<Widget>(); public static final int STATE_EXPANDED = 0; public static final int STATE_FOLDED = 1; public static final int STATE_COLLAPSED = 2; private static final int HEADER_INDEX = 0; private static final int BODY_INDEX = 1; private int state; /** * Creates a new and empty fold panel. */ public FoldPanel() { addStyleName("fold"); final HorizontalPanel titleBar = new HorizontalPanel(); titleBar.getElement().getStyle().setDisplay(Style.Display.NONE); titleBar.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); final Label heading = new Label(); heading.addStyleName("fold-title"); heading.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (state == STATE_EXPANDED) collapse(); else expand(true); } }); heading.addStyleName("fold-expanded"); titleBar.add(heading); titleBar.setCellWidth(heading, "100%"); final FlowPanel toolButtonPanel = new FlowPanel(); titleBar.add(toolButtonPanel); final FlowPanel content = new FlowPanel(); super.add(titleBar); super.add(content); } /** * Defines the header of this fold panel. * * @param text * Text to display in the header of this fold panel. */ public void setHeading(String text) { final HorizontalPanel titleBar = (HorizontalPanel) super.getWidget(HEADER_INDEX); final Label heading = (Label) titleBar.getWidget(0); heading.setText(text); if (text != null && !"".equals(text)) { super.getWidget(BODY_INDEX).addStyleName("fold-content"); titleBar.getElement().getStyle().setProperty("display", ""); } else { super.getWidget(BODY_INDEX).removeStyleName("fold-content"); titleBar.getElement().getStyle().setDisplay(Style.Display.NONE); } } @Override public void add(Widget w) { ((FlowPanel) super.getWidget(BODY_INDEX)).add(w); list.add(w); } @Override public Widget getWidget(int index) { return ((FlowPanel) super.getWidget(BODY_INDEX)).getWidget(index); } @Override public int getWidgetCount() { return ((FlowPanel) super.getWidget(BODY_INDEX)).getWidgetCount(); } /** * Adds a button with the specified <code>image</code> and <code>action</code> in the top right corner of this panel. * * @param image * Image of the button. * @param action * Action to execute when the button is clicked. */ public void addToolButton(ImageResource image, ClickHandler action) { final Image button = new Image(image); button.addStyleName("fold-tool-button"); button.addClickHandler(action); final HorizontalPanel titleBar = (HorizontalPanel) super.getWidget(HEADER_INDEX); final FlowPanel toolButtonPanel = (FlowPanel) titleBar.getWidget(1); toolButtonPanel.add(button); toolButtonPanel.setWidth(16 * toolButtonPanel.getWidgetCount() + "px"); } /** * Edits a tool button by replacing its current image by the one provided. * * @param index * The index of the button to edit. * @param image * The new image to display. */ public void setToolButtonImage(int index, ImageResource image) { final HorizontalPanel titleBar = (HorizontalPanel) super.getWidget(HEADER_INDEX); final FlowPanel toolButtonPanel = (FlowPanel) titleBar.getWidget(1); final Image button = (Image) toolButtonPanel.getWidget(index); button.setResource(image); } /** * Returns the current number of tool buttons displayed by this panel. * * @return the number of tool button. */ public int getToolButtonCount() { final HorizontalPanel titleBar = (HorizontalPanel) super.getWidget(HEADER_INDEX); final FlowPanel toolButtonPanel = (FlowPanel) titleBar.getWidget(1); return toolButtonPanel.getWidgetCount(); } public void collapse() { final FlowPanel content = (FlowPanel) super.getWidget(BODY_INDEX); for (final Widget widget : list) content.remove(widget); setState(STATE_COLLAPSED); } public void fold(boolean propagate) { final FlowPanel content = (FlowPanel) super.getWidget(BODY_INDEX); boolean collapse = true; for (int index = 0; index < list.size(); index++) { final Widget child = list.get(index); if (child instanceof FoldPanel) { collapse = false; if (propagate) ((FoldPanel) child).fold(propagate); } else { content.remove(child); } } setState(collapse ? STATE_COLLAPSED : STATE_FOLDED); } public void expand(boolean propagate) { final FlowPanel content = (FlowPanel) super.getWidget(BODY_INDEX); Widget next = null; final Iterator<Widget> children = content.iterator(); if (children.hasNext()) next = children.next(); for (int index = 0; index < list.size(); index++) { final Widget widget = list.get(index); if (widget != next) { content.insert(widget, index); } else { if (children.hasNext()) next = children.next(); else next = null; } if (propagate && widget instanceof FoldPanel) ((FoldPanel) widget).expand(propagate); } setState(STATE_EXPANDED); } private void setState(int state) { // Removing the previous style final HorizontalPanel titleBar = (HorizontalPanel) super.getWidget(HEADER_INDEX); final Widget header = titleBar.getWidget(0); switch (this.state) { case STATE_EXPANDED: header.removeStyleName("fold-expanded"); break; case STATE_FOLDED: header.removeStyleName("fold-folded"); break; case STATE_COLLAPSED: header.removeStyleName("fold-collapsed"); break; } // Adding the new style switch (state) { case STATE_EXPANDED: header.addStyleName("fold-expanded"); break; case STATE_FOLDED: header.addStyleName("fold-folded"); break; case STATE_COLLAPSED: header.addStyleName("fold-collapsed"); break; } this.state = state; } }