/******************************************************************************* * 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.search; import java.util.ArrayList; import java.util.StringTokenizer; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.help.internal.workingset.AdaptableHelpResource; import org.eclipse.help.internal.workingset.AdaptableTocsArray; import org.eclipse.help.internal.workingset.WorkingSet; import org.eclipse.help.ui.RootScopePage; import org.eclipse.help.ui.internal.Messages; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.ITreeViewerListener; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; /** * Local Help participant in the federated search. */ public class InfoCenterPage extends RootScopePage { private Text urlText; private Button searchAll; private Button searchSelected; private CheckboxTreeViewer tree; private ITreeContentProvider treeContentProvider; private ILabelProvider elementLabelProvider; private AdaptableTocsArray remoteTocs; //private boolean firstCheck; private RemoteWorkingSet workingSet; private boolean tocStale; class RemoteWorkingSet extends WorkingSet { public RemoteWorkingSet() { super("InfoCenter"); //$NON-NLS-1$ } public void load(IPreferenceStore store) { String elements = store.getString(getKey(InfoCenterSearchScopeFactory.P_TOCS)); StringTokenizer stok = new StringTokenizer(elements, InfoCenterSearchScopeFactory.TOC_SEPARATOR); ArrayList<AdaptableHelpResource> list = new ArrayList<>(); while (stok.hasMoreTokens()) { final String url = stok.nextToken(); AdaptableHelpResource res = find(url); if (res != null) list.add(res); } setElements(list.toArray(new AdaptableHelpResource[list.size()])); } private AdaptableHelpResource find(String url) { if (remoteTocs == null) return null; IAdaptable[] children = remoteTocs.getChildren(); for (int i = 0; i < children.length; i++) { IAdaptable child = children[i]; if (child instanceof AdaptableHelpResource) { AdaptableHelpResource res = (AdaptableHelpResource) child; if (res.getHref().equals(url)) return res; } } return null; } public void store(IPreferenceStore store) { StringBuffer buf = new StringBuffer(); AdaptableHelpResource[] elements = getElements(); for (int i = 0; i < elements.length; i++) { if (i > 0) buf.append(InfoCenterSearchScopeFactory.TOC_SEPARATOR); buf.append(elements[i].getHref()); } store.setValue(getKey(InfoCenterSearchScopeFactory.P_TOCS), buf.toString()); } } /** * Default constructor. */ public InfoCenterPage() { //firstCheck = true; } @Override protected int createScopeContents(Composite parent) { Font font = parent.getFont(); initializeDialogUnits(parent); Label label = new Label(parent, SWT.NULL); label.setText(Messages.InfoCenterPage_url); urlText = new Text(parent, SWT.BORDER); urlText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); urlText.setEditable(getEngineDescriptor().isUserDefined()); searchAll = new Button(parent, SWT.RADIO); searchAll.setText(Messages.selectAll); GridData gd = new GridData(); gd.horizontalSpan = 2; searchAll.setLayoutData(gd); searchAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (searchAll.getSelection()) tree.getTree().setEnabled(false); } }); searchSelected = new Button(parent, SWT.RADIO); searchSelected.setText(Messages.selectWorkingSet); gd = new GridData(); gd.horizontalSpan = 2; searchSelected.setLayoutData(gd); searchSelected.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (searchSelected.getSelection()) { tree.getTree().setEnabled(true); if (tocStale) updateTocs(); } } }); label = new Label(parent, SWT.WRAP); label.setFont(font); label.setText(Messages.WorkingSetContent); gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); gd.horizontalSpan = 2; label.setLayoutData(gd); tree = new CheckboxTreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL); gd.heightHint = convertHeightInCharsToPixels(15); gd.horizontalSpan = 2; tree.getControl().setLayoutData(gd); tree.getControl().setFont(font); treeContentProvider = new HelpWorkingSetTreeContentProvider(); tree.setContentProvider(treeContentProvider); elementLabelProvider = new HelpWorkingSetElementLabelProvider(); tree.setLabelProvider(elementLabelProvider); tree.setUseHashlookup(true); initializeControls(); tree.addCheckStateListener(event -> handleCheckStateChange(event)); tree.addTreeListener(new ITreeViewerListener() { @Override public void treeCollapsed(TreeExpansionEvent event) { } @Override public void treeExpanded(TreeExpansionEvent event) { final Object element = event.getElement(); if (tree.getGrayed(element) == false) BusyIndicator.showWhile(getShell().getDisplay(), () -> setSubtreeChecked(element, tree.getChecked(element), false)); } }); applyDialogFont(parent); // Set help for the page // WorkbenchHelp.setHelp(tree, "help_workingset_page"); return 2; } /* private void loadTocs(String urlName) { InputStream is = null; if (urlName==null || urlName.length()==0) { resetRemoteTocs(); return; } try { URL url = new URL(urlName); url = new URL(url, "toc/"); //$NON-NLS-1$ URLConnection connection = url.openConnection(); is = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader( is, "utf-8"));//$NON-NLS-1$ load(reader); reader.close(); } catch (MalformedURLException e) { HelpUIPlugin.logError(Messages.InfoCenterPage_invalidURL, e, false, true); resetRemoteTocs(); } catch (IOException e) { HelpUIPlugin.logError(Messages.InfoCenterPage_tocError, e, false, true); resetRemoteTocs(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { } } } } private void resetRemoteTocs() { remoteTocs = new AdaptableTocsArray(new IToc[0]); } private void load(Reader r) { Document document = null; try { DocumentBuilder parser = DocumentBuilderFactory.newInstance() .newDocumentBuilder(); parser.setEntityResolver(new LocalEntityResolver()); // parser.setProcessNamespace(true); document = parser.parse(new InputSource(r)); // Strip out any comments first Node root = document.getFirstChild(); while (root.getNodeType() == Node.COMMENT_NODE) { document.removeChild(root); root = document.getFirstChild(); } load(document, (Element) root); } catch (ParserConfigurationException e) { // ignore } catch (IOException e) { // ignore } catch (SAXException e) { // ignore } } private void load(Document doc, Element root) { ArrayList list = new ArrayList(); NodeList engines = root.getElementsByTagName("toc"); //$NON-NLS-1$ for (int i = 0; i < engines.getLength(); i++) { final Node node = engines.item(i); IToc toc = new IToc() { public ITopic[] getTopics() { return new ITopic[0]; } public ITopic getTopic(String href) { return null; } public String getHref() { return node.getAttributes().getNamedItem("href") //$NON-NLS-1$ .getNodeValue(); } public String getLabel() { return node.getAttributes().getNamedItem("label") //$NON-NLS-1$ .getNodeValue(); } public IUAElement[] getChildren() { return new IUAElement[0]; } public boolean isEnabled(IEvaluationContext context) { return true; } }; list.add(toc); } IToc[] tocs = (IToc[]) list.toArray(new IToc[list.size()]); remoteTocs = new AdaptableTocsArray(tocs); } */ private void initializeControls() { IPreferenceStore store = getPreferenceStore(); String url = store .getString(getKey(InfoCenterSearchScopeFactory.P_URL)); if (url.length() == 0) { url = (String) getEngineDescriptor().getParameters().get( InfoCenterSearchScopeFactory.P_URL); if (url == null) url = ""; //$NON-NLS-1$ } urlText.setText(url); //busyLoadTocs(url); workingSet = new RemoteWorkingSet(); workingSet.load(store); urlText.addModifyListener(e -> tocStale = true); tree.setInput(remoteTocs); boolean selected = false; // store.getBoolean(getKey(InfoCenterSearchScopeFactory.P_SEARCH_SELECTED)); searchAll.setSelection(!selected); searchSelected.setSelection(selected); tree.getTree().setEnabled(selected); searchAll.setEnabled(false); searchSelected.setEnabled(false); BusyIndicator.showWhile(getShell().getDisplay(), () -> { Object[] elements = workingSet.getElements(); tree.setCheckedElements(elements); for (int i = 0; i < elements.length; i++) { Object element = elements[i]; if (isExpandable(element)) setSubtreeChecked(element, true, true); updateParentState(element, true); } }); } private void updateTocs() { //String url = urlText.getText(); //busyLoadTocs(url); tocStale=false; tree.setInput(remoteTocs); BusyIndicator.showWhile(getShell().getDisplay(), () -> { Object[] elements = workingSet.getElements(); tree.setCheckedElements(elements); for (int i = 0; i < elements.length; i++) { Object element = elements[i]; if (isExpandable(element)) setSubtreeChecked(element, true, true); updateParentState(element, true); } }); } /* private void busyLoadTocs(final String url) { BusyIndicator.showWhile(urlText.getDisplay(), new Runnable() { public void run() { loadTocs(url); } }); } */ boolean isExpandable(Object element) { return treeContentProvider.hasChildren(element); } void updateParentState(Object child, boolean baseChildState) { if (child == null) return; Object parent = treeContentProvider.getParent(child); if (parent == null) return; boolean allSameState = true; Object[] children = null; children = treeContentProvider.getChildren(parent); for (int i = children.length - 1; i >= 0; i--) { if (tree.getChecked(children[i]) != baseChildState || tree.getGrayed(children[i])) { allSameState = false; break; } } tree.setGrayed(parent, !allSameState); tree.setChecked(parent, !allSameState || baseChildState); updateParentState(parent, baseChildState); } void setSubtreeChecked(Object parent, boolean state, boolean checkExpandedState) { Object[] children = treeContentProvider.getChildren(parent); for (int i = children.length - 1; i >= 0; i--) { Object element = children[i]; if (state) { tree.setChecked(element, true); tree.setGrayed(element, false); } else tree.setGrayChecked(element, false); if (isExpandable(element)) setSubtreeChecked(element, state, checkExpandedState); } } @SuppressWarnings({ "unchecked", "rawtypes" }) private void findCheckedElements(java.util.List checkedResources, Object parent) { Object[] children = treeContentProvider.getChildren(parent); for (int i = 0; i < children.length; i++) { if (tree.getGrayed(children[i])) findCheckedElements(checkedResources, children[i]); else if (tree.getChecked(children[i])) checkedResources.add(children[i]); } } void handleCheckStateChange(final CheckStateChangedEvent event) { BusyIndicator.showWhile(getShell().getDisplay(), () -> { Object element = event.getElement(); boolean state = event.getChecked(); tree.setGrayed(element, false); if (isExpandable(element)) setSubtreeChecked(element, state, state); // only check subtree if state is set to true updateParentState(element, state); // validateInput(); }); } public void updateWorkingSet() { ArrayList<AdaptableHelpResource> elements = new ArrayList<>(10); findCheckedElements(elements, tree.getInput()); workingSet.setElements(elements.toArray(new AdaptableHelpResource[elements.size()])); } @Override public boolean performOk() { IPreferenceStore store = getPreferenceStore(); if (getEngineDescriptor().isUserDefined()) store.setValue(getKey(InfoCenterSearchScopeFactory.P_URL), urlText .getText()); updateWorkingSet(); workingSet.store(store); store.setValue(getKey(InfoCenterSearchScopeFactory.P_SEARCH_SELECTED), searchSelected.getSelection()); return super.performOk(); } private String getKey(String key) { return getEngineDescriptor().getId() + "." + key; //$NON-NLS-1$ } }