/* ********************************************************************** ** ** Copyright notice ** ** ** ** (c) 2005-2009 RSSOwl Development Team ** ** http://www.rssowl.org/ ** ** ** ** 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.rssowl.org/legal/epl-v10.html ** ** ** ** A copy is found in the file epl-v10.html and important notices to the ** ** license from the team is found in the textfile LICENSE.txt distributed ** ** in this package. ** ** ** ** This copyright notice MUST APPEAR in all copies of the file! ** ** ** ** Contributors: ** ** RSSOwl Development Team - initial API and implementation ** ** ** ** ********************************************************************** */ package org.rssowl.ui.internal.dialogs; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; 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.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.rssowl.core.INewsAction; import org.rssowl.core.Owl; import org.rssowl.core.persist.IEntity; import org.rssowl.core.persist.IFilterAction; import org.rssowl.core.persist.INews; import org.rssowl.core.persist.INews.State; import org.rssowl.core.persist.ISearchCondition; import org.rssowl.core.persist.ISearchField; import org.rssowl.core.persist.ISearchFilter; import org.rssowl.core.persist.SearchSpecifier; import org.rssowl.core.persist.dao.DynamicDAO; import org.rssowl.core.persist.dao.ISearchFilterDAO; import org.rssowl.core.persist.reference.NewsReference; import org.rssowl.core.persist.service.IModelSearch; import org.rssowl.core.util.CoreUtils; import org.rssowl.core.util.SearchHit; import org.rssowl.core.util.StringUtils; import org.rssowl.ui.internal.Activator; import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor; import org.rssowl.ui.internal.OwlUI; import org.rssowl.ui.internal.filter.NewsActionDescriptor; import org.rssowl.ui.internal.filter.NewsActionPresentationManager; import org.rssowl.ui.internal.util.CColumnLayoutData; import org.rssowl.ui.internal.util.CColumnLayoutData.Size; import org.rssowl.ui.internal.util.CTable; import org.rssowl.ui.internal.util.LayoutUtils; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * A dialog to manage news filters in RSSOwl. The dialog allows to add, edit and * delete filters as well as moving them up or down to define an order of * filters to apply. * * @author bpasero */ public class NewsFiltersListDialog extends TitleAreaDialog { /* Number of News to process in a forced Filter run at once */ private static final int FILTER_CHUNK_SIZE = 50; /* Keep the visible instance saved */ private static NewsFiltersListDialog fgVisibleInstance; /* Section for Dialogs Settings */ private static final String SETTINGS_SECTION = "org.rssowl.ui.internal.dialogs.NewsFiltersListDialog"; //$NON-NLS-1$ private NewsActionPresentationManager fNewsActionPresentationManager = NewsActionPresentationManager.getInstance(); private LocalResourceManager fResources; private CheckboxTableViewer fViewer; private Button fEditButton; private Button fDeleteButton; private Button fMoveDownButton; private Button fMoveUpButton; private Image fFilterIcon; private ISearchFilterDAO fSearchFilterDao; private Button fApplySelectedFilter; private ISearchFilter fSelectedFilter; /** * @param parentShell */ public NewsFiltersListDialog(Shell parentShell) { super(parentShell); fResources = new LocalResourceManager(JFaceResources.getResources()); fFilterIcon = OwlUI.getImage(fResources, OwlUI.FILTER); fSearchFilterDao = DynamicDAO.getDAO(ISearchFilterDAO.class); } /** * @return Returns an instance of <code>NewsFiltersListDialog</code> or * <code>NULL</code> in case no instance is currently open. */ public static NewsFiltersListDialog getVisibleInstance() { return fgVisibleInstance; } /* * @see org.eclipse.jface.window.Window#open() */ @Override public int open() { fgVisibleInstance = this; return super.open(); } /* * @see org.eclipse.jface.dialogs.TrayDialog#close() */ @Override public boolean close() { boolean res = super.close(); fgVisibleInstance = null; fResources.dispose(); return res; } /* * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ @Override protected Control createDialogArea(Composite parent) { /* Separator */ new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); /* Title */ setTitle(Messages.NewsFiltersListDialog_NEWS_FILTERS); /* Title Image */ setTitleImage(OwlUI.getImage(fResources, "icons/wizban/filter_wiz.png")); //$NON-NLS-1$ /* Composite to hold all components */ Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(LayoutUtils.createGridLayout(2, 5, 10)); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Composite tableContainer = new Composite(composite, SWT.NONE); tableContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0)); tableContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); CTable cTable = new CTable(tableContainer, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION); fViewer = new CheckboxTableViewer(cTable.getControl()); fViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); fViewer.getTable().setHeaderVisible(true); ((GridData) fViewer.getTable().getLayoutData()).heightHint = fViewer.getTable().getItemHeight() * 15; fViewer.getTable().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object()); TableColumn nameCol = new TableColumn(fViewer.getTable(), SWT.NONE); CColumnLayoutData data = new CColumnLayoutData(Size.FILL, 100); cTable.manageColumn(nameCol, data, Messages.NewsFiltersListDialog_NAME, null, null, false, false); /* ContentProvider returns all filters */ fViewer.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { return fSearchFilterDao.loadAll().toArray(); } public void dispose() {} public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} }); /* Label Provider */ fViewer.setLabelProvider(new CellLabelProvider() { @Override public void update(ViewerCell cell) { ISearchFilter filter = (ISearchFilter) cell.getElement(); Display display = fViewer.getControl().getDisplay(); if (filter.isEnabled()) cell.setText(filter.getName()); else cell.setText(NLS.bind(Messages.NewsFiltersListDialog_FILTER_DISABLED, filter.getName())); cell.setImage(fFilterIcon); if (!OwlUI.isHighContrast()) cell.setForeground(filter.isEnabled() ? display.getSystemColor(SWT.COLOR_BLACK) : display.getSystemColor(SWT.COLOR_DARK_GRAY)); } }); /* Sort */ fViewer.setComparator(new ViewerComparator() { @Override public int compare(Viewer viewer, Object e1, Object e2) { ISearchFilter filter1 = (ISearchFilter) e1; ISearchFilter filter2 = (ISearchFilter) e2; return filter1.getOrder() < filter2.getOrder() ? -1 : 1; } }); /* Selection */ fViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); fEditButton.setEnabled(!selection.isEmpty()); fDeleteButton.setEnabled(!selection.isEmpty()); fApplySelectedFilter.setEnabled(!selection.isEmpty() && selection.size() == 1); updateMoveEnablement(); } }); /* Doubleclick */ fViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { onEdit(); } }); /* Set input (ignored by ContentProvider anyways) */ fViewer.setInput(this); updateCheckedState(); /* Listen on Check State Changes */ fViewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { ISearchFilter filter = (ISearchFilter) event.getElement(); filter.setEnabled(event.getChecked()); fSearchFilterDao.save(filter); fViewer.update(filter, null); updateTitle(); } }); /* Container for the Buttons to Manage Filters */ Composite buttonContainer = new Composite(composite, SWT.None); buttonContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0)); buttonContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, false)); /* Adds a new Filter */ Button addButton = new Button(buttonContainer, SWT.PUSH); addButton.setText(Messages.NewsFiltersListDialog_NEW); addButton.setFocus(); applyDialogFont(addButton); setButtonLayoutData(addButton); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onAdd(); } }); /* Edits a selected Filter */ fEditButton = new Button(buttonContainer, SWT.PUSH); fEditButton.setText(Messages.NewsFiltersListDialog_EDIT); applyDialogFont(fEditButton); setButtonLayoutData(fEditButton); fEditButton.setEnabled(false); fEditButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onEdit(); } }); /* Deletes the selected Filter */ fDeleteButton = new Button(buttonContainer, SWT.PUSH); fDeleteButton.setText(Messages.NewsFiltersListDialog_DELETE); applyDialogFont(fDeleteButton); setButtonLayoutData(fDeleteButton); fDeleteButton.setEnabled(false); fDeleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onDelete(); } }); /* Move Filter Up */ fMoveUpButton = new Button(buttonContainer, SWT.PUSH); fMoveUpButton.setText(Messages.NewsFiltersListDialog_MOVE_UP); fMoveUpButton.setEnabled(false); applyDialogFont(fMoveUpButton); setButtonLayoutData(fMoveUpButton); ((GridData) fMoveUpButton.getLayoutData()).verticalIndent = 10; fMoveUpButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onMove(true); } }); /* Move Filter Down */ fMoveDownButton = new Button(buttonContainer, SWT.PUSH); fMoveDownButton.setText(Messages.NewsFiltersListDialog_MOVE_DOWN); fMoveDownButton.setEnabled(false); applyDialogFont(fMoveDownButton); setButtonLayoutData(fMoveDownButton); fMoveDownButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onMove(false); } }); Composite buttonBar = new Composite(composite, SWT.NONE); buttonBar.setLayout(LayoutUtils.createGridLayout(2, 0, 0)); buttonBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1)); /* Button to apply filter on all News */ fApplySelectedFilter = new Button(buttonBar, SWT.PUSH); fApplySelectedFilter.setText(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER); fApplySelectedFilter.setEnabled(false); applyDialogFont(fApplySelectedFilter); setButtonLayoutData(fApplySelectedFilter); ((GridData) fApplySelectedFilter.getLayoutData()).grabExcessHorizontalSpace = false; ((GridData) fApplySelectedFilter.getLayoutData()).horizontalAlignment = SWT.BEGINNING; fApplySelectedFilter.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { onApplySelectedFilter(); } }); /* Close */ Button closeButton = new Button(buttonBar, SWT.PUSH); closeButton.setText(Messages.NewsFiltersListDialog_CLOSE); applyDialogFont(closeButton); setButtonLayoutData(closeButton); ((GridData) closeButton.getLayoutData()).grabExcessHorizontalSpace = true; ((GridData) closeButton.getLayoutData()).horizontalAlignment = SWT.END; closeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { close(); } }); /* Update Title Message */ updateTitle(); /* Set Selection if provided */ if (fSelectedFilter != null) fViewer.setSelection(new StructuredSelection(fSelectedFilter), true); applyDialogFont(composite); return composite; } private void onApplySelectedFilter() { IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); if (!selection.isEmpty()) { ISearchFilter filter = (ISearchFilter) selection.getFirstElement(); /* Retrieve those actions that are forcable to run */ List<IFilterAction> actions = filter.getActions(); List<IFilterAction> forcableActions = new ArrayList<IFilterAction>(actions.size()); for (IFilterAction action : actions) { NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId()); if (newsActionDescriptor != null && newsActionDescriptor.isForcable()) forcableActions.add(action); } /* Return early if selected Action is not forcable */ if (forcableActions.isEmpty()) { MessageDialog.openWarning(getShell(), NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName()), NLS.bind(Messages.NewsFiltersListDialog_NO_ACTIONS_TO_RUN, filter.getName())); return; } IModelSearch search = Owl.getPersistenceService().getModelSearch(); List<SearchHit<NewsReference>> targetNews = null; /* Search for all Visible News */ Set<State> visibleStates = INews.State.getVisible(); if (filter.getSearch() == null) { ISearchField stateField = Owl.getModelFactory().createSearchField(INews.STATE, INews.class.getName()); ISearchCondition stateCondition = Owl.getModelFactory().createSearchCondition(stateField, SearchSpecifier.IS, EnumSet.of(State.NEW, State.UNREAD, State.UPDATED, State.READ)); targetNews = search.searchNews(Collections.singleton(stateCondition), true); } /* Use Search from Filter */ else { List<SearchHit<NewsReference>> result = search.searchNews(filter.getSearch()); targetNews = new ArrayList<SearchHit<NewsReference>>(result.size()); /* Filter out those that are not visible */ for (SearchHit<NewsReference> resultItem : result) { INews.State state = (State) resultItem.getData(INews.STATE); if (visibleStates.contains(state)) targetNews.add(resultItem); } } /* Return early if there is no matching News */ if (targetNews.isEmpty()) { MessageDialog.openWarning(getShell(), NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName()), NLS.bind(Messages.NewsFiltersListDialog_NO_FILTER_MATCH, filter.getName())); return; } /* Ask for Confirmation */ boolean multipleActions = forcableActions.size() > 1; String title = NLS.bind(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_N, filter.getName()); StringBuilder message = new StringBuilder(); if (multipleActions) message.append(NLS.bind(Messages.NewsFiltersListDialog_PERFORM_ACTIONS, targetNews.size())).append("\n"); //$NON-NLS-1$ else message.append(NLS.bind(Messages.NewsFiltersListDialog_PERFORM_ACTION, targetNews.size())).append("\n"); //$NON-NLS-1$ for (IFilterAction action : forcableActions) { NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId()); String label = newsActionDescriptor.getNewsAction() != null ? newsActionDescriptor.getNewsAction().getLabel(action.getData()) : null; if (StringUtils.isSet(label)) message.append("\n").append(NLS.bind(Messages.NewsFiltersListDialog_FILTER_LIST_ELEMENT, label)); //$NON-NLS-1$ else message.append("\n").append(NLS.bind(Messages.NewsFiltersListDialog_FILTER_LIST_ELEMENT, newsActionDescriptor.getName())); //$NON-NLS-1$ } message.append("\n\n").append(Messages.NewsFiltersListDialog_CONFIRM); //$NON-NLS-1$ ConfirmDialog dialog = new ConfirmDialog(getShell(), title, Messages.NewsFiltersListDialog_NO_UNDO, message.toString(), IDialogConstants.OK_LABEL, null) { @Override protected String getTitleImage() { return "icons/wizban/filter_wiz.png"; //$NON-NLS-1$ } @Override public void setTitle(String newTitle) { super.setTitle(Messages.NewsFiltersListDialog_RUN_SELECTED_FILTER_TITLE); } }; /* Apply Actions in chunks of N Items to avoid Memory issues */ if (dialog.open() == IDialogConstants.OK_ID) { applyFilter(targetNews, filter); } } } private void applyFilter(final List<SearchHit<NewsReference>> news, final ISearchFilter filter) { IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { List<List<SearchHit<NewsReference>>> chunks = CoreUtils.toChunks(news, FILTER_CHUNK_SIZE); monitor.beginTask(NLS.bind(Messages.NewsFiltersListDialog_WAIT_FILTER_APPLIED, filter.getName()), chunks.size()); if (monitor.isCanceled()) return; int counter = 0; for (List<SearchHit<NewsReference>> chunk : chunks) { if (monitor.isCanceled()) return; monitor.subTask(NLS.bind(Messages.NewsFiltersListDialog_FILTERED_N_OF_M_NEWS, (counter * FILTER_CHUNK_SIZE), news.size())); List<INews> newsItemsToFilter = new ArrayList<INews>(FILTER_CHUNK_SIZE); for (SearchHit<NewsReference> chunkItem : chunk) { INews newsItemToFilter = chunkItem.getResult().resolve(); if (newsItemToFilter != null && newsItemToFilter.isVisible()) newsItemsToFilter.add(newsItemToFilter); else CoreUtils.reportIndexIssue(); } applyFilterOnChunks(newsItemsToFilter, filter); monitor.worked(1); counter++; } monitor.done(); } }; /* Show progress and allow for cancellation */ ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()); dialog.setBlockOnOpen(false); dialog.setCancelable(true); dialog.setOpenOnRun(true); try { dialog.run(true, true, runnable); } catch (InvocationTargetException e) { Activator.getDefault().logError(e.getMessage(), e); } catch (InterruptedException e) { Activator.getDefault().logError(e.getMessage(), e); } } private void applyFilterOnChunks(final List<INews> news, ISearchFilter filter) { Collection<IFilterAction> actions = CoreUtils.getActions(filter); //Need to sort structural actions to end final Set<IEntity> entitiesToSave = new HashSet<IEntity>(news.size()); final Map<INews, INews> replacements = new HashMap<INews, INews>(); for (final IFilterAction action : actions) { NewsActionDescriptor newsActionDescriptor = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId()); if (newsActionDescriptor != null && newsActionDescriptor.isForcable()) { final INewsAction newsAction = newsActionDescriptor.getNewsAction(); if (newsAction != null) { SafeRunnable.run(new ISafeRunnable() { public void handleException(Throwable e) { Activator.getDefault().logError(e.getMessage(), e); } public void run() throws Exception { List<IEntity> changedEntities = newsAction.run(news, replacements, action.getData()); entitiesToSave.addAll(changedEntities); } }); } } } /* Make sure that changed entities are saved for all actions */ if (!entitiesToSave.isEmpty()) DynamicDAO.saveAll(entitiesToSave); } private void updateTitle() { ISearchFilter problematicFilter = null; Table table = fViewer.getTable(); TableItem[] items = table.getItems(); for (TableItem item : items) { ISearchFilter filter = (ISearchFilter) item.getData(); if (filter.getSearch() == null && filter.isEnabled()) { int index = table.indexOf(item); if (index < table.getItemCount() - 1) { problematicFilter = filter; break; } } } if (problematicFilter != null) setMessage(NLS.bind(Messages.NewsFiltersListDialog_FILTER_MATCHES_ALL_NEWS, problematicFilter.getName()), IMessageProvider.WARNING); else setMessage(Messages.NewsFiltersListDialog_ENABLED_FILTERS, IMessageProvider.INFORMATION); } /* * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite) */ @Override protected Control createButtonBar(Composite parent) { return null; } private void updateMoveEnablement() { boolean enableMoveUp = true; boolean enableMoveDown = true; int[] selectionIndices = fViewer.getTable().getSelectionIndices(); if (selectionIndices.length == 1) { enableMoveUp = selectionIndices[0] != 0; enableMoveDown = selectionIndices[0] != fViewer.getTable().getItemCount() - 1; } else { enableMoveUp = false; enableMoveDown = false; } fMoveUpButton.setEnabled(enableMoveUp); fMoveDownButton.setEnabled(enableMoveDown); } private void onMove(boolean up) { TableItem[] items = fViewer.getTable().getItems(); List<ISearchFilter> sortedFilters = new ArrayList<ISearchFilter>(items.length); for (TableItem item : items) { sortedFilters.add((ISearchFilter) item.getData()); } IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); ISearchFilter selectedFilter = (ISearchFilter) selection.getFirstElement(); int selectedFilterOrder = selectedFilter.getOrder(); ISearchFilter otherFilter = null; int index = sortedFilters.indexOf(selectedFilter); /* Move Up */ if (up && index > 0) { otherFilter = sortedFilters.get(index - 1); selectedFilter.setOrder(otherFilter.getOrder()); otherFilter.setOrder(selectedFilterOrder); } /* Move Down */ else if (!up && index < sortedFilters.size() - 1) { otherFilter = sortedFilters.get(index + 1); selectedFilter.setOrder(otherFilter.getOrder()); otherFilter.setOrder(selectedFilterOrder); } fSearchFilterDao.saveAll(Arrays.asList(new ISearchFilter[] { selectedFilter, otherFilter })); fViewer.refresh(); fViewer.getTable().showSelection(); updateCheckedState(); updateMoveEnablement(); updateTitle(); } private void updateCheckedState() { TableItem[] items = fViewer.getTable().getItems(); for (TableItem item : items) { ISearchFilter filter = (ISearchFilter) item.getData(); fViewer.setChecked(filter, filter.isEnabled()); } } private void onAdd() { NewsFilterDialog dialog = new NewsFilterDialog(getShell()); Table table = fViewer.getTable(); dialog.setFilterPosition(table.getItemCount()); if (dialog.open() == IDialogConstants.OK_ID) { fViewer.refresh(); updateCheckedState(); fViewer.setSelection(new StructuredSelection(table.getItem(table.getItemCount() - 1).getData())); fViewer.getTable().setFocus(); updateTitle(); } } private void onEdit() { IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); ISearchFilter filter = (ISearchFilter) selection.getFirstElement(); NewsFilterDialog dialog = new NewsFilterDialog(getShell(), filter); if (dialog.open() == IDialogConstants.OK_ID) { fViewer.refresh(true); fViewer.getTable().setFocus(); updateTitle(); } } private void onDelete() { IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection(); List<?> selectedFilters = selection.toList(); ConfirmDialog dialog = new ConfirmDialog(getShell(), Messages.NewsFiltersListDialog_CONFIRM_DELETE, Messages.NewsFiltersListDialog_NO_UNDO, getMessage(selectedFilters), null); if (dialog.open() == IDialogConstants.OK_ID) { List<ISearchFilter> filtersToDelete = new ArrayList<ISearchFilter>(selectedFilters.size()); for (Iterator<?> iterator = selectedFilters.iterator(); iterator.hasNext();) { ISearchFilter filter = (ISearchFilter) iterator.next(); filtersToDelete.add(filter); } fSearchFilterDao.deleteAll(filtersToDelete); fViewer.remove(selection.toArray()); fixOrderAfterDelete(); updateTitle(); } } /* Ensure that after Delete, the orders are in sync again */ private void fixOrderAfterDelete() { List<ISearchFilter> filtersToSave = new ArrayList<ISearchFilter>(); TableItem[] items = fViewer.getTable().getItems(); for (int i = 0; i < items.length; i++) { TableItem item = items[i]; ISearchFilter filter = (ISearchFilter) item.getData(); filter.setOrder(i); filtersToSave.add(filter); } DynamicDAO.saveAll(filtersToSave); } private String getMessage(List<?> elements) { StringBuilder message = new StringBuilder(); /* One Element */ if (elements.size() == 1) { ISearchFilter filter = (ISearchFilter) elements.get(0); message.append(NLS.bind(Messages.NewsFiltersListDialog_CONFIRM_DELETE_FILTER_N, filter.getName())); } /* N Elements */ else { message.append(Messages.NewsFiltersListDialog_CONFIRM_DELETE_FILTERS); } return message.toString(); } /* * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ @Override protected void configureShell(Shell shell) { super.configureShell(shell); shell.setText(Messages.NewsFiltersListDialog_NEWS_FILTERS); } /** * @param filter the {@link ISearchFilter} to select. */ public void setSelection(ISearchFilter filter) { fSelectedFilter = filter; if (fViewer != null) fViewer.setSelection(new StructuredSelection(fSelectedFilter), true); } /** * Refresh the list of displayed Filters. */ public void refresh() { if (fViewer != null) { fViewer.refresh(); updateCheckedState(); } } /* * @see org.eclipse.jface.dialogs.Dialog#isResizable() */ @Override protected boolean isResizable() { return true; } /* * @see org.eclipse.jface.window.Window#getShellStyle() */ @Override protected int getShellStyle() { int style = SWT.TITLE | SWT.BORDER | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | getDefaultOrientation(); return style; } /* * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsStrategy() */ @Override protected int getDialogBoundsStrategy() { return DIALOG_PERSISTSIZE; } /* * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings() */ @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings settings = Activator.getDefault().getDialogSettings(); IDialogSettings section = settings.getSection(SETTINGS_SECTION); if (section != null) return section; return settings.addNewSection(SETTINGS_SECTION); } }