Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: editor/tools/plugins/com.xored.glance.ui/src/com/xored/glance/internal/ui/search/SearchManager.java

Issue 17431004: New UI for Find command: find-as-you-type. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: editor/tools/plugins/com.xored.glance.ui/src/com/xored/glance/internal/ui/search/SearchManager.java
===================================================================
--- editor/tools/plugins/com.xored.glance.ui/src/com/xored/glance/internal/ui/search/SearchManager.java (revision 0)
+++ editor/tools/plugins/com.xored.glance.ui/src/com/xored/glance/internal/ui/search/SearchManager.java (revision 0)
@@ -0,0 +1,455 @@
+/*******************************************************************************
+ * Copyright (c) 2012 xored software, Inc. 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:
+ * xored software, Inc. - initial API and implementation (Yuri Strot)
+ ******************************************************************************/
+package com.xored.glance.internal.ui.search;
+
+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.swt.widgets.Control;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+import com.xored.glance.internal.ui.GlancePlugin;
+import com.xored.glance.internal.ui.panels.SearchPanelManager;
+import com.xored.glance.internal.ui.panels.SearchStatusLine;
+import com.xored.glance.internal.ui.preferences.IPreferenceConstants;
+import com.xored.glance.internal.ui.sources.ISourceProviderListener;
+import com.xored.glance.internal.ui.sources.TextSourceMaker;
+import com.xored.glance.internal.ui.sources.TextSourceManager;
+import com.xored.glance.ui.panels.ISearchPanel;
+import com.xored.glance.ui.panels.ISearchPanelListener;
+import com.xored.glance.ui.sources.ITextSource;
+import com.xored.glance.ui.sources.Match;
+import com.xored.glance.ui.sources.SourceSelection;
+import com.xored.glance.ui.utils.UITextSource;
+
+/**
+ * @author Yuri Strot
+ */
+public class SearchManager {
+
+ /** Searching from the current position */
+ public static final int FIND_HERE = 0;
+ /** Searching next occurrence of the string */
+ public static final int FIND_NEXT = 1;
+ /** Searching previous occurrence of the string */
+ public static final int FIND_PREVIOUS = 2;
+
+ public static SearchManager getIntance() {
+ if (manager == null) {
+ manager = new SearchManager();
+ }
+ return manager;
+ }
+
+ public boolean activate() {
+ final TextSourceMaker source = TextSourceManager.getInstance().getSource();
+ if (update(source, true)) {
+ forceFocus();
+ return true;
+ }
+ return false;
+ }
+
+ public void startup() {
+ PlatformUI.getWorkbench().addWindowListener(new IWindowListener() {
+ public void windowOpened(final IWorkbenchWindow window) {
+ setStatusLine(window, true);
+ }
+
+ public void windowDeactivated(final IWorkbenchWindow window) {
+ }
+
+ public void windowClosed(final IWorkbenchWindow window) {
+ }
+
+ public void windowActivated(final IWorkbenchWindow window) {
+ }
+ });
+ for (final IWorkbenchWindow window : PlatformUI.getWorkbench().getWorkbenchWindows()) {
+ setStatusLine(window, true);
+ }
+ }
+
+ public void setStatusLine(final IWorkbenchWindow window, final boolean open) {
+ final ISearchPanel panel = SearchStatusLine.getSearchLine(window);
+ if (!open) {
+ panel.closePanel();
+ return;
+ }
+ panels.add(panel);
+ final SearchPanelListener listener = new SearchPanelListener(panel);
+ panel.addPanelListener(listener);
+ panelToListener.put(panel, listener);
+ updateSourceListener();
+
+ final TextSourceMaker source = TextSourceManager.getInstance().getSource();
+ if (source != null && source.getControl() != null && panel.isApplicable(source.getControl())) {
+ this.panel = panel;
+ rule = panel.getRule();
+ if (setDescription(source))
+ updateEnabling();
+ }
+ }
+
+ public boolean isInWindow(final IWorkbenchWindow window) {
+ for (final ISearchPanel panel : panels) {
+ if (panel instanceof SearchStatusLine) {
+ final SearchStatusLine sl = ((SearchStatusLine) panel);
+ if (sl.getWindow() == window) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void findNext() {
+ if (panel != null) {
+ panel.findNext();
+ }
+ }
+
+ public void findPrevious() {
+ if (panel != null) {
+ panel.findPrevious();
+ }
+ }
+
+ public void clearHistory() {
+ if (panel != null) {
+ panel.clearHistory();
+ }
+ }
+
+ public void sourceFocus() {
+ ITextSource source = getSource();
+ if (source instanceof UITextSource) {
+ UITextSource uiTextSource = (UITextSource) source;
+ if (uiTextSource.getControl() != null) {
+ uiTextSource.getControl().setFocus();
+ }
+ }
+ }
+
+ public void close() {
+ if (panel != null) {
+ panel.closePanel();
+ }
+ }
+
+ public ITextSource getSource() {
+ return source;
+ }
+
+ private boolean update(final TextSourceMaker source, final boolean openNewPanel) {
+ updatePanel(source, openNewPanel);
+ if (panel != null) {
+ rule = panel.getRule();
+ updateSourceListener();
+ if (setDescription(source))
+ updateEnabling();
+ return true;
+ }
+ return false;
+ }
+
+ private void updatePanel(final TextSourceMaker source, final boolean openNewPanel) {
+ final Control control = source.getControl();
+ if (panel != null) {
+ if (panel.isApplicable(control))
+ return;
+ if (this.source != null) {
+ this.source.dispose();
+ this.source = null;
+ }
+ creator = null;
+ panel = null;
+ }
+ for (final ISearchPanel panel : panels) {
+ if (panel.isApplicable(control)) {
+ this.panel = panel;
+ break;
+ }
+ }
+ if (panel == null && openNewPanel) {
+ panel = SearchPanelManager.getInstance().getPanel(control);
+ if (panel != null) {
+ panels.add(panel);
+ final SearchPanelListener listener = new SearchPanelListener(panel);
+ panel.addPanelListener(listener);
+ panelToListener.put(panel, listener);
+ }
+ }
+ }
+
+ private void forceFocus() {
+ String text = "";
+ if (source != null) {
+ final SourceSelection selection = source.getSelection();
+ if (selection != null) {
+ text = selection.getBlock().getText();
+ final int offset = selection.getOffset();
+ final int length = selection.getLength();
+ if (offset + length <= text.length())
+ text = text.substring(offset, offset + length);
+ else
+ text = "";
+ }
+ }
+ panel.setFocus(text);
+ }
+
+ private void find(final SearchRule rule, final int type) {
+ this.type = type;
+ if (rule != null) {
+ final boolean textEquals = rule.isTextEquals(this.rule);
+ final boolean settingsEqual = rule.isSettingsEqual(this.rule);
+ if (textEquals) {
+ if (settingsEqual) {
+ updateSelection();
+ } else {
+ updateSearch(rule, false);
+ }
+ } else {
+ updateSearch(rule, true);
+ }
+ } else {
+ updateSearch(rule, false);
+ }
+ this.rule = rule;
+ }
+
+ protected void dispose(final ISearchPanel panel) {
+ panels.remove(panel);
+ final SearchPanelListener listener = panelToListener.remove(panel);
+ panel.removePanelListener(listener);
+ if (panel == this.panel) {
+ this.panel = null;
+ if (source != null) {
+ source.dispose();
+ source = null;
+ }
+ if (creator != null) {
+ final Control control = creator.getControl();
+ if (control != null && !control.isDisposed())
+ control.forceFocus();
+ creator = null;
+ }
+ rule = null;
+ }
+ if (panels.size() == 0) {
+ if (engine != null) {
+ engine.exit();
+ engine = null;
+ }
+ if (sourceListener != null) {
+ TextSourceManager.getInstance().removeSourceProviderListener(sourceListener);
+ sourceListener = null;
+ }
+ } else {
+ updateSourceListener();
+ }
+ }
+
+ protected void updateSearch(final SearchRule rule, final boolean paused) {
+ getSearchEngine().setRule(rule);
+ }
+
+ protected void updateSelection() {
+ if (type == FIND_NEXT) {
+ getSearchEngine().selectNext();
+ } else if (type == FIND_PREVIOUS) {
+ getSearchEngine().selectPrev();
+ }
+ }
+
+ protected boolean setDescription(final TextSourceMaker descriptor) {
+ // ignore panel controls
+ if (descriptor != null && panel != null && panel.getControl() != null) {
+ if (isParent(panel.getControl(), descriptor.getControl()))
+ return false;
+ }
+ // ignore the same source
+ if (descriptor == null) {
+ if (this.creator == null)
+ return false;
+ } else if (descriptor.equals(this.creator)) {
+ return false;
+ }
+ if (source != null) {
+ source.dispose();
+ source = null;
+ this.creator = null;
+ }
+ if (descriptor != null && descriptor.isValid()) {
+ this.creator = descriptor;
+ source = new UITextSource(descriptor.create(), descriptor.getControl());
+ getSearchEngine().setSource(rule, source, true);
+ source.init();
+ updateIndexingState();
+ }
+ return true;
+ }
+
+ private void updateIndexingState() {
+ if (monitor != null) {
+ monitor.setCanceled(true);
+ monitor = null;
+ }
+
+ final boolean indexRequired = source != null && !source.isDisposed()
+ && source.isIndexRequired();
+ if (GlancePlugin.getDefault().getPreferenceStore().getBoolean(
+ IPreferenceConstants.PANEL_AUTO_INDEXING)
+ && indexRequired) {
+ index();
+ } else {
+ panel.setIndexingState(indexRequired ? ISearchPanel.INDEXING_STATE_INITIAL
+ : ISearchPanel.INDEXING_STATE_DISABLE);
+ }
+ }
+
+ public void index() {
+ if (panel != null && source != null && !source.isDisposed()) {
+ monitor = new SearchProgressMonitor(panel);
+ new Thread() {
+ @Override
+ public void run() {
+ panel.setIndexingState(ISearchPanel.INDEXING_STATE_IN_PROGRESS);
+ if (source != null) {
+ source.index(monitor);
+ }
+ }
+ }.start();
+ }
+ }
+
+ private IProgressMonitor monitor;
+
+ protected void updateEnabling() {
+ if (panel != null) {
+ panel.setEnabled(source != null);
+ if (source == null) {
+ panel.setIndexingState(ISearchPanel.INDEXING_STATE_FINISHED);
+ }
+ }
+ }
+
+ protected boolean isParent(final Control parent, Control child) {
+ while (child != null) {
+ if (child.equals(parent))
+ return true;
+ child = child.getParent();
+ }
+ return false;
+ }
+
+ private SearchEngine getSearchEngine() {
+ if (engine == null) {
+ engine = new SearchEngine(searchListener);
+ engine.start();
+ }
+ return engine;
+ }
+
+ private void updateSourceListener() {
+ if (sourceListener == null) {
+ sourceListener = new SourceListener();
+ TextSourceManager.getInstance().addSourceProviderListener(sourceListener);
+ }
+ }
+
+ private class SearchListener implements ISearchListener {
+
+ public void allFound(final Match[] matches) {
+ if (panel != null)
+ panel.allFound(matches);
+ }
+
+ public void finished() {
+ if (panel != null)
+ panel.finished();
+ }
+
+ public void firstFound(final Match match) {
+ if (panel != null)
+ panel.firstFound(match);
+ }
+ }
+
+ private class SourceListener implements ISourceProviderListener {
+ public void sourceChanged(final TextSourceMaker source) {
+ update(source, false);
+ }
+ }
+
+ private class SearchPanelListener implements ISearchPanelListener {
+
+ public SearchPanelListener(final ISearchPanel panel) {
+ this.panel = panel;
+ }
+
+ protected boolean isCurrent() {
+ return panel.equals(SearchManager.this.panel);
+ }
+
+ public void ruleChanged(final SearchRule rule) {
+ if (isCurrent())
+ find(rule, SearchManager.FIND_HERE);
+ }
+
+ public void findNext() {
+ if (isCurrent())
+ find(rule, SearchManager.FIND_NEXT);
+ }
+
+ public void findPrevious() {
+ if (isCurrent())
+ find(rule, SearchManager.FIND_PREVIOUS);
+ }
+
+ public void close() {
+ dispose(panel);
+ }
+
+ public void indexCanceled() {
+ if (monitor != null) {
+ monitor.setCanceled(true);
+ monitor = null;
+ }
+ }
+
+ private final ISearchPanel panel;
+
+ }
+
+ private static SearchManager manager;
+
+ private SearchManager() {
+ panels = new ArrayList<ISearchPanel>();
+ searchListener = new SearchListener();
+ panelToListener = new HashMap<ISearchPanel, SearchPanelListener>();
+ }
+
+ private final SearchListener searchListener;
+ private SourceListener sourceListener;
+ private final Map<ISearchPanel, SearchPanelListener> panelToListener;
+ private SearchEngine engine;
+ private final List<ISearchPanel> panels;
+ private ISearchPanel panel;
+ private ITextSource source;
+ private TextSourceMaker creator;
+
+ private int type;
+ private SearchRule rule;
+
+}

Powered by Google App Engine
This is Rietveld 408576698