diff --git a/clean_all_whitespace.sh b/clean_all_whitespace.sh
index b0b6f95..2a57986 100755
--- a/clean_all_whitespace.sh
+++ b/clean_all_whitespace.sh
@@ -1,6 +1,7 @@
#!/bin/sh
./clean_trailing_whitespace.sh build.xml
+./clean_trailing_whitespace.sh timestamper.config
./clean_trailing_whitespace.sh src/jdbernard/timestamper/*.java
./clean_trailing_whitespace.sh src/jdbernard/timestamper/*.form
./clean_trailing_whitespace.sh src/jdbernard/timestamper/resources/*.properties
diff --git a/src/jdbernard/timestamper/TimeStamperApp.java b/src/jdbernard/timestamper/TimeStamperApp.java
index b3db88b..04f4f66 100755
--- a/src/jdbernard/timestamper/TimeStamperApp.java
+++ b/src/jdbernard/timestamper/TimeStamperApp.java
@@ -4,20 +4,75 @@
package jdbernard.timestamper;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.EventObject;
+import java.util.Properties;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;
/**
* The main class of the application.
*/
-public class TimeStamperApp extends SingleFrameApplication {
+public class TimeStamperApp extends SingleFrameApplication
+implements Application.ExitListener {
+
+ private Timeline activeTimeline;
+ private String currentTimelineFile;
+ private Logger log;
+ private Properties config;
+
+ public TimeStamperApp() {
+ super();
+
+ activeTimeline = new Timeline();
+
+ log = Logger.getLogger("jdbernard.timestamper");
+ log.setLevel(Level.CONFIG);
+
+ ConsoleHandler ch = new ConsoleHandler();
+ ch.setLevel(Level.INFO);
+
+ log.addHandler(ch);
+
+ try {
+ FileHandler fh = new FileHandler("TimeStamper.log", true);
+ fh.setLevel(Level.ALL);
+ } catch (IOException ioe) {
+ log.warning("Could not open log file for writing. Switching console"
+ + " logging to verbose.");
+ ch.setLevel(Level.ALL);
+ }
+
+ try {
+ config = new Properties();
+ FileInputStream cfgIn = new FileInputStream("timestamper.config");
+ config.load(cfgIn);
+ cfgIn.close();
+ } catch (IOException ioe) {
+ log.warning("Could not load configuration options.");
+ }
+
+ try {
+ activeTimeline = Timeline.readFromFile(
+ config.getProperty("lastUsedTimelineFilename"));
+ } catch (IOException ioe) {
+ log.warning("Could not load the last used timeline file.");
+ }
+ }
/**
* At startup create and show the main frame of the application.
*/
@Override protected void startup() {
show(new TimeStamperView(this));
- getMainFrame().setSize(400, 75);
+ getMainFrame().setSize(300, 60);
+ getApplication().addExitListener(this);
}
/**
@@ -42,4 +97,58 @@ public class TimeStamperApp extends SingleFrameApplication {
public static void main(String[] args) {
launch(TimeStamperApp.class, args);
}
+
+ public void saveTimeline() {
+ saveTimelineToFile(currentTimelineFile);
+ }
+
+ public void saveTimelineToFile(String filename) {
+ if (filename == null || filename.equals(""))
+ filename = "default-timeline.txt";
+
+ try {
+ Timeline.writeToFile(filename, activeTimeline);
+ currentTimelineFile = filename;
+ } catch (IOException ioe) {
+ log.warning("Could not save timeline file: "
+ + ioe.getLocalizedMessage());
+ }
+ }
+
+ public void loadTimeline(String filename) {
+
+ if (filename == null || filename.equals("")) {
+ activeTimeline = new Timeline();
+ return;
+ }
+
+ try {
+ activeTimeline = Timeline.readFromFile(filename);
+ // TODO: re-init gui for new timeline
+ } catch (IOException ioe) {
+ log.warning("Could not load from the file: " +
+ ioe.getLocalizedMessage());
+ }
+ }
+
+ public Timeline getActiveTimeline() {
+ return activeTimeline;
+ }
+
+ @Override
+ public void willExit(EventObject e) {
+ saveTimeline();
+
+ config.setProperty("lastUsedTimelineFilename", currentTimelineFile);
+ try {
+ FileOutputStream out = new FileOutputStream("timestamper.config");
+ config.store(out, "");
+ out.close();
+ } catch (IOException ioe) {
+ log.warning("Could not save config file.");
+ }
+ }
+
+ @Override
+ public boolean canExit(EventObject e) { return true; }
}
diff --git a/src/jdbernard/timestamper/TimeStamperView.form b/src/jdbernard/timestamper/TimeStamperView.form
index d61c345..bd73c61 100755
--- a/src/jdbernard/timestamper/TimeStamperView.form
+++ b/src/jdbernard/timestamper/TimeStamperView.form
@@ -11,19 +11,25 @@
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
@@ -32,7 +38,9 @@
-
+
+
+
@@ -46,23 +54,30 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
@@ -102,6 +117,11 @@
+
+
+
+
+
@@ -133,16 +153,16 @@
-
+
-
+
-
-
-
+
+
+
@@ -157,6 +177,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -174,6 +256,6 @@
-
+
diff --git a/src/jdbernard/timestamper/TimeStamperView.java b/src/jdbernard/timestamper/TimeStamperView.java
index 7819270..1fd9796 100755
--- a/src/jdbernard/timestamper/TimeStamperView.java
+++ b/src/jdbernard/timestamper/TimeStamperView.java
@@ -4,7 +4,20 @@
package jdbernard.timestamper;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+import javax.swing.JFileChooser;
import org.jdesktop.application.Action;
+import org.jdesktop.application.Application;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
@@ -12,7 +25,7 @@ import org.jdesktop.application.FrameView;
/**
* The application's main frame.
*/
-public class TimeStamperView extends FrameView {
+public class TimeStamperView extends FrameView implements MouseMotionListener {
public TimeStamperView(SingleFrameApplication app) {
super(app);
@@ -23,6 +36,47 @@ public class TimeStamperView extends FrameView {
getFrame().setUndecorated(true);
+ fileChooser = new JFileChooser();
+
+ updateTimer = new Timer();
+ updateTimer.scheduleAtFixedRate(new TimerTask() {
+
+ @Override
+ public void run() {
+ Date currentTime = new Date();
+ currentTimeLabel.setText(Timeline.shortFormat.format(currentTime));
+ if (mostRecentTask != null) {
+ long seconds = currentTime.getTime() - mostRecentTask.getTime();
+ seconds /= 1000;
+ long minutes = seconds / 60;
+ seconds = seconds % 60;
+ long hours = minutes / 60;
+ minutes %= 60;
+ long days = hours / 24;
+ hours %= 24;
+ StringBuilder sb = new StringBuilder();
+
+ if (days > 0) sb.append(Long.toString(days) + "day ");
+ if (hours > 0) sb.append(Long.toString(hours) + "hr ");
+ if (minutes > 0) sb.append(Long.toString(minutes) + "min ");
+ sb.append(Long.toString(seconds) + "sec");
+
+ totalTimeNow.setText(sb.toString());
+ } else totalTimeNow.setText("");
+ }
+ }, 0, 1000);
+
+ thinTaskFont = taskTextField.getFont().deriveFont(Font.PLAIN);
+ boldTaskFont = thinTaskFont.deriveFont(Font.BOLD);
+
+ // refresh new timeline
+ Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
+ Timeline.TimelineMarker lastMarker = t.getLastMarker(new Date());
+
+ mostRecentTask = lastMarker.getTimestamp();
+ startTimeLabel.setText(Timeline.shortFormat.format(lastMarker.getTimestamp()));
+
+ taskTextField.setText(lastMarker.getMark());
}
/** This method is called from within the constructor to
@@ -40,11 +94,22 @@ public class TimeStamperView extends FrameView {
taskTextField = new javax.swing.JTextField();
startTimeLabel = new javax.swing.JLabel();
totalTimeNow = new javax.swing.JLabel();
- jLabel1 = new javax.swing.JLabel();
+ currentTimeLabel = new javax.swing.JLabel();
notesButton = new javax.swing.JButton();
+ optionsButton = new javax.swing.JButton();
+ optionsMenu = new javax.swing.JPopupMenu();
+ saveTimelineMenuItem = new javax.swing.JMenuItem();
+ saveTimelineAsMenuItem = new javax.swing.JMenuItem();
+ loadTimelineMenuItem = new javax.swing.JMenuItem();
mainPanel.setBorder(javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, new java.awt.Color(0, 0, 0)));
mainPanel.setName("mainPanel"); // NOI18N
+ mainPanel.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mousePressed(java.awt.event.MouseEvent evt) {
+ mainPanelMousePressed(evt);
+ }
+ });
+ mainPanel.addMouseMotionListener(this);
currentTaskLabel.setFont(currentTaskLabel.getFont().deriveFont(currentTaskLabel.getFont().getStyle() | java.awt.Font.BOLD, currentTaskLabel.getFont().getSize()+2));
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getResourceMap(TimeStamperView.class);
@@ -68,6 +133,7 @@ public class TimeStamperView extends FrameView {
}
});
+ taskTextField.setFont(taskTextField.getFont().deriveFont(taskTextField.getFont().getStyle() | java.awt.Font.BOLD));
taskTextField.setText(resourceMap.getString("taskTextField.text")); // NOI18N
taskTextField.setName("taskTextField"); // NOI18N
taskTextField.addKeyListener(new java.awt.event.KeyAdapter() {
@@ -86,35 +152,59 @@ public class TimeStamperView extends FrameView {
totalTimeNow.setText(resourceMap.getString("totalTimeNow.text")); // NOI18N
totalTimeNow.setName("totalTimeNow"); // NOI18N
- jLabel1.setFont(jLabel1.getFont().deriveFont(jLabel1.getFont().getStyle() | java.awt.Font.BOLD, jLabel1.getFont().getSize()+3));
- jLabel1.setForeground(resourceMap.getColor("jLabel1.foreground")); // NOI18N
- jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
- jLabel1.setName("jLabel1"); // NOI18N
+ currentTimeLabel.setFont(currentTimeLabel.getFont().deriveFont(currentTimeLabel.getFont().getStyle() | java.awt.Font.BOLD, currentTimeLabel.getFont().getSize()+3));
+ currentTimeLabel.setForeground(resourceMap.getColor("currentTimeLabel.foreground")); // NOI18N
+ currentTimeLabel.setText(resourceMap.getString("currentTimeLabel.text")); // NOI18N
+ currentTimeLabel.setName("currentTimeLabel"); // NOI18N
notesButton.setAction(actionMap.get("editNotes")); // NOI18N
notesButton.setHideActionText(true);
notesButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
notesButton.setName("notesButton"); // NOI18N
+ optionsButton.setIcon(resourceMap.getIcon("optionsButton.icon")); // NOI18N
+ optionsButton.setContentAreaFilled(false);
+ optionsButton.setFocusPainted(false);
+ optionsButton.setHideActionText(true);
+ optionsButton.setIconTextGap(0);
+ optionsButton.setMargin(new java.awt.Insets(0, 0, 0, 0));
+ optionsButton.setMaximumSize(new java.awt.Dimension(16, 16));
+ optionsButton.setMinimumSize(new java.awt.Dimension(16, 16));
+ optionsButton.setName("optionsButton"); // NOI18N
+ optionsButton.setPreferredSize(new java.awt.Dimension(16, 16));
+ optionsButton.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ optionsButtonMouseClicked(evt);
+ }
+ public void mouseEntered(java.awt.event.MouseEvent evt) {
+ optionsButtonMouseEntered(evt);
+ }
+ public void mouseExited(java.awt.event.MouseEvent evt) {
+ optionsButtonMouseExited(evt);
+ }
+ });
+
javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
mainPanel.setLayout(mainPanelLayout);
mainPanelLayout.setHorizontalGroup(
mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(mainPanelLayout.createSequentialGroup()
.addContainerGap()
- .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
- .addGroup(mainPanelLayout.createSequentialGroup()
+ .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
.addComponent(totalTimeNow)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(jLabel1))
- .addComponent(taskTextField)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 12, Short.MAX_VALUE)
+ .addComponent(currentTimeLabel))
+ .addComponent(taskTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE)
.addGroup(mainPanelLayout.createSequentialGroup()
.addComponent(currentTaskLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(startTimeLabel)))
.addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(mainPanelLayout.createSequentialGroup()
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 109, Short.MAX_VALUE)
+ .addComponent(optionsButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGap(0, 0, 0)
.addComponent(exitButton))
.addGroup(mainPanelLayout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -124,27 +214,53 @@ public class TimeStamperView extends FrameView {
mainPanelLayout.setVerticalGroup(
mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(mainPanelLayout.createSequentialGroup()
- .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(currentTaskLabel)
+ .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(exitButton, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(startTimeLabel))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(taskTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addComponent(notesButton))
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
- .addComponent(totalTimeNow)
- .addComponent(jLabel1))
- .addContainerGap(15, Short.MAX_VALUE))
+ .addComponent(optionsButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(notesButton)
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(currentTaskLabel)
+ .addComponent(startTimeLabel))
+ .addGap(0, 0, 0)
+ .addComponent(taskTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
+ .addGap(0, 0, 0)
+ .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(currentTimeLabel)
+ .addComponent(totalTimeNow))))
+ .addContainerGap(24, Short.MAX_VALUE))
);
+ optionsMenu.setName("optionsMenu"); // NOI18N
+
+ saveTimelineMenuItem.setAction(actionMap.get("saveTimeline")); // NOI18N
+ saveTimelineMenuItem.setName("saveTimelineMenuItem"); // NOI18N
+ optionsMenu.add(saveTimelineMenuItem);
+
+ saveTimelineAsMenuItem.setAction(actionMap.get("saveTimelineAs")); // NOI18N
+ saveTimelineAsMenuItem.setName("saveTimelineAsMenuItem"); // NOI18N
+ optionsMenu.add(saveTimelineAsMenuItem);
+
+ loadTimelineMenuItem.setAction(actionMap.get("loadTimeline")); // NOI18N
+ loadTimelineMenuItem.setName("loadTimelineMenuItem"); // NOI18N
+ optionsMenu.add(loadTimelineMenuItem);
+
setComponent(mainPanel);
}// //GEN-END:initComponents
private void taskTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_taskTextFieldKeyReleased
- // Do stuff
-
+ if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
+ Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
+ Date d = new Date();
+ t.addMarker(d, taskTextField.getText(), "No comments.");
+ startTimeLabel.setText(Timeline.shortFormat.format(d));
+ taskTextField.setFont(boldTaskFont);
+ mostRecentTask = d;
+ } else {
+ taskTextField.setFont(thinTaskFont);
+ }
}//GEN-LAST:event_taskTextFieldKeyReleased
private void exitButtonMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_exitButtonMouseEntered
@@ -155,20 +271,139 @@ private void exitButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:e
exitButton.setIcon(getResourceMap().getIcon("exitButton.icon"));
}//GEN-LAST:event_exitButtonMouseExited
+private void optionsButtonMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_optionsButtonMouseEntered
+ optionsButton.setIcon(getResourceMap().getIcon("optionsButton.hover.icon"));//GEN-LAST:event_optionsButtonMouseEntered
+}
+
+private void optionsButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_optionsButtonMouseExited
+ optionsButton.setIcon(getResourceMap().getIcon("optionsButton.icon"));//GEN-LAST:event_optionsButtonMouseExited
+}
+
+private void mainPanelMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mainPanelMousePressed
+ mousePressRelativeToFrame = evt.getPoint();
+}//GEN-LAST:event_mainPanelMousePressed
+
+private void optionsButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_optionsButtonMouseClicked
+ optionsMenu.show(evt.getComponent(), evt.getX(), evt.getY());
+}//GEN-LAST:event_optionsButtonMouseClicked
+
@Action
public void editNotes() {
-
+ // TODO:
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel currentTaskLabel;
+ private javax.swing.JLabel currentTimeLabel;
private javax.swing.JButton exitButton;
- private javax.swing.JLabel jLabel1;
+ private javax.swing.JMenuItem loadTimelineMenuItem;
private javax.swing.JPanel mainPanel;
private javax.swing.JButton notesButton;
+ private javax.swing.JButton optionsButton;
+ private javax.swing.JPopupMenu optionsMenu;
+ private javax.swing.JMenuItem saveTimelineAsMenuItem;
+ private javax.swing.JMenuItem saveTimelineMenuItem;
private javax.swing.JLabel startTimeLabel;
private javax.swing.JTextField taskTextField;
private javax.swing.JLabel totalTimeNow;
// End of variables declaration//GEN-END:variables
+ private Point mousePressRelativeToFrame;
+ private JFileChooser fileChooser;
+ private Timer updateTimer;
+ private Font boldTaskFont;
+ private Font thinTaskFont;
+ private Date mostRecentTask;
+
+ public void mouseDragged(MouseEvent e) {
+ Point currentMousePoint = e.getLocationOnScreen();
+
+ // this is the point we will compute as the new upper left
+ // coordinate of the frame. It needs to be translated some to account
+ // for the fact that the user can press the mouse anywhere on the
+ // main panel.
+ Point finalPoint = (Point) currentMousePoint.clone();
+ // find out where the new point should be, ignoreing screen bounds
+ finalPoint.translate(-mousePressRelativeToFrame.x,
+ -mousePressRelativeToFrame.y);
+
+ // get the current frame bounds
+ Rectangle frameBounds = getFrame().getBounds();
+
+ // screen resolution
+ Dimension resolution = Toolkit.getDefaultToolkit().getScreenSize();
+
+ // check to see if the frame is near any of the screen boundaries
+ // if it is, 'snap' the final point to that boundary.
+ if (frameBounds.x < 20)
+ finalPoint.translate(-finalPoint.x, 0);
+ if (frameBounds.y < 20)
+ finalPoint.translate(0, -finalPoint.y);
+ if ((resolution.width - (frameBounds.x + frameBounds.width)) < 20)
+ finalPoint.translate(resolution.width -
+ (finalPoint.x + frameBounds.width), 0);
+ if ((resolution.height - (frameBounds.y + frameBounds.height)) < 20)
+ finalPoint.translate(0, resolution.height -
+ (finalPoint.y + frameBounds.height));
+
+
+ // this point represents a backwards version of the initial calculation
+ // to find the finalPoint. It says, based on the current final point,
+ // assume I moved the frame to that point. Where, relative to that point
+ // should the mouse be, based on how far it was relative to the point
+ // when the user pressed it.
+ Point whereMouseShouldBe = (Point) finalPoint.clone();
+ whereMouseShouldBe.translate(mousePressRelativeToFrame.x,
+ mousePressRelativeToFrame.y);
+
+ // if the actual mouse location is different from the expected location,
+ // then we know that the snapping behaviour has altered the frames new
+ // placement. If this alteration is too large (30 px apart in this case)
+ // then we know the user is trying to pull the frame out of its snapped
+ // position. In this case, we want to ignore the snap calculations and
+ // base the new frame location entirely on the current mouse location
+ if (whereMouseShouldBe.distance(currentMousePoint) > 30) {
+ finalPoint = (Point) currentMousePoint.clone();
+ finalPoint.translate(-mousePressRelativeToFrame.x,
+ -mousePressRelativeToFrame.y);
+ }
+
+ // once we've figured out where to go, put us there :)
+ getFrame().setLocation(finalPoint);
+ }
+
+ public void mouseMoved(MouseEvent e) {
+ }
+
+ @Action
+ public void saveTimeline() {
+ ((TimeStamperApp) getApplication()).saveTimeline();
+ }
+
+ @Action
+ public void saveTimelineAs() {
+ if (fileChooser.showSaveDialog(getFrame())!=JFileChooser.APPROVE_OPTION)
+ return;
+
+ ((TimeStamperApp) getApplication()).saveTimelineToFile(
+ fileChooser.getSelectedFile().getAbsolutePath());
+ }
+
+ @Action
+ public void loadTimeline() {
+ if (fileChooser.showOpenDialog(getFrame())!=JFileChooser.APPROVE_OPTION)
+ return;
+
+ ((TimeStamperApp) getApplication()).loadTimeline(
+ fileChooser.getSelectedFile().getAbsolutePath());
+
+ // refresh new timeline
+ Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
+ Timeline.TimelineMarker lastMarker = t.getLastMarker(new Date());
+
+ mostRecentTask = lastMarker.getTimestamp();
+ startTimeLabel.setText(Timeline.shortFormat.format(lastMarker.getTimestamp()));
+
+ taskTextField.setText(lastMarker.getMark());
+ }
}
diff --git a/src/jdbernard/timestamper/Timeline.java b/src/jdbernard/timestamper/Timeline.java
index 031051b..992a925 100644
--- a/src/jdbernard/timestamper/Timeline.java
+++ b/src/jdbernard/timestamper/Timeline.java
@@ -93,18 +93,29 @@ public class Timeline implements Iterable {
}
public String getLastName(Date timestamp) {
- //TODO:
- return null;
+ TimelineMarker lastMarker = getLastMarker(timestamp);
+ return (lastMarker == null ?
+ "No previous marker." :
+ lastMarker.getMark());
+
}
public String getLastNotes(Date timestamp) {
- //TODO:
- return null;
+ TimelineMarker lastMarker = getLastMarker(timestamp);
+ return (lastMarker == null ?
+ "No previous marker." :
+ lastMarker.getNotes());
}
public TimelineMarker getLastMarker(Date timestamp) {
- //TODO:
- return null;
+ TimelineMarker lastMarker = null;
+ for (TimelineMarker tm : timelineList) {
+ if (tm.getTimestamp().after(timestamp))
+ break;
+ lastMarker = tm;
+ }
+
+ return lastMarker;
}
public void removeMarker(TimelineMarker marker) {
diff --git a/src/jdbernard/timestamper/resources/TimeStamperView.properties b/src/jdbernard/timestamper/resources/TimeStamperView.properties
index 4cd12e8..69e5b38 100755
--- a/src/jdbernard/timestamper/resources/TimeStamperView.properties
+++ b/src/jdbernard/timestamper/resources/TimeStamperView.properties
@@ -4,6 +4,8 @@ exitButton.text=
#NOI18N
exitButton.icon=icons/16-em-cross.png
exitButton.hover.icon=icons/16-em-cross-hover.png
+optionsButton.icon=icons/16-tool-a.png
+optionsButton.hover.icon=icons/16-tool-a-hover.png
taskTextField.text=
#NOI18N
startTimeLabel.foreground=0, 102, 102
@@ -11,11 +13,34 @@ startTimeLabel.text=12:00:00
totalTimeNow.text=3day 2hr 50min 25sec
#NOI18N
totalTimeNow.foreground=0, 153, 0
-jLabel1.text=12:00:00
-#NOI18N
-jLabel1.foreground=204, 0, 0
notesButton.text=jButton1
editNotes.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-em-pencil.png
editNotes.Action.icon=/jdbernard/timestamper/resources/icons/16-em-pencil.png
editNotes.Action.shortDescription=Edit notes for this task
editNotes.Action.text=Notes
+jButton1.text=
+showOptionsMenu.Action.text=Options menu
+showOptionsMenu.Action.shortDescription=Show the application's options menu.
+showOptionsMenu.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-tool-a.png
+showOptionsMenu.Action.icon=/jdbernard/timestamper/resources/icons/16-tool-a.png
+saveTimelineMenuItem.text=Item
+saveTimeline.Action.text=Save Timeline...
+saveTimeline.Action.smallIcon=/jdbernard/timestamper/resources/icons/document-save-16x16.png
+saveTimeline.Action.icon=/jdbernard/timestamper/resources/icons/document-save-16x16.png
+saveTimeline.Action.shortDescription=Save all actions to a timeline file.
+saveTimelineAs.Action.smallIcon=/jdbernard/timestamper/resources/icons/document-save-as-16x16.png
+saveTimelineAs.Action.icon=/jdbernard/timestamper/resources/icons/document-save-as-16x16.png
+saveTimelineAs.Action.shortDescription=Save actions to a new timeline file.
+saveTimelineAs.Action.text=Save Timeline As...
+loadTimelineMenuItem.text=Item
+loadTimeline.Action.text=Load Timeline...
+loadTimeline.Action.shortDescription=Load a set of actions from a timeline file
+loadTimeline.Action.smallIcon=/jdbernard/timestamper/resources/icons/document-open-16x16.png
+loadTimeline.Action.icon=/jdbernard/timestamper/resources/icons/document-open-16x16.png
+currentTimeLabel.text=12:00:00
+#NOI18N
+currentTimeLabel.foreground=204, 0, 0
+exit.Action.text=Exit
+exit.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-em-cross.png
+exit.Action.shortDescription=Close the application.
+exit.Action.icon=/jdbernard/timestamper/resources/icons/16-em-cross.png
diff --git a/src/jdbernard/timestamper/resources/icons/16-tool-a-hover.png b/src/jdbernard/timestamper/resources/icons/16-tool-a-hover.png
new file mode 100755
index 0000000..f602f94
Binary files /dev/null and b/src/jdbernard/timestamper/resources/icons/16-tool-a-hover.png differ
diff --git a/src/jdbernard/timestamper/resources/icons/16-tool-a.png b/src/jdbernard/timestamper/resources/icons/16-tool-a.png
new file mode 100755
index 0000000..dcf0cdf
Binary files /dev/null and b/src/jdbernard/timestamper/resources/icons/16-tool-a.png differ
diff --git a/src/jdbernard/timestamper/resources/icons/document-open-16x16.png b/src/jdbernard/timestamper/resources/icons/document-open-16x16.png
new file mode 100755
index 0000000..69dd8d4
Binary files /dev/null and b/src/jdbernard/timestamper/resources/icons/document-open-16x16.png differ
diff --git a/src/jdbernard/timestamper/resources/icons/document-save-16x16.png b/src/jdbernard/timestamper/resources/icons/document-save-16x16.png
new file mode 100755
index 0000000..22ff495
Binary files /dev/null and b/src/jdbernard/timestamper/resources/icons/document-save-16x16.png differ
diff --git a/src/jdbernard/timestamper/resources/icons/document-save-as-16x16.png b/src/jdbernard/timestamper/resources/icons/document-save-as-16x16.png
new file mode 100755
index 0000000..9bed143
Binary files /dev/null and b/src/jdbernard/timestamper/resources/icons/document-save-as-16x16.png differ
diff --git a/timestamper.config b/timestamper.config
new file mode 100755
index 0000000..e8de75c
--- /dev/null
+++ b/timestamper.config
@@ -0,0 +1,4 @@
+#
+#Fri Aug 29 18:18:08 CDT 2008
+lastUsedTimelineFilename=default-timeline.txt
+lastUsedTimelineFile=default-timeline.txt