blob: df2b0cab6f163f683c9c6992dc28c0100fe3391a [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.utils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.glance.sources.ITextBlock;
import org.eclipse.ui.glance.sources.ITextSource;
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 class UITextSource implements ITextSource, ITextSourceListener {
public UITextSource(final ITextSource source, final Control control) {
this.source = source;
this.control = control;
blocks = new ArrayList<UITextBlock>();
blockToBlock = new HashMap<ITextBlock, UITextBlock>();
listeners = new ListenerList();
source.addTextSourceListener(this);
addBlocks(source.getBlocks());
updateSelection();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.glance.sources.ITextSource#getSelection()
*/
public SourceSelection getSelection() {
return selection;
}
public Control getControl() {
return control;
}
public boolean isIndexRequired() {
return source.isIndexRequired();
}
public void dispose() {
synchronized (blocks) {
for (final UITextBlock block : blocks) {
block.dispose();
}
}
source.removeTextSourceListener(this);
source.dispose();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.glance.sources.ITextSource#isDisposed()
*/
public boolean isDisposed() {
return source.isDisposed();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.glance.sources.ITextSource#getBlocks()
*/
public ITextBlock[] getBlocks() {
return blocks.toArray(new ITextBlock[blocks.size()]);
}
public void index(final IProgressMonitor monitor) {
source.index(monitor);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSource#select(org.eclipse.ui.glance.sources
* .Match)
*/
public void select(final Match match) {
UIUtils.asyncExec(control, new Runnable() {
public void run() {
if (!source.isDisposed()) {
if (match == null)
source.select(null);
else {
final UITextBlock block = (UITextBlock) match.getBlock();
source.select(new Match(block.getBlock(), match.getOffset(), match.getLength()));
}
}
}
});
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSource#show(org.eclipse.ui.glance.sources
* .Match[])
*/
public void show(final Match[] matches) {
UIUtils.asyncExec(control, new Runnable() {
public void run() {
if (!source.isDisposed()) {
final Match[] newMatches = new Match[matches.length];
for (int i = 0; i < matches.length; i++) {
final Match match = matches[i];
final UITextBlock block = (UITextBlock) match.getBlock();
newMatches[i] = new Match(block.getBlock(), match.getOffset(), match.getLength());
}
source.show(newMatches);
}
}
});
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSource#addTextSourceListener(org.eclipse.ui
* .glance.sources.ITextSourceListener)
*/
public void addTextSourceListener(final ITextSourceListener listener) {
listeners.add(listener);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSource#removeTextSourceListener(org.
* eclipse.ui.glance.sources.ITextSourceListener)
*/
public void removeTextSourceListener(final ITextSourceListener listener) {
listeners.remove(listener);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSourceListener#blocksChanged(org.eclipse.ui
* .glance.sources.ITextBlock[],
* org.eclipse.ui.glance.sources.ITextBlock[])
*/
public void blocksChanged(final ITextBlock[] removed, final ITextBlock[] added) {
final ITextBlock[] uiRemoved = removeBlocks(removed);
final ITextBlock[] uiAdded = addBlocks(added);
final Object[] objects = listeners.getListeners();
for (final Object object : objects) {
final ITextSourceListener listener = (ITextSourceListener) object;
listener.blocksChanged(uiRemoved, uiAdded);
}
}
public void blocksReplaced(final ITextBlock[] newBlocks) {
synchronized (this.blocks) {
for (final UITextBlock uiBlock : blockToBlock.values()) {
uiBlock.dispose();
}
blockToBlock = new HashMap<ITextBlock, UITextBlock>();
blocks = new ArrayList<UITextBlock>();
}
final ITextBlock[] uiAdded = addBlocks(newBlocks);
final Object[] objects = listeners.getListeners();
for (final Object object : objects) {
final ITextSourceListener listener = (ITextSourceListener) object;
listener.blocksReplaced(uiAdded);
}
selection = source.getSelection();
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.glance.sources.ITextSourceListener#selectionChanged(org.
* eclipse.ui.glance.sources.SourceSelection)
*/
public void selectionChanged(final SourceSelection selection) {
final SourceSelection newSelection = updateSelection();
final Object[] objects = listeners.getListeners();
for (final Object object : objects) {
final ITextSourceListener listener = (ITextSourceListener) object;
listener.selectionChanged(newSelection);
}
}
protected ITextBlock[] addBlocks(final ITextBlock[] blocks) {
synchronized (this.blocks) {
final ITextBlock[] added = new ITextBlock[blocks.length];
for (int i = 0; i < blocks.length; i++) {
final ITextBlock block = blocks[i];
final UITextBlock uiBlock = new UITextBlock(block);
added[i] = uiBlock;
this.blocks.add(uiBlock);
blockToBlock.put(block, uiBlock);
}
return added;
}
}
protected ITextBlock[] removeBlocks(final ITextBlock[] blocks) {
synchronized (this.blocks) {
final List<ITextBlock> removed = new ArrayList<ITextBlock>(blocks.length);
for (int i = 0; i < blocks.length; i++) {
final ITextBlock block = blocks[i];
final UITextBlock uiBlock = blockToBlock.remove(block);
if (uiBlock != null) {
removed.add(uiBlock);
this.blocks.remove(uiBlock);
uiBlock.dispose();
}
}
return removed.toArray(new ITextBlock[removed.size()]);
}
}
protected SourceSelection updateSelection() {
final SourceSelection sourceSelection = source.getSelection();
if (sourceSelection == null) {
selection = null;
} else {
selection = new SourceSelection(blockToBlock.get(sourceSelection.getBlock()),
sourceSelection.getOffset(), sourceSelection.getLength());
}
return selection;
}
public void init() {
if (source != null) {
source.init();
}
}
private SourceSelection selection;
private Map<ITextBlock, UITextBlock> blockToBlock;
private final ListenerList listeners;
private List<UITextBlock> blocks;
private final ITextSource source;
private final Control control;
}