/******************************************************************************* * Copyright (c) 2000, 2016 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 *******************************************************************************/ package org.eclipse.help.ui.internal.views; import java.util.ArrayList; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.help.HelpSystem; import org.eclipse.help.IHelpResource; import org.eclipse.help.IToc; import org.eclipse.help.internal.base.HelpBasePlugin; import org.eclipse.help.internal.base.IHelpBaseConstants; import org.eclipse.help.search.ISearchEngineResult; import org.eclipse.help.ui.internal.HelpUIResources; import org.eclipse.help.ui.internal.IHelpUIConstants; import org.eclipse.help.ui.internal.Messages; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.ui.IMemento; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.forms.AbstractFormPart; import org.eclipse.ui.forms.widgets.FormText; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import org.osgi.service.prefs.BackingStoreException; public class SearchResultsPart extends AbstractFormPart implements IHelpPart { ReusableHelpPart parent; private Composite separator; private Composite container; private ScrolledForm innerForm; private String id; //private Action removeAllAction; private Action showCategoriesAction; private Action showDescriptionAction; private ArrayList<EngineResultSection> results; //private String phrase; private FormToolkit innerToolkit; /** * @param parent * @param toolkit * @param style */ public SearchResultsPart(Composite parent, FormToolkit toolkit, IToolBarManager tbm) { GridLayout layout = new GridLayout(); layout.marginWidth = layout.marginHeight = 0; layout.verticalSpacing = 0; innerToolkit = new FormToolkit(parent.getDisplay()); innerToolkit.getHyperlinkGroup().setHyperlinkUnderlineMode( toolkit.getHyperlinkGroup().getHyperlinkUnderlineMode()); container = innerToolkit.createComposite(parent); container.setLayout(layout); separator = innerToolkit.createCompositeSeparator(container); separator.setVisible(false); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = 1; separator.setLayoutData(gd); innerForm = innerToolkit.createScrolledForm(container); innerForm.setDelayedReflow(true); innerForm.setLayoutData(new GridData(GridData.FILL_BOTH)); final ScrollBar scrollBar = innerForm.getVerticalBar(); scrollBar.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateSeparatorVisibility(); } }); TableWrapLayout tlayout = new TableWrapLayout(); tlayout.topMargin = 0; tlayout.bottomMargin = 0; innerForm.getBody().setLayout(tlayout); results = new ArrayList<>(); contributeToToolBar(tbm); } void updateSeparatorVisibility() { ScrollBar scrollBar = innerForm.getVerticalBar(); separator.setVisible(scrollBar.getSelection()>0); } private void contributeToToolBar(IToolBarManager tbm) { /* * removeAllAction = new Action() { public void run() { clearResults(); } }; * removeAllAction.setImageDescriptor(HelpUIResources * .getImageDescriptor(IHelpUIConstants.IMAGE_REMOVE_ALL)); * removeAllAction.setToolTipText("Remove all hits"); * removeAllAction.setId("removeAll"); tbm.insertBefore("back", * removeAllAction); tbm.insertAfter("removeAll", new Separator()); */ boolean descOn = Platform.getPreferencesService().getBoolean (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_SHOW_SEARCH_DESCRIPTION, false, null); boolean showCategories = Platform.getPreferencesService().getBoolean (HelpBasePlugin.PLUGIN_ID, IHelpBaseConstants.P_KEY_SHOW_SEARCH_CATEGORIES, false, null); showCategoriesAction = new Action() { @Override public void run() { updateResultSections(); IEclipsePreferences pref = InstanceScope.INSTANCE.getNode(HelpBasePlugin.PLUGIN_ID); pref.putBoolean(IHelpBaseConstants.P_KEY_SHOW_SEARCH_CATEGORIES, showCategoriesAction.isChecked()); try { pref.flush(); } catch (BackingStoreException e) { } } }; showCategoriesAction.setImageDescriptor(HelpUIResources .getImageDescriptor(IHelpUIConstants.IMAGE_SHOW_CATEGORIES)); showCategoriesAction.setChecked(showCategories); showCategoriesAction.setToolTipText(Messages.SearchResultsPart_showCategoriesAction_tooltip); showCategoriesAction.setId("categories"); //$NON-NLS-1$ tbm.insertBefore("back", showCategoriesAction); //$NON-NLS-1$ showDescriptionAction = new Action() { @Override public void run() { updateResultSections(); IEclipsePreferences pref = InstanceScope.INSTANCE.getNode(HelpBasePlugin.PLUGIN_ID); pref.putBoolean(IHelpBaseConstants.P_KEY_SHOW_SEARCH_DESCRIPTION, showDescriptionAction.isChecked()); try { pref.flush(); } catch (BackingStoreException e) { } } }; showDescriptionAction.setImageDescriptor(HelpUIResources .getImageDescriptor(IHelpUIConstants.IMAGE_SHOW_DESC)); showDescriptionAction.setChecked(descOn); showDescriptionAction.setToolTipText(Messages.SearchResultsPart_showDescriptionAction_tooltip); showDescriptionAction.setId("description"); //$NON-NLS-1$ tbm.insertAfter("categories", showDescriptionAction); //$NON-NLS-1$ tbm.insertAfter("description", new Separator()); //$NON-NLS-1$ } @Override public void dispose() { innerToolkit.dispose(); super.dispose(); } private void updateResultSections() { BusyIndicator.showWhile(container.getDisplay(), () -> { for (int i = 0; i < results.size(); i++) { EngineResultSection section = results.get(i); section.updateResults(false); } reflow(); }); } boolean getShowCategories() { return showCategoriesAction.isChecked(); } boolean getShowDescription() { return showDescriptionAction.isChecked(); } @Override public Control getControl() { return container; } @Override public void init(ReusableHelpPart parent, String id, IMemento memento) { this.parent = parent; this.id = id; } @Override public String getId() { return id; } @Override public void setVisible(boolean visible) { container.setVisible(visible); } void clearResults() { clearResultSections(); separator.setVisible(false); reflow(); } void clearResultSections() { for (int i = 0; i < results.size(); i++) { EngineResultSection section = results.get(i); section.dispose(); } results.clear(); } void startNewSearch(String phrase, ArrayList<EngineDescriptor> eds) { //this.phrase = phrase; //separator.setVisible(true); // locate local help engine and add it first EngineDescriptor localHelp = findLocalHelp(eds); if (localHelp!=null) add(localHelp); // add engines other than local help for (int i = 0; i < eds.size(); i++) { EngineDescriptor ed = eds.get(i); if (ed==localHelp) continue; add(ed); } reflow(); } private EngineDescriptor findLocalHelp(ArrayList<EngineDescriptor> eds) { for (int i=0; i<eds.size(); i++) { EngineDescriptor ed = eds.get(i); if (ed.getEngineTypeId().equals(IHelpUIConstants.INTERNAL_HELP_ID)) return ed; } return null; } void completed() { for (int i = 0; i < results.size(); i++) { EngineResultSection section = results.get(i); section.completed(); } } void canceling() { for (int i = 0; i < results.size(); i++) { EngineResultSection section = results.get(i); section.canceling(); } } void doOpenLink(Object href) { String url = (String) href; if (url.startsWith("nw:")) { //$NON-NLS-1$ parent.showExternalURL(url.substring(3)); } else parent.showURL(url); } void doCategoryLink(String href) { parent.showPage(IHelpUIConstants.HV_ALL_TOPICS_PAGE); AllTopicsPart part = (AllTopicsPart) parent .findPart(IHelpUIConstants.HV_TOPIC_TREE); if (part != null) { IToc[] tocs = HelpSystem.getTocs(); IHelpResource target = null; for (int i = 0; i < tocs.length; i++) { if (tocs[i].getHref().equals(href)) target = tocs[i]; } if (target != null) { part.selectReveal(target); } } } @Override public boolean fillContextMenu(IMenuManager manager) { Control focusControl = container.getDisplay().getFocusControl(); if (focusControl != null && focusControl instanceof FormText) { return parent.fillFormContextMenu((FormText) focusControl, manager); } return false; } @Override public boolean hasFocusControl(Control control) { for (int i = 0; i < results.size(); i++) { EngineResultSection er = results.get(i); if (er.hasControl(control)) return true; } return false; } public synchronized void add(EngineDescriptor ed, ISearchEngineResult match) { EngineResultSection ers = findEngineResult(ed); if (match != null) ers.add(match); } public synchronized void add(EngineDescriptor ed, ISearchEngineResult[] matches) { EngineResultSection ers = findEngineResult(ed); ers.add(matches); } public synchronized void error(EngineDescriptor ed, IStatus status) { EngineResultSection ers = findEngineResult(ed); ers.error(status); } private synchronized EngineResultSection findEngineResult( EngineDescriptor ed) { for (int i = 0; i < results.size(); i++) { EngineResultSection er = results.get(i); if (er.matches(ed)) return er; } final EngineResultSection er = new EngineResultSection(this, ed); Display display = parent.getForm().getToolkit().getColors() .getDisplay(); display.syncExec(() -> { Control c = er.createControl(innerForm.getBody(), innerToolkit); c.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); }); results.add(er); return er; } private void add(EngineDescriptor ed) { final EngineResultSection er = new EngineResultSection(this, ed); Control c = er.createControl(innerForm.getBody(), innerToolkit); c.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); results.add(er); } void reflow() { innerForm.reflow(true); parent.reflow(); } @Override public boolean setFormInput(Object input) { return false; } void scrollToBeginning() { innerForm.setOrigin(0, 0); } @Override public IAction getGlobalAction(String id) { if (id.equals(ActionFactory.COPY.getId())) return parent.getCopyAction(); return null; } FormToolkit getToolkit() { return innerToolkit; } @Override public void stop() { } @Override public void toggleRoleFilter() { updateResultSections(); } @Override public void refilter() { updateResultSections(); } @Override public void saveState(IMemento memento) { } }