diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index aee2ed82463..64c3b492cac 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,14 @@ +2004-02-15 Alain Magloire + + Special working set for the C/C++ Celements + new pakage. + + * src/org/eclipse/cdt/internal/ui/workingsets + * src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPage.java + * src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPageContentProvider.java + * src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.java + * src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.properties + 2004-02-15 Alain Magloire Reorganize the action of the CView and distribute them diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties index 148f03ed425..e55906c1cc7 100644 --- a/core/org.eclipse.cdt.ui/plugin.properties +++ b/core/org.eclipse.cdt.ui/plugin.properties @@ -103,3 +103,4 @@ OpenTypeAction.tooltip= Open Type ActionDefinition.openType.name= Open Type ActionDefinition.openType.description= Open a type in a C editor +CElementWorkingSetPage.name = C/C++ diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index 3b4b8be4b1a..47d14f34506 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -538,4 +538,14 @@ + + + + + diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPage.java new file mode 100644 index 00000000000..2549ea98def --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPage.java @@ -0,0 +1,436 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials! + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation +*************************************************************************/ +package org.eclipse.cdt.internal.ui.workingsets; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.ui.CElementSorter; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ITreeViewerListener; +import org.eclipse.jface.viewers.TreeExpansionEvent; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.IWorkingSetPage; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +/** + * A celement working set page allows the user to edit an + * existing working set and create a new working set. + *

+ * Working set elements are presented as a simple resource tree. + *

+ * + */ +public class CElementWorkingSetPage extends WizardPage implements IWorkingSetPage { + + final private static String PAGE_TITLE= WorkingSetMessages.getString("CElementWorkingSetPage.title"); //$NON-NLS-1$ + final private static String PAGE_ID= WorkingSetMessages.getString("CElementWorkingSetPage"); //$NON-NLS-1$ + + private final static int SIZING_SELECTION_WIDGET_WIDTH = 50; + private final static int SIZING_SELECTION_WIDGET_HEIGHT = 200; + + private Text text; + private CheckboxTreeViewer tree; + private IWorkingSet workingSet; + private boolean firstCheck = false; // set to true if selection is set in setSelection + + /** + * Creates a new instance of the receiver. + */ + public CElementWorkingSetPage() { + super(PAGE_ID, PAGE_TITLE, CPluginImages.DESC_WIZABAN_C_APP); + setDescription(WorkingSetMessages.getString("CElementWorkingSetPage.description")); //$NON-NLS-1$ + } + + /** + * Adds working set elements contained in the given container to the list + * of checked resources. + * + * @param collectedResources list of collected resources + * @param container container to collect working set elements for + */ + private void addWorkingSetElements(List collectedResources, IContainer container) { + IAdaptable[] elements = workingSet.getElements(); + IPath containerPath = container.getFullPath(); + + for (int i = 0; i < elements.length; i++) { + IResource resource = null; + + if (elements[i] instanceof IResource) + resource = (IResource) elements[i]; + else + resource = (IResource) elements[i].getAdapter(IResource.class); + + if (resource != null) { + IPath resourcePath = resource.getFullPath(); + if (containerPath.isPrefixOf(resourcePath)) + collectedResources.add(elements[i]); + } + } + } + /** + * Overrides method in WizardPage. + * + * @see org.eclipse.jface.wizard.WizardPage#createControl(Composite) + */ + public void createControl(Composite parent) { + Font font = parent.getFont(); + Composite composite= new Composite(parent, SWT.NULL); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + setControl(composite); + + //WorkbenchHelp.setHelp(composite, IHelpContextIds.WORKING_SET_RESOURCE_PAGE); + Label label = new Label(composite, SWT.WRAP); + label.setText(WorkingSetMessages.getString("CElementWorkingSetPage.content")); //$NON-NLS-1$ + GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); + label.setLayoutData(data); + label.setFont(font); + + text = new Text(composite, SWT.SINGLE | SWT.BORDER); + text.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); + text.setFont(font); + text.addModifyListener( + new ModifyListener() { + public void modifyText(ModifyEvent e) { + validateInput(); + } + } + ); + text.setFocus(); + + label = new Label(composite, SWT.WRAP); + label.setText(WorkingSetMessages.getString("CElementWorkingSetPage.label.tree")); //$NON-NLS-1$ + data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER); + label.setLayoutData(data); + label.setFont(font); + + tree = new CheckboxTreeViewer(composite); + tree.setUseHashlookup(true); + tree.setContentProvider(new CElementWorkingSetPageContentProvider()); + tree.setLabelProvider( + new DecoratingLabelProvider( + new WorkbenchLabelProvider(), + CUIPlugin.getDefault().getWorkbench().getDecoratorManager().getLabelDecorator())); + tree.setInput(CUIPlugin.getWorkspace().getRoot()); + tree.setSorter(new CElementSorter()); + + data = new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL); + data.heightHint = SIZING_SELECTION_WIDGET_HEIGHT; + data.widthHint = SIZING_SELECTION_WIDGET_WIDTH; + tree.getControl().setLayoutData(data); + tree.getControl().setFont(font); + + tree.addCheckStateListener(new ICheckStateListener() { + public void checkStateChanged(CheckStateChangedEvent event) { + handleCheckStateChange(event); + } + }); + + tree.addTreeListener(new ITreeViewerListener() { + public void treeCollapsed(TreeExpansionEvent event) { + } + public void treeExpanded(TreeExpansionEvent event) { + final Object element = event.getElement(); + if (tree.getGrayed(element) == false) + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + public void run() { + setSubtreeChecked((IContainer) element, tree.getChecked(element), false); + } + }); + } + }); + initializeCheckedState(); + if (workingSet != null) { + text.setText(workingSet.getName()); + } + setPageComplete(false); + } + /** + * Collects all checked resources in the specified container. + * + * @param checkedResources the output, list of checked resources + * @param container the container to collect checked resources in + */ + private void findCheckedResources(List checkedResources, IContainer container) { + IResource[] resources = null; + try { + resources = container.members(); + } catch (CoreException ex) { + handleCoreException(ex, getShell(), WorkingSetMessages.getString("EditWorkingSetAction.nowizard.message"), //$NON-NLS-1$ + "updateCheckedState"); //$NON-NLS-1$ + } + for (int i = 0; i < resources.length; i++) { + if (tree.getGrayed(resources[i])) { + if (resources[i].isAccessible()) + findCheckedResources(checkedResources, (IContainer) resources[i]); + else + addWorkingSetElements(checkedResources, (IContainer) resources[i]); + } else if (tree.getChecked(resources[i])) { + checkedResources.add(resources[i]); + } + } + } + /** + * Implements IWorkingSetPage. + * + * @see org.eclipse.ui.dialogs.IWorkingSetPage#finish() + */ + public void finish() { + ArrayList resources = new ArrayList(10); + findCheckedResources(resources, (IContainer) tree.getInput()); + if (workingSet == null) { + IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); + workingSet = workingSetManager.createWorkingSet(getWorkingSetName(), (IAdaptable[]) resources.toArray(new IAdaptable[resources.size()])); + } else { + workingSet.setName(getWorkingSetName()); + workingSet.setElements((IAdaptable[]) resources.toArray(new IAdaptable[resources.size()])); + } + } + /** + * Implements IWorkingSetPage. + * + * @see org.eclipse.ui.dialogs.IWorkingSetPage#getSelection() + */ + public IWorkingSet getSelection() { + return workingSet; + } + /** + * Returns the name entered in the working set name field. + * + * @return the name entered in the working set name field. + */ + private String getWorkingSetName() { + return text.getText(); + } + /** + * Called when the checked state of a tree item changes. + * + * @param event the checked state change event. + */ + private void handleCheckStateChange(final CheckStateChangedEvent event) { + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + public void run() { + IResource resource = (IResource) event.getElement(); + boolean state = event.getChecked(); + + tree.setGrayed(resource, false); + if (resource instanceof IContainer) { + setSubtreeChecked((IContainer) resource, state, true); + } + updateParentState(resource); + validateInput(); + } + }); + } + /** + * Displays an error message when a CoreException occured. + * + * @param exception the CoreException + * @param shell parent shell for the message box + * @param title the mesage box title + * @param message additional error message + */ + private void handleCoreException(CoreException exception, Shell shell, String title, String message) { + IStatus status = exception.getStatus(); + if (status != null) { + ErrorDialog.openError(shell, title, message, status); + } else { + MessageDialog.openError(shell, WorkingSetMessages.getString("EditWorkingSetAction.nowizard.message"), exception.getLocalizedMessage()); //$NON-NLS-1$ + } + } + /** + * Sets the checked state of tree items based on the initial + * working set, if any. + */ + private void initializeCheckedState() { + if (workingSet == null) + return; + + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + public void run() { + IAdaptable[] items = workingSet.getElements(); + tree.setCheckedElements(items); + for (int i = 0; i < items.length; i++) { + IAdaptable item = items[i]; + IContainer container = null; + IResource resource = null; + + if (item instanceof IContainer) { + container = (IContainer) item; + } else { + container = (IContainer) item.getAdapter(IContainer.class); + } + if (container != null) { + setSubtreeChecked(container, true, true); + } + if (item instanceof IResource) { + resource = (IResource) item; + } else { + resource = (IResource) item.getAdapter(IResource.class); + } + if (resource != null && resource.isAccessible() == false) { + IProject project = resource.getProject(); + if (tree.getChecked(project) == false) + tree.setGrayChecked(project, true); + } + else { + updateParentState(resource); + } + } + } + }); + } + /** + * Implements IWorkingSetPage. + * + * @see org.eclipse.ui.dialogs.IWorkingSetPage#setSelection(IWorkingSet) + */ + public void setSelection(IWorkingSet workingSet) { + if (workingSet == null) { + throw new IllegalArgumentException("Working set must not be null"); //$NON-NLS-1$ + } + this.workingSet = workingSet; + if (getShell() != null && text != null) { + firstCheck = true; + initializeCheckedState(); + text.setText(workingSet.getName()); + } + } + /** + * Sets the checked state of the container's members. + * + * @param container the container whose children should be checked/unchecked + * @param state true=check all members in the container. false=uncheck all + * members in the container. + * @param checkExpandedState true=recurse into sub-containers and set the + * checked state. false=only set checked state of members of this container + */ + private void setSubtreeChecked(IContainer container, boolean state, boolean checkExpandedState) { + // checked state is set lazily on expand, don't set it if container is collapsed + if (container.isAccessible() == false || (tree.getExpandedState(container) == false && state && checkExpandedState)) { + return; + } + IResource[] members = null; + try { + members = container.members(); + } catch (CoreException ex) { + handleCoreException(ex, getShell(), WorkingSetMessages.getString("EditWorkingSetAction.nowizard.message"), //$NON-NLS-1$ + "updateCheckedState"); //$NON-NLS-1$ + } + for (int i = members.length - 1; i >= 0; i--) { + IResource element = members[i]; + boolean elementGrayChecked = tree.getGrayed(element) || tree.getChecked(element); + + if (state) { + tree.setChecked(element, true); + tree.setGrayed(element, false); + } else { + tree.setGrayChecked(element, false); + } + // unchecked state only needs to be set when the container is + // checked or grayed + if (element instanceof IContainer && (state || elementGrayChecked)) { + setSubtreeChecked((IContainer) element, state, true); + } + } + } + /** + * Check and gray the resource parent if all resources of the + * parent are checked. + * + * @param child the resource whose parent checked state should + * be set. + */ + private void updateParentState(IResource child) { + if (child == null || child.getParent() == null) + return; + + IContainer parent = child.getParent(); + boolean childChecked = false; + IResource[] members = null; + try { + members = parent.members(); + } catch (CoreException ex) { + handleCoreException(ex, getShell(), WorkingSetMessages.getString("EditWorkingSetAction.nowizard.message"), //$NON-NLS-1$ + "updateCheckedState"); //$NON-NLS-1$ + } + for (int i = members.length - 1; i >= 0; i--) { + if (tree.getChecked(members[i]) || tree.getGrayed(members[i])) { + childChecked = true; + break; + } + } + tree.setGrayChecked(parent, childChecked); + updateParentState(parent); + } + /** + * Validates the working set name and the checked state of the + * resource tree. + */ + private void validateInput() { + String errorMessage = null; + String newText = text.getText(); + + if (newText.equals(newText.trim()) == false) { + errorMessage = WorkingSetMessages.getString("CElementWorkingSetPage.warning.nameMustNotBeEmpty"); //$NON-NLS-1$ + } + else + if (firstCheck) { + firstCheck = false; + return; + } + if (newText.equals("")) { //$NON-NLS-1$ + errorMessage = WorkingSetMessages.getString("CElementWorkingSetPage.warning.nameMustNotBeEmpty"); //$NON-NLS-1$ + } + if (errorMessage == null && (workingSet == null || newText.equals(workingSet.getName()) == false)) { + IWorkingSet[] workingSets = PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSets(); + for (int i = 0; i < workingSets.length; i++) { + if (newText.equals(workingSets[i].getName())) { + errorMessage = WorkingSetMessages.getString("CElementWorkingSetPage.warning.workingSetExists"); //$NON-NLS-1$ + } + } + } + if (errorMessage == null && tree.getCheckedElements().length == 0) { + errorMessage = WorkingSetMessages.getString("CElementWorkingSetPage.warning.resourceMustBeChecked"); //$NON-NLS-1$ + } + setErrorMessage(errorMessage); + setPageComplete(errorMessage == null); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPageContentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPageContentProvider.java new file mode 100644 index 00000000000..97bb6366a5f --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/CElementWorkingSetPageContentProvider.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.workingsets; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.ui.model.WorkbenchContentProvider; + +class CElementWorkingSetPageContentProvider extends WorkbenchContentProvider { + + /* (non-Javadoc) + * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object element) { + if (element instanceof IWorkspaceRoot) { + IWorkspaceRoot root = (IWorkspaceRoot)element; + IProject[] projects = root.getProjects(); + List list = new ArrayList(projects.length); + for (int i = 0; i < projects.length; i++) { + if (CoreModel.getDefault().hasCNature(projects[i])) { + list.add(projects[i]); + } + } + return list.toArray(); + } + return super.getChildren(element); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.java new file mode 100644 index 00000000000..b87f6eef5b6 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.workingsets; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +class WorkingSetMessages { + + private static final String RESOURCE_BUNDLE= WorkingSetMessages.class.getName(); + + private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + + private WorkingSetMessages() { + } + + public static String getString(String key) { + try { + return fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + */ + public static String getFormattedString(String key, Object arg) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + if (arg == null) + arg= ""; //$NON-NLS-1$ + return MessageFormat.format(format, new Object[] { arg }); + } + + /** + * Gets a string from the resource bundle and formats it with the argument + * + * @param key the string used to get the bundle value, must not be null + */ + public static String getFormattedString(String key, Object[] args) { + String format= null; + try { + format= fgResourceBundle.getString(key); + } catch (MissingResourceException e) { + return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ + } + return MessageFormat.format(format, args); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.properties new file mode 100644 index 00000000000..6aa42cd6b9d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/WorkingSetMessages.properties @@ -0,0 +1,31 @@ +############################################################################### +# Copyright (c) 2000, 2003 IBM Corporation and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Common Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/cpl-v10.html +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### + +CElementWorkingSetPage.title= C/C++ Working Set +CElementWorkingSetPage.name= &Working set name: +CElementWorkingSetPage.description= Enter a working set name and select the working set elements. + +CElementWorkingSetPage.content= Working set &content: +CElementWorkingSetPage.warning.nameMustNotBeEmpty= The name must not be empty. +CElementWorkingSetPage.warning.workingSetExists= A working set with that name already exists. +CElementWorkingSetPage.warning.resourceMustBeChecked= At least one resource must be checked. +CElementWorkingSetPage.warning.nameWhitespace= The name must not have leading or trailing whitespace. +CElementWorkingSetPage.projectClosedDialog.message= A closed project can not be modified +CElementWorkingSetPage.projectClosedDialog.title= Working Set Change + +SelectWorkingSetAction.text= Select &Working Set... +SelectWorkingSetAction.toolTip= Select a working set +EditWorkingSetAction.text= &Edit Active Working Set... +EditWorkingSetAction.toolTip= Edit the active working set +EditWorkingSetAction.nowizard.title= Edit Working Set +EditWorkingSetAction.nowizard.message= Can not edit the active working set. +ClearWorkingSetAction.text= Deselect Wor&king Set +ClearWorkingSetAction.toolTip= Deselect the active working set