/******************************************************************************* * Copyright (c) 2012, 2014 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.ui.dialogs; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.tcf.te.ui.activator.UIPlugin; import org.eclipse.tcf.te.ui.nls.Messages; import org.eclipse.tcf.te.ui.search.TablePatternFilter; import org.eclipse.tcf.te.ui.swt.SWTControlUtil; import org.eclipse.ui.dialogs.SelectionStatusDialog; import org.eclipse.ui.navigator.IDescriptionProvider; /** * A selection dialog with a checked list and a filter text field. */ public class FilteredCheckedListDialog extends SelectionStatusDialog implements ISelectionChangedListener { // The pattern filter used filter the content of the list. TablePatternFilter patternFilter; // The text field used to enter filters. Text filterText; // The check-box style table used to display a list and select elements. CheckboxTableViewer tableViewer; // The button of select All. Button btnSelAll; // The button of deselect All Button btnDesAll; // The label provider used to provide labels, images and descriptions for the listed items. ILabelProvider labelProvider; // The initial filter displayed in the filter text field. String filter; // The elements to be selected. Object[] elements; // Currently selected items. Set<Object> checkedItems; /** * Constructor used to instantiate a dialog with a specified parent. * * @param shell The parent shell. */ public FilteredCheckedListDialog(Shell shell) { super(shell); checkedItems = new HashSet<Object>(); } /** * Set the initial filter text to be displayed in the filter text field. * * @param filterText The initial filter text. */ public void setFilterText(String filterText) { this.filter = filterText; } /** * Set the label provider used to provide labels, images and descriptive text * for items in the list. * * @param labelProvider The new label provider. */ public void setLabelProvider(ILabelProvider labelProvider) { this.labelProvider = labelProvider; } /** * Set elements to be displayed in the list for selection. * * @param elements The elements. */ public void setElements(Object[] elements) { this.elements = elements != null ? Arrays.copyOf(elements, elements.length) : null; } /* * (non-Javadoc) * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection structuredSelection = (IStructuredSelection) event.getSelection(); Object element = structuredSelection.getFirstElement(); String description = labelProvider != null && labelProvider instanceof IDescriptionProvider ? ((IDescriptionProvider)labelProvider).getDescription(element) : null; if (description == null) description = element == null ? "" : "Enable "+labelProvider.getText(element)+"."; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ updateStatus(new Status(IStatus.OK, UIPlugin.getUniqueIdentifier(), description)); } /* * (non-Javadoc) * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult() */ @Override protected void computeResult() { setSelectionResult(checkedItems.toArray()); } /* * (non-Javadoc) * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); createMessageArea(composite); createPatternFilterText(composite); createTable(composite); createSelBtn(composite); initializeData(); return composite; } /** * Get accessible name for the filter text field. * * @param e The accessible event. */ protected void getAccessibleName(AccessibleEvent e) { String filterTextString = filterText.getText(); if (filterTextString.length() == 0) { e.result = filter; } else { e.result = filterTextString; } } /** * Called when the filter text field gains focus. * * @param e The focus event. */ protected void filterTextFocusGained(FocusEvent e) { if (filter != null && filter.equals(SWTControlUtil.getText(filterText).trim())) { filterText.selectAll(); } } /** * Called when a mouse up event happens to the filter text field. * * @param e The mouse up event. */ protected void filterTextMouseUp(MouseEvent e) { if (filter != null && filter.equals(SWTControlUtil.getText(filterText).trim())) { filterText.selectAll(); } } /** * Called when a key event happens to the filter text field. * * @param e The key event. */ protected void filterTextKeyPressed(KeyEvent e) { boolean hasItems = tableViewer.getTable().getItemCount() > 0; if (hasItems && e.keyCode == SWT.ARROW_DOWN) { tableViewer.getTable().setFocus(); } } /** * Called when a traverse event happens to the filter text field. * * @param e The traverse event. */ protected void filterTextKeyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN) { e.doit = false; if (tableViewer.getTable().getItemCount() == 0) { Display.getCurrent().beep(); } else { // if the initial filter text hasn't changed, do not try to match boolean hasFocus = tableViewer.getTable().setFocus(); boolean textChanged = filter != null && !filter.equals(SWTControlUtil.getText(filterText).trim()); if (hasFocus && textChanged && filterText.getText().trim().length() > 0) { TableItem[] items = tableViewer.getTable().getItems(); for (TableItem item : items) { if (patternFilter.match(item.getText())) { tableViewer.getTable().setSelection(new TableItem[] { item }); ISelection sel = tableViewer.getSelection(); tableViewer.setSelection(sel, true); break; } } } } } } /** * Called when a text modification event happens. * * @param e The modification event. */ protected void filterTextModifyText(ModifyEvent e) { patternFilter.setPattern(filterText.getText()); tableViewer.refresh(); for (Object item : checkedItems) { tableViewer.setChecked(item, true); } } /** * Called when a list item is checked or unchecked. * * @param event The check event. */ protected void tableCheckStateChanged(CheckStateChangedEvent event) { if (event.getChecked()) checkedItems.add(event.getElement()); else checkedItems.remove(event.getElement()); } /** * Create the filter text field and add listeners to respond to control input. * * @param composite The parent composite. */ private void createPatternFilterText(Composite composite) { filterText = new Text(composite, SWT.SINGLE | SWT.BORDER); GridData filterTextGridData = new GridData(GridData.FILL_HORIZONTAL); filterText.setLayoutData(filterTextGridData); filterText.setText(filter); filterText.setFont(composite.getFont()); filterText.getAccessible().addAccessibleListener(new AccessibleAdapter() { @Override public void getName(AccessibleEvent e) { getAccessibleName(e); } }); filterText.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { filterTextFocusGained(e); } }); filterText.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { filterTextMouseUp(e); } }); filterText.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { filterTextKeyPressed(e); } }); // enter key set focus to tree filterText.addTraverseListener(new TraverseListener() { @Override public void keyTraversed(TraverseEvent e) { filterTextKeyTraversed(e); } }); filterText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { filterTextModifyText(e); } }); } /** * Create the checked list and add check action changed listener to monitor events. * * @param composite The parent composite. */ private void createTable(Composite composite) { tableViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); tableViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { tableCheckStateChanged(event); } }); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 120; data.widthHint = 200; tableViewer.getTable().setLayoutData(data); tableViewer.setContentProvider(ArrayContentProvider.getInstance()); tableViewer.setLabelProvider(labelProvider); patternFilter = new TablePatternFilter(labelProvider); tableViewer.addFilter(patternFilter); tableViewer.addSelectionChangedListener(this); } private void createSelBtn(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(2, false); composite.setLayout(layout); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); composite.setLayoutData(data); btnSelAll = new Button(composite, SWT.PUSH); btnSelAll.setText(Messages.FilteredCheckedListDialog_SelAllText); btnSelAll.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { selectAll(); } }); btnDesAll = new Button(composite, SWT.PUSH); btnDesAll.setText(Messages.FilteredCheckedListDialog_DesAllText); btnDesAll.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { deselectAll(); } }); } void selectAll() { TableItem[] items = tableViewer.getTable().getItems(); for (TableItem item : items) { if (item.getData() != null && !item.getChecked()) { item.setChecked(true); checkedItems.add(item.getData()); } } } void deselectAll() { TableItem[] children = tableViewer.getTable().getItems(); for (TableItem item : children) { if (item.getData() != null && item.getChecked()) { item.setChecked(false); checkedItems.remove(item.getData()); } } } /** * Initialize the list items in the table and force focus to it. */ private void initializeData() { tableViewer.setInput(elements); List<Object> selection = getInitialElementSelections(); if (selection != null) { for (Object element : selection) { tableViewer.setChecked(element, true); checkedItems.add(element); } } filterText.forceFocus(); } }