Last active
          December 26, 2015 01:59 
        
      - 
      
- 
        Save ulmangt/7075276 to your computer and use it in GitHub Desktop. 
    Demonstrates customizing TimeAxisPainter to display half ticks between labeled ticks on timeline.
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | import static com.metsci.glimpse.util.units.time.TimeStamp.*; | |
| import java.awt.geom.Rectangle2D; | |
| import java.util.List; | |
| import java.util.TimeZone; | |
| import javax.media.opengl.GL2; | |
| import com.metsci.glimpse.axis.Axis1D; | |
| import com.metsci.glimpse.axis.painter.TimeAxisPainter; | |
| import com.metsci.glimpse.axis.painter.label.TimeAxisLabelHandler; | |
| import com.metsci.glimpse.axis.painter.label.TimeAxisLabelHandler.TimeStruct; | |
| import com.metsci.glimpse.axis.painter.label.TimeAxisLabelHandler.TimeStructFactory; | |
| import com.metsci.glimpse.context.GlimpseBounds; | |
| import com.metsci.glimpse.context.GlimpseContext; | |
| import com.metsci.glimpse.examples.Example; | |
| import com.metsci.glimpse.plot.timeline.StackedTimePlot2D; | |
| import com.metsci.glimpse.plot.timeline.data.Epoch; | |
| import com.metsci.glimpse.support.color.GlimpseColor; | |
| import com.metsci.glimpse.support.settings.OceanLookAndFeel; | |
| import com.metsci.glimpse.util.units.time.Time; | |
| import com.metsci.glimpse.util.units.time.TimeStamp; | |
| import com.metsci.glimpse.util.units.time.format.TimeStampFormat; | |
| public class TimelineHalfTicksExample extends CollapsibleTimelinePlotExample | |
| { | |
| public static void main( String[] args ) throws Exception | |
| { | |
| Example example = Example.showWithSwing( new TimelineHalfTicksExample( ) ); | |
| // use the ocean look and feel | |
| example.getCanvas( ).setLookAndFeel( new OceanLookAndFeel( ) ); | |
| } | |
| @Override | |
| public StackedTimePlot2D getLayout( ) | |
| { | |
| StackedTimePlot2D plot = super.getLayout( ); | |
| plot.setTimeAxisPainter( new HalfTickTimeAxisPainter( plot.getEpoch( ) ) ); | |
| return plot; | |
| } | |
| public static class HalfTickTimeAxisPainter extends TimeAxisPainter | |
| { | |
| public HalfTickTimeAxisPainter( Epoch epoch ) | |
| { | |
| super( new TimeAxisLabelHandler( epoch ) ); | |
| } | |
| //@formatter:off | |
| public HalfTickTimeAxisPainter( TimeStampFormat minuteSecondFormat, | |
| TimeStampFormat hourMinuteFormat, | |
| TimeStampFormat hourDayMonthFormat, | |
| TimeStampFormat dayMonthYearFormat, | |
| TimeStampFormat dayFormat, | |
| TimeStampFormat dayMonthFormat, | |
| TimeStampFormat monthYearFormat, | |
| TimeStampFormat yearFormat, | |
| TimeZone timeZone, Epoch epoch ) | |
| { | |
| super( new TimeAxisLabelHandler( minuteSecondFormat, hourMinuteFormat, hourDayMonthFormat, dayMonthYearFormat, dayFormat, dayMonthFormat, monthYearFormat, yearFormat, timeZone, epoch ) ); | |
| } | |
| //@formatter:on | |
| @Override | |
| public void paintTo( GlimpseContext context, GlimpseBounds bounds, Axis1D axis ) | |
| { | |
| super.paintTo( context, bounds, axis ); | |
| if ( textRenderer == null ) return; | |
| GL2 gl = context.getGL( ).getGL2( ); | |
| int width = bounds.getWidth( ); | |
| int height = bounds.getHeight( ); | |
| if ( width == 0 || height == 0 ) return; | |
| gl.glMatrixMode( GL2.GL_PROJECTION ); | |
| gl.glLoadIdentity( ); | |
| gl.glOrtho( -0.5, width - 1 + 0.5f, -0.5, height - 1 + 0.5f, -1, 1 ); | |
| gl.glMatrixMode( GL2.GL_MODELVIEW ); | |
| gl.glLoadIdentity( ); | |
| gl.glColor4fv( tickColor, 0 ); | |
| List<TimeStamp> tickTimes = handler.tickTimes( axis, width ); | |
| double tickInterval = handler.tickInterval( tickTimes ); | |
| ///////////// START MODIFIED CODE ///////////// | |
| // Tick marks | |
| gl.glBegin( GL2.GL_LINES ); | |
| for ( int i = 0; i < tickTimes.size( ); i++ ) | |
| { | |
| TimeStamp t = tickTimes.get( i ); | |
| double x = axis.valueToScreenPixel( fromTimeStamp( t ) ); | |
| gl.glVertex2d( x, height ); | |
| gl.glVertex2d( x, height - tickLineLength ); | |
| // draw half tick | |
| if ( i < tickTimes.size( ) - 1 ) | |
| { | |
| TimeStamp t1 = tickTimes.get( i + 1 ); | |
| TimeStamp halfway = t.add( t.durationBefore( t1 ) / 2.0 ); | |
| x = axis.valueToScreenPixel( fromTimeStamp( halfway ) ); | |
| gl.glVertex2d( x, height ); | |
| gl.glVertex2d( x, height - tickLineLength ); | |
| } | |
| } | |
| gl.glEnd( ); | |
| ///////////// END MODIFIED CODE ///////////// | |
| if ( showCurrentTimeLabel ) drawCurrentTimeTick( gl, axis, width, height ); | |
| GlimpseColor.setColor( textRenderer, textColor ); | |
| textRenderer.beginRendering( width, height ); | |
| try | |
| { | |
| if ( tickInterval <= Time.fromMinutes( 1 ) ) | |
| { | |
| // Time labels | |
| double jTimeText = printTickLabels( tickTimes, axis, handler.getSecondMinuteFormat( ), width, height ); | |
| // Date labels | |
| printHoverLabels( tickTimes, axis, handler.getHourDayMonthFormat( ), handler.getHourStructFactory( ), jTimeText, width, height ); | |
| } | |
| else if ( tickInterval <= Time.fromHours( 12 ) ) | |
| { | |
| // Time labels | |
| double jTimeText = printTickLabels( tickTimes, axis, handler.getHourMinuteFormat( ), width, height ); | |
| // Date labels | |
| printHoverLabels( tickTimes, axis, handler.getDayMonthYearFormat( ), handler.getDayStructFactory( ), jTimeText, width, height ); | |
| } | |
| else if ( tickInterval <= Time.fromDays( 10 ) ) | |
| { | |
| // Date labels | |
| double jTimeText = printTickLabels( tickTimes, axis, handler.getDayFormat( ), width, height ); | |
| // Year labels | |
| printHoverLabels( tickTimes, axis, handler.getMonthYearFormat( ), handler.getMonthStructFactory( ), jTimeText, width, height ); | |
| } | |
| else if ( tickInterval <= Time.fromDays( 60 ) ) | |
| { | |
| // Date labels | |
| double jTimeText = printTickLabels( tickTimes, axis, handler.getMonthFormat( ), width, height ); | |
| // Year labels | |
| printHoverLabels( tickTimes, axis, handler.getYearFormat( ), handler.getYearStructFactory( ), jTimeText, width, height ); | |
| } | |
| else | |
| { | |
| // Date labels | |
| printTickLabels( tickTimes, axis, handler.getYearFormat( ), width, height ); | |
| } | |
| } | |
| finally | |
| { | |
| textRenderer.endRendering( ); | |
| } | |
| } | |
| protected TimeStamp getCurrentTime( ) | |
| { | |
| return currentTime( ); | |
| } | |
| private void printHoverLabels( List<TimeStamp> tickTimes, Axis1D axis, TimeStampFormat format, TimeStructFactory factory, double jTimeText, int width, int height ) | |
| { | |
| // text heights vary slightly, making the labels appear unevenly spaced in height | |
| // just use the height of a fixed sample character | |
| Rectangle2D fixedBounds = textRenderer.getBounds( "M" ); | |
| double textHeight = fixedBounds.getHeight( ); | |
| // Date labels | |
| List<TimeStruct> timeStructs = handler.timeStructs( axis, tickTimes, factory ); | |
| for ( TimeStruct time : timeStructs ) | |
| { | |
| String text = time.textCenter.toString( format ); | |
| Rectangle2D textBounds = textRenderer.getBounds( text ); | |
| double textWidth = textBounds.getWidth( ); | |
| int iMin = axis.valueToScreenPixel( fromTimeStamp( time.start ) ); | |
| int iMax = ( int ) Math.floor( axis.valueToScreenPixel( fromTimeStamp( time.end ) ) - textWidth ); | |
| int iApprox = ( int ) Math.round( axis.valueToScreenPixel( fromTimeStamp( time.textCenter ) ) - 0.5 * textWidth ); | |
| int i = Math.max( iMin, Math.min( iMax, iApprox ) ); | |
| if ( i < 0 || i + textWidth > width ) continue; | |
| int j = ( int ) Math.floor( jTimeText - textHeight - hoverLabelOffset ); | |
| textRenderer.draw( text, i, j ); | |
| } | |
| } | |
| private double printTickLabels( List<TimeStamp> tickTimes, Axis1D axis, TimeStampFormat format, int width, int height ) | |
| { | |
| // text heights vary slightly, making the labels appear unevenly spaced in height | |
| // just use the height of a fixed sample character | |
| Rectangle2D fixedBounds = textRenderer.getBounds( "M" ); | |
| double textHeight = fixedBounds.getHeight( ); | |
| // Time labels | |
| int jTimeText = Integer.MAX_VALUE; | |
| for ( TimeStamp t : tickTimes ) | |
| { | |
| String string = t.toString( format ); | |
| Rectangle2D textBounds = textRenderer.getBounds( string ); | |
| double textWidth = textBounds.getWidth( ); | |
| int i = ( int ) Math.round( axis.valueToScreenPixel( fromTimeStamp( t ) ) - 0.5 * textWidth ); | |
| if ( i < 0 || i + textWidth > width ) continue; | |
| int j = ( int ) Math.round( height - tickLineLength - textHeight ); | |
| jTimeText = Math.min( jTimeText, j ); | |
| textRenderer.draw( string, i, j ); | |
| } | |
| return jTimeText; | |
| } | |
| private void drawCurrentTimeTick( GL2 gl, Axis1D axis, int width, int height ) | |
| { | |
| int iTick = axis.valueToScreenPixel( fromTimeStamp( getCurrentTime( ) ) ); | |
| gl.glColor4fv( currentTimeTickColor, 0 ); | |
| gl.glLineWidth( currentTimeLineThickness ); | |
| gl.glBegin( GL2.GL_LINES ); | |
| gl.glVertex2d( iTick, height ); | |
| gl.glVertex2d( iTick, 0 ); | |
| gl.glEnd( ); | |
| String text = "NOW"; | |
| GlimpseColor.setColor( textRenderer, currentTimeTextColor ); | |
| textRenderer.beginRendering( width, height ); | |
| try | |
| { | |
| textRenderer.draw( text, iTick + 3, 0 + 3 ); | |
| } | |
| finally | |
| { | |
| textRenderer.endRendering( ); | |
| } | |
| } | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment