// Copyright (c) 2003-2005 by Leif Frenzel - see http://leiffrenzel.de
package net.sf.eclipsefp.haskell.ui.internal.views.outline;
import java.util.Comparator;
import java.util.List;
import net.sf.eclipsefp.haskell.buildwrapper.types.Location;
import net.sf.eclipsefp.haskell.buildwrapper.types.OutlineDef;
import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin;
import net.sf.eclipsefp.haskell.ui.internal.editors.haskell.HaskellEditor;
import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import net.sf.eclipsefp.haskell.ui.util.HaskellUIImages;
import net.sf.eclipsefp.haskell.ui.util.IImageNames;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
/** <p>The outline page for the Haskell editor.</p>
*
* @author Leif Frenzel
*/
public class HaskellOutlinePage extends ContentOutlinePage {
private List<OutlineDef> input;
private HaskellEditor editor;
public HaskellOutlinePage( final HaskellEditor textEditor ) {
this.editor = textEditor;
}
@Override
public void createControl( final Composite parent ) {
super.createControl( parent );
TreeViewer viewer = getTreeViewer();
viewer.setContentProvider( new OutlineCP() );
viewer.setLabelProvider( new OutlineLabelProvider());
viewer.addSelectionChangedListener( this );
IActionBars actionBars= getSite().getActionBars();
registerToolbarActions(actionBars);
if( input != null ) {
viewer.setInput( input );
}
}
private void registerToolbarActions( final IActionBars actionBars ) {
IToolBarManager toolBarManager= actionBars.getToolBarManager();
toolBarManager.add(new LexicalSortingAction());
}
@Override
public void selectionChanged( final SelectionChangedEvent event ) {
super.selectionChanged( event );
ISelection selection= event.getSelection();
if( selection.isEmpty() ) {
editor.resetHighlightRange();
} else {
IStructuredSelection sel = ( IStructuredSelection )selection;
Object firstElement = sel.getFirstElement();
/*if( firstElement instanceof IHaskellLanguageElement ) {
IHaskellLanguageElement elem = ( IHaskellLanguageElement )firstElement;
IEditorInput fei = editor.getEditorInput();
IDocument doc = editor.getDocumentProvider().getDocument( fei );
ISourceLocation srcLoc = elem.getSourceLocation();
if( srcLoc != null ) {
int offset = -1;
try {
offset = doc.getLineOffset( srcLoc.getLine() ) + srcLoc.getColumn();
} catch( final BadLocationException badlox ) {
// ignore
}
int length = elem.getName().length();
try {
editor.setHighlightRange( offset, length, true );
} catch( IllegalArgumentException iaex ) {
editor.resetHighlightRange();
}
}
}*/
if (firstElement instanceof OutlineDef){
OutlineDef od=(OutlineDef)firstElement;
reveal(editor,od);
}
}
}
/** <p>sets the input of the outline page.</p> */
public void setInput( final List<OutlineDef> outlineDefs ) {
this.input=outlineDefs;
if (this.input!=null){
this.update();
} else {
editor=null;
}
}
public List<OutlineDef> getInput() {
return input;
}
/** <p>updates the outline page.</p> */
public void update() {
if (getControl()!=null && !getControl().isDisposed()){
getControl().getDisplay().asyncExec( new Runnable(){
@Override
public void run() {
TreeViewer viewer = getTreeViewer();
if( viewer != null ) {
Control control= viewer.getControl();
if( control != null && !control.isDisposed() ) {
control.setRedraw( false );
viewer.setInput( input );
viewer.expandToLevel( AbstractTreeViewer.ALL_LEVELS );
control.setRedraw( true );
}
}
}
} );
}
}
class LexicalSortingAction extends Action {
public LexicalSortingAction() {
super();
PlatformUI.getWorkbench().getHelpSystem().setHelp(this, "Outline.LexicalSortingAction"); //$NON-NLS-1$
setText(UITexts.outline_sortByName);
setImageDescriptor(HaskellUIImages.getImageDescriptor( IImageNames.ACTION_SORT ));
setToolTipText(UITexts.outline_sortByName_tooltip);
setDescription(UITexts.outline_sortByName_description);
boolean checked= HaskellUIPlugin.getDefault().getPreferenceStore().getBoolean("Outline.LexicalSortingAction.isChecked"); //$NON-NLS-1$
valueChanged(checked, false);
}
@Override
public void run() {
valueChanged(isChecked(), true);
}
private void valueChanged(final boolean on, final boolean store) {
setChecked(on);
BusyIndicator.showWhile(getTreeViewer().getControl().getDisplay(), new Runnable() {
@Override
public void run() {
if (on) {
getTreeViewer().setComparator(new OutlineDefComparator( OutlineDef.BY_NAME));
} else {
getTreeViewer().setComparator(new OutlineDefComparator(OutlineDef.BY_LOCATION));
}
}
});
if (store) {
HaskellUIPlugin.getDefault().getPreferenceStore().setValue("Outline.LexicalSortingAction.isChecked", on); //$NON-NLS-1$
}
}
}
class OutlineDefComparator extends ViewerComparator{
private final Comparator<OutlineDef> comp;
public OutlineDefComparator( final Comparator<OutlineDef> comp ) {
super();
this.comp = comp;
}
@Override
public int compare( final Viewer viewer, final Object e1, final Object e2 ) {
return comp.compare( (OutlineDef)e1, (OutlineDef)e2 );
}
}
public static void reveal(final HaskellEditor editor,final OutlineDef od){
Location srcLoc=od.getLocation();
if (srcLoc!=null){
IEditorInput fei = editor.getEditorInput();
IDocument doc = editor.getDocumentProvider().getDocument( fei );
try {
int offset=srcLoc.getStartOffset( doc );
int length = srcLoc.getEndOffset( doc )-offset;
try {
//editor.setHighlightRange( offset, length, true );
editor.selectAndReveal( offset, length );
} catch( IllegalArgumentException iaex ) {
editor.resetHighlightRange();
}
} catch( final BadLocationException badlox ) {
// ignore
}
}
}
}