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