/*
 * 12/23/2008
 *
 * SizeGrip.java - A size grip component that sits at the bottom of the window,
 * allowing the user to easily resize that window.
 * 
 * This library is distributed under a modified BSD license.  See the included
 * RSyntaxTextArea.License.txt file for details.
 */
package org.fife.ui.rsyntaxtextarea.focusabletip;

import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Window;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.MouseInputAdapter;


/**
 * A component that allows its parent window to be resizable, similar to the
 * size grip seen on status bars.
 *
 * @author Robert Futrell
 * @version 1.0
 */
class SizeGrip extends JPanel {

	/**
	 * The size grip to use if we're on OS X.
	 */
	private Image osxSizeGrip;


	public SizeGrip() {
		MouseHandler adapter = new MouseHandler();
		addMouseListener(adapter);
		addMouseMotionListener(adapter);
		setPreferredSize(new Dimension(16, 16));
	}


	/**
	 * Overridden to ensure that the cursor for this component is appropriate
	 * for the orientation.
	 *
	 * @param o The new orientation.
	 */
	@Override
	public void applyComponentOrientation(ComponentOrientation o) {
		possiblyFixCursor(o.isLeftToRight());
		super.applyComponentOrientation(o);
	}


	/**
	 * Creates and returns the OS X size grip image.
	 *
	 * @return The OS X size grip.
	 */
	private Image createOSXSizeGrip() {
		ClassLoader cl = getClass().getClassLoader();
		URL url = cl.getResource("org/fife/ui/rsyntaxtextarea/focusabletip/osx_sizegrip.png");
		if (url==null) {
			// We're not running in a jar - we may be debugging in Eclipse,
			// for example
			File f = new File("../RSyntaxTextArea/src/org/fife/ui/rsyntaxtextarea/focusabletip/osx_sizegrip.png");
			if (f.isFile()) {
				try {
					url = f.toURI().toURL();
				} catch (MalformedURLException mue) { // Never happens
					mue.printStackTrace();
					return null;
				}
			}
			else {
				return null; // Can't find resource or image file
			}
		}
		Image image = null;
		try {
			image = ImageIO.read(url);
		} catch (IOException ioe) { // Never happens
			ioe.printStackTrace();
		}
		return image;
	}


	/**
	 * Paints this panel.
	 *
	 * @param g The graphics context.
	 */
	@Override
	protected void paintComponent(Graphics g) {

		super.paintComponent(g);

		Dimension dim = getSize();

		if (osxSizeGrip!=null) {
			g.drawImage(osxSizeGrip, dim.width-16, dim.height-16, null);
			return;
		}

		Color c1 = UIManager.getColor("Label.disabledShadow");
		Color c2 = UIManager.getColor("Label.disabledForeground");
		ComponentOrientation orientation = getComponentOrientation();

		if (orientation.isLeftToRight()) {
			int width = dim.width  -= 3;
			int height = dim.height -= 3;
			g.setColor(c1);
			g.fillRect(width-9,height-1, 3,3);
			g.fillRect(width-5,height-1, 3,3);
			g.fillRect(width-1,height-1, 3,3);
			g.fillRect(width-5,height-5, 3,3);
			g.fillRect(width-1,height-5, 3,3);
			g.fillRect(width-1,height-9, 3,3);
			g.setColor(c2);
			g.fillRect(width-9,height-1, 2,2);
			g.fillRect(width-5,height-1, 2,2);
			g.fillRect(width-1,height-1, 2,2);
			g.fillRect(width-5,height-5, 2,2);
			g.fillRect(width-1,height-5, 2,2);
			g.fillRect(width-1,height-9, 2,2);
		}
		else {
			int height = dim.height -= 3;
			g.setColor(c1);
			g.fillRect(10,height-1, 3,3);
			g.fillRect(6,height-1, 3,3);
			g.fillRect(2,height-1, 3,3);
			g.fillRect(6,height-5, 3,3);
			g.fillRect(2,height-5, 3,3);
			g.fillRect(2,height-9, 3,3);
			g.setColor(c2);
			g.fillRect(10,height-1, 2,2);
			g.fillRect(6,height-1, 2,2);
			g.fillRect(2,height-1, 2,2);
			g.fillRect(6,height-5, 2,2);
			g.fillRect(2,height-5, 2,2);
			g.fillRect(2,height-9, 2,2);
		}

	}


	/**
	 * Ensures that the cursor for this component is appropriate for the
	 * orientation.
	 *
	 * @param ltr Whether the current component orientation is LTR.
	 */
	protected void possiblyFixCursor(boolean ltr) {
		int cursor = Cursor.NE_RESIZE_CURSOR;
		if (ltr) {
			cursor = Cursor.NW_RESIZE_CURSOR;
		}
		if (cursor!=getCursor().getType()) {
			setCursor(Cursor.getPredefinedCursor(cursor));
		}
	}


	@Override
	public void updateUI() {
		super.updateUI();
		// TODO: Key off of Aqua LaF, not just OS X, as this size grip looks
		// bad on other LaFs on Mac such as Nimbus.
		if (System.getProperty("os.name").contains("OS X")) {
			if (osxSizeGrip==null) {
				osxSizeGrip = createOSXSizeGrip();
			}
		}
		else { // Clear memory in case of runtime LaF change.
			osxSizeGrip = null;
		}

	}


	/**
	 * Listens for mouse events on this panel and resizes the parent window
	 * appropriately.
	 */
	/*
	 * NOTE: We use SwingUtilities.convertPointToScreen() instead of just using
	 * the locations relative to the corner component because the latter proved
	 * buggy - stretch the window too wide and some kind of arithmetic error
	 * started happening somewhere - our window would grow way too large.
	 */
	private class MouseHandler extends MouseInputAdapter {

		private Point origPos;

		@Override
		public void mouseDragged(MouseEvent e) {
			Point newPos = e.getPoint();
			SwingUtilities.convertPointToScreen(newPos, SizeGrip.this);
			int xDelta = newPos.x - origPos.x;
			int yDelta = newPos.y - origPos.y;
			Window wind = SwingUtilities.getWindowAncestor(SizeGrip.this);
			if (wind!=null) { // Should always be true
				if (getComponentOrientation().isLeftToRight()) {
					int w = wind.getWidth();
					if (newPos.x>=wind.getX()) {
						w += xDelta;
					}
					int h = wind.getHeight();
					if (newPos.y>=wind.getY()) {
						h += yDelta;
					}
					wind.setSize(w,h);
				}
				else { // RTL
					int newW = Math.max(1, wind.getWidth()-xDelta);
					int newH = Math.max(1, wind.getHeight()+yDelta);
					wind.setBounds(newPos.x, wind.getY(), newW, newH);
				}
				// invalidate()/validate() needed pre-1.6.
				wind.invalidate();
				wind.validate();
			}
			origPos.setLocation(newPos);
		}

		@Override
		public void mousePressed(MouseEvent e) {
			origPos = e.getPoint();
			SwingUtilities.convertPointToScreen(origPos, SizeGrip.this);
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			origPos = null;
		}

	}


}