Source code: jac/aspects/gui/web/AbstractCollection.java
1 /*
2 Copyright (C) 2001-2003 Laurent Martelli <laurent@aopsys.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
18 package jac.aspects.gui.web;
19
20 import jac.aspects.gui.*;
21 import jac.aspects.gui.FieldView;
22 import jac.core.Collaboration;
23 import jac.core.Wrappee;
24 import jac.core.rtti.ClassItem;
25 import jac.core.rtti.ClassRepository;
26 import jac.core.rtti.CollectionItem;
27 import jac.core.rtti.FieldItem;
28 import jac.core.rtti.MetaItem;
29 import jac.core.rtti.MethodItem;
30 import jac.util.Classes;
31 import jac.util.Log;
32 import java.io.PrintWriter;
33 import java.util.Collection;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Vector;
37 import java.util.HashMap;
38
39
40 public abstract class AbstractCollection extends AbstractView
41 implements CollectionListener, CollectionView
42 {
43 protected CollectionItem collection;
44 protected Object substance;
45 protected CollectionModel model;
46
47 MethodView addButton;
48 MethodView removeButton;
49
50 /* index of selected row (-1 if no row if selection is empty) */
51 int selected = -1;
52
53 /* indicates which column is chosen to sort list (-1 if no column
54 * is chosen) */
55 int sortColumn = -1;
56
57 /* number of rows to display on each page */
58 int rowsPerPage = 10;
59 /* do we split the collection in multiple pages */
60 boolean split;
61
62 /* do we show a column with row numbers */
63 boolean showRowNumbers;
64
65 /* current offset */
66 int startIndex = 0;
67
68 public AbstractCollection(ViewFactory factory, DisplayContext context,
69 CollectionItem collection, Object substance,
70 CollectionModel model) {
71 super(factory,context);
72
73 this.collection = collection;
74 this.substance = substance;
75 this.model = model;
76 this.rowsPerPage = GuiAC.getNumRowsPerPage(collection);
77 this.startIndex = GuiAC.getStartIndex(collection);
78 this.showRowNumbers = GuiAC.isShowRowNumbers(collection);
79 split = rowsPerPage>0;
80 sort();
81 }
82
83 public AbstractCollection() {
84 }
85
86 public void setSubstance(Object substance) {
87 this.substance = substance;
88 }
89
90 public CollectionModel getCollectionModel() {
91 return model;
92 }
93
94 /**
95 * Generate HTML code for a collection's event (add, remove, ...)
96 * @param out write HTML to this writer
97 * @param event name of the associated event
98 * @param icon name of icon resource to display
99 * @param label text to display
100 */
101 void genCollectionEvent(PrintWriter out,
102 String event,
103 String icon,
104 String label) {
105
106 JacRequest request = ((WebDisplay)context.getDisplay()).getRequest();
107 if (request.isIEUserAgent()) {
108 out.println(
109 "<table class=\"method\"><td>"+
110 iconElement(ResourceManager.getResource(icon),"")+
111 eventURL(label,event,"").toString()+
112 "</td></table>");
113 } else {
114 out.println(
115 "<span class=\"method\">"+
116 iconElement(ResourceManager.getResource(icon),"")+
117 eventURL(label,event,"").toString()+
118 "</span>");
119 }
120 }
121
122 /**
123 * Sorts the collection with the column index stored in the context
124 * if any.
125 */
126 public abstract void sort();
127
128 public void onView(Object object) {
129 Log.trace("gui.events",toString()+".onView("+object+")");
130 selected = model.indexOf(object);
131
132 // used for CollectionItemView
133 CollectionPosition extra = new CollectionPosition(
134 this,
135 collection,selected,substance);
136
137 EventHandler.get().onSelection(context,collection,object,
138 null,extra,true);
139 }
140
141 // HTMLViewer interface
142
143 /**
144 * Generate HTML for adder, remover, and prev/next buttons
145 * @param out print HTML code to this writer
146 */
147 protected void genAdderAndRemover(PrintWriter out) {
148 boolean addable = GuiAC.isAddable(substance,collection);
149 boolean removable = GuiAC.isRemovable(substance,collection);
150 if (!(addable ||
151 (model.getRowCount()>0 && removable) ||
152 (startIndex>0) ||
153 (split && startIndex+rowsPerPage<model.getRowCount()))) {
154 return;
155 }
156 out.println("<div class=\"methods\">");
157 if (addable) {
158 if (GuiAC.isAutoCreate(collection)) {
159 genCollectionEvent(out,"onAddToCollection","new_icon",GuiAC.getLabelAdd());
160 /*
161 genCollectionEvent(out,"onAddToCollection","new_icon","add new");
162 genCollectionEvent(out,"onAddExistingToCollection","new_icon","add existing");
163 */
164 } else {
165 genCollectionEvent(out,"onAddToCollection","new_icon",GuiAC.getLabelAdd());
166 }
167 }
168 // removed this because does not work fine
169 /*if ( model.getRowCount()>0 && GuiAC.isRemovable(collection)) {
170 genCollectionEvent(out,"onRemoveFromCollection","remove_icon","remove");
171 }*/
172 if (startIndex>0) {
173 out.println("<a href=\""+eventURL("onFirst")+"\">"+
174 iconElement(ResourceManager.getResource("first_icon"),"first")+
175 "</a>");
176 out.println("<a href=\""+eventURL("onPrevious")+"\">"+
177 iconElement(ResourceManager.getResource("previous_icon"),"previous")+
178 "</a>");
179 }
180 if (model.getRowCount()>0 && (startIndex>0 || startIndex+rowsPerPage<model.getRowCount())) {
181 out.println("["+(startIndex+1)+"-"+
182 Math.min(startIndex+rowsPerPage,model.getRowCount())+"/"+
183 model.getRowCount()+"]");
184 }
185 if (split && startIndex+rowsPerPage<model.getRowCount()) {
186 out.println("<a href=\""+eventURL("onNext")+"\">"+
187 iconElement(ResourceManager.getResource("next_icon"),"next")+
188 "</a></span>");
189 out.println("<a href=\""+eventURL("onLast")+"\">"+
190 iconElement(ResourceManager.getResource("last_icon"),"last")+
191 "</a></span>");
192 }
193 if (split && model.getRowCount()>rowsPerPage) {
194 out.println("["+(startIndex/rowsPerPage+1)+"/"+
195 (int)Math.ceil((float)model.getRowCount()/(float)rowsPerPage)+"]");
196 }
197
198 out.println("</div>");
199 }
200
201 // CollectionView interface
202
203 public void setSelected(int index) {
204 selected = index;
205 }
206
207 public void setField(FieldItem field) {
208 collection = (CollectionItem)field;
209 }
210
211 public FieldItem getField() {
212 return collection;
213 }
214
215 public void setValue(Object value) {
216 }
217
218 public void updateModel(Object substance) {
219 }
220
221 // CollectionListener interface
222
223 public void onView(int index) {
224 Log.trace("gui.events",toString()+".onView("+index+")");
225 selected = index;
226
227 // used for CollectionItemView
228 CollectionPosition extra = new CollectionPosition(
229 this,
230 collection,index,substance);
231
232 EventHandler.get().onSelection(context,collection,model.getObject(index),
233 null,extra,true);
234 }
235
236 public void onRemove(int index) {
237 Log.trace("gui.events",toString()+".onRemove("+index+")");
238 Object toRemove = model.getObject(index);
239
240 EventHandler.get()
241 .onRemoveFromCollection(context, substance, collection, toRemove);
242 }
243
244 public void onTableInvoke(int index,String methodName) {
245 Log.trace("gui.events",toString()+".onTableInvoke("+index+")");
246 selected = index;
247 EventHandler.get().onInvoke(
248 context,model.getObject(index),
249 ClassRepository.get().getClass(model.getObject(index))
250 .getMethod(methodName));
251 }
252
253 public void onAddToCollection() {
254 EventHandler.get().onAddToCollection(context,substance,collection,false);
255 sort();
256 }
257
258 public void onAddExistingToCollection() {
259 EventHandler.get().onAddToCollection(context,substance,collection,true);
260 sort();
261 }
262
263 public void onRemoveFromCollection() {
264 EventHandler.get().onRemoveFromCollection(context,substance,collection);
265 sort();
266 }
267
268 public void onNext() {
269 if (startIndex+rowsPerPage<model.getRowCount())
270 startIndex += rowsPerPage;
271 context.getDisplay().refresh();
272 }
273
274 public void onLast() {
275 startIndex = model.getRowCount() - model.getRowCount()%rowsPerPage;
276 if (startIndex==model.getRowCount())
277 startIndex -= rowsPerPage;
278 context.getDisplay().refresh();
279 }
280
281 public void onPrevious() {
282 startIndex -= rowsPerPage;
283 if (startIndex<0)
284 startIndex = 0;
285 context.getDisplay().refresh();
286 }
287
288 public void onFirst() {
289 startIndex = 0;
290 context.getDisplay().refresh();
291 }
292
293 /**
294 * Returns an HTML link to remove the element at a given position.
295 */
296 protected String removeLink(int position) {
297 // We should use eventURL
298 return "<a href=\""+eventURL("onRemove")+
299 "&index="+position+"\">"+
300 iconElement(ResourceManager.getResource("remove_icon"),"remove")+"</a>";
301 }
302
303 protected String viewLink(int position) {
304 // We should use eventURL
305 return "<a href=\""+eventURL("onView")+
306 "&index="+position+"\">"+
307 iconElement(ResourceManager.getResource("view_icon"),"view")+"</a>";
308 }
309
310 /**
311 * Build an HTML link with an image showing if a column is used to
312 * sort the collection
313 * @param column the index of the column
314 * @param text additional text to put in the link
315 * @return the HTML code of the link
316 */
317 protected String sortLink(int column,String text) {
318 SortCriteria criteria = ((TableSorter)model).getSortCriteria(column);
319 String iconResource;
320 if (criteria==null) {
321 iconResource = "small_down_icon";
322 } else {
323 if (criteria.isAscending())
324 iconResource = "small_down_icon_selected";
325 else
326 iconResource = "small_up_icon_selected";
327 }
328 return
329 " <a href=\""+eventURL("onHeaderClick")+"&col="+column+"\""
330 + " title=\"sort\">"
331 + iconElement(ResourceManager.getResource(iconResource),"sort")
332 + " " + text
333 + "</a>";
334 }
335
336 }