// ********************************************************************** // // <copyright> // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // </copyright> // ********************************************************************** // // $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/omGraphics/FilterSupport.java,v $ // $RCSfile: FilterSupport.java,v $ // $Revision: 1.7 $ // $Date: 2004/10/14 18:06:11 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.omGraphics; import java.awt.Shape; import java.awt.geom.Area; import java.io.Serializable; import com.bbn.openmap.util.Debug; /** * This class provides support for implementing the OMGraphicHandler * interface. If you already calculate an OMGraphicList, you can use * this class to apply filtering to it. The graphics on the list you * provide it will be made visible or not depending on whether they * meet the filter criteria. * <p> * * The visibility of the graphics is affected when a filter is * applied, and visibility is used as the test if whether a graphic is * added to a returned list. Use resetFiltering() to turn visibility * back on for all the OMGraphics. If a graphic is not visible when a * filter is applied, then the filter test will automatically fail. */ public class FilterSupport implements OMGraphicHandler, Serializable { /** * The source graphic list. */ protected OMGraphicList list = null; /** * A flag to use the Area.intersect(Area) test, which may be a * performance hit. */ protected boolean precise = true; protected boolean DEBUG = Debug.debugging("list"); public FilterSupport() {} public FilterSupport(OMGraphicList omgl) { setList(omgl); } /** * Filters the OMGraphicHandler graphic list so that graphics * within the given shape will be visible. Returns an * OMGraphicList with those visible shapes. The returned list * should not be assumed to be the same OMGraphicList object that * is maintained inside the OMGraphicHandler. Same as calling * filter(withinThisShape, true). * * @param withinThisShape java.awt.Shape object defining a * boundary. * @return OMGraphicList containing OMGraphics that are within the * Shape. */ public OMGraphicList filter(Shape withinThisShape) { return filter(withinThisShape, true); } /** * Filters the OMGraphicHandler graphic list so that graphics * inside or outside the given shape will be visible. Returns an * OMGraphicList with those visible shapes. The returned list * should not be assumed to be the same OMGraphicList object that * is maintained inside the OMGraphicHandler. * * @param shapeBoundary java.awt.Shape object defining a boundary. * @param getInsideBoundary if true, the filter will look for * shapes inside and contacting the boundary. If false, the * filter will look for shapes outside the boundary. * @return OMGraphicList containing OMGraphics that are within the * Shape. */ public OMGraphicList filter(Shape shapeBoundary, boolean getInsideBoundary) { Area area = null; if (shapeBoundary != null) { area = new Area(shapeBoundary); } if (Debug.debugging("filtersupportdetail")) { Debug.output(getList().getDescription()); } return filterList(getList(), area, getInsideBoundary); } /** * Method that provides a recursive mechanism to go through * OMGraphicsLists to filter out areas, inside or outside another. */ protected OMGraphicList filterList(OMGraphicList omgl, Area area, boolean getInsideArea) { OMGraphicList ret = new OMGraphicList(); boolean DEBUG_DETAIL = Debug.debugging("filtersupportdetail"); boolean DEBUG = Debug.debugging("filtersupport") || DEBUG_DETAIL; if (DEBUG) { Debug.output("FilterSupport.filterList"); } int count = 0; // for debugging if (area != null && omgl != null) { // just checking for (OMGraphic omg : omgl) { if (DEBUG) { Debug.output("FilterSupport.filterList evaluating " + (count++) + " OMGraphic, " + omg); } boolean outsideFilter = true; // If not visible, automatically fails... if (!omg.isVisible()) { if (DEBUG) { Debug.output(" OMGraphic not visible, ignoring"); } continue; } if (omg instanceof OMGraphicList) { if (omg == omgl) { Debug.output(" OMGraphic is parent list (points to itself), ignoring..."); continue; } if (DEBUG) { Debug.output(" (filterList recursiving handing OMGraphicList)"); } OMGraphicList subList = filterList((OMGraphicList) omg, area, getInsideArea); if (!subList.isEmpty()) { if (DEBUG) { Debug.output(" +++ OMGraphicList's contents (" + subList.size() + ") pass filter, adding..."); } if (((OMGraphicList)omg).isVague()) { passedFilter(omg); omg.setVisible(true); ret.add(omg); } else { passedFilter(subList); ret.add(subList); } } else { if (DEBUG) { Debug.output(" --- OMGraphicList's contents fail filter, ignoring..."); } failedFilter(omg); } continue; } else { Shape omgShape = omg.getShape(); if (omgShape != null) { if (omgShape.getBounds2D().getWidth() == 0 && omgShape.getBounds2D().getHeight() == 0) { if (area.contains(omgShape.getBounds2D().getX(), omgShape.getBounds2D().getY())) { if (DEBUG_DETAIL) { Debug.output(" +++ omg contains position"); } outsideFilter = false; } } else if (area.intersects(omgShape.getBounds2D())) { if (DEBUG_DETAIL) { Debug.output(" +++ omg intersects bounds"); } // The area.interects() method above is a // general case. If you care about // preciseness, set the precise flag. // Depending on the performance cost, we might // want to make it permanent. if (precise) { Area omgArea = new Area(omgShape); if (!omgArea.isSingular()) { Area clone = (Area) area.clone(); clone.intersect(omgArea); if (!clone.isEmpty()) { outsideFilter = false; } } else { outsideFilter = false; } } else { outsideFilter = false; } } } // decide what to do depending on filteredOut and // getInsideArea if ((outsideFilter && !getInsideArea) || (!outsideFilter && getInsideArea)) { if (DEBUG) { Debug.output(" +++ OMGraphic passes filter, adding..."); } passedFilter(omg); ret.add(omg); } else { if (DEBUG) { Debug.output(" --- OMGraphic fails filter, hiding..."); } failedFilter(omg); } } } } return ret; } /** * Returns true if the OMGraphicHandler can handle SQL statements * for filtering. */ public boolean supportsSQL() { return false; } /** * Filters the OMGraphicHandler graphic list so that graphics * meeting the SQL query statement will be visible. Returns an * OMGraphicList with those visible shapes. The returned list * should not be assumed to be the same OMGraphicList object that * is maintained inside the OMGraphicHandler. * * @param SQLQuery a SELECT SQL statement * @return OMGraphicList containing OMGraphics that meet the * SELECT statement criteria. */ public OMGraphicList filter(String SQLQuery) { return new OMGraphicList(); } /** * Allows the OMGraphicHandler to receive graphics or take some * action on one. * * @param graphic the OMGraphic to do the action on. * @param action the OMAction describing what to do to the * graphic. * @return true if the action was able to be carried out. */ public boolean doAction(OMGraphic graphic, OMAction action) { OMGraphicList list = getList(); if (list != null) { list.doAction(graphic, action); } return true; // we can handle it. } /** * Return the graphic list currently being used by the * OMGraphicHandler. If filters have been applied, then the * OMGraphics that have made it through the filter are visible. * List may be null, if it hasn't been set. * * @see OMGraphic#isVisible() */ public synchronized OMGraphicList getList() { if (DEBUG) { Debug.output("FilterSupport.getList() with " + (list != null ? list.size() + " graphics." : "null list.")); } return list; } /** * Indicates if the OMGraphicHandler can have its OMGraphicList * set. */ public boolean canSetList() { return true; } /** * Set the OMGraphicList within this OMGraphicHandler. Works if * canSetGraphicList == true. */ public synchronized void setList(OMGraphicList omgl) { if (DEBUG) { Debug.output("FilterSupport.setList() with " + (omgl != null ? omgl.size() + " graphics." : "null list.")); } list = omgl; } /** * Remove all filters, and reset all graphics to be visible. */ public void resetFiltering() { OMGraphicList list = getList(); if (list != null) list.setVisible(true); } /** * Method called when FilterSupport finds an OMGraphic that fails * the filter test. The OMGraphic is not being added to a list * that is being returned for passing OMGraphics in another * method, this call-out is an opportunity to make settings on * OMGraphics that pass the filter. By default, the visibility of * the OMGraphic is set to false. */ protected void failedFilter(OMGraphic omg) { omg.setVisible(false); } /** * Method called when FilterSupport finds an OMGraphic that passes * the filter test. The OMGraphic is already being added to a list * that is being returned in another method, this call-out is an * opportunity to make settings on OMGraphics that pass the * filter. */ protected void passedFilter(OMGraphic omg) { // NO-OP, by default } }