/******************************************************************************* * 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.swt.nebula.widgets.compositetable.day.internal; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.LinkedList; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Widget; /** * Represents a time slice that is the same time but may span several days. * For example: 11:00 - 11:15 PM from Sunday through Saturday. * * @since 3.2 */ public class TimeSlice extends Composite { private final Image allDayImage = new Image(Display.getCurrent(), TimeSlice.class.getResourceAsStream("clock.png")); /** * The 0th control in the layout may have a java.lang.Integer LayoutData * indicating its preferred width. Otherwise, DaysLayout will ask the * control to compute its preferred size and will use the width returned by * that computation. All other controls will be equally allotted horizontal * width in the parent control. */ private static class TimeSliceAcrossTimeLayout extends Layout { Point preferredSize = new Point(-1, -1); protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { if (preferredSize.x == -1 || flushCache) { preferredSize.x = wHint; preferredSize.y = -1; // NOTE: This assumes at least one child // control Control[] children = composite.getChildren(); for (int i = 0; i < children.length; i++) { Control child = children[i]; preferredSize.y = Math.max(preferredSize.y, child .computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y); } } return preferredSize; } protected void layout(Composite composite, boolean flushCache) { Point parentSize = composite.getSize(); Control[] children = composite.getChildren(); // layout 0th control Integer preferredWidth = (Integer) children[0].getLayoutData(); if (preferredWidth == null) { preferredWidth = new Integer(children[0].computeSize( SWT.DEFAULT, SWT.DEFAULT).x); } children[0].setBounds(0, 0, preferredWidth.intValue(), parentSize.y); // layout the rest of the controls int controlWidth = 0; int extraWidth = 0; if (children.length >= 2) { controlWidth = (parentSize.x - preferredWidth.intValue()) / (children.length - 1); extraWidth = (parentSize.x - preferredWidth.intValue()) % (children.length - 1); } int leftPosition = preferredWidth.intValue(); for (int i = 1; i < children.length; i++) { Control control = children[i]; int width = controlWidth; if (extraWidth > 0) { ++width; --extraWidth; } control.setBounds(leftPosition, 0, width, parentSize.y); leftPosition += width; } } } private CLabel timeLabel = null; private LinkedList columns = new LinkedList(); /** * @return Returns the columns. */ public LinkedList getColumns() { return columns; } /** * Returns the control that implements the specified column. * * @param column The column number. * @return Control the SWT control that implements this column. */ public Control getColumnControl(int column) { return (Control) columns.get(column); } /** * Return the column number of the specified widget. * * @param widget the TimeSlot widget * @return the column number of the specified TimeSlot within this TimeSlice. */ public int getControlColumn(Widget widget) { int columnNumber = 0; for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { if (columnsIter.next() == widget) { return columnNumber; } ++columnNumber; } throw new IllegalArgumentException("Unrecognized widget passed to getControlColumn"); } /** * Constructor TimeSlice. Construct a TimeSlice control, passing the parent * and style bits. * * @param parent * The SWT parent object. * @param style * The set of style bits this control accepts. Currently SWT.NONE. */ public TimeSlice(Composite parent, int style) { super(parent, SWT.NULL); initialize(); } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#setMenu(org.eclipse.swt.widgets.Menu) */ public void setMenu(Menu menu) { super.setMenu(menu); for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { TimeSlot cell = (TimeSlot) columnsIter.next(); cell.setMenu(menu); } } /** * Initialize the control */ private void initialize() { timeLabel = new CLabel(this, SWT.RIGHT); timeLabel.setText("23:00 PM"); Integer preferredWidth = new Integer(timeLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT, false).x + 5); timeLabel.setLayoutData(preferredWidth); timeLabel.setText(""); setBackground(Display.getCurrent().getSystemColor( SWT.COLOR_WIDGET_BACKGROUND)); setSize(new Point(537, 16)); setLayout(new TimeSliceAcrossTimeLayout()); } private boolean headerControl = false; /** * @return Returns the headerControl. */ public boolean isHeaderControl() { return headerControl; } /** * @param headerControl The headerControl to set. */ public void setHeaderControl(boolean headerControl) { this.headerControl = headerControl; } private int numberOfColumns = 1; /** * Gets the number of columns that will be displayed in this row. The * default number of columns is 1. * * @return numberOfColumns The number of days to display. */ public int getNumberOfColumns() { return numberOfColumns; } /** * Sets the number of columns that will be displayed in this row. The * default number of columns is 1. This method may only be called *once* at * the beginning of the control's life cycle, and the value passed must be * >1. * <p> * Calling this method more than once results in undefined behavior. * * @param numberOfColumns * The number of days to display. */ public void setNumberOfColumns(int numberOfColumns) { this.numberOfColumns = numberOfColumns; Control[] tabStops = new Control[numberOfColumns]; for (int i = numberOfColumns; i > 0; --i) { if (headerControl) { CLabel control = new CLabel(this, SWT.SHADOW_OUT | SWT.BORDER | SWT.CENTER); tabStops[numberOfColumns-i] = control; columns.add(control); } else { TimeSlot control = new TimeSlot(this, SWT.NONE); tabStops[numberOfColumns-i] = control; columns.add(control); } } setTabList(tabStops); } private Date currentTime = new Date(); /** * @return The current time set in this "days" row. */ public Date getCurrentTime() { return currentTime; } /** * @param currentTime */ public void setCurrentTime(Date currentTime) { // if currentTime is null, we are becoming an all-day event row if (currentTime == null) { timeLabel.setImage(allDayImage); timeLabel.setText(""); setAllDayEventOnDays(true); return; } setAllDayEventOnDays(false); timeLabel.setImage(null); setTimeOnDays(currentTime); this.currentTime = currentTime; Calendar calendar = new GregorianCalendar(); calendar.setTime(currentTime); // Only the hours will display in the label if (calendar.get(Calendar.MINUTE) == 0) { DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT); String time = df.format(currentTime); timeLabel.setText(time); } else { timeLabel.setText(""); } } private void setTimeOnDays(Date currentTime) { for (Iterator daysIter = columns.iterator(); daysIter.hasNext();) { Object dayCandidate = daysIter.next(); if (dayCandidate instanceof TimeSlot) { TimeSlot day = (TimeSlot) dayCandidate; day.setTime(currentTime); } } } private void setAllDayEventOnDays(boolean isAllDayEvent) { for (Iterator daysIter = columns.iterator(); daysIter.hasNext();) { Object dayCandidate = daysIter.next(); if (dayCandidate instanceof TimeSlot) { TimeSlot day = (TimeSlot) dayCandidate; day.setAllDay(isAllDayEvent); } } } /** * @see org.eclipse.swt.widgets.Control#addFocusListener * * @param listener */ public void addCellFocusListener(FocusListener listener) { for (Iterator daysIter = columns.iterator(); daysIter.hasNext();) { Object dayCandidate = daysIter.next(); if (dayCandidate instanceof TimeSlot) { TimeSlot day = (TimeSlot) dayCandidate; day.addFocusListener(listener); } } } /** * @see org.eclipse.swt.widgets.Control#removeFocusListener * @param listener */ public void removeCellFocusListener(FocusListener listener) { for (Iterator daysIter = columns.iterator(); daysIter.hasNext();) { Object dayCandidate = daysIter.next(); if (dayCandidate instanceof TimeSlot) { TimeSlot day = (TimeSlot) dayCandidate; day.removeFocusListener(listener); } } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#addKeyListener(org.eclipse.swt.events.KeyListener) */ public void addKeyListener(KeyListener listener) { super.addKeyListener(listener); for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { TimeSlot cell = (TimeSlot) columnsIter.next(); cell.addKeyListener(listener); } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#removeKeyListener(org.eclipse.swt.events.KeyListener) */ public void removeKeyListener(KeyListener listener) { super.removeKeyListener(listener); for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { TimeSlot cell = (TimeSlot) columnsIter.next(); cell.removeKeyListener(listener); } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#addKeyListener(org.eclipse.swt.events.KeyListener) */ public void addMouseListener(MouseListener listener) { super.addMouseListener(listener); for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { TimeSlot cell = (TimeSlot) columnsIter.next(); cell.addMouseListener(listener); } } /* (non-Javadoc) * @see org.eclipse.swt.widgets.Control#removeKeyListener(org.eclipse.swt.events.KeyListener) */ public void removeMouseListener(MouseListener listener) { super.removeMouseListener(listener); for (Iterator columnsIter = columns.iterator(); columnsIter.hasNext();) { TimeSlot cell = (TimeSlot) columnsIter.next(); cell.removeMouseListener(listener); } } } // @jve:decl-index=0:visual-constraint="10,10"