blob: ad5bd52e5b216b55d0d27462209a9cd594c09a91 [file] [log] [blame]
/*
* 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 static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
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;
/** Full size being scrolled (after zoom), in pixels */
private int mFullSize;;
/** 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();
}
}
/** Recomputes the scrollbar and view port settings */
public void refresh() {
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 getScaledImgSize() {
return (int) (mImgSize * mScale);
}
/**
* Changes the size of the canvas image and the client size. Recomputes
* scrollbars.
*
* @param imgSize the size of the image being scaled
* @param fullSize the size of the full view area being scrolled
* @param clientSize the size of the view port
*/
public void setSize(int imgSize, int fullSize, int clientSize) {
mImgSize = imgSize;
mFullSize = fullSize;
mClientSize = clientSize;
mScrollbar.setPageIncrement(clientSize);
resizeScrollbar();
}
private void resizeScrollbar() {
// scaled image size
int sx = (int) (mScale * mFullSize);
// 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;
ImageOverlay imageOverlay = mCanvas.getImageOverlay();
if (imageOverlay != null && imageOverlay.getShowDropShadow()
&& delta >= SHADOW_SIZE / 2) {
mMargin -= SHADOW_SIZE / 2;
// Add a little padding on the top too, if there's room. The shadow assets
// include enough padding on the bottom to not make this look clipped.
if (mMargin < 4) {
mMargin += 4;
}
}
} else {
mMargin = DEFAULT_MARGIN;
}
if (mCanvas.getPreviewManager().hasPreviews()) {
// Make more room for the previews
mMargin = 2;
}
// 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);
}
public int inverseScale(int canwasW) {
return (int) (canwasW / mScale);
}
}