/******************************************************************************* * Copyright (c) 2013 Google, Inc 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: * Sergey Prigogin (Google) - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.preferences; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle; import org.eclipse.cdt.internal.ui.refactoring.includes.IncludeGroupStyle.IncludeKind; import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.cdt.internal.ui.wizards.dialogfields.ITreeListAdapter; import org.eclipse.cdt.internal.ui.wizards.dialogfields.TreeListDialogField; /** * The preference block for configuring styles of different categories of include statements. */ public class IncludeCategoriesBlock extends OptionsConfigurationBlock { private final List<IncludeGroupStyle> styles; private final Map<IncludeKind, Category> categories = new HashMap<IncludeKind, Category>(); private TreeListDialogField<Category> categoryTree; private PixelConverter pixelConverter; private StackLayout editorAreaStack; private Category selectedCategory; public IncludeCategoriesBlock(IStatusChangeListener context, IProject project, IWorkbenchPreferenceContainer container, List<IncludeGroupStyle> styles) { super(context, project, new Key[0], container); this.styles = styles; createCategories(); } private void createCategories() { createCategory(IncludeKind.RELATED); createCategory(IncludeKind.PARTNER); createCategory(IncludeKind.IN_SAME_FOLDER); createCategory(IncludeKind.IN_SUBFOLDER); createCategory(IncludeKind.SYSTEM); createCategory(IncludeKind.SYSTEM_WITH_EXTENSION); createCategory(IncludeKind.SYSTEM_WITHOUT_EXTENSION); createCategory(IncludeKind.OTHER); createCategory(IncludeKind.IN_SAME_PROJECT); createCategory(IncludeKind.IN_OTHER_PROJECT); createCategory(IncludeKind.EXTERNAL); } private Category createCategory(IncludeKind includeKind) { Category parentCategory = categories.get(includeKind.parent); Category category = new Category(includeKind, parentCategory); categories.put(category.getIncludeKind(), category); return category; } public void postSetSelection(Object element) { categoryTree.postSetSelection(new StructuredSelection(element)); } @Override protected Control createContents(Composite parent) { pixelConverter = new PixelConverter(parent); setShell(parent.getShell()); Composite composite = new Composite(parent, SWT.NONE); composite.setFont(parent.getFont()); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; composite.setLayout(layout); IncludeStyleAdapter adapter = new IncludeStyleAdapter(); categoryTree = new TreeListDialogField<Category>(adapter, null, new IncludeStyleLabelProvider()); categoryTree.setDialogFieldListener(adapter); categoryTree.setLabelText(PreferencesMessages.IncludeCategoriesBlock_header_categories); categoryTree.setViewerComparator(adapter); for (Category category : categories.values()) { if (category.parent == null) categoryTree.addElement(category); } Label label = categoryTree.getLabelControl(composite); label.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false)); Control tree = categoryTree.getTreeControl(composite); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.widthHint = pixelConverter.convertWidthInCharsToPixels(50); gd.heightHint = pixelConverter.convertHeightInCharsToPixels(2); tree.setLayoutData(gd); createCategoryEditors(composite); categoryTree.setTreeExpansionLevel(2); categoryTree.selectFirstElement(); updateControls(); return composite; } private void createCategoryEditors(Composite parent) { Composite editorArea = new Composite(parent, SWT.NONE); editorArea.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, false)); editorArea.setFont(parent.getFont()); editorAreaStack = new StackLayout(); editorArea.setLayout(editorAreaStack); Map<IncludeKind, IncludeGroupStyle> stylesByKind = new HashMap<IncludeKind, IncludeGroupStyle>(); for (IncludeGroupStyle style : styles) { if (style.getIncludeKind() != IncludeKind.MATCHING_PATTERN) stylesByKind.put(style.getIncludeKind(), style); } for (Category category : categories.values()) { IncludeGroupStyleBlock block = new IncludeGroupStyleBlock(fContext, fProject, fContainer, category.getDescription()); IncludeGroupStyle style = stylesByKind.get(category.getIncludeKind()); block.setStyle(style); Control composite = block.createContents(editorArea); category.setEditor(block, composite); } } @Override protected void updateControls() { super.updateControls(); // Refresh categoryTree.refresh(); updateConfigurationBlock(categoryTree.getSelectedElements()); for (Category category : categories.values()) { category.getEditor().updateControls(); } } private void updateConfigurationBlock(List<Object> selection) { if (selection.size() == 0) return; selectedCategory = (Category) selection.get(0); editorAreaStack.topControl = selectedCategory.getEditorArea(); editorAreaStack.topControl.getParent().layout(); } @Override protected void validateSettings(Key changedKey, String oldValue, String newValue) { fContext.statusChanged(new StatusInfo()); } /** * Represents a category of settings. */ private final static class Category { public final Category parent; public final int index; // Index in the siblings list private final List<Category> children; private final IncludeKind includeKind; private Control editorArea; private IncludeGroupStyleBlock editor; Category(IncludeKind includeKind, Category parent) { this.includeKind = includeKind; this.parent = parent; children = new ArrayList<Category>(); index = parent != null ? parent.addChild(this) : 0; } private int addChild(Category category) { children.add(category); return children.size() - 1; } Category[] getChildren() { return children.toArray(new Category[children.size()]); } boolean hasChildren() { return !children.isEmpty(); } @Override public String toString() { return includeKind.name; } IncludeKind getIncludeKind() { return includeKind; } IncludeGroupStyleBlock getEditor() { return editor; } Control getEditorArea() { return editorArea; } void setEditor(IncludeGroupStyleBlock editor, Control editorArea) { this.editor = editor; this.editorArea = editorArea; } String getName() { return includeKind.name; } String getDescription() { return includeKind.description; } } private class IncludeStyleAdapter extends ViewerComparator implements ITreeListAdapter<Category>, IDialogFieldListener { @Override public void selectionChanged(TreeListDialogField<Category> field) { updateConfigurationBlock(field.getSelectedElements()); } @Override public void customButtonPressed(TreeListDialogField<Category> field, int index) { } @Override public void doubleClicked(TreeListDialogField<Category> field) { } @Override public Category[] getChildren(TreeListDialogField<Category> field, Object element) { return ((Category) element).getChildren(); } @Override public Category getParent(TreeListDialogField<Category> field, Object element) { return ((Category) element).parent; } @Override public boolean hasChildren(TreeListDialogField<Category> field, Object element) { return ((Category) element).hasChildren(); } @Override public void dialogFieldChanged(DialogField field) { } @Override public void keyPressed(TreeListDialogField<Category> field, KeyEvent event) { } @Override public int category(Object element) { return ((Category) element).index; } } private static class IncludeStyleLabelProvider extends LabelProvider { @Override public Image getImage(Object element) { return null; } @Override public String getText(Object element) { return ((Category) element).getName(); } } }