/* * Copyright 2014 PRImA Research Lab, University of Salford, United Kingdom * * 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. */ package org.primaresearch.web.gwt.client.ui.page.tool; import org.primaresearch.maths.geometry.Point; import org.primaresearch.maths.geometry.Polygon; import org.primaresearch.maths.geometry.Rect; import org.primaresearch.web.gwt.client.page.PageSyncManager; import org.primaresearch.web.gwt.client.ui.page.SelectionManager; import org.primaresearch.web.gwt.client.ui.page.SelectionManager.SelectionListener; import org.primaresearch.web.gwt.client.ui.page.tool.controls.DraggableControl; import org.primaresearch.web.gwt.shared.page.ContentObjectC; import com.google.gwt.dom.client.Style.Cursor; /** * Tool/control for repositioning page content objects. * * @author Christian Clausner * */ public class MoveRegionTool extends DraggableControl implements SelectionListener { private ContentObjectC selObj = null; private Polygon referencePolygon = null; private PageSyncManager pageSync; private boolean alwaysRefreshPageView; private boolean fillWholeRegion; //private int posInBoundingBoxX = 0; //private int posInBoundingBoxY = 0; /** * Constructor * * @param imageUrl Icon resource * @param selectionManager Content object selection manager to add a listener * @param pageSync Synchronisation manager for sending the changed outline to the server * @param alwaysRefreshPageView If set to <code>false</code> the view is only refreshed when the user releases the mouse button, otherwise it is refreshed as well when moving the mouse. */ public MoveRegionTool(String imageUrl, SelectionManager selectionManager, PageSyncManager pageSync, boolean alwaysRefreshPageView, boolean fillWholeRegion) { super(imageUrl); selectionManager.addListener(this); this.asWidget().setVisible(false); this.asWidget().getElement().getStyle().setCursor(Cursor.MOVE); this.pageSync = pageSync; this.alwaysRefreshPageView = alwaysRefreshPageView; this.fillWholeRegion = fillWholeRegion; } @Override public void selectionChanged(SelectionManager manager) { if (manager.isEmpty() || manager.getSelection().size() > 1) { this.asWidget().setVisible(false); selObj = null; } else { //One object selected selObj = manager.getSelection().iterator().next(); this.asWidget().setVisible(selObj != null && !selObj.isReadOnly()); updatePosition(); } } /** * Updates the position of the control in relation to the currently selected page content object. */ private void updatePosition() { if (selObj == null) return; int x,y; Rect objectRect = selObj.getCoords().getBoundingBox(); if (fillWholeRegion) { x = (int)(objectRect.left * getPageView().getZoomFactor()); y = (int)(objectRect.top * getPageView().getZoomFactor()); int w = (int)(objectRect.getWidth() * getPageView().getZoomFactor()); int h = (int)(objectRect.getHeight() * getPageView().getZoomFactor()); this.asWidget().setWidth(w+"px"); this.asWidget().setHeight(h+"px"); } else { //Centre int halfWidth = this.asWidget().getElement().getClientWidth() / 2; int halfHeight = this.asWidget().getElement().getClientHeight() / 2; x = (int)(((objectRect.left + objectRect.right)/2.0) * getPageView().getZoomFactor()) - halfWidth; y = (int)(((objectRect.top + objectRect.bottom)/2.0) * getPageView().getZoomFactor()) - halfHeight; } setPosistion(x, y); } @Override protected void onDrag(Point start, Point current) { if (referencePolygon == null) { //Keep the original polygon as reference referencePolygon = selObj.getCoords().clone(); //posInBoundingBoxX = start.x - referencePolygon.getBoundingBox().left; //posInBoundingBoxY = start.y - referencePolygon.getBoundingBox().top; } //Calculate the offset from the 'mouse down point' int translateX = (int)((double)(current.x - start.x) / getPageView().getZoomFactor()); int translateY = (int)((double)(current.y - start.y) / getPageView().getZoomFactor()); //Confine to document dimensions Rect boundingBox = referencePolygon.getBoundingBox(); if (boundingBox.left + translateX < 0) translateX = -boundingBox.left; else if (boundingBox.right + translateX >= pageView.getPageLayout().getWidth()) translateX = pageView.getPageLayout().getWidth() - boundingBox.right - 1; if (boundingBox.top + translateY < 0) translateY = -boundingBox.top; else if (boundingBox.bottom + translateY >= pageView.getPageLayout().getHeight()) translateY = pageView.getPageLayout().getHeight() - boundingBox.bottom - 1; //Update the position of the polygon Polygon polygon = selObj.getCoords(); for (int i=0; i<polygon.getSize(); i++) { polygon.getPoint(i).x = referencePolygon.getPoint(i).x + translateX; polygon.getPoint(i).y = referencePolygon.getPoint(i).y + translateY; } polygon.setBoundingBoxOutdated(); //Update all other widgets that are on the page view pageView.refreshHoverWidgets(); //Refresh page view if (alwaysRefreshPageView) pageView.getRenderer().refresh(); } @Override protected void onDragEnd(Point start, Point current) { referencePolygon = null; this.getPageView().getRenderer().refresh(); //Sync to server pageSync.syncObjectOutline(selObj); } @Override public void refresh() { updatePosition(); } }