diff --git a/photos/portraits/album.properties b/photos/portraits/album.properties new file mode 100644 index 0000000..6272b07 --- /dev/null +++ b/photos/portraits/album.properties @@ -0,0 +1,2 @@ + +cover=valdemar-dahl.jpg diff --git a/pom.xml b/pom.xml index 251fa4e..2d7245e 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ junit junit 4.4 - test + org.springframework diff --git a/src/org/forkalsrud/album/exif/Album.java b/src/org/forkalsrud/album/exif/Album.java new file mode 100644 index 0000000..e004243 --- /dev/null +++ b/src/org/forkalsrud/album/exif/Album.java @@ -0,0 +1,84 @@ +/** + * + */ +package org.forkalsrud.album.exif; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +/** + * @author knut + * + */ +public class Album { + + Entry cover; + + List contents = new ArrayList(); + + public Entry getCover() { + return cover; + } + + + public List getContents() { + return contents; + } + + + public void setCover(Entry cover) { + this.cover = cover; + } + + + public void addContents(Entry entry) { + contents.add(entry); + } + + + + public void sort() { + + Collections.sort(contents, new Comparator() { + + public int compare(Entry e1, Entry e2) { + + if (!e1.isFile() && e2.isFile()) { + return -1; + } else if (e1.isFile() && !e2.isFile()) { + return +1; + } + Date d1 = e1.getDate(); + Date d2 = e2.getDate(); + if (d1 != null && d2 != null) { + return d1.compareTo(d2); + } else if (d1 != null) { + return -1; + } else if (d2 != null) { + return +1; + } else { + return 0; + } + } + }); + fillLinkedList(); + } + + void fillLinkedList() { + + Entry prev = null; + for (Entry e : contents) { + e.prev = prev; + if (prev != null) { + prev.next = e; + } + prev = e; + } + if (prev != null) { + prev.next = null; + } + } +} diff --git a/src/org/forkalsrud/album/exif/Entry.java b/src/org/forkalsrud/album/exif/Entry.java index e1a2874..193758c 100644 --- a/src/org/forkalsrud/album/exif/Entry.java +++ b/src/org/forkalsrud/album/exif/Entry.java @@ -15,8 +15,10 @@ import java.util.Date; */ public class Entry { - String name; - Dimension size; + boolean isFile; + String name; + String path; + Dimension size; String caption; Date date; int orientation; @@ -25,6 +27,17 @@ public class Entry { String etag; + public boolean isFile() { + return isFile; + } + + + public void setFile(boolean isFile) { + this.isFile = isFile; + } + + + /** * @return Returns the name. */ @@ -132,4 +145,15 @@ public class Entry { } + public String getPath() { + return path; + } + + + public void setPath(String path) { + this.path = path; + } + + + } diff --git a/src/org/forkalsrud/album/exif/EntryDao.java b/src/org/forkalsrud/album/exif/EntryDao.java index 393728f..858efd8 100644 --- a/src/org/forkalsrud/album/exif/EntryDao.java +++ b/src/org/forkalsrud/album/exif/EntryDao.java @@ -17,8 +17,6 @@ import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -54,7 +52,7 @@ public class EntryDao { return directory.lastModified() <= new File(directory, CACHE_FILE).lastModified(); } - public List read(File directory) throws FileNotFoundException, IOException, JpegProcessingException, MetadataException, ParseException { + public Album read(File directory) throws FileNotFoundException, IOException, JpegProcessingException, MetadataException, ParseException { List entries = new ArrayList(); @@ -73,46 +71,25 @@ public class EntryDao { Properties combined = new Properties(); combined.putAll(cachedProps); combined.putAll(overrideProps); - populate(combined, entries); - Collections.sort(entries, new Comparator() { + Entry cover = populate(combined, entries); - public int compare(Entry e1, Entry e2) { - - Date d1 = e1.getDate(); - Date d2 = e2.getDate(); - if (d1 != null && d2 != null) { - return d1.compareTo(d2); - } else if (d1 != null) { - return -1; - } else if (d2 != null) { - return +1; - } else { - return 0; - } - } - }); - fillLinkedList(entries); - return entries; - } - - void fillLinkedList(List entries) { - - Entry prev = null; + Album alb = new Album(); + alb.setCover(cover); for (Entry e : entries) { - e.prev = prev; - if (prev != null) { - prev.next = e; - } - prev = e; - } - if (prev != null) { - prev.next = null; + alb.addContents(e); } + generateDirectoryEntries(directory, alb); + alb.sort(); + return alb; } - private void populate(Properties cachedProps, List entries) throws ParseException { + + private Entry populate(Properties cachedProps, List entries) throws ParseException { + + Entry cover = null; + String coverFileName = cachedProps.getProperty("cover"); HashMap entryMap = new HashMap(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss"); Iterator i = cachedProps.keySet().iterator(); @@ -122,22 +99,28 @@ public class EntryDao { String name = key.substring("file.".length(), key.length() - ".dimensions".length()); if (!entryMap.containsKey(name)) { Entry entry = new Entry(); + entry.setFile(true); entry.setName(name); + entry.setPath(name); entry.setDate(sdf.parse(cachedProps.getProperty("file." + name + ".captureDate"))); entry.setSize(new Dimension(cachedProps.getProperty("file." + name + ".dimensions"))); entry.setCaption(cachedProps.getProperty("file." + name + ".caption")); entry.setOrientation(Integer.parseInt(cachedProps.getProperty("file." + name + ".orientation"))); entry.setEtag(cachedProps.getProperty("file." + name + ".etag")); entries.add(entry); + if (name != null && name.equals(coverFileName)) { + cover = entry; + } } } } + return cover; } public Entry readFile(File file) throws FileNotFoundException, IOException, JpegProcessingException, MetadataException, ParseException { - - List dir = read(file.getParentFile()); + + List dir = read(file.getParentFile()).getContents(); String name = file.getName(); for (Entry e : dir) { if (name.equals(e.name)) { @@ -149,11 +132,46 @@ public class EntryDao { void generateEntries(File directory, Properties cachedProps) throws JpegProcessingException, MetadataException, FileNotFoundException, IOException { - File[] files = directory.listFiles(new FileFilter() { + generateFileEntries(directory, cachedProps); + File dst = new File(directory, CACHE_FILE); + if (directory.canWrite()) { + cachedProps.store(new FileOutputStream(dst), "Extra Comments"); + } + } + + void generateDirectoryEntries(File directory, Album album) throws FileNotFoundException, JpegProcessingException, MetadataException, IOException, ParseException { + + File[] dirs = directory.listFiles(new FileFilter() { public boolean accept(File file) { - return !file.isHidden() && !file.isDirectory() && !CACHE_FILE.equals(file.getName()) && !OVERRIDE_FILE.equals(file.getName()); + return !file.isHidden() && file.isDirectory() && !CACHE_FILE.equals(file.getName()) && !OVERRIDE_FILE.equals(file.getName()); + } + + }); + for (File dir : dirs) { + + Album childAlbum = read(dir); + Entry childCover = childAlbum.getCover(); + if (childCover != null) { + childCover.setFile(false); + childCover.setName(dir.getName()); + childCover.setPath(dir.getName() + "/" + childCover.getPath()); + album.addContents(childCover); + } + } + } + + + void generateFileEntries(File directory, Properties cachedProps) + throws JpegProcessingException, MetadataException, IOException { + File[] files = directory.listFiles(new FileFilter() { + + public boolean accept(File file) { + + String name = file.getName(); + boolean isImageFile = name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".JPG"); + return isImageFile && !file.isHidden() && !file.isDirectory() && !CACHE_FILE.equals(file.getName()) && !OVERRIDE_FILE.equals(file.getName()); } }); @@ -213,11 +231,7 @@ public class EntryDao { } } } - File dst = new File(directory, CACHE_FILE); - if (directory.canWrite()) { - cachedProps.store(new FileOutputStream(dst), "Extra Comments"); - } - } + } Dimension decodeImageForDimensions(File file) throws IOException { diff --git a/src/org/forkalsrud/album/web/AlbumServlet.java b/src/org/forkalsrud/album/web/AlbumServlet.java index b3ab0a1..7402dc6 100644 --- a/src/org/forkalsrud/album/web/AlbumServlet.java +++ b/src/org/forkalsrud/album/web/AlbumServlet.java @@ -52,8 +52,13 @@ public class AlbumServlet pathInfo = pathInfo.substring(0, pathInfo.length() - ".photo".length()); page = "photo"; } + int parentPos = pathInfo.substring(0, pathInfo.length() - 1).lastIndexOf('/'); + if (parentPos >= 0) { + req.setAttribute("parent", req.getServletPath() + pathInfo.substring(0, parentPos) + "/"); + } + req.setAttribute("assets", "/" + req.getContextPath() + "assets"); File file = new File(basePath + pathInfo); -// System.out.println("path=" + file); +// System.out.println("path=" + req.getContextPath()); if (!file.canRead()) { res.setStatus(HttpServletResponse.SC_FORBIDDEN); return; @@ -61,7 +66,7 @@ public class AlbumServlet if (file.isDirectory()) { try { - List entries = dao.read(file); + List entries = dao.read(file).getContents(); res.setContentType("text/html"); req.setAttribute("directory", file.getName()); req.setAttribute("path", req.getServletPath()); @@ -169,7 +174,7 @@ public class AlbumServlet @Override public String getServletInfo() { - return "Display a directory as an org.forkalsrud.album"; + return "Display of org.forkalsrud.album"; } } diff --git a/webapp/WEB-INF/velocity/directory.vm b/webapp/WEB-INF/velocity/directory.vm index 79b7ad5..920d4fb 100644 --- a/webapp/WEB-INF/velocity/directory.vm +++ b/webapp/WEB-INF/velocity/directory.vm @@ -14,6 +14,9 @@ margin: 10px auto; text-align: center; } + h1 { + text-align: left; + } a:link, a:visited { text-decoration: none; color: #4c4c4c; @@ -30,18 +33,27 @@ img { padding: 5px; } + .nav { + border: 0 none; + padding: 0px; + vertical-align: middle; + } -

$directory

-
+

#if($prev && $prev.isFile())#else#end#if($parent)#else#end#if($next && $next.isFile())#else#end$directory

+
#set($thmb = 150) #foreach($entry in $entries) #set($dim = $entry.size.scaled($thmb))
$entry.name
-
+#if($entry.isFile()) +
+#else +
+#end $!entry.caption
#end diff --git a/webapp/WEB-INF/velocity/photo.vm b/webapp/WEB-INF/velocity/photo.vm index bace66a..87a7c4b 100644 --- a/webapp/WEB-INF/velocity/photo.vm +++ b/webapp/WEB-INF/velocity/photo.vm @@ -14,6 +14,9 @@ margin: 10px auto; text-align: center; } + h1 { + text-align: left; + } a:link, a:visited { text-decoration: none; color: #4c4c4c; @@ -30,23 +33,21 @@ img { padding: 5px; } + .nav { + border: 0 none; + padding: 0px; + vertical-align: middle; + } -
-#if($prev) - <-- -#end -#if($next) - --> -#end -
- +

#if($prev && $prev.isFile())#else#end#if($parent)#else#end#if($next && $next.isFile())#else#end$entry.name

+
#set($thmb = 480) #set($dim = $entry.size.scaled($thmb))
- $entry.name
+

$!entry.caption
diff --git a/webapp/assets/left-inactive.png b/webapp/assets/left-inactive.png new file mode 100644 index 0000000..111f3a2 Binary files /dev/null and b/webapp/assets/left-inactive.png differ diff --git a/webapp/assets/left.png b/webapp/assets/left.png new file mode 100644 index 0000000..7249de6 Binary files /dev/null and b/webapp/assets/left.png differ diff --git a/webapp/assets/right-inactive.png b/webapp/assets/right-inactive.png new file mode 100644 index 0000000..bbf636e Binary files /dev/null and b/webapp/assets/right-inactive.png differ diff --git a/webapp/assets/right.png b/webapp/assets/right.png new file mode 100644 index 0000000..db48ef3 Binary files /dev/null and b/webapp/assets/right.png differ diff --git a/webapp/assets/up-inactive.png b/webapp/assets/up-inactive.png new file mode 100644 index 0000000..96283e0 Binary files /dev/null and b/webapp/assets/up-inactive.png differ diff --git a/webapp/assets/up.png b/webapp/assets/up.png new file mode 100644 index 0000000..e23378c Binary files /dev/null and b/webapp/assets/up.png differ