blob: cef402645673d574d68cc73d5bd5554970136554 [file] [log] [blame]
/*******************************************************************************
* 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$
}
}