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