/*******************************************************************************
* Copyright (c) 2009, 2015 Alena Laskavaia 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:
* Alena Laskavaia - initial API and implementation
* IBM Corporation
* Marc-Andre Laperle
*******************************************************************************/
package org.eclipse.cdt.codan.internal.ui.preferences;
import java.text.MessageFormat;
import org.eclipse.cdt.codan.core.CodanRuntime;
import org.eclipse.cdt.codan.core.PreferenceConstants;
import org.eclipse.cdt.codan.core.model.CodanSeverity;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemCategory;
import org.eclipse.cdt.codan.core.model.IProblemElement;
import org.eclipse.cdt.codan.core.model.IProblemProfile;
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
import org.eclipse.cdt.codan.core.param.IProblemPreference;
import org.eclipse.cdt.codan.core.param.LaunchModeProblemPreference;
import org.eclipse.cdt.codan.core.param.RootProblemPreference;
import org.eclipse.cdt.codan.internal.core.CodanPreferencesLoader;
import org.eclipse.cdt.codan.internal.ui.CodanUIActivator;
import org.eclipse.cdt.codan.internal.ui.CodanUIMessages;
import org.eclipse.cdt.codan.internal.ui.ImageConstants;
import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
public class ProblemsTreeEditor extends CheckedTreeEditor {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static final String SINGLE_PLACEHOLDER_ONLY = "{0}"; //$NON-NLS-1$
private CodanPreferencesLoader codanPreferencesLoader = new CodanPreferencesLoader();
public ProblemsTreeEditor() {
super();
}
class ProblemsCheckStateProvider implements ICheckStateProvider {
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ICheckStateProvider#isChecked(java.lang
* .Object)
*/
@Override
public boolean isChecked(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
return p.isEnabled();
}
if (element instanceof IProblemCategory) {
// checked if at least one is checked (buy grayed)
IProblemCategory p = (IProblemCategory) element;
Object[] children = p.getChildren();
for (int i = 0; i < children.length; i++) {
Object object = children[i];
if (isChecked(object)) {
return true;
}
}
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ICheckStateProvider#isGrayed(java.lang.
* Object)
*/
@Override
public boolean isGrayed(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
IProblemPreference preference = p.getPreference();
if (preference instanceof RootProblemPreference) {
LaunchModeProblemPreference pref = ((RootProblemPreference) preference).getLaunchModePreference();
if (pref == null) {
return false;
}
boolean enabled = p.isEnabled();
boolean match = pref.isAllEnabled();
if (enabled && match)
return false;
if (!enabled && pref.isAllDisabled())
return false;
return true;
}
return false;
}
if (element instanceof IProblemCategory) {
// checked if at least one is checked (buy grayed)
IProblemCategory p = (IProblemCategory) element;
Object[] children = p.getChildren();
boolean all_checked = true;
boolean all_unchecked = true;
for (int i = 0; i < children.length; i++) {
Object object = children[i];
if (isChecked(object)) {
all_unchecked = false;
} else {
all_checked = false;
}
}
if (all_checked || all_unchecked)
return false;
return true;
}
return false;
}
}
class ProblemsContentProvider implements IContentProvider, ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof Object[])
return (Object[]) parentElement;
if (parentElement instanceof IProblemCategory) {
return ((IProblemCategory) parentElement).getChildren();
}
if (parentElement instanceof IProblemProfile) {
return ((IProblemProfile) parentElement).getRoot().getChildren();
}
return new Object[0];
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
}
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
Object element = event.getElement();
if (element instanceof IProblemWorkingCopy) {
((IProblemWorkingCopy) element).setEnabled(event.getChecked());
} else if (element instanceof IProblemCategory) {
IProblemCategory cat = (IProblemCategory) element;
IProblemElement[] children = cat.getChildren();
for (int i = 0; i < children.length; i++) {
IProblemElement pe = children[i];
checkStateChanged(new CheckStateChangedEvent(getTreeViewer(), pe, event.getChecked()));
}
}
getTreeViewer().refresh();
}
public ProblemsTreeEditor(Composite parent, IProblemProfile profile) {
super(PreferenceConstants.P_PROBLEMS, CodanUIMessages.ProblemsTreeEditor_Problems, parent);
setEmptySelectionAllowed(true);
getTreeViewer().getTree().setHeaderVisible(true);
// getTreeViewer().getTree().
getTreeViewer().setContentProvider(new ProblemsContentProvider());
getTreeViewer().setCheckStateProvider(new ProblemsCheckStateProvider());
//getTreeViewer().getTree().
ColumnViewerToolTipSupport.enableFor(getTreeViewer(), ToolTip.RECREATE);
// column Name
TreeViewerColumn column1 = new TreeViewerColumn(getTreeViewer(), SWT.NONE);
column1.getColumn().setWidth(300);
column1.getColumn().setText(CodanUIMessages.ProblemsTreeEditor_NameColumn);
column1.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
return p.getName();
}
if (element instanceof IProblemCategory) {
IProblemCategory p = (IProblemCategory) element;
return p.getName();
}
return null;
}
@Override
public boolean useNativeToolTip(Object object) {
return true;
}
@Override
public String getToolTipText(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
String sampleMessage = getSampleMessage(p);
int wrapLen = sampleMessage.length();
if (wrapLen < 60)
wrapLen = 60;
if (wrapLen > 100)
wrapLen = 100;
String toolTip = ""; //$NON-NLS-1$
String description = p.getDescription();
if (description != null) {
toolTip = wrapText(description, wrapLen);
toolTip += "\n\n"; //$NON-NLS-1$
}
toolTip += CodanUIMessages.ProblemsTreeEditor_ToolTip;
toolTip += "\n "; //$NON-NLS-1$
toolTip += wrapText(sampleMessage, wrapLen);
return toolTip;
}
return super.getToolTipText(element);
}
private String wrapText(String description, int i) {
String result = ""; //$NON-NLS-1$
while (description.length() > i) {
int k = description.lastIndexOf(' ', i);
if (k < 0)
k = i;
result += description.substring(0, k);
result += '\n';
description = description.substring(k);
}
return result + description;
}
});
// column Severity
TreeViewerColumn column2 = new TreeViewerColumn(getTreeViewer(), SWT.NONE);
column2.getColumn().setWidth(100);
column2.getColumn().setText(CodanUIMessages.ProblemsTreeEditor_SeverityColumn);
column2.setLabelProvider(new ColumnLabelProvider() {
@Override
public Image getImage(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
switch (p.getSeverity().intValue()) {
case IMarker.SEVERITY_INFO:
return CodanUIActivator.getDefault().getImage(ImageConstants.ICON_INFO);
case IMarker.SEVERITY_WARNING:
return CodanUIActivator.getDefault().getImage(ImageConstants.ICON_WARNING);
case IMarker.SEVERITY_ERROR:
return CodanUIActivator.getDefault().getImage(ImageConstants.ICON_ERROR);
}
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof IProblem) {
IProblem p = (IProblem) element;
return p.getSeverity().toTranslatableString();
}
return null;
}
});
column2.setEditingSupport(new EditingSupport(getTreeViewer()) {
@Override
protected boolean canEdit(Object element) {
return element instanceof IProblem;
}
@Override
protected CellEditor getCellEditor(Object element) {
return new ComboBoxCellEditor(getTreeViewer().getTree(), CodanSeverity.stringValues(), SWT.READ_ONLY);
}
@Override
protected Object getValue(Object element) {
return ((IProblem) element).getSeverity().intValue();
}
@Override
protected void setValue(Object element, Object value) {
int index = ((Integer) value).intValue();
CodanSeverity val = CodanSeverity.values()[index];
((IProblemWorkingCopy) element).setSeverity(val);
getTreeViewer().update(element, null);
}
});
getTreeViewer().setAutoExpandLevel(2);
codanPreferencesLoader.setInput(profile);
getViewer().setInput(profile);
}
@Override
protected void doLoad() {
if (getTreeControl() != null) {
IProblem[] probs = codanPreferencesLoader.getProblems();
for (int i = 0; i < probs.length; i++) {
String id = probs[i].getId();
String s = getPreferenceStore().getString(id);
if (s == null || s.length() == 0) {
s = codanPreferencesLoader.getProperty(id);
}
codanPreferencesLoader.setProperty(id, s);
}
getViewer().setInput(codanPreferencesLoader.getInput());
}
}
@Override
protected void doLoadDefault() {
if (getTreeControl() != null) {
CodanPreferencesLoader defaultPreferences = new CodanPreferencesLoader(CodanRuntime.getInstance().getCheckersRegistry().getDefaultProfile());
IProblem[] probs = codanPreferencesLoader.getProblems();
for (int i = 0; i < probs.length; i++) {
String id = probs[i].getId();
String s = getPreferenceStore().getDefaultString(id);
if (s == null || s.length() == 0) {
s = defaultPreferences.getProperty(id);
}
codanPreferencesLoader.setProperty(id, s);
}
getViewer().setInput(codanPreferencesLoader.getInput());
setPresentsDefaultValue(true);
}
}
@Override
protected void doStore() {
codanPreferencesLoader.setInput((IProblemProfile) getViewer().getInput());
IProblem[] probs = codanPreferencesLoader.getProblems();
for (int i = 0; i < probs.length; i++) {
String id = probs[i].getId();
String s = codanPreferencesLoader.getProperty(id);
getPreferenceStore().setValue(id, s);
String params = codanPreferencesLoader.getPreferencesString(id);
if (params != null)
getPreferenceStore().setValue(codanPreferencesLoader.getPreferencesKey(id), params);
}
}
@Override
protected Object modelFromString(String s) {
return codanPreferencesLoader.getInput();
}
@Override
protected String modelToString(Object model) {
return ""; //$NON-NLS-1$
}
public static String getSampleMessage(IProblem problem) {
String messagePattern = problem.getMessagePattern();
String message = CodanUIMessages.CodanPreferencePage_NoInfo;
if (SINGLE_PLACEHOLDER_ONLY.equals(messagePattern)) {
message = EMPTY_STRING;
} else if (messagePattern != null) {
message = MessageFormat.format(messagePattern, "X", "Y", "Z"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return message;
}
@Override
protected CheckboxTreeViewer doCreateTreeViewer(Composite parent, int style) {
PatternFilter filter = new PatternFilter();
filter.setIncludeLeadingWildcard(true);
FilteredTree filteredTree = new FilteredTree(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION,
filter, true) {
@Override
protected TreeViewer doCreateTreeViewer(Composite parent, int style) {
return new CheckboxTreeViewer(parent, style);
}
};
return (CheckboxTreeViewer) filteredTree.getViewer();
}
}