blob: 3f26267fdebcfd750b2600a870efa14842b0fddf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 The Pampered Chef 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:
* The Pampered Chef - initial API and implementation
******************************************************************************/
package org.eclipse.jface.examples.databinding.compositetable.month.internal;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import org.eclipse.jface.examples.databinding.compositetable.day.internal.ICalendarableItemControl;
import org.eclipse.jface.examples.databinding.compositetable.month.MonthCalendarableItemControl;
import org.eclipse.jface.examples.databinding.compositetable.timeeditor.CalendarableItem;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
/**
* An SWT custom control representing a single day in a month-mode calendar.
*/
public class Day extends Canvas implements PaintListener, DisposeListener {
private final Color FOCUS_RUBBERBAND;
private Color CURRENT_MONTH;
private Color OTHER_MONTH;
private Color CELL_BACKGROUND_LIGHT;
private static final int FOCUS_LINE_WIDTH = 2;
private boolean focusControl = false;
private static final int _SIZE_MULTIPLIER = 7;
private Label dayNumber = null;
private Label spacer = null;
private Point textBounds;
private Point monthPosition = null;
/**
* @param parent
* @param style
*/
public Day(Composite parent, int style) {
super(parent, style);
Display display = Display.getCurrent();
FOCUS_RUBBERBAND = new Color(display, lighten(saturate(display.getSystemColor(SWT.COLOR_TITLE_BACKGROUND).getRGB(), .85f), -.333f));
CURRENT_MONTH = display.getSystemColor(SWT.COLOR_WHITE);
OTHER_MONTH = new Color(display, new RGB(230, 230, 230));
CELL_BACKGROUND_LIGHT = new Color(display, new RGB(248, 248, 248));
initialize();
addTraverseListener(traverseListener);
addKeyListener(keyListener);
addMouseListener(mouseListener);
spacer.addMouseListener(mouseListener);
dayNumber.addMouseListener(mouseListener);
addFocusListener(focusListener);
addPaintListener(this);
addDisposeListener(this);
}
/**
* Sets the color's saturation to the specified value.
*
* @param color The RGB of the color
* @param saturation the new saturation (between 0 and 1)
* @return a Color that is saturated by the specified amount
*/
private RGB saturate(RGB color, float saturation) {
float[] hsb = color.getHSB();
return new RGB(hsb[0], saturation, hsb[2]);
}
/**
* @param color The RGB of the color
* @param amount The amount to lighten as a percentage expresssed as a float between -1 and 1.
* @return The new RGB that is lightened by the specified amount
*/
private RGB lighten(RGB color, float amount) {
float[] hsb = color.getHSB();
float b = hsb[2] + hsb[2] * amount;
if (b < 0) b=0;
if (b > 1) b=1;
return new RGB(hsb[0], hsb[1], b);
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
public void widgetDisposed(DisposeEvent e) {
FOCUS_RUBBERBAND.dispose();
OTHER_MONTH.dispose();
CELL_BACKGROUND_LIGHT.dispose();
removeTraverseListener(traverseListener);
removeKeyListener(keyListener);
removeMouseListener(mouseListener);
spacer.removeMouseListener(mouseListener);
dayNumber.removeMouseListener(mouseListener);
removeFocusListener(focusListener);
removePaintListener(this);
removeDisposeListener(this);
}
private void initialize() {
GridData gd = new GridData();
gd.horizontalSpan = 2;
gd.verticalAlignment = GridData.FILL;
gd.grabExcessVerticalSpace = true;
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = GridData.FILL;
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessHorizontalSpace = true;
gridData.verticalAlignment = GridData.CENTER;
spacer = new Label(this, SWT.NONE);
spacer.setLayoutData(gridData);
spacer.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
gridLayout.verticalSpacing = 0;
dayNumber = new Label(this, SWT.NONE);
dayNumber.setFont(JFaceResources.getFontRegistry().get(
JFaceResources.BANNER_FONT));
dayNumber.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
dayNumber.setForeground(Display.getCurrent().getSystemColor(
SWT.COLOR_LIST_SELECTION));
dayNumber.setText("31");
textBounds = dayNumber.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
this.setBackground(Display.getCurrent().getSystemColor(
SWT.COLOR_LIST_BACKGROUND));
this.setLayout(gridLayout);
setSize(new org.eclipse.swt.graphics.Point(106, 101));
setBackground(CELL_BACKGROUND_LIGHT);
}
public Point computeSize(int wHint, int hHint, boolean changed) {
Point size = new Point(0, 0);
size.x = textBounds.x * _SIZE_MULTIPLIER;
size.y = textBounds.y * _SIZE_MULTIPLIER / 2;
return size;
}
/**
* @return The (day, week) of this day in the month.
*/
public Point getMonthPosition() {
return monthPosition;
}
/**
* @param monthPosition The (day, week) of this day in the month.
*/
public void setMonthPosition(Point monthPosition) {
this.monthPosition = monthPosition;
}
/**
* @return The day's number
*/
public int getDayNumber() {
return Integer.parseInt(dayNumber.getText());
}
/**
* @param dayNum the day number to set
*/
public void setDayNumber(int dayNum) {
dayNumber.setText(Integer.toString(dayNum));
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
*/
public void paintControl(PaintEvent e) {
GC gc = e.gc;
// Save stuff we're about to change so we can restore it later
int oldLineStyle = gc.getLineStyle();
int oldLineWidth = gc.getLineWidth();
// Draw focus rubberband if we're focused
try {
if (focusControl) {
gc.setLineStyle(SWT.LINE_DASH);
gc.setLineWidth(FOCUS_LINE_WIDTH);
gc.setForeground(FOCUS_RUBBERBAND);
Point parentSize = getSize();
gc.drawRectangle(FOCUS_LINE_WIDTH,
FOCUS_LINE_WIDTH, parentSize.x - 4,
parentSize.y - 3);
}
} finally {
gc.setLineStyle(oldLineStyle);
gc.setLineWidth(oldLineWidth);
}
}
private LinkedList mouseListeners = new LinkedList();
/* (non-Javadoc)
* @see org.eclipse.swt.widgets.Control#addMouseListener(org.eclipse.swt.events.MouseListener)
*/
public void addMouseListener(MouseListener listener) {
super.addMouseListener(listener);
if (listener != mouseListener) mouseListeners.add(listener);
}
public void removeMouseListener(MouseListener listener) {
super.removeMouseListener(listener);
if (listener != mouseListener) mouseListeners.remove(listener);
}
private MouseListener mouseListener = new MouseListener() {
public void mouseDown(MouseEvent e) {
setFocus();
for (Iterator i = mouseListeners.iterator(); i.hasNext();) {
MouseListener listener = (MouseListener) i.next();
listener.mouseDown(e);
}
}
public void mouseUp(MouseEvent e) {
for (Iterator i = mouseListeners.iterator(); i.hasNext();) {
MouseListener listener = (MouseListener) i.next();
listener.mouseUp(e);
}
}
public void mouseDoubleClick(MouseEvent e) {
for (Iterator i = mouseListeners.iterator(); i.hasNext();) {
MouseListener listener = (MouseListener) i.next();
listener.mouseDoubleClick(e);
}
}
};
private KeyListener keyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
switch (e.keyCode) {
case SWT.ARROW_LEFT:
if (monthPosition.x > 0) {
traverse(SWT.TRAVERSE_TAB_PREVIOUS);
}
return;
case SWT.ARROW_RIGHT:
if (monthPosition.x < 6) {
traverse(SWT.TRAVERSE_TAB_NEXT);
}
return;
case SWT.TAB:
if ((e.stateMask & SWT.SHIFT) != 0) {
traverse(SWT.TRAVERSE_TAB_PREVIOUS);
return;
}
traverse(SWT.TRAVERSE_TAB_NEXT);
return;
}
}
};
/**
* Permit focus events via keyboard.
*/
private TraverseListener traverseListener = new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
// NOOP: this just lets us receive focus from SWT
}
};
/**
* When we gain/lose focus, redraw ourselves appropriately
*/
private FocusListener focusListener = new FocusListener() {
public void focusGained(FocusEvent e) {
focusControl = true;
Color background = getBackgroundTakingIntoAccountIfWeAreInTheCurrentMonth(true);
resetAllBackgrounds(Day.this, background);
redraw();
}
public void focusLost(FocusEvent e) {
focusControl = false;
Color background = getBackgroundTakingIntoAccountIfWeAreInTheCurrentMonth(false);
resetAllBackgrounds(Day.this, background);
redraw();
}
};
private void resetAllBackgrounds(Composite composite, Color color) {
composite.setBackground(color);
Control[] children = composite.getChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Composite) {
resetAllBackgrounds((Composite) children[i], color);
} else {
children[i].setBackground(color);
}
}
}
private Color getBackgroundTakingIntoAccountIfWeAreInTheCurrentMonth(boolean focused) {
if (inCurrentMonth && focused) {
return CURRENT_MONTH;
}
if (inCurrentMonth) {
return CELL_BACKGROUND_LIGHT;
}
return OTHER_MONTH;
}
private boolean inCurrentMonth = false;
/**
* @param inCurrentMonth
*/
public void setInCurrentMonth(boolean inCurrentMonth) {
this.inCurrentMonth = inCurrentMonth;
Color background = getBackgroundTakingIntoAccountIfWeAreInTheCurrentMonth(false);
resetAllBackgrounds(this, background);
}
private CalendarableItem[] controls = null;
/**
* @param controls
*/
public void setItems(CalendarableItem[] controls) {
if (this.controls != null) {
for (int i = 0; i < this.controls.length; i++) {
ICalendarableItemControl control = this.controls[i].getControl();
control.removeMouseListener(mouseListener);
control.dispose();
}
}
this.controls = controls;
for (int i = 0; i < this.controls.length; i++) {
MonthCalendarableItemControl control = new MonthCalendarableItemControl(this, SWT.NULL);
getBackgroundTakingIntoAccountIfWeAreInTheCurrentMonth(false);
control.setText(this.controls[i].getText());
Image image = this.controls[i].getImage();
if (image != null) {
control.setImage(image);
}
control.setToolTipText(this.controls[i].getToolTipText());
control.addMouseListener(mouseListener);
GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false);
gd.horizontalSpan=2;
control.setLayoutData(gd);
this.controls[i].setControl(control);
}
}
private Date date;
/**
* Sets the Date represented by this Day.
*
* @param date The date to set
*/
public void setDate(Date date) {
this.date = date;
}
/**
* Returns the Date represented by this Day.
*
* @return This Day's date
*/
public Date getDate() {
return date;
}
} // @jve:decl-index=0:visual-constraint="10,10"