All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.java.balloontip.positioners.BasicBalloonTipPositioner Maven / Gradle / Ivy

There is a newer version: 1.2.4.1
Show newest version
/**
 * Copyright (c) 2011 Bernhard Pauler, Tim Molderez.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the 3-Clause BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/BSD-3-Clause
 */

package net.java.balloontip.positioners;

import java.awt.Point;
import java.awt.Rectangle;

/**
 * Provides common functionality for the positioner classes
 * LeftAbovePositioner, LeftBelowPositioner, RightAbovePositioner and RightBelowPositioner
 * @author Tim Molderez
 */
public abstract class BasicBalloonTipPositioner extends BalloonTipPositioner {

	protected int x = 0;							// Current position
	protected int y = 0;
	protected int hOffset = 0;						// Current horizontal offset
	protected boolean flipX = false;				// Current orientation
	protected boolean flipY = false;

	protected int preferredHorizontalOffset;		// The preferred value of the horizontal offset
	protected int preferredVerticalOffset;			// The preferred value of the vertical offset
	protected int minimumHorizontalOffset;			// The horizontal offset may not become smaller than this value		

	protected boolean offsetCorrection = true;		// If true, a balloon tip should adjust its horizontal offset when the left/right side collides with the window's border
	protected boolean orientationCorrection = true;	// If true, a balloon tip should flip/mirror itself if otherwise it would become invisible 

	protected boolean fixedAttachLocation = false;	// If true, attachLocationX and attachLocationY should be used to determine the position of the tip

	protected float attachLocationX = 0.0f;			// A percentage that determines the X-location of the tip on the attached object
	protected float attachLocationY = 0.0f;			// A percentage that determines the Y-location of the tip on the attached object
													// For example, if attachLocationX and Y are both 0.5, then the tip is centered on the attached object
	
	/**
	 * Constructor
	 * @param hO	Preferred horizontal offset
	 * @param vO	Preferred vertical offset
	 */
	public BasicBalloonTipPositioner(int hO, int vO) {
		super();
		preferredHorizontalOffset = hO;
		preferredVerticalOffset = vO;
	}
	
	protected void onStyleChange() {
		balloonTip.getStyle().setHorizontalOffset(preferredHorizontalOffset);
		balloonTip.getStyle().setVerticalOffset(preferredVerticalOffset);
		minimumHorizontalOffset = balloonTip.getStyle().getMinimalHorizontalOffset();
	}

	/**
	 * Retrieve the preferred horizontal offset
	 * @return Preferred horizontal offset
	 */
	public int getPreferredHorizontalOffset() {
		return preferredHorizontalOffset;
	}

	/**
	 * Set the preferred horizontal offset
	 * @param preferredHorizontalOffset
	 */
	public void setPreferredHorizontalOffset(int preferredHorizontalOffset) {
		this.preferredHorizontalOffset = preferredHorizontalOffset;
		balloonTip.getStyle().setHorizontalOffset(preferredHorizontalOffset);
		balloonTip.repaint();
	}

	/**
	 * Retrieve the preferred vertical offset
	 * @return Preferred vertical offset
	 */
	public int getPreferredVerticalOffset() {
		return preferredVerticalOffset;
	}

	/**
	 * Set the preferred horizontal offset
	 * @param preferredVerticalOffset
	 */
	public void setPreferredVerticalOffset(int preferredVerticalOffset) {
		this.preferredVerticalOffset = preferredVerticalOffset;
		this.minimumHorizontalOffset = 2 * preferredVerticalOffset;
		balloonTip.getStyle().setVerticalOffset(preferredVerticalOffset);
	}

	/**
	 * Is offset correction enabled?
	 * @return True if offset correction is enabled
	 */
	public boolean isOffsetCorrected() {
		return offsetCorrection;
	}

	/**
	 * Set offset correction
	 * @param offsetCorrection	enabled if true
	 */
	public void enableOffsetCorrection(boolean offsetCorrection) {
		this.offsetCorrection = offsetCorrection;
	}

	/**
	 * Is orientation correction enabled?
	 * @return True if orientation correction is enabled
	 */
	public boolean isOrientationCorrected() {
		return orientationCorrection;
	}

	/**
	 * Set orientation correction
	 * @param orientationCorrection		enabled if true
	 */
	public void enableOrientationCorrection(boolean orientationCorrection) {
		this.orientationCorrection = orientationCorrection;
	}

	/**
	 * Does the tip have a fixed location?
	 * @return True if the balloon has a fixed attaching location
	 */
	public boolean isFixedAttachLocation() {
		return fixedAttachLocation;
	}

	/**
	 * Set whether the tip should have a fixed location
	 * @param fixedAttachLocation	the tip has a fixed location if true
	 */
	public void enableFixedAttachLocation(boolean fixedAttachLocation) {
		this.fixedAttachLocation = fixedAttachLocation;
	}

	/**
	 * Returns the percentage that determines the X-coordinate of the tip within the attached component
	 * (whereas 0.0 is the left side and 1.0 is the right side)
	 * @return The percentage that determines the X-coordinate of the attaching location
	 */
	public float getAttachLocationX() {
		return attachLocationX;
	}

	/**
	 * Returns the percentage that determines the Y-coordinate of the tip within the attached component
	 * (whereas 0.0 is the top and 1.0 is the bottom)
	 * @return The percentage that determines the Y-coordinate of the attaching location
	 */
	public float getAttachLocationY() {
		return attachLocationY;
	}

	/**
	 * Set where the tip should be located, relative to the component the balloon is attached to.
	 * @param attachLocationX	a number from 0.0 to 1.0 (whereas 0 is the left side; 1 is the right side)
	 * @param attachLocationY	a number from 0.0 to 1.0 (whereas 0 is the top; 1 is the bottom)
	 */
	public void setAttachLocation(float attachLocationX, float attachLocationY) {
		this.attachLocationX = attachLocationX;
		this.attachLocationY = attachLocationY;
	}

	public Point getTipLocation() {
		int tipX = x + hOffset;
		int tipY = y + balloonTip.getHeight();

		if (flipX) {
			tipX = x + hOffset;
		}
		if (flipY) {
			tipY = y;
		}

		return new Point(tipX, tipY);
	}

	/*
	 * Applies offset correction to the current position of the balloon tip
	 */
	protected void applyOffsetCorrection() {
		// Check collision with the left side of the window
		int overflow = -x;
		int balloonWidth = balloonTip.getPreferredSize().width;

		if (overflow > 0) {
			x += overflow;
			hOffset -= overflow;
			// Take into account the minimum horizontal offset
			if (hOffset < minimumHorizontalOffset) {
				hOffset = minimumHorizontalOffset;
				if (flipX) {
					x += -overflow +  (balloonWidth - preferredHorizontalOffset) - minimumHorizontalOffset;
				}else {
					x += -overflow +  preferredHorizontalOffset - minimumHorizontalOffset;
				}
			}
		}

		// Check collision with the right side of the window
		overflow = (x+balloonWidth) - balloonTip.getTopLevelContainer().getWidth();
		if (overflow > 0) {
			x -= overflow;
			hOffset += overflow;

			// Take into account the minimum horizontal offset
			if (hOffset > balloonWidth - minimumHorizontalOffset) {
				hOffset = balloonWidth - minimumHorizontalOffset;
				if (flipX) {
					x += overflow + preferredHorizontalOffset + minimumHorizontalOffset;
				}else {
					x += overflow -  (balloonWidth - preferredHorizontalOffset) + minimumHorizontalOffset;
				}
			}
		}		
	}
	
	public void determineAndSetLocation(Rectangle attached) {
		determineLocation(attached);
		
		if (flipX) {
			balloonTip.getStyle().setHorizontalOffset(balloonTip.getPreferredSize().width - hOffset);
		} else {
			balloonTip.getStyle().setHorizontalOffset(hOffset);
		}
		
		balloonTip.getStyle().flip(flipX, flipY);
		balloonTip.setBounds(x, y, balloonTip.getPreferredSize().width, balloonTip.getPreferredSize().height);
		
		balloonTip.revalidate(); // Revalidate is needed in case the balloon gets flipped; validate wouldn't do in that case.
		if (hOffset != preferredHorizontalOffset) {
			balloonTip.repaint(); // In certain cases, when the horizontal offset changes, it doesn't get redrawn properly without a repaint...
		}
	}
	
	/*
	 * Calculates the current position of the balloon tip, but does not apply it yet
	 * @param attached		the balloon tip is attached to this rectangle
	 */
	protected abstract void determineLocation(Rectangle attached);
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy