001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Alexandre Russel 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.platform.annotations.gwt.client.view; 021 022import java.util.HashMap; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Map; 026import java.util.Set; 027 028import org.nuxeo.ecm.platform.annotations.gwt.client.annotea.RDFConstant; 029import org.nuxeo.ecm.platform.annotations.gwt.client.configuration.AnnotationDefinition; 030import org.nuxeo.ecm.platform.annotations.gwt.client.configuration.AnnotationFilter; 031import org.nuxeo.ecm.platform.annotations.gwt.client.configuration.WebConfiguration; 032import org.nuxeo.ecm.platform.annotations.gwt.client.configuration.filter.InMenuFilter; 033import org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController; 034import org.nuxeo.ecm.platform.annotations.gwt.client.model.Annotation; 035import org.nuxeo.ecm.platform.annotations.gwt.client.model.AnnotationChangeListener; 036import org.nuxeo.ecm.platform.annotations.gwt.client.model.AnnotationModel; 037import org.nuxeo.ecm.platform.annotations.gwt.client.util.AnnotationUtils; 038import org.nuxeo.ecm.platform.annotations.gwt.client.view.i18n.TranslationConstants; 039import org.nuxeo.ecm.platform.annotations.gwt.client.view.i18n.TranslationMessages; 040 041import com.google.gwt.core.client.GWT; 042import com.google.gwt.user.client.Window; 043import com.google.gwt.user.client.ui.ChangeListener; 044import com.google.gwt.user.client.ui.ClickListener; 045import com.google.gwt.user.client.ui.Frame; 046import com.google.gwt.user.client.ui.Grid; 047import com.google.gwt.user.client.ui.HTML; 048import com.google.gwt.user.client.ui.HorizontalPanel; 049import com.google.gwt.user.client.ui.Image; 050import com.google.gwt.user.client.ui.Label; 051import com.google.gwt.user.client.ui.ListBox; 052import com.google.gwt.user.client.ui.PushButton; 053import com.google.gwt.user.client.ui.VerticalPanel; 054import com.google.gwt.user.client.ui.Widget; 055 056/** 057 * @author Alexandre Russel 058 */ 059public class AnnotationManagerPanel extends VerticalPanel implements AnnotationChangeListener { 060 061 private static final String CLASS_NAME = "annotationManagerPanel"; 062 063 private final WebConfiguration webConfiguration; 064 065 private AnnotationController controller; 066 067 private AnnotationModel model; 068 069 private VerticalPanel shownAnnotation = new VerticalPanel(); 070 071 private Map<String, Integer> selectedParams = new HashMap<String, Integer>(); 072 073 private HorizontalPanel selectedRow; 074 075 public AnnotationManagerPanel(AnnotationController controller, WebConfiguration webConfiguration) { 076 this.controller = controller; 077 this.webConfiguration = webConfiguration; 078 079 setStyleName(CLASS_NAME); 080 } 081 082 public void onChange(AnnotationModel model, ChangeEvent ce) { 083 this.model = model; 084 if (ce == ChangeEvent.annotationList) { 085 update(); 086 } 087 } 088 089 private void update() { 090 clear(); 091 addAnnotationsActionList(); 092 addFiltersToolbar(); 093 addAnnotationsList(); 094 } 095 096 private void addFiltersToolbar() { 097 HorizontalPanel toolBar = new HorizontalPanel(); 098 List<AnnotationFilter> filters = webConfiguration.getFilters(); 099 for (final AnnotationFilter filter : filters) { 100 PushButton button = new PushButton(new Image(filter.getIcon()), new ClickListener() { 101 public void onClick(Widget sender) { 102 model.setFilter(filter); 103 } 104 }); 105 button.setTitle(filter.getName()); 106 toolBar.add(button); 107 } 108 109 Label spacer = new Label(" "); 110 toolBar.add(spacer); 111 toolBar.setCellWidth(spacer, "100%"); 112 113 List<AnnotationDefinition> inMenuAnnos = webConfiguration.getAnnotationDefinitions(new InMenuFilter()); 114 TranslationMessages translationMessages = GWT.create(TranslationMessages.class); 115 for (AnnotationDefinition annotationDef : inMenuAnnos) { 116 final String annName = annotationDef.getName(); 117 PushButton button = new PushButton(new Image(annotationDef.getListIcon()), new ClickListener() { 118 public void onClick(Widget sender) { 119 new AnnotationListPopup(annName, model.filterAnnotations(new AnnotationFilter("", "", annName, 120 null, null)), webConfiguration).show(); 121 } 122 }); 123 button.setTitle(translationMessages.viewAnnotations(annotationDef.getName())); 124 toolBar.add(button); 125 } 126 for (AnnotationDefinition annotationDef : inMenuAnnos) { 127 final String annName = annotationDef.getName(); 128 final String annType = annotationDef.getType(); 129 PushButton button = new PushButton(new Image(annotationDef.getCreateIcon()), new ClickListener() { 130 public void onClick(Widget sender) { 131 controller.createNewAnnotation("#xpointer(null-range)"); 132 NewAnnotationPopup popup = new NewAnnotationPopup(null, controller, false, annType, annName); 133 popup.show(); 134 135 } 136 }); 137 button.setTitle(translationMessages.addAnnotation(annotationDef.getName())); 138 toolBar.add(button); 139 } 140 add(toolBar); 141 142 final AnnotationFilter currentFilter = model.getFilter(); 143 if (currentFilter != null && !currentFilter.getParameters().isEmpty()) { 144 List<String> parameters = currentFilter.getParameters(); 145 Map<String, String> labels = webConfiguration.getFieldLabels(); 146 Grid filterGrid = new Grid(parameters.size(), 2); 147 filterGrid.setStyleName("filterGrid"); 148 filterGrid.getColumnFormatter().setWidth(1, "100%"); 149 for (int i = 0; i < parameters.size(); i++) { 150 final String parameter = parameters.get(i); 151 152 filterGrid.setWidget(i, 0, new Label( 153 (labels.containsKey(parameter) ? labels.get(parameter) : parameter) + ": ")); 154 final ListBox filterListBox = new ListBox(); 155 filterListBox.setStyleName("filterListBox"); 156 filterListBox.addItem("All"); 157 Set<String> values = new HashSet<String>(); 158 for (Annotation annotation : model.getUnfilteredAnnotations()) { 159 if (parameter.equals(RDFConstant.R_TYPE)) { 160 values.add(annotation.getShortType()); 161 } else if (parameter.equals(RDFConstant.D_CREATOR)) { 162 values.add(annotation.getAuthor()); 163 } else { 164 String value = annotation.getFields().get(parameter); 165 if (value != null) { 166 values.add(value); 167 } 168 } 169 } 170 for (String value : values) { 171 filterListBox.addItem(value); 172 } 173 if (selectedParams.containsKey(parameter)) { 174 filterListBox.setSelectedIndex(selectedParams.get(parameter).intValue()); 175 } 176 if (parameter.equals(RDFConstant.R_TYPE)) { 177 filterListBox.addChangeListener(new ChangeListener() { 178 public void onChange(Widget arg0) { 179 int selectedIndex = filterListBox.getSelectedIndex(); 180 if (selectedIndex == 0) { 181 currentFilter.setType(null); 182 } else { 183 currentFilter.setType(filterListBox.getItemText(selectedIndex)); 184 } 185 selectedParams.put(parameter, Integer.valueOf(selectedIndex)); 186 model.setFilter(currentFilter); 187 } 188 }); 189 } else if (parameter.equals(RDFConstant.D_CREATOR)) { 190 filterListBox.addChangeListener(new ChangeListener() { 191 public void onChange(Widget arg0) { 192 int selectedIndex = filterListBox.getSelectedIndex(); 193 if (selectedIndex == 0) { 194 currentFilter.setAuthor(null); 195 } else { 196 currentFilter.setAuthor(filterListBox.getItemText(selectedIndex)); 197 } 198 selectedParams.put(parameter, Integer.valueOf(selectedIndex)); 199 model.setFilter(currentFilter); 200 } 201 }); 202 } else { 203 filterListBox.addChangeListener(new ChangeListener() { 204 public void onChange(Widget arg0) { 205 int selectedIndex = filterListBox.getSelectedIndex(); 206 if (selectedIndex == 0) { 207 currentFilter.removeField(parameter); 208 } else { 209 currentFilter.setField(parameter, filterListBox.getItemText(selectedIndex)); 210 } 211 selectedParams.put(parameter, Integer.valueOf(selectedIndex)); 212 model.setFilter(currentFilter); 213 } 214 }); 215 } 216 filterGrid.setWidget(i, 1, filterListBox); 217 } 218 add(filterGrid); 219 } 220 } 221 222 private void addAnnotationsActionList() { 223 add(new AnnotationActionsBanner(controller)); 224 } 225 226 private void addAnnotationsList() { 227 HorizontalPanel hpSelected = null; 228 int selectedAnnotationIndex = -1; 229 230 VerticalPanel vp = new VerticalPanel(); 231 vp.setStylePrimaryName("annotation-list"); 232 final List<Annotation> annotations = model.getAnnotations(); 233 for (int y = 0; y < annotations.size(); y++) { 234 final int row = y; 235 Annotation annotation = annotations.get(y); 236 final HorizontalPanel hp = new HorizontalPanel(); 237 hp.setWidth("100%"); 238 AnnotationDefinition def = webConfiguration.getAnnotationDefinition(annotation.getShortType()); 239 240 Image icon = new Image(def.getIcon()); 241 icon.addClickListener(new ClickListener() { 242 public void onClick(Widget sender) { 243 updateSelectedAnnotation(row); 244 selectAnnotation(hp, row); 245 } 246 }); 247 hp.add(icon); 248 249 Label date = new Label(annotation.getFormattedDate()); 250 date.addClickListener(new ClickListener() { 251 public void onClick(Widget sender) { 252 updateSelectedAnnotation(row); 253 selectAnnotation(hp, row); 254 } 255 }); 256 hp.add(date); 257 258 // add the displayed fields 259 Set<String> displayedFields = webConfiguration.getDisplayedFields(); 260 for (String displayedField : displayedFields) { 261 String value = annotation.getFields().get(displayedField); 262 Label l = new Label(value != null ? value : " "); 263 l.addClickListener(new ClickListener() { 264 public void onClick(Widget sender) { 265 updateSelectedAnnotation(row); 266 selectAnnotation(hp, row); 267 } 268 }); 269 hp.add(l); 270 } 271 vp.add(hp); 272 273 if (getSelectedAnnotationIndex() == row) { 274 hpSelected = hp; 275 selectedAnnotationIndex = row; 276 } 277 } 278 add(vp); 279 280 if (hpSelected != null && selectedAnnotationIndex > -1) { 281 selectAnnotation(hpSelected, selectedAnnotationIndex); 282 } 283 } 284 285 private native void updateSelectedAnnotation(int index) /*-{ 286 if (typeof top['updateSelectedAnnotation'] != "undefined") { 287 top['updateSelectedAnnotation'](index); 288 } 289 }-*/; 290 291 private void selectAnnotation(HorizontalPanel hp, int index) { 292 setSelectedannotationIndex(index); 293 updateShownAnnotation(index); 294 updateSelectedRow(hp, index); 295 } 296 297 private native void setSelectedannotationIndex(int index) /*-{ 298 top['selectedAnnotationIndex'] = index; 299 }-*/; 300 301 private native int getSelectedAnnotationIndex() /*-{ 302 if (typeof top['selectedAnnotationIndex'] != "undefined") { 303 return top['selectedAnnotationIndex']; 304 } else { 305 return -1; 306 } 307 }-*/; 308 309 private void updateShownAnnotation(int y) { 310 remove(shownAnnotation); 311 shownAnnotation = new VerticalPanel(); 312 shownAnnotation.addStyleName("shown-annotation"); 313 Annotation ann = model.getAnnotations().get(y); 314 add(shownAnnotation); 315 HorizontalPanel horizontalPanel = new HorizontalPanel(); 316 AnnotationDefinition def = webConfiguration.getAnnotationDefinition(ann.getShortType()); 317 Image image = new Image(def.getIcon()); 318 horizontalPanel.add(image); 319 horizontalPanel.add(new Label(ann.getFormattedDate())); 320 321 // add the displayed fields 322 Set<String> displayedFields = webConfiguration.getDisplayedFields(); 323 for (String displayedField : displayedFields) { 324 String value = ann.getFields().get(displayedField); 325 horizontalPanel.add(new Label("•")); 326 Label valueLabel = new Label(value != null ? value : " "); 327 horizontalPanel.add(valueLabel); 328 } 329 Label spacer = new Label(" "); 330 horizontalPanel.add(spacer); 331 horizontalPanel.setCellWidth(spacer, "100%"); 332 333 shownAnnotation.add(horizontalPanel); 334 if (ann.isBodyUrl()) { 335 Frame frame = new Frame(); 336 frame.setUrl(ann.getBody()); 337 shownAnnotation.add(frame); 338 } else { 339 HTML label = new HTML(AnnotationUtils.replaceCarriageReturns(ann.getBody())); 340 label.setStyleName("annotation-body"); 341 shownAnnotation.add(label); 342 } 343 } 344 345 protected void updateSelectedRow(HorizontalPanel hp, final int index) { 346 if (selectedRow != null) { 347 selectedRow.removeStyleName("selectedAnnotationInList"); 348 selectedRow.remove(selectedRow.getWidgetCount() - 1); 349 } 350 hp.setStyleName("selectedAnnotationInList"); 351 352 Image deleteImage = new Image("icons/delete.png"); 353 deleteImage.addClickListener(new ClickListener() { 354 public void onClick(Widget sender) { 355 TranslationConstants translationConstants = GWT.create(TranslationConstants.class); 356 if (Window.confirm(translationConstants.menuConfirmDelete())) { 357 controller.deleteAnnotation(index); 358 setSelectedannotationIndex(-1); 359 } 360 } 361 }); 362 hp.add(deleteImage); 363 364 selectedRow = hp; 365 } 366 367}