package tk.amberide.ide.gui.viewer; import tk.amberide.engine.gl.FrameTimer; import tk.amberide.ide.gui.FileViewerPanel; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.*; /** * * @author Tudor */ public class ImageViewerPanel extends FileViewerPanel { protected class ImageViewer extends JComponent { BufferedImage image; double u = 1; JScrollPane container; final ImageViewerPanel owner; public ImageViewer(ImageViewerPanel owner, File file) throws IOException { this.owner = owner; image = ImageIO.read(file); container = new JScrollPane(this); updateSize(); container.getHorizontalScrollBar().setUnitIncrement(16); container.getVerticalScrollBar().setUnitIncrement(16); MouseAdapter adapter = new MouseAdapter() { int lx, ly; @Override public void mousePressed(MouseEvent e) { lx = e.getXOnScreen(); ly = e.getYOnScreen(); if (container.getWidth() < imageWidth() || container.getHeight() < imageHeight()) container.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); requestFocusInWindow(); } @Override public void mouseDragged(MouseEvent e) { moveImage(e); } @Override public void mouseReleased(MouseEvent e) { moveImage(e); container.setCursor(Cursor.getDefaultCursor()); } void moveImage(MouseEvent e) { if (container.getWidth() < imageWidth()) { int dx = lx - e.getXOnScreen(); container.getHorizontalScrollBar().setValue(container.getHorizontalScrollBar().getValue() + dx); } if (container.getHeight() < imageHeight()) { int dy = ly - e.getYOnScreen(); container.getVerticalScrollBar().setValue(container.getVerticalScrollBar().getValue() + dy); } lx = e.getXOnScreen(); ly = e.getYOnScreen(); } }; addMouseMotionListener(adapter); addMouseListener(adapter); addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { if (e.isControlDown()) { double multiplier = e.getUnitsToScroll() < 0 ? 1.3 : 1.0/1.3; u *= multiplier; updateZoom(multiplier); } } }); addKeyListener(new KeyAdapter() { protected FrameTimer timer = new FrameTimer(); @Override public void keyPressed(KeyEvent e) { if (e.getModifiersEx() == 0) { int delta = Math.min(timer.getDelta() / 5, 200); switch (e.getKeyCode()) { case KeyEvent.VK_W: case KeyEvent.VK_UP: container.getVerticalScrollBar().setValue(container.getVerticalScrollBar().getValue() - delta); break; case KeyEvent.VK_S: case KeyEvent.VK_DOWN: container.getVerticalScrollBar().setValue(container.getVerticalScrollBar().getValue() + delta); break; case KeyEvent.VK_A: case KeyEvent.VK_LEFT: container.getHorizontalScrollBar().setValue(container.getHorizontalScrollBar().getValue() - delta); break; case KeyEvent.VK_D: case KeyEvent.VK_RIGHT: container.getHorizontalScrollBar().setValue(container.getHorizontalScrollBar().getValue() + delta); break; } } else if (e.isControlDown()) { double multiplier; switch (e.getKeyCode()) { case KeyEvent.VK_EQUALS: case KeyEvent.VK_PLUS: case KeyEvent.VK_ADD: multiplier = 1.3; u *= multiplier; updateZoom(multiplier); break; case KeyEvent.VK_MINUS: case KeyEvent.VK_SUBTRACT: multiplier = 1./1.3; u *= multiplier; updateZoom(multiplier); break; } } } }); updateStatus(); } private void updateZoom(double multiplier) { JScrollBar sx = container.getHorizontalScrollBar(), sy = container.getVerticalScrollBar(); int vx = sx.getVisibleAmount() / 2, vy = sy.getVisibleAmount() / 2; updateSize(); repaint(); container.revalidate(); sx.setValue((int) ((sx.getValue() + vx) * multiplier) - sx.getVisibleAmount() / 2); sy.setValue((int) ((sy.getValue() + vy) * multiplier) - sx.getVisibleAmount() / 2); updateStatus(); } private void updateStatus() { owner.status.setText(String.format("Image Size: %dx%d, Scaled Size: %dx%d (%.2f%%)", image.getWidth(), image.getHeight(), imageWidth(), imageHeight(), u * 100)); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, imageWidth(), imageHeight(), null); } public int imageWidth() { return (int) (image.getWidth() * u); } public int imageHeight() { return (int) (image.getHeight() * u); } protected void updateSize() { Dimension size = new Dimension(imageWidth(), imageHeight()); setPreferredSize(size); container.setPreferredSize(size); container.updateUI(); } public JComponent getContainer() { return container; } } ImageViewer viewer; JLabel status = new JLabel("Loading image..."); public ImageViewerPanel(File file) { super(file); setLayout(new BorderLayout()); try { add((viewer = new ImageViewer(this, file)).getContainer(), BorderLayout.CENTER); } catch (Exception e) { add(wrap(new JLabel("Failed to load image.")), BorderLayout.CENTER); e.printStackTrace(); status.setText("Failed to load image: " + e.getMessage()); } } protected JScrollPane wrap(JComponent component) { JScrollPane pane = new JScrollPane(component); pane.getHorizontalScrollBar().setUnitIncrement(16); pane.getVerticalScrollBar().setUnitIncrement(16); return pane; } @Override public JMenu[] getContextMenus() { return new JMenu[0]; } @Override public JComponent getStatusBar() { return status; } }