Skip to content

Instantly share code, notes, and snippets.

@ulmangt
Created March 21, 2012 16:56
Show Gist options
  • Save ulmangt/2149503 to your computer and use it in GitHub Desktop.
Save ulmangt/2149503 to your computer and use it in GitHub Desktop.
JFace ToolTip Example
/*
* Copyright (c) 2012, Metron, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Metron, Inc. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL METRON, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.metsci.plus.ui.experimental;
import static com.metsci.glimpse.gl.util.GLPBufferUtils.createPixelBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.media.opengl.GL;
import javax.media.opengl.GLContext;
import org.eclipse.jface.window.DefaultToolTip;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import com.metsci.glimpse.axis.Axis1D;
import com.metsci.glimpse.context.GlimpseBounds;
import com.metsci.glimpse.event.mouse.GlimpseMouseEvent;
import com.metsci.glimpse.event.mouse.GlimpseMouseMotionListener;
import com.metsci.glimpse.gl.Jogular;
import com.metsci.glimpse.layout.GlimpseLayout;
import com.metsci.glimpse.painter.base.GlimpseDataPainter1D;
import com.metsci.glimpse.plot.StackedPlot2D.Orientation;
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.repaint.RepaintManager;
import com.metsci.glimpse.swt.canvas.SwtGlimpseCanvas;
import com.metsci.glimpse.swt.misc.SwtLookAndFeel;
import com.metsci.glimpse.util.units.time.Time;
import com.metsci.glimpse.util.units.time.TimeStamp;
// see: http://tom-eclipse-dev.blogspot.com/2006/11/are-os-tooltips-not-flexible-enough.html
// see: http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fjface%2Fwindow%2FDefaultToolTip.html
// for information on JFace ToolTips
public class ToolTipExample
{
private static final Logger logger = Logger.getLogger( ToolTipExample.class.getSimpleName( ) );
public static GlimpseLayout getLayout( final SwtGlimpseCanvas canvas )
{
// create a timeline with plot areas arranged in a vertical line
StackedTimePlot2D plot = new StackedTimePlot2D( Orientation.VERTICAL, new Epoch( TimeStamp.currentTime( ) ) );
// calculate some TimeStamps representing the selected time range and initial extents of the timeline
final Epoch epoch = plot.getEpoch( );
TimeStamp selectionMaxTime = epoch.getTimeStamp( );
TimeStamp selectionMinTime = selectionMaxTime.subtract( Time.fromHours( 3 ) );
TimeStamp axisMaxTime = selectionMaxTime.add( Time.fromHours( 1 ) );
TimeStamp axisMinTime = selectionMaxTime.subtract( Time.fromHours( 20 ) );
// add some times to draw lines at
final List<TimeStamp> timeList = new ArrayList<TimeStamp>( );
timeList.add( selectionMaxTime.subtract( Time.fromHours( 2 ) ) );
timeList.add( selectionMaxTime.subtract( Time.fromHours( 2.3 ) ) );
timeList.add( selectionMaxTime.subtract( Time.fromHours( 2.4 ) ) );
timeList.add( selectionMaxTime.subtract( Time.fromHours( 4 ) ) );
// set the selected time range
plot.setTimeSelection( selectionMinTime, selectionMaxTime );
// set the overall bounds of the timeline
plot.setTimeAxisBounds( axisMinTime, axisMaxTime );
// create two plots (which by default will appear to the right of the timeline)
// the returned ChartLayoutInfo reference can be used to add GlimpsePainters to
// the plot area or customize its coloring and appearance
plot.createTimePlot( "plot-1-id" );
plot.createTimePlot( "plot-2-id" );
plot.createTimePlot( "plot-3-id" );
plot.getOverlayLayout( ).addPainter( new DataIndicatorLinePainter( epoch, timeList ) );
plot.getOverlayLayout( ).addGlimpseMouseMotionListener( new GlimpseMouseMotionListener( )
{
private final long selectionTolerancePixels = 10;
private ToolTip tooltip;
private TimeStamp selectedTime;
@Override
public void mouseMoved( GlimpseMouseEvent e )
{
// get the TimeStamp representing the current mouse position
double mouseValue = e.getAxis1D( ).screenPixelToValue( e.getX( ) );
TimeStamp mouseTime = epoch.toTimeStamp( mouseValue );
// get the TimeStamps corresponding to 10 pixels to the left and right of the mouse position
double selectionTolerance = selectionTolerancePixels / e.getAxis1D( ).getPixelsPerValue( );
TimeStamp maxTime = mouseTime.add( selectionTolerance );
TimeStamp minTime = mouseTime.subtract( selectionTolerance );
TimeStamp newSelectedTime = null;
// see if any of the data times fall within the window calculated above
for ( TimeStamp time : timeList )
{
if ( time.isAfter( minTime ) && time.isBefore( maxTime ) )
{
newSelectedTime = time;
}
}
// if we didn't find data near the mouse
// dispose of any existing tooltip and return
if ( newSelectedTime == null )
{
if ( tooltip != null )
{
tooltip.hide( );
tooltip = null;
}
selectedTime = null;
return;
}
// if the data near the mouse hasn't changed, just return
if ( newSelectedTime.equals( selectedTime ) ) return;
selectedTime = newSelectedTime;
// there is an existing tooltip, dispose of it
if ( tooltip != null ) tooltip.hide( );
// get the pixel coordinate of the data time
final int dataPixelX = e.getAxis1D( ).valueToScreenPixel( ( epoch.fromTimeStamp( selectedTime ) ) );
// the tooltip is hidden when the mouse moves over it and I haven't figured out how to disable this
// without the 10 pixel downward shift, the tooltip appears right under the mouse and is hidden immediately
final int dataPixelY = e.getY( ) + 10;
// create a new tool tip
tooltip = new DefaultToolTip( canvas, SWT.NONE, true )
{
@Override
public String getText( Event event )
{
return "Data Time: " + selectedTime;
}
};
// show the tooltip at the specified location
tooltip.show( new Point( dataPixelX, dataPixelY ) );
logger.info( "Data Time: " + selectedTime );
}
} );
return plot;
}
// a simple painter to draw lines at the provided data values
public static class DataIndicatorLinePainter extends GlimpseDataPainter1D
{
private double[] dataValues;
private float[] lineColor;
public DataIndicatorLinePainter( Epoch epoch, List<TimeStamp> dataTimes )
{
// convert the absolute timestamps into relative time axis coordinates
this.dataValues = new double[dataTimes.size( )];
for ( int i = 0; i < dataTimes.size( ); i++ )
{
this.dataValues[i] = epoch.fromTimeStamp( dataTimes.get( i ) );
}
this.lineColor = GlimpseColor.fromColorRgba( 0, 139, 139, 200 );
}
@Override
public void paintTo( GL gl, GlimpseBounds bounds, Axis1D axis )
{
int height = bounds.getHeight( );
// set line color and width
gl.glColor4fv( lineColor, 0 );
gl.glLineWidth( 1.8f );
// draw a line at each time from the top of the layout bounds to the bottom
gl.glBegin( GL.GL_LINES );
try
{
for ( double value : dataValues )
{
gl.glVertex2d( value, 0 );
gl.glVertex2d( value, height );
}
}
finally
{
gl.glEnd( );
}
}
}
// SWT boilerplate
public static void main( String[] args )
{
Jogular.initJogl( );
GLContext context = createPixelBuffer( 1, 1 ).getContext( );
Display display = new Display( );
Shell shell = new Shell( display );
shell.setText( "Glimpse Example (SWT)" );
shell.setLayout( new FillLayout( ) );
SwtGlimpseCanvas canvas = new SwtGlimpseCanvas( shell, context, SWT.NO_BACKGROUND );
canvas.addLayout( getLayout( canvas ) );
canvas.setLookAndFeel( new SwtLookAndFeel( ) );
RepaintManager.newRepaintManager( canvas );
shell.setSize( 800, 800 );
shell.setLocation( 0, 0 );
shell.open( );
shell.moveAbove( null );
while ( !shell.isDisposed( ) )
if ( !display.readAndDispatch( ) ) display.sleep( );
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment