You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ctakes.apache.org by se...@apache.org on 2015/02/19 19:06:17 UTC
svn commit: r1660963 [16/19] - in /ctakes/sandbox/timelanes: META-INF/ edu/
edu/mayo/ edu/mayo/bmi/ edu/mayo/bmi/annotation/
edu/mayo/bmi/annotation/knowtator/ org/ org/chboston/ org/chboston/cnlp/
org/chboston/cnlp/anafora/ org/chboston/cnlp/anafora/a...
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/DefaultTimeSpanRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/DefaultTimeSpanRenderer.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/DefaultTimeSpanRenderer.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/DefaultTimeSpanRenderer.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,431 @@
+package org.chboston.cnlp.timeline.gui.timespan.plus;
+
+import org.chboston.cnlp.timeline.gui.timespan.TimeSpanDrawUtil;
+import org.chboston.cnlp.timeline.timespan.EndPointer;
+import org.chboston.cnlp.timeline.timespan.TimeSpan;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+import org.chboston.cnlp.timeline.timespan.plus.TimeEndPoint;
+
+import java.awt.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/2/13
+ */
+public class DefaultTimeSpanRenderer extends AbstractTimeSpanRenderer {
+
+ static private final TimeSpanPainter DEFAULT_PAINTER = new DefaultTimeSpanPainter();
+
+ protected Color getPlainColor( final boolean isSelected, final boolean isFocused, final boolean isFuzzy ) {
+ return TimeSpanDrawUtil.getPlainColor( isSelected, isFocused, isFuzzy );
+ }
+
+ protected Color getPlainColor( final boolean isSelected, final boolean isFocused, final boolean isFuzzy,
+ final int width ) {
+ return TimeSpanDrawUtil.getPlainColor( isSelected, isFocused, isFuzzy, width );
+ }
+
+ protected TimeSpanPainter getPainter() {
+ return DEFAULT_PAINTER;
+ }
+
+
+ private void paintStart( final Graphics2D g2d, final TimeSpan timeSpan ) {
+ if ( timeSpan instanceof PointedTimeSpan ) {
+ paintRelativeStart( g2d, (PointedTimeSpan)timeSpan );
+ } else {
+ final int height = getHeight();
+ paintEdge( g2d, 0, TimeSpanDrawUtil.LINE_THINNESS, height, timeSpan.isFuzzyDate() );
+ }
+ }
+
+ private void paintEnd( final Graphics2D g2d, final TimeSpan timeSpan ) {
+ if ( timeSpan instanceof PointedTimeSpan ) {
+ paintRelativeStop( g2d, (PointedTimeSpan)timeSpan );
+ } else {
+ final int width = getWidth();
+ final int height = getHeight();
+ paintEdge( g2d, width - TimeSpanDrawUtil.LINE_THINNESS, width, height, timeSpan.isFuzzyDate() );
+ }
+ }
+
+ // private void paintInside( final Graphics2D g2d, final TimeSpan timeSpan ) {
+ // if ( timeSpan instanceof TimeSpanPlus ) {
+ // paintRelativeInside( g2d, (TimeSpanPlus) timeSpan );
+ // } else {
+ // paintAbsoluteInside( g2d );
+ // }
+ // }
+
+ private void paintRelativeStart( final Graphics2D g2d, final PointedTimeSpan timeSpan ) {
+ final int startOffset = TimeSpanDrawUtil.getStartOffset( timeSpan );
+ final TimeEndPoint startTime = timeSpan.getStartTime();
+ final int height = getHeight();
+ switch ( startTime.getPointer() ) {
+ case BEFORE:
+ if ( timeSpan.isSingleDate()
+ && timeSpan.getStopTime().getPointer() == EndPointer.EQUAL ) {
+ // ~ tlink Ends-On
+ paintOuterLine( g2d, 0, startOffset, TimeSpanDrawUtil.LINE_THINNESS, height, startTime.isFuzzy() );
+ return;
+ }
+ paintSolidTriangle( g2d, 0, startOffset, height, startTime.isFuzzy() );
+ break;
+ case AFTER:
+ if ( timeSpan.isSingleDate() ) {
+ // ~ tlink After
+ return;
+ }
+ // ~ tlink Contains
+ paintEdge( g2d, 0, TimeSpanDrawUtil.LINE_THINNESS, height, startTime.isFuzzy() );
+ break;
+ case EQUAL:
+ if ( !timeSpan.isSingleDate()
+ || timeSpan.getStopTime().getPointer() == EndPointer.AFTER ) {
+ // Equal Start OR ~ tlink Begins-On
+ paintEdge( g2d, 0, TimeSpanDrawUtil.LINE_THINNESS, height, startTime.isFuzzy() );
+ }
+ break;
+ case OVERLAP:
+ paintOuterLine( g2d, 0, startOffset, TimeSpanDrawUtil.LINE_THICKNESS, height, startTime.isFuzzy() );
+ break;
+ }
+ }
+
+ private void paintRelativeStop( final Graphics2D g2d, final PointedTimeSpan timeSpan ) {
+ final int endOffset = TimeSpanDrawUtil.getEndOffset( timeSpan );
+ final TimeEndPoint timeEndPoint = timeSpan.getStopTime();
+ final int width = getWidth();
+ final int leftX = width - endOffset;
+ final int height = getHeight();
+ switch ( timeEndPoint.getPointer() ) {
+ case BEFORE:
+ if ( timeSpan.isSingleDate() ) {
+ // ~ tlink Before
+ return;
+ }
+ // ~ tlink Contains
+ paintEdge( g2d, width - TimeSpanDrawUtil.LINE_THINNESS, width, height, timeEndPoint.isFuzzy() );
+ break;
+ case AFTER:
+ if ( timeSpan.isSingleDate()
+ && timeSpan.getStartTime().getPointer() == EndPointer.EQUAL ) {
+ // ~ tlink Ends-On
+ paintOuterLine( g2d, leftX, width, TimeSpanDrawUtil.LINE_THINNESS, height, timeEndPoint.isFuzzy() );
+ return;
+ }
+ paintSolidTriangle( g2d, width, leftX, height, timeEndPoint.isFuzzy() );
+ break;
+ case EQUAL:
+ if ( !timeSpan.isSingleDate()
+ || timeSpan.getStartTime().getPointer() == EndPointer.BEFORE ) {
+ // Equal Stop OR ~ tlink Ends-On
+ paintEdge( g2d, width - TimeSpanDrawUtil.LINE_THINNESS, width, height, timeEndPoint.isFuzzy() );
+ }
+ break;
+ case OVERLAP:
+ paintOuterLine( g2d, leftX, width, TimeSpanDrawUtil.LINE_THICKNESS, height, timeEndPoint.isFuzzy() );
+ break;
+ }
+ }
+
+ protected void paintDiamond( final Graphics2D g2d ) {
+ final int width = getWidth();
+ final int halfWidth = width / 2 - 1;
+ final int height = getHeight();
+ final int halfHeight = height / 2 - 1;
+ final Color color = getPlainColor( isSelected(), isFocused(), isFuzzy() );
+ g2d.setPaint( color );
+ final int[] xPoints = { 0, halfWidth, width - 1, halfWidth, 0 };
+ final int[] yPoints = { halfHeight, 0, halfHeight, height - 1, halfHeight };
+ g2d.fillPolygon( xPoints, yPoints, xPoints.length );
+ }
+
+ // protected void paintTriangle( final Graphics2D g2d, final int pointX, final int nockX,
+ // final int fuzzyX, final int solidX, final int height ) {
+ // final int width = Math.abs( nockX - pointX );
+ // final int halfHeight = height / 2 - 1;
+ // final Color insideColor = getPlainColor( isSelected(), isFuzzy(), width );
+ // final Color outsideColor = getPlainColor( isSelected(), true, width );
+ // final GradientPaint gradient1 = new GradientPaint( solidX, 0, insideColor, fuzzyX, 0, outsideColor, false );
+ // g2d.setPaint( gradient1 );
+ // final int[] xPoints = {pointX, nockX, nockX, pointX, pointX};
+ // final int[] yPoints = {halfHeight - 1, 0, height - 1, halfHeight, halfHeight - 1};
+ // g2d.fillPolygon( xPoints, yPoints, xPoints.length );
+ // }
+
+ // TODO This would be faster as an image
+ protected void paintSolidTriangle( final Graphics2D g2d, final int pointX, final int nockX, final int height,
+ final boolean isFuzzy ) {
+ final int halfHeight = height / 2 - 1;
+ final Color color = getPlainColor( isSelected(), isFocused(), isFuzzy );
+ g2d.setPaint( color );
+ final int[] xPoints = { pointX, nockX, nockX, pointX, pointX };
+ final int[] yPoints = { halfHeight - 1, 0, height - 1, halfHeight, halfHeight - 1 };
+ g2d.fillPolygon( xPoints, yPoints, xPoints.length );
+ }
+
+ // TODO This would be faster as an image
+ protected void paintInnerEdge( final Graphics2D g2d, final int pointX, final int nockX, final int height,
+ final boolean isFuzzy ) {
+ final int halfHeight = height / 2 - 1;
+ final int halfThick = TimeSpanDrawUtil.LINE_THICKNESS / 2;
+ final int top = Math.max( 0, halfHeight - halfThick );
+ final int bottom = Math.min( height, top + TimeSpanDrawUtil.LINE_THICKNESS );
+ final int lineHeight = bottom - top;
+ final Color color = getPlainColor( isSelected(), isFocused(), isFuzzy );
+ g2d.setPaint( color );
+ final int[] xPoints1 = { pointX, nockX, nockX, pointX, pointX };
+ final int[] yPoints1 = { 0, top, bottom, lineHeight, 0 };
+ g2d.fillPolygon( xPoints1, yPoints1, xPoints1.length );
+ final int[] xPoints2 = { pointX, nockX, nockX, pointX, pointX };
+ final int[] yPoints2 = { height, bottom, top, height - lineHeight, height };
+ g2d.fillPolygon( xPoints2, yPoints2, xPoints2.length );
+ }
+
+ protected void paintEdge( final Graphics2D g2d, final int leftX, final int rightX, final int height,
+ final boolean isFuzzy ) {
+ final int width = Math.min( getWidth(), Math.abs( rightX - leftX ) );
+ final Color color = getPlainColor( isSelected(), isFocused(), isFuzzy, getWidth() );
+ g2d.setPaint( color );
+ g2d.fillRect( leftX, 0, width, height );
+ }
+
+ protected void paintOuterLine( final Graphics2D g2d, final int leftX, final int rightX, final int thickness,
+ final int height, final boolean isFuzzy ) {
+ final int width = Math.abs( rightX - leftX );
+ final int halfHeight = height / 2 - 1;
+ final int top = halfHeight - thickness / 2;
+ final Color color = getPlainColor( isSelected(), isFocused(), isFuzzy, width );
+ g2d.setPaint( color );
+ g2d.fillRect( leftX, top, width, thickness );
+ }
+
+ protected void paintInnerLine( final Graphics2D g2d, final TimeSpan timeSpan ) {
+ if ( timeSpan instanceof PointedTimeSpan ) {
+ paintRelativeLine( g2d, (PointedTimeSpan)timeSpan );
+ } else {
+ paintAbsoluteLine( g2d, timeSpan );
+ }
+ }
+
+ // protected void paintSolidLine( final Graphics2D g2d, final int x, final int width,
+ // final int y, final int thickness ) {
+ // final Color solidColor = getPlainColor( isSelected(), false );
+ // g2d.setPaint( solidColor );
+ // g2d.fillRect( x, y, width, thickness );
+ // }
+ //
+ //
+ // protected void paintGradientLine( final Graphics2D g2d, final int x, final int width,
+ // final int solidX, final int fuzzyX,
+ // final int y, final int thickness ) {
+ // final Color solidColor = getPlainColor( isSelected(), false );
+ // final Color fuzzyColor = getPlainColor( isSelected(), true );
+ // final GradientPaint gradient1 = new GradientPaint( solidX, y, solidColor, fuzzyX, y, fuzzyColor, false );
+ // g2d.setPaint( gradient1 );
+ // g2d.fillRect( x, y, width, thickness );
+ // }
+
+
+ protected void paintRelativeLine( final Graphics2D g2d, final PointedTimeSpan timeSpan ) {
+ final TimeEndPoint startTime = timeSpan.getStartTime();
+ final boolean isStartFuzzy = startTime.isFuzzy();
+ final EndPointer startPointer = startTime.getPointer();
+ final TimeEndPoint stopTime = timeSpan.getStopTime();
+ final boolean isStopFuzzy = stopTime.isFuzzy();
+ final EndPointer stopPointer = stopTime.getPointer();
+ final int width = getWidth();
+ final int height = getHeight();
+ final int halfHeight = height / 2 - 1;
+ final int startOffset = TimeSpanDrawUtil.getStartOffset( timeSpan )
+ + (startPointer == EndPointer.AFTER ? TimeSpanDrawUtil.LINE_THINNESS : 0);
+ final int endOffset = TimeSpanDrawUtil.getEndOffset( timeSpan )
+ + (stopPointer == EndPointer.BEFORE ? TimeSpanDrawUtil.LINE_THINNESS : 0);
+ final int plainColorWidth = width - startOffset - endOffset;
+ final int lineThickess = TimeSpanDrawUtil.isEndOnly( timeSpan ) ? TimeSpanDrawUtil.LINE_THINNESS
+ : TimeSpanDrawUtil.LINE_THICKNESS;
+ final int halfThick = lineThickess / 2;
+ final int top = Math.max( 0, halfHeight - halfThick );
+ final int bottom = Math.min( height, top + lineThickess );
+ final int lineHeight = bottom - top;
+ if ( TimeSpanDrawUtil.isEndOnly( timeSpan ) ) {
+ final Color color = getPlainColor( isSelected(), isFocused(), true, plainColorWidth );
+ g2d.setPaint( color );
+ g2d.fillRect( 0, top, width, lineHeight );
+ return;
+ }
+ final TimeSpanPainter painter = getPainter();
+ if ( !isStartFuzzy && !isStopFuzzy ) {
+ final Color solidColor = getPlainColor( isSelected(), isFocused(), false, plainColorWidth );
+ // paint the center
+ g2d.setPaint( solidColor );
+// g2d.fillRect( startOffset, top, plainColorWidth, lineHeight );
+ painter.paint( g2d, startOffset, top, plainColorWidth, lineHeight );
+ return;
+ }
+ final int quarterWidth = (int)(plainColorWidth / 4.d);
+ final int halfWidth = (int)(plainColorWidth / 2.d);
+ final int threeqWidth = plainColorWidth - quarterWidth;
+ final Color solidColor = getPlainColor( isSelected(), isFocused(), false, halfWidth );
+ // paint the center
+ g2d.setPaint( solidColor );
+ if ( isStartFuzzy && !isStopFuzzy ) {
+// g2d.fillRect( startOffset + quarterWidth, top, threeqWidth + 2, lineHeight );
+ painter.paint( g2d, startOffset + quarterWidth, top, threeqWidth + 2, lineHeight );
+ } else if ( !isStartFuzzy ) {
+// g2d.fillRect( startOffset, top, threeqWidth + 2, lineHeight );
+ painter.paint( g2d, startOffset, top, threeqWidth + 2, lineHeight );
+ } else {
+// g2d.fillRect( startOffset + quarterWidth, top, halfWidth + 2, lineHeight );
+ painter.paint( g2d, startOffset + quarterWidth, top, halfWidth + 2, lineHeight );
+ }
+ // paint the fuzzy sides
+ final Color fuzzyColor = getPlainColor( isSelected(), isFocused(), true, quarterWidth );
+ if ( isStartFuzzy ) {
+ final GradientPaint gradient1 = new GradientPaint( startOffset, 0, fuzzyColor,
+ startOffset + quarterWidth, 0, solidColor, false );
+ g2d.setPaint( gradient1 );
+// g2d.fillRect( startOffset, top, quarterWidth, lineHeight );
+ painter.paint( g2d, startOffset, top, quarterWidth, lineHeight );
+ }
+ if ( isStopFuzzy ) {
+ final GradientPaint gradient2 = new GradientPaint( startOffset + threeqWidth, 0, solidColor,
+ startOffset + plainColorWidth, 0, fuzzyColor, false );
+ g2d.setPaint( gradient2 );
+// g2d.fillRect( startOffset + threeqWidth, top, quarterWidth, lineHeight );
+ painter.paint( g2d, startOffset + threeqWidth, top, quarterWidth, lineHeight );
+ }
+ }
+
+ protected interface TimeSpanPainter {
+ public void paint( final Graphics2D g2d, final int x, final int y, final int width, final int height );
+ }
+
+ static final private class DefaultTimeSpanPainter implements TimeSpanPainter {
+ @Override
+ public void paint( final Graphics2D g2d, final int x, final int y, final int width, final int height ) {
+ g2d.fillRect( x, y, width, height );
+ }
+ }
+
+ // protected void paintRelativeInside( final Graphics2D g2d, final TimeSpanPlus timeSpan ) {
+ // final int width = getWidth();
+ // final int startOffset = TimeSpanDrawUtil.getStartOffset( timeSpan );
+ // final int endOffset = TimeSpanDrawUtil.getEndOffset( timeSpan );
+ // final int insideWidth = width - startOffset - endOffset;
+ // if ( insideWidth < 1 ) {
+ // return;
+ // }
+ // final int height = getHeight();
+ // final int halfHeight = height / 2 - 1;
+ // final int plainColorWidth = width - startOffset - endOffset;
+ // final int lineThickess = TimeSpanDrawUtil.isEndOnly( timeSpan ) ? TimeSpanDrawUtil.LINE_THINNESS
+ // : TimeSpanDrawUtil.LINE_THICKNESS;
+ // final int halfThick = lineThickess / 2;
+ // final int top = Math.max( 0, halfHeight - halfThick );
+ // final int bottom = Math.min( height, top + lineThickess );
+ // final int lineHeight = bottom - top;
+ //// if ( TimeSpanDrawUtil.isEndOnly( timeSpan ) ) {
+ //// final Color color = getPlainColor( isSelected(), true, plainColorWidth );
+ //// g2d.setPaint( color );
+ //// g2d.fillRect( startOffset, top, insideWidth, lineHeight );
+ //// return;
+ //// }
+ //// if ( timeSpan.isBeforeOverlap() ) {
+ //// final int halfWidth = (int) (insideWidth / 2.d);
+ //// paintGradientLine( g2d, startOffset, insideWidth, startOffset, halfWidth, top, lineHeight );
+ //// } else if ( timeSpan.isEqual() ) {
+ //// paintAbsoluteInside( g2d );
+ //// } else if ( timeSpan.beginsWith() ) {
+ //// final int halfWidth = (int) (insideWidth / 2.d);
+ //// paintGradientLine( g2d, startOffset, insideWidth, startOffset, halfWidth, top, lineHeight );
+ //// } else if ( timeSpan.endsWith() ) {
+ //// final int halfWidth = (int) (insideWidth / 2.d);
+ //// paintGradientLine( g2d, startOffset, insideWidth, halfWidth, startOffset, top, lineHeight );
+ //// } else if ( timeSpan.contains() ) {
+ //// paintAbsoluteInside( g2d );
+ //// } else if ( timeSpan.isContainedBy() ) {
+ //// paintAbsoluteInside( g2d );
+ //// } else if ( timeSpan.isOverlapping() ) {
+ //// paintAbsoluteInside( g2d );
+ //// }
+ // }
+
+ // protected void paintAbsoluteInside( final Graphics2D g2d ) {
+ // final int width = getWidth();
+ // final int height = getHeight();
+ // final int halfHeight = height / 2 - 1;
+ // final int halfThick = TimeSpanDrawUtil.LINE_THICKNESS / 2;
+ // final int top = Math.max( 0, halfHeight - halfThick );
+ // final int bottom = Math.min( height, top + TimeSpanDrawUtil.LINE_THICKNESS );
+ // final int lineHeight = bottom - top;
+ // if ( isFuzzy() ) {
+ // final int quarterWidth = (int) (width / 4.d);
+ // paintGradientLine( g2d, 0, quarterWidth, quarterWidth, 0, top, lineHeight );
+ //
+ // final int halfWidth = (int) (width / 2.d);
+ // paintSolidLine( g2d, quarterWidth, halfWidth + 2, top, lineHeight );
+ //
+ // final int threeqWidth = width - quarterWidth;
+ // paintGradientLine( g2d, threeqWidth, quarterWidth, threeqWidth, width, top, lineHeight );
+ // } else {
+ // paintSolidLine( g2d, 0, width, top, lineHeight );
+ // }
+ // }
+
+
+ protected void paintAbsoluteLine( final Graphics2D g2d, final TimeSpan timeSpan ) {
+ final int width = getWidth();
+ final int height = getHeight();
+ final int halfHeight = height / 2 - 1;
+ final int halfThick = TimeSpanDrawUtil.LINE_THICKNESS / 2;
+ final int top = Math.max( 0, halfHeight - halfThick );
+ final int bottom = Math.min( height, top + TimeSpanDrawUtil.LINE_THICKNESS );
+ final int lineHeight = bottom - top;
+ if ( isFuzzy() ) {
+ final int quarterWidth = (int)(width / 4.d);
+ final int halfWidth = (int)(width / 2.d);
+ final int threeqWidth = width - quarterWidth;
+ final Color solidColor = getPlainColor( isSelected(), isFocused(), false, halfWidth );
+ // paint the center
+ g2d.setPaint( solidColor );
+ g2d.fillRect( quarterWidth, top, halfWidth + 2, lineHeight );
+ // paint the fuzzy sides
+ final Color fuzzyColor = getPlainColor( isSelected(), isFocused(), true, quarterWidth );
+ // paint the left fade section
+ final GradientPaint gradient1 = new GradientPaint( 0, 0, fuzzyColor,
+ quarterWidth, 0, solidColor, false );
+ g2d.setPaint( gradient1 );
+ g2d.fillRect( 0, top, quarterWidth, lineHeight );
+ // paint the right fade section
+ final GradientPaint gradient2 = new GradientPaint( threeqWidth, 0, solidColor,
+ width, 0, fuzzyColor, false );
+ g2d.setPaint( gradient2 );
+ g2d.fillRect( threeqWidth, top, quarterWidth, lineHeight );
+ } else {
+ final Color solidColor = getPlainColor( isSelected(), isFocused(), false, width );
+ // paint the center
+ g2d.setPaint( solidColor );
+ g2d.fillRect( 0, top, width, lineHeight );
+ }
+ }
+
+ public void paint( final Graphics g ) {
+ final TimeSpan timeSpan = getTimeSpan();
+ final Graphics2D g2d = (Graphics2D)g.create();
+ if ( isExpanded() ) {
+ paintDiamond( g2d );
+ } else {
+ paintStart( g2d, timeSpan );
+ paintEnd( g2d, timeSpan );
+ if ( !timeSpan.isSingleDate() ) {
+ paintInnerLine( g2d, timeSpan );
+ }
+ }
+ g2d.dispose();
+ }
+
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/TimeSpanRenderer.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/TimeSpanRenderer.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/TimeSpanRenderer.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/plus/TimeSpanRenderer.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,21 @@
+package org.chboston.cnlp.timeline.gui.timespan.plus;
+
+
+import org.chboston.cnlp.timeline.gui.timeline.TimelineComponent;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+
+import javax.swing.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/2/13
+ */
+public interface TimeSpanRenderer {
+
+ JComponent getTimeSpanRendererComponent( final TimelineComponent timelineComponent,
+ final PointedTimeSpan timeSpan,
+ boolean selected, boolean expanded,
+ boolean Focused );
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/DefaultTimeSpanSelectionModel.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/DefaultTimeSpanSelectionModel.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/DefaultTimeSpanSelectionModel.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/DefaultTimeSpanSelectionModel.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,159 @@
+package org.chboston.cnlp.timeline.gui.timespan.selection;
+
+
+import org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+
+import java.util.*;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 9/20/12
+ */
+final public class DefaultTimeSpanSelectionModel implements TimeSpanSelectionModel {
+
+ final private Collection<TimeSpanSelectionListener> _listeners = new HashSet<>();
+ final private Map<PointedTimeSpan, Collection<Entity>> _selectedEntities = new HashMap<>();
+ final private Set<String> _selectedTexts = new HashSet<>();
+ final private SemanticClassType _semanticType;
+ private boolean _valueIsAdjusting;
+
+
+ public DefaultTimeSpanSelectionModel() {
+ this( null );
+ }
+
+ public DefaultTimeSpanSelectionModel( final SemanticClassType semanticType ) {
+ _semanticType = semanticType;
+ }
+
+ public void setSelectedEntities( final Object source,
+ final Map<PointedTimeSpan, Collection<Entity>> timeSpanEntities ) {
+ if ( timeSpanEntities == null ) {
+ return;
+ }
+ _selectedEntities.clear();
+ _selectedEntities.putAll( timeSpanEntities );
+ fireValueChanged( source );
+ }
+
+ public Map<PointedTimeSpan, Collection<Entity>> getSelectedEntities() {
+ return _selectedEntities;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setSelectedTerms( final Object source, final Collection<String> texts ) {
+ _selectedTexts.clear();
+ for ( String text : texts ) {
+ if ( !text.trim().isEmpty() ) {
+ _selectedTexts.add( text );
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Collection<String> getSelectedTexts() {
+ return _selectedTexts;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SemanticClassType getSemanticType() {
+ return _semanticType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeSelectedTimeSpan( final Object source, final PointedTimeSpan timeSpan ) {
+ if ( timeSpan == null ) {
+ return;
+ }
+ final Collection<Entity> removedEntities = _selectedEntities.remove( timeSpan );
+ if ( removedEntities != null ) {
+ fireValueChanged( source );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void clearSelection( final Object source ) {
+ _selectedEntities.clear();
+ fireValueChanged( source );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isSelectionEmpty() {
+ return _selectedEntities.isEmpty();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setValueIsAdjusting( final Object source, final boolean valueIsAdjusting ) {
+ if ( valueIsAdjusting != _valueIsAdjusting ) {
+ _valueIsAdjusting = valueIsAdjusting;
+ fireValueChanged( source );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean getValueIsAdjusting() {
+ return _valueIsAdjusting;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addSelectionListener( final TimeSpanSelectionListener listener ) {
+ if ( listener != null ) {
+ _listeners.add( listener );
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeSelectionListener( final TimeSpanSelectionListener listener ) {
+ if ( listener != null ) {
+ _listeners.remove( listener );
+ }
+ }
+
+ private void fireValueChanged( final Object source ) {
+ if ( _listeners.isEmpty() ) {
+ return;
+ }
+ final TimeSpanSelectionEvent event = new TimeSpanSelectionEvent( source,
+ _selectedEntities,
+ _selectedTexts,
+ _semanticType,
+ getValueIsAdjusting() );
+ for ( TimeSpanSelectionListener listener : _listeners ) {
+ listener.valueChanged( event );
+ }
+ }
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/SelectionForwarder.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/SelectionForwarder.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/SelectionForwarder.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/SelectionForwarder.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,76 @@
+package org.chboston.cnlp.timeline.gui.timespan.selection;
+
+import org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/16/13
+ */
+public enum SelectionForwarder implements TimeSpanSelectionListener {
+ INSTANCE;
+
+ static public SelectionForwarder getInstance() {
+ return INSTANCE;
+ }
+
+ final private Collection<TimeSpanSelectionModel> _models = new HashSet<>();
+ boolean _isForwarding;
+
+ public void addSelectionModel( final TimeSpanSelectionModel model ) {
+ if ( model != null ) {
+ _models.add( model );
+ model.addSelectionListener( this );
+ }
+ }
+
+ public void removeSelectionModel( final TimeSpanSelectionModel model ) {
+ if ( model != null ) {
+ _models.remove( model );
+ model.removeSelectionListener( this );
+ }
+ }
+
+ public void removeAllSelectionModels() {
+ for ( TimeSpanSelectionModel model : _models ) {
+ model.removeSelectionListener( this );
+ }
+ _models.clear();
+ }
+
+ private void forward( final Object source, final Map<PointedTimeSpan, Collection<Entity>> selectedEntities,
+ final Collection<String> selectionTexts, final SemanticClassType semanticType ) {
+ for ( TimeSpanSelectionModel model : _models ) {
+ if ( model.equals( source ) ) {
+ continue;
+ }
+ final SemanticClassType modelSemanticType = model.getSemanticType();
+ if ( modelSemanticType != null && modelSemanticType != semanticType ) {
+ model.clearSelection( source );
+ }
+ // removed else 5/28/2014 spf -- did this mess up the "add event" painting?
+// } else {
+ model.setValueIsAdjusting( source, true );
+ model.setSelectedTerms( source, selectionTexts );
+ model.setSelectedEntities( source, selectedEntities );
+ model.setValueIsAdjusting( source, false );
+// }
+ }
+ }
+
+
+ public void valueChanged( final TimeSpanSelectionEvent event ) {
+ if ( _isForwarding || event == null || event.getValueIsAdjusting() ) {
+ return;
+ }
+ _isForwarding = true;
+ forward( event.getSource(), event.getSelectedEntities(), event.getSelectionTexts(), event.getSemanticType() );
+ _isForwarding = false;
+ }
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionEvent.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionEvent.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionEvent.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionEvent.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,94 @@
+package org.chboston.cnlp.timeline.gui.timespan.selection;
+
+import net.jcip.annotations.Immutable;
+import org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+
+import java.util.Collection;
+import java.util.EventObject;
+import java.util.Map;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 9/20/12
+ */
+@Immutable
+final public class TimeSpanSelectionEvent extends EventObject {
+
+ final private Map<PointedTimeSpan, Collection<Entity>> _timeSpanEntities;
+ private final Collection<String> _selectionTexts;
+ private final SemanticClassType _semanticType;
+ private final boolean _isAdjusting;
+
+ public TimeSpanSelectionEvent( final Object source,
+ final Map<PointedTimeSpan, Collection<Entity>> timeSpanEntities,
+ final Collection<String> selectionTexts,
+ final SemanticClassType semanticType,
+ final boolean isAdjusting ) {
+ super( source );
+ _timeSpanEntities = timeSpanEntities;
+ _selectionTexts = selectionTexts;
+ _semanticType = semanticType;
+ _isAdjusting = isAdjusting;
+ }
+
+
+ // /**
+ // * Represents a change in selection status between {@code firstIndex} and
+ // * {@code lastIndex}, inclusive. {@code firstIndex} is less than or equal to
+ // * {@code lastIndex}. The selection of at least one index within the range will
+ // * have changed.
+ // *
+ // * @param selections all selections to which this event applies
+ // * @param isAdjusting whether or not this is one in a series of
+ // * multiple events, where changes are still being made
+ // */
+
+ public Map<PointedTimeSpan, Collection<Entity>> getSelectedEntities() {
+ return _timeSpanEntities;
+ }
+
+ // public Collection<TimeSpanPlus> getSelectedTimeSpans() {
+ // return _timeSpanEntities.keySet();
+ // }
+
+ public Collection<String> getSelectionTexts() {
+ return _selectionTexts;
+ }
+
+ public SemanticClassType getSemanticType() {
+ return _semanticType;
+ }
+
+ /**
+ * Returns whether or not this is one in a series of multiple events,
+ * where changes are still being made. See the documentation for
+ * {@link javax.swing.ListSelectionModel#setValueIsAdjusting} for
+ * more details on how this is used.
+ *
+ * @return {@code true} if this is one in a series of multiple events,
+ * where changes are still being made
+ */
+ public boolean getValueIsAdjusting() {
+ return _isAdjusting;
+ }
+
+ /**
+ * Returns a {@code String} that displays and identifies this
+ * object's properties.
+ *
+ * @return a String representation of this object
+ */
+ public String toString() {
+ String properties =
+ " source=" + getSource() +
+ " selections= " + _timeSpanEntities.toString() +
+ (_semanticType == null ? "" : (" semantic type= " + _semanticType.toString())) +
+ " isAdjusting= " + _isAdjusting +
+ " ";
+ return getClass().getName() + "[" + properties + "]";
+ }
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionListener.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionListener.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionListener.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionListener.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,18 @@
+package org.chboston.cnlp.timeline.gui.timespan.selection;
+
+import java.util.EventListener;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 9/20/12
+ */
+public interface TimeSpanSelectionListener extends EventListener {
+ /**
+ * Called whenever the value of the selection changes.
+ *
+ * @param event the event that characterizes the change.
+ */
+ void valueChanged( final TimeSpanSelectionEvent event );
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionModel.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionModel.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionModel.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/gui/timespan/selection/TimeSpanSelectionModel.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,89 @@
+package org.chboston.cnlp.timeline.gui.timespan.selection;
+
+import org.chboston.cnlp.nlp.annotation.classtype.SemanticClassType;
+import org.chboston.cnlp.nlp.annotation.entity.Entity;
+import org.chboston.cnlp.timeline.timespan.plus.PointedTimeSpan;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 9/20/12
+ */
+public interface TimeSpanSelectionModel {
+
+ void setSelectedEntities( final Object source, Map<PointedTimeSpan, Collection<Entity>> timeSpanEntities );
+
+ Map<PointedTimeSpan, Collection<Entity>> getSelectedEntities();
+
+ void setSelectedTerms( final Object source, final Collection<String> text );
+
+ Collection<String> getSelectedTexts();
+
+ SemanticClassType getSemanticType();
+
+ void removeSelectedTimeSpan( final Object source, final PointedTimeSpan timeSpan );
+
+ void clearSelection( final Object source );
+
+ /**
+ * Returns true if no TimeSpans are selected.
+ */
+ boolean isSelectionEmpty();
+
+ /**
+ * Sets the {@code valueIsAdjusting} property, which indicates whether
+ * or not upcoming selection changes should be considered part of a single
+ * change. The value of this property is used to initialize the
+ * {@code valueIsAdjusting} property of the {@code ListSelectionEvent}s that
+ * are generated.
+ * <p/>
+ * For example, if the selection is being updated in response to a user
+ * drag, this property can be set to {@code true} when the drag is initiated
+ * and set to {@code false} when the drag is finished. During the drag,
+ * listeners receive events with a {@code valueIsAdjusting} property
+ * set to {@code true}. At the end of the drag, when the change is
+ * finalized, listeners receive an event with the value set to {@code false}.
+ * Listeners can use this pattern if they wish to update only when a change
+ * has been finalized.
+ * <p/>
+ * Setting this property to {@code true} begins a series of changes that
+ * is to be considered part of a single change. When the property is changed
+ * back to {@code false}, an event is sent out characterizing the entire
+ * selection change (if there was one), with the event's
+ * {@code valueIsAdjusting} property set to {@code false}.
+ *
+ * @param valueIsAdjusting the new value of the property
+ * @see #getValueIsAdjusting
+ */
+ void setValueIsAdjusting( final Object source, boolean valueIsAdjusting );
+
+ /**
+ * Returns {@code true} if the selection is undergoing a series of changes.
+ *
+ * @return true if the selection is undergoing a series of changes
+ * @see #setValueIsAdjusting
+ */
+ boolean getValueIsAdjusting();
+
+ /**
+ * Add a listener to the list that's notified each time a change
+ * to the selection occurs.
+ *
+ * @param listener the TimeSpanSelectionListener
+ * @see #removeSelectionListener
+ */
+ void addSelectionListener( final TimeSpanSelectionListener listener );
+
+ /**
+ * Remove a listener from the list that's notified each time a
+ * change to the selection occurs.
+ *
+ * @param listener the TimeSpanSelectionListener
+ * @see #addSelectionListener
+ */
+ void removeSelectionListener( final TimeSpanSelectionListener listener );
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUIDelegate.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUIDelegate.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUIDelegate.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUIDelegate.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,194 @@
+package org.chboston.cnlp.timeline.oldUI;
+
+import java.awt.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/10/12
+ */
+final public class SpiralBarUIDelegate {
+
+ private double _spokeDistance = SpiralBarUtil.MED_SPOKE_LENGTH;
+ private int _loopCount = SpiralBarUtil.MED_LOOP_COUNT;
+ private double _stopRadian = SpiralBarUtil.MED_STOP_RADIAN;
+ private double _startRadian = SpiralBarUtil.START_RADIAN;
+
+ private int _circumference = SpiralBarUtil.SPIRAL_CIRCUMFERENCE;
+ private int _trackSpacer = SpiralBarUtil.SCROLLBAR_TRACK_SPACER;
+
+
+ private Color _shadowColor = Color.GRAY;
+ private Color _highlightColor = Color.LIGHT_GRAY;
+ private Color _focusColor = Color.LIGHT_GRAY;
+ private int _scrollBarWidth;
+ private Rectangle _spiralBounds = new Rectangle();
+
+
+ // private java.util.List<SpotSketcher> _spotSketcherList;
+ private SpiralBarUtil.SpotSketcher _spotSketcher;
+ private SpiralBarUtil.SpanSketcher _spanSketcher;
+ private Set<Integer> _spotSet;
+ private Set<Point> _spanSet;
+
+
+ public void setSpokeDistance( final double spokeDistance ) {
+ _spokeDistance = spokeDistance;
+ }
+
+ public double getSpokeDistance() {
+ return _spokeDistance;
+ }
+
+ public void setLoopCount( final int loopCount ) {
+ _loopCount = loopCount;
+ }
+
+ public int getLoopCount() {
+ return _loopCount;
+ }
+
+ public void setStopRadian( final double stopRadian ) {
+ _stopRadian = stopRadian;
+ }
+
+ public double getStopRadian() {
+ return _stopRadian;
+ }
+
+ public void setStartRadian( final double startRadian ) {
+ _startRadian = startRadian;
+ }
+
+ public double getStartRadian() {
+ return _startRadian;
+ }
+
+ public void setCircumference( final int circumference ) {
+ _circumference = circumference;
+ }
+
+ public int getCircumference() {
+ return _circumference;
+ }
+
+ public int getTrackSpacer() {
+ return _trackSpacer;
+ }
+
+ public void setTrackSpacer( final int trackSpacer ) {
+ _trackSpacer = trackSpacer;
+ }
+
+ public void setShadowColor( final Color shadowColor ) {
+ _shadowColor = shadowColor;
+ }
+
+ public Color getShadowColor() {
+ return _shadowColor;
+ }
+
+ public void setHighlightColor( final Color highlightColor ) {
+ _highlightColor = highlightColor;
+ }
+
+ public Color getHighlightColor() {
+ return _highlightColor;
+ }
+
+ public void setFocusColor( final Color focusColor ) {
+ _focusColor = focusColor;
+ }
+
+ public Color getFocusColor() {
+ return _focusColor;
+ }
+
+ public void setScrollBarWidth( final int scrollBarWidth ) {
+ if ( scrollBarWidth <= 0 ) {
+ _scrollBarWidth = 16;
+ } else {
+ _scrollBarWidth = scrollBarWidth;
+ }
+ }
+
+ public int getScrollBarWidth() {
+ return _scrollBarWidth;
+ }
+
+ public void setSpiralBounds( final Rectangle bounds ) {
+ _spiralBounds = bounds;
+ }
+
+ public void setSpiralBounds( final int x, final int y, final int width, final int height ) {
+ _spiralBounds = new Rectangle( x, y, width, height );
+ }
+
+ public Rectangle getSpiralBounds() {
+ return _spiralBounds;
+ }
+
+ // final public void addSpotSketcher( final SpotSketcher spotSketcher ) {
+ // if ( _spotSketcherList == null ) {
+ // _spotSketcherList = new ArrayList<SpotSketcher>();
+ // }
+ // if ( !_spotSketcherList.contains( spotSketcher ) ) {
+ // _spotSketcherList.add( spotSketcher );
+ // }
+ // }
+ //
+ // final public void removeSpotSketcher( final SpotSketcher spotSketcher ) {
+ // if ( _spotSketcherList != null ) {
+ // _spotSketcherList.remove( spotSketcher );
+ // }
+ // }
+ //
+ // final public Collection<SpotSketcher> getSpotSketchers() {
+ // return _spotSketcherList;
+ // }
+
+ final public void setSpotSketcher( final SpiralBarUtil.SpotSketcher spotSketcher ) {
+ _spotSketcher = spotSketcher;
+ }
+
+ final public SpiralBarUtil.SpotSketcher getSpotSketcher() {
+ return _spotSketcher;
+ }
+
+ final public void setSpanSketcher( final SpiralBarUtil.SpanSketcher spanSketcher ) {
+ _spanSketcher = spanSketcher;
+ }
+
+ final public SpiralBarUtil.SpanSketcher getSpanSketcher() {
+ return _spanSketcher;
+ }
+
+
+ final public void addSpot( final int spot ) {
+ if ( _spotSet == null ) {
+ _spotSet = new HashSet<>();
+ }
+ _spotSet.add( spot );
+ }
+
+ final public Collection<Integer> getSpots() {
+ return Collections.unmodifiableSet( _spotSet );
+ }
+
+ final public void addSpan( final int start, final int stop ) {
+ if ( _spanSet == null ) {
+ _spanSet = new HashSet<>();
+ }
+ _spanSet.add( new Point( start, stop ) );
+ }
+
+ final public Collection<Point> getSpans() {
+ return Collections.unmodifiableSet( _spanSet );
+ }
+
+
+}
Added: ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUtil.java
URL: http://svn.apache.org/viewvc/ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUtil.java?rev=1660963&view=auto
==============================================================================
--- ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUtil.java (added)
+++ ctakes/sandbox/timelanes/org/chboston/cnlp/timeline/oldUI/SpiralBarUtil.java Thu Feb 19 18:06:13 2015
@@ -0,0 +1,410 @@
+package org.chboston.cnlp.timeline.oldUI;
+
+import java.awt.*;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+
+/**
+ * Author: SPF
+ * Affiliation: CHIP-NLP
+ * Date: 8/10/12
+ */
+final public class SpiralBarUtil {
+
+
+ private SpiralBarUtil() {
+ }
+
+ static public final Color TRACK_COLOR = new Color( 156, 156, 156, 196 );
+ static public final Color TRACK_HIGHLIGHT = Color.LIGHT_GRAY.brighter();
+ static public final Color TRACK_SHADOW = Color.GRAY.brighter();
+
+ static public final Color THUMB_COLOR = Color.LIGHT_GRAY.brighter();
+ static public final Color THUMB_SHADOW = new Color( 64, 64, 64, 128 );
+ static public final Color THUMB_SHADOW_EDGE = new Color( 128, 128, 128, 128 );
+
+ static public final Color TIMELINE_COLOR = Color.DARK_GRAY;
+ static public final Color DATE_COLOR = Color.GREEN;
+ static public final Color DATE_HIGHLIGHT = Color.LIGHT_GRAY;
+ static public final Color DATE_SHADOW = Color.BLACK;
+ // static public final Color DATE_SELECTED = Color.CYAN.darker().darker();
+ static public final Color DATE_SELECTED = Color.CYAN.darker();
+
+ static public final Color TIMELINE_ENDPOINT_COLOR = Color.DARK_GRAY;
+ static public final Color TIMELINE_ENDPOINT_SHADOW = Color.BLACK;
+
+ static public final Stroke STROKE_SEVEN = new BasicStroke( 7, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_SIX = new BasicStroke( 6, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_FIVE = new BasicStroke( 5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_FOUR = new BasicStroke( 4, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_THREE = new BasicStroke( 3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_TWO = new BasicStroke( 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_ONE = new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+
+ static public final Stroke STROKE_ROUND_NINE = new BasicStroke( 9, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_ROUND_SEVEN = new BasicStroke( 7, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_ROUND_SIX = new BasicStroke( 6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_ROUND_FIVE = new BasicStroke( 5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+ static public final Stroke STROKE_ROUND_FOUR = new BasicStroke( 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND );
+
+ static public final Stroke ZOOM_DRAG_STROKE_1 = new BasicStroke( 22, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Stroke ZOOM_DRAG_STROKE = new BasicStroke( 20, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND );
+ static public final Color ZOOM_DRAG_COLOR = Color.LIGHT_GRAY;
+ static public final Color ZOOM_DRAG_SHADOW = Color.GRAY;
+
+ static public final double RADIAN = Math.PI / 180; // 1 Radian
+
+ static public final double START_RADIAN = 0;
+
+ // Good combinations are 2 & 2, 1 & 4, 1.5 & 3, 0.9 & 5, 1.1 & 4,
+ static public final double SMALL_SPOKE_LENGTH = 0.9;
+ static public final int SMALL_LOOP_COUNT = 5;
+ static public final double SMALL_STOP_RADIAN = 5.75;
+
+ static public final double MED_SPOKE_LENGTH = 1.475;
+ static public final int MED_LOOP_COUNT = 3;
+ static public final double MED_STOP_RADIAN = 3.75;
+
+ static public final double LARGE_SPOKE_LENGTH = 2;
+ static public final int LARGE_LOOP_COUNT = 2;
+ static public final double LARGE_STOP_RADIAN = 2.75;
+
+ static public final int SCROLLBAR_TRACK_SPACER = 3;
+ static public final int SPIRAL_CIRCUMFERENCE = 72;
+
+
+ static public GeneralPath createCompleteSpiralPath( final SpiralBarUIDelegate spiralUI, final int width,
+ final double start, final double end ) {
+ final int circumference = spiralUI.getCircumference();
+ final double centerX = circumference / 2;
+ final double centerY = circumference / 2;
+ return createCompleteSpiralPath( centerX, centerY, width - centerX, centerY, start, end,
+ spiralUI.getStopRadian(), spiralUI.getSpokeDistance() );
+ }
+
+
+ /**
+ * Archimedean Spiral.
+ *
+ * @return Graphics2D GeneralPath for the spiral
+ */
+ static public GeneralPath createCompleteSpiralPath( final double centerX1, final double centerY1,
+ final double centerX2, final double centerY2,
+ final double start, final double end,
+ final double loops, final double spokeDistance ) {
+ final double startDistance = start * 360 * RADIAN;
+ final double stopDistance = loops * 360 * RADIAN;
+ final double endDistance = end * 360 * RADIAN;
+
+ double r = spokeDistance * startDistance;
+ double x = Math.cos( startDistance ) * r + centerX1;
+ double y = Math.sin( startDistance ) * r + centerY1;
+
+ final GeneralPath path = new GeneralPath();
+ // start at the center of the west spiral
+ path.moveTo( x, y );
+ for ( double theta = startDistance; theta < stopDistance; theta += RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = Math.cos( theta ) * r + centerX1;
+ y = Math.sin( theta ) * r + centerY1;
+ path.lineTo( x, y );
+ }
+
+ x = centerX2 - Math.cos( stopDistance ) * r;
+ y = Math.sin( stopDistance ) * r + centerY2;
+
+ // start at the turn of the east spiral
+ path.lineTo( x, y );
+ for ( double theta = stopDistance; theta >= endDistance; theta -= RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = centerX2 - Math.cos( theta ) * r;
+ y = Math.sin( theta ) * r + centerY2;
+ path.lineTo( x, y );
+ }
+ return path;
+ }
+
+
+ /**
+ * Archimedean Spiral.
+ *
+ * @return Graphics2D GeneralPath for the spiral
+ */
+ static public GeneralPath createLeftSpiralPath( final double centerX1, final double centerY1,
+ final double start, final double end,
+ final double spokeDistance ) {
+ final double startDistance = start * 360 * RADIAN;
+ final double stopDistance = end * 360 * RADIAN;
+
+ double r = spokeDistance * startDistance;
+ double x = Math.cos( startDistance ) * r + centerX1;
+ double y = Math.sin( startDistance ) * r + centerY1;
+
+ final GeneralPath path = new GeneralPath();
+ // start at the center of the west spiral
+ path.moveTo( x, y );
+ for ( double theta = startDistance; theta < stopDistance; theta += RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = Math.cos( theta ) * r + centerX1;
+ y = Math.sin( theta ) * r + centerY1;
+ path.lineTo( x, y );
+ }
+ return path;
+ }
+
+ /**
+ * Archimedean Spiral.
+ *
+ * @return Graphics2D GeneralPath for the spiral
+ */
+ static public double getLeftSpiralTheta( final double pointX, final double pointY,
+ final SpiralBarUIDelegate spiralUI ) {
+ final Point2D wantedPoint = new Point2D.Double( pointX, pointY );
+ final int circumference = spiralUI.getCircumference();
+ final int centerX1 = circumference / 2;
+ final int centerY1 = circumference / 2;
+ final double stopRadian = spiralUI.getStopRadian();
+ final double spokeDistance = spiralUI.getSpokeDistance();
+ final double startDistance = 0;
+ final double stopDistance = stopRadian * 360 * RADIAN;
+
+ double r = spokeDistance * startDistance;
+ double x = Math.cos( startDistance ) * r + centerX1;
+ double y = Math.sin( startDistance ) * r + centerY1;
+
+ Point2D.Double spiralPoint = new Point2D.Double( x, y );
+ double bestTheta = startDistance;
+ double bestDistance = wantedPoint.distance( spiralPoint );
+
+ // start at the center of the west spiral
+ for ( double theta = startDistance; theta < stopDistance; theta += RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = Math.cos( theta ) * r + centerX1;
+ y = Math.sin( theta ) * r + centerY1;
+ spiralPoint = new Point2D.Double( x, y );
+ final double distance = wantedPoint.distance( spiralPoint );
+ if ( distance <= bestDistance ) {
+ bestTheta = theta;
+ bestDistance = distance;
+ }
+ }
+ return bestTheta / 360 / RADIAN;
+ }
+
+ /**
+ * Archimedean Spiral.
+ *
+ * @return Graphics2D GeneralPath for the spiral
+ */
+ static public double getRightSpiralTheta( final double pointX, final double pointY,
+ final SpiralBarUIDelegate spiralUI, final int spiralWidth ) {
+ final Point2D wantedPoint = new Point2D.Double( pointX, pointY );
+ final int circumference = spiralUI.getCircumference();
+ final int centerX1 = spiralWidth - circumference / 2;
+ final int centerY1 = circumference / 2;
+ final double stopRadian = spiralUI.getStopRadian();
+ final double spokeDistance = spiralUI.getSpokeDistance();
+ final double startDistance = 0;
+ final double stopDistance = stopRadian * 360 * RADIAN;
+
+ double r = spokeDistance * stopDistance;
+ double x = centerX1 - Math.cos( stopDistance ) * r;
+ double y = Math.sin( stopDistance ) * r + centerY1;
+
+ Point2D.Double spiralPoint = new Point2D.Double( x, y );
+ double bestTheta = stopDistance;
+ double bestDistance = wantedPoint.distance( spiralPoint );
+
+ // start at the center of the west spiral
+ for ( double theta = stopDistance; theta >= startDistance; theta -= RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = centerX1 - Math.cos( theta ) * r;
+ y = Math.sin( theta ) * r + centerY1;
+ spiralPoint = new Point2D.Double( x, y );
+ final double distance = wantedPoint.distance( spiralPoint );
+ if ( distance <= bestDistance ) {
+ bestTheta = theta;
+ bestDistance = distance;
+ }
+ }
+ return bestTheta / 360 / RADIAN;
+ }
+
+
+ /**
+ * Archimedean Spiral.
+ *
+ * @return Graphics2D GeneralPath for the spiral
+ */
+ static public GeneralPath createRightSpiralPath( final double centerX1, final double centerY1,
+ final double start, final double end,
+ final double spokeDistance, GeneralPath path ) {
+ final double startDistance = start * 360 * RADIAN;
+ final double stopDistance = end * 360 * RADIAN;
+
+ double r = spokeDistance * stopDistance;
+ double x = centerX1 - Math.cos( stopDistance ) * r;
+ double y = Math.sin( stopDistance ) * r + centerY1;
+
+ final boolean havePath = path != null && path.getCurrentPoint() != null;
+ if ( !havePath ) {
+ path = new GeneralPath();
+ // start at the turn of the east spiral
+ path.moveTo( x, y );
+ } else {
+ path.lineTo( x, y );
+ }
+ for ( double theta = stopDistance; theta >= startDistance; theta -= RADIAN ) {
+ r = spokeDistance * theta; // Radius of current point
+ x = centerX1 - Math.cos( theta ) * r;
+ y = Math.sin( theta ) * r + centerY1;
+ path.lineTo( x, y );
+ }
+ return path;
+ }
+
+ static public double getLineLociForPoint( final double x, final double y,
+ final SpiralBarUIDelegate spiralUI, final int spiralWidth,
+ final int firstVisibleX, final int visibleWidth,
+ final int totalLineWidth ) {
+ final int circumference = spiralUI.getCircumference();
+ final int centerX1 = circumference / 2;
+ if ( x >= centerX1 && x <= spiralWidth - centerX1 && y <= 10 ) {
+ // Point is on horizontal line
+ final double sketchX = x - centerX1 - spiralUI.getTrackSpacer();
+ final double sketchWidth = spiralWidth - circumference;
+ final double sketchRatioX = sketchX / sketchWidth;
+ final double scaledX = sketchRatioX * visibleWidth;
+ return firstVisibleX + scaledX;
+ }
+ final double spiralledLength = totalLineWidth - visibleWidth; // full length for spiral
+ final double stopRadian = spiralUI.getStopRadian();
+ if ( x < circumference ) {
+ // Point is on left spiral
+ final double theta = getLeftSpiralTheta( x, y, spiralUI );
+ final double lociX = theta * spiralledLength / stopRadian;
+ final double reverse = spiralledLength - lociX;
+ if ( reverse > firstVisibleX ) {
+ return firstVisibleX;
+ }
+ final double min = Math.min( firstVisibleX, reverse );
+ // System.out.println(
+ // "Left, Loci " + lociX + " lineW " + totalLineWidth + " spiralL " + spiralledLength + " min " + min
+ // + " return " + (firstVisibleX - min) );
+ return firstVisibleX - min;
+ }
+ // Point is on right spiral
+ final double theta = getRightSpiralTheta( x, y, spiralUI, spiralWidth );
+ final double lociX = theta * spiralledLength / stopRadian;
+ // System.out.println(
+ // "Right, Loci " + lociX + " lineW " + totalLineWidth + " spiralL " + spiralledLength + " add " + (
+ // firstVisibleX + visibleWidth) );
+ return Math.min( totalLineWidth, firstVisibleX + visibleWidth + lociX );
+ }
+
+ // TODO - use this for all path creation
+ static public GeneralPath getPathOnCompleteSpiral( final SpiralBarUIDelegate spiralUI, final int spiralWidth,
+ final int wantedX1, final int wantedX2,
+ final int firstVisibleX, final int visibleWidth,
+ final int totalLineWidth ) {
+ final int circumference = spiralUI.getCircumference();
+ final int centerX1 = circumference / 2;
+ final int centerY1 = circumference / 2;
+ final double spiralledLength = totalLineWidth - visibleWidth; // full length for spiral
+ final double stopRadian = spiralUI.getStopRadian();
+ final double spokeDistance = spiralUI.getSpokeDistance();
+ GeneralPath path = new GeneralPath();
+ if ( wantedX1 < firstVisibleX ) {
+ final double spiralX1 = firstVisibleX - wantedX1; // length for left spiral + x on length
+ final double ratioX1 = stopRadian - stopRadian * spiralX1 / spiralledLength;
+ final double spiralX2 = wantedX2 < firstVisibleX ? firstVisibleX - wantedX2
+ : 0; // length for left spiral + x on length
+ final double ratioX2 = stopRadian - stopRadian * spiralX2 / spiralledLength;
+ path = createLeftSpiralPath( centerX1, centerY1, ratioX1, ratioX2, spokeDistance );
+ if ( wantedX2 <= firstVisibleX ) {
+ return path;
+ }
+ }
+ if ( wantedX1 >= firstVisibleX && wantedX1 <= firstVisibleX + visibleWidth ) {
+ final Point p1 = getPointOnLine( spiralUI, spiralWidth, wantedX1, firstVisibleX, visibleWidth );
+ path.moveTo( p1.x, p1.y );
+ }
+ if ( wantedX2 >= firstVisibleX && wantedX2 <= firstVisibleX + visibleWidth ) {
+ final Point p2 = getPointOnLine( spiralUI, spiralWidth, wantedX2, firstVisibleX, visibleWidth );
+ path.lineTo( p2.x, p2.y );
+ return path;
+ }
+ if ( wantedX2 > firstVisibleX + visibleWidth ) {
+ final double spiralX1 = wantedX1 < firstVisibleX + visibleWidth ? 0 : wantedX1 - firstVisibleX
+ -
+ visibleWidth; // length for left spiral + x on length
+ final double ratioX1 = stopRadian - stopRadian * spiralX1 / spiralledLength;
+ final double spiralX2 = wantedX2 - (firstVisibleX + visibleWidth); // length for left spiral + x on length
+ final double ratioX2 = stopRadian - stopRadian * spiralX2 / spiralledLength;
+ path = createRightSpiralPath( spiralWidth - centerX1, centerY1, ratioX2, ratioX1, spokeDistance, path );
+ }
+ return path;
+ }
+
+ // TODO remove - only used in temp2
+ static public Point getPointOnCompleteSpiral( final SpiralBarUIDelegate spiralUI, final int spiralWidth,
+ final int wantedX,
+ final int firstVisibleX, final int visibleWidth,
+ final int totalLineWidth ) {
+ if ( wantedX >= firstVisibleX && wantedX <= firstVisibleX + visibleWidth ) {
+ return getPointOnLine( spiralUI, spiralWidth, wantedX, firstVisibleX, visibleWidth );
+ }
+ final double spiralledLength = totalLineWidth - visibleWidth; // full length for spiral
+ final double stopRadian = spiralUI.getStopRadian();
+ if ( wantedX < firstVisibleX ) {
+ final double spiralX = firstVisibleX - wantedX; // length for left spiral + x on length
+ final double ratioX = stopRadian * spiralX / spiralledLength;
+ return getPointOnSpiral( spiralUI, stopRadian - ratioX );
+ }
+ final double spiralX = wantedX - (firstVisibleX + visibleWidth);
+ final double ratioX = stopRadian * spiralX / spiralledLength;
+ final Point reversed = getPointOnSpiral( spiralUI, stopRadian - ratioX );
+ return new Point( spiralWidth - reversed.x, reversed.y );
+ }
+
+ static public Point getPointOnLine( final SpiralBarUIDelegate spiralUI, final int spiralWidth,
+ final int wantedX,
+ final int firstVisibleX, final int visibleWidth ) {
+ final int y = 1;
+ final int x = wantedX - firstVisibleX;
+ final int circumference = spiralUI.getCircumference();
+ final int sketchWidth = spiralWidth - circumference;
+ final double scaleX = x / (double)visibleWidth * sketchWidth;
+ return new Point( circumference / 2 + (int)scaleX, y );
+ }
+
+ // TODO remove - only used in getPointOnCompleteSpiral
+ static public Point getPointOnSpiral( final SpiralBarUIDelegate spiralUI, final double ratioX ) {
+ final double rDistance = ratioX * 360 * RADIAN;
+ final double r = rDistance * spiralUI.getSpokeDistance();
+ final double x = Math.cos( rDistance ) * r;
+ final double y = Math.sin( rDistance ) * r;
+
+ final int circumference = spiralUI.getCircumference();
+ final int centerX1 = circumference / 2;
+ final int centerY1 = circumference / 2;
+ return new Point( centerX1 + (int)x, centerY1 + (int)y );
+ }
+
+
+ // static public interface SpotModel {
+ // int getSpotCount();
+ // }
+ //
+ //
+ //
+ // // TODO replace with model, renderers
+ static public interface SpotSketcher {
+ public void sketchSpot( final Graphics2D g, final Point point );
+ }
+
+ static public interface SpanSketcher {
+ public void sketchSpan( final Graphics2D g, final Point point1, final Point point2 );
+ }
+
+}