/*******************************************************************************
* Copyright (c) 2011, 2013 Wind River Systems, 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.disassembly;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.debug.ui.disassembly.rulers.IColumnSupport;
import org.eclipse.cdt.debug.ui.disassembly.rulers.IContributedRulerColumn;
import org.eclipse.cdt.debug.ui.disassembly.rulers.RulerColumnDescriptor;
import org.eclipse.cdt.debug.ui.disassembly.rulers.RulerColumnRegistry;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.text.source.CompositeRuler;
import org.eclipse.jface.text.source.IVerticalRulerColumn;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.jface.util.SafeRunnable;
/**
* Implements the ruler column support of for the given disassembly part.
* <p>
* This is currently only used to support vertical ruler columns.
* </p>
*/
class DisassemblyColumnSupport implements IColumnSupport {
private final DisassemblyPart fDisassembly;
private final RulerColumnRegistry fRegistry;
private final List<IContributedRulerColumn> fColumns;
/**
* Creates a new column support for the given disassembly part. Only the disassembly part itself should normally
* create such an instance.
*
* @param editor the disassembly part
* @param registry the contribution registry to refer to
*/
public DisassemblyColumnSupport(DisassemblyPart disassembly, RulerColumnRegistry registry) {
Assert.isLegal(disassembly != null);
Assert.isLegal(registry != null);
fDisassembly= disassembly;
fRegistry= registry;
fColumns= new ArrayList<IContributedRulerColumn>();
}
/*
* @see org.eclipse.ui.texteditor.IColumnSupport#setColumnVisible(java.lang.String, boolean)
*/
@Override
public final void setColumnVisible(RulerColumnDescriptor descriptor, boolean visible) {
Assert.isLegal(descriptor != null);
final CompositeRuler ruler= getRuler();
if (ruler == null)
return;
if (!isColumnSupported(descriptor))
visible= false;
if (isColumnVisible(descriptor)) {
if (!visible)
removeColumn(ruler, descriptor);
} else {
if (visible)
addColumn(ruler, descriptor);
}
}
private void addColumn(final CompositeRuler ruler, final RulerColumnDescriptor descriptor) {
final int idx= computeIndex(ruler, descriptor);
SafeRunnable runnable= new SafeRunnable() {
@Override
public void run() throws Exception {
IContributedRulerColumn column= descriptor.createColumn(fDisassembly);
fColumns.add(column);
initializeColumn(column);
ruler.addDecorator(idx, column);
}
};
SafeRunner.run(runnable);
}
/**
* Hook to let subclasses initialize a newly created column.
* <p>
* Subclasses may extend this method.</p>
*
* @param column the created column
*/
protected void initializeColumn(IContributedRulerColumn column) {
}
private void removeColumn(final CompositeRuler ruler, final RulerColumnDescriptor descriptor) {
removeColumn(ruler, getVisibleColumn(ruler, descriptor));
}
private void removeColumn(final CompositeRuler ruler, final IContributedRulerColumn rulerColumn) {
if (rulerColumn != null) {
SafeRunnable runnable= new SafeRunnable() {
@Override
public void run() throws Exception {
if (ruler != null)
ruler.removeDecorator(rulerColumn);
rulerColumn.columnRemoved();
}
};
SafeRunner.run(runnable);
}
}
/**
* Returns the currently visible column matching <code>id</code>, <code>null</code> if
* none.
*
* @param ruler the composite ruler to scan
* @param descriptor the descriptor of the column of interest
* @return the matching column or <code>null</code>
*/
private IContributedRulerColumn getVisibleColumn(CompositeRuler ruler, RulerColumnDescriptor descriptor) {
for (Iterator<?> it= ruler.getDecoratorIterator(); it.hasNext();) {
IVerticalRulerColumn column= (IVerticalRulerColumn)it.next();
if (column instanceof IContributedRulerColumn) {
IContributedRulerColumn rulerColumn= (IContributedRulerColumn)column;
RulerColumnDescriptor rcd= rulerColumn.getDescriptor();
if (descriptor.equals(rcd))
return rulerColumn;
}
}
return null;
}
/**
* Computes the insertion index for a column contribution into the currently visible columns.
*
* @param ruler the composite ruler into which to insert the column
* @param descriptor the descriptor to compute the index for
* @return the insertion index for a new column
*/
private int computeIndex(CompositeRuler ruler, RulerColumnDescriptor descriptor) {
int index= 0;
List<?> all= fRegistry.getColumnDescriptors();
int newPos= all.indexOf(descriptor);
for (Iterator<?> it= ruler.getDecoratorIterator(); it.hasNext();) {
IVerticalRulerColumn column= (IVerticalRulerColumn) it.next();
if (column instanceof IContributedRulerColumn) {
RulerColumnDescriptor rcd= ((IContributedRulerColumn)column).getDescriptor();
if (rcd != null && all.indexOf(rcd) > newPos)
break;
}
index++;
}
return index;
}
@Override
public final boolean isColumnVisible(RulerColumnDescriptor descriptor) {
Assert.isLegal(descriptor != null);
CompositeRuler ruler= getRuler();
return ruler != null && getVisibleColumn(ruler, descriptor) != null;
}
@Override
public final boolean isColumnSupported(RulerColumnDescriptor descriptor) {
Assert.isLegal(descriptor != null);
if (getRuler() == null)
return false;
return descriptor.matchesPart(fDisassembly);
}
/**
* Returns the disassembly part's vertical ruler, if it is a {@link CompositeRuler}, <code>null</code>
* otherwise.
*
* @return the disassembly part's {@link CompositeRuler} or <code>null</code>
*/
private CompositeRuler getRuler() {
Object ruler= fDisassembly.getAdapter(IVerticalRulerInfo.class);
if (ruler instanceof CompositeRuler)
return (CompositeRuler) ruler;
return null;
}
/**
* {@inheritDoc}
* <p>
* Subclasses may extend this method.</p>
*
*/
@Override
public void dispose() {
for (Iterator<IContributedRulerColumn> iter= new ArrayList<IContributedRulerColumn>(fColumns).iterator(); iter.hasNext();)
removeColumn(getRuler(), iter.next());
fColumns.clear();
}
}