/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.ui; import javax.swing.JComponent; import javax.swing.JLabel; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.image.BufferedImage; /** * A component representing an image display with a draggable slider box in it. */ public class SliderBoxImageDisplay extends JComponent { private static final int HANDLE_SIZE = 6; private BufferedImage image; private final int imageWidth; private final int imageHeight; private final SliderBoxChangeListener sliderBoxChangeListener; private final JComponent sliderBox; private int sliderSectionX; private int sliderSectionY; private Rectangle sliderRectOld; private Point clickPos; private boolean imageWidthFixed; private boolean imageHeightFixed; public SliderBoxImageDisplay(int imageWidth, int imageHeight, SliderBoxChangeListener sliderBoxChangeListener) { this.imageWidth = imageWidth; this.imageHeight = imageHeight; this.sliderBoxChangeListener = sliderBoxChangeListener; sliderBox = new JLabel(); sliderBox.setBounds(0, 0, 1, 1); sliderBox.setOpaque(false); sliderBox.setBorder(UIDefaults.SLIDER_BOX_BORDER); setLayout(null); setPreferredSize(new Dimension(imageWidth, imageHeight)); add(sliderBox); clearSliderSections(); addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { sliderRectOld = new Rectangle(sliderBox.getBounds()); clickPos = new Point(e.getPoint()); computeSliderSections(e); } @Override public void mouseReleased(MouseEvent e) { sliderRectOld = null; clickPos = null; clearSliderSections(); } }); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseDragged(MouseEvent e) { if (sliderRectOld == null || clickPos == null) { return; } modifySliderBox(e); } }); } public void setImage(BufferedImage image) { this.image = image; setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); repaint(); } @Override protected void paintComponent(Graphics graphics) { graphics.setColor(getBackground()); if (image != null) { graphics.drawImage(image, 0, 0, null); } } public boolean isImageWidthFixed() { return imageWidthFixed; } public void setImageWidthFixed(boolean imageWidthFixed) { if (this.imageWidthFixed == imageWidthFixed) { return; } this.imageWidthFixed = imageWidthFixed; if (this.imageWidthFixed) { setSliderBoxBounds(0, sliderBox.getY(), imageWidth, sliderBox.getHeight(), true); } } public boolean isImageHeightFixed() { return imageHeightFixed; } public void setImageHeightFixed(boolean imageHeightFixed) { if (this.imageHeightFixed == imageHeightFixed) { return; } this.imageHeightFixed = imageHeightFixed; if (this.imageHeightFixed) { setSliderBoxBounds(sliderBox.getX(), 0, sliderBox.getWidth(), imageHeight, true); } } public SliderBoxChangeListener getSliderBoxChangeListener() { return sliderBoxChangeListener; } public Rectangle getSliderBoxBounds() { return sliderBox.getBounds(); } public void setSliderBoxBounds(Rectangle rectangle) { setSliderBoxBounds(rectangle, false); } public void setSliderBoxBounds(Rectangle rectangle, boolean fireEvent) { setSliderBoxBounds(rectangle.x, rectangle.y, rectangle.width, rectangle.height, fireEvent); } public void setSliderBoxBounds(int x, int y, int width, int height) { setSliderBoxBounds(x, y, width, height, false); } public void setSliderBoxBounds(int x, int y, int width, int height, boolean fireEvent) { if (isImageWidthFixed()) { x = 0; width = imageWidth; } if (isImageHeightFixed()) { y = 0; height = imageHeight; } if (sliderBox.getX() == x && sliderBox.getY() == y && sliderBox.getWidth() == width && sliderBox.getHeight() == height) { return; } sliderBox.setBounds(x, y, width, height); // also repaints! if (sliderBoxChangeListener != null && fireEvent) { sliderBoxChangeListener.sliderBoxChanged(sliderBox.getBounds()); } } private void clearSliderSections() { sliderSectionX = -1; sliderSectionY = -1; } private void computeSliderSections(MouseEvent e) { int x = e.getX(); int y = e.getY(); int x1 = sliderBox.getX(); int y1 = sliderBox.getY(); int x2 = sliderBox.getX() + sliderBox.getWidth(); int y2 = sliderBox.getY() + sliderBox.getHeight(); int dx1 = Math.abs(x1 - x); int dy1 = Math.abs(y1 - y); int dx2 = Math.abs(x2 - x); int dy2 = Math.abs(y2 - y); sliderSectionX = -1; if (dx1 <= HANDLE_SIZE) { sliderSectionX = 0; // left slider handle selected } else if (dx2 <= HANDLE_SIZE) { sliderSectionX = 2; // right slider handle selected } else if (x >= x1 && x < x2) { sliderSectionX = 1; // center slioder handle selected } sliderSectionY = -1; if (dy1 <= HANDLE_SIZE) { sliderSectionY = 0; // upper slider handle selected } else if (dy2 <= HANDLE_SIZE) { sliderSectionY = 2; // lower slider handle selected } else if (y > y1 && y < y2) { sliderSectionY = 1; // center slider handle selected } } private void modifySliderBox(MouseEvent e) { int x = e.getX(); int y = e.getY(); int dx = x - clickPos.x; int dy = y - clickPos.y; int sbx = 0; int sby = 0; int sbw = 0; int sbh = 0; boolean validMode = false; if (sliderSectionX == 0 && sliderSectionY == 0) { sbx = sliderRectOld.x + dx; sby = sliderRectOld.y + dy; sbw = sliderRectOld.width - dx; sbh = sliderRectOld.height - dy; validMode = true; } else if (sliderSectionX == 1 && sliderSectionY == 0) { sbx = sliderRectOld.x; sby = sliderRectOld.y + dy; sbw = sliderRectOld.width; sbh = sliderRectOld.height - dy; validMode = true; } else if (sliderSectionX == 2 && sliderSectionY == 0) { sbx = sliderRectOld.x; sby = sliderRectOld.y + dy; sbw = sliderRectOld.width + dx; sbh = sliderRectOld.height - dy; validMode = true; } else if (sliderSectionX == 0 && sliderSectionY == 1) { sbx = sliderRectOld.x + dx; sby = sliderRectOld.y; sbw = sliderRectOld.width - dx; sbh = sliderRectOld.height; validMode = true; } else if (sliderSectionX == 1 && sliderSectionY == 1) { sbx = sliderRectOld.x + dx; sby = sliderRectOld.y + dy; sbw = sliderRectOld.width; sbh = sliderRectOld.height; validMode = true; } else if (sliderSectionX == 2 && sliderSectionY == 1) { sbx = sliderRectOld.x; sby = sliderRectOld.y; sbw = sliderRectOld.width + dx; sbh = sliderRectOld.height; validMode = true; } else if (sliderSectionX == 0 && sliderSectionY == 2) { sbx = sliderRectOld.x + dx; sby = sliderRectOld.y; sbw = sliderRectOld.width - dx; sbh = sliderRectOld.height + dy; validMode = true; } else if (sliderSectionX == 1 && sliderSectionY == 2) { sbx = sliderRectOld.x; sby = sliderRectOld.y; sbw = sliderRectOld.width; sbh = sliderRectOld.height + dy; validMode = true; } else if (sliderSectionX == 2 && sliderSectionY == 2) { sbx = sliderRectOld.x; sby = sliderRectOld.y; sbw = sliderRectOld.width + dx; sbh = sliderRectOld.height + dy; validMode = true; } if (validMode && sbw > 2 && sbh > 2) { setSliderBoxBounds(sbx, sby, sbw, sbh, true); } } public static interface SliderBoxChangeListener { void sliderBoxChanged(Rectangle sliderBoxBounds); } }