/******************************************************************************* * Copyright (c) 2009 the CHISEL group and contributors. 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: Del Myers - initial API and implementation *******************************************************************************/ package ca.uvic.chisel.widgets; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.TypedListener; /** * A simple widget that presents millisecond time values in hh:mm:ss._ms format. * Can't display more than 99 hours. * * @author Del Myers * */ public class TimeField extends Composite { private static final long MAX_TIME = 999 + 1000 * (59 + 60 * (59 + 60 * 24)); private class FieldModifyListener extends MouseAdapter implements KeyListener, FocusListener { private int focusTime; /* * (non-Javadoc) * @see * java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent) */ @Override public void mouseDown(MouseEvent e) { if (e.time == focusTime) { ((Text) e.widget).selectAll(); } } /* * (non-Javadoc) * @see * org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt. * events.ModifyEvent) */ public void keyReleased(KeyEvent e) { if (e.keyCode == '\r') { doUpdate(); } } private void doUpdate() { if (updating) { return; } // set the new time long hour = 0; long minute = 0; long second = 0; long ms = 0; try { ms += Long.parseLong(msText.getText()); } catch (NumberFormatException ex) { } try { second += Long.parseLong(secondText.getText()); } catch (NumberFormatException ex) { } try { minute += Long.parseLong(minuteText.getText()); } catch (NumberFormatException ex) { } try { hour += Long.parseLong(hourText.getText()); } catch (NumberFormatException ex) { } long time = ms + 1000 * (second + 60 * (minute + 60 * (hour))); updateTime(time); } /* * (non-Javadoc) * @see * org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events * .KeyEvent) */ public void keyPressed(KeyEvent e) { } /* * (non-Javadoc) * @see * org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt. * events.FocusEvent) */ public void focusGained(FocusEvent e) { focusTime = e.time; } /* * (non-Javadoc) * @see * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events * .FocusEvent) */ public void focusLost(FocusEvent e) { doUpdate(); } } private Text hourText; private Text minuteText; private Text secondText; private Text msText; private long time; private FieldModifyListener modifyListener; private boolean updating; private static final long SECOND_TIME = 1000; private static final long MINUTE_TIME = SECOND_TIME * 60; private static final long HOUR_TIME = MINUTE_TIME * 60; /** * @param parent * @param style */ public TimeField(Composite parent, int style) { super(parent, style); this.modifyListener = new FieldModifyListener(); GridLayout layout = new GridLayout(7, false); layout.marginWidth = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; Composite page = this; page.setLayout(layout); hourText = createText(page, style); Label l = new Label(page, SWT.NONE); l.setText(":"); l.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); minuteText = createText(page, style); l = new Label(page, SWT.NONE); l.setText(":"); l.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); secondText = createText(page, style); l = new Label(page, SWT.NONE); l.setText("."); l.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); msText = createText(page, style); setTime(0); } /** * @param page * @param style * @return */ private Text createText(Composite page, int style) { // get rid of multiple lines if they are present in the style. style = (style | SWT.MULTI | SWT.SINGLE) ^ SWT.MULTI; Text t = new Text(page, style); t.setLayoutData(new GridData(SWT.END, SWT.END, false, false)); t.addKeyListener(modifyListener); t.addFocusListener(modifyListener); t.addMouseListener(modifyListener); return t; } private void updateTime(long time) { if (time == getTime()) { return; } setTime(time); fireChange(); } /** * */ private void fireChange() { Event e = new Event(); e.data = time; e.text = "" + time; notifyListeners(SWT.Modify, e); } /** * Sets the time to the given millisecond time. * * @param time */ public void setTime(long time) { checkWidget(); if (time > MAX_TIME) { time = MAX_TIME; } this.time = time; updateFields(); } /** * */ private void updateFields() { updating = true; long hours = time / HOUR_TIME; long remainder = time % HOUR_TIME; long minutes = remainder / MINUTE_TIME; remainder = remainder % MINUTE_TIME; long seconds = remainder / SECOND_TIME; remainder = remainder % SECOND_TIME; String text = "" + hours; text = padWithZeros(text, 2); hourText.setText(text); text = "" + minutes; text = padWithZeros(text, 2); minuteText.setText(text); text = "" + seconds; text = padWithZeros(text, 2); secondText.setText(text); text = "" + remainder; text = padWithZeros(text, 3); msText.setText(text); updating = false; } /** * Returns the "hours" field of the time. * * @param time * @return the "hours" field of the time. */ public static String getHours(long time) { return padWithZeros((time / HOUR_TIME) + "", 2); } /** * Returns the "minutes" field of the time. * * @param time * @return the "minutes" field of the time. */ public static String getMinutes(long time) { return padWithZeros(((time % HOUR_TIME) / MINUTE_TIME) + "", 2); } /** * Returns the "seconds" field of the time. * * @param time * @return the "seconds" field of the time. */ public static String getSeconds(long time) { return padWithZeros((((time % HOUR_TIME) % MINUTE_TIME) / SECOND_TIME) + "", 2); } /** * Returns the "milliseconds" field of the time. * * @param time * @return the "milliseconds" field of the time. */ public static String getMillis(long time) { return padWithZeros( ((((time % HOUR_TIME) % MINUTE_TIME) % SECOND_TIME)) + "", 3); } /** * @return a string representation of the given time. */ public static String toString(long time) { return getHours(time) + ":" + getMinutes(time) + ":" + getSeconds(time) + "." + getMillis(time); } /** * @param text * @param i */ private static String padWithZeros(String text, int i) { while (text.length() < i) { text = 0 + text; } return text; } /** * @return */ public long getTime() { return time; } /** * Adds a listener for when the value of the time has changed. This sort of * breaks the purpose of a modify listener, but I don't really have any idea * what other kind of listener to put in. * * @param typedTimeListener */ public void addModifyListener(ModifyListener listener) { checkWidget(); if (listener == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); TypedListener tl = new TypedListener(listener); addListener(SWT.Modify, tl); } }