Corrected page numbering.
[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.Serializable;
19 import java.util.logging.Logger;
20 import javax.inject.Inject;
21 import javax.servlet.ServletContext;
22
23 import org.apache.wicket.PageParameters;
24 import org.apache.wicket.markup.ComponentTag;
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.wamblee.general.ValueHolder;
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     public static class MyValueHolder<T extends Serializable> extends ValueHolder<T> implements Serializable {
43         public MyValueHolder(T aValue) {
44             super(aValue);
45         }
46
47         public MyValueHolder() {
48             super();
49         }
50     }
51
52     private static final Logger LOGGER = Logger.getLogger(AlbumPanel.class.getName());
53
54     private static final long serialVersionUID = 1L;
55     public static final int MAX_ROWS = 5;
56     public static final int MAX_COLUMNS = 5;
57
58     @Inject
59     @AuthorizedPhotos
60     private transient Album authorized;
61
62     @Inject
63     private ServletContext context;
64
65     private class SerializableEntryLink extends Link {
66
67         private String path;
68
69         public SerializableEntryLink(String aId, String aPath) {
70             super(aId);
71             path = aPath;
72         }
73
74         @Override
75         public void onClick() {
76             PageParameters pars = new PageParameters();
77             pars.put("path", path);
78
79             setResponsePage(HomePage.class, pars);
80         }
81     }
82
83     private String path;
84     private int index;
85
86     /**
87      * Constructor that is invoked when page is invoked without a session.
88      *
89      * @param parameters Page parameters
90      */
91     public AlbumPanel(String aId, final PageParameters parameters) throws Exception {
92         super(aId);
93
94         path = parameters.getString("path", "/");
95         if (!path.startsWith("/")) {
96             info("Invalid album '" + path + "', showing root album instead");
97             path = "/";
98         }
99         add(new Label("path", path));
100
101         index = 0;
102         String indexString = parameters.getString("index", "0");
103         try {
104             index = Integer.parseInt(indexString);
105         }
106         catch (NumberFormatException e) {
107             // use default value 0
108         }
109         if (index < 0) {
110             index = 0;
111         }
112
113         Link prevLink = new Link("prevLink") {
114             @Override
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);
120             }
121
122             @Override
123             public boolean isEnabled() {
124                 return index - MAX_ROWS * MAX_COLUMNS >= 0;
125             }
126         };
127         add(prevLink);
128
129         // Avoid implicit references to the album to keep the link objects
130         // small and serializable.
131         final int albumSize = getAlbum().size();
132         Link nextLink = new Link("nextLink") {
133             @Override
134             public void onClick() {
135                 PageParameters pars = new PageParameters();
136                 pars.put("path", path);
137                 pars.put("index", index + MAX_ROWS * MAX_COLUMNS);
138                 setResponsePage(HomePage.class, pars);
139             }
140
141             @Override
142             public boolean isEnabled() {
143                 return index + MAX_ROWS * MAX_COLUMNS < albumSize;
144             }
145         };
146         add(nextLink);
147
148         Link parentLink = new Link("parentLink") {
149             {
150                 if ("/".equals(path)) {
151                     setEnabled(false);
152                 }
153             }
154
155             @Override
156             public void onClick() {
157                 PageParameters pars = new PageParameters();
158                 String parentPath = path.substring(0, path.lastIndexOf("/"));
159                 if (parentPath.length() == 0) {
160                     parentPath = "/";
161                 }
162                 pars.put("path", parentPath);
163                 pars.put("index", 0);
164                 setResponsePage(HomePage.class, pars);
165             }
166         };
167         add(parentLink);
168
169         RepeatingView pageLinks = new RepeatingView("pageLinks");
170         add(pageLinks);
171         Album album = getAlbum();
172         for (int i = 0; i < (album.size() + MAX_ROWS * MAX_COLUMNS - 1) / MAX_ROWS / MAX_COLUMNS; i++) {
173             final int istart = i * MAX_ROWS * MAX_COLUMNS;
174             Link pageLink = new Link("pageLink") {
175                 {
176                     if (istart == index) {
177                         setEnabled(false);
178                     }
179                 }
180
181                 @Override
182                 public void onClick() {
183                     PageParameters pars = new PageParameters();
184                     pars.put("path", path);
185                     pars.put("index", istart);
186                     setResponsePage(HomePage.class, pars);
187                 }
188             };
189             pageLink.add(new Label("label", (i + 1) + ""));
190             pageLinks.add(pageLink);
191             WebMarkupContainer container = new WebMarkupContainer(pageLinks.newChildId());
192             container.add(pageLink);
193             pageLinks.add(container);
194         }
195
196         RepeatingView row = new RepeatingView("row") {
197             @Override
198             protected void onPopulate() {
199                 removeAll();
200                 final ValueHolder<Integer> ientry = new MyValueHolder<Integer>(index);
201                 int irow = 0;
202                 Album album = getAlbum();
203                 while (irow < MAX_ROWS && ientry.getValue() < album.size()) {
204                     WebMarkupContainer columns = new WebMarkupContainer(newChildId());
205                     add(columns);
206                     RepeatingView column = new RepeatingView("column") {
207                         @Override
208                         protected void onPopulate() {
209                             removeAll();
210                             int icolumn = 0;
211                             Album album = getAlbum();
212                             while (icolumn < MAX_COLUMNS && ientry.getValue() < album.size()) {
213                                 WebMarkupContainer thumbnail = new WebMarkupContainer(newChildId());
214                                 add(thumbnail);
215
216                                 final PhotoEntry entry = album.getEntry(ientry.getValue());
217                                 Link link = new SerializableEntryLink("thumbnail", entry.getPath());
218                                 thumbnail.add(link);
219
220                                 final ValueHolder<String> pathinfo = new MyValueHolder<String>();
221                                 if (entry instanceof Photo) {
222                                     pathinfo.setValue("/image/thumbnail/" + entry.getPath());
223                                 } else {
224                                     pathinfo.setValue("/image/resource/folder.png");
225                                 }
226                                 link.add(new Image("image") {
227                                     @Override
228                                     protected void onComponentTag(ComponentTag tag) {
229                                         tag.put("src", context.getContextPath() + pathinfo.getValue());
230                                     }
231                                 });
232
233                                 link.add(new Label("name", album.getEntry(ientry.getValue()).getId()));
234                                 icolumn++;
235                                 ientry.setValue(ientry.getValue() + 1);
236                             }
237                         }
238                     };
239                     columns.add(column);
240                     irow++;
241                 }
242             }
243         };
244
245         add(row);
246
247         // upload panel
248         if (path.equals("/")) {
249             add(new WebMarkupContainer("uploadPanel"));
250             add(new WebMarkupContainer("createFolderPanel"));
251         } else {
252             add(new UploadPanel("uploadPanel", path));
253             add(new CreateFolderPanel("createFolderPanel", path));
254         }
255     }
256
257     private Album getAlbum() {
258         PhotoEntry current = authorized.getEntry(path);
259         if (current instanceof Photo) {
260             throw new RuntimeException("AlbumPanel can only show album: " + current.getClass().getName());
261         }
262         return (Album) current;
263     }
264 }