/*
* MyGWT Widget Library
* Copyright(c) 2007, MyGWT.
* licensing@mygwt.net
*
* http://mygwt.net/license
*/
package net.mygwt.ui.client.widget;
import java.util.ArrayList;
import java.util.List;
import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.MyDOM;
import net.mygwt.ui.client.Style;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.fx.FXStyle;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseListenerCollection;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SourcesMouseEvents;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.WidgetHelper;
/**
* A <code>Container</code> with an optional header that can be expanded and
* collapsed.
*
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>COLLAPSE, HEADER</dd>
*
* <dt><b>Events:</b></dt>
*
* <dd><b>BeforeExpand</b> : (widget)<br>
* <div>Fires before the panel is expanded. Listeners can set the
* <code>doit</code> field to <code>false</code> to cancel the expand.</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
*
* <dd><b>Expand</b> : (widget)<br>
* <div>Fires after the panel is expanded</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
*
* <dd><b>BeforeCollapse</b> : (widget)<br>
* <div>Fires before the panel is collpased. Listeners can set the
* <code>doit</code> field <code>false</code> to cancel the collapse.</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
*
* <dd><b>Collapse</b> : (widget)<br>
* <div>Fires after the panel is collapsed.</div>
* <ul>
* <li>widget : this</li>
* </ul>
* </dd>
*
* <dt><b>CSS:</b></dt>
* <dd>.my-cpanel ( the panel panel)</dd>
* <dd>.my-cpanel .my-cpanel-hdr-text (the header text)</dd>
* <dd>.my-cpanel-small ( smaller header section )</dd>
* <dd>.my-cpanel-small .my-cpanel-hdr-text (the header text)</dd>
* </dl>
*/
public class ContentPanel extends WidgetContainer implements SourcesMouseEvents {
/**
* <code>true</code> to animate expand and collapse. Default value is
* <code>true</code>.
*/
public boolean animateCollapse = true;
/**
* <code>true</code> to collapse when header is clicked. Default value is
* <code>false</code>.
*/
public boolean titleCollapse = false;
protected int style;
protected Item header;
protected SimplePanel body;
private String text, iconStyle;
private String baseStyle;
private boolean expanded = true;
private boolean animating;
private IconButton collapseBtn;
private MouseListenerCollection mouseListeners;
private List widgets;
private int padding;
/**
* Creates a new content panel.
*
* @param style the style information
*/
public ContentPanel(int style) {
this(style, "my-cpanel");
}
/**
* Creates a new content panel.
*
* @param style the style information
* @param baseStyle an alternate base style.
*/
public ContentPanel(int style, String baseStyle) {
this.style = style;
this.baseStyle = baseStyle;
widgets = new ArrayList();
}
/**
* Adds a button to the header.
*
* @param btn the button
* @param listener the click listener
* @return the button
*/
public IconButton addButton(IconButton btn, Listener listener) {
btn.addListener(Events.Click, listener);
widgets.add(btn);
if (rendered) {
header.addButton(btn);
}
return btn;
}
/**
* Adds a button to the header.
*
* @param style the button style
* @param listener the click listener
* @return the new icon button
*/
public IconButton addButton(String style, Listener listener) {
IconButton btn = new IconButton(style);
return addButton(btn, listener);
}
/**
* Adds a listener interface to receive mouse events.
*
* @param listener the listener interface to add
*/
public void addMouseListener(MouseListener listener) {
if (mouseListeners == null) {
mouseListeners = new MouseListenerCollection();
}
mouseListeners.add(listener);
}
/**
* Adds a widget to the tool area of the header.
*
* @param widget the widget to be added
*/
public void addWidget(Widget widget) {
widgets.add(widget);
if (rendered) {
header.addWidget(widget);
}
}
/**
* Returns the panel's header widget.
*
* @return the header
*/
public Item getHeader() {
if (!rendered) {
render();
}
return header;
}
public Element getLayoutTarget() {
return body.getElement();
}
/**
* Returns the panel's title text.
*
* @return the text
*/
public String getText() {
return text;
}
/**
* Returns <code>true</code> if the panel is expanded.
*
* @return the expand state
*/
public boolean isExpanded() {
return expanded;
}
public void onBaseEvent(BaseEvent be) {
super.onBaseEvent(be);
switch (be.type) {
case Event.ONMOUSEDOWN:
case Event.ONMOUSEUP:
case Event.ONMOUSEMOVE:
case Event.ONMOUSEOVER:
case Event.ONMOUSEOUT: {
if (mouseListeners != null) {
mouseListeners.fireMouseEvent(this, be.event);
}
break;
}
}
}
/**
* Removes a previously added listener interface.
*
* @param listener the listener interface to remove
*/
public void removeMouseListener(MouseListener listener) {
if (mouseListeners != null) {
mouseListeners.remove(listener);
}
}
/**
* Sets the panel's expand state.
*
* @param expanded <code>true<code> true to expand
*/
public void setExpanded(boolean expanded) {
if (animating) {
return;
}
this.expanded = expanded;
if (rendered) {
if (expanded && fireEvent(Events.BeforeExpand)) {
onExpand();
} else if (fireEvent(Events.BeforeCollapse)) {
onCollapse();
}
}
}
/**
* Sets the panel's icon style.
*
* @param style the icon style
*/
public void setIconStyle(String style) {
this.iconStyle = style;
if (rendered && header != null) {
header.setIconStyle(style);
}
}
/**
* Sets the padding of the content element.
*
* @param padding the new padding
*/
public void setPadding(int padding) {
this.padding = padding;
if (rendered) {
DOM.setIntStyleAttribute(body.getElement(), "padding", padding);
}
}
/**
* Sets the header's text. Does nothing if header is not visible.
*
* @param text the new header text
*/
public void setText(String text) {
this.text = text;
if (rendered && header != null) {
header.setText(text);
}
}
protected void afterCollapse() {
expanded = false;
animating = false;
fireEvent(Events.Collapse);
fireEvent(Events.Resize);
}
protected void afterExpand() {
expanded = true;
animating = false;
fireEvent(Events.Expand);
fireEvent(Events.Resize);
}
protected void afterRender() {
super.afterRender();
if (padding != 0) {
setPadding(padding);
}
if ((style & Style.COLLAPSE) != 0) {
setExpanded(expanded);
}
}
protected void doAttachChildren() {
super.doAttachChildren();
if (header != null) {
WidgetHelper.doAttach(header);
}
WidgetHelper.doAttach(body);
}
protected void doDetachChildren() {
super.doDetachChildren();
if (header != null) {
WidgetHelper.doDetach(header);
}
WidgetHelper.doDetach(body);
}
protected void onCollapse() {
collapseBtn.changeStyle("my-tool-down");
if (animateCollapse && !animating) {
animating = true;
FXStyle fx = new FXStyle(body.getElement());
fx.duration = 300;
fx.addListener(Events.EffectComplete, new Listener() {
public void handleEvent(BaseEvent be) {
afterCollapse();
}
});
fx.slideOut(Style.NORTH);
} else {
body.setVisible(false);
afterCollapse();
}
}
protected void onExpand() {
collapseBtn.changeStyle("my-tool-up");
if (animateCollapse && !animating) {
animating = true;
FXStyle fx = new FXStyle(body.getElement());
fx.duration = 300;
fx.addListener(Events.EffectComplete, new Listener() {
public void handleEvent(BaseEvent be) {
afterExpand();
}
});
fx.slideIn(Style.SOUTH);
} else {
body.setVisible(true);
afterExpand();
}
}
protected void onRender() {
setElement(DOM.createDiv());
setStyleName(baseStyle);
if ((style & Style.HEADER) != 0) {
header = new Item(baseStyle + "-hdr");
DOM.appendChild(getElement(), header.getElement());
header.setWidth("100%");
addStyleName("my-cpanel-showheader");
if (text != null) {
header.setText(text);
}
if (iconStyle != null) {
header.setIconStyle(iconStyle);
}
for (int i = 0; i < widgets.size(); i++) {
Widget w = (Widget) widgets.get(i);
if (w instanceof IconButton) {
header.addButton((IconButton) w);
} else {
header.addWidget(w);
}
}
}
body = new SimplePanel();
body.setStyleName(baseStyle + "-body");
DOM.appendChild(getElement(), body.getElement());
if (header != null) {
body.addStyleName(baseStyle + "-body-header");
}
if ((style & Style.COLLAPSE) != 0) {
collapseBtn = new IconButton("my-tool-up");
collapseBtn.addListener(Events.Click, new Listener() {
public void handleEvent(BaseEvent be) {
be.stopEvent();
setExpanded(!isExpanded());
}
});
collapseBtn.render();
collapseBtn.setSize(15, 15);
if (header != null) {
header.addButton(collapseBtn);
}
}
}
protected void onResize(int width, int height) {
if (height != Style.DEFAULT) {
int h = getHeight(true);
if (header != null) {
h -= header.getHeight();
}
if (!MyDOM.isVisibleBox()) {
h -= 1;
}
MyDOM.setHeight(body.getElement(), h, true);
}
layout();
}
}