/******************************************************************************* * Copyright (c) 2007, 2009 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 * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation * - fix for bug 183850, 182652, 182800, 215069 * Innoopract - RAP adaption *******************************************************************************/ package org.eclipse.jface.viewers; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.widgets.*; /** * A concrete implementation of {@link FocusCellHighlighter} using by setting * the control into owner draw mode and highlighting the currently selected * cell. To make the use this class you should create the control with the * {@link SWT#FULL_SELECTION} bit set * * <p> * <strong>RAP specific:</strong> despite its name that was taken as-is from * JFace/RCP to ease single-sourcing, this class does not use custom drawing * to highlight the focused cell. * <br /> * The focused cell is displayed using the selection colors of the system. * </p> * * This class can be subclassed to configure how the coloring of the selected * cell. * * @since 1.2 * */ public class FocusCellOwnerDrawHighlighter extends FocusCellHighlighter { private final ColumnViewer viewer; /** * Create a new instance which can be passed to a * * @param viewer * the viewer */ public FocusCellOwnerDrawHighlighter(ColumnViewer viewer) { super(viewer); this.viewer = viewer; hookListener(viewer); viewer.getControl().setData( Table.HIDE_SELECTION, Boolean.TRUE ); } private void markFocusedCell(Event event, ViewerCell cell) { Color background = (cell.getControl().isFocusControl()) ? getSelectedCellBackgroundColor(cell) : getSelectedCellBackgroundColorNoFocus(cell); Color foreground = (cell.getControl().isFocusControl()) ? getSelectedCellForegroundColor(cell) : getSelectedCellForegroundColorNoFocus(cell); if (foreground != null || background != null || onlyTextHighlighting(cell)) { // GC gc = event.gc; if (background == null) { background = cell.getItem().getDisplay().getSystemColor( SWT.COLOR_LIST_SELECTION); } if (foreground == null) { foreground = cell.getItem().getDisplay().getSystemColor( SWT.COLOR_LIST_SELECTION_TEXT); } // gc.setBackground(background); // gc.setForeground(foreground); // // if (onlyTextHighlighting(cell)) { // Rectangle area = event.getBounds(); // Rectangle rect = cell.getTextBounds(); // if( rect != null ) { // area.x = rect.x; // } // gc.fillRectangle(area); // } else { // gc.fillRectangle(event.getBounds()); // } cell.setBackground( background ); cell.setForeground( foreground ); // event.detail &= ~SWT.SELECTED; } } private void removeSelectionInformation(Event event, ViewerCell cell) { // GC gc = event.gc; // gc.setBackground(cell.getViewerRow().getBackground( // cell.getColumnIndex())); Color tableBackground = cell.getControl().getBackground(); Color cellBackground = cell.getViewerRow().getBackground( cell.getColumnIndex() ); if( !cellBackground.equals( tableBackground ) ) { cell.setBackground( cellBackground ); } else { cell.setBackground( null ); } // gc.setForeground(cell.getViewerRow().getForeground( // cell.getColumnIndex())); Color tableForeground = cell.getControl().getForeground(); Color cellForeground = cell.getViewerRow().getForeground( cell.getColumnIndex() ); if( !cellForeground.equals( tableForeground ) ) { cell.setForeground( cellForeground ); } else { cell.setForeground( null ); } // gc.fillRectangle(cell.getBounds()); // event.detail &= ~SWT.SELECTED; } private void hookListener(final ColumnViewer viewer) { // // Listener listener = new Listener() { // // public void handleEvent(Event event) { //// if ((event.detail & SWT.SELECTED) > 0) { // ViewerCell focusCell = getFocusCell(); // ViewerRow row = viewer.getViewerRowFromItem(event.item); // // Assert // .isNotNull(row, // "Internal structure invalid. Item without associated row is not possible."); //$NON-NLS-1$ // //// ViewerCell cell = row.getCell(event.index); //// //// if (focusCell == null || !cell.equals(focusCell)) { //// removeSelectionInformation(event, cell); //// } else { //// markFocusedCell(event, cell); //// } // // focusCellChanged( focusCell ); // } // // }; //// viewer.getControl().addListener(SWT.EraseItem, listener); // viewer.getControl().addListener(SWT.KeyDown, listener); // viewer.getControl().addListener(SWT.MouseDown, listener); // [rst] We use a JFace SelectionChanged listener to keep track of // programmatic selection changes and handle MULTI correctly. // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=261647 viewer.addSelectionChangedListener( new ISelectionChangedListener() { private Widget[] oldSelection = getSelectedItems(); private ViewerCell oldFocusCell = getFocusCell(); public void selectionChanged( SelectionChangedEvent event ) { // erase old selection for( int i = 0; i < oldSelection.length; i++ ) { Widget item = oldSelection[ i ]; if( !item.isDisposed() ) { ViewerRow row = viewer.getViewerRowFromItem( item ); int count = row.getColumnCount(); for( int j = 0; j < count; j++ ) { ViewerCell cell = row.getCell( j ); removeSelectionInformation( null, cell ); } } } if( oldFocusCell != null ) { Widget item = oldFocusCell.getItem(); if( !item.isDisposed() ) { removeSelectionInformation( null, oldFocusCell ); } } // colorize new selection Widget[] selection = getSelectedItems(); ViewerCell focusCell = getFocusCell(); int index = 0; if( focusCell != null ) { index = focusCell.getColumnIndex(); } else if( oldFocusCell != null ) { index = oldFocusCell.getColumnIndex(); } for( int i = 0; i < selection.length; i++ ) { Widget item = selection[ i ]; ViewerRow row = viewer.getViewerRowFromItem( item ); ViewerCell cell = row.getCell( index ); markFocusedCell( null, cell ); } oldSelection = selection; oldFocusCell = focusCell; } }); } /** * The color to use when rendering the background of the selected cell when * the control has the input focus * * @param cell * the cell which is colored * @return the color or <code>null</code> to use the default */ protected Color getSelectedCellBackgroundColor(ViewerCell cell) { return null; } /** * The color to use when rendering the foreground (=text) of the selected * cell when the control has the input focus * * @param cell * the cell which is colored * @return the color or <code>null</code> to use the default */ protected Color getSelectedCellForegroundColor(ViewerCell cell) { return null; } /** * The color to use when rendering the foreground (=text) of the selected * cell when the control has <b>no</b> input focus * * @param cell * the cell which is colored * @return the color or <code>null</code> to use the same used when * control has focus */ protected Color getSelectedCellForegroundColorNoFocus(ViewerCell cell) { return null; } /** * The color to use when rendering the background of the selected cell when * the control has <b>no</b> input focus * * @param cell * the cell which is colored * @return the color or <code>null</code> to use the same used when * control has focus */ protected Color getSelectedCellBackgroundColorNoFocus(ViewerCell cell) { return null; } /** * Controls whether the whole cell or only the text-area is highlighted * * @param cell * the cell which is highlighted * @return <code>true</code> if only the text area should be highlighted */ protected boolean onlyTextHighlighting(ViewerCell cell) { // return false; return true; } protected void init() { ColumnViewerEditorActivationListener listener = new ColumnViewerEditorActivationListener() { public void afterEditorActivated( ColumnViewerEditorActivationEvent e ) { } public void afterEditorDeactivated( ColumnViewerEditorDeactivationEvent e ) { focusCellChanged( getFocusCell(), null ); } public void beforeEditorActivated( ColumnViewerEditorActivationEvent e ) { } public void beforeEditorDeactivated( ColumnViewerEditorDeactivationEvent e ) { } }; ColumnViewerEditor editor = viewer.getColumnViewerEditor(); editor.addEditorActivationListener( listener ); } protected void focusCellChanged(ViewerCell newCell, ViewerCell oldCell) { // super.focusCellChanged(newCell, oldCell); // // // Redraw new area // if (newCell != null) { // Rectangle rect = newCell.getBounds(); // int x = newCell.getColumnIndex() == 0 ? 0 : rect.x; // int width = newCell.getColumnIndex() == 0 ? rect.x + rect.width // : rect.width; // // 1 is a fix for Linux-GTK // newCell.getControl().redraw(x, rect.y - 1, width, rect.height + 1, // true); // } // // if (oldCell != null) { // Rectangle rect = oldCell.getBounds(); // int x = oldCell.getColumnIndex() == 0 ? 0 : rect.x; // int width = oldCell.getColumnIndex() == 0 ? rect.x + rect.width // : rect.width; // // 1 is a fix for Linux-GTK // oldCell.getControl().redraw(x, rect.y - 1, width, rect.height + 1, // true); // } if( oldCell != null ) { oldCell.setBackground( null ); oldCell.setForeground( null ); // [if] Fix for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=264226 // When selected item is deleted, the oldCell item and element are out of sync // viewer.updateItem( oldCell.getItem(), oldCell.getElement() ); } if( newCell != null && isItemSelected( newCell.getItem() ) ) { markFocusedCell( null, newCell ); } } // RAP [if] Helping methods private Widget[] getSelectedItems() { Control control = viewer.getControl(); Widget[] result = null; if( control instanceof Table ) { result = ( ( Table )control ).getSelection(); } else if( control instanceof Tree ) { result = ( ( Tree )control ).getSelection(); } return result; } private boolean isItemSelected( final Widget item ) { boolean result = false; Widget[] selection = getSelectedItems(); for( int i = 0; i < selection.length && !result; i++ ) { result = item == selection[ i ]; } return result; } // RAPEND }