| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * 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 com.android.ide.eclipse.adt.internal.editors.draw9patch.ui; |
| |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.NinePatchedImage; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.NinePatchedImage.Chunk; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.NinePatchedImage.Tick; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.KeyListener; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.events.MouseMoveListener; |
| import org.eclipse.swt.events.PaintEvent; |
| import org.eclipse.swt.events.PaintListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Canvas; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.ScrollBar; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.ArrayBlockingQueue; |
| |
| /** |
| * View and edit Draw 9-patch image. |
| */ |
| public class ImageViewer extends Canvas implements PaintListener, KeyListener, MouseListener, |
| MouseMoveListener { |
| private static final boolean DEBUG = false; |
| |
| public static final String HELP_MESSAGE_KEY_TIPS = "Press Shift to erase pixels." |
| + " Press Control to draw layout bounds."; |
| |
| public static final String HELP_MESSAGE_KEY_TIPS2 = "Release Shift to draw pixels."; |
| |
| private static final Color BLACK_COLOR = AdtPlugin.getDisplay().getSystemColor(SWT.COLOR_BLACK); |
| private static final Color RED_COLOR = AdtPlugin.getDisplay().getSystemColor(SWT.COLOR_RED); |
| |
| private static final Color BACK_COLOR |
| = new Color(AdtPlugin.getDisplay(), new RGB(0x00, 0xFF, 0x00)); |
| private static final Color LOCK_COLOR |
| = new Color(AdtPlugin.getDisplay(), new RGB(0xFF, 0x00, 0x00)); |
| private static final Color PATCH_COLOR |
| = new Color(AdtPlugin.getDisplay(), new RGB(0xFF, 0xFF, 0x00)); |
| private static final Color PATCH_ONEWAY_COLOR |
| = new Color(AdtPlugin.getDisplay(), new RGB(0x00, 0x00, 0xFF)); |
| private static final Color CORRUPTED_COLOR |
| = new Color(AdtPlugin.getDisplay(), new RGB(0xFF, 0x00, 0x00)); |
| |
| private static final int NONE_ALPHA = 0xFF; |
| private static final int LOCK_ALPHA = 50; |
| private static final int PATCH_ALPHA = 50; |
| private static final int GUIDE_ALPHA = 60; |
| |
| private static final int MODE_NONE = 0x00; |
| private static final int MODE_BLACK_TICK = 0x01; |
| private static final int MODE_RED_TICK = 0x02; |
| private static final int MODE_ERASE = 0xFF; |
| |
| private int mDrawMode = MODE_NONE; |
| |
| private static final int MARGIN = 5; |
| private static final String CHECKER_PNG_PATH = "/icons/checker.png"; |
| |
| private Image mBackgroundLayer = null; |
| |
| private NinePatchedImage mNinePatchedImage = null; |
| |
| private Chunk[][] mChunks = null; |
| private Chunk[][] mBadChunks = null; |
| |
| private boolean mIsLockShown = true; |
| private boolean mIsPatchesShown = false; |
| private boolean mIsBadPatchesShown = false; |
| |
| private ScrollBar mHorizontalBar; |
| private ScrollBar mVerticalBar; |
| |
| private int mZoom = 500; |
| |
| private int mHorizontalScroll = 0; |
| private int mVerticalScroll = 0; |
| |
| private final Rectangle mPadding = new Rectangle(0, 0, 0, 0); |
| |
| // one pixel size that considered zoom |
| private int mZoomedPixelSize = 1; |
| |
| private Image mBufferImage = null; |
| |
| private boolean isCtrlPressed = false; |
| private boolean isShiftPressed = false; |
| |
| private final List<UpdateListener> mUpdateListenerList |
| = new ArrayList<UpdateListener>(); |
| |
| private final Point mCursorPoint = new Point(0, 0); |
| |
| private static final int DEFAULT_UPDATE_QUEUE_SIZE = 10; |
| |
| private final ArrayBlockingQueue<NinePatchedImage> mUpdateQueue |
| = new ArrayBlockingQueue<NinePatchedImage>(DEFAULT_UPDATE_QUEUE_SIZE); |
| |
| private final Runnable mUpdateRunnable = new Runnable() { |
| @Override |
| public void run() { |
| if (isDisposed()) { |
| return; |
| } |
| |
| redraw(); |
| |
| fireUpdateEvent(); |
| } |
| }; |
| |
| private final Thread mUpdateThread = new Thread() { |
| @Override |
| public void run() { |
| while (!isDisposed()) { |
| try { |
| mUpdateQueue.take(); |
| mNinePatchedImage.findPatches(); |
| mNinePatchedImage.findContentsArea(); |
| |
| mChunks = mNinePatchedImage.getChunks(mChunks); |
| mBadChunks = mNinePatchedImage.getCorruptedChunks(mBadChunks); |
| |
| AdtPlugin.getDisplay().asyncExec(mUpdateRunnable); |
| |
| } catch (InterruptedException e) { |
| } |
| } |
| } |
| }; |
| |
| private StatusChangedListener mStatusChangedListener = null; |
| |
| public void addUpdateListener(UpdateListener l) { |
| mUpdateListenerList.add(l); |
| } |
| |
| public void removeUpdateListener(UpdateListener l) { |
| mUpdateListenerList.remove(l); |
| } |
| |
| private void fireUpdateEvent() { |
| int len = mUpdateListenerList.size(); |
| for(int i=0; i < len; i++) { |
| mUpdateListenerList.get(i).update(mNinePatchedImage); |
| } |
| } |
| |
| public void setStatusChangedListener(StatusChangedListener l) { |
| mStatusChangedListener = l; |
| if (mStatusChangedListener != null) { |
| mStatusChangedListener.helpTextChanged(HELP_MESSAGE_KEY_TIPS); |
| } |
| } |
| |
| void setShowLock(boolean show) { |
| mIsLockShown = show; |
| redraw(); |
| } |
| |
| void setShowPatchesArea(boolean show) { |
| mIsPatchesShown = show; |
| redraw(); |
| } |
| |
| void setShowBadPatchesArea(boolean show) { |
| mIsBadPatchesShown = show; |
| redraw(); |
| } |
| |
| void setZoom(int zoom) { |
| mZoom = zoom; |
| mZoomedPixelSize = getZoomedPixelSize(1); |
| redraw(); |
| } |
| |
| public ImageViewer(Composite parent, int style) { |
| super(parent, style); |
| |
| mUpdateThread.start(); |
| |
| mBackgroundLayer = AdtPlugin.getImageDescriptor(CHECKER_PNG_PATH).createImage(); |
| |
| addMouseListener(this); |
| addMouseMoveListener(this); |
| addPaintListener(this); |
| |
| mHorizontalBar = getHorizontalBar(); |
| mHorizontalBar.setThumb(1); |
| mHorizontalBar.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| super.widgetSelected(event); |
| ScrollBar bar = (ScrollBar) event.widget; |
| if (mHorizontalBar.isVisible() |
| && mHorizontalScroll != bar.getSelection()) { |
| mHorizontalScroll = bar.getSelection(); |
| redraw(); |
| } |
| } |
| }); |
| |
| mVerticalBar = getVerticalBar(); |
| mVerticalBar.setThumb(1); |
| mVerticalBar.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| super.widgetSelected(event); |
| ScrollBar bar = (ScrollBar) event.widget; |
| if (mVerticalBar.isVisible() |
| && mVerticalScroll != bar.getSelection()) { |
| mVerticalScroll = bar.getSelection(); |
| redraw(); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Load the image file. |
| * |
| * @param fileName must be absolute path |
| */ |
| public NinePatchedImage loadFile(String fileName) { |
| mNinePatchedImage = new NinePatchedImage(fileName); |
| |
| return mNinePatchedImage; |
| } |
| |
| /** |
| * Start displaying the image. |
| */ |
| public void startDisplay() { |
| mZoomedPixelSize = getZoomedPixelSize(1); |
| |
| scheduleUpdate(); |
| } |
| |
| private void draw(int x, int y, int drawMode) { |
| if (drawMode == MODE_ERASE) { |
| erase(x, y); |
| } else { |
| int color = (drawMode == MODE_RED_TICK) ? NinePatchedImage.RED_TICK |
| : NinePatchedImage.BLACK_TICK; |
| mNinePatchedImage.setPatch(x, y, color); |
| redraw(); |
| |
| scheduleUpdate(); |
| } |
| } |
| |
| private void erase(int x, int y) { |
| mNinePatchedImage.erase(x, y); |
| redraw(); |
| |
| scheduleUpdate(); |
| } |
| |
| private void scheduleUpdate() { |
| try { |
| mUpdateQueue.put(mNinePatchedImage); |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| @Override |
| public void mouseDown(MouseEvent event) { |
| if (event.button == 1 && !isShiftPressed) { |
| mDrawMode = !isCtrlPressed ? MODE_BLACK_TICK : MODE_RED_TICK; |
| draw(mCursorPoint.x, mCursorPoint.y, mDrawMode); |
| } else if (event.button == 3 || isShiftPressed) { |
| mDrawMode = MODE_ERASE; |
| erase(mCursorPoint.x, mCursorPoint.y); |
| } |
| } |
| |
| @Override |
| public void mouseUp(MouseEvent event) { |
| mDrawMode = MODE_NONE; |
| } |
| |
| @Override |
| public void mouseDoubleClick(MouseEvent event) { |
| } |
| |
| private int getLogicalPositionX(int x) { |
| return Math.round((x - mPadding.x + mHorizontalScroll) / ((float) mZoom / 100)); |
| } |
| |
| private int getLogicalPositionY(int y) { |
| return Math.round((y - mPadding.y + mVerticalScroll) / ((float) mZoom / 100)); |
| } |
| |
| @Override |
| public void mouseMove(MouseEvent event) { |
| int posX = getLogicalPositionX(event.x); |
| int posY = getLogicalPositionY(event.y); |
| |
| int width = mNinePatchedImage.getWidth(); |
| int height = mNinePatchedImage.getHeight(); |
| |
| if (posX < 0) { |
| posX = 0; |
| } |
| if (posX >= width) { |
| posX = width - 1; |
| } |
| if (posY < 0) { |
| posY = 0; |
| } |
| if (posY >= height) { |
| posY = height - 1; |
| } |
| |
| if (mDrawMode != MODE_NONE) { |
| int drawMode = mDrawMode; |
| if (isShiftPressed) { |
| drawMode = MODE_ERASE; |
| } else if (mDrawMode != MODE_ERASE) { |
| drawMode = !isCtrlPressed ? MODE_BLACK_TICK : MODE_RED_TICK; |
| } |
| |
| /* |
| * Consider the previous cursor position because mouseMove events are |
| * scatter. |
| */ |
| int x = mCursorPoint.x; |
| int y = mCursorPoint.y; |
| for (; y != posY; y += (y > posY) ? -1 : 1) { |
| draw(x, y, drawMode); |
| } |
| |
| x = mCursorPoint.x; |
| y = mCursorPoint.y; |
| for (; x != posX; x += (x > posX) ? -1 : 1) { |
| draw(x, y, drawMode); |
| } |
| } |
| mCursorPoint.x = posX; |
| mCursorPoint.y = posY; |
| |
| redraw(); |
| |
| if (mStatusChangedListener != null) { |
| // Update position on status panel if position is in logical size. |
| if (posX >= 0 && posY >= 0 |
| && posX <= mNinePatchedImage.getWidth() |
| && posY <= mNinePatchedImage.getHeight()) { |
| mStatusChangedListener.cursorPositionChanged(posX + 1, posY + 1); |
| } |
| } |
| } |
| |
| private synchronized void calcPaddings(int width, int height) { |
| Point canvasSize = getSize(); |
| |
| mPadding.width = getZoomedPixelSize(width); |
| mPadding.height = getZoomedPixelSize(height); |
| |
| int margin = getZoomedPixelSize(MARGIN); |
| |
| if (mPadding.width < canvasSize.x) { |
| mPadding.x = (canvasSize.x - mPadding.width) / 2; |
| } else { |
| mPadding.x = margin; |
| } |
| |
| if (mPadding.height < canvasSize.y) { |
| mPadding.y = (canvasSize.y - mPadding.height) / 2; |
| } else { |
| mPadding.y = margin; |
| } |
| } |
| |
| private void calcScrollBarSettings() { |
| Point size = getSize(); |
| int screenWidth = size.x; |
| int screenHeight = size.y; |
| |
| int imageWidth = getZoomedPixelSize(mNinePatchedImage.getWidth() + 1); |
| int imageHeight = getZoomedPixelSize(mNinePatchedImage.getHeight() + 1); |
| |
| // consider the scroll bar sizes |
| int verticalBarSize = mVerticalBar.getSize().x; |
| int horizontalBarSize = mHorizontalBar.getSize().y; |
| |
| int horizontalScroll = imageWidth - (screenWidth - verticalBarSize); |
| int verticalScroll = imageHeight - (screenHeight - horizontalBarSize); |
| |
| int margin = getZoomedPixelSize(MARGIN) * 2; |
| |
| if (horizontalScroll > 0) { |
| mHorizontalBar.setVisible(true); |
| |
| // horizontal maximum |
| int max = horizontalScroll + verticalBarSize + margin; |
| mHorizontalBar.setMaximum(max); |
| |
| // set corrected scroll size |
| int value = mHorizontalBar.getSelection(); |
| value = max < value ? max : value; |
| |
| mHorizontalBar.setSelection(value); |
| mHorizontalScroll = value; |
| |
| } else { |
| mHorizontalBar.setSelection(0); |
| mHorizontalBar.setMaximum(0); |
| mHorizontalBar.setVisible(false); |
| } |
| |
| if (verticalScroll > 0) { |
| mVerticalBar.setVisible(true); |
| |
| // vertical maximum |
| int max = verticalScroll + horizontalBarSize + margin; |
| mVerticalBar.setMaximum(max); |
| |
| // set corrected scroll size |
| int value = mVerticalBar.getSelection(); |
| value = max < value ? max : value; |
| |
| mVerticalBar.setSelection(value); |
| mVerticalScroll = value; |
| |
| } else { |
| mVerticalBar.setSelection(0); |
| mVerticalBar.setMaximum(0); |
| mVerticalBar.setVisible(false); |
| } |
| } |
| |
| private int getZoomedPixelSize(int val) { |
| return Math.round(val * (float) mZoom / 100); |
| } |
| |
| @Override |
| public void paintControl(PaintEvent pe) { |
| if (mNinePatchedImage == null) { |
| return; |
| } |
| |
| // Use buffer |
| GC bufferGc = null; |
| if (mBufferImage == null) { |
| mBufferImage = new Image(AdtPlugin.getDisplay(), pe.width, pe.height); |
| } else { |
| int width = mBufferImage.getBounds().width; |
| int height = mBufferImage.getBounds().height; |
| if (width != pe.width || height != pe.height) { |
| mBufferImage = new Image(AdtPlugin.getDisplay(), pe.width, pe.height); |
| } |
| } |
| |
| // Draw previous image once for prevent flicking |
| pe.gc.drawImage(mBufferImage, 0, 0); |
| |
| bufferGc = new GC(mBufferImage); |
| bufferGc.setAdvanced(true); |
| |
| // Make interpolation disable |
| bufferGc.setInterpolation(SWT.NONE); |
| |
| // clear buffer |
| bufferGc.fillRectangle(0, 0, pe.width, pe.height); |
| |
| calcScrollBarSettings(); |
| |
| // padding from current zoom |
| int width = mNinePatchedImage.getWidth(); |
| int height = mNinePatchedImage.getHeight(); |
| calcPaddings(width, height); |
| |
| int baseX = mPadding.x - mHorizontalScroll; |
| int baseY = mPadding.y - mVerticalScroll; |
| |
| // draw checker image |
| bufferGc.drawImage(mBackgroundLayer, |
| 0, 0, mBackgroundLayer.getImageData().width, |
| mBackgroundLayer.getImageData().height, |
| baseX, baseY, mPadding.width, mPadding.height); |
| |
| if (DEBUG) { |
| System.out.println(String.format("%d,%d %d,%d %d,%d", |
| width, height, baseX, baseY, mPadding.width, mPadding.height)); |
| } |
| |
| // draw image |
| /* TODO: Do not draw invisible area, for better performance. */ |
| bufferGc.drawImage(mNinePatchedImage.getImage(), 0, 0, width, height, baseX, baseY, |
| mPadding.width, mPadding.height); |
| |
| bufferGc.setBackground(BLACK_COLOR); |
| |
| // draw patch ticks |
| drawHorizontalPatches(bufferGc, baseX, baseY); |
| drawVerticalPatches(bufferGc, baseX, baseY); |
| |
| // draw content ticks |
| drawHorizontalContentArea(bufferGc, baseX, baseY); |
| drawVerticalContentArea(bufferGc, baseX, baseY); |
| |
| if (mNinePatchedImage.isValid(mCursorPoint.x, mCursorPoint.y)) { |
| bufferGc.setForeground(BLACK_COLOR); |
| } else if (mIsLockShown) { |
| drawLockArea(bufferGc, baseX, baseY); |
| } |
| |
| // Patches |
| if (mIsPatchesShown) { |
| drawPatchAreas(bufferGc, baseX, baseY); |
| } |
| |
| // Bad patches |
| if (mIsBadPatchesShown) { |
| drawBadPatchAreas(bufferGc, baseX, baseY); |
| } |
| |
| if (mNinePatchedImage.isValid(mCursorPoint.x, mCursorPoint.y)) { |
| bufferGc.setForeground(BLACK_COLOR); |
| } else { |
| bufferGc.setForeground(RED_COLOR); |
| } |
| |
| drawGuideLine(bufferGc, baseX, baseY); |
| |
| bufferGc.dispose(); |
| |
| pe.gc.drawImage(mBufferImage, 0, 0); |
| } |
| |
| private static final Color getColor(int color) { |
| switch (color) { |
| case NinePatchedImage.RED_TICK: |
| return RED_COLOR; |
| default: |
| return BLACK_COLOR; |
| } |
| } |
| |
| private void drawVerticalPatches(GC gc, int baseX, int baseY) { |
| List<Tick> verticalPatches = mNinePatchedImage.getVerticalPatches(); |
| for (Tick t : verticalPatches) { |
| if (t.color != NinePatchedImage.TRANSPARENT_TICK) { |
| gc.setBackground(getColor(t.color)); |
| gc.fillRectangle( |
| baseX, |
| baseY + getZoomedPixelSize(t.start), |
| mZoomedPixelSize, |
| getZoomedPixelSize(t.getLength())); |
| } |
| } |
| } |
| |
| private void drawHorizontalPatches(GC gc, int baseX, int baseY) { |
| List<Tick> horizontalPatches = mNinePatchedImage.getHorizontalPatches(); |
| for (Tick t : horizontalPatches) { |
| if (t.color != NinePatchedImage.TRANSPARENT_TICK) { |
| gc.setBackground(getColor(t.color)); |
| gc.fillRectangle( |
| baseX + getZoomedPixelSize(t.start), |
| baseY, |
| getZoomedPixelSize(t.getLength()), |
| mZoomedPixelSize); |
| } |
| } |
| } |
| |
| private void drawHorizontalContentArea(GC gc, int baseX, int baseY) { |
| List<Tick> horizontalContentArea = mNinePatchedImage.getHorizontalContents(); |
| for (Tick t : horizontalContentArea) { |
| if (t.color != NinePatchedImage.TRANSPARENT_TICK) { |
| gc.setBackground(getColor(t.color)); |
| gc.fillRectangle( |
| baseX + getZoomedPixelSize(t.start), |
| baseY + getZoomedPixelSize(mNinePatchedImage.getHeight() - 1), |
| getZoomedPixelSize(t.getLength()), |
| mZoomedPixelSize); |
| } |
| } |
| |
| } |
| |
| private void drawVerticalContentArea(GC gc, int baseX, int baseY) { |
| List<Tick> verticalContentArea = mNinePatchedImage.getVerticalContents(); |
| for (Tick t : verticalContentArea) { |
| if (t.color != NinePatchedImage.TRANSPARENT_TICK) { |
| gc.setBackground(getColor(t.color)); |
| gc.fillRectangle( |
| baseX + getZoomedPixelSize(mNinePatchedImage.getWidth() - 1), |
| baseY + getZoomedPixelSize(t.start), |
| mZoomedPixelSize, |
| getZoomedPixelSize(t.getLength())); |
| } |
| } |
| } |
| |
| private void drawLockArea(GC gc, int baseX, int baseY) { |
| gc.setAlpha(LOCK_ALPHA); |
| gc.setForeground(LOCK_COLOR); |
| gc.setBackground(LOCK_COLOR); |
| |
| gc.fillRectangle( |
| baseX + mZoomedPixelSize, |
| baseY + mZoomedPixelSize, |
| getZoomedPixelSize(mNinePatchedImage.getWidth() - 2), |
| getZoomedPixelSize(mNinePatchedImage.getHeight() - 2)); |
| gc.setAlpha(NONE_ALPHA); |
| |
| } |
| |
| private void drawPatchAreas(GC gc, int baseX, int baseY) { |
| if (mChunks != null) { |
| int yLen = mChunks.length; |
| int xLen = mChunks[0].length; |
| |
| gc.setAlpha(PATCH_ALPHA); |
| |
| for (int yPos = 0; yPos < yLen; yPos++) { |
| for (int xPos = 0; xPos < xLen; xPos++) { |
| Chunk c = mChunks[yPos][xPos]; |
| |
| if (c.type == Chunk.TYPE_FIXED) { |
| gc.setBackground(BACK_COLOR); |
| } else if (c.type == Chunk.TYPE_HORIZONTAL) { |
| gc.setBackground(PATCH_ONEWAY_COLOR); |
| } else if (c.type == Chunk.TYPE_VERTICAL) { |
| gc.setBackground(PATCH_ONEWAY_COLOR); |
| } else if (c.type == Chunk.TYPE_HORIZONTAL + Chunk.TYPE_VERTICAL) { |
| gc.setBackground(PATCH_COLOR); |
| } |
| Rectangle r = c.rect; |
| gc.fillRectangle( |
| baseX + getZoomedPixelSize(r.x), |
| baseY + getZoomedPixelSize(r.y), |
| getZoomedPixelSize(r.width), |
| getZoomedPixelSize(r.height)); |
| } |
| } |
| } |
| gc.setAlpha(NONE_ALPHA); |
| } |
| |
| private void drawBadPatchAreas(GC gc, int baseX, int baseY) { |
| if (mBadChunks != null) { |
| int yLen = mBadChunks.length; |
| int xLen = mBadChunks[0].length; |
| |
| gc.setAlpha(NONE_ALPHA); |
| gc.setForeground(CORRUPTED_COLOR); |
| gc.setBackground(CORRUPTED_COLOR); |
| |
| for (int yPos = 0; yPos < yLen; yPos++) { |
| for (int xPos = 0; xPos < xLen; xPos++) { |
| Chunk c = mBadChunks[yPos][xPos]; |
| if ((c.type & Chunk.TYPE_CORRUPT) != 0) { |
| Rectangle r = c.rect; |
| gc.drawRectangle( |
| baseX + getZoomedPixelSize(r.x), |
| baseY + getZoomedPixelSize(r.y), |
| getZoomedPixelSize(r.width), |
| getZoomedPixelSize(r.height)); |
| } |
| } |
| } |
| } |
| } |
| |
| private void drawGuideLine(GC gc, int baseX, int baseY) { |
| gc.setAntialias(SWT.ON); |
| gc.setInterpolation(SWT.HIGH); |
| |
| int x = Math.round((mCursorPoint.x * ((float) mZoom / 100) + baseX) |
| + ((float) mZoom / 100 / 2)); |
| int y = Math.round((mCursorPoint.y * ((float) mZoom / 100) + baseY) |
| + ((float) mZoom / 100 / 2)); |
| gc.setAlpha(GUIDE_ALPHA); |
| |
| Point size = getSize(); |
| gc.drawLine(x, 0, x, size.y); |
| gc.drawLine(0, y, size.x, y); |
| |
| gc.setAlpha(NONE_ALPHA); |
| } |
| |
| @Override |
| public void keyPressed(KeyEvent event) { |
| int keycode = event.keyCode; |
| if (keycode == SWT.CTRL) { |
| isCtrlPressed = true; |
| } |
| if (keycode == SWT.SHIFT) { |
| isShiftPressed = true; |
| if (mStatusChangedListener != null) { |
| mStatusChangedListener.helpTextChanged(HELP_MESSAGE_KEY_TIPS2); |
| } |
| } |
| } |
| |
| @Override |
| public void keyReleased(KeyEvent event) { |
| int keycode = event.keyCode; |
| if (keycode == SWT.CTRL) { |
| isCtrlPressed = false; |
| } |
| if (keycode == SWT.SHIFT) { |
| isShiftPressed = false; |
| if (mStatusChangedListener != null) { |
| mStatusChangedListener.helpTextChanged(HELP_MESSAGE_KEY_TIPS); |
| } |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| mBackgroundLayer.dispose(); |
| super.dispose(); |
| } |
| |
| /** |
| * Listen image updated event. |
| */ |
| public interface UpdateListener { |
| /** |
| * 9-patched image has been updated. |
| */ |
| public void update(NinePatchedImage image); |
| } |
| |
| /** |
| * Listen status changed event. |
| */ |
| public interface StatusChangedListener { |
| /** |
| * Mouse cursor position has been changed. |
| */ |
| public void cursorPositionChanged(int x, int y); |
| |
| /** |
| * Help text has been changed. |
| */ |
| public void helpTextChanged(String text); |
| } |
| } |