blob: 3dd1b6364576feaff3045c1f89380b9ad9186523 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.common.ui.calendar;
import java.util.Date;
import org.eclipse.bpel.common.ui.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
/**
* The CalendarPopup is designed to easily allow other controls to provide
* a calendar popup. The CalendarPopup is responsible for displaying a calendar
* control popup.
*
* The control that uses this class must provide a reference control as an anchor
* point to determine where the popup should be displayed.
*/
public class CalendarPopup {
Date date;
CalendarControl calendar;
Shell popupShell;
Shell shell;
Rectangle bounds;
int borderWidth;
private Button todayButton;
private Button noneButton;
/**
*
* @param shell shell containing the anchor
* @param absoluteBounds anchor bounds relative to the display
* @param borderWidth anchor border width
* @param initialDate
* @return
*/
public static Date openCalendarPopup(Shell shell, Rectangle absoluteBounds, int borderWidth, Date initialDate) {
return openCalendarPopup(shell, absoluteBounds, borderWidth, initialDate, null);
}
/**
*
* @param shell shell containing the anchor
* @param absoluteBounds anchor bounds relative to the display
* @param borderWidth anchor border width
* @param initialDate
* @return
*/
public static Date openCalendarPopup(Shell shell, Rectangle absoluteBounds, int borderWidth, Date initialDate,
String timezone)
{
CalendarPopup popup = new CalendarPopup(shell, absoluteBounds, borderWidth, initialDate,
timezone);
popup.open();
Display display = shell.getDisplay();
while (!popup.popupShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
popup.dispose();
return popup.date;
}
public static Date openCalendarPopup(Control anchor, Date initialDate) {
Rectangle anchorBounds = anchor.getBounds();
Point absolute = anchor.toDisplay(anchorBounds.x, anchorBounds.y);
anchorBounds.x = absolute.x;
anchorBounds.y = absolute.y;
return openCalendarPopup(anchor.getShell(), anchorBounds, anchor.getBorderWidth(), initialDate);
}
private CalendarPopup(Shell shell, Rectangle bounds, int borderWidth, Date initialDate,
String timezone)
{
this.shell = shell;
this.bounds = bounds;
this.borderWidth = borderWidth;
this.date = initialDate;
createShell();
hookListeners();
if (timezone != null)
calendar.setTimeZone(timezone);
calendar.setSelectedDate(initialDate);
}
private void createShell() {
popupShell = new Shell(shell, SWT.ON_TOP);
popupShell.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
GridLayout gl = new GridLayout(2, true);
popupShell.setLayout(gl);
calendar = new CalendarControl(popupShell);
GridData gd = new GridData();
gd.horizontalSpan = 2;
calendar.setLayoutData(gd);
todayButton = new Button(popupShell, SWT.PUSH);
todayButton.setText(Messages.CalendarPopup_todayButton_text);
noneButton = new Button(popupShell, SWT.PUSH);
noneButton.setText(Messages.CalendarPopup_noneButton_text);
int width = calculateButtonWidthHint();
gd = new GridData();
gd.horizontalAlignment = GridData.END;
gd.widthHint = width;
todayButton.setLayoutData(gd);
gd = new GridData();
gd.horizontalAlignment = GridData.BEGINNING;
gd.widthHint = width;
noneButton.setLayoutData(gd);
popupShell.pack();
}
private void hookListeners() {
popupShell.addListener(SWT.Deactivate,new Listener() {
public void handleEvent(final Event e) {
e.widget.getDisplay().asyncExec(new Runnable() {
public void run() {
Shell activeShell = Display.getCurrent().getActiveShell();
if(activeShell == null || (activeShell != popupShell)) {
selectAndClose(date);
}
}
});
}
});
popupShell.addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
switch (e.keyCode) {
case SWT.ESC:
selectAndClose(date);
e.doit = false;
break;
}
}
});
calendar.addMouseListener(new MouseAdapter() {
private int index = -1;
@Override
public void mouseDown(MouseEvent e) {
index = calendar.getMatrixIndex(e.x, e.y);
}
@Override
public void mouseUp(MouseEvent e) {
if (index != -1 && index == calendar.getMatrixIndex(e.x, e.y)) {
selectAndClose(calendar.getSelectedDate());
} else {
index = -1;
}
}
});
calendar.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
// TODO Is this Platform independent?
if (e.keyCode == SWT.CR) {
selectAndClose(calendar.getSelectedDate());
}
}
});
todayButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
selectAndClose(new Date());
}
});
noneButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
selectAndClose(null);
}
});
}
private int calculateButtonWidthHint() {
Point todaySize = todayButton.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point noneSize = noneButton.computeSize(SWT.DEFAULT, SWT.DEFAULT);
return (todaySize.x > noneSize.x) ? todaySize.x : noneSize.x;
}
void selectAndClose(Date date) {
this.date = date;
close();
}
/**
* Shows a popup that contains the calendar control as well as
* "Today" and "None" buttons.
*
* The popup is displayed in a position that it is fully visible on the screen.
* It uses the anchor control as a reference point to display the popup.
*/
private void open() {
calendar.setFocus();
Monitor monitor = shell.getMonitor();
Rectangle size = popupShell.getBounds();
Rectangle monitorBounds = monitor.getBounds();
Point location = new Point(bounds.x, bounds.y + bounds.height);
if (location.x + size.width > monitorBounds.x + monitorBounds.width) {
location.x = monitorBounds.x + monitorBounds.width - size.width;
} else if (location.x < monitorBounds.x) {
location.x = monitorBounds.x;
} else {
location.x -= borderWidth;
}
if (location.y + size.height > monitorBounds.y + monitorBounds.height) {
location.y = location.y - size.height - bounds.height - (borderWidth * 2);
} else if (location.y < monitorBounds.y) {
location.y = monitorBounds.y;
}
popupShell.setLocation(location.x, location.y);
popupShell.open();
}
/**
* Hides the calendar popup from view.
*/
private void close() {
if (popupShell == null || popupShell.isDisposed())
return;
popupShell.setVisible(false);
popupShell.dispose();
}
/**
* Disposes of the resources used by this class. This method must be called
* when the client is finished with the calendar popup.
*/
private void dispose() {
if (calendar != null) {
calendar.dispose();
calendar = null;
}
if (popupShell != null) {
popupShell.dispose();
popupShell = null;
}
}
}