// Copyright (c) 2006 - 2008, Markus Strauch.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
package net.sf.sdedit.ui.components;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Observable;
import java.util.Observer;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MouseInputListener;
import net.sf.sdedit.icons.Icons;
/*
* TODO: parameterize the "scaling curve"
*/
public class ScalePanel extends JPanel implements Observer,
MouseInputListener {
private final static long serialVersionUID = 0xAB343925;
private static ImageIcon fitHeightIcon = Icons.getIcon("large/fit_height");
private static ImageIcon fitWidthIcon = Icons.getIcon("large/fit_width");
private static ImageIcon fitWindowIcon = Icons.getIcon("large/fit_window");
private static ImageIcon normalSizeIcon = Icons.getIcon("large/normalsize");
private JSlider scaleSlider;
private JLabel sliderLabel;
private Scalable scalable;
private Point root = null;
private int initialValue;
public ScalePanel(boolean showButtons) {
super();
setLayout(new BorderLayout());
sliderLabel = new JLabel();
sliderLabel.setToolTipText("Zoom factor");
sliderLabel.setPreferredSize(new Dimension(40, 1));
sliderLabel.setOpaque(false);
add(sliderLabel, BorderLayout.WEST);
scaleSlider = new JSlider(1, 400, 100);
scaleSlider.setPreferredSize(new Dimension(100, 0));
scaleSlider.setMaximumSize(new Dimension(100, 0));
scaleSlider.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked (MouseEvent e) {
if (ScalePanel.this.isEnabled() &&
e.getClickCount() == 2 &&
e.getButton() == MouseEvent.BUTTON1) {
scalable.setScale(1);
}
}
});
scaleSlider.setOpaque(false);
scaleSlider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
double scale = scaleSlider.getValue() * scaleSlider.getValue()
/ 40000D;
scale = Math.max(0.01, scale);
scalable.setScale(scale);
}
});
add(scaleSlider, BorderLayout.CENTER);
if (showButtons) {
JPanel sliderButtonsPanel = new JPanel();
sliderButtonsPanel.setLayout(new GridLayout(1, 4));
JButton normalSizeButton = new JButton(normalSizeAction);
JButton fitHeightButton = new JButton(fitHeightAction);
JButton fitWidthButton = new JButton(fitWidthAction);
JButton fitWindowButton = new JButton(fitWindowAction);
normalSizeButton.setMargin(new Insets(1, 1, 1, 1));
normalSizeButton.setOpaque(false);
fitHeightButton.setMargin(new Insets(1, 1, 1, 1));
fitHeightButton.setOpaque(false);
fitWidthButton.setMargin(new Insets(1, 1, 1, 1));
fitWidthButton.setOpaque(false);
fitWindowButton.setMargin(new Insets(1, 1, 1, 1));
fitWindowButton.setOpaque(false);
sliderButtonsPanel.add(normalSizeButton);
sliderButtonsPanel.add(fitHeightButton);
sliderButtonsPanel.add(fitWidthButton);
sliderButtonsPanel.add(fitWindowButton);
sliderButtonsPanel.setOpaque(false);
add(sliderButtonsPanel, BorderLayout.EAST);
}
}
public final Action fitWidthAction = new AbstractAction() {
{
putValue(Action.SHORT_DESCRIPTION, "Fit width");
putValue(Action.SMALL_ICON, fitWidthIcon);
}
public void actionPerformed(ActionEvent e) {
fitWidth();
}
};
public final Action fitHeightAction = new AbstractAction() {
{
putValue(Action.SHORT_DESCRIPTION, "Fit height");
putValue(Action.SMALL_ICON, fitHeightIcon);
}
public void actionPerformed(ActionEvent e) {
fitHeight();
}
};
public final Action fitWindowAction = new AbstractAction() {
{
putValue(Action.SHORT_DESCRIPTION, "Fit window");
putValue(Action.SMALL_ICON, fitWindowIcon);
}
public void actionPerformed(ActionEvent e) {
fitWindow();
}
};
public final Action normalSizeAction = new AbstractAction() {
{
putValue(Action.SHORT_DESCRIPTION, "Zoom to 100 %");
putValue(Action.SMALL_ICON, normalSizeIcon);
}
public void actionPerformed(ActionEvent e) {
normalsize();
}
};
private void normalsize () {
if (scalable != null) {
scalable.setScale(1);
}
}
private void fitWidth() {
if (scalable != null) {
scalable.fitWidth();
}
}
private void fitHeight() {
if (scalable != null) {
scalable.fitHeight();
}
}
private void fitWindow() {
if (scalable != null) {
scalable.fitSize();
}
}
public void setScalable(final Scalable scalable) {
scalable.asObservable().deleteObservers();
scalable.asObservable().addObserver(this);
this.scalable = scalable;
update(scalable.asObservable(), scalable);
}
public JSlider getSlider() {
return scaleSlider;
}
public void mouseClicked(MouseEvent e) { /* empty */ }
public void mouseEntered(MouseEvent e) { /* empty */ }
public void mouseExited(MouseEvent e) { /* empty */ }
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
root = e.getPoint();
initialValue = scaleSlider.getValue();
}
}
public void mouseReleased(MouseEvent e) {
root = null;
}
@Override
public void setEnabled(boolean on) {
super.setEnabled(on);
scaleSlider.setEnabled(on);
sliderLabel.setEnabled(on);
}
public void mouseDragged(MouseEvent e) {
if (root != null) {
int dist = (root.y - e.getPoint().y) / 4;
if (Math.abs(dist) > 0) {
int newValue = initialValue + dist;
newValue = Math.max(newValue, scaleSlider.getMinimum());
newValue = Math.min(newValue, scaleSlider.getMaximum());
scaleSlider.setValue(newValue);
}
}
}
public void mouseMoved(MouseEvent e) { /* empty */ }
public synchronized void update(Observable o, Object arg) {
Scalable _scalable = (Scalable) arg;
double scale = _scalable.getScale();
int s = (int) (200 * Math.sqrt(scale));
String text = (int) (scale * 100) + " %";
sliderLabel.setText(text);
scaleSlider.setValue(s);
}
}