Restructured the project. Moving to multiple-source timelines
that can automatically sync with one another.
This commit is contained in:
parent
42d2d82c74
commit
89ad2ac447
BIN
doc/feed.pdf
Normal file
BIN
doc/feed.pdf
Normal file
Binary file not shown.
77
doc/feed.rst
Normal file
77
doc/feed.rst
Normal file
@ -0,0 +1,77 @@
|
||||
Centralized vs. decentralized
|
||||
-----------------------------
|
||||
|
||||
Centralized
|
||||
```````````
|
||||
|
||||
- one central list
|
||||
- remote apps that sync with central?
|
||||
|
||||
Decentralized
|
||||
`````````````
|
||||
|
||||
- sync to URL(s)?
|
||||
|
||||
- need a network protocol
|
||||
- HTTP?
|
||||
- SSL?
|
||||
|
||||
- group-wise sync?
|
||||
|
||||
- establish master/slaves?
|
||||
- easier than coordinated group-update:::
|
||||
|
||||
map each URL to synch -> the last time updated.
|
||||
if (update_period):
|
||||
forall URLs: synch
|
||||
else if (incoming_update):
|
||||
forall (URLs older than incoming update): synch
|
||||
|
||||
- synch based on hash of updates?
|
||||
|
||||
- need canonicalizer for text. Use XML?
|
||||
- hash algorithm:::
|
||||
|
||||
SHA-1 of:
|
||||
concatenate:
|
||||
date (YYYYMMDDhhmmssSSS)
|
||||
name
|
||||
notes
|
||||
|
||||
External Feeds
|
||||
--------------
|
||||
|
||||
Item format
|
||||
```````````
|
||||
|
||||
- time started
|
||||
- name/description
|
||||
- notes
|
||||
- category?
|
||||
|
||||
Pull from
|
||||
`````````
|
||||
|
||||
- needs to be optional
|
||||
- standardized input format
|
||||
|
||||
- easy to parse
|
||||
- no errors, false positives
|
||||
- restrictive.
|
||||
|
||||
- flexible input format
|
||||
|
||||
- matches regex's?
|
||||
- map groups to fields
|
||||
|
||||
Push to
|
||||
```````
|
||||
|
||||
- optional
|
||||
- standardized output
|
||||
|
||||
- cannot be flexible to match output medium
|
||||
|
||||
- flexible input format
|
||||
|
||||
- choose fields and format values
|
8
doc/sample-txt-timeline-with-sync-info.txt
Normal file
8
doc/sample-txt-timeline-with-sync-info.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# sync-options:
|
||||
# LOCAL TIMELINE: this file
|
||||
# SYNC TO: ssh://jdbernard@jdbernard.no-ip.org/timelines/jdbernard.timeline.txt
|
||||
# SYNC TO: http://www.twitter.com/jdbernard
|
||||
# pull only
|
||||
# update every 30 sec
|
||||
# SYNC TO: file:///home/jdbernard/timelines/jdbernard.timeline.bak
|
||||
# push only
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
build.xml.data.CRC32=6a978a17
|
||||
build.xml.script.CRC32=6e5ad54e
|
||||
build.xml.stylesheet.CRC32=be360661
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=52850847
|
||||
nbproject/build-impl.xml.script.CRC32=adeac2b5
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=487672f9
|
||||
build.xml.data.CRC32=6a978a17
|
||||
build.xml.script.CRC32=6e5ad54e
|
||||
build.xml.stylesheet.CRC32=be360661
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=618e720f
|
||||
nbproject/build-impl.xml.script.CRC32=70e39602
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45
|
||||
|
@ -1,7 +1,8 @@
|
||||
compile.on.save=false
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
jaxws.endorsed.dir=C:\\Program Files\\NetBeans 6.5\\java2\\modules\\ext\\jaxws21\\api:C:\\Program Files\\NetBeans 6.5\\ide10\\modules\\ext\\jaxb\\api
|
||||
user.properties.file=C:\\Documents and Settings\\jbernard\\.netbeans\\6.5\\build.properties
|
||||
jaxws.endorsed.dir=C:\\Program Files\\NetBeans 6.7.1\\java2\\modules\\ext\\jaxws21\\api:C:\\Program Files\\NetBeans 6.7.1\\ide11\\modules\\ext\\jaxb\\api
|
||||
user.properties.file=C:\\Documents and Settings\\jbernard\\.netbeans\\6.7\\build.properties
|
||||
axis2.deploy.war=C:\\Program Files\\glassfish-v2ur2\\domains\\domain1\\autodeploy\\axis2.war
|
||||
|
@ -1,76 +1,77 @@
|
||||
application.desc=Simple application used to track activities throughout time.
|
||||
application.homepage=
|
||||
application.title=TimeStamper
|
||||
application.vendor=Jonathan Bernard
|
||||
application.version=1.7
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/TimeStamper.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.appframework-1.0.3.jar=lib/appframework-1.0.3.jar
|
||||
file.reference.jcalendar-1.3.2.jar=lib/jcalendar-1.3.2.jar
|
||||
file.reference.swing-worker-1.1.jar=lib/swing-worker-1.1.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${file.reference.appframework-1.0.3.jar}:\
|
||||
${file.reference.swing-worker-1.1.jar}:\
|
||||
${file.reference.jcalendar-1.3.2.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jnlp.codebase.type=local
|
||||
jnlp.codebase.url=file:/C:/Documents%20and%20Settings/jbernard/My%20Documents/Development/TimeStamper/dist/
|
||||
jnlp.enabled=false
|
||||
jnlp.icon=C:\\Documents and Settings\\jbernard\\My Documents\\Development\\TimeStamper\\src\\jdbernard\\timestamper\\resources\\icons\\appointment-new-16x16.png
|
||||
jnlp.offline-allowed=true
|
||||
jnlp.signed=true
|
||||
main.class=jdbernard.timestamper.TimeStamperApp
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
application.desc=Simple application used to track activities throughout time.
|
||||
application.homepage=
|
||||
application.title=TimeStamper
|
||||
application.vendor=Jonathan Bernard
|
||||
application.version=1.7
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/TimeStamper.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.appframework-1.0.3.jar=lib/appframework-1.0.3.jar
|
||||
file.reference.jcalendar-1.3.2.jar=lib/jcalendar-1.3.2.jar
|
||||
file.reference.swing-worker-1.1.jar=lib/swing-worker-1.1.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${file.reference.appframework-1.0.3.jar}:\
|
||||
${file.reference.swing-worker-1.1.jar}:\
|
||||
${file.reference.jcalendar-1.3.2.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.source=1.5
|
||||
javac.target=1.5
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}:\
|
||||
${libs.junit.classpath}:\
|
||||
${libs.junit_4.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jnlp.codebase.type=local
|
||||
jnlp.codebase.url=file:/C:/Documents%20and%20Settings/jbernard/My%20Documents/Development/TimeStamper/dist/
|
||||
jnlp.enabled=false
|
||||
jnlp.icon=C:\\Documents and Settings\\jbernard\\My Documents\\Development\\TimeStamper\\src\\jdbernard\\timestamper\\resources\\icons\\appointment-new-16x16.png
|
||||
jnlp.offline-allowed=true
|
||||
jnlp.signed=true
|
||||
main.class=jdbernard.timestamper.gui.TimeStamperApp
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
platform.active=default_platform
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project
|
||||
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
|
||||
# or test-sys-prop.name=value to set system properties for unit tests):
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=src
|
||||
test.src.dir=test
|
||||
|
@ -1,24 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1">
|
||||
<extension file="jnlp-impl.xml" id="jws">
|
||||
<dependency dependsOn="jnlp" target="jar"/>
|
||||
</extension>
|
||||
</buildExtensions>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>TimeStamper</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
<swingapp xmlns="http://www.netbeans.org/ns/form-swingapp/1">
|
||||
<application-class name="jdbernard.timestamper.TimeStamperApp"/>
|
||||
</swingapp>
|
||||
</configuration>
|
||||
</project>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1">
|
||||
<extension file="jnlp-impl.xml" id="jws">
|
||||
<dependency dependsOn="jnlp" target="jar"/>
|
||||
</extension>
|
||||
</buildExtensions>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>TimeStamper</name>
|
||||
<minimum-ant-version>1.6.5</minimum-ant-version>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots>
|
||||
<root id="test.src.dir"/>
|
||||
</test-roots>
|
||||
</data>
|
||||
<swingapp xmlns="http://www.netbeans.org/ns/form-swingapp/1">
|
||||
<application-class name="jdbernard.timestamper.gui.TimeStamperApp"/>
|
||||
</swingapp>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -1,77 +1,26 @@
|
||||
package jdbernard.timestamper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Scanner;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import jdbernard.timestamper.core.TimelineProperties;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Timeline t = new Timeline();
|
||||
String choice;
|
||||
Scanner in = new Scanner(System.in);
|
||||
System.out.println("Enter config file, terminate with EOF");
|
||||
BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
boolean loop = true;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintWriter pw = new PrintWriter(baos);
|
||||
|
||||
while(loop) {
|
||||
System.out.println("[N]ew Timestamp, [S]ave, [L]oad, [P]rint, [Q]uit: ");
|
||||
choice = in.nextLine();
|
||||
String filename;
|
||||
for(String line = bin.readLine(); line != null && !"EOF".equals(line); line = bin.readLine())
|
||||
pw.println(line);
|
||||
|
||||
switch (choice.toLowerCase().charAt(0)) {
|
||||
case 'n':
|
||||
System.out.println("Enter time (HH:mm:ss) ");
|
||||
Date d = new Date();
|
||||
d.setHours(0);
|
||||
d.setMinutes(0);
|
||||
d.setSeconds(0);
|
||||
d.setTime(d.getTime() + Timeline.shortFormat.parse(in.nextLine()).getTime());
|
||||
pw.flush();
|
||||
pw.close();
|
||||
|
||||
System.out.println("Enter mark ('EOM' to end) ");
|
||||
String line = "";
|
||||
StringBuilder mark = new StringBuilder();
|
||||
line = in.nextLine();
|
||||
while (!line.endsWith("EOM")) {
|
||||
mark.append(line);
|
||||
line = in.nextLine();
|
||||
}
|
||||
mark.append(line.substring(0, line.length() - 3));
|
||||
|
||||
System.out.println("Enter notes ('EON' to end) ");
|
||||
StringBuilder notes = new StringBuilder();
|
||||
line = in.nextLine();
|
||||
while (!line.endsWith("EON")) {
|
||||
notes.append(line);
|
||||
line = in.nextLine();
|
||||
}
|
||||
notes.append(line.substring(0, line.length() - 3));
|
||||
|
||||
t.addMarker(d, mark.toString(), notes.toString());
|
||||
break;
|
||||
|
||||
case 's':
|
||||
System.out.print("Enter filename to save: ");
|
||||
filename = in.nextLine();
|
||||
|
||||
Timeline.writeToFile(filename, t);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
System.out.println("Enter filename to load: ");
|
||||
filename = in.nextLine();
|
||||
|
||||
t = Timeline.readFromFile(filename);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
Timeline.writeToStream(System.out, t);
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
loop = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,281 +0,0 @@
|
||||
package jdbernard.timestamper;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Scanner;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Jonathan Bernard <jdbernard@gmail.com>
|
||||
* A Timeline object represents a series of markers at specific points in time.
|
||||
* The markers have a name or symbol (the 'mark') and notes associated with that
|
||||
* mark.
|
||||
*/
|
||||
public class Timeline implements Iterable<Timeline.TimelineMarker> {
|
||||
|
||||
/**
|
||||
* This represents a marker on the timeline.
|
||||
* The date of the marker and the mark cannot be changed once assigned.
|
||||
*/
|
||||
public class TimelineMarker implements Comparable<TimelineMarker> {
|
||||
private final Date timestamp;
|
||||
private final String mark;
|
||||
private String notes;
|
||||
|
||||
public TimelineMarker(Date timestamp, String mark, String notes) {
|
||||
if (timestamp == null || mark == null)
|
||||
throw new IllegalArgumentException("Null timestamp or mark"
|
||||
+ " is not permitted.");
|
||||
|
||||
this.timestamp = timestamp;
|
||||
this.mark = mark;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public Date getTimestamp() { return timestamp; }
|
||||
|
||||
public String getMark() { return mark; }
|
||||
|
||||
public String getNotes() { return notes; }
|
||||
|
||||
public void setNotes(String notes) { this.notes = notes; }
|
||||
|
||||
@Override
|
||||
public int compareTo(TimelineMarker that) {
|
||||
if (that == null) return Integer.MAX_VALUE;
|
||||
|
||||
return this.timestamp.compareTo(that.timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) return false;
|
||||
if (!(that instanceof TimelineMarker)) return false;
|
||||
|
||||
return this.timestamp.equals(((TimelineMarker)that).timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 53 * hash + (this.timestamp != null ? this.timestamp.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static enum ReadingState {
|
||||
NewMarker,
|
||||
StartMark,
|
||||
ReadMark,
|
||||
StartNotes,
|
||||
ReadNotes,
|
||||
EndMarker
|
||||
};
|
||||
|
||||
public static SimpleDateFormat shortFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
public static SimpleDateFormat longFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
|
||||
|
||||
private static int lineWrap = 78;
|
||||
private TreeSet<TimelineMarker> timelineList;
|
||||
|
||||
public Timeline() {
|
||||
timelineList = new TreeSet<TimelineMarker>();
|
||||
}
|
||||
|
||||
public void addMarker(Date timestamp, String name, String notes) {
|
||||
timelineList.add(new TimelineMarker(timestamp, name, notes));
|
||||
}
|
||||
|
||||
public String getLastName(Date timestamp) {
|
||||
TimelineMarker lastMarker = getLastMarker(timestamp);
|
||||
return (lastMarker == null ?
|
||||
"No previous marker." :
|
||||
lastMarker.getMark());
|
||||
|
||||
}
|
||||
|
||||
public String getLastNotes(Date timestamp) {
|
||||
TimelineMarker lastMarker = getLastMarker(timestamp);
|
||||
return (lastMarker == null ?
|
||||
"No previous marker." :
|
||||
lastMarker.getNotes());
|
||||
}
|
||||
|
||||
public TimelineMarker getLastMarker(Date timestamp) {
|
||||
TimelineMarker lastMarker = null;
|
||||
for (TimelineMarker tm : timelineList) {
|
||||
if (tm.getTimestamp().after(timestamp))
|
||||
break;
|
||||
lastMarker = tm;
|
||||
}
|
||||
|
||||
return lastMarker;
|
||||
}
|
||||
|
||||
public void removeMarker(TimelineMarker marker) {
|
||||
timelineList.remove(marker);
|
||||
}
|
||||
|
||||
public Iterator<TimelineMarker> iterator() {
|
||||
return timelineList.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the a representation of the timeline to a stream. This method
|
||||
* flushes the stream after it finishes writing but does not close the
|
||||
* stream.
|
||||
* @param stream An open stream to write the timeline representation to.
|
||||
* @param timeline The timeline to write.
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public static void writeToStream(OutputStream stream, Timeline timeline)
|
||||
throws IOException {
|
||||
Writer out = new OutputStreamWriter(stream);
|
||||
for (TimelineMarker tm : timeline.timelineList) {
|
||||
|
||||
// write timestamp
|
||||
out.write(longFormat.format(tm.getTimestamp()) + "\n");
|
||||
|
||||
// write mark
|
||||
String mark = tm.getMark().replace('\n', '\u0000');
|
||||
if (mark.length() < lineWrap) out.write(mark + "\n");
|
||||
else {
|
||||
// wrap lines if neccessary
|
||||
int i;
|
||||
for (i = 0; (i + lineWrap) < mark.length(); i+=lineWrap)
|
||||
out.write(mark.substring(i, i+lineWrap) + "\\\n");
|
||||
if (i < mark.length())
|
||||
out.write(mark.substring(i, mark.length()) + "\n");
|
||||
}
|
||||
|
||||
// write notes
|
||||
String notes = tm.getNotes().replace('\n', '\u0000');
|
||||
if (notes.length() < lineWrap) out.write(notes + "\n");
|
||||
else {
|
||||
// wrap lines if neccessary
|
||||
int i;
|
||||
for (i = 0; (i + lineWrap) < notes.length(); i+=lineWrap)
|
||||
out.write(notes.substring(i, i+lineWrap) + "\\\n");
|
||||
if (i < notes.length())
|
||||
out.write(notes.substring(i, notes.length()) + "\n");
|
||||
}
|
||||
out.write("\n");
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a representation of a timeline to a file.
|
||||
* @param filename The path to the destination file.
|
||||
* @param timeline The timeline to write.
|
||||
* @throws java.io.IOException
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static void writeToFile(String filename, Timeline timeline)
|
||||
throws IOException, FileNotFoundException {
|
||||
OutputStream out = new FileOutputStream(filename);
|
||||
writeToStream(out, timeline);
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <b>Timeline</b> instance from a given stream.
|
||||
* @param stream The stream to read from.
|
||||
* @return A new <b>Timeline</b> instance specified by the input stream.
|
||||
* @throws java.io.IOException
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static Timeline readFromStream(InputStream stream)
|
||||
throws IOException, FileNotFoundException {
|
||||
Scanner in = new Scanner(stream);
|
||||
Timeline timeline = new Timeline();
|
||||
|
||||
ReadingState readingState = ReadingState.NewMarker;
|
||||
Date d = null;
|
||||
StringBuilder mark = null;
|
||||
StringBuilder notes = null;
|
||||
String line;
|
||||
int lineNumber = 0;
|
||||
|
||||
while (in.hasNextLine()) {
|
||||
line = in.nextLine();
|
||||
lineNumber++;
|
||||
|
||||
switch (readingState) {
|
||||
|
||||
case NewMarker:
|
||||
try { d = longFormat.parse(line); }
|
||||
catch (ParseException pe) {
|
||||
throw new IOException("Error parsing timeline file at line "
|
||||
+ lineNumber + ": expected a new marker date but could not parse"
|
||||
+ " the date. Error: " + pe.getLocalizedMessage());
|
||||
}
|
||||
readingState = ReadingState.StartMark;
|
||||
break;
|
||||
|
||||
case StartMark:
|
||||
mark = new StringBuilder();
|
||||
// fall through to ReadMark
|
||||
case ReadMark:
|
||||
if (line.endsWith("\\")) {
|
||||
readingState = ReadingState.ReadMark;
|
||||
line = line.substring(0, line.length() - 1);
|
||||
}
|
||||
else readingState = ReadingState.StartNotes;
|
||||
mark.append(line);
|
||||
break;
|
||||
|
||||
case StartNotes:
|
||||
notes = new StringBuilder();
|
||||
// fall through to ReadNotes
|
||||
case ReadNotes:
|
||||
if (line.endsWith("\\")) {
|
||||
readingState = ReadingState.ReadNotes;
|
||||
line = line.substring(0, line.length() - 1);
|
||||
}
|
||||
else readingState = ReadingState.EndMarker;
|
||||
notes.append(line);
|
||||
break;
|
||||
|
||||
case EndMarker:
|
||||
String sMark = mark.toString().replace('\u0000', '\n');
|
||||
String sNotes = notes.toString().replace('\u0000', '\n');
|
||||
timeline.addMarker(d, sMark, sNotes);
|
||||
readingState = ReadingState.NewMarker;
|
||||
}
|
||||
}
|
||||
|
||||
//if (readingState != ReadingState.NewMarker)
|
||||
//TODO: warning of invalid marker file
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Timline instance from a file representation.
|
||||
* @param filename The path of the source file.
|
||||
* @return The new Timeline instance.
|
||||
* @throws java.io.IOException
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static Timeline readFromFile(String filename)
|
||||
throws IOException, FileNotFoundException {
|
||||
InputStream in = new FileInputStream(filename);
|
||||
Timeline t = readFromStream(in);
|
||||
in.close();
|
||||
return t;
|
||||
}
|
||||
}
|
21
src/jdbernard/timestamper/core/AuthenticationException.java
Normal file
21
src/jdbernard/timestamper/core/AuthenticationException.java
Normal file
@ -0,0 +1,21 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class AuthenticationException extends IOException {
|
||||
|
||||
public AuthenticationException() { super(); }
|
||||
|
||||
public AuthenticationException(String message) { super(message); }
|
||||
|
||||
public AuthenticationException(Throwable t) { super(t); }
|
||||
|
||||
public AuthenticationException(String message, Throwable t) {
|
||||
super(message, t);
|
||||
}
|
||||
|
||||
}
|
64
src/jdbernard/timestamper/core/FileTimelineSource.java
Normal file
64
src/jdbernard/timestamper/core/FileTimelineSource.java
Normal file
@ -0,0 +1,64 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class FileTimelineSource extends TimelineSource {
|
||||
|
||||
private File file;
|
||||
|
||||
public FileTimelineSource(URI uri) {
|
||||
super(uri);
|
||||
this.file = new File(uri);
|
||||
}
|
||||
|
||||
/** * {@inheritDoc } */
|
||||
public Timeline read() throws IOException {
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
Timeline t = StreamBasedTimelineSource.readFromStream(fin);
|
||||
fin.close();
|
||||
return t;
|
||||
}
|
||||
|
||||
public Timeline readWithComments(OutputStream commentStream)
|
||||
throws IOException {
|
||||
FileInputStream fin = new FileInputStream(file);
|
||||
Timeline t = StreamBasedTimelineSource.readFromStream(fin, commentStream);
|
||||
fin.close();
|
||||
return t;
|
||||
}
|
||||
|
||||
/** * {@inheritDoc } */
|
||||
public void persist(Timeline t) throws IOException {
|
||||
FileOutputStream fout = new FileOutputStream(file);
|
||||
StreamBasedTimelineSource.writeToStream(fout, t);
|
||||
fout.close();
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
File dir = file.getParentFile();
|
||||
return (dir.canRead() && dir.canWrite());
|
||||
}
|
||||
|
||||
public void authenticate() throws AuthenticationException {
|
||||
File dir = file.getParentFile();
|
||||
if (!dir.canRead())
|
||||
throw new AuthenticationException("This FileTimelineSource does not"
|
||||
+ " have read access to the parent directory for the "
|
||||
+ "given file (" + file.getAbsolutePath() + ".");
|
||||
|
||||
if (!dir.canWrite())
|
||||
throw new AuthenticationException("This FileTimelineSource does not"
|
||||
+ " have write access to the parent directory for the "
|
||||
+ "given file (" + file.getAbsolutePath() + ".");
|
||||
|
||||
}
|
||||
}
|
203
src/jdbernard/timestamper/core/StreamBasedTimelineSource.java
Normal file
203
src/jdbernard/timestamper/core/StreamBasedTimelineSource.java
Normal file
@ -0,0 +1,203 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class StreamBasedTimelineSource extends TimelineSource {
|
||||
|
||||
private static final int lineWrap = 78;
|
||||
|
||||
private static enum ReadingState {
|
||||
NewMarker,
|
||||
StartMark,
|
||||
ReadMark,
|
||||
StartNotes,
|
||||
ReadNotes,
|
||||
EndMarker
|
||||
};
|
||||
|
||||
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private ByteArrayOutputStream comments;
|
||||
|
||||
public StreamBasedTimelineSource(InputStream inStream,
|
||||
OutputStream outStream) {
|
||||
super(null);
|
||||
this.in = inStream;
|
||||
this.out = outStream;
|
||||
this.comments = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
/** {@inheritDoc } */
|
||||
public Timeline read() throws IOException {
|
||||
return readFromStream(in, comments);
|
||||
}
|
||||
|
||||
/** {@inheritDoc } */
|
||||
public void persist(Timeline t) throws IOException {
|
||||
writeToStream(out, t);
|
||||
}
|
||||
|
||||
public void authenticate() throws AuthenticationException { }
|
||||
public boolean isAuthenticated() { return true; }
|
||||
|
||||
/**
|
||||
* Allows a user to extract the comments from the last parsed file.
|
||||
* @return a <code>byte[]</code> representing the portions of the file
|
||||
* which were comments.
|
||||
*/
|
||||
public byte[] getCommentBytes() {
|
||||
return comments.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the a representation of the timeline to a stream. This method
|
||||
* flushes the stream after it finishes writing but does not close the
|
||||
* stream.
|
||||
* @param stream An open stream to write the timeline representation to.
|
||||
* @param timeline The timeline to write.
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public static void writeToStream(OutputStream stream, Timeline timeline)
|
||||
throws IOException {
|
||||
Writer out = new OutputStreamWriter(stream);
|
||||
for (TimelineMarker tm : timeline) {
|
||||
|
||||
// write timestamp
|
||||
out.write(Timeline.longFormat.format(tm.getTimestamp()) + "\n");
|
||||
|
||||
// write mark
|
||||
String mark = tm.getMark().replace('\n', '\u0000');
|
||||
if (mark.length() < lineWrap) out.write(mark + "\n");
|
||||
else {
|
||||
// wrap lines if neccessary
|
||||
int i;
|
||||
for (i = 0; (i + lineWrap) < mark.length(); i+=lineWrap)
|
||||
out.write(mark.substring(i, i+lineWrap) + "\\\n");
|
||||
if (i < mark.length())
|
||||
out.write(mark.substring(i, mark.length()) + "\n");
|
||||
}
|
||||
|
||||
// write notes
|
||||
String notes = tm.getNotes().replace('\n', '\u0000');
|
||||
if (notes.length() < lineWrap) out.write(notes + "\n");
|
||||
else {
|
||||
// wrap lines if neccessary
|
||||
int i;
|
||||
for (i = 0; (i + lineWrap) < notes.length(); i+=lineWrap)
|
||||
out.write(notes.substring(i, i+lineWrap) + "\\\n");
|
||||
if (i < notes.length())
|
||||
out.write(notes.substring(i, notes.length()) + "\n");
|
||||
}
|
||||
out.write("\n");
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a <b>Timeline</b> instance from a given stream.
|
||||
* @param stream The stream to read from.
|
||||
* @return A new <b>Timeline</b> instance specified by the input stream.
|
||||
* @throws java.io.IOException
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static Timeline readFromStream(InputStream stream)
|
||||
throws IOException {
|
||||
return readFromStream(stream, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <b>Timeline</b> instance from a given stream.
|
||||
* @param stream The stream to read from.
|
||||
* @param commentStream A stream to write comments found in the file. This
|
||||
* parameter may be <b>null</b>, in which case comments are ignored.
|
||||
* @return A new <b>Timeline</b> instance specified by the input stream.
|
||||
* @throws java.io.IOException
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static Timeline readFromStream(InputStream stream,
|
||||
OutputStream commentStream) throws IOException {
|
||||
Scanner in = new Scanner(stream);
|
||||
Timeline timeline = new Timeline();
|
||||
PrintWriter commentsWriter = commentStream == null ?
|
||||
null : new PrintWriter(commentStream);
|
||||
|
||||
ReadingState readingState = ReadingState.NewMarker;
|
||||
Date d = null;
|
||||
StringBuilder mark = null;
|
||||
StringBuilder notes = null;
|
||||
String line;
|
||||
int lineNumber = 0;
|
||||
|
||||
while (in.hasNextLine()) {
|
||||
line = in.nextLine();
|
||||
lineNumber++;
|
||||
|
||||
// line is a comment
|
||||
if (line.startsWith("#")) {
|
||||
if (commentsWriter != null) commentsWriter.println(line);
|
||||
continue; // don't parse this line as part of the timeline
|
||||
}
|
||||
|
||||
switch (readingState) {
|
||||
|
||||
case NewMarker:
|
||||
try { d = Timeline.longFormat.parse(line); }
|
||||
catch (ParseException pe) {
|
||||
throw new IOException("Error parsing timeline file at line "
|
||||
+ lineNumber + ": expected a new marker date but could not parse"
|
||||
+ " the date. Error: " + pe.getLocalizedMessage());
|
||||
}
|
||||
readingState = ReadingState.StartMark;
|
||||
break;
|
||||
|
||||
case StartMark:
|
||||
mark = new StringBuilder();
|
||||
// fall through to ReadMark
|
||||
case ReadMark:
|
||||
if (line.endsWith("\\")) {
|
||||
readingState = ReadingState.ReadMark;
|
||||
line = line.substring(0, line.length() - 1);
|
||||
}
|
||||
else readingState = ReadingState.StartNotes;
|
||||
mark.append(line);
|
||||
break;
|
||||
|
||||
case StartNotes:
|
||||
notes = new StringBuilder();
|
||||
// fall through to ReadNotes
|
||||
case ReadNotes:
|
||||
if (line.endsWith("\\")) {
|
||||
readingState = ReadingState.ReadNotes;
|
||||
line = line.substring(0, line.length() - 1);
|
||||
}
|
||||
else readingState = ReadingState.EndMarker;
|
||||
notes.append(line);
|
||||
break;
|
||||
|
||||
case EndMarker:
|
||||
String sMark = mark.toString().replace('\u0000', '\n');
|
||||
String sNotes = notes.toString().replace('\u0000', '\n');
|
||||
timeline.addMarker(d, sMark, sNotes);
|
||||
readingState = ReadingState.NewMarker;
|
||||
}
|
||||
}
|
||||
|
||||
return timeline;
|
||||
}
|
||||
}
|
129
src/jdbernard/timestamper/core/SyncTarget.java
Normal file
129
src/jdbernard/timestamper/core/SyncTarget.java
Normal file
@ -0,0 +1,129 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class SyncTarget {
|
||||
|
||||
protected final TimelineSource source;
|
||||
protected final Timeline localTimeline;
|
||||
protected final String name;
|
||||
|
||||
protected Timer syncTimer;
|
||||
protected SyncTask syncTask;
|
||||
|
||||
protected long syncInterval= 30 * 60 * 1000; // 30 minutes converted to ms
|
||||
protected boolean pushEnabled = true;
|
||||
protected boolean pullEnabled = true;
|
||||
protected boolean syncOnExit = true;
|
||||
|
||||
protected class SyncTask extends TimerTask {
|
||||
@Override public void run() {
|
||||
synchronized(this) {
|
||||
try { SyncTarget.this.sync(); }
|
||||
catch (IOException ioe) { /* TODO */ }
|
||||
}}}
|
||||
|
||||
protected SyncTarget(String name, TimelineSource source,
|
||||
Timeline localTimeline) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
this.localTimeline = localTimeline;
|
||||
|
||||
syncTimer = new Timer(source.toString() + " sync-timer");
|
||||
syncTask = new SyncTask();
|
||||
syncTimer.schedule(syncTask, syncInterval, syncInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync the local timeline with the remote timeline represented by this
|
||||
* SyncTarget object.
|
||||
* @return <b>true</b> if the two timelines were out of sync and have
|
||||
* been put into synch, <b>false</b> if the timelines were already in
|
||||
* sync and no action was requried.
|
||||
* @throws IOException if there is an error communicating with the remote
|
||||
* timeline. This includes AuthenticationException.
|
||||
*/
|
||||
protected boolean sync() throws IOException {
|
||||
assert (pullEnabled || pushEnabled);
|
||||
|
||||
Timeline remoteTimeline;
|
||||
boolean syncPerformed = false;
|
||||
|
||||
// make sure we're authenticated to whatever source we're using
|
||||
if (!SyncTarget.this.source.isAuthenticated()) {
|
||||
SyncTarget.this.source.authenticate();
|
||||
}
|
||||
|
||||
// try to copy the remote timeline locally
|
||||
remoteTimeline = SyncTarget.this.source.read();
|
||||
|
||||
// if we are pulling markers from the remote line
|
||||
if (SyncTarget.this.pullEnabled) {
|
||||
// get all markers in the remote timeline not in the local one
|
||||
Collection<TimelineMarker> diffFromRemote =
|
||||
remoteTimeline.difference(localTimeline);
|
||||
|
||||
if (diffFromRemote.size() != 0) {
|
||||
// add all markers in the remote tline to the local one
|
||||
localTimeline.addAll(diffFromRemote);
|
||||
syncPerformed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we are pushing markers to the remote timeline
|
||||
if (SyncTarget.this.pushEnabled) {
|
||||
// get all markers in the local timeline but not in the remote
|
||||
Collection<TimelineMarker> diffFromLocal =
|
||||
localTimeline.difference(remoteTimeline);
|
||||
|
||||
if (diffFromLocal.size() != 0) {
|
||||
// add the difference to the remote timeline
|
||||
remoteTimeline.addAll(diffFromLocal);
|
||||
syncPerformed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return syncPerformed;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
|
||||
public TimelineSource getSource() { return source; }
|
||||
|
||||
public synchronized void setSyncInterval(long syncInterval) {
|
||||
this.syncInterval= syncInterval;
|
||||
|
||||
syncTask.cancel();
|
||||
syncTask = new SyncTask();
|
||||
|
||||
syncTimer.purge();
|
||||
syncTimer.schedule(syncTask, syncInterval, syncInterval);
|
||||
}
|
||||
|
||||
public long getSyncInterval() { return syncInterval; }
|
||||
|
||||
public synchronized void enablePush(boolean enablePush) {
|
||||
this.pullEnabled = enablePush;
|
||||
}
|
||||
|
||||
public boolean isPushEnabled() { return pushEnabled; }
|
||||
|
||||
public synchronized void enablePull(boolean enablePull) {
|
||||
this.pullEnabled = enablePull;
|
||||
}
|
||||
|
||||
public boolean isPullEnabled() { return pullEnabled; }
|
||||
|
||||
public synchronized void enableSyncOnExit(boolean syncOnExit) {
|
||||
this.syncOnExit = syncOnExit;
|
||||
}
|
||||
|
||||
public boolean isSyncOnExitEnabled() { return syncOnExit; }
|
||||
}
|
95
src/jdbernard/timestamper/core/Timeline.java
Normal file
95
src/jdbernard/timestamper/core/Timeline.java
Normal file
@ -0,0 +1,95 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* @author Jonathan Bernard {@literal <jdbernard@gmail.com>}
|
||||
* A Timeline object represents a series of markers at specific points in time.
|
||||
* The markers have a name or symbol (the 'mark') and notes associated with that
|
||||
* mark.
|
||||
*/
|
||||
public class Timeline implements Iterable<TimelineMarker> {
|
||||
|
||||
public static SimpleDateFormat shortFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
public static SimpleDateFormat longFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
|
||||
private TreeSet<TimelineMarker> timelineList;
|
||||
|
||||
public Timeline() {
|
||||
timelineList = new TreeSet<TimelineMarker>();
|
||||
}
|
||||
|
||||
public void addMarker(Date timestamp, String name, String notes) {
|
||||
timelineList.add(new TimelineMarker(timestamp, name, notes));
|
||||
}
|
||||
|
||||
public String getLastName(Date timestamp) {
|
||||
TimelineMarker lastMarker = getLastMarker(timestamp);
|
||||
return (lastMarker == null ?
|
||||
"No previous marker." :
|
||||
lastMarker.getMark());
|
||||
|
||||
}
|
||||
|
||||
public String getLastNotes(Date timestamp) {
|
||||
TimelineMarker lastMarker = getLastMarker(timestamp);
|
||||
return (lastMarker == null ?
|
||||
"No previous marker." :
|
||||
lastMarker.getNotes());
|
||||
}
|
||||
|
||||
public TimelineMarker getLastMarker(Date timestamp) {
|
||||
TimelineMarker lastMarker = null;
|
||||
for (TimelineMarker tm : timelineList) {
|
||||
if (tm.getTimestamp().after(timestamp))
|
||||
break;
|
||||
lastMarker = tm;
|
||||
}
|
||||
|
||||
return lastMarker;
|
||||
}
|
||||
|
||||
public void removeMarker(TimelineMarker marker) {
|
||||
timelineList.remove(marker);
|
||||
}
|
||||
|
||||
public Iterator<TimelineMarker> iterator() {
|
||||
return timelineList.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the difference of the this timeline relative to another timeline.
|
||||
* More specifically, return the set of all
|
||||
* {@link jdbernard.timestamper.core.TimelineMarker}s that are present in
|
||||
* the <b>this</b> timeline but not present in the given timeline.
|
||||
* timeline.
|
||||
* @param t
|
||||
* @return A collection representing the TimelineMarkers present in
|
||||
* <b>this</b> timeline but not in the given timeline.
|
||||
*/
|
||||
public Collection<TimelineMarker> difference(Timeline t) {
|
||||
TreeSet<TimelineMarker> difference = new TreeSet<TimelineMarker>();
|
||||
|
||||
for (TimelineMarker tm : timelineList) {
|
||||
if (!t.timelineList.contains(tm))
|
||||
difference.add(tm);
|
||||
}
|
||||
|
||||
return difference;
|
||||
}
|
||||
|
||||
public void addAll(Timeline t) {
|
||||
for (TimelineMarker tm : t) {
|
||||
if (!timelineList.contains(tm))
|
||||
timelineList.add(tm);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAll(Collection<TimelineMarker> c) {
|
||||
timelineList.addAll(c);
|
||||
}
|
||||
}
|
63
src/jdbernard/timestamper/core/TimelineMarker.java
Normal file
63
src/jdbernard/timestamper/core/TimelineMarker.java
Normal file
@ -0,0 +1,63 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Jonathan Bernard {@literal <jdbernard@gmail.com>}
|
||||
* This represents a marker on the timeline.
|
||||
* The date of the marker and the mark cannot be changed once assigned.
|
||||
*/
|
||||
public class TimelineMarker implements Comparable<TimelineMarker> {
|
||||
|
||||
private final Date timestamp;
|
||||
private final String mark;
|
||||
private String notes;
|
||||
|
||||
public TimelineMarker(Date timestamp, String mark, String notes) {
|
||||
if (timestamp == null || mark == null)
|
||||
throw new IllegalArgumentException("Null timestamp or mark"
|
||||
+ " is not permitted.");
|
||||
|
||||
this.timestamp = timestamp;
|
||||
this.mark = mark;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public Date getTimestamp() { return timestamp; }
|
||||
|
||||
public String getMark() { return mark; }
|
||||
|
||||
public String getNotes() { return notes; }
|
||||
|
||||
public void setNotes(String notes) { this.notes = notes; }
|
||||
|
||||
@Override
|
||||
public int compareTo(TimelineMarker that) {
|
||||
if (that == null) return Integer.MAX_VALUE;
|
||||
|
||||
int val = this.timestamp.compareTo(that.timestamp);
|
||||
if (val == 0) val = this.mark.compareTo(that.mark);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof TimelineMarker)) return false;
|
||||
|
||||
TimelineMarker that = (TimelineMarker) o;
|
||||
return this.timestamp.equals(that.timestamp) &&
|
||||
this.mark.equals(that.mark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 61 * hash + (this.timestamp != null ? this.timestamp.hashCode() : 0);
|
||||
hash = 61 * hash + (this.mark != null ? this.mark.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Scanner;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
@ -16,145 +20,144 @@ import java.util.StringTokenizer;
|
||||
*/
|
||||
public class TimelineProperties {
|
||||
|
||||
public static final String LOCAL_TIMELINE_URI = "timeline.uri";
|
||||
public static final String REMOTE_TIMELINE_BASE = "remote.timeline.";
|
||||
|
||||
private static final Pattern remoteTimelinePropPattern =
|
||||
Pattern.compile("\\Q" + REMOTE_TIMELINE_BASE + "\\E([^\\s\\.=]+?)[\\.=].*");
|
||||
|
||||
private File propertyFile;
|
||||
private Timeline timeline;
|
||||
private TimelineSource timelineSource;
|
||||
private LinkedList<SyncTarget> syncTargets = new LinkedList<SyncTarget>();
|
||||
|
||||
public TimelineProperties(InputStream in) throws IOException {
|
||||
parseConfig(in);
|
||||
}
|
||||
public TimelineProperties() {
|
||||
this.propertyFile = new File("timeline.default.properties");
|
||||
Properties config = new Properties();
|
||||
|
||||
private static enum ReadingState {
|
||||
LocalTimelineDef, // expecting LOCAL TIMELINE definition
|
||||
NewSync, // expecting a SYNC TO def
|
||||
NewSyncOrOptions // either a NewDef, or a block of options
|
||||
}
|
||||
File timelineFile = new File("timeline.default.txt");
|
||||
URI timelineURI = timelineFile.toURI();
|
||||
|
||||
private void parseConfig(InputStream is) throws IOException {
|
||||
Scanner in = new Scanner(is);
|
||||
URI sourceURI;
|
||||
|
||||
// read the information for the local timeline
|
||||
if (!nextExtendedToken(in, "LOCAL TIMELINE:")) {
|
||||
throw new IOException("Missing 'LOCAL TIMELINE:' definition."
|
||||
+ " This must be the first line of the options file.");
|
||||
timeline = new Timeline();
|
||||
timelineSource = TimelineSourceFactory.newInstance(timelineURI);
|
||||
try { timelineSource.persist(timeline); }
|
||||
catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// parse the source URI
|
||||
timelineSource = parseSource(in);
|
||||
config.setProperty(LOCAL_TIMELINE_URI, timelineURI.toString());
|
||||
|
||||
// load timeline from source
|
||||
timeline = timelineSource.read(); // TODO: authentication
|
||||
|
||||
// add as many Syncs as we find
|
||||
for (SyncTarget st = parseSync(in); st != null; st = parseSync(in))
|
||||
syncTargets.add(st);
|
||||
}
|
||||
|
||||
private SyncTarget parseSync(Scanner in) throws IOException {
|
||||
SyncTarget st;
|
||||
String token;
|
||||
|
||||
if (!nextExtendedToken(in, "SYNC WITH:")) { return null; }
|
||||
|
||||
st = new SyncTarget(parseSource(in), timeline);
|
||||
|
||||
while (true) {
|
||||
if (nextExtendedToken(in, "PULL ONLY")) {
|
||||
st.enablePull(true);
|
||||
st.enablePush(false);
|
||||
}
|
||||
|
||||
else if (nextExtendedToken(in, "PUSH ONLY")) {
|
||||
st.enablePull(false);
|
||||
st.enablePush(true);
|
||||
}
|
||||
|
||||
else if (nextExtendedToken(in, "PUSH AND PULL") ||
|
||||
nextExtendedToken(in, "PULL AND PUSH")) {
|
||||
st.enablePull(true);
|
||||
st.enablePush(true);
|
||||
}
|
||||
|
||||
else if (nextExtendedToken(in, "SYNC ON EXIT")) {
|
||||
st.enableSyncOnExit(true);
|
||||
}
|
||||
|
||||
else if (nextExtendedToken(in, "UPDATE EVERY")) {
|
||||
long updateAmount = 1;
|
||||
|
||||
// parse the time amount if present
|
||||
token = in.next("\\d+");
|
||||
if (token != null) { updateAmount = Long.parseLong(token); }
|
||||
|
||||
token = in.next();
|
||||
if ("seconds".startsWith(token.toLowerCase()))
|
||||
updateAmount *= 1000;
|
||||
else if ("minutes".startsWith(token.toLowerCase()))
|
||||
updateAmount *= 1000 * 60;
|
||||
else if ("hours".startsWith(token.toLowerCase()))
|
||||
updateAmount *= 1000 * 60 * 60;
|
||||
else if ("days".startsWith(token.toLowerCase()))
|
||||
updateAmount *= 1000 * 60 * 60 * 24;
|
||||
else if ("weeks".startsWith(token.toLowerCase()))
|
||||
updateAmount *= 1000 * 60 * 60 * 24 * 7;
|
||||
else throw new IOException("'" + token + "' is not a supported"
|
||||
+ " measure of time. The supported measures are "
|
||||
+ "'seconds', 'minutes', 'hours', 'days', and 'weeks'.");
|
||||
}
|
||||
|
||||
else return st;
|
||||
try { config.store(new FileOutputStream(propertyFile), ""); }
|
||||
catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
private TimelineSource parseSource(Scanner in) throws IOException {
|
||||
public TimelineProperties(File propertyFile) throws IOException {
|
||||
String strURI;
|
||||
URI sourceURI;
|
||||
URI timelineURI;
|
||||
|
||||
if (!in.hasNext()) {
|
||||
throw new IOException("Expected the URI of a timeline source, but "
|
||||
+ "ran out of input.");
|
||||
this.propertyFile = propertyFile;
|
||||
Properties config = new Properties();
|
||||
try {
|
||||
config.load(new InputStreamReader(new FileInputStream(propertyFile)));
|
||||
} catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
strURI = in.next();
|
||||
try { sourceURI = new URI(strURI); }
|
||||
catch (URISyntaxException urise) {
|
||||
throw new IOException("The source link '" + strURI + "' is not a"
|
||||
+ " valid URI.", urise);
|
||||
}
|
||||
|
||||
return TimelineSourceFactory.newInstance(sourceURI);
|
||||
}
|
||||
|
||||
private static boolean nextExtendedToken(Scanner in, String expectedToken)
|
||||
throws IOException {
|
||||
StringTokenizer st = new StringTokenizer(expectedToken);
|
||||
|
||||
if (st.countTokens() < 1 || !in.hasNext()) { return false; }
|
||||
|
||||
// read one token
|
||||
String curToken = st.nextToken();
|
||||
String inToken = in.next("(?i)\\Q" + curToken + "\\E");
|
||||
if (inToken == null) return false;
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
curToken = st.nextToken();
|
||||
if (!in.hasNext()) {
|
||||
throw new IOException("Ran out of input while expecting '"
|
||||
+ curToken + "' from '" + expectedToken + "'.");
|
||||
}
|
||||
|
||||
inToken = in.next("(?i)\\Q" + curToken + "\\E");
|
||||
if (inToken == null) {
|
||||
throw new IOException("Found '" + in.next() + "' but expected '"
|
||||
+ curToken + "' from '" + expectedToken + "'.");
|
||||
// load local timeline
|
||||
strURI = config.getProperty(LOCAL_TIMELINE_URI, "");
|
||||
if ("".equals(strURI)) {
|
||||
timelineURI = new File("timeline.default.txt").toURI();
|
||||
} else {
|
||||
try { timelineURI = new URI(strURI); }
|
||||
catch (URISyntaxException urise) {
|
||||
throw new IOException("Unable to load the timeline: the timeline "
|
||||
+ "URI is invalid.", urise);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
timelineSource = TimelineSourceFactory.newInstance(timelineURI);
|
||||
timeline = timelineSource.read();
|
||||
|
||||
// search keys for remote timeline entries
|
||||
for (Object keyObj : config.keySet()) {
|
||||
if (!(keyObj instanceof String)) continue;
|
||||
|
||||
String key = (String) keyObj;
|
||||
String stName;
|
||||
String remoteBase;
|
||||
SyncTarget st;
|
||||
|
||||
Matcher m = remoteTimelinePropPattern.matcher(key);
|
||||
if (!m.matches()) continue;
|
||||
|
||||
stName = m.group(1);
|
||||
remoteBase = REMOTE_TIMELINE_BASE + stName;
|
||||
|
||||
strURI = config.getProperty(remoteBase + ".uri", "");
|
||||
try { timelineURI = new URI(strURI); }
|
||||
catch (URISyntaxException urise) { /* TODO */ }
|
||||
|
||||
// add a new SyncTarget to the list
|
||||
st = new SyncTarget(stName, TimelineSourceFactory
|
||||
.newInstance(timelineURI), timeline);
|
||||
syncTargets.add(st);
|
||||
|
||||
// check for synch options
|
||||
st.enablePull(Boolean.parseBoolean(
|
||||
config.getProperty(remoteBase + ".pull", "true")));
|
||||
st.enablePush(Boolean.parseBoolean(
|
||||
config.getProperty(remoteBase + ".push", "true")));
|
||||
st.enableSyncOnExit(Boolean.parseBoolean(
|
||||
config.getProperty(remoteBase + ".sync-on-exit", "true")));
|
||||
st.setSyncInterval(Long.parseLong(
|
||||
config.getProperty(remoteBase + ".update-interval",
|
||||
"1800000"))); // thirty minutes
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToStream(OutputStream out) throws IOException {
|
||||
public void save() throws IOException {
|
||||
Properties config = new Properties();
|
||||
timelineSource.persist(timeline);
|
||||
|
||||
config.setProperty(LOCAL_TIMELINE_URI,
|
||||
timelineSource.getURI().toString());
|
||||
|
||||
for (SyncTarget st : syncTargets) {
|
||||
String remoteBase = REMOTE_TIMELINE_BASE + st.getName();
|
||||
config.setProperty(remoteBase + ".uri",
|
||||
st.getSource().getURI().toString());
|
||||
config.setProperty(remoteBase + ".pull",
|
||||
Boolean.toString(st.isPullEnabled()));
|
||||
config.setProperty(remoteBase + ".push",
|
||||
Boolean.toString(st.isPushEnabled()));
|
||||
config.setProperty(remoteBase + ".sync-on-exit",
|
||||
Boolean.toString(st.isSyncOnExitEnabled()));
|
||||
config.setProperty(remoteBase + ".update-interval",
|
||||
Long.toString(st.getSyncInterval()));
|
||||
}
|
||||
|
||||
try {
|
||||
config.store(new FileOutputStream(propertyFile), "");
|
||||
} catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
public void save(File newFile) throws IOException {
|
||||
propertyFile = newFile;
|
||||
save();
|
||||
}
|
||||
|
||||
public Timeline getTimeline() { return timeline; }
|
||||
|
||||
public void setTimelineSource(TimelineSource newSource) {
|
||||
this.timelineSource = newSource;
|
||||
}
|
||||
|
||||
public TimelineSource getTimelineSource() { return timelineSource; }
|
||||
|
||||
public Collection<SyncTarget> getSyncTargets() { return syncTargets; }
|
||||
}
|
||||
|
25
src/jdbernard/timestamper/core/TimelineSource.java
Normal file
25
src/jdbernard/timestamper/core/TimelineSource.java
Normal file
@ -0,0 +1,25 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public abstract class TimelineSource {
|
||||
|
||||
protected final URI uri;
|
||||
|
||||
public TimelineSource(URI uri) { this.uri = uri; }
|
||||
|
||||
public abstract Timeline read() throws IOException;
|
||||
public abstract void persist(Timeline t) throws IOException;
|
||||
public abstract boolean isAuthenticated();
|
||||
public abstract void authenticate() throws AuthenticationException;
|
||||
|
||||
public URI getURI() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
38
src/jdbernard/timestamper/core/TimelineSourceFactory.java
Normal file
38
src/jdbernard/timestamper/core/TimelineSourceFactory.java
Normal file
@ -0,0 +1,38 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class TimelineSourceFactory {
|
||||
|
||||
public static TimelineSource newInstance(URI uri) {
|
||||
// File based
|
||||
if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
return new FileTimelineSource(uri);
|
||||
}
|
||||
|
||||
// Twitter
|
||||
else if ("http".equalsIgnoreCase(uri.getScheme()) &&
|
||||
("twitter.com".equalsIgnoreCase(uri.getHost())
|
||||
|| "www.twitter.com".equalsIgnoreCase(uri.getHost()))) {
|
||||
throw new UnsupportedOperationException("Twitter based timeline "
|
||||
+ "sources are not yet supported.");
|
||||
}
|
||||
|
||||
// SSH
|
||||
else if ("ssh".equalsIgnoreCase(uri.getScheme())) {
|
||||
throw new UnsupportedOperationException("SSH based timeline sources"
|
||||
+ " are not yet supported.");
|
||||
}
|
||||
|
||||
// unknown
|
||||
else {
|
||||
throw new UnsupportedOperationException("Timeline sources for the"
|
||||
+ " " + uri.getScheme() + " are not currently supported.");
|
||||
}
|
||||
}
|
||||
}
|
34
src/jdbernard/timestamper/core/TwitterTimelineSource.java
Normal file
34
src/jdbernard/timestamper/core/TwitterTimelineSource.java
Normal file
@ -0,0 +1,34 @@
|
||||
package jdbernard.timestamper.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jonathan Bernard ({@literal jonathan.bernard@gemalto.com})
|
||||
*/
|
||||
public class TwitterTimelineSource extends TimelineSource {
|
||||
|
||||
private String username;
|
||||
private char[] password;
|
||||
|
||||
public TwitterTimelineSource(URI uri) {
|
||||
super(uri);
|
||||
}
|
||||
|
||||
public Timeline read() throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void persist(Timeline t) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void authenticate() throws AuthenticationException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
}
|
1
src/jdbernard/timestamper/AboutDialog.form → src/jdbernard/timestamper/gui/AboutDialog.form
Executable file → Normal file
1
src/jdbernard/timestamper/AboutDialog.form → src/jdbernard/timestamper/gui/AboutDialog.form
Executable file → Normal file
@ -12,6 +12,7 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
4
src/jdbernard/timestamper/AboutDialog.java → src/jdbernard/timestamper/gui/AboutDialog.java
Executable file → Normal file
4
src/jdbernard/timestamper/AboutDialog.java → src/jdbernard/timestamper/gui/AboutDialog.java
Executable file → Normal file
@ -4,7 +4,7 @@
|
||||
* Created on October 19, 2008, 3:14 PM
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.awt.Point;
|
||||
@ -56,7 +56,7 @@ public class AboutDialog extends JDialog implements MouseMotionListener {
|
||||
});
|
||||
aboutPanel.addMouseMotionListener(this);
|
||||
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getResourceMap(AboutDialog.class);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getResourceMap(AboutDialog.class);
|
||||
iconLabel.setIcon(resourceMap.getIcon("iconLabel.icon")); // NOI18N
|
||||
iconLabel.setText(resourceMap.getString("iconLabel.text")); // NOI18N
|
||||
iconLabel.setName("iconLabel"); // NOI18N
|
1
src/jdbernard/timestamper/NotesDialog.form → src/jdbernard/timestamper/gui/NotesDialog.form
Executable file → Normal file
1
src/jdbernard/timestamper/NotesDialog.form → src/jdbernard/timestamper/gui/NotesDialog.form
Executable file → Normal file
@ -12,6 +12,7 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
4
src/jdbernard/timestamper/NotesDialog.java → src/jdbernard/timestamper/gui/NotesDialog.java
Executable file → Normal file
4
src/jdbernard/timestamper/NotesDialog.java → src/jdbernard/timestamper/gui/NotesDialog.java
Executable file → Normal file
@ -4,7 +4,7 @@
|
||||
* Created on September 3, 2008, 4:53 PM
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
@ -61,7 +61,7 @@ public class NotesDialog extends JDialog implements MouseMotionListener {
|
||||
setUndecorated(true);
|
||||
|
||||
mainPanel.setBorder(javax.swing.BorderFactory.createMatteBorder(2, 2, 2, 2, new java.awt.Color(0, 0, 0)));
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getResourceMap(NotesDialog.class);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getResourceMap(NotesDialog.class);
|
||||
mainPanel.setToolTipText(resourceMap.getString("mainPanel.toolTipText")); // NOI18N
|
||||
mainPanel.setName("mainPanel"); // NOI18N
|
||||
mainPanel.addMouseListener(new java.awt.event.MouseAdapter() {
|
39
src/jdbernard/timestamper/PunchcardDisplayDialog.form → src/jdbernard/timestamper/gui/PunchcardDisplayDialog.form
Executable file → Normal file
39
src/jdbernard/timestamper/PunchcardDisplayDialog.form → src/jdbernard/timestamper/gui/PunchcardDisplayDialog.form
Executable file → Normal file
@ -1,6 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Container class="jdbernard.timestamper.gui.TimelineDayDisplay" name="dayDisplay">
|
||||
<Properties>
|
||||
<Property name="name" type="java.lang.String" value="dayDisplay" noResource="true"/>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="100" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="100" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
</Container>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="name" type="java.lang.String" value="Form" noResource="true"/>
|
||||
@ -12,6 +32,7 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
@ -48,6 +69,8 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_ListenersCodePost" type="java.lang.String" value="mainPanel.addMouseMotionListener(this);"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="detailPanel">
|
||||
<Properties>
|
||||
@ -179,7 +202,7 @@
|
||||
<Component class="javax.swing.JButton" name="prevWeekButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="previousWeek" methodName="previousWeek"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="previousWeek" methodName="previousWeek"/>
|
||||
</Property>
|
||||
<Property name="hideActionText" type="boolean" value="true"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
@ -196,7 +219,7 @@
|
||||
<Component class="javax.swing.JButton" name="prevDayButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="previousDay" methodName="previousDay"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="previousDay" methodName="previousDay"/>
|
||||
</Property>
|
||||
<Property name="hideActionText" type="boolean" value="true"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
@ -213,7 +236,7 @@
|
||||
<Component class="javax.swing.JButton" name="currentDayButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="currentDay" methodName="currentDay"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="currentDay" methodName="currentDay"/>
|
||||
</Property>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
<Insets value="[0, 2, 0, 2]"/>
|
||||
@ -229,7 +252,7 @@
|
||||
<Component class="javax.swing.JButton" name="nextDayButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="nextDay" methodName="nextDay"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="nextDay" methodName="nextDay"/>
|
||||
</Property>
|
||||
<Property name="hideActionText" type="boolean" value="true"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
@ -246,7 +269,7 @@
|
||||
<Component class="javax.swing.JButton" name="nextWeekButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="nextWeek" methodName="nextWeek"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="nextWeek" methodName="nextWeek"/>
|
||||
</Property>
|
||||
<Property name="hideActionText" type="boolean" value="true"/>
|
||||
<Property name="margin" type="java.awt.Insets" editor="org.netbeans.beaninfo.editors.InsetsEditor">
|
||||
@ -265,7 +288,7 @@
|
||||
<Component class="javax.swing.JButton" name="newMarkerButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="newMarker" methodName="newMarker"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="newMarker" methodName="newMarker"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="newMarkerButton" noResource="true"/>
|
||||
</Properties>
|
||||
@ -278,7 +301,7 @@
|
||||
<Component class="javax.swing.JButton" name="deleteMarkerButton">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="deleteMarker" methodName="deleteMarker"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="deleteMarker" methodName="deleteMarker"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="deleteMarkerButton" noResource="true"/>
|
||||
</Properties>
|
||||
@ -291,7 +314,7 @@
|
||||
<Component class="javax.swing.JButton" name="saveMarkerChanges">
|
||||
<Properties>
|
||||
<Property name="action" type="javax.swing.Action" editor="org.netbeans.modules.swingapp.ActionEditor">
|
||||
<action class="jdbernard.timestamper.PunchcardDisplayDialog" id="saveMarkerChanges" methodName="saveMarkerChanges"/>
|
||||
<action class="jdbernard.timestamper.gui.PunchcardDisplayDialog" id="saveMarkerChanges" methodName="saveMarkerChanges"/>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="saveMarkerChanges" noResource="true"/>
|
||||
</Properties>
|
61
src/jdbernard/timestamper/PunchcardDisplayDialog.java → src/jdbernard/timestamper/gui/PunchcardDisplayDialog.java
Executable file → Normal file
61
src/jdbernard/timestamper/PunchcardDisplayDialog.java → src/jdbernard/timestamper/gui/PunchcardDisplayDialog.java
Executable file → Normal file
@ -4,8 +4,9 @@
|
||||
* Created on October 16, 2008, 4:37 PM
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import jdbernard.timestamper.core.TimelineMarker;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
@ -64,8 +65,8 @@ implements MouseMotionListener, ChangeListener {
|
||||
private void initComponents() {
|
||||
java.awt.GridBagConstraints gridBagConstraints;
|
||||
|
||||
dayDisplay = new jdbernard.timestamper.gui.TimelineDayDisplay();
|
||||
mainPanel = new javax.swing.JPanel();
|
||||
dayDisplay = new jdbernard.timestamper.TimelineDayDisplay();
|
||||
detailPanel = new javax.swing.JPanel();
|
||||
textPane = new javax.swing.JPanel();
|
||||
markTextField = new javax.swing.JTextField();
|
||||
@ -84,6 +85,19 @@ implements MouseMotionListener, ChangeListener {
|
||||
deleteMarkerButton = new javax.swing.JButton();
|
||||
saveMarkerChanges = new javax.swing.JButton();
|
||||
|
||||
dayDisplay.setName("dayDisplay"); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout dayDisplayLayout = new javax.swing.GroupLayout(dayDisplay);
|
||||
dayDisplay.setLayout(dayDisplayLayout);
|
||||
dayDisplayLayout.setHorizontalGroup(
|
||||
dayDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 100, Short.MAX_VALUE)
|
||||
);
|
||||
dayDisplayLayout.setVerticalGroup(
|
||||
dayDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 100, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
setName("Form"); // NOI18N
|
||||
setUndecorated(true);
|
||||
@ -97,26 +111,12 @@ implements MouseMotionListener, ChangeListener {
|
||||
});
|
||||
mainPanel.addMouseMotionListener(this);
|
||||
|
||||
dayDisplay.setName("dayDisplay"); // NOI18N
|
||||
dayDisplay.setPreferredSize(new java.awt.Dimension(100, 100));
|
||||
|
||||
javax.swing.GroupLayout dayDisplayLayout = new javax.swing.GroupLayout(dayDisplay);
|
||||
dayDisplay.setLayout(dayDisplayLayout);
|
||||
dayDisplayLayout.setHorizontalGroup(
|
||||
dayDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 405, Short.MAX_VALUE)
|
||||
);
|
||||
dayDisplayLayout.setVerticalGroup(
|
||||
dayDisplayLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGap(0, 339, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
detailPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
|
||||
detailPanel.setName("detailPanel"); // NOI18N
|
||||
|
||||
textPane.setName("textPane"); // NOI18N
|
||||
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getResourceMap(PunchcardDisplayDialog.class);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getResourceMap(PunchcardDisplayDialog.class);
|
||||
markTextField.setText(resourceMap.getString("markTextField.text")); // NOI18N
|
||||
markTextField.setName("markTextField"); // NOI18N
|
||||
|
||||
@ -175,7 +175,7 @@ implements MouseMotionListener, ChangeListener {
|
||||
gridBagConstraints.weightx = 1.0;
|
||||
datePanel.add(dateLabel, gridBagConstraints);
|
||||
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getActionMap(PunchcardDisplayDialog.class, this);
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getActionMap(PunchcardDisplayDialog.class, this);
|
||||
prevWeekButton.setAction(actionMap.get("previousWeek")); // NOI18N
|
||||
prevWeekButton.setHideActionText(true);
|
||||
prevWeekButton.setMargin(new java.awt.Insets(0, 2, 0, 2));
|
||||
@ -270,26 +270,7 @@ implements MouseMotionListener, ChangeListener {
|
||||
.addComponent(textPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
|
||||
mainPanel.setLayout(mainPanelLayout);
|
||||
mainPanelLayout.setHorizontalGroup(
|
||||
mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(dayDisplay, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 405, Short.MAX_VALUE)
|
||||
.addComponent(detailPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
);
|
||||
mainPanelLayout.setVerticalGroup(
|
||||
mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addComponent(dayDisplay, javax.swing.GroupLayout.DEFAULT_SIZE, 339, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(detailPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
mainPanel.add(detailPanel);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
@ -315,7 +296,7 @@ private void mainPanelMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:e
|
||||
private javax.swing.JButton currentDayButton;
|
||||
private javax.swing.JLabel dateLabel;
|
||||
private javax.swing.JPanel datePanel;
|
||||
private jdbernard.timestamper.TimelineDayDisplay dayDisplay;
|
||||
private jdbernard.timestamper.gui.TimelineDayDisplay dayDisplay;
|
||||
private javax.swing.JButton deleteMarkerButton;
|
||||
private javax.swing.JPanel detailPanel;
|
||||
private javax.swing.JPanel mainPanel;
|
||||
@ -418,7 +399,7 @@ private void mainPanelMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:e
|
||||
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if (e.getSource() == dayDisplay) {
|
||||
Timeline.TimelineMarker marker = dayDisplay.getSelectedTimelineMarker();
|
||||
TimelineMarker marker = dayDisplay.getSelectedTimelineMarker();
|
||||
|
||||
if (marker == null) {
|
||||
timestampDateChooser.setDate(null);
|
1
src/jdbernard/timestamper/TimeStamperAboutBox.form → src/jdbernard/timestamper/gui/TimeStamperAboutBox.form
Executable file → Normal file
1
src/jdbernard/timestamper/TimeStamperAboutBox.form → src/jdbernard/timestamper/gui/TimeStamperAboutBox.form
Executable file → Normal file
@ -14,6 +14,7 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
6
src/jdbernard/timestamper/TimeStamperAboutBox.java → src/jdbernard/timestamper/gui/TimeStamperAboutBox.java
Executable file → Normal file
6
src/jdbernard/timestamper/TimeStamperAboutBox.java → src/jdbernard/timestamper/gui/TimeStamperAboutBox.java
Executable file → Normal file
@ -2,7 +2,7 @@
|
||||
* TimeStamperAboutBox.java
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import org.jdesktop.application.Action;
|
||||
|
||||
@ -37,13 +37,13 @@ public class TimeStamperAboutBox extends javax.swing.JDialog {
|
||||
javax.swing.JLabel appDescLabel = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getResourceMap(TimeStamperAboutBox.class);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getResourceMap(TimeStamperAboutBox.class);
|
||||
setTitle(resourceMap.getString("title")); // NOI18N
|
||||
setModal(true);
|
||||
setName("aboutBox"); // NOI18N
|
||||
setResizable(false);
|
||||
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getActionMap(TimeStamperAboutBox.class, this);
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getActionMap(TimeStamperAboutBox.class, this);
|
||||
closeButton.setAction(actionMap.get("closeAboutBox")); // NOI18N
|
||||
closeButton.setName("closeButton"); // NOI18N
|
||||
|
77
src/jdbernard/timestamper/TimeStamperApp.java → src/jdbernard/timestamper/gui/TimeStamperApp.java
Executable file → Normal file
77
src/jdbernard/timestamper/TimeStamperApp.java → src/jdbernard/timestamper/gui/TimeStamperApp.java
Executable file → Normal file
@ -2,7 +2,7 @@
|
||||
* TimeStamperApp.java
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -16,6 +16,7 @@ import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import jdbernard.timestamper.core.TimelineProperties;
|
||||
import org.jdesktop.application.Application;
|
||||
import org.jdesktop.application.SingleFrameApplication;
|
||||
|
||||
@ -25,16 +26,14 @@ import org.jdesktop.application.SingleFrameApplication;
|
||||
public class TimeStamperApp extends SingleFrameApplication
|
||||
implements Application.ExitListener {
|
||||
|
||||
private Timeline activeTimeline;
|
||||
private String currentTimelineFile;
|
||||
private TimelineProperties timelineProperties;
|
||||
private Logger log;
|
||||
private Properties config;
|
||||
|
||||
public TimeStamperApp() {
|
||||
super();
|
||||
|
||||
// set defaults for fields
|
||||
activeTimeline = new Timeline();
|
||||
timelineProperties = new TimelineProperties();
|
||||
|
||||
// set up logger
|
||||
log = Logger.getLogger("jdbernard.timestamper");
|
||||
@ -71,25 +70,14 @@ implements Application.ExitListener {
|
||||
}
|
||||
|
||||
// load the last used timeline
|
||||
loadTimeline(config.getProperty("lastUsedTimelineFilename"));
|
||||
// TODO: fix
|
||||
loadTimelineProperties(config.getProperty("lastUsedTimelineProperties", "timeline.default.properties"));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override protected void initialize(String[] args) {
|
||||
if (args.length > 0) {
|
||||
File inFile = new File(args[0]);
|
||||
if (!inFile.exists())
|
||||
try { inFile.createNewFile(); }
|
||||
catch (IOException ioe) {
|
||||
log.warning("No file '" + args[0] + " exists and an error"
|
||||
+ " occurred trying to create it.");
|
||||
}
|
||||
|
||||
currentTimelineFile = args[0];
|
||||
loadTimeline(currentTimelineFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,48 +112,45 @@ implements Application.ExitListener {
|
||||
launch(TimeStamperApp.class, args);
|
||||
}
|
||||
|
||||
public void saveTimeline() {
|
||||
saveTimelineToFile(currentTimelineFile);
|
||||
public TimelineProperties getTimelineProperties() {
|
||||
return timelineProperties;
|
||||
}
|
||||
|
||||
public void saveTimelineToFile(String filename) {
|
||||
if (filename == null || filename.equals(""))
|
||||
filename = "default-timeline.txt";
|
||||
|
||||
public void saveTimelineProperties() {
|
||||
try {
|
||||
Timeline.writeToFile(filename, activeTimeline);
|
||||
currentTimelineFile = filename;
|
||||
timelineProperties.save();
|
||||
} catch (IOException ioe) {
|
||||
log.warning("Could not save timeline file: "
|
||||
+ ioe.getLocalizedMessage());
|
||||
log.warning("Could not save the timeline to <"
|
||||
+ timelineProperties.getTimelineSource().getURI().toString()
|
||||
+ ">:" + ioe.getLocalizedMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void saveTimelinePropertiesAs(File propertyFile) {
|
||||
try { timelineProperties.save(propertyFile); }
|
||||
catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
public void loadTimeline(String filename) {
|
||||
|
||||
if (filename == null || filename.equals("")) {
|
||||
activeTimeline = new Timeline();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
activeTimeline = Timeline.readFromFile(filename);
|
||||
currentTimelineFile = filename;
|
||||
} catch (IOException ioe) {
|
||||
log.warning("Could not load from the file: " +
|
||||
ioe.getLocalizedMessage());
|
||||
}
|
||||
public void loadTimelineProperties(String filename) {
|
||||
loadTimelineProperties(new File(filename));
|
||||
}
|
||||
|
||||
public Timeline getActiveTimeline() {
|
||||
return activeTimeline;
|
||||
public void loadTimelineProperties(File propertyFile) {
|
||||
try { timelineProperties = new TimelineProperties(propertyFile); }
|
||||
catch (IOException ioe) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void willExit(EventObject e) {
|
||||
saveTimeline();
|
||||
saveTimelineProperties();
|
||||
|
||||
config.setProperty("lastUsedTimelineFilename", currentTimelineFile);
|
||||
config.setProperty("lastUsedTimelineProperties",
|
||||
timelineProperties.getTimelineSource().getURI().toString());
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream("timestamper.config");
|
||||
config.store(out, "");
|
1
src/jdbernard/timestamper/TimeStamperView.form → src/jdbernard/timestamper/gui/TimeStamperView.form
Executable file → Normal file
1
src/jdbernard/timestamper/TimeStamperView.form → src/jdbernard/timestamper/gui/TimeStamperView.form
Executable file → Normal file
@ -267,6 +267,7 @@
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
31
src/jdbernard/timestamper/TimeStamperView.java → src/jdbernard/timestamper/gui/TimeStamperView.java
Executable file → Normal file
31
src/jdbernard/timestamper/TimeStamperView.java → src/jdbernard/timestamper/gui/TimeStamperView.java
Executable file → Normal file
@ -2,8 +2,10 @@
|
||||
* TimeStamperView.java
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import jdbernard.timestamper.core.TimelineMarker;
|
||||
import jdbernard.timestamper.core.Timeline;
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
@ -16,7 +18,6 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
@ -24,7 +25,6 @@ import org.jdesktop.application.Action;
|
||||
import org.jdesktop.application.ResourceMap;
|
||||
import org.jdesktop.application.SingleFrameApplication;
|
||||
import org.jdesktop.application.FrameView;
|
||||
import sun.security.jca.GetInstance;
|
||||
|
||||
/**
|
||||
* The application's main frame.
|
||||
@ -129,11 +129,11 @@ ChangeListener {
|
||||
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);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getResourceMap(TimeStamperView.class);
|
||||
currentTaskLabel.setText(resourceMap.getString("currentTaskLabel.text")); // NOI18N
|
||||
currentTaskLabel.setName("currentTaskLabel"); // NOI18N
|
||||
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.TimeStamperApp.class).getContext().getActionMap(TimeStamperView.class, this);
|
||||
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(jdbernard.timestamper.gui.TimeStamperApp.class).getContext().getActionMap(TimeStamperView.class, this);
|
||||
exitButton.setAction(actionMap.get("quit")); // NOI18N
|
||||
exitButton.setBorder(null);
|
||||
exitButton.setContentAreaFilled(false);
|
||||
@ -269,7 +269,8 @@ ChangeListener {
|
||||
|
||||
private void taskTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_taskTextFieldKeyReleased
|
||||
if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
|
||||
Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
|
||||
Timeline t = ((TimeStamperApp) getApplication())
|
||||
.getTimelineProperties().getTimeline();
|
||||
Date d = new Date();
|
||||
t.addMarker(d, taskTextField.getText(), "No comments.");
|
||||
startTimeLabel.setText(Timeline.shortFormat.format(d));
|
||||
@ -312,8 +313,9 @@ ChangeListener {
|
||||
}
|
||||
|
||||
public void setNotesForActiveTask(String notes) {
|
||||
Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
|
||||
Timeline.TimelineMarker tm = t.getLastMarker(new Date());
|
||||
Timeline t = ((TimeStamperApp) getApplication())
|
||||
.getTimelineProperties().getTimeline();
|
||||
TimelineMarker tm = t.getLastMarker(new Date());
|
||||
if (tm == null) return;
|
||||
tm.setNotes(notes);
|
||||
}
|
||||
@ -472,7 +474,7 @@ ChangeListener {
|
||||
|
||||
@Action
|
||||
public void saveTimeline() {
|
||||
((TimeStamperApp) getApplication()).saveTimeline();
|
||||
((TimeStamperApp) getApplication()).saveTimelineProperties();
|
||||
}
|
||||
|
||||
@Action
|
||||
@ -480,8 +482,8 @@ ChangeListener {
|
||||
if (fileChooser.showSaveDialog(getFrame())!=JFileChooser.APPROVE_OPTION)
|
||||
return;
|
||||
|
||||
((TimeStamperApp) getApplication()).saveTimelineToFile(
|
||||
fileChooser.getSelectedFile().getAbsolutePath());
|
||||
((TimeStamperApp) getApplication()).saveTimelinePropertiesAs(
|
||||
fileChooser.getSelectedFile());
|
||||
}
|
||||
|
||||
@Action
|
||||
@ -489,15 +491,16 @@ ChangeListener {
|
||||
if (fileChooser.showOpenDialog(getFrame())!=JFileChooser.APPROVE_OPTION)
|
||||
return;
|
||||
|
||||
((TimeStamperApp) getApplication()).loadTimeline(
|
||||
((TimeStamperApp) getApplication()).loadTimelineProperties(
|
||||
fileChooser.getSelectedFile().getAbsolutePath());
|
||||
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public void refreshDialog() {
|
||||
Timeline t = ((TimeStamperApp) getApplication()).getActiveTimeline();
|
||||
Timeline.TimelineMarker lastMarker = t.getLastMarker(new Date());
|
||||
Timeline t = ((TimeStamperApp) getApplication())
|
||||
.getTimelineProperties().getTimeline();
|
||||
TimelineMarker lastMarker = t.getLastMarker(new Date());
|
||||
|
||||
if (lastMarker != null) {
|
||||
mostRecentTask = lastMarker.getTimestamp();
|
25
src/jdbernard/timestamper/TimelineDayDisplay.java → src/jdbernard/timestamper/gui/TimelineDayDisplay.java
Executable file → Normal file
25
src/jdbernard/timestamper/TimelineDayDisplay.java → src/jdbernard/timestamper/gui/TimelineDayDisplay.java
Executable file → Normal file
@ -2,8 +2,10 @@
|
||||
* Author: Jonathan Bernard - jonathan.bernard@gemalto.com
|
||||
*/
|
||||
|
||||
package jdbernard.timestamper;
|
||||
package jdbernard.timestamper.gui;
|
||||
|
||||
import jdbernard.timestamper.core.TimelineMarker;
|
||||
import jdbernard.timestamper.core.Timeline;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
@ -31,7 +33,7 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
ChangeListener {
|
||||
|
||||
private class MarkerDisplayEntry {
|
||||
public Timeline.TimelineMarker marker;
|
||||
public TimelineMarker marker;
|
||||
public float relY;
|
||||
public float relHeight;
|
||||
public Rectangle2D markBounds;
|
||||
@ -186,7 +188,7 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
|
||||
private ArrayList<MarkerDisplayEntry> markerEntries;
|
||||
private ArrayList<TimeLegendEntry> timeLegendLocations;
|
||||
private Timeline.TimelineMarker currentMarker;
|
||||
private TimelineMarker currentMarker;
|
||||
private ArrayList<ChangeListener> changeListeners = new ArrayList<ChangeListener>();
|
||||
|
||||
private Point lastMousePress;
|
||||
@ -318,18 +320,20 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
return selectedOpaque;
|
||||
}
|
||||
|
||||
public Timeline.TimelineMarker getSelectedTimelineMarker() {
|
||||
public TimelineMarker getSelectedTimelineMarker() {
|
||||
return currentMarker;
|
||||
}
|
||||
|
||||
public void addMarker(Date timestamp, String mark, String notes) {
|
||||
Timeline timeline = TimeStamperApp.getApplication().getActiveTimeline();
|
||||
Timeline timeline = TimeStamperApp.getApplication()
|
||||
.getTimelineProperties().getTimeline();
|
||||
timeline.addMarker(timestamp, mark, notes);
|
||||
updateMarkers(getGraphics());
|
||||
}
|
||||
|
||||
public void deleteSelectedMarker() {
|
||||
Timeline timeline = TimeStamperApp.getApplication().getActiveTimeline();
|
||||
Timeline timeline = TimeStamperApp.getApplication()
|
||||
.getTimelineProperties().getTimeline();
|
||||
timeline.removeMarker(currentMarker);
|
||||
updateMarkers(getGraphics());
|
||||
}
|
||||
@ -348,7 +352,8 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
*/
|
||||
private void updateMarkers(Graphics g) {
|
||||
|
||||
Timeline timeline = TimeStamperApp.getApplication().getActiveTimeline();
|
||||
Timeline timeline = TimeStamperApp.getApplication()
|
||||
.getTimelineProperties().getTimeline();
|
||||
Insets insets = this.getInsets();
|
||||
Rectangle bounds = this.getBounds();
|
||||
Rectangle canvasBounds = new Rectangle(insets.left, insets.top,
|
||||
@ -396,7 +401,7 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
|
||||
// get all relevant markers starting from the marker just before the
|
||||
// visible start of the display
|
||||
Timeline.TimelineMarker tm = timeline.getLastMarker(rangeStartDate);
|
||||
TimelineMarker tm = timeline.getLastMarker(rangeStartDate);
|
||||
|
||||
// If there is no previous marker
|
||||
if (tm == null)
|
||||
@ -408,11 +413,11 @@ public class TimelineDayDisplay extends JComponent implements MouseListener,
|
||||
|
||||
// Now we want to step through the timeline, capturing all markers
|
||||
// between the visible ranges.
|
||||
Iterator<Timeline.TimelineMarker> itr = timeline.iterator();
|
||||
Iterator<TimelineMarker> itr = timeline.iterator();
|
||||
|
||||
while (!itr.next().equals(tm));
|
||||
|
||||
ArrayList<Timeline.TimelineMarker> markers = new ArrayList<Timeline.TimelineMarker>();
|
||||
ArrayList<TimelineMarker> markers = new ArrayList<TimelineMarker>();
|
||||
while (rangeEndDate.after(tm.getTimestamp())) {
|
||||
markers.add(tm);
|
||||
if (itr.hasNext()) tm = itr.next();
|
0
src/jdbernard/timestamper/resources/AboutDialog.properties → src/jdbernard/timestamper/gui/resources/AboutDialog.properties
Executable file → Normal file
0
src/jdbernard/timestamper/resources/AboutDialog.properties → src/jdbernard/timestamper/gui/resources/AboutDialog.properties
Executable file → Normal file
0
src/jdbernard/timestamper/resources/NotesDialog.properties → src/jdbernard/timestamper/gui/resources/NotesDialog.properties
Executable file → Normal file
0
src/jdbernard/timestamper/resources/NotesDialog.properties → src/jdbernard/timestamper/gui/resources/NotesDialog.properties
Executable file → Normal file
@ -0,0 +1,42 @@
|
||||
markTextField.text=
|
||||
previousWeek.Action.text=<<
|
||||
previousWeek.Action.shortDescription=Go back one week.
|
||||
dateLabel.text=date
|
||||
#NOI18N
|
||||
dateLabel.background=255, 255, 153
|
||||
prevWeekButton.text=jButton1
|
||||
previousWeek.Action.icon=icons/media-seek-backward.png
|
||||
previousWeek.Action.smallIcon=icons/media-seek-backward.png
|
||||
prevDayButton.text=jButton1
|
||||
previousDay.Action.smallIcon=icons/media-playback-reverse.png
|
||||
previousDay.Action.icon=icons/media-playback-reverse.png
|
||||
previousDay.Action.shortDescription=Go back one day.
|
||||
previousDay.Action.text=Previous Day
|
||||
currentDay.Action.text=Today
|
||||
currentDay.Action.shortDescription=Go to today's date.
|
||||
jButton2.text=jButton2
|
||||
nextDay.Action.smallIcon=icons/media-playback-start.png
|
||||
nextDay.Action.icon=icons/media-playback-start.png
|
||||
nextDay.Action.shortDescription=Go one day forward.
|
||||
nextDay.Action.text=Next Day
|
||||
nextWeekButton.text=jButton3
|
||||
nextWeek.Action.text=Next Week
|
||||
nextWeek.Action.smallIcon=icons/media-seek-forward.png
|
||||
nextWeek.Action.icon=icons/media-seek-forward.png
|
||||
nextWeek.Action.shortDescription=Go one week forward.
|
||||
newMarkerButton.text=jButton1
|
||||
newMarker.Action.smallIcon=icons/16-square-green-add.png
|
||||
newMarker.Action.icon=icons/16-square-green-add.png
|
||||
newMarker.Action.shortDescription=Create a new timestamp mark.
|
||||
newMarker.Action.text=New Marker
|
||||
deleteMarkerButton.text=jButton1
|
||||
deleteMarker.Action.text=Delete Marker
|
||||
deleteMarker.Action.shortDescription=Delete a timestamp mark.
|
||||
deleteMarker.Action.smallIcon=icons/16-square-red-delete.png
|
||||
deleteMarker.Action.icon=icons/16-square-red-delete.png
|
||||
saveMarkerChanges.text=jButton1
|
||||
saveMarkerChanges.Action.smallIcon=icons/document-save-16x16.png
|
||||
saveMarkerChanges.Action.icon=icons/document-save-16x16.png
|
||||
saveMarkerChanges.Action.shortDescription=Save timeline marker changes.
|
||||
saveMarkerChanges.Action.text=Save Changes
|
||||
timestampDateChooser.dateFormatString=MMM d, yyyy HH:mm
|
@ -9,9 +9,9 @@ Application.description = Simple application used to track activities throughout
|
||||
Application.vendorId = Jonathan Bernard
|
||||
Application.id = TimeStamper
|
||||
Application.lookAndFeel = system
|
||||
Application.icon=/jdbernard/timestamper/resources/icons/appointment-new-32x32.png
|
||||
Application.icon=icons/appointment-new-32x32.png
|
||||
quit.Action.text=Exit
|
||||
quit.Action.accelerator=ctrl pressed Q
|
||||
quit.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-em-cross.png
|
||||
quit.Action.icon=/jdbernard/timestamper/resources/icons/16-em-cross.png
|
||||
quit.Action.smallIcon=icons/16-em-cross.png
|
||||
quit.Action.icon=icons/16-em-cross.png
|
||||
quit.Action.shortDescription=Exit the application
|
28
src/jdbernard/timestamper/resources/TimeStamperView.properties → src/jdbernard/timestamper/gui/resources/TimeStamperView.properties
Executable file → Normal file
28
src/jdbernard/timestamper/resources/TimeStamperView.properties → src/jdbernard/timestamper/gui/resources/TimeStamperView.properties
Executable file → Normal file
@ -14,36 +14,36 @@ totalTimeNow.text=3day 2hr 50min 25sec
|
||||
#NOI18N
|
||||
totalTimeNow.foreground=0, 153, 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.smallIcon=icons/16-em-pencil.png
|
||||
editNotes.Action.icon=icons/16-em-pencil.png
|
||||
editNotes.Action.shortDescription=Edit notes for this task
|
||||
editNotes.Action.text=Show 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
|
||||
showOptionsMenu.Action.smallIcon=icons/16-tool-a.png
|
||||
showOptionsMenu.Action.icon=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.smallIcon=icons/document-save-16x16.png
|
||||
saveTimeline.Action.icon=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.smallIcon=icons/document-save-as-16x16.png
|
||||
saveTimelineAs.Action.icon=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
|
||||
loadTimeline.Action.smallIcon=icons/document-open-16x16.png
|
||||
loadTimeline.Action.icon=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.smallIcon=icons/16-em-cross.png
|
||||
exit.Action.shortDescription=Close the application.
|
||||
exit.Action.icon=/jdbernard/timestamper/resources/icons/16-em-cross.png
|
||||
exit.Action.icon=icons/16-em-cross.png
|
||||
notesButton2.text=jToggleButton1
|
||||
#NOI18N
|
||||
optionsButton.rolloverIcon=icons/16-tool-a-hover.png
|
||||
@ -53,8 +53,8 @@ showNotesDialogCheckBoxMenuItem.text=CheckBox
|
||||
showPunchcardCheckBoxMenuItem.text=CheckBox
|
||||
showPunchcard.Action.shortDescription=View the timeline
|
||||
showPunchcard.Action.text=Show Timeline...
|
||||
showPunchcard.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-file-archive.png
|
||||
showPunchcard.Action.icon=/jdbernard/timestamper/resources/icons/16-file-archive.png
|
||||
showPunchcard.Action.smallIcon=icons/16-file-archive.png
|
||||
showPunchcard.Action.icon=icons/16-file-archive.png
|
||||
editNotes.Action.accelerator=ctrl pressed N
|
||||
showPunchcard.Action.accelerator=ctrl pressed T
|
||||
showAboutCheckBoxMenuItem.text=CheckBox
|
@ -1,42 +0,0 @@
|
||||
markTextField.text=
|
||||
previousWeek.Action.text=<<
|
||||
previousWeek.Action.shortDescription=Go back one week.
|
||||
dateLabel.text=date
|
||||
#NOI18N
|
||||
dateLabel.background=255, 255, 153
|
||||
prevWeekButton.text=jButton1
|
||||
previousWeek.Action.icon=/jdbernard/timestamper/resources/icons/media-seek-backward.png
|
||||
previousWeek.Action.smallIcon=/jdbernard/timestamper/resources/icons/media-seek-backward.png
|
||||
prevDayButton.text=jButton1
|
||||
previousDay.Action.smallIcon=/jdbernard/timestamper/resources/icons/media-playback-reverse.png
|
||||
previousDay.Action.icon=/jdbernard/timestamper/resources/icons/media-playback-reverse.png
|
||||
previousDay.Action.shortDescription=Go back one day.
|
||||
previousDay.Action.text=Previous Day
|
||||
currentDay.Action.text=Today
|
||||
currentDay.Action.shortDescription=Go to today's date.
|
||||
jButton2.text=jButton2
|
||||
nextDay.Action.smallIcon=/jdbernard/timestamper/resources/icons/media-playback-start.png
|
||||
nextDay.Action.icon=/jdbernard/timestamper/resources/icons/media-playback-start.png
|
||||
nextDay.Action.shortDescription=Go one day forward.
|
||||
nextDay.Action.text=Next Day
|
||||
nextWeekButton.text=jButton3
|
||||
nextWeek.Action.text=Next Week
|
||||
nextWeek.Action.smallIcon=/jdbernard/timestamper/resources/icons/media-seek-forward.png
|
||||
nextWeek.Action.icon=/jdbernard/timestamper/resources/icons/media-seek-forward.png
|
||||
nextWeek.Action.shortDescription=Go one week forward.
|
||||
newMarkerButton.text=jButton1
|
||||
newMarker.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-square-green-add.png
|
||||
newMarker.Action.icon=/jdbernard/timestamper/resources/icons/16-square-green-add.png
|
||||
newMarker.Action.shortDescription=Create a new timestamp mark.
|
||||
newMarker.Action.text=New Marker
|
||||
deleteMarkerButton.text=jButton1
|
||||
deleteMarker.Action.text=Delete Marker
|
||||
deleteMarker.Action.shortDescription=Delete a timestamp mark.
|
||||
deleteMarker.Action.smallIcon=/jdbernard/timestamper/resources/icons/16-square-red-delete.png
|
||||
deleteMarker.Action.icon=/jdbernard/timestamper/resources/icons/16-square-red-delete.png
|
||||
saveMarkerChanges.text=jButton1
|
||||
saveMarkerChanges.Action.smallIcon=/jdbernard/timestamper/resources/icons/document-save-16x16.png
|
||||
saveMarkerChanges.Action.icon=/jdbernard/timestamper/resources/icons/document-save-16x16.png
|
||||
saveMarkerChanges.Action.shortDescription=Save timeline marker changes.
|
||||
saveMarkerChanges.Action.text=Save Changes
|
||||
timestampDateChooser.dateFormatString=MMM d, yyyy HH:mm
|
Loading…
x
Reference in New Issue
Block a user