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 * troger 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.pictures.tiles.gwt.client.model; 023 024import java.util.ArrayList; 025import java.util.List; 026 027import com.allen_sauer.gwt.log.client.Log; 028 029/** 030 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 031 */ 032public class TilingModel { 033 034 public enum TilingModelEvent { 035 MOVE_EVENT, TILING_INFO_UPDATED 036 }; 037 038 private TilingInfo tilingInfo; 039 040 private int totalWidth; 041 042 private int totalHeight; 043 044 private int viewAreaTop; 045 046 private int viewAreaLeft; 047 048 private int viewAreaWidth; 049 050 private int viewAreaHeight; 051 052 private int maxLeft; 053 054 private int maxTop; 055 056 // we won't zoom out below this zoom 057 private double defaultZoom; 058 059 // used to recenter the area after zooming in / out 060 private int oldXToCenterOn = 0; 061 062 private int oldYToCenterOn = 0; 063 064 private double oldZoom = 1; 065 066 private List<TilingModelListener> listeners = new ArrayList<TilingModelListener>(); 067 068 private TilingInfoCallback tilingInfoCallback = new TilingInfoCallback() { 069 public void tilingInfoUpdated() { 070 updateModel(); 071 072 // compute new center 073 int x = (int) Math.round(oldXToCenterOn * getCurrentZoom() / oldZoom); 074 int y = (int) Math.round(oldYToCenterOn * getCurrentZoom() / oldZoom); 075 // center 076 Log.debug("center on: x=" + x + ", y=" + y); 077 centerOn(x, y, false); 078 079 // fire the event 080 fireEvent(TilingModelEvent.TILING_INFO_UPDATED); 081 } 082 }; 083 084 public TilingModel(TilingInfo ti, int viewAreaWidth, int viewAreaHeight, double defaultZoom) { 085 tilingInfo = ti; 086 this.defaultZoom = defaultZoom; 087 this.viewAreaWidth = viewAreaWidth; 088 this.viewAreaHeight = viewAreaHeight; 089 viewAreaTop = viewAreaLeft = 0; 090 updateModel(); 091 } 092 093 public void notifyListeners() { 094 fireEvent(TilingModelEvent.TILING_INFO_UPDATED); 095 } 096 097 private void updateModel() { 098 totalWidth = (int) Math.round(tilingInfo.getOriginalImageWidth() * getCurrentZoom()); 099 totalHeight = (int) Math.round(tilingInfo.getOriginalImageHeight() * getCurrentZoom()); 100 101 maxLeft = totalWidth - viewAreaWidth; 102 maxTop = totalHeight - viewAreaHeight; 103 } 104 105 public void move(int x, int y, boolean fireEvent) { 106 viewAreaLeft += x; 107 viewAreaTop += y; 108 ensureCorrectValues(); 109 if (fireEvent) { 110 fireEvent(TilingModelEvent.MOVE_EVENT); 111 } 112 } 113 114 public void move(int x, int y) { 115 move(x, y, true); 116 } 117 118 public void resetView() { 119 viewAreaLeft = viewAreaTop = 0; 120 } 121 122 public void setLocation(int left, int top, boolean fireEvent) { 123 viewAreaLeft = left; 124 viewAreaTop = top; 125 ensureCorrectValues(); 126 if (fireEvent) { 127 fireEvent(TilingModelEvent.MOVE_EVENT); 128 } 129 } 130 131 public void setLocation(int left, int top) { 132 setLocation(left, top, true); 133 } 134 135 public void centerOn(int x, int y, boolean fireEvent) { 136 viewAreaLeft = x - viewAreaWidth / 2; 137 viewAreaTop = y - viewAreaHeight / 2; 138 Log.debug("viewAreaLeft= " + viewAreaLeft + " viewAreaTop= " + viewAreaTop); 139 ensureCorrectValues(); 140 if (fireEvent) { 141 fireEvent(TilingModelEvent.MOVE_EVENT); 142 } 143 } 144 145 public void centerOn(int x, int y) { 146 centerOn(x, y, true); 147 } 148 149 private void ensureCorrectValues() { 150 if (viewAreaLeft > maxLeft) { 151 viewAreaLeft = maxLeft; 152 } 153 if (viewAreaTop > maxTop) { 154 viewAreaTop = maxTop; 155 } 156 if (viewAreaLeft < 0) { 157 viewAreaLeft = 0; 158 } 159 if (viewAreaTop < 0) { 160 viewAreaTop = 0; 161 } 162 } 163 164 public void zoomIn() { 165 tilingInfo.setMaxTiles(tilingInfo.getMaxTiles() * 2); 166 saveOldCoord(); 167 tilingInfo.updateTilingInfo(tilingInfoCallback); 168 } 169 170 public void zoomOut() { 171 if (getCurrentZoom() <= defaultZoom) { 172 return; 173 } 174 tilingInfo.setMaxTiles(tilingInfo.getMaxTiles() / 2); 175 saveOldCoord(); 176 tilingInfo.updateTilingInfo(tilingInfoCallback); 177 } 178 179 private void saveOldCoord() { 180 oldZoom = getCurrentZoom(); 181 oldXToCenterOn = viewAreaLeft + viewAreaWidth / 2; 182 oldYToCenterOn = viewAreaTop + viewAreaHeight / 2; 183 } 184 185 public void addListener(TilingModelListener listener) { 186 listeners.add(listener); 187 } 188 189 public void removeListener(TilingModelListener listener) { 190 listeners.remove(listener); 191 } 192 193 private void fireEvent(TilingModelEvent event) { 194 for (TilingModelListener l : listeners) { 195 l.onModelChange(event, this); 196 } 197 } 198 199 /** 200 * @return the totalWidth. 201 */ 202 public int getTotalWidth() { 203 return totalWidth; 204 } 205 206 /** 207 * @return the totalHeight. 208 */ 209 public int getTotalHeight() { 210 return totalHeight; 211 } 212 213 /** 214 * @return the viewAreaTop. 215 */ 216 public int getViewAreaTop() { 217 return viewAreaTop; 218 } 219 220 /** 221 * @return the viewAreaLeft. 222 */ 223 public int getViewAreaLeft() { 224 return viewAreaLeft; 225 } 226 227 /** 228 * @return the viewAreaWidth. 229 */ 230 public int getViewAreaWidth() { 231 return viewAreaWidth; 232 } 233 234 /** 235 * @return the viewAreaHeight. 236 */ 237 public int getViewAreaHeight() { 238 return viewAreaHeight; 239 } 240 241 public int getTileWidth() { 242 return tilingInfo.getTileWidth(); 243 } 244 245 public int getTileHeight() { 246 return tilingInfo.getTileHeight(); 247 } 248 249 public int getWidthInTiles() { 250 return tilingInfo.getNbXTiles(); 251 } 252 253 public int getHeightInTiles() { 254 return tilingInfo.getNbYTiles(); 255 } 256 257 public String getBaseUrl() { 258 return tilingInfo.getBaseUrl(); 259 } 260 261 public double getCurrentZoom() { 262 return tilingInfo.getZoom(); 263 } 264 265 public long getLastModificationDate() { 266 return tilingInfo.getLastModificationDate(); 267 } 268 269}