This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 134147 - AlignWithSupport.locationSuggested handles differently x and y movements
Summary: AlignWithSupport.locationSuggested handles differently x and y movements
Status: NEW
Alias: None
Product: platform
Classification: Unclassified
Component: Graph (show other bugs)
Version: 6.x
Hardware: Macintosh All
: P3 blocker (vote)
Assignee: issues@platform
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-04-29 10:56 UTC by crosati
Modified: 2010-04-01 14:46 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description crosati 2008-04-29 10:56:51 UTC
In the code (NB 6.0) of AlignWithSupport.locationSuggested y movement handling didn't use the "bothSides" flag, working as it is set always to true.

The following implementation solves the problem and adds handling for "snap to centers" movements:


public class FEPAlignWithSupport
{

	private static final int GRAVITY = 10;

	private int							gravity;
	private AlignWithWidgetCollector	collector;
	private LayerWidget					interractionLayer;
	private AlignWithMoveDecorator		decorator;
	private ConnectionWidget			lineWidget1;
	private ConnectionWidget			lineWidget2;

	public FEPAlignWithSupport (
		AlignWithWidgetCollector	collector,
		LayerWidget					interractionLayer,
		AlignWithMoveDecorator		decorator
	)
	{
		this(collector, interractionLayer, decorator, GRAVITY);
	}

	public FEPAlignWithSupport (
		AlignWithWidgetCollector	collector,
		LayerWidget					interractionLayer,
		AlignWithMoveDecorator		decorator,
		int							gravity
	)
	{
		this.collector         = collector;
		this.interractionLayer = interractionLayer;
		this.decorator         = decorator;
		this.gravity           = gravity;
	}

	public int getGravity ( )
	{
		return gravity;
	}

	public void hide ( )
	{
		if ( interractionLayer != null )
		{
			interractionLayer.removeChild(lineWidget1);
			interractionLayer.removeChild(lineWidget2);
		}
	}

	protected Point locationSuggested (
		Widget		widget,
		Rectangle	sceneWidgetBounds,
		Point		suggestedLocation,
		boolean		horizontal,
		boolean		vertical,
		boolean		bothSides,
		boolean		centers,
		boolean		snapHack
	)
	{

		Point					point   = new Point(suggestedLocation);
		Collection<Rectangle>	regions = collector.getRegions(widget);

		if ( horizontal )
		{

			boolean	snap = false;
			int		xs   = 0;
			int		x    = 0;
			int		dx   = 0;
			int		y1   = 0;
			int		y2   = 0;
			int     b1   = sceneWidgetBounds.x;
			int     b2   = sceneWidgetBounds.x + sceneWidgetBounds.width;
			int		b3   = sceneWidgetBounds.x + sceneWidgetBounds.width / 2;

			for ( Rectangle rectangle : regions )
			{

				int		d;
				int		a1      = rectangle.x;
				int		a2      = a1 + rectangle.width;
				int		a3      = a1 + rectangle.width / 2;
				boolean	snapNow = false;

				if ( centers )
				{

					d = Math.abs(a3 - b3);

					if ( ( snap && d < dx ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						x       = a3;
						xs      = a3 - sceneWidgetBounds.width / 2;
						dx      = d;
					}

				}

				d = Math.abs(a1 - b1);

				if ( ( snap && d < dx ) || ( ! snap && d < gravity ) )
				{
					snap    = true;
					snapNow = true;
					x       = a1;
					xs      = a1;
					dx      = d;
				}

				if ( bothSides )
				{

					d = Math.abs(a1 - b2);

					if ( ( snap && d < dx ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						x       = a1;
						xs      = a1 - sceneWidgetBounds.width;
						dx      = d;
					}

				}

				d = Math.abs(a2 - b1);

				if ( ( snap && d < dx ) || ( ! snap && d < gravity ) )
				{
					snap    = true;
					snapNow = true;
					x       = a2;
					xs      = a2;
					dx      = d;
				}

				if ( bothSides )
				{

					d = Math.abs(a2 - b2);

					if ( ( snap && d < dx ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						x       = a2;
						xs      = a2 - sceneWidgetBounds.width;
						dx      = d;
					}

				}

				if ( snapNow )
				{
					y1 = rectangle.y;
					y2 = rectangle.y + rectangle.height;
				}

			}

			if ( snap )
			{

				point.x = xs;

				if ( snapHack )
					point.x -= widget.getBounds().x;

			}


			if ( interractionLayer != null )
			{
				lineWidget1.setControlPoints(
					snap
				  ? Arrays.asList(
						new Point(x, Math.min(sceneWidgetBounds.y, y1)),
						new Point(x, Math.max(sceneWidgetBounds.y + sceneWidgetBounds.height, y2))
					)
				  : Collections.<Point>emptyList(),
					true
				);
			}

		}

		if ( vertical )
		{

			boolean	snap = false;
			int		ys   = 0;
			int		y    = 0;
			int		dy   = 0;
			int		x1   = 0;
			int		x2   = 0;
			int		b1   = sceneWidgetBounds.y;
			int		b2   = sceneWidgetBounds.y + sceneWidgetBounds.height;
			int		b3   = sceneWidgetBounds.y + sceneWidgetBounds.height / 2;

			for ( Rectangle rectangle : regions )
			{

				int		d;
				int		a1      = rectangle.y;
				int		a2      = a1 + rectangle.height;
				int		a3      = a1 + rectangle.height / 2;
				boolean	snapNow = false;

				if ( centers )
				{

					d = Math.abs(a3 - b3);

					if ( ( snap && d < dy ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						y       = a3;
						ys      = a3 - sceneWidgetBounds.height / 2;
						dy      = d;
					}
					
				}

				d = Math.abs(a1 - b1);

				if ( ( snap && d < dy ) || ( ! snap && d < gravity ) )
				{
					snap    = true;
					snapNow = true;
					y       = a1;
					ys      = a1;
					dy      = d;
				}

				if ( bothSides )
				{

					d = Math.abs(a1 - b2);

					if ( ( snap && d < dy ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						y       = a1;
						ys      = a1 - sceneWidgetBounds.height;
						dy      = d;
					}
					
				}

				d = Math.abs(a2 - b1);
				
				if ( ( snap && d < dy ) || ( ! snap && d < gravity ) )
				{
					snap    = true;
					snapNow = true;
					y       = a2;
					ys      = a2;
					dy      = d;
				}

				if ( bothSides )
				{

					d = Math.abs(a2 - b2);

					if ( ( snap && d < dy ) || ( ! snap && d < gravity ) )
					{
						snap    = true;
						snapNow = true;
						y       = a2;
						ys      = a2 - sceneWidgetBounds.height;
						dy      = d;
					}
					
				}

				if ( snapNow )
				{
					x1 = rectangle.x;
					x2 = rectangle.x + rectangle.width;
				}

			}

			if ( snap )
			{

				point.y = ys;

				if ( snapHack )
					point.y -= widget.getBounds().y;

			}

			if ( interractionLayer != null )
			{
				lineWidget2.setControlPoints(
					snap
				  ? Arrays.asList(
						new Point(Math.min(sceneWidgetBounds.x, x1), y),
						new Point(Math.max(sceneWidgetBounds.x + sceneWidgetBounds.width, x2), y)
					)
				  : Collections.<Point>emptyList(),
					true
				);
			}

		}

		return point;

	}

	public void setGravity ( int gravity )
	{
		this.gravity = gravity;
	}

	public void show ( )
	{

		if ( interractionLayer != null )
		{

			if ( lineWidget1 == null )
				lineWidget1 = decorator.createLineWidget(interractionLayer.getScene());
			if ( lineWidget2 == null )
				lineWidget2 = decorator.createLineWidget(interractionLayer.getScene());

			interractionLayer.addChild(lineWidget1);
			interractionLayer.addChild(lineWidget2);
			lineWidget1.setControlPoints(Collections.<Point>emptySet(), true);
			lineWidget2.setControlPoints(Collections.<Point>emptySet(), true);

		}

	}

}	//	class FEPAlignWithSupport


Moreover, the following classes allow snapped movements handling of a selection of widgets using the selection lead for the snap operations:


private class MultiAlignWithMoveStrategyProvider
	extends FEPAlignWithSupport
	implements MoveStrategy, MoveProvider
{

	private boolean				outerBounds;
	private Point				original;
	private Map<Widget, Point>	originals = new HashMap<Widget, Point>();


	public MultiAlignWithMoveStrategyProvider (
		AlignWithWidgetCollector	collector,
		LayerWidget					interractionLayer,
		AlignWithMoveDecorator		decorator,
		boolean						outerBounds
	)
	{
		super(collector, interractionLayer, decorator);
		this.outerBounds = outerBounds;
	}

	public Point locationSuggested ( Widget widget, Point originalLocation, Point suggestedLocation )
	{

		Point		widgetLocation = widget.getLocation();
		Rectangle	widgetBounds   = outerBounds ? widget.getBounds() : widget.getClientArea();
		Rectangle	bounds         = widget.convertLocalToScene(widgetBounds);

		bounds.translate(suggestedLocation.x - widgetLocation.x, suggestedLocation.y - widgetLocation.y);

		Insets	insets = widget.getBorder().getInsets();

		if ( ! outerBounds )
		{
			suggestedLocation.x += insets.left;
			suggestedLocation.y += insets.top;
		}

		Point	point = super.locationSuggested(widget, bounds, suggestedLocation, true, true, true, true, true);

		if ( ! outerBounds )
		{
			point.x -= insets.left;
			point.y -= insets.top;
		}

		return widget.getParentWidget().convertSceneToLocal(point);

	}

	public void movementStarted ( Widget widget )
	{

		Object	object = scene.findObject(widget);

		if ( scene.isNode(object) )
		{
			for ( Object o : scene.getSelectedObjects() )
			{
				if ( scene.isNode(o) )
				{

					Widget	w = scene.findWidget(o);

					if ( w != null )
						originals.put(w, w.getPreferredLocation());

				}
			}
		}
		else
			originals.put(widget, widget.getPreferredLocation());

		show();

	}

	public void movementFinished ( Widget widget )
	{

		hide();

		originals.clear();

		original = null;

	}

	public Point getOriginalLocation ( Widget widget )
	{

		original = widget.getPreferredLocation();

		return original;

	}

	public void setNewLocation ( Widget widget, Point location )
	{

		int dx = location.x - original.x;
		int dy = location.y - original.y;

		for ( Map.Entry<Widget, Point> entry : originals.entrySet() )
		{

			Point	point = entry.getValue();

			entry.getKey().setPreferredLocation(new Point(point.x + dx, point.y + dy));

		}

	}

}	//	class MultiAlignWithMoveStrategyProvider


private class MultiMoveProvider
	implements MoveProvider
{

	private Point				original;
	private Map<Widget, Point>	originals = new HashMap<Widget, Point>();

	public void movementStarted ( Widget widget )
	{

		Object	object = scene.findObject(widget);

		if ( scene.isNode(object) )
		{
			for ( Object o : scene.getSelectedObjects() )
			{
				if ( scene.isNode(o) )
				{

					Widget	w = scene.findWidget(o);

					if ( w != null )
						originals.put(w, w.getPreferredLocation());

				}
			}
		}
		else
			originals.put(widget, widget.getPreferredLocation());

	}

	public void movementFinished ( Widget widget )
	{

		originals.clear();

		original = null;

	}

	public Point getOriginalLocation ( Widget widget )
	{

		original = widget.getPreferredLocation();

		return original;

	}

	public void setNewLocation ( Widget widget, Point location )
	{

		int dx = location.x - original.x;
		int dy = location.y - original.y;

		for ( Map.Entry<Widget, Point> entry : originals.entrySet() )
		{

			Point	point = entry.getValue();

			entry.getKey().setPreferredLocation(new Point(point.x + dx, point.y + dy));

		}

	}

}	//	class MultiMoveProvider


Claudio