/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php * * 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 com.android.ide.eclipse.adt.internal.editors.layout.gle2; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.ScrollBar; /** * Helper class to convert between control pixel coordinates and canvas coordinates. * Takes care of the zooming and offset of the canvas. */ public class CanvasTransform { /** * Default margin around the rendered image, reduced * when the contents do not fit. */ public static final int DEFAULT_MARGIN = 25; /** * The canvas which controls the zooming. */ private final LayoutCanvas mCanvas; /** Canvas image size (original, before zoom), in pixels. */ private int mImgSize; /** Client size, in pixels. */ private int mClientSize; /** Left-top offset in client pixel coordinates. */ private int mTranslate; /** Current margin */ private int mMargin = DEFAULT_MARGIN; /** Scaling factor, > 0. */ private double mScale; /** Scrollbar widget. */ private ScrollBar mScrollbar; public CanvasTransform(LayoutCanvas layoutCanvas, ScrollBar scrollbar) { mCanvas = layoutCanvas; mScrollbar = scrollbar; mScale = 1.0; mTranslate = 0; mScrollbar.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // User requested scrolling. Changes translation and redraw canvas. mTranslate = mScrollbar.getSelection(); CanvasTransform.this.mCanvas.redraw(); } }); mScrollbar.setIncrement(20); } /** * Sets the new scaling factor. Recomputes scrollbars. * @param scale Scaling factor, > 0. */ public void setScale(double scale) { if (mScale != scale) { mScale = scale; resizeScrollbar(); } } /** * Returns current scaling factor. * * @return The current scaling factor */ public double getScale() { return mScale; } /** * Returns Canvas image size (original, before zoom), in pixels. * * @return Canvas image size (original, before zoom), in pixels */ public int getImgSize() { return mImgSize; } /** * Returns the scaled image size in pixels. * * @return The scaled image size in pixels. */ public int getScalledImgSize() { return (int) (mImgSize * mScale); } /** Changes the size of the canvas image and the client size. Recomputes scrollbars. */ public void setSize(int imgSize, int clientSize) { mImgSize = imgSize; setClientSize(clientSize); } /** Changes the size of the client size. Recomputes scrollbars. */ public void setClientSize(int clientSize) { mClientSize = clientSize; mScrollbar.setPageIncrement(clientSize); resizeScrollbar(); } private void resizeScrollbar() { // scaled image size int sx = (int) (mImgSize * mScale); // Adjust margin such that for zoomed out views // we don't waste space (unless the viewport is // large enough to accommodate it) int delta = mClientSize - sx; if (delta < 0) { mMargin = 0; } else if (delta < 2 * DEFAULT_MARGIN) { mMargin = delta / 2; } else { mMargin = DEFAULT_MARGIN; } // actual client area is always reduced by the margins int cx = mClientSize - 2 * mMargin; if (sx < cx) { mTranslate = 0; mScrollbar.setEnabled(false); } else { mScrollbar.setEnabled(true); int selection = mScrollbar.getSelection(); int thumb = cx; int maximum = sx; if (selection + thumb > maximum) { selection = maximum - thumb; if (selection < 0) { selection = 0; } } mScrollbar.setValues(selection, mScrollbar.getMinimum(), maximum, thumb, mScrollbar .getIncrement(), mScrollbar.getPageIncrement()); mTranslate = selection; } } public int getMargin() { return mMargin; } public int translate(int canvasX) { return mMargin - mTranslate + (int) (mScale * canvasX); } public int scale(int canwasW) { return (int) (mScale * canwasW); } public int inverseTranslate(int screenX) { return (int) ((screenX - mMargin + mTranslate) / mScale); } }