Merge timestamper-gui

This commit is contained in:
Jonathan Bernard 2024-08-04 21:42:33 -05:00
commit ee087d302d
127 changed files with 4931 additions and 2 deletions

8
.gitignore vendored
View File

@ -1,5 +1,9 @@
.gradle/
*.sw?
build/
dist/
.gradle/
staging/
temp/
release
.sass-cache
*.build.tar.gz
*.sw?

62
gui/.classpath Normal file
View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main"/>
<classpathentry kind="src" path="griffon-app/conf"/>
<classpathentry kind="src" path="griffon-app/models"/>
<classpathentry kind="src" path="griffon-app/views"/>
<classpathentry kind="src" path="griffon-app/controllers"/>
<classpathentry kind="src" path="griffon-app/resources"/>
<classpathentry kind="src" path="test/integration"/>
<classpathentry kind="src" path="test/unit"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="GRIFFON_HOME/ant/lib/ant.jar"/>
<classpathentry kind="var" path="GRIFFON_HOME/lib/swingx-0.9.3.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/swing-worker.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/commons-lang-2.4.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/ant-launcher-1.7.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/gant_groovy1.6-1.6.0.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/asm-2.2.3.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/commons-cli-1.0.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/groovy-all-1.6.4.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/swingxbuilder-0.1.6-SNAPSHOT.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/jline-0.9.94.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/svnkit-1.2.0.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/log4j-1.2.15.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/ant-nodeps-1.7.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/ant-1.7.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/ant-trax-1.7.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/commons-logging-1.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/ant-junit-1.7.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/MultipleGradientPaint.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/spring-2.5.6.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/lib/junit-3.8.2.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/dist/griffon-rt-0.2.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/dist/griffon-resources-0.2.1.jar" />
<classpathentry kind="var" path="GRIFFON_HOME/dist/griffon-cli-0.2.1.jar" />
<classpathentry kind="output" path="staging/classes"/>
</classpath>

4
gui/.hgignore Executable file
View File

@ -0,0 +1,4 @@
.*.swp
.*.swo
staging
dist

18
gui/.project Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>TimeStamper</name>
<comment/>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

BIN
gui/CHANGE ME Normal file

Binary file not shown.

43
gui/TimeStamper.iml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="GRIFFON_MODULE" version="4">
<component name="FacetManager">
<facet type="Griffon" name="Griffon">
<configuration />
</facet>
<!--
<facet type="Spring" name="Spring">
<configuration>
<fileset id="Griffon" name="Griffon" removed="false">
<file>file://$MODULE_DIR$/web-app/WEB-INF/applicationContext.xml</file>
</fileset>
</configuration>
</facet>
-->
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/griffon-app/conf" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/griffon-app/models" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/griffon-app/views" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/griffon-app/controllers" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/griffon-app/lifecycle" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/integration" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/test/unit" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Griffon 0.3" level="project" />
<orderEntry type="module-library">
<library name="Griffon User Library">
<CLASSES>
<root url="file://$MODULE_DIR$/lib" />
</CLASSES>
<JAVADOC />
<SOURCES />
<jarDirectory url="file://$MODULE_DIR$/lib" recursive="false" />
</library>
</orderEntry>
</component>
</module>

59
gui/TimeStamper.ipr Normal file
View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="ProjectFileVersion" converted="true" />
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/TimeStamper.iml" filepath="$PROJECT_DIR$/TimeStamper.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="libraryTable">
<library name="Griffon 0.3">
<CLASSES>
<root url="jar:///home/jdbernard/programs/griffon/lib/log4j-1.2.15.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/spring-2.5.6.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/ant-trax-1.8.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/gant_groovy1.6-1.6.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/svnkit-1.2.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/junit-4.8.1.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/commons-cli-1.2.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/ant-nodeps-1.8.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/groovy-all-1.7.1.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/commons-lang-2.4.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/ant-junit-1.8.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/jline-0.9.94.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/ant-launcher-1.8.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/commons-logging-1.1.1.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/asm-3.2.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/lib/ant-1.8.0.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/dist/griffon-resources-0.3.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/dist/griffon-cli-0.3.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/dist/griffon-rt-0.3.jar!/" />
<root url="jar:///home/jdbernard/programs/griffon/dist/griffon-scripts-0.3.jar!/" />
</CLASSES>
</library>
</component>
</project>

65
gui/TimeStamper.iws Normal file
View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project relativePaths="false" version="4">
<component name="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="TimeStamper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="TimeStamper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="TimeStamper" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="0.5" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<showStructure ProjectPane="false" />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
</component>
<!--
<component name="RunManager" selected="Griffon Application.Griffon:TimeStamper">
<configuration default="false" name="Griffon:TimeStamper" type="GriffonRunConfigurationType" factoryName="Griffon Application">
<module name="TimeStamper" />
<setting name="vmparams" value="" />
<setting name="griffonparams" value="" />
<setting name="hostik" value="localhost" />
<setting name="port" value="8080" />
<setting name="jndi" value="false" />
<setting name="recomp" value="false" />
<setting name="recompileFreq" value="3" />
<setting name="launchBrowser" value="true" />
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" value="true" />
</method>
</configuration>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="Griffon Application.Griffon:TimeStamper" />
</list>
</component>
-->
<component name="ToolWindowManager">
<frame x="10" y="10" width="1260" height="984" extended-state="0" />
<editor active="false" />
<layout>
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.25" sideWeight="0.6623068" order="0" side_tool="false" />
</layout>
</component>
</project>

20
gui/TimeStamper.launch Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.codehaus.griffon.GriffonMain"/>
<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER&quot; javaProject=&quot;TimeStamper&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;TimeStamper&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/TimeStamper&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="4"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="TimeStamper"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dbase.dir=${project_loc} -Dgriffon.env=development"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/TimeStamper"/>
</listAttribute>
<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
</launchConfiguration>

73
gui/TimeStamper.tmproj Normal file
View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>documents</key>
<array>
<dict>
<key>filename</key>
<string>TimeStamper.launch</string>
</dict>
<dict>
<key>filename</key>
<string>build.xml</string>
</dict>
<dict>
<key>name</key>
<string>griffon-app</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>griffon-app</string>
</dict>
<dict>
<key>name</key>
<string>test</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>test</string>
</dict>
<dict>
<key>name</key>
<string>lib</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>lib</string>
</dict>
<dict>
<key>name</key>
<string>scripts</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>scripts</string>
</dict>
<dict>
<key>name</key>
<string>src</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>src</string>
</dict>
<dict>
<key>name</key>
<string>web-app</string>
<key>regexFolderFilter</key>
<string>!.*/(\.[^/]*|CVS|_darcs|_MTN|\{arch\}|blib|.*~\.nib|.*\.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$</string>
<key>sourceDirectory</key>
<string>web-app</string>
</dict>
</array>
<key>fileHierarchyDrawerWidth</key>
<integer>200</integer>
<key>metaData</key>
<dict/>
<key>showFileHierarchyDrawer</key>
<true/>
<key>windowFrame</key>
<string>{{237, 127}, {742, 553}}</string>
</dict>
</plist>

10
gui/application.properties Executable file
View File

@ -0,0 +1,10 @@
#Do not edit app.griffon.* properties, they may change automatically. DO NOT put application configuration in here, it is not the right place!
#Thu, 25 Apr 2013 06:40:33 -0500
#Thu Apr 01 22:28:40 CDT 2010
app.version=2.1
app.griffon.version=1.2.0
app.name=TimeStamper
plugins.swing=1.2.0
archetype.default=1.2.0
app.toolkit=swing

97
gui/build.xml Executable file
View File

@ -0,0 +1,97 @@
<project name="timestamper" default="test">
<!-- =================================
target: clean
================================= -->
<target name="clean" description="--> Cleans a Griffon application">
<griffon>
<arg value="clean"/>
</griffon>
</target>
<!-- =================================
target: package
================================= -->
<target name="package" description="--> Packages up Griffon artifacts">
<griffon>
<arg value="package"/>
</griffon>
</target>
<!-- =================================
target: run-app
================================= -->
<target name="run-app" description="--> Run a Griffon application in standalone mode">
<griffon>
<arg value="run-app"/>
</griffon>
</target>
<!-- =================================
target: debug-app
================================= -->
<target name="debug-app" description="--> Run a Griffon application in standalone mode with debugging turned on">
<griffon>
<arg value="run-app"/>
<arg value="-debug"/>
</griffon>
</target>
<!-- =================================
target: run-webstart
================================= -->
<target name="run-webstart" description="--> Run a Griffon application in webstart mode">
<griffon>
<arg value="run-webstart"/>
</griffon>
</target>
<!-- =================================
target: run-applet
================================= -->
<target name="run-applet" description="--> Run a Griffon application in applet mode">
<griffon>
<arg value="run-applet"/>
</griffon>
</target>
<!-- =================================
target: test
================================= -->
<target name="test" description="--> Run a Griffon applications unit tests">
<griffon>
<arg value="test-app"/>
</griffon>
</target>
<!-- =================================
target: dist
================================= -->
<target name="dist" description="--> Packages up Griffon artifacts in the Production Environment">
<griffon>
<arg value="prod"/>
<arg value="package"/>
</griffon>
</target>
<!-- set up the griffon macro -->
<property environment="env"/>
<property name="griffon.home" value="${env.GRIFFON_HOME}"/>
<property name="jdk.home" value="${env.JAVA_HOME}"/>
<condition property="griffon" value="griffon.bat">
<os family="windows"/>
</condition>
<property name="griffon" value="griffon" />
<macrodef name="griffon">
<element name="griffon-args" implicit="yes"/>
<sequential>
<exec executable="${griffon.home}/bin/${griffon}" failonerror="true">
<env key="JAVA_HOME" value="${jdk.home}"/>
<env key="GRIFFON_HOME" value="${griffon.home}"/>
<griffon-args/>
</exec>
</sequential>
</macrodef>
<!-- end set up the griffon macro -->
</project>

BIN
gui/doc/feed.pdf Executable file

Binary file not shown.

77
gui/doc/feed.rst Executable file
View 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

View 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

BIN
gui/doc/uml.tsm Normal file

Binary file not shown.

View File

@ -0,0 +1,27 @@
application {
title="TimeStamper"
startupGroups=["TimeStamperMain"]
autoShutdown=true
}
mvcGroups {
LogDialog {
model="com.jdblabs.timestamper.gui.LogDialogModel"
controller="com.jdblabs.timestamper.gui.LogDialogController"
view="com.jdblabs.timestamper.gui.LogDialogView"
}
TimeStamperMain {
model="com.jdblabs.timestamper.gui.TimeStamperMainModel"
view="com.jdblabs.timestamper.gui.TimeStamperMainView"
controller="com.jdblabs.timestamper.gui.TimeStamperMainController"
}
PunchcardDialog {
model="com.jdblabs.timestamper.gui.PunchcardDialogModel"
view="com.jdblabs.timestamper.gui.PunchcardDialogView"
controller="com.jdblabs.timestamper.gui.PunchcardDialogController"
}
NotesDialog {
model="com.jdblabs.timestamper.gui.NotesDialogModel"
view="com.jdblabs.timestamper.gui.NotesDialogView"
controller="com.jdblabs.timestamper.gui.NotesDialogController"
}
}

View File

@ -0,0 +1,191 @@
// key signing information
environments {
development {
signingkey {
params {
// sigfile = 'GRIFFON'
// keystore = "${basedir}/griffon-app/conf/keys/devKeystore"
// alias = 'development'
storepass = 'BadStorePassword'
keypass = 'BadKeyPassword'
lazy = true // only sign when unsigned
}
}
}
test {
griffon {
jars {
sign = false
pack = false
}
}
}
production {
signingkey {
params {
// NOTE: for production keys it is more secure to rely on key prompting
// no value means we will prompt //storepass = 'BadStorePassword'
// no value means we will prompt //keypass = 'BadKeyPassword'
lazy = false // sign, regardless of existing signatures
}
}
griffon {
jars {
sign = true
pack = true
destDir = "${basedir}/staging"
}
webstart {
codebase = 'CHANGE ME'
}
}
}
}
griffon {
memory {
//max = '64m'
//min = '2m'
//minPermSize = '2m'
//maxPermSize = '64m'
}
jars {
sign = false
pack = false
destDir = "${basedir}/staging"
jarName = "${appName}.jar"
}
extensions {
jarUrls = []
jnlpUrls = []
/*
props {
someProperty = 'someValue'
}
resources {
linux { // windows, macosx, solaris
jars = []
nativelibs = []
props {
someProperty = 'someValue'
}
}
}
*/
}
webstart {
codebase = "${new File(griffon.jars.destDir).toURI().toASCIIString()}"
jnlp = 'application.jnlp'
}
applet {
jnlp = 'applet.jnlp'
html = 'applet.html'
}
}
// required for custom environments
signingkey {
params {
def env = griffon.util.Environment.current.name
sigfile = 'GRIFFON-' + env
keystore = "${basedir}/griffon-app/conf/keys/${env}Keystore"
alias = env
// storepass = 'BadStorePassword'
// keypass = 'BadKeyPassword'
lazy = true // only sign when unsigned
}
}
griffon {
doc {
logo = '<a href="http://griffon-framework.org" target="_blank"><img alt="The Griffon Framework" src="../img/griffon.png" border="0"/></a>'
sponsorLogo = "<br/>"
footer = "<br/><br/>Made with Griffon (@griffon.version@)"
}
}
deploy {
application {
title = "${appName} ${appVersion}"
vendor = System.properties['user.name']
homepage = "http://localhost/${appName}"
description {
complete = "${appName} ${appVersion}"
oneline = "${appName} ${appVersion}"
minimal = "${appName} ${appVersion}"
tooltip = "${appName} ${appVersion}"
}
icon {
'default' {
name = 'griffon-icon-64x64.png'
width = '64'
height = '64'
}
splash {
name = 'griffon.png'
width = '391'
height = '123'
}
selected {
name = 'griffon-icon-64x64.png'
width = '64'
height = '64'
}
disabled {
name = 'griffon-icon-64x64.png'
width = '64'
height = '64'
}
rollover {
name = 'griffon-icon-64x64.png'
width = '64'
height = '64'
}
shortcut {
name = 'griffon-icon-64x64.png'
width = '64'
height = '64'
}
}
}
}
griffon.project.dependency.resolution = {
// inherit Griffon' default dependencies
inherits("global") {
}
log "warn" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
repositories {
griffonHome()
// uncomment the below to enable remote dependency resolution
// from public Maven repositories
//mavenLocal()
//mavenCentral()
//mavenRepo "http://snapshots.repository.codehaus.org"
//mavenRepo "http://repository.codehaus.org"
//mavenRepo "http://download.java.net/maven/2/"
//mavenRepo "http://repository.jboss.com/maven2/"
}
dependencies {
// specify dependencies here under either 'build', 'compile', 'runtime' or 'test' scopes eg.
// runtime 'mysql:mysql-connector-java:5.1.5'
}
}
log4j = {
// Example of changing the log pattern for the default console
// appender:
appenders {
console name: 'stdout', layout: pattern(conversionPattern: '%d [%t] %-5p %c - %m%n')
}
error 'org.codehaus.griffon',
'org.springframework',
'org.apache.karaf',
'groovyx.net'
warn 'griffon'
}

View File

@ -0,0 +1,7 @@
root {
'groovy.swing.SwingBuilder' {
controller = ['Threading']
view = '*'
}
}

View File

@ -0,0 +1,15 @@
log4j = {
// Example of changing the log pattern for the default console
// appender:
appenders {
console name: 'stdout', layout: pattern(conversionPattern: '%d [%t] %-5p %c - %m%n')
}
error 'org.codehaus.griffon'
info 'griffon.util',
'griffon.core',
'griffon.@application.toolkit@',
'griffon.app'
}

View File

@ -0,0 +1,5 @@
import org.slf4j.LoggerFactory
onNewInstance = { klass, type, instance ->
instance.metaClass.logger = LoggerFactory.getLogger(klass.name)
}

Binary file not shown.

View File

@ -0,0 +1,43 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
<script src="http://java.com/js/deployJava.js"></script>
<script>
var attributes = {id: 'TimeStamper',
codebase:'@griffonAppCodebase@',
code:'@griffonAppletClass@',
archive:'@appletJars@',
width:'240', height:'320'} ;
var parameters = {fontSize:16,
java_arguments: "-Djnlp.packEnabled=true",
jnlp_href:'@griffonAppCodebase@/applet.jnlp',
draggable:'true',
image:'griffon.png',
boxmessage:'Loading TimeStamper',
boxbgcolor:'#FFFFFF', boxfgcolor:'#000000',
codebase_lookup: 'false'} ;
var version = '1.5.0' ;
deployJava.runApplet(attributes, parameters, version);
</script>
<!--
<APPLET CODEBASE='@griffonAppCodebase@'
CODE='@griffonAppletClass@'
ARCHIVE='@appletJars@'
WIDTH='240' HEIGHT='320'>
<PARAM NAME="java_arguments" VALUE="-Djnlp.packEnabled=true">
<PARAM NAME='jnlp_href' VALUE='@griffonAppCodebase@/applet.jnlp'>
<PARAM NAME='dragggable' VALUE='true'>
<PARAM NAME='image' VALUE='griffon.png'>
<PARAM NAME='boxmessage' VALUE='Loading TimeStamper'>
<PARAM NAME='boxbgcolor' VALUE='#FFFFFF'>
<PARAM NAME='boxfgcolor' VALUE='#000000'>
<PARAM NAME='codebase_lookup' VALUE='false'>
</APPLET>
-->
</body>
</html>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE jnlp SYSTEM "http://java.sun.com/dtd/JNLP-1.5.dtd">
<jnlp
version="2.1"
codebase="@griffonAppCodebase@"
href="@jnlpFileName@"
>
<information>
<title>TimeStamper</title>
<vendor>TimeStamper</vendor>
<!--<homepage href="http://app.example.com/"/>-->
<!--fallback description-->
<description>TimeStamper</description>
<description kind="one-line">TimeStamper</description>
<description kind="short">TimeStamper</description>
<description kind="tooltip">TimeStamper</description>
<!-- fallback icon -->
<icon href="griffon-icon-48x48.png" kind="default" width="48" height="48"/>
<!-- icon used for splash screen -->
<icon href="griffon.png" kind="splash" width="381" height="123"/>
<!-- icon used in menu -->
<icon href="griffon-icon-16x16.png" kind="shortcut" width="16" height="16"/>
<!-- icon used on desktop -->
<icon href="griffon-icon-32x32.png" kind="shortcut" width="32" height="32"/>
<!-- to create shortcuts, uncomment this
<shortcut online="true">
<desktop/>
<menu submenu="TimeStamper"/>
</shortcut>
-->
<offline-allowed/>
</information>
<security>
<all-permissions/>
<!--<j2ee-application-client-permissions/>-->
</security>
<resources>
<property name="jnlp.packEnabled" value="true"/>
<j2se version="1.5+" @memoryOptions@/>
<!-- auto-added jars follow, griffon-rt, app, and groovy -->
@jnlpJars@
<!-- Add all extra jars below here, or the app may break -->
@jnlpExtensions@
</resources>
<applet-desc
documentbase="@griffonAppCodebase@"
name="TimeStamperApplet"
main-class="@griffonAppletClass@"
width="320"
height="640">
<!-- params are ignored when referenced from web page for 6u10 -->
<!--<param name="key1" value="value1"/>-->
<!--<param name="key2" value="value2"/>-->
</applet-desc>
</jnlp>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE jnlp SYSTEM "http://java.sun.com/dtd/JNLP-1.5.dtd">
<jnlp
version="2.1"
codebase="@griffonAppCodebase@"
href="@jnlpFileName@"
>
<information>
<title>TimeStamper</title>
<vendor>TimeStamper</vendor>
<!--<homepage href="http://app.example.com/"/>-->
<!--fallback description-->
<description>TimeStamper</description>
<description kind="one-line">TimeStamper</description>
<description kind="short">TimeStamper</description>
<description kind="tooltip">TimeStamper</description>
<!-- fallback icon -->
<icon href="griffon-icon-48x48.png" kind="default" width="48" height="48"/>
<!-- icon used for splash screen -->
<icon href="griffon.png" kind="splash" width="381" height="123"/>
<!-- icon used in menu -->
<icon href="griffon-icon-16x16.png" kind="shortcut" width="16" height="16"/>
<!-- icon used on desktop -->
<icon href="griffon-icon-32x32.png" kind="shortcut" width="32" height="32"/>
<!-- to create shortcuts, uncomment this
<shortcut online="true">
<desktop/>
<menu submenu="TimeStamper"/>
</shortcut>
<offline-allowed/>
-->
</information>
<security>
<all-permissions/>
<!--<j2ee-application-client-permissions/>-->
</security>
<resources>
<property name="jnlp.packEnabled" value="true"/>
<j2se version="1.5+" @memoryOptions@/>
<!-- auto-added jars follow, griffon-rt, app, and groovy -->
@jnlpJars@
<!-- Add all extra jars below here, or the app may break -->
@jnlpExtensions@
</resources>
<application-desc main-class="@griffonApplicationClass@">
<!-- params are ignored when referenced from web page for 6u10 -->
<!--<param name="key1" value="value1"/>-->
<!--<param name="key2" value="value2"/>-->
</application-desc>
</jnlp>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,16 @@
package com.jdblabs.timestamper.gui
class LogDialogController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
// this method is called after model and view are injected
}
/*
def action = { evt = null ->
}
*/
}

View File

@ -0,0 +1,18 @@
package com.jdblabs.timestamper.gui
import java.awt.Point
class NotesDialogController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
def loc = model.mainMVC.view.frame.location
Point p = new Point(0, (int) model.mainMVC.view.frame.bounds.height + 50)
p.translate((int) loc.x, (int) loc.y)
view.dialog.location = p
}
}

View File

@ -0,0 +1,22 @@
package com.jdblabs.timestamper.gui
import java.awt.Point
class PunchcardDialogController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
def loc = model.mainMVC.view.frame.location
Point p = new Point(0, (int) model.mainMVC.view.frame.bounds.height + 50)
p.translate((int) loc.x, (int) loc.y)
view.dialog.location = p
}
/*
def action = { evt = null ->
}
*/
}

View File

@ -0,0 +1,168 @@
package com.jdblabs.timestamper.gui
import com.jdbernard.util.SmartConfig
import com.jdblabs.timestamper.core.TimelineMarker
import com.jdblabs.timestamper.core.TimelineProperties
class TimeStamperMainController {
// these will be injected by Griffon
def model
def view
def thisMVC
def syncTimers = [:]
void mvcGroupInit(Map args) {
def configFile
logger.trace("Initializing TimeStamperMain MVC...")
// init mvc map
thisMVC = ['model': model, 'view': view, 'controller': this]
model.notesDialogMVC = buildMVCGroup('NotesDialog', 'notesDialog',
'mainMVC': thisMVC)
model.punchcardDialogMVC = buildMVCGroup('PunchcardDialog',
'punchcardDialog', 'mainMVC': thisMVC)
// load application properties
String userHomeDir = System.getProperty('user.home')
configFile = new File(userHomeDir, ".timestamperrc")
logger.trace("Reading configuration from {}", configFile.canonicalPath)
model.config = new SmartConfig(configFile)
// load the last used timeline file
String lastUsed = model.config.lastUsed
if (lastUsed == "") {
lastUsed = 'timeline.default.properties'
model.config.setProperty('lastUsed', lastUsed)
}
// load the plugin directory
File pluginDir = model.config.getProperty("pluginDir", new File("plugins"))
if (!pluginDir.exists()) pluginDir.mkdirs()
logger.trace("Adding plugin classpath: '{}'", pluginDir.canonicalPath)
def pluginLoader = new GroovyClassLoader(this.class.classLoader)
pluginLoader.addURL(pluginDir.toURI().toURL())
pluginDir.eachFileMatch(/.*\.jar/) { jarfile ->
pluginLoader.addURL(jarfile.toURI().toURL()) }
// instantiate plugins
model.config."plugin.classes".split(',').each { className -> try {
if (className.trim() == "") return
def pluginClass = pluginLoader.loadClass(className)
model.plugins <<pluginClass.newInstance()
logger.trace("Loaded plugin: {}", className)
} catch (ClassNotFoundException cnfe) {
logger.warn("Unable to load plugin ${className}: " +
"class not found.", cnfe)
} catch (Throwable t) {
logger.warn("Unable to load plugin ${className}.", t)
} }
// run plugin startup hook
model.plugins.each { plugin ->
wrapPluginCall { plugin.onStartup(thisMVC) } }
logger.trace("Reading Timeline properties from '{}'", lastUsed)
load(new File(lastUsed))
}
def wrapPluginCall(Closure c) {
try { c() } catch (Throwable t) {
logger.warn("Plugin threw an exception in ${functionName} " +
"when passed ${param}:", t)
return false
}
}
def load = { File propertiesFile ->
// pass through plugins
propertiesFile = model.plugins.inject(propertiesFile) { file, plugin ->
// call plugin
def ret = wrapPluginCall { plugin.onTimelineLoad(thisMVC, file) }
// if the plugin call succeeded, pass the result, else pass
// the last one
ret ? ret : file
}
try {
model.config.lastUsed = propertiesFile.canonicalPath
} catch (IOException ioe) { logger.error(ioe) }
// load the properties file
model.timelineProperties = new TimelineProperties(propertiesFile)
// load the main timeline
model.timeline = model.timelineProperties.timeline
// load the last marker
model.currentMarker = model.timeline.getLastMarker(new Date())
}
def saveas = {
}
def exitGracefully = { evt = null ->
// hide the frame immediately
view.frame.visible = false
logger.trace("Exiting gracefully.")
// save config
logger.debug("Config: {}", model.config)
model.config.save()
// save timeline and properties
model.timelineProperties.save()
// call plugin exit hooks
model.plugins.each { plugin ->
wrapPluginCall { plugin.onExit(thisMVC) } }
logger.trace("Completed graceful shutdown.")
app.shutdown()
}
def newTask = { mark, notes = "No comments.", timestamp = new Date() ->
TimelineMarker tm = new TimelineMarker(timestamp, mark, notes)
// pass through the plugins
tm = model.plugins.inject(tm) { marker, plugin ->
def ret = wrapPluginCall { plugin.onNewTask(thisMVC, marker) }
ret ? ret : marker
}
model.timeline.addMarker(tm)
model.currentMarker = model.timeline.getLastMarker(new Date())
// auto-persist if enabled
if (model.timelineProperties.persistOnUpdate)
model.timelineProperties.save()
}
def deleteTask = { marker ->
// pass through the plugins
model.plugins.each { plugin ->
wrapPluginCall { plugin.onDeleteTask(thisMVC, marker) } }
model.timeline.removeMarker(marker)
model.currentMarker = model.timeline.getLastMarker(new Date())
// auto-persist if enabled
if (model.timelineProperties.persistOnUpdate)
model.timelineProperties.save()
}
}

View File

View File

@ -0,0 +1,22 @@
/*
* This script is executed inside the EDT, so be sure to
* call long running code in another thread.
*
* You have the following options
* - SwingBuilder.doOutside { // your code }
* - Thread.start { // your code }
* - SwingXBuilder.withWorker( start: true ) {
* onInit { // initialization (optional, runs in current thread) }
* work { // your code }
* onDone { // finish (runs inside EDT) }
* }
*
* You have the following options to run code again inside EDT
* - SwingBuilder.doLater { // your code }
* - SwingBuilder.edt { // your code }
* - SwingUtilities.invokeLater { // your code }
*/
import groovy.swing.SwingBuilder
SwingBuilder.lookAndFeel('system', 'nimbus', ['metal', [boldFonts: false]])

View File

@ -0,0 +1,18 @@
/*
* This script is executed inside the EDT, so be sure to
* call long running code in another thread.
*
* You have the following options
* - SwingBuilder.doOutside { // your code }
* - Thread.start { // your code }
* - SwingXBuilder.withWorker( start: true ) {
* onInit { // initialization (optional, runs in current thread) }
* work { // your code }
* onDone { // finish (runs inside EDT) }
* }
*
* You have the following options to run code again inside EDT
* - SwingBuilder.doLater { // your code }
* - SwingBuilder.edt { // your code }
* - SwingUtilities.invokeLater { // your code }
*/

View File

@ -0,0 +1,18 @@
/*
* This script is executed inside the EDT, so be sure to
* call long running code in another thread.
*
* You have the following options
* - SwingBuilder.doOutside { // your code }
* - Thread.start { // your code }
* - SwingXBuilder.withWorker( start: true ) {
* onInit { // initialization (optional, runs in current thread) }
* work { // your code }
* onDone { // finish (runs inside EDT) }
* }
*
* You have the following options to run code again inside EDT
* - SwingBuilder.doLater { // your code }
* - SwingBuilder.edt { // your code }
* - SwingUtilities.invokeLater { // your code }
*/

View File

@ -0,0 +1,19 @@
/*
* This script is executed inside the EDT, so be sure to
* call long running code in another thread.
*
* You have the following options
* - SwingBuilder.doOutside { // your code }
* - Thread.start { // your code }
* - SwingXBuilder.withWorker( start: true ) {
* onInit { // initialization (optional, runs in current thread) }
* work { // your code }
* onDone { // finish (runs inside EDT) }
* }
*
* You have the following options to run code again inside EDT
* - SwingBuilder.doLater { // your code }
* - SwingBuilder.edt { // your code }
* - SwingUtilities.invokeLater { // your code }
*/

View File

View File

@ -0,0 +1,7 @@
package com.jdblabs.timestamper.gui
import groovy.beans.Bindable
class LogDialogModel {
def mainMVC
}

View File

@ -0,0 +1,9 @@
package com.jdblabs.timestamper.gui
import groovy.beans.Bindable
class NotesDialogModel {
// needs to be injected by buildMVCGroup call
def mainMVC
}

View File

@ -0,0 +1,9 @@
package com.jdblabs.timestamper.gui
import groovy.beans.Bindable
class PunchcardDialogModel {
// needs to be injected by buildMVCGroup() call
def mainMVC
}

View File

@ -0,0 +1,25 @@
package com.jdblabs.timestamper.gui
import groovy.beans.Bindable
import java.awt.Point
import java.awt.Rectangle
import java.util.Properties
import com.jdbernard.util.SmartConfig
import com.jdblabs.timestamper.core.Timeline
import com.jdblabs.timestamper.core.TimelineMarker
import com.jdblabs.timestamper.core.TimelineProperties
class TimeStamperMainModel {
@Bindable TimelineMarker currentMarker
@Bindable Timeline timeline
@Bindable TimelineProperties timelineProperties
SmartConfig config
List plugins = []
def notesDialogMVC
def punchcardDialogMVC
@Bindable Point absoluteLocation
@Bindable Rectangle frameSize
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,20 @@
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.FileAppender
import static ch.qos.logback.classic.Level.*
appender("CONSOLE", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%level - %msg%n"
}
}
appender("FILE", FileAppender) {
file="timestamper.log"
encoder(PatternLayoutEncoder) {
pattern = "%date %level %logger - %msg%n"
}
}
root(WARN, ["CONSOLE"])
logger("com.jdblabs.*", TRACE, ["FILE"], false)

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

1880
gui/griffon-app/session.vim Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
package com.jdblabs.timestamper.gui
import javax.swing.JDialog
dialog = dialog(new JDialog(model.mainMVC.view.frame),
title: 'Error Messages...',
modal: false) {
logger.trace( "Building LogDialog view." )
}

View File

@ -0,0 +1,65 @@
package com.jdblabs.timestamper.gui
import java.awt.Color
import java.awt.Point
import java.awt.Rectangle
import java.awt.Toolkit
import javax.swing.BoxLayout
import javax.swing.JDialog
import net.miginfocom.swing.MigLayout
Point mousePressRelativeToDialog
Point offsetFromMainFrame = new Point(0,0)
boolean coupledToMainFrame = false
mousePressed = { evt -> mousePressRelativeToDialog = evt?.point }
mouseDragged = { evt ->
GUIUtil.componentDragged(dialog, evt, mousePressRelativeToDialog,
new Rectangle(Toolkit.defaultToolkit.screenSize),
model.mainMVC.view.frame.bounds)
offsetFromMainFrame = GUIUtil.calculateOffset(
model.mainMVC.view.frame, dialog)
coupledToMainFrame = GUIUtil.componentsCoupled(dialog,
model.mainMVC.view.frame);
}
dialog = dialog(new JDialog(model.mainMVC.view.frame),
title: 'Notes',
modal: false,
undecorated: true,
minimumSize: [325, 200],
mousePressed: mousePressed,
mouseDragged: mouseDragged,
iconImage: imageIcon('/16-em-pencil.png').image,
iconImages: [imageIcon('/16-em-pencil.png').image],
location: bind(source: model.mainMVC.model,
sourceProperty: 'absoluteLocation',
converter: { loc ->
if (coupledToMainFrame) {
Point p = new Point(offsetFromMainFrame)
p.translate((int) loc.x, (int) loc.y)
return p
} else return dialog.location })
) {
logger.trace('Building NotesDialog GUI')
panel(
border:lineBorder(color: Color.BLACK, thickness:1, parent:true),
layout: new MigLayout('insets 10 10 10 10, fill')
) {
scrollPane(constraints: 'growx, growy') {
notesTextArea = textArea(lineWrap: true, columns: 20, rows: 5,
wrapStyleWord: true,
text: bind(source: model.mainMVC.model,
sourceProperty: 'currentMarker',
sourceValue: { model.mainMVC.model.currentMarker?.notes}),
keyReleased: {
if (model.mainMVC.model.currentMarker != null)
model.mainMVC.model.currentMarker.notes =
notesTextArea.text})
}
}
}

View File

@ -0,0 +1,164 @@
package com.jdblabs.timestamper.gui
import java.awt.Color
import java.awt.Point
import java.awt.Toolkit
import java.awt.Rectangle
import java.beans.PropertyChangeListener
import java.text.SimpleDateFormat
import javax.swing.JDialog
import java.util.Calendar
import javax.swing.SwingConstants
import com.jdblabs.timestamper.gui.TimelineDayDisplay
import com.toedter.calendar.JDateChooser
import net.miginfocom.swing.MigLayout
Point mousePressRelativeToDialog
Point offsetFromMainFrame = new Point(0,0)
boolean coupledToMainFrame = false
dateFormatter = new SimpleDateFormat("EEE MMM dd")
mousePressed = { evt -> mousePressRelativeToDialog = evt?.point }
mouseDragged = { evt ->
GUIUtil.componentDragged(dialog, evt, mousePressRelativeToDialog,
new Rectangle(Toolkit.defaultToolkit.screenSize),
model.mainMVC.view.frame.bounds)
offsetFromMainFrame = GUIUtil.calculateOffset(
model.mainMVC.view.frame, dialog)
coupledToMainFrame = GUIUtil.componentsCoupled(dialog,
model.mainMVC.view.frame);
}
dialog = dialog(new JDialog(model.mainMVC.view.frame),
title: 'Punchcard',
modal: false,
undecorated: true,
mousePressed: mousePressed,
mouseDragged: mouseDragged,
iconImage: imageIcon('/16-file-archive.png').image,
iconImages: [imageIcon('/16-file-archive.png').image],
minimumSize: [450, 500],
location: bind(source: model.mainMVC.model,
sourceProperty: 'absoluteLocation',
converter: { loc ->
if (coupledToMainFrame) {
Point p = new Point(offsetFromMainFrame)
p.translate((int) loc.x, (int) loc.y)
return p
} else return dialog.location })
) {
logger.trace('Building PunchcardDialog GUI')
panel(
border:lineBorder(color: Color.BLACK, thickness:1, parent:true),
layout: new MigLayout('fill, insets 10 10 10 10',
'[grow]', '[grow]10[grow 0]')
) {
dayDisplay = widget(constraints: 'grow, gp 200',
new TimelineDayDisplay(model.mainMVC.model.timeline),
timeline: bind(source: model.mainMVC.model,
sourceProperty: 'timeline'))
model.mainMVC.model.addPropertyChangeListener('currentMarker', {
dayDisplay.stateChanged(null) } as PropertyChangeListener)
panel(
border: lineBorder(color: Color.BLACK, thickness: 1),
constraints: 'growx, growy 0, newline, bottom',
layout: new MigLayout('fill, insets 0 10 0 10',
'[grow]10[grow 0]', '[][][grow 0]')
) {
dateChooser = widget(new JDateChooser(),
constraints: 'growx, gaptop 10',
dateFormatString: 'MMM d, yyyy HH:mm',
date: bind(source: dayDisplay,
sourceProperty: 'selectedTimelineMarker',
converter: { it?.timestamp }))
panel(constraints: 'spany 3, wrap, al trailing',
layout: new MigLayout('insets 0', '[]0[]0[]0[]0[]',
'[]0[]0[]0[]0[]')
) {
label(background: [255, 255, 153],
constraints: 'growx, spanx 5, wrap',
horizontalAlignment: SwingConstants.CENTER,
opaque: true,
text: bind(source: dayDisplay,
sourceProperty: 'rangeStart',
converter: { dateFormatter.format(it) }))
Calendar calendar = Calendar.getInstance()
button(icon: imageIcon('/previous-week.png'),
border: emptyBorder(4),
actionPerformed: {
calendar.time = dayDisplay.rangeStart
calendar.add(Calendar.WEEK_OF_YEAR, -1)
dayDisplay.day = calendar.time })
button(icon: imageIcon('/previous-day.png'),
border: emptyBorder(4),
actionPerformed: {
calendar.time = dayDisplay.rangeStart
calendar.add(Calendar.DAY_OF_YEAR, -1)
dayDisplay.day = calendar.time })
button(text: 'Today',
border: emptyBorder(4),
actionPerformed: {
calendar = Calendar.getInstance()
dayDisplay.day = calendar.time })
button(icon: imageIcon('/next-day.png'),
border: emptyBorder(4),
actionPerformed: {
calendar.time = dayDisplay.rangeStart
calendar.add(Calendar.DAY_OF_YEAR, 1)
dayDisplay.day = calendar.time })
button(icon: imageIcon('/next-week.png'),
constraints: 'wrap',
border: emptyBorder(4),
actionPerformed: {
calendar.time = dayDisplay.rangeStart
calendar.add(Calendar.WEEK_OF_YEAR, 1)
dayDisplay.day = calendar.time })
button(text: 'New Marker', icon: imageIcon('/new-marker.png'),
constraints: 'growx, spanx 5, wrap',
horizontalAlignment: SwingConstants.CENTER,
actionPerformed: {
model.mainMVC.controller.newTask(markTextField.text,
notesTextField.text, dateChooser.date) })
button(text: 'Delete Marker',
icon: imageIcon('/delete-marker.png'),
constraints: 'growx, spanx 5, wrap',
horizontalAlignment: SwingConstants.CENTER,
actionPerformed: {
model.mainMVC.controller.deleteTask(
dayDisplay.selectedTimelineMarker) })
button(text: 'Apply Changes',
icon: imageIcon('/document-save-16x16.png'),
constraints: 'growx, spanx 5',
horizontalAlignment: SwingConstants.CENTER,
actionPerformed: {
Date d = dateChooser.date
String m = markTextField.text
String n = notesTextField.text
model.mainMVC.controller.deleteTask(
dayDisplay.selectedTimelineMarker)
model.mainMVC.controller.newTask(m, n, d) })
}
markTextField = textField(constraints: 'growx, wrap',
text: bind(source: dayDisplay,
sourceProperty: 'selectedTimelineMarker',
converter: { it?.mark }))
scrollPane(constraints: 'growx, gapbottom 10',
minimumSize: [0, 50]) {
notesTextField = textArea( wrapStyleWord: true, lineWrap: true,
text: bind(source: dayDisplay,
sourceProperty: 'selectedTimelineMarker',
converter: { it?.notes }))
}
}
}
}

View File

@ -0,0 +1,205 @@
package com.jdblabs.timestamper.gui
import java.awt.Color
import java.awt.Font
import java.awt.Point
import java.awt.Rectangle
import java.awt.Toolkit
import java.awt.event.KeyEvent
import javax.swing.BoxLayout
import javax.swing.JDialog
import javax.swing.JFileChooser
import javax.swing.SwingConstants
import javax.swing.Timer
import com.jdblabs.timestamper.core.Timeline
import net.miginfocom.swing.MigLayout
/* ========== *
* GUI Events *
* ========== */
taskTextFieldChanged = { evt = null ->
if (evt.keyCode == KeyEvent.VK_ENTER) {
taskTextField.font = taskBoldFont
controller.newTask(taskTextField.text)
}
else if (evt.keyCode == KeyEvent.VK_ESCAPE) {
taskTextField.font = taskBoldFont
taskTextField.text = model.currentMarker.mark
}
else if (!evt.isActionKey())
taskTextField.font = taskThinFont
}
showNotes = { evt = null ->
model.notesDialogMVC.view.dialog.visible = notesVisibleButton.selected
}
showPunchcard = { evt = null ->
model.punchcardDialogMVC.view.dialog.visible = punchcardVisibleButton.selected
}
mousePressed = { evt = null ->
mousePressRelativeToFrame = evt?.point
}
mouseDragged = { evt = null ->
GUIUtil.componentDragged(frame, evt, mousePressRelativeToFrame,
new Rectangle(Toolkit.defaultToolkit.screenSize))
}
/* ============== *
* GUI Definition *
* ============== */
updateTimer = new Timer(1000, action(name: 'GUI Refresh', closure: {
Date currentTime = new Date()
currentTimeLabel.text = Timeline.shortFormat.format(currentTime)
if (model.currentMarker != null) {
long seconds = currentTime.time - model.currentMarker.timestamp.time
seconds /= 1000
long minutes = seconds / 60
seconds = seconds % 60
long hours = minutes / 60
minutes %= 60
long days = hours / 24
hours %= 24
StringBuilder sb = new StringBuilder()
if (days > 0) sb.append(days + "day ")
if (hours > 0) sb.append(hours + "hr ")
if (minutes > 0) sb.append(minutes + "min ")
sb.append(seconds + "sec")
totalTimeLabel.text = sb.toString()
} else totalTimeLabel.text = ""
}))
updateTimer.start()
optionsMenu = popupMenu() {
menuItem(icon: imageIcon('/document-save-16x16.png'), text: 'Save Timeline',
actionPerformed: { model.timelineProperties.save() })
menuItem(icon: imageIcon('/document-save-as-16x16.png'),
text: 'Save a new copy...', actionPerformed: controller.&saveas)
menuItem(icon: imageIcon('/document-open-16x16.png'),
text: 'Load Timeline...', actionPerformed: {
if (fileDialog.showOpenDialog(frame) ==
JFileChooser.APPROVE_OPTION)
controller.load(fileDialog.selectedFile) })
checkBoxMenuItem(text: 'Save on update?',
selected: bind(source: model, sourceProperty: 'timelineProperties',
sourceValue: { model.timelineProperties?.persistOnUpdate }),
actionPerformed: {
model.timelineProperties.persistOnUpdate = it.source.selected })
aboutMenuItem = checkBoxMenuItem(text: 'About...',
actionPerformed: { aboutDialog.visible = aboutMenuItem.selected })
}
fileDialog = fileChooser();
frame = application(title:'TimeStamper',
location:[50,50],
locationByPlatform:true,
minimumSize: [325, 0],
pack:true,
undecorated:true,
iconImage: imageIcon('/appointment-new-32x32.png').image,
iconImages: [imageIcon('/appointment-new-32x32.png').image,
imageIcon('/appointment-new-16x16.png').image],
componentMoved: { evt -> model.absoluteLocation = frame.location }
) {
logger.trace('Building TimeStamperMain GUI')
panel(
border:lineBorder(color:Color.BLACK, thickness:1, parent:true),
layout: new MigLayout('insets 0 5 0 0, fill','', '[]0[]0[]'),
mousePressed: mousePressed,
mouseDragged: mouseDragged
) {
def mainFont = new Font(Font.SANS_SERIF, Font.BOLD, 12)
def timeFont = new Font(Font.SANS_SERIF, Font.BOLD, 14)
label("Current task started at ", font: mainFont)
label(constraints: 'align leading', font: timeFont,
foreground: [0, 102, 102],
text: bind(source: model, sourceProperty: 'currentMarker',
sourceValue: {
model.currentMarker == null ? "00:00:00" :
Timeline.shortFormat.format(model.currentMarker.timestamp)
}))
panel(constraints: 'alignx trailing, aligny top, wrap') {
boxLayout(axis: BoxLayout.X_AXIS)
button(mouseClicked: { evt ->
optionsMenu.show(evt.component, evt.x, evt.y) },
icon: imageIcon('/16-tool-a.png'),
rolloverIcon: imageIcon('/16-tool-a-hover.png'),
border: emptyBorder(0),
contentAreaFilled: false,
hideActionText: true,
toolTipText: 'Options Menu')
button(actionPerformed: controller.&exitGracefully,
icon: imageIcon('/16-em-cross.png'),
rolloverIcon: imageIcon('/16-em-cross-hover.png'),
border: emptyBorder(0),
contentAreaFilled: false,
hideActionText: true,
toolTipText: 'Close Application')
}
taskTextField = textField("Task name",
constraints: "growx, span 2, w 250::",
keyReleased: taskTextFieldChanged,
toolTipText: 'The current task',
text: bind(source: model, sourceProperty: 'currentMarker',
sourceValue: { model.currentMarker?.mark }))
taskThinFont = taskTextField.font
taskBoldFont = taskTextField.font.deriveFont(Font.BOLD)
panel(constraints: 'alignx leading, aligny top, gapright 5px, wrap') {
boxLayout(axis: BoxLayout.X_AXIS)
notesVisibleButton = toggleButton(
actionPerformed: showNotes,
icon: imageIcon('/16-em-pencil.png'),
hideActionText: true,
border: emptyBorder(4),
toolTipText: 'Show/hide task notes.')
punchcardVisibleButton = toggleButton(
actionPerformed: showPunchcard,
icon: imageIcon('/16-file-archive.png'),
hideActionText: true,
border: emptyBorder(4),
toolTipText: 'Show/hide the timeline display.')
}
totalTimeLabel = label("", constraints: 'alignx leading',
font: timeFont, foreground: [0, 153, 0])
currentTimeLabel = label("00:00:00", constraints: 'align trailing',
font: timeFont, foreground: [204, 0, 0])
}
}
aboutDialog = dialog(new JDialog(frame),
visible: false,
locationRelativeTo: null,
pack: true,
undecorated: true,
title: "About TimeStamper v" + app.metadata.'app.version'
) {
panel(layout: new MigLayout('fill'),
border: lineBorder(color: Color.BLACK, thickness: 1)) {
label(font: new Font(Font.SANS_SERIF, Font.PLAIN, 18),
text: "TimeStamper", constraints: 'growx, wrap',
horizontalAlignment: SwingConstants.CENTER)
label(text: "version " + app.metadata.'app.version'
+ " by Jonathan Bernard", constraints: 'growx, wrap',
horizontalAlignment: SwingConstants.CENTER)
textField(text: 'http://www.jdb-labs.com/timestamper',
constraints: 'growx', foreground: [0,0,200], editable: false,
horizontalAlignment: SwingConstants.CENTER)
}
}

165
gui/griffonw Normal file
View File

@ -0,0 +1,165 @@
#!/bin/bash
##############################################################################
##
## Griffon start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRIFFON_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Griffon"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/"
APP_HOME="`pwd -P`"
cd "$SAVED"
CLASSPATH=$APP_HOME/wrapper/griffon-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query businessSystem maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add APP_NAME to the JAVA_OPTS as -Xdock:name
if $darwin; then
JAVA_OPTS="$JAVA_OPTS -Xdock:name=$APP_NAME"
# we may also want to set -Xdock:image
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRIFFON_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRIFFON_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRIFFON_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRIFFON_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GriffonWrapperMain "$@"

90
gui/griffonw.bat Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Griffon startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRIFFON_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\wrapper\griffon-wrapper.jar
@rem Execute Griffon
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRIFFON_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GriffonWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRIFFON_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRIFFON_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

BIN
gui/keystore.jks Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
gui/lib/ezmorph-1.0.6.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
gui/lib/httpcore-4.1.jar Normal file

Binary file not shown.

BIN
gui/lib/httpmime-4.1.1.jar Normal file

Binary file not shown.

BIN
gui/lib/jcalendar-1.3.2.jar Executable file

Binary file not shown.

Binary file not shown.

BIN
gui/lib/jdb-util-1.1.jar Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More