/GHPC_Source/org/lateralgm/components/visual/VisualPanel.java
https://github.com/piluke/GameMaker-HTML5-Player · Java · 271 lines · 230 code · 34 blank · 7 comment · 33 complexity · 40795ae2bae3be5d44758bc1e9c1a041 MD5 · raw file
- /*
- * Copyright (C) 2009 Quadduc <quadduc@gmail.com>
- *
- * This file is part of LateralGM.
- * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
- * See LICENSE for details.
- */
- package org.lateralgm.components.visual;
- import static org.lateralgm.main.Util.negDiv;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.Point;
- import java.awt.Rectangle;
- import java.awt.RenderingHints;
- import java.util.TreeMap;
- import javax.swing.JPanel;
- import org.lateralgm.ui.swing.visuals.BoundedVisual;
- import org.lateralgm.ui.swing.visuals.Visual;
- import org.lateralgm.ui.swing.visuals.VisualContainer;
- public class VisualPanel extends JPanel
- {
- private static final long serialVersionUID = 1L;
- public static final Point ORIGIN_MOUSE = new Point();
- private final TreeMap<Integer,Visual> visuals = new TreeMap<Integer,Visual>();
- private final Rectangle overallBounds = new Rectangle();
- public final VisualContainer container = new PanelVisualContainer();
- private int zoom = 1;
- protected Point zoomOrigin;
- private boolean boundsLocked = false;
- private boolean boundsUpdated = false;
- public VisualPanel()
- {
- setBackground(Color.GRAY);
- setOpaque(true);
- }
- protected void componentToVisual(Point p)
- {
- componentToVisual(p,zoom);
- }
- protected void componentToVisual(Point p, int z)
- {
- p.x = zoom(p.x - visualOffsetX(z),2 - z) + overallBounds.x;
- p.y = zoom(p.y - visualOffsetY(z),2 - z) + overallBounds.y;
- }
- protected void componentToVisual(Rectangle r, int z)
- {
- Point p = r.getLocation();
- componentToVisual(p,z);
- r.setLocation(p);
- r.width = zoom(r.width,2 - z);
- r.height = zoom(r.height,2 - z);
- }
- protected void visualToComponent(Point p)
- {
- visualToComponent(p,zoom);
- }
- protected void visualToComponent(Point p, int z)
- {
- p.x = zoom(p.x - overallBounds.x,z) + visualOffsetX(z);
- p.y = zoom(p.y - overallBounds.y,z) + visualOffsetY(z);
- }
- protected void visualToComponent(Rectangle r, int z)
- {
- Point p = r.getLocation();
- visualToComponent(p,z);
- r.setLocation(p);
- r.width = zoom(r.width,z);
- r.height = zoom(r.height,z);
- }
- protected double zoom(double d, int z)
- {
- return z > 0 ? z * d : d / (2 - z);
- }
- protected int zoom(int i, int z)
- {
- return z > 0 ? z * i : negDiv(i,2 - z);
- }
- protected int zoomAlign(int i, int z, boolean ceil)
- {
- return z <= 0 ? (2 - z) * negDiv(i + (ceil ? 1 - z : 0),2 - z) : i;
- }
- protected void zoomAlign(Rectangle r, int z, boolean out)
- {
- int x0 = zoomAlign(r.x,z,!out);
- int y0 = zoomAlign(r.y,z,!out);
- r.setBounds(x0,y0,zoomAlign(r.width + r.x - x0,z,out),zoomAlign(r.height + r.y - y0,z,out));
- }
- protected void zoom(Rectangle r, int z)
- {
- r.x = zoom(r.x,z);
- r.y = zoom(r.y,z);
- r.width = zoom(r.width,z);
- r.height = zoom(r.height,z);
- }
- protected int visualOffsetX(int z)
- {
- return (getWidth() - zoom(overallBounds.width,z)) / 2;
- }
- protected int visualOffsetY(int z)
- {
- return (getHeight() - zoom(overallBounds.height,z)) / 2;
- }
- protected Rectangle getOverallBounds(Rectangle r)
- {
- if (r == null) return new Rectangle(overallBounds);
- r.setBounds(overallBounds);
- return r;
- }
- protected void calculateOverallBounds(Rectangle b)
- {
- b.grow(128,128);
- b.add(0,0);
- }
- @Override
- public Dimension getPreferredSize()
- {
- Dimension s = overallBounds.getSize();
- s.width = zoom(s.width,zoom);
- s.height = zoom(s.height,zoom);
- return s;
- }
- @Override
- public Dimension getMinimumSize()
- {
- return getPreferredSize();
- }
- @Override
- public void paintComponent(Graphics g)
- {
- super.paintComponent(g);
- Graphics g2 = g.create();
- if (g2.getClip() == null) g2.setClip(0,0,getWidth(),getHeight());
- g2.translate(visualOffsetX(zoom),visualOffsetY(zoom));
- if (zoom != 1)
- {
- double s = zoom(1.0,zoom);
- Graphics2D g3 = ((Graphics2D) g2);
- g3.scale(s,s);
- g3.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- zoom < 1 ? RenderingHints.VALUE_INTERPOLATION_BILINEAR
- : RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
- }
- g2.translate(-overallBounds.x,-overallBounds.y);
- paintVisuals(g2);
- g2.dispose();
- }
- protected void paintVisuals(Graphics g)
- {
- for (Visual v : visuals.values())
- v.paint(g);
- }
- public void put(int layer, Visual v)
- {
- Visual pv = v == null ? visuals.remove(layer) : visuals.put(layer,v);
- if (pv == v) return;
- if (v instanceof BoundedVisual || pv instanceof BoundedVisual) container.updateBounds();
- repaint();
- }
- protected void lockBounds()
- {
- boundsLocked = true;
- }
- protected void unlockBounds()
- {
- boundsLocked = false;
- if (boundsUpdated)
- {
- container.updateBounds();
- boundsUpdated = false;
- }
- }
- private class PanelVisualContainer implements VisualContainer
- {
- private int oldZoom = zoom;
- public void repaint(Rectangle r)
- {
- if (r == null)
- VisualPanel.this.repaint();
- else
- {
- Rectangle cr = r.getBounds();
- zoomAlign(cr,zoom,true);
- visualToComponent(cr,zoom);
- VisualPanel.this.repaint(cr);
- }
- }
- public void updateBounds()
- {
- boolean uob = (!boundsLocked);
- if (boundsLocked) boundsUpdated = true;
- boolean uz = zoom != oldZoom;
- if (!uob && !uz) return;
- Point o = zoomOrigin;
- Point co;
- if (o == null || o == ORIGIN_MOUSE)
- {
- co = o == null ? null : getMousePosition();
- if (co == null)
- {
- Rectangle vr = getVisibleRect();
- co = new Point(vr.x + vr.width / 2,vr.y + vr.height / 2);
- }
- o = co.getLocation();
- componentToVisual(o,oldZoom);
- }
- else
- {
- co = o.getLocation();
- visualToComponent(co,oldZoom);
- }
- Rectangle oob = overallBounds.getBounds();
- if (uob)
- {
- overallBounds.setSize(-1,-1);
- for (Visual v : visuals.values())
- if (v instanceof BoundedVisual) ((BoundedVisual) v).extendBounds(overallBounds);
- calculateOverallBounds(overallBounds);
- }
- zoomAlign(overallBounds,zoom,true);
- if (oob.equals(overallBounds) && !uz) return;
- Point p = getLocation();
- setBounds(p.x + co.x - zoom(o.x - overallBounds.x,zoom),p.y + co.y
- - zoom(o.y - overallBounds.y,zoom),Math.max(getWidth(),zoom(overallBounds.width,zoom)),
- Math.max(getHeight(),zoom(overallBounds.height,zoom)));
- oldZoom = zoom;
- revalidate();
- }
- }
- public void setZoom(int z)
- {
- if (zoom == z) return;
- zoom = z;
- container.updateBounds();
- }
- }