package com.aptana.ruby.internal.debug.ui.display;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener2;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.part.ViewPart;
import com.aptana.core.logging.IdeLog;
import com.aptana.editor.ruby.RubySourceEditor;
import com.aptana.editor.ruby.RubySourceViewerConfiguration;
import com.aptana.ruby.debug.core.model.IEvaluationResult;
import com.aptana.ruby.debug.core.model.IRubyStackFrame;
import com.aptana.ruby.debug.ui.RubyDebugUIPlugin;
import com.aptana.theme.ThemePlugin;
public class DisplayView extends ViewPart implements ITextInputListener, IPerspectiveListener2
{
private IDataDisplay fDataDisplay;
private IDocumentListener fDocumentListener;
private SourceViewer fSourceViewer;
private String fRestoredContents;
/**
* This memento allows the Display view to save and restore state when it is closed and opened within a session. A
* different memento is supplied by the platform for persistance at workbench shutdown.
*/
private static IMemento fgMemento;
/**
* @see ViewPart#createChild(IWorkbenchPartContainer)
*/
public void createPartControl(Composite parent)
{
fSourceViewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
fDataDisplay = new DataDisplay(fSourceViewer);
fSourceViewer.configure(new RubySourceViewerConfiguration(RubySourceEditor.getChainedPreferenceStore(), null));
ThemePlugin.getDefault().getControlThemerFactory().apply(fSourceViewer);
IDocument doc = getRestoredDocument();
fSourceViewer.setDocument(doc);
fSourceViewer.addTextInputListener(this);
doc.addDocumentListener(new IDocumentListener()
{
public void documentChanged(DocumentEvent event)
{
if (event == null)
return;
String text = event.getText();
if (text == null)
return;
String newline = System.getProperty("line.separator"); //$NON-NLS-1$
if (text.equals(newline))
{
// evaluate the expression on this line!
IDocument doc = event.getDocument();
try
{
String prefix = doc.get(0, event.getOffset());
int index = prefix.lastIndexOf(newline);
String line = null;
if (index == -1)
{
line = prefix;
}
else
{
line = prefix.substring(index);
}
IRubyStackFrame frame = ExecuteHandler.getEvaluationContext(getSite().getWorkbenchWindow());
if (frame == null)
return; // no context to evaluate within! Maybe we're not running something under the
// debugger?
if (frame.isSuspended())
{
IEvaluationResult result = frame.evaluate(line);
if (result == null)
return;
IDataDisplay display = (IDataDisplay) getAdapter(IDataDisplay.class);
if (display == null)
return;
String toDisplay = ExecuteHandler.valueToCode(result.getValue());
display.displayExpressionValue(toDisplay);
}
}
catch (Throwable e)
{
IdeLog.logError(RubyDebugUIPlugin.getDefault(), e);
}
}
}
public void documentAboutToBeChanged(DocumentEvent event)
{
// do nothing
}
});
fRestoredContents = null;
// PlatformUI.getWorkbench().getHelpSystem().setHelp(fSourceViewer.getTextWidget(),
// IRubyDebugHelpContextIds.DISPLAY_VIEW);
getSite().getWorkbenchWindow().addPerspectiveListener(this);
}
protected IDocument getRestoredDocument()
{
IDocument doc = null;
if (fRestoredContents != null)
{
doc = new Document(fRestoredContents);
}
else
{
doc = new Document();
}
// FIXME Set up RubyDocumentProvider/partitioner stuff?
// RubyTextTools tools = RubyDebugUIPlugin.getDefault().getRubyTextTools();
// tools.setupRubyDocumentPartitioner(doc, IRubyPartitions.RUBY_PARTITIONING);
return doc;
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPart#setFocus()
*/
public void setFocus()
{
if (fSourceViewer != null)
{
fSourceViewer.getControl().setFocus();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#getAdapter(Class)
*/
@SuppressWarnings("rawtypes")
public Object getAdapter(Class required)
{
if (ITextOperationTarget.class.equals(required))
{
return fSourceViewer.getTextOperationTarget();
}
if (IFindReplaceTarget.class.equals(required))
{
return fSourceViewer.getFindReplaceTarget();
}
if (IDataDisplay.class.equals(required))
{
return fDataDisplay;
}
if (ITextViewer.class.equals(required))
{
return fSourceViewer;
}
return super.getAdapter(required);
}
/**
* Saves the contents of the display view and the formatting.
*
* @see org.eclipse.ui.IViewPart#saveState(IMemento)
*/
public void saveState(IMemento memento)
{
if (fSourceViewer != null)
{
String contents = getContents();
if (contents != null)
{
memento.putTextData(contents);
}
}
else if (fRestoredContents != null)
{
memento.putTextData(fRestoredContents);
}
}
/**
* Restores the contents of the display view and the formatting.
*
* @see org.eclipse.ui.IViewPart#init(IViewSite, IMemento)
*/
public void init(IViewSite site, IMemento memento) throws PartInitException
{
init(site);
if (fgMemento != null)
{
memento = fgMemento;
}
if (memento != null)
{
fRestoredContents = memento.getTextData();
}
}
/**
* Returns the entire trimmed contents of the current document. If the contents are "empty" <code>null</code> is
* returned.
*/
private String getContents()
{
if (fSourceViewer != null)
{
IDocument doc = fSourceViewer.getDocument();
if (doc != null)
{
String contents = doc.get().trim();
if (contents.length() > 0)
{
return contents;
}
}
}
return null;
}
/**
* @see ITextInputListener#inputDocumentAboutToBeChanged(IDocument, IDocument)
*/
public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput)
{
}
/**
* @see ITextInputListener#inputDocumentChanged(IDocument, IDocument)
*/
public void inputDocumentChanged(IDocument oldInput, IDocument newInput)
{
oldInput.removeDocumentListener(fDocumentListener);
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPart#dispose()
*/
public void dispose()
{
getSite().getWorkbenchWindow().removePerspectiveListener(this);
super.dispose();
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.IPerspectiveListener2#perspectiveChanged(org.eclipse.ui.IWorkbenchPage,
* org.eclipse.ui.IPerspectiveDescriptor, org.eclipse.ui.IWorkbenchPartReference, java.lang.String)
*/
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective,
IWorkbenchPartReference partRef, String changeId)
{
if (partRef instanceof IViewReference && changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE))
{
String id = ((IViewReference) partRef).getId();
if (id.equals(getViewSite().getId()))
{
// Display view closed. Persist contents.
String contents = getContents();
if (contents != null)
{
fgMemento = XMLMemento.createWriteRoot("DisplayViewMemento"); //$NON-NLS-1$
fgMemento.putTextData(contents);
}
}
}
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage,
* org.eclipse.ui.IPerspectiveDescriptor)
*/
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective)
{
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage,
* org.eclipse.ui.IPerspectiveDescriptor, java.lang.String)
*/
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId)
{
}
}