/* * (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: * troger * * $Id$ */ package org.nuxeo.ecm.platform.pictures.tiles.gwt.client.view; import java.util.HashMap; import java.util.Map; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.controller.TilingController; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.model.TilingModel; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.model.TilingModelListener; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.model.TilingModel.TilingModelEvent; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.util.Point; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.util.Rectangle; import org.nuxeo.ecm.platform.pictures.tiles.gwt.client.view.i18n.TranslationConstants; import com.allen_sauer.gwt.log.client.Log; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; /** * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> */ public class TilingPreviewPanel extends Composite implements TilingModelListener { private static final String DEFAULT_CLASS_NAME = "tilingPreviewPanel"; private AbsolutePanel tilingViewPanel; private AbsolutePanel tilingView; private final TilingController controller; private final TilingModel model; private final Map<String, Image> images = new HashMap<String, Image>(); public TilingPreviewPanel(TilingController tilingController, TilingModel tilingModel) { controller = tilingController; model = tilingModel; model.addListener(this); // create the panel to show the part of the image tilingViewPanel = new AbsolutePanel(); tilingViewPanel.setPixelSize(model.getViewAreaWidth(), model.getViewAreaHeight()); tilingView = new AbsolutePanel(); tilingViewPanel.add(tilingView); tilingViewPanel.addStyleName("tilingViewPanel"); AbsolutePanel rootPanel = new AbsolutePanel(); rootPanel.setPixelSize(model.getViewAreaWidth(), model.getViewAreaHeight()); rootPanel.addStyleName("tilingMasterContainer"); rootPanel.add(tilingViewPanel, 0, 0); HorizontalPanel hPanel = createZoomButtons(); rootPanel.add(hPanel, 20, 20); initWidget(rootPanel); setStyleName(DEFAULT_CLASS_NAME); } private HorizontalPanel createZoomButtons() { HorizontalPanel buttons = new HorizontalPanel(); TranslationConstants translationContants = GWT.create(TranslationConstants.class); Button resetZoomButton = new Button(); resetZoomButton.addClickListener(new ClickListener() { public void onClick(Widget arg0) { Window.Location.assign(Window.Location.getHref()); decorate(); } }); resetZoomButton.addStyleName("resetZoomButton"); resetZoomButton.setTitle(translationContants.zoom()); buttons.add(resetZoomButton); Button zoomInButton = new Button(); zoomInButton.addClickListener(new ClickListener() { public void onClick(Widget arg0) { model.zoomIn(); } }); zoomInButton.addStyleName("zoomInButton"); zoomInButton.setTitle(translationContants.zoomIn()); buttons.add(zoomInButton); Button zoomOutButton = new Button(); zoomOutButton.addClickListener(new ClickListener() { public void onClick(Widget arg0) { model.zoomOut(); } }); zoomOutButton.addStyleName("zoomOutButton"); zoomOutButton.setTitle(translationContants.zoomOut()); buttons.add(zoomOutButton); return buttons; } public void onModelChange(TilingModelEvent event, TilingModel model) { switch (event) { case MOVE_EVENT: // update the view (move) renderView(); break; case TILING_INFO_UPDATED: // clean and reload the view resetView(); renderView(); break; } } private void renderView() { int widthInTiles = model.getWidthInTiles(); int heightInTiles = model.getHeightInTiles(); int top = model.getViewAreaTop(); int left = model.getViewAreaLeft(); int width = model.getViewAreaWidth(); int height = model.getViewAreaHeight(); Rectangle viewableArea = new Rectangle(new Point(left, top), width, height); tilingView.clear(); for (int y = 0; y < heightInTiles; ++y) { for (int x = 0; x < widthInTiles; ++x) { String imageUrl = model.getBaseUrl() + "?x=" + x + "&y=" + y; imageUrl += "&date=" + model.getLastModificationDate(); int imageLeft = x * model.getTileWidth(); int imageTop = y * model.getTileHeight(); int imageRight = imageLeft + model.getTileWidth(); int imageBottom = imageTop + model.getTileHeight(); Point imageTopLeft = new Point(imageLeft, imageTop); Point imageTopRight = new Point(imageRight, imageTop); Point imageBottomLeft = new Point(imageLeft, imageBottom); Point imageBottomRight = new Point(imageRight, imageBottom); if (!viewableArea.containsAny(imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight)) { // Always draw the first image. It's used to display the // annotations if (!(x == 0 && y == 0)) { continue; } } Log.debug("Getting image: " + imageUrl); Image image = getImage(imageUrl); if (x == 0 && y == 0) { image.getElement().setId("annotationRootImage"); } tilingView.add(image, imageLeft, imageTop); } } tilingViewPanel.add(tilingView, -left, -top); decorate(); } private Image getImage(String imageUrl) { Image image = images.get(imageUrl); if (image == null) { image = new Image(imageUrl); images.put(imageUrl, image); } return image; } private void decorate() { controller.updateAnnotationDecoration(); } private void resetView() { images.clear(); tilingView.clear(); tilingView.setPixelSize(model.getTotalWidth(), model.getTotalHeight()); } }