blob: fede502b4833f39e1760ac39a797867e5cbadc70 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 Exyte
*
* 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:
* Yuri Strot - initial API and Implementation
*******************************************************************************/
package org.eclipse.ui.glance.controls.items;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.ui.glance.sources.BaseTextSource;
import org.eclipse.ui.glance.sources.ColorManager;
import org.eclipse.ui.glance.sources.ITextBlock;
import org.eclipse.ui.glance.sources.ITextSourceListener;
import org.eclipse.ui.glance.sources.Match;
import org.eclipse.ui.glance.sources.SourceSelection;
/**
* @author Yuri Strot
*
*/
public abstract class ItemSource extends BaseTextSource implements SelectionListener {
protected ItemDecorator decorator;
protected Composite composite;
public ItemSource(Composite composite) {
decorator = new ItemDecorator(composite, getItemProvider());
this.composite = composite;
}
/**
* @return the composite
*/
public Composite getControl() {
return composite;
}
protected abstract ItemProvider getItemProvider();
protected abstract void collectCells(List<ItemCell> cells);
public List<ItemCell> getCells() {
List<ItemCell> cells = decorator.getCells();
if (cells == null) {
cells = new ArrayList<ItemCell>();
collectCells(cells);
decorator.setCells(cells);
}
return cells;
}
public ITextBlock[] getBlocks() {
return getCells().toArray(new ITextBlock[getCells().size()]);
}
public Font getFont() {
return composite.getFont();
}
public void select(Match match) {
if (match != null) {
Item item = getCell(match).getItem();
getItemProvider().show(item);
getItemProvider().select(item);
}
setMatch(match);
}
public void dispose() {
if (selection != null) {
getItemProvider().select(getCell(selection).getItem());
}
decorator.dispose();
}
public boolean isDisposed() {
return decorator.isDisposed();
}
public void widgetDefaultSelected(SelectionEvent e) {
fireSelectionChanged();
}
public void widgetSelected(SelectionEvent e) {
fireSelectionChanged();
}
protected void fireSelectionChanged() {
SourceSelection selection = getSelection();
ITextSourceListener[] listeners = decorator.getListeners();
for (ITextSourceListener listener : listeners) {
listener.selectionChanged(selection);
}
}
public void show(Match[] matches) {
setMatches(matches);
}
public void removeTextSourceListener(ITextSourceListener listener) {
decorator.removeTextSourceListener(listener);
}
public void addTextSourceListener(ITextSourceListener listener) {
decorator.addTextSourceListener(listener);
}
public void setMatch(Match match) {
ItemCell cell1 = null, cell2 = null;
if (selection != null) {
cell1 = getCell(selection);
selection = null;
updateCell(cell1);
}
selection = match;
if (selection != null) {
cell2 = getCell(selection);
updateCell(cell2);
}
if (cell1 != null)
decorator.redraw(cell1);
if (cell2 != null && cell2 != cell1)
decorator.redraw(cell2);
}
public void setMatches(Match[] matches) {
cellToMatches = new HashMap<ItemCell, List<Match>>();
for (Match match : matches) {
ItemCell cell = getCell(match);
List<Match> list = cellToMatches.get(cell);
if (list == null) {
list = new ArrayList<Match>();
cellToMatches.put(cell, list);
}
list.add(match);
}
decorator.clearStyles();
for (ItemCell cell : cellToMatches.keySet()) {
updateCell(cell);
}
decorator.redraw();
}
protected void updateCell(ItemCell cell) {
List<StyleRange> list = new ArrayList<StyleRange>();
boolean selectionFound = false;
if (cellToMatches != null) {
List<Match> matches = cellToMatches.get(cell);
if (matches != null) {
for (Match match : matches) {
boolean sel = match.equals(selection);
selectionFound = selectionFound | sel;
StyleRange range = createRange(match, sel);
list.add(range);
}
}
}
if (!selectionFound && selection != null) {
ItemCell selCell = (ItemCell) selection.getBlock();
if (selCell.equals(cell)) {
list.add(createRange(selection, true));
}
}
StyleRange[] ranges = list.toArray(new StyleRange[list.size()]);
decorator.setStyles(cell, ranges);
}
private StyleRange createRange(Match match, boolean selection) {
Display display = composite.getDisplay();
Color fgColor, bgColor;
if (selection) {
// Lighten to avoid search selection on system selection
fgColor = ColorManager.lighten(display.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT), 50);
bgColor = ColorManager.getInstance().getSelectedBackgroundColor();
} else {
// To avoid white text on light-green background
fgColor = display.getSystemColor(SWT.COLOR_BLACK);
bgColor = ColorManager.getInstance().getBackgroundColor();
}
return new StyleRange(match.getOffset(), match.getLength(), fgColor, bgColor);
}
protected ItemCell getCell(Match match) {
return (ItemCell) match.getBlock();
}
private Match selection;
private Map<ItemCell, List<Match>> cellToMatches;
}