| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.help.ui.internal.search; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.help.internal.HelpPlugin; |
| import org.eclipse.help.internal.base.BaseHelpSystem; |
| import org.eclipse.help.internal.criteria.CriterionResource; |
| import org.eclipse.help.internal.workingset.AdaptableHelpResource; |
| import org.eclipse.help.internal.workingset.WorkingSet; |
| import org.eclipse.help.ui.IEngineDescriptor; |
| import org.eclipse.help.ui.RootScopePage; |
| import org.eclipse.help.ui.internal.Messages; |
| import org.eclipse.help.ui.internal.search.HelpCriteriaContentProvider.CriterionName; |
| import org.eclipse.help.ui.internal.search.HelpCriteriaContentProvider.CriterionValue; |
| 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; |
| |
| /** |
| * Local Help participant in the federated search. |
| */ |
| public class LocalHelpPage extends RootScopePage { |
| private Button searchAll; |
| |
| private Button searchSelected; |
| |
| private CheckboxTreeViewer contentTree; |
| |
| private ITreeContentProvider contentTreeContentProvider; |
| |
| private ILabelProvider contentTreeLabelProvider; |
| |
| private CheckboxTreeViewer criteriaTree; |
| |
| private ITreeContentProvider criteriaTreeContentProvider; |
| |
| private ILabelProvider criteriaTreeLabelProvider; |
| |
| //private boolean firstCheck; |
| |
| private WorkingSet workingSet; |
| |
| @Override |
| public void init(IEngineDescriptor ed, String scopeSetName) { |
| super.init(ed, scopeSetName); |
| if (scopeSetName != null) |
| workingSet = BaseHelpSystem.getWorkingSetManager().getWorkingSet( |
| scopeSetName); |
| } |
| |
| /** |
| * Default constructor. |
| */ |
| public LocalHelpPage() { |
| //firstCheck = true; |
| } |
| |
| @Override |
| protected int createScopeContents(Composite parent) { |
| Font font = parent.getFont(); |
| initializeDialogUnits(parent); |
| |
| 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) { |
| contentTree.getTree().setEnabled(false); |
| if (criteriaTree != null) { |
| criteriaTree.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) { |
| contentTree.getTree().setEnabled(true); |
| if (criteriaTree != null) { |
| criteriaTree.getTree().setEnabled(true); |
| |
| } |
| } |
| }); |
| |
| if (workingSet == null) |
| searchAll.setSelection(true); |
| else |
| searchSelected.setSelection(true); |
| |
| Label contentLabel = new Label(parent, SWT.WRAP); |
| contentLabel.setFont(font); |
| contentLabel.setText(Messages.WorkingSetContent); |
| gd = new GridData(GridData.GRAB_HORIZONTAL |
| | GridData.HORIZONTAL_ALIGN_FILL |
| | GridData.VERTICAL_ALIGN_CENTER); |
| gd.horizontalSpan = 2; |
| contentLabel.setLayoutData(gd); |
| |
| createContentTree(parent, font); |
| |
| if (HelpPlugin.getCriteriaManager().isCriteriaEnabled()) { |
| Label criteriaLabel = new Label(parent, SWT.WRAP); |
| criteriaLabel.setFont(font); |
| criteriaLabel.setText(Messages.WorkingSetCriteria); |
| gd = new GridData(GridData.GRAB_HORIZONTAL |
| | GridData.HORIZONTAL_ALIGN_FILL |
| | GridData.VERTICAL_ALIGN_CENTER); |
| gd.horizontalSpan = 2; |
| criteriaLabel.setLayoutData(gd); |
| createCriteriaTree(parent, font); |
| } |
| |
| initializeCheckedState(); |
| applyDialogFont(parent); |
| |
| // Set help for the page |
| // WorkbenchHelp.setHelp(tree, "help_workingset_page"); |
| return 1; |
| } |
| |
| protected void createContentTree(Composite parent, Font font) { |
| GridData gd; |
| contentTree = new CheckboxTreeViewer(parent, SWT.BORDER | SWT.H_SCROLL |
| | SWT.V_SCROLL); |
| gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL); |
| gd.heightHint = getTreeHeightHint(); |
| gd.horizontalSpan = 2; |
| contentTree.getControl().setLayoutData(gd); |
| contentTree.getControl().setFont(font); |
| |
| contentTreeContentProvider = new HelpWorkingSetTreeContentProvider(); |
| contentTree.setContentProvider(contentTreeContentProvider); |
| |
| contentTreeLabelProvider = new HelpWorkingSetElementLabelProvider(); |
| contentTree.setLabelProvider(contentTreeLabelProvider); |
| |
| contentTree.setUseHashlookup(true); |
| |
| contentTree.setInput(BaseHelpSystem.getWorkingSetManager().getRoot()); |
| |
| contentTree.addCheckStateListener( |
| event -> handleCheckStateChange(event, contentTree, contentTreeContentProvider)); |
| |
| contentTree.addTreeListener(new ITreeViewerListener() { |
| |
| @Override |
| public void treeCollapsed(TreeExpansionEvent event) { |
| } |
| |
| @Override |
| public void treeExpanded(TreeExpansionEvent event) { |
| final Object element = event.getElement(); |
| if (contentTree.getGrayed(element) == false) |
| BusyIndicator.showWhile(getShell().getDisplay(), |
| () -> setSubtreeChecked(element, contentTree.getChecked(element), false, |
| contentTree, contentTreeContentProvider)); |
| } |
| }); |
| contentTree.getTree().setEnabled(workingSet != null); |
| } |
| |
| protected int getTreeHeightHint() { |
| if (HelpPlugin.getCriteriaManager().isCriteriaEnabled()) { |
| return convertHeightInCharsToPixels(8); |
| } |
| return convertHeightInCharsToPixels(15); |
| } |
| |
| |
| protected void createCriteriaTree(Composite parent, Font font) { |
| GridData gd; |
| criteriaTree = new CheckboxTreeViewer(parent, SWT.BORDER | SWT.H_SCROLL |
| | SWT.V_SCROLL); |
| gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL); |
| gd.heightHint = getTreeHeightHint(); |
| gd.horizontalSpan = 2; |
| criteriaTree.getControl().setLayoutData(gd); |
| criteriaTree.getControl().setFont(font); |
| |
| criteriaTreeContentProvider = new HelpCriteriaContentProvider(); |
| criteriaTree.setContentProvider(criteriaTreeContentProvider); |
| |
| criteriaTreeLabelProvider = new HelpCriteriaLabelProvider(); |
| criteriaTree.setLabelProvider(criteriaTreeLabelProvider); |
| |
| criteriaTree.setUseHashlookup(true); |
| |
| criteriaTree.setInput(BaseHelpSystem.getWorkingSetManager().getCriterionIds()); |
| |
| criteriaTree.addCheckStateListener( |
| event -> handleCheckStateChange(event, criteriaTree, criteriaTreeContentProvider)); |
| |
| criteriaTree.addTreeListener(new ITreeViewerListener() { |
| |
| @Override |
| public void treeCollapsed(TreeExpansionEvent event) { |
| } |
| |
| @Override |
| public void treeExpanded(TreeExpansionEvent event) { |
| final Object element = event.getElement(); |
| if (criteriaTree.getGrayed(element) == false) |
| BusyIndicator.showWhile(getShell().getDisplay(), |
| () -> setSubtreeChecked(element, criteriaTree.getChecked(element), false, |
| criteriaTree, criteriaTreeContentProvider)); |
| } |
| }); |
| criteriaTree.getTree().setEnabled(workingSet != null); |
| } |
| |
| |
| private void initializeCheckedState() { |
| if (workingSet == null) |
| return; |
| |
| BusyIndicator.showWhile(getShell().getDisplay(), () -> { |
| initializeContentTree(); |
| if (HelpPlugin.getCriteriaManager().isCriteriaEnabled()) { |
| initializeCriteriaTree(); |
| } |
| }); |
| } |
| |
| boolean isExpandable(Object element, ITreeContentProvider contentProvider) { |
| return contentProvider.hasChildren(element); |
| } |
| |
| void updateParentState(Object child, boolean baseChildState, |
| CheckboxTreeViewer tree, ITreeContentProvider contentProvider) { |
| if (child == null) |
| return; |
| |
| Object parent = contentProvider.getParent(child); |
| if (parent == null) |
| return; |
| |
| boolean allSameState = true; |
| Object[] children = null; |
| children = contentProvider.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, tree, contentProvider); |
| } |
| |
| void setSubtreeChecked(Object parent, boolean state, |
| boolean checkExpandedState, |
| CheckboxTreeViewer tree, ITreeContentProvider contentProvider) { |
| |
| Object[] children = contentProvider.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, contentProvider)) |
| setSubtreeChecked(element, state, checkExpandedState, tree, contentProvider); |
| } |
| } |
| |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| private void findCheckedElements(java.util.List checkedResources, Object parent, |
| CheckboxTreeViewer tree, ITreeContentProvider contentProvider) { |
| Object[] children = contentProvider.getChildren(parent); |
| for (int i = 0; i < children.length; i++) { |
| if (tree.getGrayed(children[i])) |
| findCheckedElements(checkedResources, children[i], tree, contentProvider); |
| else if (tree.getChecked(children[i])) |
| checkedResources.add(children[i]); |
| } |
| } |
| |
| private CriterionResource[] findCheckedCriteria(Object parent, |
| CheckboxTreeViewer tree, ITreeContentProvider contentProvider) { |
| Object[] children = contentProvider.getChildren(parent); |
| List<CriterionResource> resources = new ArrayList<>(); |
| for (int i = 0; i < children.length; i++) { |
| // First level children are names |
| CriterionName name = (CriterionName) children[i]; |
| CriterionResource resource = new CriterionResource(name.getId()); |
| Object[] grandChildren = contentProvider.getChildren(name); |
| for (int j = 0; j < grandChildren.length; j++) { |
| if (tree.getChecked(grandChildren[j])) { |
| CriterionValue value = (CriterionValue) grandChildren[j]; |
| resource.addCriterionValue(value.getId()); |
| } |
| } |
| if (resource.getCriterionValues().size() > 0) { |
| resources.add(resource); |
| } |
| } |
| return resources.toArray(new CriterionResource[resources.size()]); |
| } |
| |
| void handleCheckStateChange(final CheckStateChangedEvent event, |
| final CheckboxTreeViewer tree, final ITreeContentProvider contentProvider) { |
| BusyIndicator.showWhile(getShell().getDisplay(), () -> { |
| Object element = event.getElement(); |
| boolean state = event.getChecked(); |
| tree.setGrayed(element, false); |
| if (isExpandable(element, contentProvider)) |
| setSubtreeChecked(element, state, state, tree, contentProvider); |
| // only check subtree if state is set to true |
| |
| updateParentState(element, state, tree, contentProvider); |
| // validateInput(); |
| }); |
| } |
| |
| public WorkingSet getWorkingSet() { |
| ArrayList<AdaptableHelpResource> elements = new ArrayList<>(10); |
| CriterionResource[] criteria; |
| if (!HelpPlugin.getCriteriaManager().isCriteriaEnabled()) { |
| criteria = new CriterionResource[0]; |
| } else { |
| criteria = findCheckedCriteria( |
| criteriaTree.getInput(), |
| criteriaTree, |
| criteriaTreeContentProvider); |
| } |
| findCheckedElements(elements, contentTree.getInput(), contentTree, contentTreeContentProvider); |
| if (workingSet == null) { |
| workingSet = new WorkingSet( |
| getScopeSetName(), |
| elements.toArray(new AdaptableHelpResource[elements.size()]), criteria); |
| } else { |
| workingSet.setName(getScopeSetName()); |
| workingSet.setElements(elements.toArray(new AdaptableHelpResource[elements.size()])); |
| workingSet.setCriteria(criteria); |
| } |
| return workingSet; |
| } |
| |
| @Override |
| public boolean performOk() { |
| if (searchSelected.getSelection()) |
| BaseHelpSystem.getWorkingSetManager() |
| .addWorkingSet(getWorkingSet()); |
| else |
| BaseHelpSystem.getWorkingSetManager().removeWorkingSet( |
| getWorkingSet()); |
| |
| getPreferenceStore().setValue( |
| getKey(LocalSearchScopeFactory.P_WORKING_SET), |
| getScopeSetName()); |
| getPreferenceStore().setValue( |
| getKey(LocalSearchScopeFactory.P_CAPABILITY_FILTERING), |
| false); |
| return super.performOk(); |
| } |
| |
| private String getKey(String key) { |
| return getEngineDescriptor().getId() + "." + key; //$NON-NLS-1$ |
| } |
| |
| protected void initializeContentTree() { |
| Object[] elements = workingSet.getElements(); |
| contentTree.setCheckedElements(elements); |
| for (int i = 0; i < elements.length; i++) { |
| Object element = elements[i]; |
| if (isExpandable(element, contentTreeContentProvider)) |
| setSubtreeChecked(element, true, true, contentTree, contentTreeContentProvider); |
| updateParentState(element, true, contentTree, contentTreeContentProvider); |
| } |
| } |
| |
| protected void initializeCriteriaTree() { |
| CriterionResource[] criteria = workingSet.getCriteria(); |
| criteriaTree.setCheckedElements(criteria); |
| for (int i = 0; i < criteria.length; i++) { |
| CriterionResource element = criteria[i]; |
| CriterionName name = new CriterionName(element.getCriterionName(), null); |
| List<String> values = element.getCriterionValues(); |
| for (Iterator<String> iter = values.iterator(); iter.hasNext();) { |
| String valueString = iter.next(); |
| CriterionValue value = new CriterionValue(valueString, name); |
| criteriaTree.setChecked(value, true); |
| updateParentState(value, true, criteriaTree, criteriaTreeContentProvider); |
| } |
| } |
| } |
| |
| @Override |
| protected void performDefaults() { |
| searchAll.setSelection(true); |
| searchSelected.setSelection(false); |
| contentTree.setCheckedElements(new Object[0]); |
| if (criteriaTree != null) { |
| criteriaTree.setCheckedElements(new Object[0]); |
| } |
| super.performDefaults(); |
| } |
| |
| @Override |
| protected Label createDescriptionLabel(Composite parent) { |
| if ( getContainer() == null ) { |
| return null; |
| } |
| return super.createDescriptionLabel(parent); |
| } |
| } |