/* * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Alexandre Russel * * $Id$ */ package org.nuxeo.ecm.platform.annotations.gwt.client.controler; import java.util.ArrayList; import java.util.List; import org.nuxeo.ecm.platform.annotations.gwt.client.AnnotationConstant; import org.nuxeo.ecm.platform.annotations.gwt.client.annotea.AnnoteaClient; import org.nuxeo.ecm.platform.annotations.gwt.client.configuration.WebConfiguration; import org.nuxeo.ecm.platform.annotations.gwt.client.model.Annotation; import org.nuxeo.ecm.platform.annotations.gwt.client.model.AnnotationChangeListener; import org.nuxeo.ecm.platform.annotations.gwt.client.model.AnnotationModel; import org.nuxeo.ecm.platform.annotations.gwt.client.util.Point; import org.nuxeo.ecm.platform.annotations.gwt.client.util.StringRangeXPointer; import org.nuxeo.ecm.platform.annotations.gwt.client.util.XPointerFactory; import org.nuxeo.ecm.platform.annotations.gwt.client.view.AnnotatedDocument; import org.nuxeo.ecm.platform.annotations.gwt.client.view.NewAnnotationPopup; import org.nuxeo.ecm.platform.annotations.gwt.client.view.listener.AnnotationPopupEventListener; import com.allen_sauer.gwt.log.client.Log; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.ImageElement; import com.google.gwt.user.client.Window; /** * @author Alexandre Russel */ public class AnnotationController { private static AnnotationController CURRENT_INSTANCE; private static AnnotationModel model = new AnnotationModel(); private static NewAnnotationPopup newAnnotationPopup; private static AnnotatedDocument annotatedDocument; private static final List<AnnotationPopupEventListener> annotationPopupListeners = new ArrayList<AnnotationPopupEventListener>(); private String xPointerFilter; private String pointerAdapter; private boolean annotateImageOnly; private boolean multiImage; private final AnnoteaClient annoteaClient; private final WebConfiguration webConfiguration; private int frameScrollFromTop; private boolean creationPopupOpened = false; private final boolean onFrame; public AnnotationController(WebConfiguration webConfiguration, boolean onFrame) { this.onFrame = onFrame; this.webConfiguration = (webConfiguration == null ? WebConfiguration.DEFAULT_WEB_CONFIGURATION : webConfiguration); annoteaClient = new AnnoteaClient(this); CURRENT_INSTANCE = this; if (onFrame) { annotatedDocument = new AnnotatedDocument(this); model.addChangeListener(annotatedDocument); registerOnFrameMethods(); } else { registerMainModuleMethods(); } } private native void registerOnFrameMethods() /*-{ top['addNewAnnotation'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::addNewAnnotation(); top['showAnnotations'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::showAnnotations(); top['hideAnnotations'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::hideAnnotations(); top['updateSelectedAnnotation'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::updateSelectedAnnotation(I); top['cancelNewAnnotationPopup'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::cancelNewAnnotationPopup(); top['loadAnnotationsOnFrame'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::loadAnnotations(); top['isAnnotationsVisible'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::isAnnotationsVisible(); top['deleteAnnotation'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::deleteAnnotationOnFrame(I); }-*/; private native void registerMainModuleMethods() /*-{ top['loadAnnotationsOnMainModule'] = this.@org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::loadAnnotations(); }-*/; public void addNewAnnotation() { NewAnnotationPopup popup = getNewAnnotationPopup(); Annotation annotation = getNewAnnotation(); if (popup != null && annotation != null) { if (annotation.getXpointer() instanceof StringRangeXPointer) { // pre-decorate the selected text annotatedDocument.decorateSelectedText(annotation); } popup.show(); } } public WebConfiguration getWebConfiguration() { return webConfiguration; } public AnnotatedDocument getAnnotatedDocument() { return annotatedDocument; } public void setXPointerFilter(String pointerFilter) { xPointerFilter = pointerFilter; } public void setPointerAdapter(String pointerAdapter) { this.pointerAdapter = pointerAdapter; } public boolean canAnnotate() { return webConfiguration.canAnnotate(); } public void addModelChangeListener(AnnotationChangeListener listener) { model.addChangeListener(listener); } public int getFrameScrollFromTop() { return frameScrollFromTop; } public void setFrameScrollFromTop(int frameScrollFromTop) { this.frameScrollFromTop = frameScrollFromTop; } public boolean canCreateNewCreationPopup() { return !creationPopupOpened; } public void openCreationPopup() { creationPopupOpened = true; } public void closeCreationPopup() { creationPopupOpened = false; } public void newAnnotationCreated(Annotation annotation) { model.setNewAnnotation(annotation); } public void submitNewAnnotation() { GWT.log("submiting new annotation", null); Annotation newAnnotation = model.getNewAnnotation(); annoteaClient.submitAnnotation(newAnnotation); model.setNewAnnotation(null); // set the selected annotation to the newly created one setSelectedAnnotationIndex(model.getAnnotations().size()); } private native void setSelectedAnnotationIndex(int index) /*-{ top['selectedAnnotationIndex'] = index; }-*/; public void reloadAnnotations() { if (onFrame) { reloadAnnotationsOnMainModule(); } else { reloadAnnotationsOnFrame(); } } private native void reloadAnnotationsOnMainModule() /*-{ top['loadAnnotationsOnMainModule'](); }-*/; private native void reloadAnnotationsOnFrame() /*-{ top['loadAnnotationsOnFrame'](); }-*/; public void cancelNewAnnotation() { model.setNewAnnotation(null); } public void cancelNewAnnotationPopup() { if (newAnnotationPopup != null) { newAnnotationPopup.cancel(); } } public void createNewAnnotation(String pointer) { String href = getDocumentUrl(); // Hardcoded url codec.... String xpointerURI = href.substring(0, href.lastIndexOf("@") + 1) + pointer; Annotation newAnnotation = new Annotation(XPointerFactory.getXPointer(xpointerURI)); model.setNewAnnotation(newAnnotation); } public void setAnnotationList(List<Annotation> annotations) { model.setAnnotations(annotations); } public native String getAnnoteaServerUrl() /*-{ return top['annoteaServerUrl']; }-*/; public Annotation getNewAnnotation() { return model.getNewAnnotation(); } public void loadAnnotations() { if (onFrame) { if (!isMultiImage()) { annotatedDocument.preDecorateDocument(); } } annoteaClient.getAnnotationList(getDocumentUrl()); } public native String getDocumentUrl() /*-{ return top['docUrl']; }-*/; public void decorateDocument() { Log.debug("decorate document"); annotatedDocument.preDecorateDocument(); updateAnnotation(true); } public void updateSelectedAnnotation(int index) { annotatedDocument.updateSelectedAnnotation(index); } public void setFirstAnnotationSelected() { if (!model.getAnnotations().isEmpty()) { annotatedDocument.updateSelectedAnnotation(0); } } public void setCancelNewAnnotation() { model.setNewAnnotation(null); } public void setImageOnly(boolean b) { this.annotateImageOnly = b; } public boolean isImageOnly() { return this.annotateImageOnly; } public void setMultiImage(boolean b) { this.multiImage = b; } public boolean isMultiImage() { return this.multiImage; } public String filterXPointer(ImageElement image, String xpath, int i, int j, int k, int l) { if (xPointerFilter != null) { return filter(xPointerFilter, image, xpath, i, j, k, l); } return "#xpointer(image-range(" + xpath + ",[" + i + "," + j + "],[" + k + "," + l + "]))"; } public native String filter(String xPointerFilter, ImageElement image, String xpath, int i, int j, int k, int l) /*-{ if(xPointerFilter && top[xPointerFilter]) { return top[xPointerFilter](image, xpath, i, j, k, l); } }-*/; public Point[] filterAnnotation(Point topLeft, Point bottomRight) { if (pointerAdapter == null) { return new Point[] { topLeft, bottomRight }; } String result = filterPoint(pointerAdapter, topLeft.getX(), topLeft.getY(), bottomRight.getX(), bottomRight.getY()); if (result.equals("")) { return null; } String[] points = result.split(":"); return new Point[] { new Point(points[0]), new Point(points[1]) }; } private native String filterPoint(String pointerAdapter, int x, int y, int x2, int y2) /*-{ if(pointerAdapter && top[pointerAdapter]) { return top[pointerAdapter](x, y, x2, y2); } }-*/; public static void updateAnnotation(boolean forceDecorate) { CURRENT_INSTANCE.updateAnnotations(forceDecorate); } public static void updateAnnotation() { updateAnnotation(false); } public void updateAnnotations(boolean forceDecorate) { annotatedDocument.update(forceDecorate); } public native void setAnnotationDecoratorFunction(String annotationDecoratorFunction) /*-{ top[annotationDecoratorFunction] = @org.nuxeo.ecm.platform.annotations.gwt.client.controler.AnnotationController::updateAnnotation(Z); }-*/; public void setNewAnnotationPopup(NewAnnotationPopup popup) { newAnnotationPopup = popup; } public NewAnnotationPopup getNewAnnotationPopup() { return newAnnotationPopup; } public void hideAnnotations() { annotatedDocument.hideAnnotations(); disablePopupListeners(); } public void disablePopupListeners() { for (AnnotationPopupEventListener listener : annotationPopupListeners) { listener.disable(); } } public void showAnnotations() { annotatedDocument.showAnnotations(); enablePopupListeners(); } public void enablePopupListeners() { for (AnnotationPopupEventListener listener : annotationPopupListeners) { listener.enable(); } } public void registerAnnotationPopupListener(AnnotationPopupEventListener listener) { annotationPopupListeners.add(listener); } public void removeAnnotationPopupListener(AnnotationPopupEventListener listener) { annotationPopupListeners.remove(listener); } public String getDecorateClassName() { if (annotatedDocument.isAnnotationsVisible()) { return AnnotationConstant.DECORATE_CLASS_NAME; } else { return AnnotationConstant.DECORATE_NOT_CLASS_NAME; } } public native void deleteAnnotation(int index) /*-{ top['deleteAnnotation'](index); }-*/; @SuppressWarnings("unused") private void deleteAnnotationOnFrame(int index) { annoteaClient.deleteAnnotation(Window.Location.getHref(), model.getAnnotations().get(index)); } public native boolean isAnnotationsVisible() /*-{ if (top && typeof top['annotationsShown'] != "undefined") { return top['annotationsShown']; } else { return true; } }-*/; public void removeSelectedTextDecoration() { annotatedDocument.removeSelectedTextDecoration(getNewAnnotation()); } }