From 9d2fb0ea6ee479c19d635c0abc303f0f07fc7e0a Mon Sep 17 00:00:00 2001 From: knut Date: Mon, 29 Dec 2008 01:13:02 +0000 Subject: [PATCH] Major overhaul of navigation. Now shows directories and navigation buttons. --- photos/portraits/album.properties | 2 + pom.xml | 2 +- src/org/forkalsrud/album/exif/Album.java | 84 ++++++++++++++ src/org/forkalsrud/album/exif/Entry.java | 28 ++++- src/org/forkalsrud/album/exif/EntryDao.java | 104 ++++++++++-------- .../forkalsrud/album/web/AlbumServlet.java | 11 +- webapp/WEB-INF/velocity/directory.vm | 18 ++- webapp/WEB-INF/velocity/photo.vm | 21 ++-- webapp/assets/left-inactive.png | Bin 0 -> 499 bytes webapp/assets/left.png | Bin 0 -> 540 bytes webapp/assets/right-inactive.png | Bin 0 -> 509 bytes webapp/assets/right.png | Bin 0 -> 550 bytes webapp/assets/up-inactive.png | Bin 0 -> 443 bytes webapp/assets/up.png | Bin 0 -> 511 bytes 14 files changed, 206 insertions(+), 64 deletions(-) create mode 100644 photos/portraits/album.properties create mode 100644 src/org/forkalsrud/album/exif/Album.java create mode 100644 webapp/assets/left-inactive.png create mode 100644 webapp/assets/left.png create mode 100644 webapp/assets/right-inactive.png create mode 100644 webapp/assets/right.png create mode 100644 webapp/assets/up-inactive.png create mode 100644 webapp/assets/up.png 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 0000000000000000000000000000000000000000..111f3a24a0aba63afb71cc18ada84288a82eb55f GIT binary patch literal 499 zcmVPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^SBGkWcpg8%>lg-Jv~R7l6| zmfLQFFc3tKfdFljCcUcv|9ib9Z39VxxG#fbxr7jhK2*v|7Q!n$o|#=^ILA5uFpS2p z$+02_7C;J=z$>t8lgS7Gi2&w6thp5U0JdWQMZgTW>sY4(8h@Vl%7G`9s2hzKEQc^S1T>cyu{U1;FTm!MW^3aDcu;?|u@OMoXY|mfbAci+pQ#wK zQ;(0>D}YN+P9v|TV&C{39|H6(skSnE;($hC+*VN+%n)wvR5HMMmg&NuJv?_CKi|xI~(FrvghLz zcod-jo2YPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^RrCtQWB#sB~Tu1Q2eR7l6| z)jvqpVHC#kk9tk1%)y2XG-@!4qQM%HaH^@PDS{#hq9$p!DVmKSXmo09%a)*~$kNH8 zBB&s!hW^+esHoK2axVOM`4!&#dxZucxXa~ozvn&AdCp-~s|t0j!2fll4NEIga2tkk z4Kuie^|>K~xQGv^$LA|{If2aLAZj@iK3>wUAGm?NF&xbdQpewx>L3oGtMFYd z!gmB4@ec2!h<~Y`{-y|efd`nwCu}J|*I@)l(T}J2lB<;ixDpF84e47P!Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^SBA`o4-aR2}Tk4Z#9R7l6| zmTOPKKoCXGcFRLVQKDb;|Nl9a_yVLryMDP%Ce6gq7KkQJ(lp(6_jK+&cEPv68SE^O ze>>QsGd2XqKn9ej0_DI1a0^`Nxd75BKyzhY23!c3^#wLTmBvOU%_A_;RRa4iKrcpX zT|;>ojJH#Hxfe9`0ilJKz*gQxQ_KU&Io0^~5Mcb_UD6_-l60t8)xccdjio@<6=Z>5 zz=xTW308Y}ZIr0Gf-GR z{KoQlRm0*Dy35XFXKuy^idjM9MHkD}u4X19?Yo(coKpqA1I{HE_C^?X5lED3YYnhX-b+BK&9%j{DqlRbCzAVDc+1G`54*mbC!=4H>@ySM_AF@fI|#00000NkvXXu0mjf?-kc) literal 0 HcmV?d00001 diff --git a/webapp/assets/right.png b/webapp/assets/right.png new file mode 100644 index 0000000000000000000000000000000000000000..db48ef3f1ab391b39068bef700f677169b24ec7b GIT binary patch literal 550 zcmV+>0@?kEP)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^Rr2WRVy4gdfFxJg7oR7l6| z);ntzQ4|H>Z^madibhQE*;#~WBNEUbU?mn}CD{1r6l_F-rM)OvY8$LlCkSd2D+NIj zR1gJ4M8yaOHLq*4FAT@IkYvu46s~TV$C|y)UTbguMu{F>Mu|24VVaH{&FpM@3b_-*}1t+5%(K;Xag?b zV?r>EvBaatzqItZBaY%q~@So zA>G*ymgvL2rPyT%-)f9Ef#D9a6wArBO}K@35s>$BF2__YI^Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^SC4LlT<=Kuf!O-V#SR7l6| zmf=pqKoEq#)=~>5280;({a?*!Vvr!#Qm~wVrpcyW=~Y1!Ws;_JyS>?&-MavP4QD;` zBVeGr>-%9SM!-x&4wwVWLo14b8z9r~7`RZOWr(^^q6C;W9EhYc1>U;ILW!nY)Q42p z>vxG}z*R@iK&p#2WnDyL5&2L8JFO9^e8ot6XiT)&n6z*^?gKzre>=iR4qrA@A%4rg{)rMK}kHx3vE8v zn6eP;R9vmh?IUuUC|cgNS!d&}&pzrp?fabky@|ezzCPx#32;bRa{vGf6951U69E94oEQKA00(qQO+^RT3>^Rr8U*d&*8l(kkx4{BR7l6| z)=x{6Q547Vk2A`Eq(-#}A*zkg%3eW>-a}hkxoh7l5J6~DYgg^uxe38to1loMMdBio zT(}4;LX1FBYsSqPxm;%+=b1*a=)i@0pZn)~?m6fFc=*?>T5|m`uE)Ne({N}2cTvX{ zHZXk}pfS8dGiiHxgbV!y-Nerf)Wk0=;z~at6+CSNN!#Cx4_$t;i_-kA%TV<12PY(HvPsw-*_pq74>hT1+vO5`MANL~{X5W=;884E#-*|WuXg15q60XKvCy*%d)WMJ8z)|Vuc01|6#}vNAxRJ~? zvVGq%huuW3Mv6eM@FQeq2HRPYwClHQ8BZcd&+zRe;k<<#ZA7;ybS)bSSsF?|4z^ji zgAW}JDGFW74x$~Cm$L7xD0GE7b}m8PgzoRU(f`n$e^9eSzwe;hS>-7G0og3Gaj+z4 z855!I3%w?{o7>kg9>V*zZ1~E6Dv5*DvXyrxb_lCPg@m=Cuzdgk002ovPDHLkV1kQp B;0pi% literal 0 HcmV?d00001