Package org.rssowl.ui.internal.dialogs

Source Code of org.rssowl.ui.internal.dialogs.NewsFiltersListDialog

/*   **********************************************************************  **
**   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.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.INews.State;
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.CTable;
import org.rssowl.ui.internal.util.LayoutUtils;
import org.rssowl.ui.internal.util.CColumnLayoutData.Size;

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 = toChunks(FILTER_CHUNK_SIZE, news);
        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)
              newsItemsToFilter.add(newsItemToFilter);
          }

          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 List<List<SearchHit<NewsReference>>> toChunks(int size, List<SearchHit<NewsReference>> list) {
    List<List<SearchHit<NewsReference>>> chunkList = new ArrayList<List<SearchHit<NewsReference>>>();
    List<SearchHit<NewsReference>> currentChunk = new ArrayList<SearchHit<NewsReference>>(size);
    chunkList.add(currentChunk);

    int counter = 0;
    for (SearchHit<NewsReference> entry : list) {
      currentChunk.add(entry);
      counter++;
      if (counter % size == 0) {
        currentChunk = new ArrayList<SearchHit<NewsReference>>(size);
        chunkList.add(currentChunk);
      }
    }

    if (currentChunk.isEmpty())
      chunkList.remove(currentChunk);

    return chunkList;
  }

  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);
  }
}
TOP

Related Classes of org.rssowl.ui.internal.dialogs.NewsFiltersListDialog

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.