Tuesday, January 15, 2008

gwt window manager

Just now, I found that other people have done the same thing as mine, even better than the one I did. They really have done a great job.. that they put a lot of animations, transparent backgrounds, sophisticated window buttons (e.g: vista & iMac themes), etc.
They called it GWT Window Manager. You can find out more from this link:

http://www.gwtwindowmanager.org/

gwt window demo

I have made the demo of gwt window (as shown in the figure below):












You can go to the link below to view the demo:

http://www.euzertech.com/gwt/gwtwindow.html


The source files of this demo project can be downloaded from this link:

http://www.euzertech.com/gwt/gwtwindow.zip

Please note that the background and border color of the window dialogbox generated by my Window class is transparent. So, you can use external CSS to color the window. In this demo, the source code of my CSS is as below:

.gwt-Window {
background-color: #0055ff;
border-color: #0000ff;
border-style: solid;
border-width: 2px;
}

.gwt-Window .HeadPanel {
background-color: #00eeff;
}

.gwt-Window .HeadPanel .Caption {
font-weight: bold;
}


Please note that in order to use the "Window.java", 6 images files (close.png, close_white.png, minimize.png, minimize_white.png, maximize.png, maximize_white.png) must be included in the same folder. You can see the files structure of the demo from the figure below:

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);
}
}
}