Is there a non JSNI way to add a close button to the title bar area of a DialogBox?
Yes there is
No there isn't - at least not without fiddling with GWT's DialogBox class itself or by recreating the DialogBox using common widgets. This is a known issue in GWT, aka issue 1405 (Star it to show your interest).
However; DialogBox doesn't give us the tools to do this so we need to extend it - Edit: this doesn't work.
If you want to make a drop-in replacement for DialogBox you can name your class DialogBox and import it instead of the one that's included in GWT. This thread on the GWT forum gives better details on how this can be done (outdated, uses listeners) Outdated, the internals of DialogBox have been changed a lot since this thread - it doesn't work.
Here's some code I hacked to get the same results (used the linked thread for guidance). This doesn't work:
MyDialogBox:
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
public class MyDialogBox extends DialogBox {
private class crossHandler implements ClickHandler, MouseOverHandler, MouseOutHandler
{
@Override
public void onClick(ClickEvent event) {
hide();
Window.alert("Click!");
}
@Override
public void onMouseOver(MouseOverEvent event) {
DOM.setStyleAttribute(cross.getElement(), "font-weight", "bold");
}
@Override
public void onMouseOut(MouseOutEvent event) {
DOM.setStyleAttribute(cross.getElement(), "font-weight", "normal");
}
}
Label cross = new Label("X"); // The close button
crossHandler crosshandler = new crossHandler();
HTML caption = new HTML(); // The caption aka title
HorizontalPanel captionPanel = new HorizontalPanel(); // Contains caption and cross
/**
* Creates an empty dialog box. It should not be shown until its child widget
* has been added using {@link #add(Widget)}.
*/
public MyDialogBox()
{
this(false);
}
/**
* Creates an empty dialog box specifying its "auto-hide" property. It should
* not be shown until its child widget has been added using
* {@link #add(Widget)}.
*
* @param autoHide <code>true</code> if the dialog should be automatically
* hidden when the user clicks outside of it
*/
public MyDialogBox(boolean autoHide) {
this(autoHide, true);
}
/**
* Creates an empty dialog box specifying its "auto-hide" property. It should
* not be shown until its child widget has been added using
* {@link #add(Widget)}.
*
* @param autoHide <code>true</code> if the dialog should be automatically
* hidden when the user clicks outside of it
* @param modal <code>true</code> if keyboard and mouse events for widgets not
* contained by the dialog should be ignored
*/
public MyDialogBox(boolean autoHide, boolean modal)
{
super(autoHide, modal);
cross.addClickHandler(crosshandler);
cross.addMouseOutHandler(crosshandler);
cross.addMouseOverHandler(crosshandler);
captionPanel.add(caption);
captionPanel.add(cross);
captionPanel.setStyleName("caption");
Element td = getCellElement(0, 1); // Get the cell element that holds the caption
td.setInnerHTML(""); // Remove the old caption
td.appendChild(captionPanel.getElement());
}
@Override
public void setText(String text)
{
caption.setText(text);
}
public String getText()
{
return caption.getText();
}
public void setHtml(String html)
{
caption.setHTML(html);
}
public String getHtml()
{
return caption.getHTML();
}
Note: This code doesn't work. The ClickEvent isn't sent from cross
but instead from MyDialogBox regardless of whether you add ClickHandlers to the cross
or not, IOW the MyDialogBox is the sender/source and therefor not possible to check against cross
. When cross is clicked it doesn't fire the ClickEvent for some reasons.
Edit: It appears this cannot be done without hacks unless you either write your own DialogBox (almost) from scratch or fix issue 1405. Of course there are number of existing libraries that have already solved this problem, i.e. SmartGWT and GWT-Ext, but their implementation is made mostly from scratch.
So to answer your question in one sentence: Yes there is a way, but you're not gonna like it :)
A more simplier solution is to use gwt-ext (http://code.google.com/p/gwt-ext/). It is free and easy to use and integrate. You can see their showcase http://www.gwt-ext.com/demo/. I think that what you want is the MessageBox or Layout Window (they are on the Windows category of the showcase).
Regards.
You can find the closeable dialogbox in google code under the project synthfuljava. It is actually called scrollable dialog box with a close X button at the caption.
The following blog explains the impediments that had to be overcome in order for thecaption X button to be able to listen to the click event to let it work:
http://h2g2java.blessedgeek.com/2009/07/gwt-useable-closeable-scrollable.html
We used GWT-ext from the begining in our project. It was a bad idea. They have lots of cool widgets, but they are not GWT widgets AND they have no compatibility with GWT widgets. Once you choose GWT-Ext, everything, even the event mechanism, must be in the GWT-Ext way, not in the GWT way. This library will not be updated for the newest version of GWT, because the javascript library Ext is no more free. We are removing GWT-Ext from our project now.
It´s not possible to add a different widget int the GWT DialogBox caption, but you can extend "DecoratedPanel" (it is the DialogBox parent). Look at the DialogBox source to learn the techniques, specially how it adds the Caption object to the panel and how the window drag is implemented.
That´s what we have done here, and it works very well. We´ve made our own Caption class that extends FocusablePanel (a SimplePanel that captures all mouse events) and we added a HorizontalPanel to it, with buttons and text. We had to override onAttach() and onDetach() just by calling the super method (they are protected).
I believe I am not allowed to put our source code in here, so I just can give you these tips.
Hi,
You can do it by adding a button to the center panel of the DialogBox:
Image button = new Image("");
button.addClickHandler(new ClickHandler(){
public void onClick(ClickEvent event) {
registerBox.hide();
}}));
button.setStyleName("TopRight");
Then position it with CSS:
.TopRight { float:right; margin-top:-22px; width:16px; height:16px; display:block; background-image: url(images/cancel_16.png); }
Check out the active project: http://code.google.com/p/gwt-mosaic/
Their noble goal is, as mentioned on their page:
The goal is to provide a complete widget set by keeping the API as close as possible to the GWT's standard widgets API.
Have been trapped in the GXT vortex. Not at all a fan of how they require users to use entirely different API for listeners, etc. On their part this makes sense. After all, GXT is just a port of their existing javascript libraries. But I've been looking for this MOSAIC project for too long...