Putting the album content in its own panel.
[photos] / src / main / java / org / wamblee / photos / wicket / AlbumPanel.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.photos.wicket;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.logging.Logger;
22 import javax.inject.Inject;
23
24 import org.apache.wicket.PageParameters;
25 import org.apache.wicket.markup.html.WebMarkupContainer;
26 import org.apache.wicket.markup.html.basic.Label;
27 import org.apache.wicket.markup.html.image.Image;
28 import org.apache.wicket.markup.html.link.Link;
29 import org.apache.wicket.markup.html.panel.Panel;
30 import org.apache.wicket.markup.repeater.RepeatingView;
31 import org.apache.wicket.resource.ByteArrayResource;
32 import org.wamblee.photos.model.Album;
33 import org.wamblee.photos.model.Photo;
34 import org.wamblee.photos.model.PhotoEntry;
35 import org.wamblee.photos.model.plumbing.AuthorizedPhotos;
36
37 /**
38  * Homepage
39  */
40 public class AlbumPanel extends Panel {
41
42     private static final Logger LOGGER = Logger.getLogger(AlbumPanel.class.getName());
43
44     private static final long serialVersionUID = 1L;
45
46     @Inject
47     @AuthorizedPhotos
48     private transient Album authorized;
49
50     private class SerializableEntryLink extends Link {
51
52         private String path;
53
54         public SerializableEntryLink(String aId, String aPath) {
55             super(aId);
56             path = aPath;
57         }
58
59         @Override
60         public void onClick() {
61             System.out.println("Entry " + path + " was clicked");
62             PageParameters pars = new PageParameters();
63             pars.put("path", path);
64
65             setResponsePage(HomePage.class, pars);
66         }
67     }
68
69     private String path;
70
71     /**
72      * Constructor that is invoked when page is invoked without a session.
73      *
74      * @param parameters Page parameters
75      */
76     public AlbumPanel(String aId, final PageParameters parameters) throws Exception {
77         super(aId);
78
79         path = parameters.getString("path", "/");
80         if (!path.startsWith("/")) {
81             info("Invalid album '" + path + "', showing root album instead");
82             path = "/";
83         }
84
85         PhotoEntry current = authorized.getEntry(path);
86
87         if (current instanceof Photo) {
88             throw new RuntimeException("AlbumPanel can only show album: " + current.getClass().getName());
89         }
90
91         Album album = (Album) current;
92
93         int ientry = 0;
94         int irow = 0;
95         RepeatingView row = new RepeatingView("row");
96         add(row);
97         while (irow < 5 && ientry < album.size()) {
98             int icolumn = 0;
99             WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
100             row.add(columns);
101             RepeatingView column = new RepeatingView("column");
102             columns.add(column);
103             while (icolumn < 5 && ientry < album.size()) {
104                 WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
105                 column.add(thumbnail);
106
107                 final PhotoEntry entry = album.getEntry(ientry);
108                 Link link = new SerializableEntryLink("thumbnail", entry.getPath());
109                 thumbnail.add(link);
110                 ImageData data = getData(entry);
111
112                 // TODO very inefficient. all data is loaded when generating the page.
113                 link.add(new Image("image", new ByteArrayResource(data.getContentType(), data.getData())));
114
115                 link.add(new Label("name", album.getEntry(ientry).getId()));
116                 icolumn++;
117                 ientry++;
118             }
119             irow++;
120         }
121     }
122
123     public static final class ImageData {
124         private String contentType;
125         private byte[] data;
126
127         public ImageData(String aContentType, byte[] aData) {
128             contentType = aContentType;
129             data = aData;
130         }
131
132         public String getContentType() {
133             return contentType;
134         }
135
136         public byte[] getData() {
137             return data;
138         }
139     }
140
141     private ImageData getData(PhotoEntry aEntry) {
142         if (aEntry instanceof Photo) {
143             return getData((Photo) aEntry);
144         } else if (aEntry instanceof Album) {
145             return getData((Album) aEntry);
146         } else {
147             throw new RuntimeException("Unsupported type " + aEntry.getClass().getName());
148         }
149     }
150
151     private ImageData getData(Photo aPhoto) {
152         try (InputStream is = aPhoto.getThumbNail()) {
153             return new ImageData("image/jpeg", getBytes(is));
154         }
155         catch (IOException e) {
156             // to improve.
157             throw new RuntimeException("Cannot read photo", e);
158         }
159     }
160
161     private byte[] getBytes(InputStream is) throws IOException {
162         ByteArrayOutputStream bos = new ByteArrayOutputStream();
163         byte[] block = new byte[1024];
164         int n = is.read(block);
165         while (n > 0) {
166             bos.write(block, 0, n);
167             n = is.read(block);
168         }
169         return bos.toByteArray();
170     }
171
172     private ImageData getData(Album aAlbum) {
173         try (InputStream is = getClass().getResourceAsStream("folder.png")) {
174             return new ImageData("image/png", getBytes(is));
175         }
176         catch (IOException e) {
177             throw new RuntimeException("Cannot read album jpg", e);
178         }
179     }
180 }