/*******************************************************************************
* Copyright © 2008, 2013 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.ide.rui.visualeditor.internal.widget;
import java.util.List;
import org.eclipse.edt.ide.rui.visualeditor.internal.editor.EvConstants;
import org.eclipse.edt.ide.rui.visualeditor.internal.preferences.EvPreferences;
import org.eclipse.edt.ide.rui.visualeditor.internal.util.ColorUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
/**
* This is a singleton that draws all widget outlines.
* To use, set this class' bounds.
*/
public class WidgetPainter implements DisposeListener {
protected Color BLACK = null;
protected Color GRAY = null;
protected Color WHITE = null;
protected boolean _bDragging = false;
protected boolean _bFocus = false;
protected boolean _bMouseOver = false;
protected boolean _bOutline = false;
protected boolean _bPatternSelection = false;
protected boolean _bPatternSelectionWhite = false;
protected boolean _bSelected = false;
protected boolean _bIsContainer = false;
protected boolean _bIsSelectedWidget = false;
protected Color _colorSelected = null;
protected Color _colorLogicalArea = null;
protected Composite _compositeParent = null;
protected Rectangle _rectBounds = new Rectangle( 0, 0, 0, 0 );
protected Rectangle _rectDragging = new Rectangle( 0, 0, 0, 0 );
protected List _innerRectangles = null;
protected Point _mouseDownPoint = null;
/**
*
*/
public WidgetPainter( Composite compositeParent ) {
_compositeParent = compositeParent;
_compositeParent.addDisposeListener( this );
Display display = compositeParent.getDisplay();
BLACK = display.getSystemColor( SWT.COLOR_BLACK );
GRAY = display.getSystemColor( SWT.COLOR_GRAY );
WHITE = display.getSystemColor( SWT.COLOR_WHITE );
_colorLogicalArea = new Color( display, 190, 190, 190 );
updateColors();
}
public void setMouseDownPoint(Point mouseDownPoint){
_mouseDownPoint = mouseDownPoint;
}
public void setIsSelectedWidget(boolean isSelectedWidget){
_bIsSelectedWidget = isSelectedWidget;
}
/**
* Returns the bounds of the widget.
*/
protected Rectangle getBounds() {
return new Rectangle( _rectBounds.x, _rectBounds.y, _rectBounds.width, _rectBounds.height );
}
/**
* Paints the widget's corners.
*/
protected void paintCorners( GC gc ) {
Rectangle rectBounds = getBounds();
// Compute vertical and horizontal line lengths
//---------------------------------------------
final int iS = 4; // Short
final int iL = 6; // Long
final int iOverS = 5; // Short mouse over
final int iOverL = 7; // Long mouse over
final int iSelS = 6; // Short selected
final int iSelL = 8; // Long selected
int iLengthX = 0;
int iLengthY = 0;
boolean bWidthLongerThanHeight = rectBounds.width > rectBounds.height;
if( _bSelected ) {
iLengthX = bWidthLongerThanHeight ? iSelL : iSelS;
iLengthY = bWidthLongerThanHeight ? iSelS : iSelL;
}
else if( _bMouseOver ){
iLengthX = bWidthLongerThanHeight ? iOverL : iOverS;
iLengthY = bWidthLongerThanHeight ? iOverS : iOverL;
}
else{
iLengthX = bWidthLongerThanHeight ? iL : iS;
iLengthY = bWidthLongerThanHeight ? iS : iL;
}
// Ensure lines are not longer than the widget
//--------------------------------------------
iLengthX = Math.min( iLengthX, rectBounds.width / 3 );
iLengthY = Math.min( iLengthY, rectBounds.height / 3 );
int iWidth = 2;
if( _bSelected )
iWidth = 3;
else if( _bMouseOver )
iWidth = 3;
Color color = BLACK;
for( int i = 0; i < iWidth; ++i ) {
if( i == 1 )
color = GRAY;
else if( i == 2 )
color = _bSelected ? BLACK : GRAY;
gc.setForeground( color );
// Top left
//---------
gc.drawLine( rectBounds.x, rectBounds.y, rectBounds.x + iLengthX, rectBounds.y );
gc.drawLine( rectBounds.x, rectBounds.y, rectBounds.x, rectBounds.y + iLengthY );
// Top right
//----------
gc.drawLine( rectBounds.x + rectBounds.width - 1 - iLengthX, rectBounds.y, rectBounds.x + rectBounds.width - 1, rectBounds.y );
gc.drawLine( rectBounds.x + rectBounds.width - 1, rectBounds.y, rectBounds.x + rectBounds.width - 1, rectBounds.y + iLengthY );
// Bottom left
//------------
gc.drawLine( rectBounds.x, rectBounds.y + rectBounds.height - 1, rectBounds.x + iLengthX, rectBounds.y + rectBounds.height - 1 );
gc.drawLine( rectBounds.x, rectBounds.y + rectBounds.height - 1 - iLengthY, rectBounds.x, rectBounds.y + rectBounds.height - 1 );
// Bottom right
//-------------
gc.drawLine( rectBounds.x + rectBounds.width - 1 - iLengthX, rectBounds.y + rectBounds.height - 1, rectBounds.x + rectBounds.width - 1, rectBounds.y + rectBounds.height - 1 );
gc.drawLine( rectBounds.x + rectBounds.width - 1, rectBounds.y + rectBounds.height - 1 - iLengthY, rectBounds.x + rectBounds.width - 1, rectBounds.y + rectBounds.height - 1 );
rectBounds.x++;
rectBounds.y++;
rectBounds.width -= 2;
rectBounds.height -= 2;
iLengthX--;
iLengthY--;
}
}
/**
* Draws a dashed rectangle
*/
protected void paintRectangleDotted( GC gc, int iWidth, Color color, Rectangle rectB ) {
Rectangle rectBounds = new Rectangle( rectB.x, rectB.y, rectB.width, rectB.height );
rectBounds.width--;
rectBounds.height--;
gc.setForeground( color );
gc.setLineWidth( iWidth );
gc.setLineStyle( SWT.LINE_DOT );
gc.drawRectangle( rectBounds );
gc.setLineStyle( SWT.LINE_SOLID );
}
/**
*
*/
protected void paintRectangleSelected( GC gc, Rectangle rectBounds ) {
// Solid line in black or white
//-----------------------------
gc.setLineStyle( SWT.LINE_SOLID );
gc.setLineWidth( 1 );
// No pattern, solid color
//------------------------
if( _bPatternSelection == false ){
gc.setForeground( _colorSelected );
Rectangle rect = new Rectangle( rectBounds.x, rectBounds.y, rectBounds.width - 1, rectBounds.height - 1 );
gc.drawRectangle( rect );
rect = new Rectangle( rectBounds.x + 1, rectBounds.y + 1, rectBounds.width - 3, rectBounds.height - 3 );
gc.drawRectangle( rect );
return;
}
// Patterned lines
//----------------
if( _bFocus && _bDragging == false ) {
// Solid line in black or white
//-----------------------------
gc.setLineStyle( SWT.LINE_CUSTOM );
gc.setLineDash( new int[]{4} );
gc.setLineWidth( 2 );
Rectangle rect = new Rectangle( rectBounds.x + 1, rectBounds.y + 1, rectBounds.width - 2, rectBounds.height - 2 );
gc.setForeground( _colorSelected );
gc.drawRectangle( rect );
gc.setLineDash( new int[] {} );
}
}
/**
*
*/
protected void paintRectangleSolid( GC gc, int iWidth, Color color, Rectangle rectB ) {
gc.setLineStyle( SWT.LINE_SOLID );
gc.setLineWidth( 1 );
Rectangle rectBounds = new Rectangle( rectB.x, rectB.y, rectB.width, rectB.height );
rectBounds.width--;
rectBounds.height--;
gc.setForeground( color );
for( int i = 0; i < iWidth; ++i ) {
gc.drawRectangle( rectBounds );
rectBounds.x++;
rectBounds.y++;
rectBounds.width -= 2;
rectBounds.height -= 2;
}
}
/**
*
*/
public void paintWidget( GC gc ) {
Rectangle rectBounds = getBounds();
if( rectBounds.isEmpty() )
return;
boolean selectInnerRec = false;
// inner (for example: cell of GridLayout)
if ( _innerRectangles != null ) {
for ( int i = 0; i < _innerRectangles.size(); i ++ ) {
Rectangle rectangle = (Rectangle)_innerRectangles.get(i);
if(_mouseDownPoint != null && _bIsSelectedWidget && rectangle.contains(_mouseDownPoint)){
if( _bFocus ) {
paintRectangleSelected( gc, rectangle );
} else {
paintRectangleSolid( gc, 2, _colorSelected, rectangle );
Rectangle rectOffset2 = new Rectangle( rectangle.x + 2, rectangle.y + 2, rectangle.width - 4, rectangle.height - 4 );
paintRectangleSolid( gc, 1, _bPatternSelectionWhite ? WHITE : BLACK, rectOffset2 );
}
selectInnerRec = true;
} else {
paintRectangleDotted( gc, 1, _colorLogicalArea, rectangle );
}
}
}
// Selected
//---------
if( _bSelected == true ) {
// Selected with focus
//--------------------
if( _bFocus == true && _bDragging == false ){
if(!selectInnerRec){
paintRectangleSelected( gc, rectBounds );
}
}
// Selected, no focus
//-------------------
else{
if(!selectInnerRec){
paintRectangleSolid( gc, 2, _colorSelected, rectBounds );
Rectangle rectOffset2 = new Rectangle( rectBounds.x + 2, rectBounds.y + 2, rectBounds.width - 4, rectBounds.height - 4 );
paintRectangleSolid( gc, 1, _bPatternSelectionWhite ? WHITE : BLACK, rectOffset2 );
}
}
}
// Not selected
//-------------
else if( _bOutline == true || _bMouseOver == true )
paintRectangleSolid( gc, 2, GRAY, rectBounds );
if ( _bIsContainer ) {
paintCorners( gc );
}
}
/**
* Paints the dragging rectangle for a widget that is being dragged.
*/
public void paintWidgetDragging( GC gc ) {
paintRectangleDotted( gc, 2, _colorSelected, _rectDragging );
}
/**
*
*/
public void setBounds( Rectangle rectBounds ) {
_rectBounds.x = rectBounds.x;
_rectBounds.y = rectBounds.y;
_rectBounds.width = rectBounds.width;
_rectBounds.height = rectBounds.height;
}
/**
*
*/
public void setBoundsDragging( Rectangle rectDragging ) {
_rectDragging.x = rectDragging.x;
_rectDragging.y = rectDragging.y;
_rectDragging.width = rectDragging.width;
_rectDragging.height = rectDragging.height;
}
/**
*
*/
public void setDragging( boolean bDragging ) {
_bDragging = bDragging;
}
/**
*
*/
public void setIsContainer( boolean bIsContainer ) {
_bIsContainer = bIsContainer;
}
/**
*
*/
public void setDrawOutline( boolean bOutline ) {
_bOutline = bOutline;
}
/**
*
*/
public void setFocus( boolean bFocus ) {
_bFocus = bFocus;
}
/**
*
*/
public void setMouseOver( boolean bMouseOver ) {
_bMouseOver = bMouseOver;
}
/**
*
*/
public void setSelected( boolean bSelected ) {
_bSelected = bSelected;
}
/**
*
*/
public void setInnerRectangles( List innerRectangles ) {
_innerRectangles = innerRectangles;
}
/**
* Updates the selection color based on what is specified in the preferences.
*/
public void updateColors() {
// Obtain the color and pattern preferences
//-----------------------------------------
String strColorSelection = EvPreferences.getString( EvConstants.PREFERENCE_COLOR_SELECTION );
_bPatternSelection = EvPreferences.getBoolean( EvConstants.PREFERENCE_PATTERN_SELECTION );
// Convert from 255, 255, 255 to a color
//--------------------------------------
Color color = ColorUtil.getColorFromRGBString( Display.getCurrent(), strColorSelection );
if( color == null )
return;
// Dispose of any existing color
//------------------------------
if( _colorSelected != null && _colorSelected.isDisposed() == false )
_colorSelected.dispose();
// Establish the new color
//------------------------
_colorSelected = color;
// Determine if the selected pattern color is white or black
//----------------------------------------------------------
int iRed = _colorSelected.getRed();
int iGrn = _colorSelected.getGreen();
int iBlu = _colorSelected.getBlue();
double dLuminance = 0.30 * iRed + 0.59 * iGrn + 0.11 * iBlu;
_bPatternSelectionWhite = dLuminance < EvConstants.LUMINOSITY_WHITE_BLACK_BOUNDARY;
}
/**
* Declared in DisposeListener.
* Disposes of any colors that are not system colors.
*/
public void widgetDisposed( DisposeEvent e ) {
if( _colorSelected != null && _colorSelected.isDisposed() == false ) {
_colorSelected.dispose();
_colorSelected = null;
}
if( _colorLogicalArea != null && _colorLogicalArea.isDisposed() == false ) {
_colorLogicalArea.dispose();
_colorLogicalArea = null;
}
}
}