Package selector

Class SelectionModel

java.lang.Object
selector.SelectionModel
Direct Known Subclasses:
PointToPointSelectionModel, SplineSelectionModel

public abstract class SelectionModel extends Object
Represents the process of selecting a region of an image by adding control points that are used to extend a selection path. Supports removing points (and any segments they defined) in the opposite order that they were added and moving points after the selection has been completed.
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Declares capabilities that an object representing the "state" of selection progress must be able to support.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected LinkedList<Point>
    The sequence of control points used to define this selection, in the order in which they were added.
    protected BufferedImage
    The image we are selecting from (may be null, in which case no operations should be attempted until the image has been set).
    Helper object for managing property change notifications.
    protected LinkedList<PolyLine>
    The sequence of segments representing the current selection path.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    SelectionModel(boolean notifyOnEdt)
    If `notifyOnEdt` is true, property change listeners will be notified on Swing's Event Dispatch thread, regardless of which thread the event was fired from.
    protected
    Initialize this model with the same `segments`, `controlPoints`, and image as `copy`.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    If no selection has been started, start selecting from `p`.
    void
    Register `listener` to be notified whenever any property of this model is changed.
    void
    Register `listener` to be notified whenever the property named `propertyName` of this model is changed.
    protected abstract void
    Add `p` as the next control point of our selection, extending our selection with a new segment if appropriate.
    void
    Cancel any asynchronous processing currently being performed on behalf of this model.
    int
    closestPoint(Point p, int maxDistanceSq)
    Return the index of this model's control point that is the closest to `p`, as long as the square of its distance to `p` is no greater than `maxDistanceSq`.
    Return the sequence of control points used to define the current selection.
    abstract void
    Close the current selection path by connecting the last segment to the starting point and transitioning to a "finished" state.
    Return an indication of the progress of any asynchronous processing currently being performed on behalf of this model.
    Return the image we are currently selecting from.
    Return the last control point added to the current selection.
    abstract PolyLine
    Return a path representing a preview of how the selection would be extended if `p` were to be added with `addPoint()`.
    abstract void
    movePoint(int index, Point newPos)
    Move the control point with index `index` to `newPos`, updating the path of any segments affected by that control point.
    void
    Stop notifying `listener` of property changes for this model (assuming it was added no more than once).
    void
    Stop notifying `listener` of changes to the property named `propertyName` for this model (assuming it was added no more than once).
    void
    Clear the current selection path and any starting point.
    void
    Write a PNG image to `out` containing the pixels from the current selection.
    Return the sequence of poly-line segments forming the current selection path.
    void
    Select from `newImg` instead of any previous set image.
    protected void
    When no selection has yet been started, set our first control point to `start` and transition to the appropriate state.
    Return the status of this model's current selection.
    void
    If we are still processing the most recently added point, cancel that operation.
    protected abstract void
    Remove the last control point from our selection.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • segments

      protected LinkedList<PolyLine> segments
      The sequence of segments representing the current selection path. The start point of each segment must equal the end point of the previous segment (ensuring continuity). If our state is "finished," then this list must be non-empty, and the end point of the last segment must equal the start point of the first segment. Whenever the contents of this list change, a "selection" property change event must be fired.
    • controlPoints

      protected LinkedList<Point> controlPoints
      The sequence of control points used to define this selection, in the order in which they were added. All points are "semantically distinct"; for example, if the selection is finished, the end point will NOT be included in this list if it is the same as the starting point (which is usually the case).
    • img

      protected BufferedImage img
      The image we are selecting from (may be null, in which case no operations should be attempted until the image has been set).
    • propSupport

      protected SwingPropertyChangeSupport propSupport
      Helper object for managing property change notifications.
  • Constructor Details

    • SelectionModel

      protected SelectionModel(boolean notifyOnEdt)
      If `notifyOnEdt` is true, property change listeners will be notified on Swing's Event Dispatch thread, regardless of which thread the event was fired from. It should generally be set to "true" when this model will be used with a GUI, and "false" when unit testing. The image will initially be set to null.
    • SelectionModel

      protected SelectionModel(SelectionModel copy)
      Initialize this model with the same `segments`, `controlPoints`, and image as `copy`. Does NOT copy any listeners from `copy`. This constructor must only be invoked on Swing's Event Dispatch Thread, since `copy`'s state may be shared with a background processing thread.

      It may not be possible for two different models to represent the same selection, in which case a subclass constructor may reset its selection state.

  • Method Details

    • state

      public abstract SelectionModel.SelectionState state()
      Return the status of this model's current selection.
    • selection

      public List<PolyLine> selection()
      Return the sequence of poly-line segments forming the current selection path. The returned list is not modifiable, but it will reflect subsequent changes made to this model.
    • controlPoints

      public List<Point> controlPoints()
      Return the sequence of control points used to define the current selection. The returned list is not modifiable, but it will reflect subsequent changes made to this model. Clients must not mutate the constituent Points.
    • image

      public BufferedImage image()
      Return the image we are currently selecting from.
    • setImage

      public void setImage(BufferedImage newImg)
      Select from `newImg` instead of any previous set image. Resets the selection. Notifies listeners that the "image" property has changed.
    • addPoint

      public void addPoint(Point p)
      If no selection has been started, start selecting from `p`. Otherwise, if a selection is in progress, append a segment from its last point to point `p`. Subclasses determine the path of the new segment. Listeners will be notified if the "state" or "selection" properties are changed.
    • lastPoint

      public Point lastPoint()
      Return the last control point added to the current selection. If no segments have been added to the selection yet, or if the selection has finished, this will be the starting point. Throws an `IllegalStateException` if our state is empty.
    • liveWire

      public abstract PolyLine liveWire(Point p)
      Return a path representing a preview of how the selection would be extended if `p` were to be added with `addPoint()`. In many cases, this will be a path connecting our last point to `p`, but this may not make sense in all cases (for example, `p` might be added as a "control point" that does not lie on the path, in which case the "live wire" may be a straight segment to the control point, or it may be a preview of how the path will be affected by the control point). Subclasses should refine this specification.
    • undo

      public void undo()
      If we are still processing the most recently added point, cancel that operation. Otherwise, remove the last segment from the selection path. If the selection path does not contain any segments, reset the selection to clear our starting point. Listeners will be notified if the "state" or "selection" properties are changed. Removal of a point other than the start may require asynchronous processing.
    • finishSelection

      public abstract void finishSelection()
      Close the current selection path by connecting the last segment to the starting point and transitioning to a "finished" state. If no segments have been added yet, reset this selection instead. Listeners will be notified if the "state" or "selection" properties are changed. Throws an `IllegalStateException` if the selection is already finished or cannot be finished.
    • reset

      public void reset()
      Clear the current selection path and any starting point. Listeners will be notified if the "state" or "selection" properties are changed. Subclasses should override this method in order to transition to an empty state.
    • closestPoint

      public int closestPoint(Point p, int maxDistanceSq)
      Return the index of this model's control point that is the closest to `p`, as long as the square of its distance to `p` is no greater than `maxDistanceSq`. If no control point along the selection is close enough, return -1. If multiple points are tied for closest, any of their indices may be returned. Throws an IllegalStateException if our selection is not yet finished. Control point indices are zero-based and are consistent with the list returned by `controlPoints()`.
    • movePoint

      public abstract void movePoint(int index, Point newPos)
      Move the control point with index `index` to `newPos`, updating the path of any segments affected by that control point. Listeners will be notified that the "selection" property has changed. Control point indices are zero-based and are consistent with the list returned by `controlPoints()`.
    • saveSelection

      public void saveSelection(OutputStream out) throws IOException
      Write a PNG image to `out` containing the pixels from the current selection. The size of the image matches the bounding box of the selection, and pixels outside of the selection are transparent. Throws an IOException if the image could not be written. Throws an IllegalStateException if our selection is not finished.
      Throws:
      IOException
    • startSelection

      protected void startSelection(Point start)
      When no selection has yet been started, set our first control point to `start` and transition to the appropriate state. Listeners will be notified that the "state" property has changed. Throws an `IllegalStateException` if our state is not empty.

      The default implementation checks that the state is empty and adds the control point. Subclasses must override this method in order to perform the state transition and notify listeners.

    • appendToSelection

      protected abstract void appendToSelection(Point p)
      Add `p` as the next control point of our selection, extending our selection with a new segment if appropriate. This may result in a state change. Requires that our state allows adding points. Not responsible for notifying listeners that the selection has changed (this must be handled subsequently by the caller).
    • undoPoint

      protected abstract void undoPoint()
      Remove the last control point from our selection. Listeners will be notified if the "state" or "selection" properties are changed.
    • addPropertyChangeListener

      public void addPropertyChangeListener(PropertyChangeListener listener)
      Register `listener` to be notified whenever any property of this model is changed.
    • addPropertyChangeListener

      public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
      Register `listener` to be notified whenever the property named `propertyName` of this model is changed.
    • removePropertyChangeListener

      public void removePropertyChangeListener(PropertyChangeListener listener)
      Stop notifying `listener` of property changes for this model (assuming it was added no more than once). Does not affect listeners who were registered with a particular property name.
    • removePropertyChangeListener

      public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)
      Stop notifying `listener` of changes to the property named `propertyName` for this model (assuming it was added no more than once). Does not affect listeners who were not registered with `propertyName`.
    • cancelProcessing

      public void cancelProcessing()
      Cancel any asynchronous processing currently being performed on behalf of this model.
    • getProcessingProgress

      public Object getProcessingProgress()
      Return an indication of the progress of any asynchronous processing currently being performed on behalf of this model. The type of object returned will depend on the subclass. Returns null if no asynchronous processing is currently being performed.