Monday, January 14, 2008

gwt window dialogbox widget with minimize and close buttons

I wanted to make a draggable window dialog box with minimize and close buttons on the caption panel, but i couldn't find this kind of gwt widget API from the web. So, i have decided to build my own one by modifying the source code from a gwt library file called "DialogBox.java". Below is the source code of my "Window.java":

/*
* Copyright 2007 Google Inc.
*
* Modified from DialogBox.java of GWT 1.4.61
* by Wong Thai Min at 14th January 2008.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.thaimin.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ImageBundle;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
* A form of popup window that has a caption area at the top and can be dragged by the
* user. Minimize, maximize and close window buttons are on the caption area.
*
* CSS Style Rules
*
* .gwt-Window { the outside of the window }
* .gwt-Window .HeadPanel { the header panell of the window }
* .gwt-Window .HeadPanel .Caption { the caption }
*
*/
public class Window extends PopupPanel implements MouseListener {

public interface WindowImages extends ImageBundle {

AbstractImagePrototype maximize();

AbstractImagePrototype maximize_white();

AbstractImagePrototype minimize();

AbstractImagePrototype minimize_white();

AbstractImagePrototype close();

AbstractImagePrototype close_white();
}
public static final WindowImages images = (WindowImages) GWT.create(WindowImages.class);
private Image minmax = images.minimize().createImage();
private Image close = images.close().createImage();
private HorizontalPanel icons = new HorizontalPanel();
private HorizontalPanel headhor = new HorizontalPanel();
private VerticalPanel headver = new VerticalPanel();
private FlexTable content = new FlexTable();
private Label caption = new Label();
private Widget child;
private boolean dragging;
private int dragStartX, dragStartY;
private FlexTable panel = new FlexTable();

/**
* Creates an empty dialog box. It should not be shown until its child widget
* has been added using {@link #add(Widget)}.
*/
public Window() {
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 true if the dialog should be automatically
* hidden when the user clicks outside of it
*/
public Window(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 true if the dialog should be automatically
* hidden when the user clicks outside of it
* @param modal true if keyboard and mouse events for widgets
* not contained by the dialog should be ignored
*/
public Window(boolean autoHide, boolean modal) {
super(autoHide, modal);

// minimize & close buttons for DialogBox
minmax.setTitle("minimize");
close.setTitle("close");

// panel:headver:headhor:icons HorizontalPanel ==> display minmax & close images
icons.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
icons.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
icons.setHeight("100%");
icons.setSpacing(2);
icons.add(minmax);
icons.add(close);

// panel:headver:headhor HorizontalPanel
headhor.setWidth("100%");
headhor.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
headhor.add(caption);
headhor.setCellWidth(caption, "100%");
headhor.setCellHorizontalAlignment(caption, HorizontalPanel.ALIGN_LEFT);
headhor.add(icons);
headhor.setCellHorizontalAlignment(icons, HorizontalPanel.ALIGN_RIGHT);

// panel:headver:content VerticalPanel

// panel:headver VerticalPanel
headver.setWidth("100%");
headver.add(headhor);
headver.add(content);

// panel Flextable
panel.setWidget(0, 0, headver);
panel.setHeight("100%");
panel.setBorderWidth(0);
panel.setCellPadding(0);
panel.setCellSpacing(0);
panel.getCellFormatter().setHeight(1, 0, "100%");
panel.getCellFormatter().setWidth(1, 0, "100%");
panel.getCellFormatter().setAlignment(1, 0,
HasHorizontalAlignment.ALIGN_CENTER,
HasVerticalAlignment.ALIGN_MIDDLE);

// Display the layout of the window
super.setWidget(panel);

setStyleName("gwt-Window");
headhor.setStyleName("HeadPanel");
caption.setStyleName("Caption");
caption.addMouseListener(this);

//---------------------- Mouse Listener for window buttons -----------------
minmax.addMouseListener(new MouseListener() {

public void onMouseDown(Widget sender, int x, int y) {
}

// Minimize(grey) icon become white color
public void onMouseEnter(Widget sender) {
if (isMinimize()) {
images.maximize_white().applyTo(minmax);
} else {
images.minimize_white().applyTo(minmax);
}
}

public void onMouseLeave(Widget sender) {
if (isMinimize()) {
images.maximize().applyTo(minmax);
} else {
images.minimize().applyTo(minmax);
}
}

public void onMouseMove(Widget sender, int x, int y) {
}

public void onMouseUp(Widget sender, int x, int y) {
if (isMinimize()) {
setMinimize(false);
} else {
setMinimize(true);
}
}
});

close.addMouseListener(new MouseListener() {

public void onMouseDown(Widget sender, int x, int y) {
}
// Close(grey) icon become white color
public void onMouseEnter(Widget sender) {
images.close_white().applyTo(close);
}

public void onMouseLeave(Widget sender) {
images.close().applyTo(close);
}

public void onMouseMove(Widget sender, int x, int y) {
}

public void onMouseUp(Widget sender, int x, int y) {
}
});

// Close the window
close.addClickListener(new ClickListener() {

public void onClick(Widget sender) {
hide();
}
});
//------------------ End of Mouse Listener for window buttons ------------------
}

public String getText() {
return caption.getText();
}

public boolean onEventPreview(Event event) {
// We need to preventDefault() on mouseDown events (outside of the
// DialogBox content) to keep text from being selected when it
// is dragged.
if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
if (DOM.isOrHasChild(caption.getElement(), DOM.eventGetTarget(event))) {
DOM.eventPreventDefault(event);
}
}

return super.onEventPreview(event);
}

public void onMouseDown(Widget sender, int x, int y) {
dragging = true;
DOM.setCapture(caption.getElement());
dragStartX = x;
dragStartY = y;
}

public void onMouseEnter(Widget sender) {
}

public void onMouseLeave(Widget sender) {
}

public void onMouseMove(Widget sender, int x, int y) {
if (dragging) {
int absX = x + getAbsoluteLeft();
int absY = y + getAbsoluteTop();
setPopupPosition(absX - dragStartX, absY - dragStartY);
}
}

public void onMouseUp(Widget sender, int x, int y) {
dragging = false;
DOM.releaseCapture(caption.getElement());
}

public boolean remove(Widget w) {
if (child != w) {
return false;
}

panel.remove(w);
return true;
}

/**
* Set the caption of the window.
*
* @param text
*/
public void setText(String text) {
caption.setText(text);
}

/**
* Insert a content widget into the window. If there is any widget in the
* content area of the window, it will be removed and replaced by
* w.
*
* @param w The content widget to be inserted to the Window.
*/
public void setWidget(Widget w) {
// If there is already a widget, remove it.
if (child != null) {
content.remove(child);
}

// Add the widget to the center of the cell.
if (w != null) {
content.setWidget(1, 0, w);
}

child = w;
}

/**
* Override, so that interior panel reflows to match parent's new width.
*
* @Override
*/
public void setWidth(String width) {
super.setWidth(width);

// note that you CANNOT call panel.setWidth("100%") until parent's width
// has been explicitly set, b/c until then parent's width is unconstrained
// and setting panel's width to 100% will flow parent to 100% of browser
// (i.e. can't do this in constructor)
panel.setWidth("100%");
}

/**
* Determines whether the window state is currently minimized or restored.
*/
public boolean isMinimize() {
return !content.isVisible();
}

/**
* Set the window state whether to be minimized or restored.
*
* @param state true to minimize the window.
*/
public void setMinimize(boolean b) {
content.setVisible(!b);
if (b = true) {
images.maximize().applyTo(minmax);
} else {
images.minimize().applyTo(minmax);
}
}
}

1 comment:

Papagayo69100 said...

Hi !!!
Nice idea your windows , but I've try to try it but I don't success to get it work, is there any special issue to make it work ????