Package org.rssowl.ui.internal.dialogs

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

/*   **********************************************************************  **
**   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.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
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.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.newsaction.MoveNewsAction;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IFilterAction;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.ISearch;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.Pair;
import org.rssowl.core.util.StringUtils;
import org.rssowl.ui.internal.Activator;
import org.rssowl.ui.internal.ContextMenuCreator;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.filter.NewsActionDescriptor;
import org.rssowl.ui.internal.filter.NewsActionList;
import org.rssowl.ui.internal.filter.NewsActionPresentationManager;
import org.rssowl.ui.internal.search.LocationControl;
import org.rssowl.ui.internal.search.SearchConditionList;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.LayoutUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
* A dialog to add and update a news filter with search conditions and actions.
*
* @author bpasero
*/
public class NewsFilterDialog extends TitleAreaDialog {

  /* Section for Dialogs Settings */
  private static final String SETTINGS_SECTION = "org.rssowl.ui.internal.dialogs.NewsFilterDialog"; //$NON-NLS-1$

  /* Action Searches */
  private static final String SEARCHES_ACTION = "org.rssowl.ui.internal.dialogs.filter.SearchesAction"; //$NON-NLS-1$

  /* Action Filters */
  private static final String FILTERS_ACTION = "org.rssowl.ui.internal.dialogs.filter.FiltersAction"; //$NON-NLS-1$

  private LocalResourceManager fResources;
  private final ISearchFilter fEditedFilter;
  private final List<Integer> fExcludedConditions = getExcludedConditions();
  private LocationControl fLocationControl;
  private SearchConditionList fSearchConditionList;
  private NewsActionPresentationManager fNewsActionPresentationManager = NewsActionPresentationManager.getInstance();
  private Button fMatchAllRadio;
  private Button fMatchAnyRadio;
  private Button fMatchAllNewsRadio;
  private NewsActionList fFilterActionList;
  private Text fNameInput;
  private int fFilterPosition;
  private ISearch fPresetSearch;
  private boolean fPresetMatchAll;
  private List<IFilterAction> fPresetActions;
  private ISearchFilter fAddedFilter;

  /**
   * @param parentShell the Shell to create this Dialog on.
   */
  public NewsFilterDialog(Shell parentShell) {
    this(parentShell, (ISearchFilter) null);
  }

  /**
   * @param parentShell the Shell to create this Dialog on.
   * @param filter the {@link ISearchFilter} to edit or <code>null</code> if
   * none.
   */
  public NewsFilterDialog(Shell parentShell, ISearchFilter filter) {
    super(parentShell);

    fEditedFilter = filter;
    fResources = new LocalResourceManager(JFaceResources.getResources());
  }

  /**
   * @param parentShell the Shell to create this Dialog on.
   * @param presetSearch a search that is preset in the condition area.
   */
  public NewsFilterDialog(Shell parentShell, ISearch presetSearch) {
    this(parentShell, presetSearch, null, false);
  }

  /**
   * @param parentShell the Shell to create this Dialog on.
   * @param presetSearch a search that is preset in the condition area.
   * @param presetActions a list of {@link IFilterAction} that is preset
   * @param matchAll <code>true</code> to all news or <code>false</code>
   * otherwise.
   */
  public NewsFilterDialog(Shell parentShell, ISearch presetSearch, List<IFilterAction> presetActions, boolean matchAll) {
    super(parentShell);

    fPresetSearch = presetSearch;
    fPresetActions = presetActions;
    fPresetMatchAll = matchAll;
    fEditedFilter = null;
    fResources = new LocalResourceManager(JFaceResources.getResources());
  }

  /**
   * @param filterPosition the sort order for the resulting news filter.
   */
  public void setFilterPosition(int filterPosition) {
    fFilterPosition = filterPosition;
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#okPressed()
   */
  @Override
  protected void okPressed() {

    /* Generate Name if necessary */
    if (!StringUtils.isSet(fNameInput.getText()))
      onGenerateName();

    /* Ensure that a Search Condition is specified if required */
    if (fSearchConditionList.isEmpty() && !fMatchAllNewsRadio.getSelection()) {
      setErrorMessage(Messages.NewsFilterDialog_ENTER_CONDITION);
      fSearchConditionList.focusInput();
      return;
    }

    /* Ensure that an Action is specified */
    if (fFilterActionList.isEmpty()) {
      setErrorMessage(Messages.NewsFilterDialog_CHOOSE_ACTION);
      fFilterActionList.focusInput();
      return;
    }

    /* Ensure that Actions are not conflicting */
    List<IFilterAction> actions = fFilterActionList.createActions();
    if (isConflicting(actions))
      return;

    /* Create new Filter and save */
    if (fEditedFilter == null) {
      fAddedFilter = createFilter(actions);
      DynamicDAO.save(fAddedFilter);
    }

    /* Update existing Filter */
    else {
      updateFilter(actions);
      DynamicDAO.save(fEditedFilter);
    }

    super.okPressed();
  }

  /**
   * @return the {@link ISearchFilter} that was added or updated.
   */
  public ISearchFilter getFilter() {
    return fEditedFilter != null ? fEditedFilter : fAddedFilter;
  }

  private ISearchFilter createFilter(List<IFilterAction> actions) {
    IModelFactory factory = Owl.getModelFactory();
    ISearch search = createSearch();

    /* Create Actions */
    ISearchFilter filter = factory.createSearchFilter(null, search, fNameInput.getText());
    filter.setEnabled(true);
    filter.setMatchAllNews(fMatchAllNewsRadio.getSelection());
    filter.setOrder(fFilterPosition);
    for (IFilterAction action : actions) {
      filter.addAction(action);
    }

    return filter;
  }

  private ISearch createSearch() {
    IModelFactory factory = Owl.getModelFactory();
    ISearch search = null;
    ISearchCondition locationCondition = fLocationControl.toScopeCondition();

    /* Only use Location Condition */
    if (locationCondition != null && fMatchAllNewsRadio.getSelection()) {
      search = factory.createSearch(null);
      search.addSearchCondition(locationCondition);
    }

    /* Build Conditions from Location and List */
    else if (!fMatchAllNewsRadio.getSelection()) {
      List<ISearchCondition> conditions = fSearchConditionList.createConditions();
      if (locationCondition != null)
        conditions.add(locationCondition);
      search = factory.createSearch(null);
      search.setMatchAllConditions(fMatchAllRadio.getSelection());
      for (ISearchCondition condition : conditions) {
        search.addSearchCondition(condition);
      }
    }

    return search;
  }

  private void updateFilter(List<IFilterAction> actions) {

    /* Name */
    fEditedFilter.setName(fNameInput.getText());

    /* Actions */
    if (fFilterActionList.isModified()) {

      /* Remove Old Actions */
      List<IFilterAction> oldActions = fEditedFilter.getActions();
      for (IFilterAction oldAction : oldActions) {
        fEditedFilter.removeAction(oldAction);
      }

      /* Add New Actions */
      for (IFilterAction action : actions) {
        fEditedFilter.addAction(action);
      }
    }

    /* Update Conditioner */
    fEditedFilter.setMatchAllNews(fMatchAllNewsRadio.getSelection());

    /* Update Search */
    ISearch oldSearch = fEditedFilter.getSearch();
    fEditedFilter.setSearch(createSearch());
    if (oldSearch != null)
      DynamicDAO.delete(oldSearch);
  }

  private boolean isConflicting(List<IFilterAction> actions) {
    for (IFilterAction action : actions) {
      NewsActionDescriptor newsAction = fNewsActionPresentationManager.getNewsActionDescriptor(action.getActionId());
      for (IFilterAction otherAction : actions) {
        if (action == otherAction)
          continue;

        NewsActionDescriptor otherNewsAction = fNewsActionPresentationManager.getNewsActionDescriptor(otherAction.getActionId());
        if (otherNewsAction.getNewsAction().conflictsWith(newsAction.getNewsAction())) {
          StringBuilder str = new StringBuilder();
          str.append(NLS.bind(Messages.NewsFilterDialog_REMOVE_ACTION_N, otherNewsAction.getName(), newsAction.getName()));

          setErrorMessage(str.toString());
          return true;
        }
      }
    }

    return false;
  }

  /*
   * @see org.eclipse.jface.dialogs.TrayDialog#close()
   */
  @Override
  public boolean close() {
    boolean res = super.close();
    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.NewsFilterDialog_NEWS_FILTER);

    /* Title Image */
    setTitleImage(OwlUI.getImage(fResources, "icons/wizban/filter_wiz.png")); //$NON-NLS-1$

    /* Title Message */
    setMessage(Messages.NewsFilterDialog_DEFINE_SEARCH);

    /* Name Input Filed */
    Composite container = new Composite(parent, SWT.None);
    container.setLayout(LayoutUtils.createGridLayout(2, 10, 5, 0, 5, false));
    container.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

    Label nameLabel = new Label(container, SWT.NONE);
    nameLabel.setText(Messages.NewsFilterDialog_NAME);

    Composite nameContainer = new Composite(container, SWT.BORDER);
    nameContainer.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    nameContainer.setLayout(LayoutUtils.createGridLayout(2, 0, 0));
    nameContainer.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    fNameInput = new Text(nameContainer, SWT.SINGLE);
    OwlUI.makeAccessible(fNameInput, nameLabel);
    fNameInput.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    if (fEditedFilter != null) {
      fNameInput.setText(fEditedFilter.getName());
      fNameInput.selectAll();
    }

    fNameInput.addModifyListener(new ModifyListener() {
      public void modifyText(ModifyEvent e) {
        setErrorMessage(null);
      }
    });

    GC gc = new GC(fNameInput);
    gc.setFont(JFaceResources.getDialogFont());
    FontMetrics fontMetrics = gc.getFontMetrics();
    int entryFieldWidth = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.ENTRY_FIELD_WIDTH);
    gc.dispose();

    ((GridData) fNameInput.getLayoutData()).widthHint = entryFieldWidth; //Required to avoid large spanning dialog for long Links

    ToolBar generateTitleBar = new ToolBar(nameContainer, SWT.FLAT);
    OwlUI.makeAccessible(generateTitleBar, Messages.NewsFilterDialog_CREATE_NAME_FROM_CONDITIONS);
    generateTitleBar.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

    ToolItem generateTitleItem = new ToolItem(generateTitleBar, SWT.PUSH);
    generateTitleItem.setImage(OwlUI.getImage(fResources, "icons/etool16/info.gif")); //$NON-NLS-1$
    generateTitleItem.setToolTipText(Messages.NewsFilterDialog_CREATE_NAME_FROM_CONDITIONS);
    generateTitleItem.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onGenerateName();
      }
    });

    /* Sashform dividing search definition from actions */
    SashForm sashForm = new SashForm(parent, SWT.VERTICAL | SWT.SMOOTH);
    sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    /* Top Sash */
    Composite topSash = new Composite(sashForm, SWT.NONE);
    topSash.setLayout(LayoutUtils.createGridLayout(2, 0, 0, 0, 0, false));
    createConditionControls(topSash);

    /* Bottom Sash */
    Composite bottomSash = new Composite(sashForm, SWT.NONE);
    bottomSash.setLayout(LayoutUtils.createGridLayout(1, 0, 0, 0, 0, false));

    /* Label in between */
    Composite labelContainer = new Composite(bottomSash, SWT.NONE);
    labelContainer.setLayout(LayoutUtils.createGridLayout(1, 10, 3, 0, 0, false));
    ((GridLayout) labelContainer.getLayout()).marginBottom = 2;
    labelContainer.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    Label explanationLabel = new Label(labelContainer, SWT.NONE);
    explanationLabel.setText(Messages.NewsFilterDialog_PERFORM_ACTIONS);

    /* Action Controls */
    createActionControls(bottomSash);

    /* Separator */
    new Label(bottomSash, SWT.SEPARATOR | SWT.HORIZONTAL).setLayoutData(new GridData(SWT.FILL, SWT.END, true, false));

    /* Set weights to even */
    sashForm.setWeights(new int[] { 50, 50 });

    applyDialogFont(parent);

    return parent;
  }

  /*
   * @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
   */
  @Override
  protected Control createButtonBar(Composite parent) {
    GridLayout layout = new GridLayout(1, false);
    layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
    layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
    layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
    layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);

    Composite buttonBar = new Composite(parent, SWT.NONE);
    buttonBar.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
    buttonBar.setLayout(layout);

    /* Preview Link */
    Link previewLink = new Link(buttonBar, SWT.NONE);
    previewLink.setText(Messages.NewsFilterDialog_PREVIEW_SEARCH);
    applyDialogFont(previewLink);
    previewLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    previewLink.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        onPreview();
      }
    });

    /* Create Buttons */
    createButtonsForButtonBar(buttonBar);

    return buttonBar;
  }

  private void onPreview() {
    final List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

    /* Create Condition from Scope */
    if (fMatchAllNewsRadio.getSelection()) {
      ISearchCondition locationCondition = fLocationControl.toScopeCondition();
      if (locationCondition != null) {
        locationCondition.setSpecifier(SearchSpecifier.IS);
        conditions.add(locationCondition);
      }
    }

    /* Create Conditions from List */
    else {
      conditions.addAll(fSearchConditionList.createConditions());
      if (!conditions.isEmpty()) {
        ISearchCondition locationCondition = fLocationControl.toScopeCondition();
        if (locationCondition != null)
          conditions.add(locationCondition);
      }
    }

    /* Show if conditions are present */
    if (!conditions.isEmpty()) {
      JobRunner.runInUIThread(getShell(), new Runnable() {
        public void run() {
          SearchNewsDialog dialog = new SearchNewsDialog(getShell(), conditions, fMatchAllRadio.getSelection(), true);
          dialog.setBlockOnOpen(false);
          dialog.open();
        }
      });
    }
  }

  void onGenerateName() {
    String name;
    ISearchCondition locationCondition = fLocationControl.toScopeCondition();
    if (fMatchAllNewsRadio.getSelection() && locationCondition == null) {
      name = Messages.NewsFilterDialog_ALL_NEWS;
    } else {
      List<ISearchCondition> conditions = fSearchConditionList.createConditions();
      if (locationCondition != null)
        conditions.add(locationCondition);
      name = CoreUtils.getName(conditions, fMatchAllRadio.getSelection());
    }

    if (name.length() > 0) {
      fNameInput.setText(name);
      fNameInput.selectAll();
    }
  }

  private void createConditionControls(Composite container) {
    Composite topControlsContainer = new Composite(container, SWT.None);
    topControlsContainer.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
    topControlsContainer.setLayout(LayoutUtils.createGridLayout(6, 10, 3));

    boolean matchAllNews = (fEditedFilter != null) ? fEditedFilter.matchAllNews() : fPresetMatchAll;
    boolean matchAllConditions = !matchAllNews && (fEditedFilter != null) ? fEditedFilter.getSearch().matchAllConditions() : true;

    if (fPresetSearch != null)
      matchAllConditions = fPresetSearch.matchAllConditions();

    /* Radio to select Condition Matching */
    fMatchAllRadio = new Button(topControlsContainer, SWT.RADIO);
    fMatchAllRadio.setText(Messages.NewsFilterDialog_MATCH_ALL_CONDITIONS);
    fMatchAllRadio.setSelection(matchAllConditions && !matchAllNews);

    fMatchAnyRadio = new Button(topControlsContainer, SWT.RADIO);
    fMatchAnyRadio.setText(Messages.NewsFilterDialog_MATCH_ANY_CONDITION);
    fMatchAnyRadio.setSelection(!matchAllConditions && !matchAllNews);

    fMatchAllNewsRadio = new Button(topControlsContainer, SWT.RADIO);
    fMatchAllNewsRadio.setText(Messages.NewsFilterDialog_MATCH_ALL);
    fMatchAllNewsRadio.setSelection(matchAllNews);
    fMatchAllNewsRadio.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        setControlEnabled(fSearchConditionList, !fMatchAllNewsRadio.getSelection());
      }
    });

    /* Separator */
    Label sep = new Label(topControlsContainer, SWT.SEPARATOR | SWT.VERTICAL);
    sep.setLayoutData(new GridData(SWT.DEFAULT, 20));

    /* Scope */
    Composite scopeContainer = new Composite(topControlsContainer, SWT.None);
    scopeContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    scopeContainer.setLayout(LayoutUtils.createGridLayout(2, 0, 0, 0, 5, false));

    Label locationLabel = new Label(scopeContainer, SWT.NONE);
    locationLabel.setText(Messages.NewsFilterDialog_IN);

    fLocationControl = new LocationControl(scopeContainer, SWT.WRAP) {
      @Override
      protected String getDefaultLabel() {
        return Messages.NewsFilterDialog_ALL_NEWS;
      }
    };
    fLocationControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
    ((GridData) fLocationControl.getLayoutData()).widthHint = 100;
    fLocationControl.setLayout(LayoutUtils.createGridLayout(1, 0, 0, 0, 0, false));

    /* ToolBar to add and select existing saved searches */
    final ToolBarManager dialogToolBar = new ToolBarManager(SWT.RIGHT | SWT.FLAT);

    /* Separator */
    dialogToolBar.add(new Separator());

    /* Existing Filters */
    {
      IAction existingFilters = new Action(Messages.NewsFilterDialog_SHOW_NEWS_FILTER, IAction.AS_DROP_DOWN_MENU) {
        @Override
        public void run() {
          OwlUI.positionDropDownMenu(this, dialogToolBar);
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
          return OwlUI.FILTER;
        }

        @Override
        public String getId() {
          return FILTERS_ACTION;
        }
      };

      existingFilters.setMenuCreator(new ContextMenuCreator() {

        @Override
        public Menu createMenu(Control parent) {
          Collection<ISearchFilter> filters = CoreUtils.loadSortedNewsFilters();
          Menu menu = new Menu(parent);

          /* Show Something if Collection is Empty */
          if (filters.isEmpty()) {
            MenuItem item = new MenuItem(menu, SWT.None);
            item.setText(Messages.NewsFilterDialog_NO_FILTER);
            item.setEnabled(false);
          }

          /* Show Existing News Filters */
          for (final ISearchFilter filter : filters) {
            MenuItem item = new MenuItem(menu, SWT.None);
            item.setText(filter.getName());
            item.setImage(OwlUI.getImage(fResources, OwlUI.FILTER));
            item.addSelectionListener(new SelectionAdapter() {

              @Override
              public void widgetSelected(SelectionEvent e) {

                /* Search */
                if (filter.getSearch() != null)
                  showSearch(filter.getSearch());

                /* Match All News */
                if (filter.matchAllNews()) {
                  fMatchAnyRadio.setSelection(false);
                  fMatchAllRadio.setSelection(false);
                  fMatchAllNewsRadio.setSelection(true);
                  setControlEnabled(fSearchConditionList, false);
                }

                /* Actions */
                fFilterActionList.showActions(filter.getActions());
              }
            });
          }

          return menu;
        }
      });

      dialogToolBar.add(existingFilters);
    }

    /* Existing Saved Searches */
    {
      IAction savedSearches = new Action(Messages.NewsFilterDialog_SHOW_SAVED_SEARCH, IAction.AS_DROP_DOWN_MENU) {
        @Override
        public void run() {
          OwlUI.positionDropDownMenu(this, dialogToolBar);
        }

        @Override
        public ImageDescriptor getImageDescriptor() {
          return OwlUI.SEARCHMARK;
        }

        @Override
        public String getId() {
          return SEARCHES_ACTION;
        }
      };

      savedSearches.setMenuCreator(new ContextMenuCreator() {

        @Override
        public Menu createMenu(Control parent) {
          Collection<ISearchMark> searchMarks = CoreUtils.loadSortedSearchMarks();
          Menu menu = new Menu(parent);

          /* Show Something if Collection is Empty */
          if (searchMarks.isEmpty()) {
            MenuItem item = new MenuItem(menu, SWT.None);
            item.setText(Messages.NewsFilterDialog_NO_SAVED_SEARCH);
            item.setEnabled(false);
          }

          /* Show Existing Saved Searches */
          for (final ISearchMark searchMark : searchMarks) {
            if (isSupported(searchMark)) {
              MenuItem item = new MenuItem(menu, SWT.None);
              item.setText(searchMark.getName());
              item.setImage(OwlUI.getImage(fResources, OwlUI.SEARCHMARK));
              item.addSelectionListener(new SelectionAdapter() {

                @Override
                public void widgetSelected(SelectionEvent e) {
                  showSearch(searchMark);
                }
              });
            }
          }

          return menu;
        }
      });

      dialogToolBar.add(savedSearches);
    }

    dialogToolBar.createControl(topControlsContainer);
    dialogToolBar.getControl().setLayoutData(new GridData(SWT.END, SWT.BEGINNING, true, false));

    /* Container for Conditions */
    final Composite conditionsContainer = new Composite(container, SWT.NONE);
    conditionsContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    conditionsContainer.setLayout(LayoutUtils.createGridLayout(2, 5, 10));
    conditionsContainer.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
    conditionsContainer.setBackgroundMode(SWT.INHERIT_FORCE);
    conditionsContainer.addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent e) {
        GC gc = e.gc;
        Rectangle clArea = conditionsContainer.getClientArea();
        gc.setForeground(conditionsContainer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
        gc.drawLine(clArea.x, clArea.y, clArea.x + clArea.width, clArea.y);
        gc.drawLine(clArea.x, clArea.y + clArea.height - 1, clArea.x + clArea.width, clArea.y + clArea.height - 1);
      }
    });

    /* Search Conditions List */
    fSearchConditionList = new SearchConditionList(conditionsContainer, SWT.None, getDefaultConditions(), fExcludedConditions);
    fSearchConditionList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    fSearchConditionList.setVisibleItemCount(3);

    /* Show Initial Conditions if present */
    List<ISearchCondition> initialConditions = null;
    if (fEditedFilter != null && fEditedFilter.getSearch() != null)
      initialConditions = fEditedFilter.getSearch().getSearchConditions();
    else if (fPresetSearch != null)
      initialConditions = fPresetSearch.getSearchConditions();

    if (initialConditions != null) {
      Pair<ISearchCondition, List<ISearchCondition>> conditions = CoreUtils.splitScope(initialConditions);
      Long[][] locationValue = null;
      if (conditions.getFirst() != null && conditions.getFirst().getValue() instanceof Long[][])
        locationValue = (Long[][]) conditions.getFirst().getValue();

      fLocationControl.select(locationValue);

      if (!conditions.getSecond().isEmpty())
        fSearchConditionList.showConditions(conditions.getSecond());

      if (CoreUtils.isLocationConflict(initialConditions))
        setMessage(Messages.NewsFilterDialog_LOCATION_IN_WARNING, IMessageProvider.WARNING);
    }

    /* Update Enable-State of Search Condition List */
    setControlEnabled(fSearchConditionList, !fMatchAllNewsRadio.getSelection());

    /* Generate Name if preset */
    if (fPresetSearch != null)
      onGenerateName();
  }

  /* Load a search into the UI */
  private void showSearch(ISearch search) {

    /* Match Conditions */
    fMatchAllRadio.setSelection(search.matchAllConditions());
    fMatchAnyRadio.setSelection(!search.matchAllConditions());
    fMatchAllNewsRadio.setSelection(false);
    setControlEnabled(fSearchConditionList, true);

    /* Location */
    Pair<ISearchCondition, List<ISearchCondition>> conditions = CoreUtils.splitScope(search.getSearchConditions());
    Long[][] location = null;
    if (conditions.getFirst() != null && conditions.getFirst().getValue() instanceof Long[][])
      location = (Long[][]) conditions.getFirst().getValue();
    fLocationControl.select(location);

    /* Show Conditions */
    fSearchConditionList.showConditions(conditions.getSecond());

    /* Layout */
    fLocationControl.getParent().getParent().getParent().layout(true, true);
  }

  private void setControlEnabled(Control control, boolean enabled) {
    control.setEnabled(enabled);
    if (control instanceof Composite) {
      Composite composite = (Composite) control;
      Control[] children = composite.getChildren();
      for (Control child : children) {
        setControlEnabled(child, enabled);
      }
    }
  }

  private boolean isSupported(ISearchMark searchmark) {
    List<ISearchCondition> conditions = searchmark.getSearchConditions();
    for (ISearchCondition condition : conditions) {
      if (fExcludedConditions.contains(condition.getField().getId()))
        return false;
    }

    return true;
  }

  /* We allow all conditions because a filter could also be run on existing news! */
  private List<Integer> getExcludedConditions() {
    return Collections.emptyList();
  }

  private List<ISearchCondition> getDefaultConditions() {
    List<ISearchCondition> conditions = new ArrayList<ISearchCondition>(1);
    IModelFactory factory = Owl.getModelFactory();

    ISearchField field = factory.createSearchField(IEntity.ALL_FIELDS, INews.class.getName());
    ISearchCondition condition = factory.createSearchCondition(field, SearchSpecifier.CONTAINS_ALL, ""); //$NON-NLS-1$

    conditions.add(condition);

    return conditions;
  }

  private void createActionControls(Composite container) {

    /* Container for Actions */
    final Composite actionsContainer = new Composite(container, SWT.NONE);
    actionsContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    actionsContainer.setLayout(LayoutUtils.createGridLayout(2, 5, 10));
    actionsContainer.setBackground(container.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
    actionsContainer.setBackgroundMode(SWT.INHERIT_FORCE);
    actionsContainer.addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent e) {
        GC gc = e.gc;
        Rectangle clArea = actionsContainer.getClientArea();
        gc.setForeground(actionsContainer.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
        gc.drawLine(clArea.x, clArea.y, clArea.x + clArea.width, clArea.y);
      }
    });

    /* Action List */
    fFilterActionList = new NewsActionList(actionsContainer, SWT.NONE, getDefaultActions());
    fFilterActionList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
    fFilterActionList.setVisibleItemCount(3);

    /* Show initial Actions if present */
    if (fEditedFilter != null)
      fFilterActionList.showActions(fEditedFilter.getActions());
    else if (fPresetActions != null)
      fFilterActionList.showActions(fPresetActions);
  }

  private List<IFilterAction> getDefaultActions() {
    List<IFilterAction> defaultActions = new ArrayList<IFilterAction>(1);

    IModelFactory factory = Owl.getModelFactory();
    defaultActions.add(factory.createFilterAction(MoveNewsAction.ID));

    return defaultActions;
  }

  /*
   * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
   */
  @Override
  protected void configureShell(Shell shell) {
    super.configureShell(shell);
    if (fEditedFilter == null)
      shell.setText(Messages.NewsFilterDialog_NEW_FILTER);
    else
      shell.setText(NLS.bind(Messages.NewsFilterDialog_EDIT_NEWS_FILTER_N, fEditedFilter.getName()));
  }

  /*
   * @see org.eclipse.jface.dialogs.Dialog#isResizable()
   */
  @Override
  protected boolean isResizable() {
    return true;
  }

  /*
   * @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.NewsFilterDialog

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.