/*
* @(#)AbstractDrawingState.java
*
* Copyright 2002 EGANTT LLP. All rights reserved.
* PROPRIETARY/QPL. Use is subject to license terms.
*/
package com.egantt.model.drawing.state;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.egantt.model.drawing.DrawingState;
import com.egantt.model.drawing.axis.AxisView;
import com.egantt.model.drawing.axis.view.event.ViewEvent;
import com.egantt.model.drawing.axis.view.event.ViewListener;
import com.egantt.model.drawing.part.event.DrawingPartEvent;
import com.egantt.model.drawing.part.event.DrawingPartListener;
import com.egantt.model.drawing.state.event.DrawingStateEvent;
import com.egantt.model.drawing.state.event.DrawingStateListener;
/**
* The simplest implementation of a DrawingState notifies the container
* that a repaint has occured
*/
public abstract class AbstractDrawingState implements DrawingState
{
protected DrawingPartListener drawingPartListener = new LocalDrawingPartListener();
protected ViewListener viewListener = new LocalViewListener();
protected List<DrawingStateListener> stateListeners = new ArrayList<DrawingStateListener>(1); // assumes 1x manager
protected List<AxisView> viewListeners = new ArrayList<AxisView>(4); // 4x(3D), 3x(Fake3D), 2x(2D)
protected Map <Object, Shape>bounds = new HashMap<Object, Shape>();
//___________________________________________________________________________
public synchronized boolean put(Object key, AxisView axisView)
{
return addViewListener(axisView);
}
public synchronized boolean put(Object key, Shape bounds)
{
return this.bounds.put(key, bounds) == null;
}
public boolean contains(Object key)
{
return this.bounds.containsKey(key);
}
// _________________________________________________________________________
public Object getValueAt(Point _location) {
return getValueAt(_location, 2, 2);
}
public Object getValueAt(Point _location, int xOffset, int yOffset)
{
Point2D location = new Point2D.Double(_location.getX(), _location.getY());
Rectangle locationBounds = new Rectangle(_location.x - xOffset, _location.y - yOffset, xOffset * 2, yOffset * 2) ;
for (Iterator iter = this.bounds.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
Shape shape = (Shape) entry.getValue();
if (!shape.getBounds().intersects(locationBounds))
continue;
if (shape.contains(location) || shape.intersects(locationBounds))
return entry.getKey();
}
return null;
}
// _________________________________________________________________________
public void initialise()
{
clearAxisListeners();
clearBounds();
}
public void terminate()
{
}
// __________________________________________________________________________
public boolean addDrawingStateListener(DrawingStateListener listener)
{
return stateListeners.add(listener);
}
public boolean removeDrawingStateListener(DrawingStateListener listener)
{
return stateListeners.remove(listener);
}
// __________________________________________________________________________
protected synchronized boolean addViewListener(AxisView axisView)
{
return viewListeners.add(axisView) && axisView.addViewListener(viewListener);
}
protected synchronized boolean removeViewListener(AxisView axisView)
{
return axisView.removeViewListener(viewListener) && viewListeners.remove(viewListener);
}
// __________________________________________________________________________
protected synchronized void clearAxisListeners()
{
// clear axis listeners
for (Iterator iter = viewListeners.iterator(); iter.hasNext();)
{
AxisView axisView = (AxisView) iter.next();
axisView.removeViewListener(viewListener);
iter.remove();
}
}
//___________________________________________________________________________
protected synchronized void clearBounds()
{
this.bounds.clear();
}
//___________________________________________________________________________
protected void fireChanged(EventObject e)
{
// use the real propogation ID, we never generated anything we are just
// forwarding it on behalf of another object is this the right thing?
DrawingStateEvent event = new DrawingStateEvent(e.getSource());
for (Iterator iter = stateListeners.iterator(); iter.hasNext();)
((DrawingStateListener) iter.next()).stateChanged(event);
}
/**
* listens to n Axises
*/
protected class LocalViewListener implements ViewListener
{
public void stateChanged(ViewEvent event)
{
fireChanged(event);
}
}
//___________________________________________________________________________
/**
* Listens to n drawings
*/
protected class LocalDrawingPartListener implements DrawingPartListener
{
public void stateChanged(DrawingPartEvent event)
{
fireChanged(event);
}
}
}