/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2015 Broad Institute
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* ZoomSliderPanel.java
*
* Created on September 25, 2007, 12:03 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.broad.igv.ui.panel;
import org.broad.igv.ui.util.IconFactory;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* @author jrobinso
*/
public class ZoomSliderPanel extends JPanel {
static Color TICK_GRAY = new Color(90, 90, 90);
static Color TICK_BLUE = new Color(25, 50, 200);
//double imageScaleFactor = 0.8;
Image slider;
Image zoomPlus;
Image zoomMinus;
Rectangle zoomPlusRect;
Rectangle zoomMinusRect;
Rectangle[] zoomLevelRects;
/**
* Should correspond to "maxZoomLevel" in class referenceFrame.
*/
int numZoomLevels = 25;
private int minZoomLevel = 0;
/**
* Set the allowed zoom level, user cannot zoom out past this level
*
* @param minZoomLevel
*/
public void setMinZoomLevel(int minZoomLevel){
this.minZoomLevel = minZoomLevel;
}
private static final Color TRANSPARENT_GRAY = new Color(200, 200, 200, 150);
private ReferenceFrame referenceFrame;
public ZoomSliderPanel(){
this(null);
}
/**
* @param referenceFrame The ReferenceFrame whose zoom level this panel will control
*/
public ZoomSliderPanel(ReferenceFrame referenceFrame) {
this.referenceFrame = referenceFrame;
slider = IconFactory.getInstance().getIcon(IconFactory.IconID.SLIDER).getImage();
zoomPlus = IconFactory.getInstance().getIcon(IconFactory.IconID.ZOOM_PLUS).getImage();
zoomMinus = IconFactory.getInstance().getIcon(IconFactory.IconID.ZOOM_MINUS).getImage();
zoomLevelRects = new Rectangle[numZoomLevels];
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
init();
}
private void updateTickCount() {
int tmp = getReferenceFrame().getMaxZoom() + 1;
if (tmp != numZoomLevels) {
numZoomLevels = tmp;
zoomLevelRects = new Rectangle[numZoomLevels];
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
updateTickCount();
//if (this.isEnabled()) {
paintHorizontal(g);
//}
}
protected void paintHorizontal(Graphics g) {
Graphics2D transGraphics = (Graphics2D) g.create();
transGraphics.setColor(TRANSPARENT_GRAY);
int buttonWidth = zoomPlus.getWidth(null);
int buttonHeight = zoomPlus.getHeight(null);
Insets insets = getInsets();
int panelWidth = getWidth() - insets.left - insets.right;
int panelHeight = getHeight() - insets.top - insets.bottom;
final boolean enabled = isEnabled();
g.setColor(enabled ? Color.BLACK : Color.LIGHT_GRAY);
double x = insets.left;
double xStep = ((double) (panelWidth - 2 * buttonWidth - 10)) / (numZoomLevels);
int y = insets.top + (panelHeight - buttonHeight) / 2;
g.drawImage(zoomMinus, (int) x, y, null);
zoomMinusRect = new Rectangle((int) x, y, buttonWidth, buttonHeight);
if (!isEnabled()) {
transGraphics.fill(zoomMinusRect);
}
x += 5 + buttonWidth;
int lastX = (int) (x - xStep);
for (int i = 0; i < numZoomLevels; i++) {
Rectangle zoomRect = new Rectangle((int) x, y, (int) (x - lastX), buttonHeight);
int xLine = (int) (x + xStep / 2);
g.drawLine(xLine, y + 3, xLine, y + buttonHeight - 4);
zoomLevelRects[i] = zoomRect;
lastX = (int) x;
x += xStep;
}
x += 5;
y = insets.top + panelHeight / 2 - 1;
//g.drawLine(xTop, y, xBottom, y);
y = insets.top + (panelHeight - buttonHeight) / 2;
//if (isEnabled()) {
g.drawImage(zoomPlus, (int) x, y, null);
//}
zoomPlusRect = new Rectangle((int) x, y, buttonWidth, buttonWidth);
if (!isEnabled()) {
transGraphics.fill(zoomPlusRect);
}
// Draw current level -- zoomIndex is the zoom level + 1.
int zoom = (toolZoom >= 0 ? toolZoom : getReferenceFrame().getAdjustedZoom());
if (enabled) {
if (zoom >= 0 && zoom < zoomLevelRects.length) {
Rectangle rect = zoomLevelRects[zoom];
g.setColor(TICK_BLUE);
g.fill3DRect(
(int) (rect.getX() + rect.getWidth() / 2) - 3,
(int) rect.getY(),
6,
(int) rect.getHeight(),
true);
//y = (int) (rect.getY() + (rect.getHeight() - slider.getHeight(null)) / 2);
// temporary hack
//if(zoomIndex == 12) y += 15;
//g.drawImage(slider, x + 1, y, null);
}
}
transGraphics.dispose();
}
int setZoom(MouseEvent e) {
if (zoomPlusRect.contains(e.getX(), e.getY())) {
toolZoom++;
} else if (zoomMinusRect.contains(e.getX(), e.getY()) && toolZoom > minZoomLevel) {
toolZoom--;
} else {
for (int i = 0; i < zoomLevelRects.length; i++) {
Rectangle rect = zoomLevelRects[i];
if (rect.contains(e.getX(), e.getY()) && i >= minZoomLevel) {
toolZoom = i;
}
}
}
return toolZoom;
}
private ReferenceFrame getReferenceFrame() {
if(referenceFrame == null) return FrameManager.getDefaultFrame();
return referenceFrame;
}
int toolZoom = -1;
private void init() {
MouseInputAdapter mouseAdapter = new MouseInputAdapter() {
int lastMousePressX = 0;
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
if (!isEnabled()) {
return;
}
toolZoom = Math.max(0, getReferenceFrame().getAdjustedZoom());
}
@Override
public void mouseReleased(MouseEvent e) {
if (!isEnabled()) {
return;
}
//Sometimes the zoom doesn't change, don't need to do anything in that case
int oldToolZoom = toolZoom;
int diff = setZoom(e) - oldToolZoom;
if(diff == 0) {
toolZoom = -1;
return;
}
repaint();
int effectiveZoom = toolZoom + getReferenceFrame().getMinZoom();
getReferenceFrame().changeZoom(effectiveZoom);
toolZoom = -1;
}
@Override
public void mouseDragged(MouseEvent e) {
// Dragging zoom tool is disable. Generates too many
// repaint events.
setZoom(e);
repaint();
}
};
addMouseMotionListener(mouseAdapter);
addMouseListener(mouseAdapter);
}
}