/*******************************************************************************
* Copyright (c) 2015 Fabio Zadrozny 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:
* Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.ui.internal.css.swt.dom;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Scrollable;
/**
* Abstract class for dealing with an SWT.EraseItem event which customizes the
* selection color.
*/
public abstract class AbstractControlSelectionEraseListener implements Listener {
@Override
public void handleEvent(Event event) {
Scrollable control = (Scrollable) event.widget;
int columnCount = getNumberOfColumns(control);
boolean selected = (event.detail & SWT.SELECTED) != 0;
boolean hot = (event.detail & SWT.HOT) != 0;
// If we're painting the selection we also deal with hotness to be
// consistent (i.e.: hotness is a 'selection preview on hover').
event.detail &= ~SWT.HOT;
if (selected || hot) {
GC gc = event.gc;
Rectangle area = control.getClientArea();
// Handling hotness with more than one column doesn't
// work well because we'd have to change the clipping
// for all of that (which isn't really possible)...
boolean handlingOnlyHot = !selected && hot;
if (handlingOnlyHot) {
if (columnCount > 1) {
return;
}
}
String dataBackgroundKey;
String dataBorderKey;
if (handlingOnlyHot) {
dataBackgroundKey = ControlSelectedColorCustomization.HOT_BACKGROUND_COLOR;
dataBorderKey = ControlSelectedColorCustomization.HOT_BORDER_COLOR;
} else {
dataBackgroundKey = ControlSelectedColorCustomization.SELECTION_BACKGROUND_COLOR;
dataBorderKey = ControlSelectedColorCustomization.SELECTION_BORDER_COLOR;
}
Object dataBackground = control.getData(dataBackgroundKey);
Object dataBorder = control.getData(dataBorderKey);
Object dataSelectionForeground = control
.getData(ControlSelectedColorCustomization.SELECTION_FOREGROUND_COLOR);
Color background = null;
if ((dataBackground instanceof Color)) {
background = (Color) dataBackground;
if (background.isDisposed()) {
return;
}
}
Color border = null;
if ((dataBorder instanceof Color)) {
border = (Color) dataBorder;
if (border.isDisposed()) {
return;
}
}
Color selectionForeground = null;
if ((dataSelectionForeground instanceof Color)) {
selectionForeground = (Color) dataSelectionForeground;
} else {
// Default is the control foreground color.
selectionForeground = control.getForeground();
}
if (selectionForeground.isDisposed()) {
return;
}
if (background == null && border == null) {
// Nothing to draw
return;
}
// Update clip to cover the whole column.
int width = area.width;
if (event.index == columnCount - 1 || columnCount == 0) {
// i.e.: we only need to fix this for the last column
// or if the tree/table reports having no columns (which
// means single column... really weird hum?)
if (width > 0) {
Region region = new Region();
gc.getClipping(region);
region.add(event.x, event.y, width, event.height);
gc.setClipping(region);
region.dispose();
}
}
if (background != null) {
Color oldbackground = gc.getBackground();
gc.setBackground(background);
try {
gc.fillRectangle(0, area.y, area.width + 2, area.height);
} finally {
gc.setBackground(oldbackground);
}
}
if (border != null) {
gc.setForeground(border);
gc.drawRectangle(0, event.y, width - 1, event.height - 1);
}
// Restore the foreground for proper drawing later on.
// This should be the color that SWT uses to draw the
// foreground later on!
gc.setForeground(selectionForeground);
// we just painted the background...
event.detail &= ~SWT.BACKGROUND;
fixEventDetail(control, event);
}
}
/**
* Subclasses should override to fix the event.detail after the selection
* event was handled.
*
* @param control
* the control which had the erase event.
* @param event
* the event to have the details fixed.
*/
protected abstract void fixEventDetail(Control control, Event event);
/**
* @param control
* @return the number of columns from the control
*/
protected abstract int getNumberOfColumns(Control control);
}