Package org.eclipse.ui.internal.activities.ws

Source Code of org.eclipse.ui.internal.activities.ws.ActivityEnabler

/*******************************************************************************
* Copyright (c) 2003, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.activities.ws;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
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.Point;
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.Text;
import org.eclipse.ui.activities.ActivitiesPreferencePage;
import org.eclipse.ui.activities.IActivity;
import org.eclipse.ui.activities.ICategory;
import org.eclipse.ui.activities.ICategoryActivityBinding;
import org.eclipse.ui.activities.IMutableActivityManager;
import org.eclipse.ui.activities.NotDefinedException;

/**
* A simple control provider that will allow the user to toggle on/off the
* activities bound to categories.
*
* @since 3.0
*/
public class ActivityEnabler {

  private static final int ALL = 2;

  private static final int NONE = 0;

  private static final int SOME = 1;

  private ISelectionChangedListener selectionListener = new ISelectionChangedListener() {

    /*
     * (non-Javadoc)
     *
     * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
     */
    public void selectionChanged(SelectionChangedEvent event) {
      Object element = ((IStructuredSelection) event.getSelection())
          .getFirstElement();
      try {
        if (element instanceof ICategory) {
          descriptionText.setText(((ICategory) element)
              .getDescription());
        } else if (element instanceof IActivity) {
          descriptionText.setText(((IActivity) element)
              .getDescription());
        }
      } catch (NotDefinedException e) {
        descriptionText.setText(""); //$NON-NLS-1$
      }
    }
  };

  /**
   * Listener that manages the grey/check state of categories.
   */
  private ICheckStateListener checkListener = new ICheckStateListener() {

    /*
     * (non-Javadoc)
     *
     * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
     */
    public void checkStateChanged(CheckStateChangedEvent event) {
      Set checked = new HashSet(Arrays.asList(dualViewer
          .getCheckedElements()));
      Object element = event.getElement();
      if (element instanceof ICategory) {
        // clicking on a category should enable/disable all activities
        // within it
        dualViewer.setSubtreeChecked(element, event.getChecked());
        // the state of the category is always absolute after clicking
        // on it. Never gray.
        dualViewer.setGrayed(element, false);
        Object categoryActivities[] = provider.getChildren(element);
        // Update the category's activities for multiplicity in other
        // categories
        for (int index = 0; index < categoryActivities.length; index++) {
          handleDuplicateActivities(event.getChecked(),
              categoryActivities[index]);
        }

      } else {
        // Activity checked
        handleActivityCheck(checked, element);
        handleDuplicateActivities(event.getChecked(), element);
      }
    }

    /**
     * Handle duplicate activities.
     *
     * @param checkedState
     *            Checked state of the element.
     * @param element
     *            The checked element.
     */
    private void handleDuplicateActivities(boolean checkedState,
        Object element) {
      // Retrieve duplicate activities from the other categories
      Object[] duplicateActivities = provider
          .getDuplicateCategoryActivities((CategorizedActivity) element);
      CategorizedActivity activity = null;
      for (int index = 0; index < duplicateActivities.length; index++) {
        activity = (CategorizedActivity) duplicateActivities[index];
        // Update the duplicate activity with the same state as the
        // original
        dualViewer.setChecked(activity, checkedState);
        // handle the activity check to potentially update its
        // category's enablement
        handleActivityCheck(new HashSet(Arrays.asList(dualViewer
            .getCheckedElements())), activity);
      }
    }

    /**
     * Handle the checking of an activity and update its category's checked
     * state.
     *
     * @param checked
     *            The set of checked elements in the viewer.
     * @param element
     *            The checked element.
     */
    private void handleActivityCheck(Set checked, Object element) {
      // clicking on an activity can potentially change the check/gray
      // state of its category.
      CategorizedActivity proxy = (CategorizedActivity) element;
      Object[] children = provider.getChildren(proxy.getCategory());
      int state = NONE;
      int count = 0;
      for (int i = 0; i < children.length; i++) {
        if (checked.contains(children[i])) {
          count++;
        }
      }

      if (count == children.length) {
        state = ALL;
      } else if (count != 0) {
        state = SOME;
      }

      if (state == NONE) {
        checked.remove(proxy.getCategory());
      } else {
        checked.add(proxy.getCategory());
      }

      dualViewer.setGrayed(proxy.getCategory(), state == SOME);
      dualViewer.setCheckedElements(checked.toArray());
      // Check child required activities and uncheck parent required activities
      // if needed
      handleRequiredActivities(checked, element);
    }

    /**
     * Handle the activity's required activities (parent and child).
     *
     * @param checked
     *            The set of checked elements in the viewer.
     * @param element
     *            The checked element.
     * 
     */
    private void handleRequiredActivities(Set checked, Object element) {
      Object[] requiredActivities = null;
      // An element has been checked - we want to check its child required
      // activities
      if (checked.contains(element)) {
        requiredActivities = provider
            .getChildRequiredActivities(((CategorizedActivity) element)
                .getId());
        for (int index = 0; index < requiredActivities.length; index++) {
          // We want to check the element if it is unchecked
          if (!checked.contains(requiredActivities[index])) {
            dualViewer.setChecked(requiredActivities[index], true);
            handleActivityCheck(new HashSet(Arrays
                .asList(dualViewer.getCheckedElements())),
                requiredActivities[index]);
          }
        }
      }
      // An element has been unchecked - we want to uncheck its parent
      // required activities
      else {
        requiredActivities = provider
            .getParentRequiredActivities(((CategorizedActivity) element)
                .getId());
        for (int index = 0; index < requiredActivities.length; index++) {
          // We want to uncheck the element if it is checked
          if (checked.contains(requiredActivities[index])) {
            dualViewer.setChecked(requiredActivities[index], false);
            handleActivityCheck(new HashSet(Arrays
                .asList(dualViewer.getCheckedElements())),
                requiredActivities[index]);
          }
        }
      }
    }

  };

  protected CheckboxTreeViewer dualViewer;

  /**
   * The Set of activities that belong to at least one category.
   */
  private Set managedActivities = new HashSet(7);

  /**
   * The content provider.
   */
  protected ActivityCategoryContentProvider provider = new ActivityCategoryContentProvider();

  /**
   * The descriptive text.
   */
  protected Text descriptionText;

  private Properties strings;

    private IMutableActivityManager activitySupport;

  /**
   * Create a new instance.
   *
   * @param activitySupport
   *            the <code>IMutableActivityMananger</code> to use.
   * @param strings
   *            map of strings to use. See the constants on
   *            {@link org.eclipse.ui.activities.ActivitiesPreferencePage} for
   *            details.
   */
  public ActivityEnabler(IMutableActivityManager activitySupport, Properties strings) {
    this.activitySupport = activitySupport;
    this.strings = strings;
  }

  /**
   * Create the controls.
   *
   * @param parent
   *            the parent in which to create the controls.
   * @return the composite in which the controls exist.
   */
  public Control createControl(Composite parent) {
        GC gc = new GC(parent);
        gc.setFont(JFaceResources.getDialogFont());
        FontMetrics fontMetrics = gc.getFontMetrics();
        gc.dispose();
       
    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(createGridLayoutWithoutMargins(1, fontMetrics));

    new Label(composite, SWT.NONE).setText(strings.getProperty(ActivitiesPreferencePage.ACTIVITY_NAME, ActivityMessages.ActivityEnabler_activities) + ':');

    dualViewer = new CheckboxTreeViewer(composite);
    dualViewer.setComparator(new ViewerComparator());
    dualViewer.setLabelProvider(new ActivityCategoryLabelProvider());
    dualViewer.setContentProvider(provider);
    dualViewer.setInput(activitySupport);
    GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
    dualViewer.getControl().setLayoutData(data);

    Composite buttonComposite = new Composite(composite, SWT.NONE);
    buttonComposite.setLayout(createGridLayoutWithoutMargins(2, fontMetrics));

    Button selectAllButton = new Button(buttonComposite, SWT.PUSH);
    selectAllButton.setText(ActivityMessages.ActivityEnabler_selectAll);
    selectAllButton.addSelectionListener(new SelectionAdapter() {
      /*
       * (non-Javadoc)
       *
       * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
       */
      public void widgetSelected(SelectionEvent e) {
        toggleTreeEnablement(true);
      }
    });
    setButtonLayoutData(selectAllButton, fontMetrics);

    Button deselectAllButton = new Button(buttonComposite, SWT.PUSH);
    deselectAllButton.setText(ActivityMessages.ActivityEnabler_deselectAll);
    deselectAllButton.addSelectionListener(new SelectionAdapter() {
      /*
       * (non-Javadoc)
       *
       * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
       */
      public void widgetSelected(SelectionEvent e) {
        toggleTreeEnablement(false);
      }
    });
    setButtonLayoutData(deselectAllButton, fontMetrics);

    new Label(composite, SWT.NONE).setText(ActivityMessages.ActivityEnabler_description);

    descriptionText = new Text(composite, SWT.READ_ONLY | SWT.WRAP | SWT.BORDER
        | SWT.V_SCROLL);
    data = new GridData(SWT.FILL, SWT.FILL, true, false);
    data.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, 5);
    descriptionText.setLayoutData(data);
    setInitialStates();

    dualViewer.addCheckStateListener(checkListener);
    dualViewer.addSelectionChangedListener(selectionListener);

    dualViewer.setSelection(new StructuredSelection());

        Dialog.applyDialogFont(composite);
       
    return composite;
  }

  private GridLayout createGridLayoutWithoutMargins(int nColumns, FontMetrics fontMetrics) {
    GridLayout layout = new GridLayout(nColumns, false);
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    layout.horizontalSpacing = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.HORIZONTAL_SPACING);
    layout.verticalSpacing = Dialog.convertVerticalDLUsToPixels(fontMetrics, IDialogConstants.VERTICAL_SPACING);
    return layout;
  }

    private GridData setButtonLayoutData(Button button, FontMetrics fontMetrics) {
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_WIDTH);
        Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
        data.widthHint = Math.max(widthHint, minSize.x);
        button.setLayoutData(data);
        return data;
    }
   
  /**
   * @param categoryId
   *            the id to fetch.
   * @return return all ids for activities that are in the given in the
   *         category.
   */
  private Collection getCategoryActivityIds(String categoryId) {
    ICategory category = activitySupport.getCategory(
        categoryId);
    Set activityBindings = category.getCategoryActivityBindings();
    List categoryActivities = new ArrayList(activityBindings.size());
    for (Iterator i = activityBindings.iterator(); i.hasNext();) {
      ICategoryActivityBinding binding = (ICategoryActivityBinding) i
          .next();
      String activityId = binding.getActivityId();
      categoryActivities.add(activityId);
    }
    return categoryActivities;
  }

  /**
   * Set the enabled category/activity check/grey states based on initial
   * activity enablement.
   */
  private void setInitialStates() {
    Set enabledActivities = activitySupport
        .getEnabledActivityIds();
    setEnabledStates(enabledActivities);
  }

  private void setEnabledStates(Set enabledActivities) {
    Set categories = activitySupport
        .getDefinedCategoryIds();
    List checked = new ArrayList(10), grayed = new ArrayList(10);
    for (Iterator i = categories.iterator(); i.hasNext();) {
      String categoryId = (String) i.next();
      ICategory category = activitySupport
          .getCategory(categoryId);

      int state = NONE;
      Collection activities = getCategoryActivityIds(categoryId);
      int foundCount = 0;
      for (Iterator j = activities.iterator(); j.hasNext();) {
        String activityId = (String) j.next();
        managedActivities.add(activityId);
        if (enabledActivities.contains(activityId)) {
          IActivity activity = activitySupport
              .getActivity(activityId);
          checked.add(new CategorizedActivity(category, activity));
          //add activity proxy
          foundCount++;
        }
      }

      if (foundCount == activities.size()) {
        state = ALL;
      } else if (foundCount > 0) {
        state = SOME;
      }

      if (state == NONE) {
        continue;
      }
      checked.add(category);

      if (state == SOME) {
        grayed.add(category);
      }
    }

    dualViewer.setCheckedElements(checked.toArray());
    dualViewer.setGrayedElements(grayed.toArray());
  }

  /**
   * Update activity enablement based on the check states of activities in the
   * tree.
   */
  public void updateActivityStates() {
    Set enabledActivities = new HashSet(activitySupport
                .getEnabledActivityIds());

    // remove all but the unmanaged activities (if any).
    enabledActivities.removeAll(managedActivities);

    Object[] checked = dualViewer.getCheckedElements();
    for (int i = 0; i < checked.length; i++) {
      Object element = checked[i];
      if (element instanceof ICategory || dualViewer.getGrayed(element)) {
        continue;
      }
      enabledActivities.add(((IActivity) element).getId());
    }

    activitySupport.setEnabledActivityIds(enabledActivities);
  }

  /**
   * Restore the default activity states.
   */
  public void restoreDefaults() {
      Set defaultEnabled = new HashSet();
      Set activityIds = activitySupport.getDefinedActivityIds();
      for (Iterator i = activityIds.iterator(); i.hasNext();) {
            String activityId = (String) i.next();
            IActivity activity = activitySupport.getActivity(activityId);
            try {
                if (activity.isDefaultEnabled()) {
                    defaultEnabled.add(activityId);
                }
            } catch (NotDefinedException e) {
                // this can't happen - we're iterating over defined activities.
            }
        }
     
    setEnabledStates(defaultEnabled);
  }

  /**
   * Toggles the enablement state of all activities.
   *
   * @param enabled
   *            whether the tree should be enabled
   */
  protected void toggleTreeEnablement(boolean enabled) {
    Object[] elements = provider.getElements(activitySupport);
   
    //reset grey state to null
    dualViewer.setGrayedElements(new Object[0]);
   
    //enable all categories
    for (int i = 0; i < elements.length; i++) {
      dualViewer
          .expandToLevel(elements[i], AbstractTreeViewer.ALL_LEVELS);
      dualViewer.setSubtreeChecked(elements[i], enabled);
    }
  }
}
TOP

Related Classes of org.eclipse.ui.internal.activities.ws.ActivityEnabler

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.