/*******************************************************************************
* Copyright (c) 2010 Alena Laskavaia
* 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
*******************************************************************************/
package org.eclipse.cdt.codan.internal.ui.views;
import java.util.Collection;
import org.eclipse.cdt.codan.core.model.ICodanProblemMarker;
import org.eclipse.cdt.codan.internal.ui.CodanUIActivator;
import org.eclipse.cdt.codan.ui.AbstractCodanProblemDetailsProvider;
import org.eclipse.cdt.codan.ui.CodanEditorUtility;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
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.Composite;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
/**
* Problems Details view show details for selected problem marker.
* Other plugins can contribute to override default behaviour using
* codanProblemDetails extension point.
*/
public class ProblemDetails extends ViewPart {
/**
* The ID of the view as specified by the extension.
*/
public static final String ID = "org.eclipse.cdt.codan.internal.ui.views.ProblemDetails"; //$NON-NLS-1$
private Composite area;
/**
* Control for problem message, which can include location
*/
private Link message;
/**
* Control for problem description which can include links to help or
* web-sites with extra info
*/
private Link description;
private GenericCodanProblemDetailsProvider genProvider = new GenericCodanProblemDetailsProvider();
private AbstractCodanProblemDetailsProvider curProvider = genProvider;
/**
* The constructor.
*/
public ProblemDetails() {
}
/**
* This is a callback that will allow us
* to create the area and initialize it.
*/
@Override
public void createPartControl(Composite parent) {
final String problemsViewId = "org.eclipse.ui.views.ProblemView"; //$NON-NLS-1$
area = new Composite(parent, SWT.NONE);
area.setLayout(new GridLayout());
SelectionAdapter linkSelAdapter = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
String link = e.text;
if (link == null)
return;
if (link.startsWith("http")) { //$NON-NLS-1$
org.eclipse.swt.program.Program.launch(e.text);
return;
}
// link file format example "file:/tmp/file.c#42", 42 is the line number
if (link.startsWith("file:")) { //$NON-NLS-1$
try {
CodanEditorUtility.openFileURL(link, curProvider.getMarker().getResource());
} catch (PartInitException e1) {
CodanUIActivator.log(e1);
} catch (BadLocationException e1) {
CodanUIActivator.log(e1);
}
return;
}
if (link.startsWith("help:")) { //$NON-NLS-1$
// open in eclipse help TODO
return;
}
}
};
message = new Link(area, SWT.WRAP);
message.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
message.addSelectionListener(linkSelAdapter);
description = new Link(area, SWT.WRAP);
description.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
description.addSelectionListener(linkSelAdapter);
ISelectionService ser = (ISelectionService) getSite().getService(ISelectionService.class);
ser.addSelectionListener(new ISelectionListener() {
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (part.getSite().getId().equals(problemsViewId)) {
processSelection(selection);
}
}
});
ISelection selection = ser.getSelection(problemsViewId);
processSelection(selection);
}
protected void processSelection(ISelection selection) {
if (selection == null || selection.isEmpty())
return;
if (selection instanceof IStructuredSelection) {
Object firstElement = ((IStructuredSelection) selection).getFirstElement();
IMarker marker = null;
if (firstElement instanceof IAdaptable) {
marker = (IMarker) ((IAdaptable) firstElement).getAdapter(IMarker.class);
} else if (firstElement instanceof IMarker) {
marker = (IMarker) firstElement;
}
if (marker != null) {
queryProviders(marker);
area.layout();
}
}
}
private void queryProviders(IMarker marker) {
String id = marker.getAttribute(ICodanProblemMarker.ID, "id"); //$NON-NLS-1$
Collection<AbstractCodanProblemDetailsProvider> providers = ProblemDetailsExtensions.getProviders(id);
for (AbstractCodanProblemDetailsProvider provider : providers) {
synchronized (provider) {
provider.setMarker(marker);
if (provider.isApplicable(id)) {
applyProvider(provider);
return;
}
}
}
genProvider.setMarker(marker);
applyProvider(genProvider);
}
private void applyProvider(AbstractCodanProblemDetailsProvider provider) {
curProvider = provider;
setTextSafe(message, provider, provider.getStyledProblemMessage());
setTextSafe(description, provider, provider.getStyledProblemDescription());
}
protected void setTextSafe(Link control, AbstractCodanProblemDetailsProvider provider, String text) {
try {
control.setText(text);
} catch (Exception e) {
// this is debug message
control.setText("failed to set text: " + provider.getClass() + " " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Passing the focus request to the area's control.
*/
@Override
public void setFocus() {
message.setFocus();
}
}