2 * Copyright 2005-2010 the original author or authors.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.wamblee.photos.wicket;
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;
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;
40 public class AlbumPanel extends Panel {
42 private static final Logger LOGGER = Logger.getLogger(AlbumPanel.class.getName());
44 private static final long serialVersionUID = 1L;
45 public static final int MAX_ROWS = 5;
46 public static final int MAX_COLUMNS = 5;
50 private transient Album authorized;
52 private class SerializableEntryLink extends Link {
56 public SerializableEntryLink(String aId, String aPath) {
62 public void onClick() {
63 System.out.println("Entry " + path + " was clicked");
64 PageParameters pars = new PageParameters();
65 pars.put("path", path);
67 setResponsePage(HomePage.class, pars);
75 * Constructor that is invoked when page is invoked without a session.
77 * @param parameters Page parameters
79 public AlbumPanel(String aId, final PageParameters parameters) throws Exception {
82 path = parameters.getString("path", "/");
83 if (!path.startsWith("/")) {
84 info("Invalid album '" + path + "', showing root album instead");
87 add(new Label("path", path));
90 String indexString = parameters.getString("index", "0");
92 index = Integer.parseInt(indexString);
94 catch (NumberFormatException e) {
95 // use default value 0
101 PhotoEntry current = authorized.getEntry(path);
102 if (current instanceof Photo) {
103 throw new RuntimeException("AlbumPanel can only show album: " + current.getClass().getName());
105 final Album album = (Album) current;
107 Link prevLink = new Link("prevLink") {
109 if (index - MAX_ROWS * MAX_COLUMNS < 0) {
115 public void onClick() {
116 PageParameters pars = new PageParameters();
117 pars.put("path", path);
118 pars.put("index", index - MAX_ROWS * MAX_COLUMNS);
119 setResponsePage(HomePage.class, pars);
124 // Avoid implicit references to the album to keep the link objects
125 // small and serializable.
126 final int albumSize = album.size();
127 Link nextLink = new Link("nextLink") {
129 if (index + MAX_ROWS * MAX_COLUMNS >= albumSize) {
135 public void onClick() {
136 PageParameters pars = new PageParameters();
137 pars.put("path", path);
138 pars.put("index", index + MAX_ROWS * MAX_COLUMNS);
139 setResponsePage(HomePage.class, pars);
144 Link parentLink = new Link("parentLink") {
146 if ("/".equals(path)) {
152 public void onClick() {
153 PageParameters pars = new PageParameters();
154 String parentPath = path.substring(0, path.lastIndexOf("/"));
155 if (parentPath.length() == 0) {
158 pars.put("path", parentPath);
159 pars.put("index", 0);
160 setResponsePage(HomePage.class, pars);
165 RepeatingView pageLinks = new RepeatingView("pageLinks");
167 for (int i = 0; i < album.size() / MAX_ROWS / MAX_COLUMNS; i++) {
168 final int istart = i * MAX_ROWS * MAX_COLUMNS;
169 Link pageLink = new Link("pageLink") {
171 if (istart == index) {
177 public void onClick() {
178 PageParameters pars = new PageParameters();
179 pars.put("path", path);
180 pars.put("index", istart);
181 setResponsePage(HomePage.class, pars);
184 pageLink.add(new Label("label", i + ""));
185 pageLinks.add(pageLink);
186 WebMarkupContainer container = new WebMarkupContainer(pageLinks.newChildId());
187 container.add(pageLink);
188 pageLinks.add(container);
193 RepeatingView row = new RepeatingView("row");
195 while (irow < MAX_ROWS && ientry < album.size()) {
197 WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
199 RepeatingView column = new RepeatingView("column");
201 while (icolumn < MAX_COLUMNS && ientry < album.size()) {
202 WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
203 column.add(thumbnail);
205 final PhotoEntry entry = album.getEntry(ientry);
206 Link link = new SerializableEntryLink("thumbnail", entry.getPath());
208 ImageData data = getData(entry);
210 // TODO very inefficient. all data is loaded when generating the page.
211 link.add(new Image("image", new ByteArrayResource(data.getContentType(), data.getData())));
213 link.add(new Label("name", album.getEntry(ientry).getId()));
221 public static final class ImageData {
222 private String contentType;
225 public ImageData(String aContentType, byte[] aData) {
226 contentType = aContentType;
230 public String getContentType() {
234 public byte[] getData() {
239 private ImageData getData(PhotoEntry aEntry) {
240 if (aEntry instanceof Photo) {
241 return getData((Photo) aEntry);
242 } else if (aEntry instanceof Album) {
243 return getData((Album) aEntry);
245 throw new RuntimeException("Unsupported type " + aEntry.getClass().getName());
249 private ImageData getData(Photo aPhoto) {
250 try (InputStream is = aPhoto.getThumbNail()) {
251 return new ImageData("image/jpeg", getBytes(is));
253 catch (IOException e) {
255 throw new RuntimeException("Cannot read photo", e);
259 private byte[] getBytes(InputStream is) throws IOException {
260 ByteArrayOutputStream bos = new ByteArrayOutputStream();
261 byte[] block = new byte[1024];
262 int n = is.read(block);
264 bos.write(block, 0, n);
267 return bos.toByteArray();
270 private ImageData getData(Album aAlbum) {
271 try (InputStream is = getClass().getResourceAsStream("folder.png")) {
272 return new ImageData("image/png", getBytes(is));
274 catch (IOException e) {
275 throw new RuntimeException("Cannot read album jpg", e);