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 Link nextLink = new Link("nextLink") {
126 if (index + MAX_ROWS * MAX_COLUMNS >= album.size()) {
132 public void onClick() {
133 PageParameters pars = new PageParameters();
134 pars.put("path", path);
135 pars.put("index", index + MAX_ROWS * MAX_COLUMNS);
136 setResponsePage(HomePage.class, pars);
141 Link parentLink = new Link("parentLink") {
143 if ("/".equals(path)) {
149 public void onClick() {
150 PageParameters pars = new PageParameters();
151 String parentPath = path.substring(0, path.lastIndexOf("/"));
152 if (parentPath.length() == 0) {
155 pars.put("path", parentPath);
156 pars.put("index", 0);
157 setResponsePage(HomePage.class, pars);
162 RepeatingView pageLinks = new RepeatingView("pageLinks");
164 for (int i = 0; i < album.size() / MAX_ROWS / MAX_COLUMNS; i++) {
165 final int istart = i * MAX_ROWS * MAX_COLUMNS;
166 Link pageLink = new Link("pageLink") {
168 if (istart == index) {
174 public void onClick() {
175 PageParameters pars = new PageParameters();
176 pars.put("path", path);
177 pars.put("index", istart);
178 setResponsePage(HomePage.class, pars);
181 pageLink.add(new Label("label", i + ""));
182 pageLinks.add(pageLink);
183 WebMarkupContainer container = new WebMarkupContainer(pageLinks.newChildId());
184 container.add(pageLink);
185 pageLinks.add(container);
190 RepeatingView row = new RepeatingView("row");
192 while (irow < MAX_ROWS && ientry < album.size()) {
194 WebMarkupContainer columns = new WebMarkupContainer(row.newChildId());
196 RepeatingView column = new RepeatingView("column");
198 while (icolumn < MAX_COLUMNS && ientry < album.size()) {
199 WebMarkupContainer thumbnail = new WebMarkupContainer(column.newChildId());
200 column.add(thumbnail);
202 final PhotoEntry entry = album.getEntry(ientry);
203 Link link = new SerializableEntryLink("thumbnail", entry.getPath());
205 ImageData data = getData(entry);
207 // TODO very inefficient. all data is loaded when generating the page.
208 link.add(new Image("image", new ByteArrayResource(data.getContentType(), data.getData())));
210 link.add(new Label("name", album.getEntry(ientry).getId()));
218 public static final class ImageData {
219 private String contentType;
222 public ImageData(String aContentType, byte[] aData) {
223 contentType = aContentType;
227 public String getContentType() {
231 public byte[] getData() {
236 private ImageData getData(PhotoEntry aEntry) {
237 if (aEntry instanceof Photo) {
238 return getData((Photo) aEntry);
239 } else if (aEntry instanceof Album) {
240 return getData((Album) aEntry);
242 throw new RuntimeException("Unsupported type " + aEntry.getClass().getName());
246 private ImageData getData(Photo aPhoto) {
247 try (InputStream is = aPhoto.getThumbNail()) {
248 return new ImageData("image/jpeg", getBytes(is));
250 catch (IOException e) {
252 throw new RuntimeException("Cannot read photo", e);
256 private byte[] getBytes(InputStream is) throws IOException {
257 ByteArrayOutputStream bos = new ByteArrayOutputStream();
258 byte[] block = new byte[1024];
259 int n = is.read(block);
261 bos.write(block, 0, n);
264 return bos.toByteArray();
267 private ImageData getData(Album aAlbum) {
268 try (InputStream is = getClass().getResourceAsStream("folder.png")) {
269 return new ImageData("image/png", getBytes(is));
271 catch (IOException e) {
272 throw new RuntimeException("Cannot read album jpg", e);