Package org.eclipse.ui.internal

Source Code of org.eclipse.ui.internal.SaveablesList

/*******************************************************************************
* Copyright (c) 2006, 2007 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;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.AssertionFailedException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.window.IShellProvider;
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.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.Shell;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.SaveablesLifecycleEvent;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.model.WorkbenchPartLabelProvider;

/**
* The model manager maintains a list of open saveable models.
*
* @see Saveable
* @see ISaveablesSource
*
* @since 3.2
*/
public class SaveablesList implements ISaveablesLifecycleListener {

  private ListenerList listeners = new ListenerList();

  // event source (mostly ISaveablesSource) -> Set of Saveable
  private Map modelMap = new HashMap();

  // reference counting map, Saveable -> Integer
  private Map modelRefCounts = new HashMap();

  private Set nonPartSources = new HashSet();

  /**
   * Returns the list of open models managed by this model manager.
   *
   * @return a list of models
   */
  public Saveable[] getOpenModels() {
    Set allDistinctModels = new HashSet();
    Iterator saveables = modelMap.values().iterator();
    while (saveables.hasNext())
      allDistinctModels.addAll((Set)saveables.next());
   
    return (Saveable[]) allDistinctModels.toArray(
        new Saveable[allDistinctModels.size()]);
  }

  // returns true if this model has not yet been in getModels()
  private boolean addModel(Object source, Saveable model) {
    boolean result = false;
    Set modelsForSource = (Set) modelMap.get(source);
    if (modelsForSource == null) {
      modelsForSource = new HashSet();
      modelMap.put(source, modelsForSource);
    }
    if (modelsForSource.add(model)) {
      result = incrementRefCount(modelRefCounts, model);
    } else {
      logWarning(
          "Ignored attempt to add saveable that was already registered", source, model); //$NON-NLS-1$
    }
    return result;
  }

  /**
   * returns true if the given key was added for the first time
   *
   * @param referenceMap
   * @param key
   * @return true if the ref count of the given key is now 1
   */
  private boolean incrementRefCount(Map referenceMap, Object key) {
    boolean result = false;
    Integer refCount = (Integer) referenceMap.get(key);
    if (refCount == null) {
      result = true;
      refCount = new Integer(0);
    }
    referenceMap.put(key, new Integer(refCount.intValue() + 1));
    return result;
  }

  /**
   * returns true if the given key has been removed
   *
   * @param referenceMap
   * @param key
   * @return true if the ref count of the given key was 1
   */
  private boolean decrementRefCount(Map referenceMap, Object key) {
    boolean result = false;
    Integer refCount = (Integer) referenceMap.get(key);
    Assert.isTrue(refCount != null);
    if (refCount.intValue() == 1) {
      referenceMap.remove(key);
      result = true;
    } else {
      referenceMap.put(key, new Integer(refCount.intValue() - 1));
    }
    return result;
  }

  // returns true if this model was removed from getModels();
  private boolean removeModel(Object source, Saveable model) {
    boolean result = false;
    Set modelsForSource = (Set) modelMap.get(source);
    if (modelsForSource == null) {
      logWarning(
          "Ignored attempt to remove a saveable when no saveables were known", source, model); //$NON-NLS-1$
    } else {
      if (modelsForSource.remove(model)) {
        result = decrementRefCount(modelRefCounts, model);
        if (modelsForSource.isEmpty()) {
          modelMap.remove(source);
        }
      } else {
        logWarning(
            "Ignored attempt to remove a saveable that was not registered", source, model); //$NON-NLS-1$
      }
    }
    return result;
  }

  private void logWarning(String message, Object source, Saveable model) {
    // create a new exception
    AssertionFailedException assertionFailedException = new AssertionFailedException("unknown saveable: " + model //$NON-NLS-1$
        + " from part: " + source); //$NON-NLS-1$
    // record the current stack trace to help with debugging
    assertionFailedException.fillInStackTrace();
    WorkbenchPlugin.log(StatusUtil.newStatus(IStatus.WARNING, message,
        assertionFailedException));
  }

  /**
   * This implementation of handleModelLifecycleEvent must be called by
   * implementers of ISaveablesSource whenever the list of models of the model
   * source changes, or when the dirty state of models changes. The
   * ISaveablesSource instance must be passed as the source of the event
   * object.
   * <p>
   * This method may also be called by objects that hold on to models but are
   * not workbench parts. In this case, the event source must be set to an
   * object that is not an instanceof IWorkbenchPart.
   * </p>
   * <p>
   * Corresponding open and close events must originate from the same
   * (identical) event source.
   * </p>
   * <p>
   * This method must be called on the UI thread.
   * </p>
   */
  public void handleLifecycleEvent(SaveablesLifecycleEvent event) {
    if (!(event.getSource() instanceof IWorkbenchPart)) {
      // just update the set of non-part sources. No prompting necessary.
      // See bug 139004.
      updateNonPartSource((ISaveablesSource) event.getSource());
      return;
    }
    Saveable[] modelArray = event.getSaveables();
    switch (event.getEventType()) {
    case SaveablesLifecycleEvent.POST_OPEN:
      addModels(event.getSource(), modelArray);
      break;
    case SaveablesLifecycleEvent.PRE_CLOSE:
      Saveable[] models = event.getSaveables();
      Map modelsDecrementing = new HashMap();
      Set modelsClosing = new HashSet();
      for (int i = 0; i < models.length; i++) {
        incrementRefCount(modelsDecrementing, models[i]);
      }

      fillModelsClosing(modelsClosing, modelsDecrementing);
      boolean canceled = promptForSavingIfNecessary(PlatformUI
          .getWorkbench().getActiveWorkbenchWindow(), modelsClosing, modelsDecrementing,
          !event.isForce());
      if (canceled) {
        event.setVeto(true);
      }
      break;
    case SaveablesLifecycleEvent.POST_CLOSE:
      removeModels(event.getSource(), modelArray);
      break;
    case SaveablesLifecycleEvent.DIRTY_CHANGED:
      fireModelLifecycleEvent(new SaveablesLifecycleEvent(this, event
          .getEventType(), event.getSaveables(), false));
      break;
    }
  }

  /**
   * Updates the set of non-part saveables sources.
   * @param source
   */
  private void updateNonPartSource(ISaveablesSource source) {
    Saveable[] saveables = source.getSaveables();
    if (saveables.length == 0) {
      nonPartSources.remove(source);
    } else {
      nonPartSources.add(source);
    }
  }

  /**
   * @param source
   * @param modelArray
   */
  private void removeModels(Object source, Saveable[] modelArray) {
    List removed = new ArrayList();
    for (int i = 0; i < modelArray.length; i++) {
      Saveable model = modelArray[i];
      if (removeModel(source, model)) {
        removed.add(model);
      }
    }
    if (removed.size() > 0) {
      fireModelLifecycleEvent(new SaveablesLifecycleEvent(this,
          SaveablesLifecycleEvent.POST_OPEN, (Saveable[]) removed
              .toArray(new Saveable[removed.size()]), false));
    }
  }

  /**
   * @param source
   * @param modelArray
   */
  private void addModels(Object source, Saveable[] modelArray) {
    List added = new ArrayList();
    for (int i = 0; i < modelArray.length; i++) {
      Saveable model = modelArray[i];
      if (addModel(source, model)) {
        added.add(model);
      }
    }
    if (added.size() > 0) {
      fireModelLifecycleEvent(new SaveablesLifecycleEvent(this,
          SaveablesLifecycleEvent.POST_OPEN, (Saveable[]) added
              .toArray(new Saveable[added.size()]), false));
    }
  }

  /**
   * @param event
   */
  private void fireModelLifecycleEvent(SaveablesLifecycleEvent event) {
    Object[] listenerArray = listeners.getListeners();
    for (int i = 0; i < listenerArray.length; i++) {
      ((ISaveablesLifecycleListener) listenerArray[i])
          .handleLifecycleEvent(event);
    }
  }

  /**
   * Adds the given listener to the list of listeners. Has no effect if the
   * same (identical) listener has already been added. The listener will be
   * notified about changes to the models managed by this model manager. Event
   * types include: <br>
   * POST_OPEN when models were added to the list of models <br>
   * POST_CLOSE when models were removed from the list of models <br>
   * DIRTY_CHANGED when the dirty state of models changed
   * <p>
   * Listeners should ignore all other event types, including PRE_CLOSE. There
   * is no guarantee that listeners are notified before models are closed.
   *
   * @param listener
   */
  public void addModelLifecycleListener(ISaveablesLifecycleListener listener) {
    listeners.add(listener);
  }

  /**
   * Removes the given listener from the list of listeners. Has no effect if
   * the given listener is not contained in the list.
   *
   * @param listener
   */
  public void removeModelLifecycleListener(ISaveablesLifecycleListener listener) {
    listeners.remove(listener);
  }

  /**
   * @param partsToClose
   * @param save
   * @param window
   * @return the post close info to be passed to postClose
   */
  public Object preCloseParts(List partsToClose, boolean save,
      final IWorkbenchWindow window) {
    // reference count (how many occurrences of a model will go away?)
    PostCloseInfo postCloseInfo = new PostCloseInfo();
    for (Iterator it = partsToClose.iterator(); it.hasNext();) {
      IWorkbenchPart part = (IWorkbenchPart) it.next();
      postCloseInfo.partsClosing.add(part);
      if (part instanceof ISaveablePart) {
        ISaveablePart saveablePart = (ISaveablePart) part;
        if (save && !saveablePart.isSaveOnCloseNeeded()) {
          // pretend for now that this part is not closing
          continue;
        }
      }
      if (save && part instanceof ISaveablePart2) {
        ISaveablePart2 saveablePart2 = (ISaveablePart2) part;
        // TODO show saveablePart2 before prompting, see
        // EditorManager.saveAll
        int response = SaveableHelper.savePart(saveablePart2, window,
            true);
        if (response == ISaveablePart2.CANCEL) {
          // user canceled
          return null;
        } else if (response != ISaveablePart2.DEFAULT) {
          // only include this part in the following logic if it returned
          // DEFAULT
          continue;
        }
      }
      Saveable[] modelsFromSource = getSaveables(part);
      for (int i = 0; i < modelsFromSource.length; i++) {
        incrementRefCount(postCloseInfo.modelsDecrementing,
            modelsFromSource[i]);
      }
    }
    fillModelsClosing(postCloseInfo.modelsClosing,
        postCloseInfo.modelsDecrementing);
    if (save) {
      boolean canceled = promptForSavingIfNecessary(window,
          postCloseInfo.modelsClosing, postCloseInfo.modelsDecrementing, true);
      if (canceled) {
        return null;
      }
    }
    return postCloseInfo;
  }

  /**
   * @param window
   * @param modelsClosing
   * @param canCancel
   * @return true if the user canceled
   */
  private boolean promptForSavingIfNecessary(final IWorkbenchWindow window,
      Set modelsClosing, Map modelsDecrementing, boolean canCancel) {
    List modelsToOptionallySave = new ArrayList();
    for (Iterator it = modelsDecrementing.keySet().iterator(); it.hasNext();) {
      Saveable modelDecrementing = (Saveable) it.next();
      if (modelDecrementing.isDirty() && !modelsClosing.contains(modelDecrementing)) {
        modelsToOptionallySave.add(modelDecrementing);
      }
    }
   
    boolean shouldCancel = modelsToOptionallySave.isEmpty() ? false : promptForSaving(modelsToOptionallySave,
        window, window, canCancel, true);
   
    if (shouldCancel) {
      return true;
    }

    List modelsToSave = new ArrayList();
    for (Iterator it = modelsClosing.iterator(); it.hasNext();) {
      Saveable modelClosing = (Saveable) it.next();
      if (modelClosing.isDirty()) {
        modelsToSave.add(modelClosing);
      }
    }
    return modelsToSave.isEmpty() ? false : promptForSaving(modelsToSave,
        window, window, canCancel, false);
  }

  /**
   * @param modelsClosing
   * @param modelsDecrementing
   */
  private void fillModelsClosing(Set modelsClosing, Map modelsDecrementing) {
    for (Iterator it = modelsDecrementing.keySet().iterator(); it.hasNext();) {
      Saveable model = (Saveable) it.next();
      if (modelsDecrementing.get(model).equals(modelRefCounts.get(model))) {
        modelsClosing.add(model);
      }
    }
  }

  /**
   * Prompt the user to save the given saveables.
   * @param modelsToSave the saveables to be saved
   * @param shellProvider the provider used to obtain a shell in prompting is
   *            required. Clients can use a workbench window for this.
   * @param runnableContext a runnable context that will be used to provide a
   *            progress monitor while the save is taking place. Clients can
   *            use a workbench window for this.
   * @param canCancel whether the operation can be canceled
   * @param stillOpenElsewhere whether the models are referenced by open parts
   * @return true if the user canceled
   */
  public boolean promptForSaving(List modelsToSave,
      final IShellProvider shellProvider, IRunnableContext runnableContext, final boolean canCancel, boolean stillOpenElsewhere) {
    // Save parts, exit the method if cancel is pressed.
    if (modelsToSave.size() > 0) {
      boolean canceled = SaveableHelper.waitForBackgroundSaveJobs(modelsToSave);
      if (canceled) {
        return true;
      }

      IPreferenceStore apiPreferenceStore = PrefUtil.getAPIPreferenceStore();
      boolean dontPrompt = stillOpenElsewhere && !apiPreferenceStore.getBoolean(IWorkbenchPreferenceConstants.PROMPT_WHEN_SAVEABLE_STILL_OPEN);

      if (dontPrompt) {
        modelsToSave.clear();
        return false;
      } else if (modelsToSave.size() == 1) {
        Saveable model = (Saveable) modelsToSave.get(0);
        // Show a dialog.
        String[] buttons;
        if(canCancel) {
          buttons = new String[] { IDialogConstants.YES_LABEL,
              IDialogConstants.NO_LABEL,
              IDialogConstants.CANCEL_LABEL };
        } else {
          buttons = new String[] { IDialogConstants.YES_LABEL,
              IDialogConstants.NO_LABEL};
        }

        // don't save if we don't prompt
        int choice = ISaveablePart2.NO;
       
        MessageDialog dialog;
        if (stillOpenElsewhere) {
          String message = NLS
              .bind(
                  WorkbenchMessages.EditorManager_saveChangesOptionallyQuestion,
                  model.getName());
          MessageDialogWithToggle dialogWithToggle = new MessageDialogWithToggle(shellProvider.getShell(),
              WorkbenchMessages.Save_Resource, null, message,
              MessageDialog.QUESTION, buttons, 0, WorkbenchMessages.EditorManager_closeWithoutPromptingOption, false) {
            protected int getShellStyle() {
              return (canCancel ? SWT.CLOSE : SWT.NONE)
                  | SWT.TITLE | SWT.BORDER
                  | SWT.APPLICATION_MODAL
                  | getDefaultOrientation();
            }
          };
          dialog = dialogWithToggle;
        } else {
          String message = NLS
              .bind(
                  WorkbenchMessages.EditorManager_saveChangesQuestion,
                  model.getName());
          dialog = new MessageDialog(shellProvider.getShell(),
              WorkbenchMessages.Save_Resource, null, message,
              MessageDialog.QUESTION, buttons, 0) {
            protected int getShellStyle() {
              return (canCancel ? SWT.CLOSE : SWT.NONE)
                  | SWT.TITLE | SWT.BORDER
                  | SWT.APPLICATION_MODAL
                  | getDefaultOrientation();
            }
          };
        }

        choice = SaveableHelper.testGetAutomatedResponse();
        if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
          choice = dialog.open();
         
          if(stillOpenElsewhere) {
            // map value of choice back to ISaveablePart2 values
            switch (choice) {
            case IDialogConstants.YES_ID:
              choice = ISaveablePart2.YES;
              break;
            case IDialogConstants.NO_ID:
              choice = ISaveablePart2.NO;
              break;
            case IDialogConstants.CANCEL_ID:
              choice = ISaveablePart2.CANCEL;
              break;
            default:
              break;
            }
            MessageDialogWithToggle dialogWithToggle = (MessageDialogWithToggle) dialog;
            if (choice != ISaveablePart2.CANCEL && dialogWithToggle.getToggleState()) {
              apiPreferenceStore.setValue(IWorkbenchPreferenceConstants.PROMPT_WHEN_SAVEABLE_STILL_OPEN, false);
            }
          }
        }

        // Branch on the user choice.
        // The choice id is based on the order of button labels
        // above.
        switch (choice) {
        case ISaveablePart2.YES: // yes
          break;
        case ISaveablePart2.NO: // no
          modelsToSave.clear();
          break;
        default:
        case ISaveablePart2.CANCEL: // cancel
          return true;
        }
      } else {
        MyListSelectionDialog dlg = new MyListSelectionDialog(
            shellProvider.getShell(),
            modelsToSave,
            new ArrayContentProvider(),
            new WorkbenchPartLabelProvider(),
            stillOpenElsewhere ? WorkbenchMessages.EditorManager_saveResourcesOptionallyMessage
                : WorkbenchMessages.EditorManager_saveResourcesMessage,
            canCancel, stillOpenElsewhere);
        dlg.setInitialSelections(modelsToSave.toArray());
        dlg.setTitle(EditorManager.SAVE_RESOURCES_TITLE);

        // this "if" statement aids in testing.
        if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) {
          int result = dlg.open();
          // Just return null to prevent the operation continuing
          if (result == IDialogConstants.CANCEL_ID)
            return true;

          if (dlg.getDontPromptSelection()) {
            apiPreferenceStore.setValue(IWorkbenchPreferenceConstants.PROMPT_WHEN_SAVEABLE_STILL_OPEN, false);
          }
         
          modelsToSave = Arrays.asList(dlg.getResult());
        }
      }
    }
    // Create save block.
    return saveModels(modelsToSave, shellProvider, runnableContext);
  }

  /**
   * Save the given models.
   * @param finalModels the list of models to be saved
   * @param shellProvider the provider used to obtain a shell in prompting is
   *            required. Clients can use a workbench window for this.
   * @param runnableContext a runnable context that will be used to provide a
   *            progress monitor while the save is taking place. Clients can
   *            use a workbench window for this.
   * @return <code>true</code> if the operation was canceled
   */
  public boolean saveModels(final List finalModels, final IShellProvider shellProvider, IRunnableContext runnableContext) {
    IRunnableWithProgress progressOp = new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor) {
        IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
            monitor);
        monitorWrap.beginTask("", finalModels.size()); //$NON-NLS-1$
        for (Iterator i = finalModels.iterator(); i.hasNext();) {
          Saveable model = (Saveable) i.next();
          // handle case where this model got saved as a result of
          // saving another
          if (!model.isDirty()) {
            monitor.worked(1);
            continue;
          }
          SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), shellProvider, true);
          if (monitorWrap.isCanceled())
            break;
        }
        monitorWrap.done();
      }
    };

    // Do the save.
    return !SaveableHelper.runProgressMonitorOperation(
        WorkbenchMessages.Save_All, progressOp, runnableContext,
        shellProvider);
  }

  private static class PostCloseInfo {
    private List partsClosing = new ArrayList();

    private Map modelsDecrementing = new HashMap();

    private Set modelsClosing = new HashSet();
  }

  /**
   * @param postCloseInfoObject
   */
  public void postClose(Object postCloseInfoObject) {
    PostCloseInfo postCloseInfo = (PostCloseInfo) postCloseInfoObject;
    List removed = new ArrayList();
    for (Iterator it = postCloseInfo.partsClosing.iterator(); it.hasNext();) {
      IWorkbenchPart part = (IWorkbenchPart) it.next();
      Set saveables = (Set) modelMap.get(part);
      if (saveables != null) {
        // make a copy to avoid a ConcurrentModificationException - we
        // will remove from the original set as we iterate
        saveables = new HashSet(saveables);
        for (Iterator it2 = saveables.iterator(); it2.hasNext();) {
          Saveable saveable = (Saveable) it2.next();
          if (removeModel(part, saveable)) {
            removed.add(saveable);
          }
        }
      }
    }
    if (removed.size() > 0) {
      fireModelLifecycleEvent(new SaveablesLifecycleEvent(this,
          SaveablesLifecycleEvent.POST_CLOSE, (Saveable[]) removed
              .toArray(new Saveable[removed.size()]), false));
    }
  }

  /**
   * Returns the saveable models provided by the given part. If the part does
   * not provide any models, a default model is returned representing the
   * part.
   *
   * @param part
   *            the workbench part
   * @return the saveable models
   */
  private Saveable[] getSaveables(IWorkbenchPart part) {
    if (part instanceof ISaveablesSource) {
      ISaveablesSource source = (ISaveablesSource) part;
      return source.getSaveables();
    } else if (part instanceof ISaveablePart) {
      return new Saveable[] { new DefaultSaveable(part) };
    } else {
      return new Saveable[0];
    }
  }

  /**
   * @param actualPart
   */
  public void postOpen(IWorkbenchPart part) {
    addModels(part, getSaveables(part));
  }

  /**
   * @param actualPart
   */
  public void dirtyChanged(IWorkbenchPart part) {
    Saveable[] saveables = getSaveables(part);
    if (saveables.length > 0) {
      fireModelLifecycleEvent(new SaveablesLifecycleEvent(this,
          SaveablesLifecycleEvent.DIRTY_CHANGED, saveables, false));
    }
  }

  /**
   * For testing purposes. Not to be called by clients.
   *
   * @param model
   * @return
   */
  public Object[] testGetSourcesForModel(Saveable model) {
    List result = new ArrayList();
    for (Iterator it = modelMap.entrySet().iterator(); it.hasNext();) {
      Map.Entry entry = (Map.Entry) it.next();
      Set values = (Set) entry.getValue();
      if (values.contains(model)) {
        result.add(entry.getKey());
      }
    }
    return result.toArray();
  }

  private static final class MyListSelectionDialog extends
      ListSelectionDialog {
    private final boolean canCancel;
    private Button checkbox;
    private boolean dontPromptSelection;
    private boolean stillOpenElsewhere;

    private MyListSelectionDialog(Shell shell, Object input,
        IStructuredContentProvider contentprovider,
        ILabelProvider labelProvider, String message, boolean canCancel, boolean stillOpenElsewhere) {
      super(shell, input, contentprovider, labelProvider, message);
      this.canCancel = canCancel;
      this.stillOpenElsewhere = stillOpenElsewhere;
      if (!canCancel) {
        int shellStyle = getShellStyle();
        shellStyle &= ~SWT.CLOSE;
        setShellStyle(shellStyle);
      }
    }

    /**
     * @return
     */
    public boolean getDontPromptSelection() {
      return dontPromptSelection;
    }

    protected void createButtonsForButtonBar(Composite parent) {
      createButton(parent, IDialogConstants.OK_ID,
          IDialogConstants.OK_LABEL, true);
      if (canCancel) {
        createButton(parent, IDialogConstants.CANCEL_ID,
            IDialogConstants.CANCEL_LABEL, false);
      }
    }
   
    protected Control createDialogArea(Composite parent) {
       Composite dialogAreaComposite = (Composite) super.createDialogArea(parent);
      
       if (stillOpenElsewhere) {
         Composite checkboxComposite = new Composite(dialogAreaComposite, SWT.NONE);
         checkboxComposite.setLayout(new GridLayout(2, false));
        
         checkbox = new Button(checkboxComposite, SWT.CHECK);
         checkbox.addSelectionListener(new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            dontPromptSelection = checkbox.getSelection();
          }
         });
         GridData gd = new GridData();
         gd.horizontalAlignment = SWT.BEGINNING;
         checkbox.setLayoutData(gd);
        
         Label label = new Label(checkboxComposite, SWT.NONE);
         label.setText(WorkbenchMessages.EditorManager_closeWithoutPromptingOption);
         gd = new GridData();
         gd.grabExcessHorizontalSpace = true;
         gd.horizontalAlignment = SWT.BEGINNING;
       }
      
       return dialogAreaComposite;
    }
  }

  /**
   * @return a list of ISaveablesSource objects registered with this saveables
   *         list which are not workbench parts.
   */
  public ISaveablesSource[] getNonPartSources() {
    return (ISaveablesSource[]) nonPartSources
        .toArray(new ISaveablesSource[nonPartSources.size()]);
  }

  /**
   * @param model
   */
  public IWorkbenchPart[] getPartsForSaveable(Saveable model) {
    List result = new ArrayList();
    for (Iterator it = modelMap.entrySet().iterator(); it.hasNext();) {
      Map.Entry entry = (Map.Entry) it.next();
      Set values = (Set) entry.getValue();
      if (values.contains(model) && entry.getKey() instanceof IWorkbenchPart) {
        result.add(entry.getKey());
      }
    }
    return (IWorkbenchPart[]) result.toArray(new IWorkbenchPart[result.size()]);
  }

}
TOP

Related Classes of org.eclipse.ui.internal.SaveablesList

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.