/*******************************************************************************
* Copyright (c) 2016 ARM Ltd. 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:
* ARM Ltd and ARM Germany GmbH - Initial API and implementation
*******************************************************************************/
package com.arm.cmsis.config.editors;
import java.util.Collection;
import java.util.Map;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.internal.ui.editor.asm.AsmTextEditor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
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.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import com.arm.cmsis.config.IHelpContextIds;
import com.arm.cmsis.config.Messages;
import com.arm.cmsis.config.model.IConfigWizardItem;
import com.arm.cmsis.config.model.IConfigWizardItem.EItemErrorType;
import com.arm.cmsis.config.model.IConfigWizardItem.EItemType;
import com.arm.cmsis.pack.ui.CpPlugInUI;
import com.arm.cmsis.pack.ui.tree.AdvisedCellLabelProvider;
import com.arm.cmsis.pack.ui.tree.AdvisedEditingSupport;
import com.arm.cmsis.pack.ui.tree.ColumnAdvisor;
import com.arm.cmsis.pack.ui.tree.IColumnAdvisor;
import com.arm.cmsis.parser.ConfigWizardParser;
import com.arm.cmsis.parser.ConfigWizardScanner;
import com.arm.cmsis.utils.Utils;
/**
* An example showing how to create a multi-page editor. This example has 3
* pages:
* <ul>
* <li>page 0 contains a nested text editor.
* <li>page 1 allows you to use configuration wizard
* </ul>
*/
@SuppressWarnings("restriction")
public class ConfigEditor extends MultiPageEditorPart implements IResourceChangeListener {
/** The text editor used in page 0. */
TextEditor editor;
/** The document in the editor. */
private IDocument fDocument;
/** The resource file in the workspace*/
IFile fFile;
/** parser job for the config wizard. */
Job fParserJob;
/** parser for the config wizard. */
ConfigWizardParser fParser;
/** True if user has changed the text before switch pages */
boolean fNeedReparse;
/** The tree viewer */
TreeViewer fViewer;
/** The second column's advisor */
private IColumnAdvisor fColumnAdvisor;
/** The tooltip text */
private StyledText fText;
IConfigWizardItem getConfigWizardItem(Object obj) {
if (obj instanceof IConfigWizardItem) {
return (IConfigWizardItem) obj;
}
return null;
}
/**
* Creates a multi-page editor example.
*/
public ConfigEditor() {
super();
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
fParserJob = new Job(Messages.ConfigEditor_ParsingConfigWizard) {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask(Messages.ConfigEditor_ParsingConfigWizard, 100);
monitor.worked(98);
fParser.parse();
fNeedReparse = false;
monitor.done();
return Status.OK_STATUS;
}
};
fParserJob.setUser(true);
fParserJob.setPriority(Job.INTERACTIVE);
fParserJob.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
IConfigWizardItem root = fParser.getConfigWizardRoot();
if (root == null) { // parsing error
editor.selectAndReveal(fParser.getParsingErrorOffset(), 0);
} else if (fViewer.getControl() != null &&
!fViewer.getControl().isDisposed()) {
fViewer.setInput(root);
}
}
});
}
});
}
/**
* Creates page 0 of the multi-page editor, which contains a text editor.
*/
void createPage0() {
try {
IEditorInput editorInput = getEditorInput();
if (editorInput.getName().toLowerCase().endsWith(".s")) { //$NON-NLS-1$
editor = new AsmTextEditor();
} else {
editor = new CEditor();
}
int index = addPage(editor, getEditorInput());
setPageText(index, Messages.ConfigEditor_FirstPageText);
setPartName(editor.getTitle());
setTitleImage(CpPlugInUI.getImage(CpPlugInUI.ICON_DETAILS));
fDocument = editor.getDocumentProvider().getDocument(editor.getEditorInput());
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(), Messages.ConfigEditor_ErrorInNestedTextEditor,
null, e.getStatus());
}
}
/**
* Creates page 1 of the multi-page editor, which shows the
* configuration wizard
*/
void createPage1() {
Composite composite = new Composite(getContainer(), SWT.NONE);
composite.setLayout(new GridLayout(3, false));
buildToolBar(composite);
buildTreeViewer(composite);
buildText(composite);
int index = addPage(composite);
setPageText(index, Messages.ConfigEditor_SecondPageText);
}
/**
* Creates the pages of the multi-page editor.
*/
@Override
protected void createPages() {
createPage0();
fParser = new ConfigWizardParser(new ConfigWizardScanner(editor instanceof AsmTextEditor), fDocument);
if (fParser.containWizard()) {
fParserJob.schedule();
createPage1();
hookDocumentChangeListener();
setActivePage(1);
}
}
protected void hookDocumentChangeListener() {
fDocument.addDocumentListener(new IDocumentListener() {
@Override
public void documentChanged(DocumentEvent event) {
fNeedReparse = true;
}
@Override
public void documentAboutToBeChanged(DocumentEvent event) {
// do nothing
}
});
}
/**
* The <code>MultiPageEditorPart</code> implementation of this
* <code>IWorkbenchPart</code> method disposes all nested editors.
* Subclasses may extend.
*/
@Override
public void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
super.dispose();
}
/**
* Saves the multi-page editor's document.
*/
@Override
public void doSave(IProgressMonitor monitor) {
getEditor(0).doSave(monitor);
}
/**
* Saves the multi-page editor's document as another file. Also updates the
* text for page 0's tab, and updates this multi-page editor's input to
* correspond to the nested editor's.
*/
@Override
public void doSaveAs() {
IEditorPart editor = getEditor(0);
editor.doSaveAs();
setPartName(editor.getTitle());
setInput(editor.getEditorInput());
}
@Override
protected void setInput(IEditorInput input) {
super.setInput(input);
fFile = ResourceUtil.getFile(input);
String title= input.getName();
setPartName(title);
}
/**
* The <code>MultiPageEditorExample</code> implementation of this method
* checks that the input is an instance of <code>IFileEditorInput</code>.
*/
@Override
public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException {
if (!(editorInput instanceof IFileEditorInput)) {
throw new PartInitException(Messages.ConfigEditor_InvalidEditorInput);
}
super.init(site, editorInput);
}
@Override
public boolean isSaveAsAllowed() {
return true;
}
/**
* Calculates the contents of page 2 when the it is activated.
*/
@Override
protected void pageChange(int newPageIndex) {
if (newPageIndex == 1 && fNeedReparse) {
if (fParser.findConfigurationWizard()) {
fParserJob.schedule();
fNeedReparse = false;
super.pageChange(newPageIndex);
} else {
removePage(1);
}
return;
} else if (newPageIndex == 0) {
fNeedReparse = false;
}
super.pageChange(newPageIndex);
}
/**
* Closes all project files on project close.
*/
@Override
public void resourceChanged(final IResourceChangeEvent event) {
// consider only POST_CHANGE events
if (event.getType() != IResourceChangeEvent.POST_CHANGE) {
return;
}
IResourceDelta resourseDelta = event.getDelta();
IResourceDeltaVisitor deltaVisitor = new IResourceDeltaVisitor() {
@Override
public boolean visit(IResourceDelta delta) {
IResource resource = delta.getResource();
int type = resource.getType();
if (type == IResource.ROOT) {
return true; // workspace => visit children
}
int kind = delta.getKind();
int flags = delta.getFlags();
if (type == IResource.FILE && kind == IResourceDelta.REMOVED
&& resource.equals(fFile)) {
if ((flags & IResourceDelta.MOVED_TO) == IResourceDelta.MOVED_TO) {
// renamed
IPath newPath = delta.getMovedToPath();
IFile r = (IFile) ResourcesPlugin.getWorkspace()
.getRoot().findMember(newPath);
final FileEditorInput fileEditorInput = new FileEditorInput(
r);
Display.getDefault().asyncExec(() -> setInput(fileEditorInput));
return false;
} else if (flags == 0 // project deleted
|| (flags & IResourceDelta.MARKERS) != 0) { // markers have changed
Display.getDefault().asyncExec(() -> {
ConfigEditor.this.getEditorSite().getPage()
.closeEditor(ConfigEditor.this, true);
});
return false;
}
}
return true;
}
};
try {
resourseDelta.accept(deltaVisitor);
} catch (CoreException e) {
e.printStackTrace();
}
}
@Override
protected Control getControl(int pageIndex) {
if (pageIndex == 1) {
return fViewer.getControl();
}
return super.getControl(pageIndex);
}
@Override
public void setFocus() {
if (fNeedReparse && getActivePage() == 1) {
if (fParser.findConfigurationWizard()) {
fParserJob.schedule();
fNeedReparse = false;
} else {
removePage(1);
}
}
super.setFocus();
}
/************************* Here begins the Configuration Wizard GUI part *************************/
class ManagedToolBar {
ToolBar toolBar;
ToolBarManager toolBarManager;
public ManagedToolBar(final Composite parent, int style){
toolBarManager = new ToolBarManager(style);
toolBar = toolBarManager.createControl(parent);
toolBar.setLayoutData(new GridData(GridData.FILL_HORIZONTAL|GridData.GRAB_HORIZONTAL));
toolBar.addListener(SWT.FOCUSED, new Listener() {
@Override
public void handleEvent(Event event) {
parent.setFocus();
}
});
}
public void addAction(IAction action, boolean showText) {
if(showText) {
ActionContributionItem aci = new ActionContributionItem(action);
aci.setMode(ActionContributionItem.MODE_FORCE_TEXT);
toolBarManager.add(aci);
} else {
toolBarManager.add(action);
}
toolBarManager.update(true);
}
public void dispose() {
toolBarManager.removeAll();
toolBarManager.dispose();
toolBarManager = null;
toolBar = null;
}
}
private void buildToolBar(Composite parent) {
Label imageLabel = new Label(parent, SWT.LEFT);
imageLabel.setImage(CpPlugInUI.getImage(CpPlugInUI.ICON_DETAILS));
Label title = new Label(parent, SWT.NONE);
FontDescriptor boldDescriptor = FontDescriptor.createFrom(title.getFont()).setStyle(SWT.BOLD).increaseHeight(1);
Font boldFont = boldDescriptor.createFont(title.getDisplay());
title.setFont(boldFont);
title.setText(Messages.ConfigEditor_SecondPageText);
ManagedToolBar toolbar = new ManagedToolBar(parent, SWT.FLAT|SWT.RIGHT_TO_LEFT);
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IHelpContextIds.CONFIG_WIZARD);
Action help = new Action(Messages.ConfigEditor_Help, IAction.AS_PUSH_BUTTON) {
@Override
public void run() {
parent.notifyListeners(SWT.Help, new Event());
}
};
help.setToolTipText(Messages.ConfigEditor_HelpForConfigWizard);
help.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_HELP));
toolbar.addAction(help, false);
Action collapseAll = new Action(Messages.ConfigEditor_CollapseAll, IAction.AS_PUSH_BUTTON) {
@Override
public void run() {
fViewer.collapseAll();
}
};
collapseAll.setToolTipText(Messages.ConfigEditor_CollapseAllItems);
collapseAll.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_COLLAPSE_ALL));
toolbar.addAction(collapseAll, false);
Action expandAll = new Action(Messages.ConfigEditor_ExpandAll, IAction.AS_PUSH_BUTTON) {
@Override
public void run() {
fViewer.expandAll();
}
};
expandAll.setToolTipText(Messages.ConfigEditor_ExpandAllItems);
expandAll.setImageDescriptor(CpPlugInUI.getImageDescriptor(CpPlugInUI.ICON_EXPAND_ALL));
toolbar.addAction(expandAll, false);
}
private void buildText(Composite parent) {
fText = new StyledText(parent, SWT.MULTI | SWT.BORDER);
fText.setEnabled(false);
fText.setEditable(false);
GridData gd_text = new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1);
gd_text.heightHint = 80;
fText.setLayoutData(gd_text);
}
class ContentProvider implements ITreeContentProvider {
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
IConfigWizardItem item = getConfigWizardItem(parentElement);
if (item != null) {
return item.getChildren().toArray();
}
return new Object[0];
}
@Override
public Object getParent(Object element) {
IConfigWizardItem item = getConfigWizardItem(element);
if (item != null) {
return item.getParent();
}
return null;
}
@Override
public boolean hasChildren(Object element) {
return getChildren(element) != null && getChildren(element).length > 0;
}
}
class FirstColumnLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object obj) {
IConfigWizardItem item = getConfigWizardItem(obj);
if (item != null) {
return item.getName();
}
return null;
}
@Override
public Color getForeground(Object element) {
IConfigWizardItem item = getConfigWizardItem(element);
if (item.isInconsistent()) {
return new Color(Display.getDefault(), 255, 0, 0);
}
return super.getForeground(element);
}
@Override
public String getToolTipText(Object obj) {
IConfigWizardItem item = getConfigWizardItem(obj);
if (item != null && !item.getTooltip().isEmpty()) {
return item.getTooltip();
}
return null;
}
}
private static final int COLEDIT = 1;
private class ConfigColumnAdvisor extends ColumnAdvisor {
public ConfigColumnAdvisor(ColumnViewer columnViewer) {
super(columnViewer);
}
@Override
public CellControlType getCellControlType(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
EItemType type = item.getItemType();
switch (type) {
case HEADING_ENABLE:
case OPTION_CHECK:
case CODE_ENABLE:
case CODE_DISABLE:
return CellControlType.CHECK;
case OPTION_SELECT:
return CellControlType.MENU;
case OPTION:
if (item.getSpinStep() != 0) {
return CellControlType.SPIN;
}
break;
default:
break;
}
return CellControlType.TEXT;
}
@Override
public boolean isEnabled(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
return item.canModify();
}
@Override
public boolean canEdit(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
EItemType type = item.getItemType();
switch (type) {
case HEADING:
return false;
case HEADING_ENABLE:
case CODE_ENABLE:
case CODE_DISABLE:
return isEnabled(item.getParent(), columnIndex);
case OPTION:
case OPTION_CHECK:
case OPTION_SELECT:
case OPTION_STRING:
return isEnabled(obj, columnIndex);
default:
break;
}
return false;
}
@Override
public boolean getCheck(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
return item.getValue() > 0;
}
@Override
public void setCheck(Object element, int columnIndex, boolean newVal) {
IConfigWizardItem item = getConfigWizardItem(element);
fParser.updateModel(item, newVal);
fViewer.update(item, null);
fViewer.refresh();
}
@Override
public Image getImage(Object obj, int columnIndex) {
if (getCellControlType(obj, columnIndex) == CellControlType.INPLACE_CHECK
|| getCellControlType(obj, columnIndex) == CellControlType.CHECK) {
boolean check = getCheck(obj, columnIndex);
boolean enabled = canEdit(obj, columnIndex);
Image image;
if (enabled) {
image = check ? CpPlugInUI.getImage(CpPlugInUI.ICON_CHECKED)
: CpPlugInUI.getImage(CpPlugInUI.ICON_UNCHECKED);
} else {
image = check ? CpPlugInUI.getImage(CpPlugInUI.ICON_CHECKED_GREY)
: CpPlugInUI.getImage(CpPlugInUI.ICON_UNCHECKED_GREY);
}
return image;
}
return super.getImage(obj, columnIndex);
}
@Override
public String getString(Object obj, int columnIndex) {
CellControlType type = getCellControlType(obj, columnIndex);
if (type == CellControlType.CHECK) {
return null;
}
IConfigWizardItem item = getConfigWizardItem(obj);
EItemErrorType errorType = item.getItemErrorType();
if (errorType == EItemErrorType.NUMBER_PARSE_ERROR) {
return "<<< Invalid number >>>"; //$NON-NLS-1$
} else if (errorType == EItemErrorType.LOCATE_POSITION_ERROR) {
return "<<< Unable to locate value position >>>"; //$NON-NLS-1$
}
if (item.getItemType() == EItemType.OPTION_STRING) {
return item.getString().replace("\\\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$
}
// for heading item and notification item, there is no value to show
if (item.getItemType() == EItemType.HEADING || item.getItemType() == EItemType.ROOT
|| item.getItemType() == EItemType.NOTIFICATION) {
return null;
}
long value = item.getValue();
long modifier = item.getModifier();
char op = item.getModification();
long realValue = Utils.modifyValueR(value, op, modifier,
item.getMaxValue(), item.getMinValue());
if (type == CellControlType.MENU) {
Map<Long, String> items = item.getItems();
if (items.containsKey(realValue)) {
return items.get(realValue);
}
return "<<< Invalid Index >>>"; //$NON-NLS-1$
}
if (item.getBase() == 10) {
return String.valueOf(realValue);
} else if (item.getBase() == 2) {
String str = Long.toBinaryString(realValue);
StringBuilder sb = new StringBuilder(str);
int idx = sb.length() - 4;
while (idx > 0) {
sb.insert(idx, " "); //$NON-NLS-1$
idx = idx - 4;
}
return "0b" + sb.toString().toUpperCase(); //$NON-NLS-1$
} else if (item.getBase() == 8) {
String str = Long.toOctalString(realValue);
return "0" + str; //$NON-NLS-1$
} else {
String str = Long.toHexString(realValue);
if (!str.startsWith("0") && str.length()%2 != 0) { //$NON-NLS-1$
str = "0" + str; //$NON-NLS-1$
}
StringBuilder sb = new StringBuilder(str);
int idx = sb.length() - 4;
while (idx > 0) {
sb.insert(idx, " "); //$NON-NLS-1$
idx = idx - 4;
}
return "0x" + sb.toString().toUpperCase(); //$NON-NLS-1$
}
}
@Override
public long getCurrentSelectedIndex(Object element, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(element);
// This is selection
if (item.getItemType() == EItemType.OPTION_SELECT) {
long key = item.getValue();
int i = 0;
for (Long k : item.getItems().keySet()) {
if (k == key) {
return i;
}
i++;
}
return 0;
}
long modifier = item.getModifier();
char op = item.getModification();
long realValue = Utils.modifyValueR(item.getValue(), op, modifier,
item.getMaxValue(), item.getMinValue());
return realValue;
}
@Override
public void setCurrentSelectedIndex(Object obj, int columnIndex, long newVal) {
IConfigWizardItem item = getConfigWizardItem(obj);
// This is selection
fParser.updateModel(item, newVal);
fViewer.update(item, null);
}
@Override
public String[] getStringArray(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
Assert.isTrue(item.getItemType() == EItemType.OPTION_SELECT);
Collection<String> str = item.getItems().values();
return str.toArray(new String[str.size()]);
}
@Override
public long getMaxCount(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
long max = item.getMaxValue();
return max;
}
@Override
public long getMinCount(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
long min = item.getMinValue();
if (min < 0) {
min = 0;
}
return min;
}
@Override
public long getSpinStep(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
long spinStep = item.getSpinStep();
return spinStep;
}
@Override
public int getItemBase(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
return item.getBase();
}
@Override
public void setString(Object obj, int columnIndex, String newVal) {
if (getCellControlType(obj, columnIndex) == CellControlType.CHECK) {
return;
}
IConfigWizardItem item = getConfigWizardItem(obj);
fParser.updateModel(item, newVal);
fViewer.update(item, null);
}
@Override
public String getTooltipText(Object obj, int columnIndex) {
IConfigWizardItem item = getConfigWizardItem(obj);
if (item.getTooltip().isEmpty()) {
return null;
}
return item.getTooltip();
}
}
private void buildTreeViewer(Composite parent) {
fViewer = new TreeViewer(parent, SWT.FULL_SELECTION | SWT.BORDER |
SWT.H_SCROLL | SWT.V_SCROLL);
Tree tree = fViewer.getTree();
tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
tree.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem item = (TreeItem) e.item;
if (item != null) {
IConfigWizardItem configItem = getConfigWizardItem(item.getData());
if (configItem != null) {
setCursorAndRevealAt(configItem.getStartLine());
showTooltipText(configItem);
}
}
}
});
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
fColumnAdvisor = new ConfigColumnAdvisor(fViewer);
TreeViewerColumn column0 = new TreeViewerColumn(fViewer, SWT.LEFT);
column0.getColumn().setText(Messages.ConfigEditor_Option);
column0.getColumn().setWidth(320);
column0.setLabelProvider(new FirstColumnLabelProvider());
TreeViewerColumn column1 = new TreeViewerColumn(fViewer, SWT.LEFT);
column1.getColumn().setText(Messages.ConfigEditor_Value);
column1.getColumn().setWidth(100);
column1.setEditingSupport(new AdvisedEditingSupport(fViewer, fColumnAdvisor, COLEDIT));
column1.setLabelProvider(new AdvisedCellLabelProvider(fColumnAdvisor, COLEDIT));
// Add an empty column and adjust its width automatically for better looking
TreeViewerColumn column2 = new TreeViewerColumn(fViewer, SWT.LEFT);
column2.getColumn().setWidth(1);
column2.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return ""; //$NON-NLS-1$
}
});
if (System.getProperty("os.name").startsWith("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$
parent.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
Tree tree = (Tree) fViewer.getControl();
Rectangle area = parent.getClientArea();
Point preferredSize = tree.computeSize(SWT.DEFAULT, SWT.DEFAULT);
int width = area.width - 2*tree.getBorderWidth();
if (preferredSize.y > tree.getBounds().height) {
// Subtract the scrollbar width from the total column width
// if a vertical scrollbar will be required
Point vBarSize = tree.getVerticalBar().getSize();
width -= vBarSize.x;
}
Point oldSize = tree.getSize();
if (oldSize.x > area.width) {
// tree is getting smaller so make the columns
// smaller first and then resize the tree to
// match the client area width
column2.getColumn().setWidth(Math.max(0, width - column0.getColumn().getWidth() -
column1.getColumn().getWidth() - 10));
tree.setSize(area.width, area.height);
} else {
// tree is getting bigger so make the tree
// bigger first and then make the columns wider
// to match the client area width
tree.setSize(area.width, area.height);
column2.getColumn().setWidth(Math.max(0, width - column0.getColumn().getWidth() -
column1.getColumn().getWidth() - 10));
}
}
});
}
fViewer.setContentProvider(new ContentProvider());
fViewer.setInput(fParser.getConfigWizardRoot());
ColumnViewerToolTipSupport.enableFor(fViewer);
}
void setCursorAndRevealAt(int line) {
try {
int offset = fDocument.getLineOffset(line);
editor.selectAndReveal(offset, 0);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
void showTooltipText(IConfigWizardItem configItem) {
if (configItem.getTooltip().isEmpty()) {
fText.setText(""); //$NON-NLS-1$
return;
}
String name = configItem.getName() + System.lineSeparator();
String tooltip = configItem.getTooltip();
fText.setText(name + tooltip);
StyleRange styleRange = new StyleRange();
styleRange.start = 0;
styleRange.length = name.length();
styleRange.fontStyle = SWT.BOLD;
styleRange.foreground = Display.getDefault().getSystemColor(SWT.COLOR_BLACK);
fText.setStyleRange(styleRange);
}
}