/****************************************************************************** * Copyright (c) 2010-2013, Linagora * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.common.internal.provisional.ui; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; /** * A tool tip implemented with a shell and intended for fixed locations. * @author Vincent Zurczak - EBM WebSourcing */ public abstract class FixedShellTooltip implements ControlListener { private final Shell shell; private final Control controlToFollow; private final boolean right; private final int topMargin; private final AtomicBoolean shown = new AtomicBoolean( false ); /** * Constructor. * @param controlToFollow the control to which this shell will be stuck to * @param right true if the tool tip should be placed on the right, false to put it on the left * @param topMargin the margin between the top of the tool tip and the top of the control */ public FixedShellTooltip( Control controlToFollow, boolean right, int topMargin ) { this.controlToFollow = controlToFollow; this.topMargin = topMargin; this.right = right; this.shell = new Shell( controlToFollow.getShell(), SWT.TOOL ); populateTooltip( this.shell ); this.shell.pack(); controlToFollow.addControlListener( this ); controlMoved( null ); } /** * Populates the tool tip. * @param parent */ public abstract void populateTooltip( Composite parent ); /** * Shows the tool tip (with a small delay). */ public void show() { this.shown.set( true ); this.shell.getDisplay().asyncExec( new Runnable() { @Override public void run() { try { Thread.sleep( 1000 ); } catch( InterruptedException e ) { // nothing } if( FixedShellTooltip.this.shown.get()) FixedShellTooltip.this.shell.setVisible( true ); } }); } /** * Hides the tool tip. */ public void hide() { this.shown.set( false ); this.shell.setVisible( false ); } /* * (non-Jsdoc) * @see org.eclipse.swt.events.ControlListener * #controlResized(org.eclipse.swt.events.ControlEvent) */ @Override public void controlResized( ControlEvent e ) { Rectangle rect = this.controlToFollow.getBounds(); if( this.right ) FixedShellTooltip.this.shell.setLocation( rect.x + rect.width, rect.y + this.topMargin ); else FixedShellTooltip.this.shell.setLocation( rect.x - this.shell.getSize().x, rect.y + this.topMargin ); } /* * (non-Jsdoc) * @see org.eclipse.swt.events.ControlListener * #controlMoved(org.eclipse.swt.events.ControlEvent) */ @Override public void controlMoved( ControlEvent e ) { Rectangle rect = this.controlToFollow.getBounds(); if( this.right ) FixedShellTooltip.this.shell.setLocation( rect.x + rect.width, rect.y + this.topMargin ); else FixedShellTooltip.this.shell.setLocation( rect.x - this.shell.getSize().x, rect.y + this.topMargin ); } /** * Disposes the created resources. * <p> * Sub-classes that override this method should call super.dispose() at the end. * </p> */ public void dispose() { if( ! this.controlToFollow.isDisposed()) this.controlToFollow.removeControlListener( this ); if( ! this.shell.isDisposed()) { this.shell.close(); this.shell.dispose(); } } }