/** * */ package com.xored.glance.ui.utils; import com.xored.glance.ui.sources.ITextBlock; import com.xored.glance.ui.sources.ITextSource; import com.xored.glance.ui.sources.ITextSourceListener; import com.xored.glance.ui.sources.Match; import com.xored.glance.ui.sources.SourceSelection; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ListenerList; import org.eclipse.swt.widgets.Control; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Yuri Strot */ public class UITextSource implements ITextSource, ITextSourceListener { private SourceSelection selection; private Map<ITextBlock, UITextBlock> blockToBlock; private final ListenerList listeners; private List<UITextBlock> blocks; private final ITextSource source; private final Control control; 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 com.xored.glance.ui.sources.ITextSource#addTextSourceListener(com.xored * .glance.ui.sources.ITextSourceListener) */ @Override public void addTextSourceListener(final ITextSourceListener listener) { listeners.add(listener); } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSourceListener#blocksChanged(com.xored * .glance.ui.sources.ITextBlock[], com.xored.glance.ui.sources.ITextBlock[]) */ @Override 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); } } @Override 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(); } @Override public void dispose() { synchronized (blocks) { for (final UITextBlock block : blocks) { block.dispose(); } } source.removeTextSourceListener(this); source.dispose(); } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#getBlocks() */ @Override public ITextBlock[] getBlocks() { return blocks.toArray(new ITextBlock[blocks.size()]); } public Control getControl() { return control; } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#getSelection() */ @Override public SourceSelection getSelection() { return selection; } @Override public void index(final IProgressMonitor monitor) { source.index(monitor); } @Override public void init() { if (source != null) { source.init(); } } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#isDisposed() */ @Override public boolean isDisposed() { return source.isDisposed(); } @Override public boolean isIndexRequired() { return source.isIndexRequired(); } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#removeTextSourceListener(com. * xored.glance.ui.sources.ITextSourceListener) */ @Override public void removeTextSourceListener(final ITextSourceListener listener) { listeners.remove(listener); } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#select(com.xored.glance.ui.sources .Match) */ @Override public void select(final Match match) { UIUtils.asyncExec(control, new Runnable() { @Override 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 com.xored.glance.ui.sources.ITextSourceListener#selectionChanged(com. * xored.glance.ui.sources.SourceSelection) */ @Override 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); } } /* * (non-Javadoc) * * @see com.xored.glance.ui.sources.ITextSource#show(com.xored.glance.ui.sources .Match[]) */ @Override public void show(final Match[] matches) { UIUtils.asyncExec(control, new Runnable() { @Override 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); } } }); } @Override public void updateSourceSelection() { updateSelection(); } 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; } }