package de.unisiegen.tpml.graphics.outline;
import java.awt.Color;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Timer;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.tree.TreePath;
import de.unisiegen.tpml.core.expressions.Attribute;
import de.unisiegen.tpml.core.expressions.CurriedMethod;
import de.unisiegen.tpml.core.expressions.Expression;
import de.unisiegen.tpml.core.expressions.Identifier;
import de.unisiegen.tpml.core.expressions.Method;
import de.unisiegen.tpml.core.interfaces.BoundIdentifiers;
import de.unisiegen.tpml.core.interfaces.BoundTypeNames;
import de.unisiegen.tpml.core.interfaces.DefaultExpressions;
import de.unisiegen.tpml.core.interfaces.DefaultIdentifiers;
import de.unisiegen.tpml.core.interfaces.DefaultTypeNames;
import de.unisiegen.tpml.core.interfaces.DefaultTypes;
import de.unisiegen.tpml.core.interfaces.ExpressionOrType;
import de.unisiegen.tpml.core.interfaces.SortedChildren;
import de.unisiegen.tpml.core.prettyprinter.PrettyAnnotation;
import de.unisiegen.tpml.core.types.MonoType;
import de.unisiegen.tpml.core.types.Type;
import de.unisiegen.tpml.core.types.TypeName;
import de.unisiegen.tpml.core.util.Theme;
import de.unisiegen.tpml.graphics.StyledLanguageDocument;
import de.unisiegen.tpml.graphics.bigstep.BigStepView;
import de.unisiegen.tpml.graphics.editor.TextEditorPanel;
import de.unisiegen.tpml.graphics.editor.TypeEditorPanel;
import de.unisiegen.tpml.graphics.minimaltyping.MinimalTypingView;
import de.unisiegen.tpml.graphics.outline.binding.OutlineBinding;
import de.unisiegen.tpml.graphics.outline.binding.OutlineUnbound;
import de.unisiegen.tpml.graphics.outline.listener.OutlineActionListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineComponentListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineItemListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineKeyListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineMouseListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlinePropertyChangeListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineTreeExpansionListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineTreeModelListener;
import de.unisiegen.tpml.graphics.outline.listener.OutlineTreeSelectionListener;
import de.unisiegen.tpml.graphics.outline.node.OutlineNode;
import de.unisiegen.tpml.graphics.outline.ui.OutlineDisplayTree;
import de.unisiegen.tpml.graphics.outline.ui.OutlineTimerTask;
import de.unisiegen.tpml.graphics.outline.ui.OutlineUI;
import de.unisiegen.tpml.graphics.outline.util.OutlinePreferences;
import de.unisiegen.tpml.graphics.smallstep.SmallStepView;
import de.unisiegen.tpml.graphics.subtyping.SubTypingView;
import de.unisiegen.tpml.graphics.typechecker.TypeCheckerView;
import de.unisiegen.tpml.graphics.typeinference.TypeInferenceView;
/**
* This class is the main class of the {@link Outline}. It loads the
* {@link OutlinePreferences}, creates the {@link OutlineUI} and loads new
* {@link Expression}s.
*
* @author Christian Fehler
* @version $Rev$
*/
public final class DefaultOutline implements Outline
{
/**
* The free attribute set name.
*/
private static final String SELECTED = "selected"; //$NON-NLS-1$
/**
* The bound identifier attribute set name.
*/
private static final String IDENTIFER = "identifier"; //$NON-NLS-1$
/**
* The bound type name attribute set name.
*/
private static final String TYPE_NAME = "type_name"; //$NON-NLS-1$
/**
* The {@link OutlineUI}.
*
* @see #getUI()
*/
private OutlineUI uI = null;
/**
* The {@link OutlineItemListener}.
*/
private OutlineItemListener itemListener = null;
/**
* The {@link OutlinePreferences}.
*
* @see #getPreferences()
*/
private OutlinePreferences preferences = null;
/**
* The loaded {@link ExpressionOrType}.
*/
private ExpressionOrType loadedExpressionOrType = null;
/**
* The {@link OutlineUnbound}, in which the unbound {@link Identifier}s in
* the given {@link Expression} are saved.
*/
private OutlineUnbound outlineUnbound = null;
/**
* The <code>Timer</code> for the executing.
*/
private Timer outlineTimer = null;
/**
* The root {@link OutlineNode}.
*/
private OutlineNode rootNode = null;
/**
* The {@link TextEditorPanel}.
*/
private TextEditorPanel sourceView = null;
/**
* The {@link TypeEditorPanel}.
*/
private TypeEditorPanel typeEditorPanel = null;
/**
* The sync outline.
*/
private DefaultOutline syncOutline = null;
/**
* The error status of the {@link Outline}.
*/
private boolean error = false;
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pBigStepView The {@link BigStepView}.
*/
public DefaultOutline ( BigStepView pBigStepView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateAutoUpdate ();
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pBigStepView.getJSplitPane (), this ) );
// PropertyChangeListener
pBigStepView.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pBigStepView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pBigStepView.getBigStepProofModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pBigStepView
.getBigStepProofModel () ) );
// MouseListener
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pMinimalTypingView The {@link MinimalTypingView}.
*/
public DefaultOutline ( MinimalTypingView pMinimalTypingView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateAutoUpdate ();
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pMinimalTypingView.getJSplitPane (),
this ) );
// PropertyChangeListener
pMinimalTypingView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pMinimalTypingView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pMinimalTypingView.getMinimalTypingProofModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pMinimalTypingView
.getMinimalTypingProofModel () ) );
// MouseListener
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pSmallStepView {@link SmallStepView}.
*/
public DefaultOutline ( SmallStepView pSmallStepView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pSmallStepView.getJSplitPane (), this ) );
// PropertyChangeListener
pSmallStepView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pSmallStepView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pSmallStepView.getSmallStepProofModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pSmallStepView
.getSmallStepProofModel () ) );
// MouseListener
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemAutoUpdate ()
.addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxAutoUpdate ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pSubTypingSourceView The {@link TypeEditorPanel}.
* @param pModus The {@link Outline.Modus} of this {@link Outline}.
*/
public DefaultOutline ( TypeEditorPanel pSubTypingSourceView,
Outline.Modus pModus )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.typeEditorPanel = pSubTypingSourceView;
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pSubTypingSourceView.getJSplitPane (),
this ) );
// MouseListener
switch ( pModus )
{
case FIRST :
{
pSubTypingSourceView.getEditor ().addMouseListener (
new OutlineMouseListener ( this, pSubTypingSourceView ) );
break;
}
case SECOND :
{
pSubTypingSourceView.getEditor2 ().addMouseListener (
new OutlineMouseListener ( this, pSubTypingSourceView ) );
break;
}
}
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// PropertyChangeListener
pSubTypingSourceView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pSubTypingSourceView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemHighlightSourceCode ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemAutoUpdate ()
.addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxHighlightSourceCode ().addItemListener (
this.itemListener );
this.uI.getJCheckBoxAutoUpdate ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pSubTypingView The {@link SubTypingView}.
*/
public DefaultOutline ( SubTypingView pSubTypingView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateAutoUpdate ();
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pSubTypingView.getJSplitPane (), this ) );
// PropertyChangeListener
pSubTypingView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pSubTypingView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pSubTypingView.getSubTypingModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pSubTypingView ) );
// MouseListener
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pSourceView The {@link TextEditorPanel}.
*/
public DefaultOutline ( TextEditorPanel pSourceView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.sourceView = pSourceView;
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pSourceView.getJSplitPane (), this ) );
// MouseListener
this.sourceView.getEditor ().addMouseListener (
new OutlineMouseListener ( this, pSourceView ) );
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// PropertyChangeListener
this.sourceView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
this.sourceView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemHighlightSourceCode ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemAutoUpdate ()
.addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxHighlightSourceCode ().addItemListener (
this.itemListener );
this.uI.getJCheckBoxAutoUpdate ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pTypeCheckerView The {@link TypeCheckerView}.
*/
public DefaultOutline ( TypeCheckerView pTypeCheckerView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateAutoUpdate ();
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ()
.addComponentListener (
new OutlineComponentListener ( pTypeCheckerView.getJSplitPane (),
this ) );
// PropertyChangeListener
pTypeCheckerView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pTypeCheckerView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pTypeCheckerView.getTypeCheckerProofModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pTypeCheckerView
.getTypeCheckerProofModel () ) );
// MouseListener
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Initilizes the {@link OutlinePreferences} and the {@link OutlineUI}.
*
* @param pTypeInferenceView The {@link TypeInferenceView}.
*/
public DefaultOutline ( TypeInferenceView pTypeInferenceView )
{
this.preferences = new OutlinePreferences ();
this.uI = new OutlineUI ( this );
this.uI.deactivateAutoUpdate ();
this.uI.deactivateHighlightSourceCode ();
// ComponentListener
this.uI.getJScrollPaneOutline ().addComponentListener (
new OutlineComponentListener ( pTypeInferenceView.getJSplitPane (),
this ) );
// PropertyChangeListener
pTypeInferenceView
.addPropertyChangeListener ( new OutlinePropertyChangeListener (
pTypeInferenceView.getJSplitPane (), this ) );
Theme.currentTheme ().addPropertyChangeListener (
new OutlinePropertyChangeListener ( this ) );
// TreeModelListener
pTypeInferenceView.getTypeInferenceProofModel ().addTreeModelListener (
new OutlineTreeModelListener ( this, pTypeInferenceView
.getTypeInferenceProofModel () ) );
this.uI.getJTreeOutline ().addMouseListener (
new OutlineMouseListener ( this ) );
// ActionListener
OutlineActionListener outlineActionListener = new OutlineActionListener (
this );
this.uI.getJMenuItemExpand ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemExpandAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapse ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCollapseAll ().addActionListener (
outlineActionListener );
this.uI.getJMenuItemClose ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCloseAll ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemCopy ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemSelection ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemBinding ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemFree ().addActionListener ( outlineActionListener );
this.uI.getJMenuItemReplace ().addActionListener ( outlineActionListener );
// ComponentListener
this.uI.getJPanelMain ().addComponentListener (
new OutlineComponentListener ( this ) );
// ItemListener
this.itemListener = new OutlineItemListener ( this );
this.uI.getJCheckBoxSelection ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxBinding ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxFree ().addItemListener ( this.itemListener );
this.uI.getJCheckBoxReplace ().addItemListener ( this.itemListener );
// KeyListener
this.uI.getJTreeOutline ()
.addKeyListener ( new OutlineKeyListener ( this ) );
// TreeExpansionListener
this.uI.getJTreeOutline ().addTreeExpansionListener (
new OutlineTreeExpansionListener ( this ) );
// TreeSelectionListener
this.uI.getJTreeOutline ().getSelectionModel ().addTreeSelectionListener (
new OutlineTreeSelectionListener ( this ) );
}
/**
* Creates the children with the given {@link Expression} and adds them to the
* given {@link OutlineNode}.
*
* @param pExpression The {@link Expression}, with which the children should
* be created.
* @param pParent The {@link OutlineNode} where the children should be added.
*/
private final void createExpression ( Expression pExpression,
OutlineNode pParent )
{
// Child Expression
int [] expressionsIndex = null;
// Identifier
Identifier [] identifiers = null;
int [] identifiersIndex = null;
// Bound Identifier
ArrayList < ArrayList < Identifier >> identifiersBound = null;
// Type
MonoType [] types = null;
int [] typesIndex = null;
// Sorted Children
ExpressionOrType [] sortedChildren = null;
// The Expression has one or more child Expressions
if ( pExpression instanceof DefaultExpressions )
{
expressionsIndex = ( ( DefaultExpressions ) pExpression )
.getExpressionsIndex ();
}
// The Expresion has one or more Identifiers
if ( pExpression instanceof DefaultIdentifiers )
{
identifiersIndex = ( ( DefaultIdentifiers ) pExpression )
.getIdentifiersIndex ();
identifiers = ( ( DefaultIdentifiers ) pExpression ).getIdentifiers ();
}
// The Expression has one or more Identifiers which bind other Identifiers
if ( pExpression instanceof BoundIdentifiers )
{
identifiersBound = ( ( BoundIdentifiers ) pExpression )
.getIdentifiersBound ();
}
// The Expression has one or more Types.
if ( pExpression instanceof DefaultTypes )
{
typesIndex = ( ( DefaultTypes ) pExpression ).getTypesIndex ();
types = ( ( DefaultTypes ) pExpression ).getTypes ();
}
// The Expression has sorted children.
if ( pExpression instanceof SortedChildren )
{
sortedChildren = ( ( SortedChildren ) pExpression ).getSortedChildren ();
}
OutlineNode outlineNodeId;
OutlineNode outlineNodeType;
OutlineNode outlineNodeE;
OutlineBinding < Identifier > outlineBinding;
// No sorted children
if ( sortedChildren == null )
{
// Identifier
if ( ( identifiers != null ) && ( identifiersIndex != null ) )
{
for ( int i = 0 ; i < identifiers.length ; i++ )
{
if ( identifiersBound == null )
{
outlineBinding = null;
}
else
{
outlineBinding = new OutlineBinding < Identifier > (
identifiersBound.get ( i ) );
}
outlineNodeId = new OutlineNode ( identifiers [ i ],
identifiersIndex [ i ], outlineBinding );
// Identifier - Type
if ( ( types != null ) && ( typesIndex != null ) )
{
for ( int j = 0 ; j < types.length ; j++ )
{
if ( ( types [ j ] != null ) && ( typesIndex [ j ] != -1 )
&& ( typesIndex [ j ] == identifiersIndex [ i ] ) )
{
outlineNodeType = new OutlineNode ( types [ j ],
this.outlineUnbound, typesIndex [ j ] );
createType ( types [ j ], outlineNodeType );
outlineNodeId.add ( outlineNodeType );
}
}
}
pParent.add ( outlineNodeId );
}
}
// Type
if ( ( types != null ) && ( typesIndex != null ) )
{
for ( int i = 0 ; i < types.length ; i++ )
{
if ( ( types [ i ] != null ) && ( typesIndex [ i ] == -1 ) )
{
outlineNodeType = new OutlineNode ( types [ i ],
this.outlineUnbound, typesIndex [ i ] );
createType ( types [ i ], outlineNodeType );
pParent.add ( outlineNodeType );
}
}
}
// Expression
if ( expressionsIndex != null )
{
ArrayList < Expression > children = pExpression.children ();
for ( int i = 0 ; i < children.size () ; i++ )
{
Expression child = children.get ( i );
outlineNodeE = new OutlineNode ( child, this.outlineUnbound,
expressionsIndex [ i ] );
createExpression ( child, outlineNodeE );
pParent.add ( outlineNodeE );
}
}
}
// Sorted children
else
{
ArrayList < ExpressionOrType > notFound = new ArrayList < ExpressionOrType > (
sortedChildren.length );
for ( int i = 0 ; i < sortedChildren.length ; i++ )
{
ExpressionOrType current = sortedChildren [ i ];
boolean found = false;
// Identifier
if ( ( identifiers != null ) && ( identifiersIndex != null ) )
{
for ( int j = 0 ; j < identifiers.length ; j++ )
{
if ( current == identifiers [ j ] )
{
if ( identifiersBound == null )
{
outlineBinding = null;
}
else
{
outlineBinding = new OutlineBinding < Identifier > (
identifiersBound.get ( i ) );
}
outlineNodeId = new OutlineNode ( identifiers [ j ],
identifiersIndex [ j ], outlineBinding );
pParent.add ( outlineNodeId );
found = true;
break;
}
}
}
// Type
if ( ( !found ) && ( types != null ) && ( typesIndex != null ) )
{
for ( int j = 0 ; j < types.length ; j++ )
{
if ( current == types [ j ] )
{
outlineNodeType = new OutlineNode ( types [ j ],
this.outlineUnbound, typesIndex [ j ] );
createType ( types [ j ], outlineNodeType );
pParent.add ( outlineNodeType );
found = true;
break;
}
}
}
// Expression
if ( ( !found ) && ( expressionsIndex != null ) )
{
ArrayList < Expression > children = pExpression.children ();
for ( int j = 0 ; j < children.size () ; j++ )
{
if ( current == children.get ( j ) )
{
Expression child = children.get ( j );
outlineNodeE = new OutlineNode ( child, this.outlineUnbound,
expressionsIndex [ j ] );
createExpression ( child, outlineNodeE );
pParent.add ( outlineNodeE );
found = true;
break;
}
}
}
if ( !found )
{
notFound.add ( current );
}
}
// Not found PrettyPrintables
if ( notFound.size () > 0 )
{
for ( ExpressionOrType current : notFound )
{
if ( current instanceof Identifier )
{
outlineNodeId = new OutlineNode ( ( Identifier ) current, -1, null );
pParent.add ( outlineNodeId );
}
else
if ( current instanceof Type )
{
outlineNodeType = new OutlineNode ( ( Type ) current,
this.outlineUnbound, -1 );
createType ( ( Type ) current, outlineNodeType );
pParent.add ( outlineNodeType );
}
else
if ( current instanceof Expression )
{
outlineNodeE = new OutlineNode ( ( Expression ) current,
this.outlineUnbound, -1 );
createExpression ( ( Expression ) current, outlineNodeE );
pParent.add ( outlineNodeE );
}
}
}
}
}
/**
* Creates the children with the given {@link Type} and adds them to the given
* {@link OutlineNode}.
*
* @param pType The {@link Type}, with which the children should be created.
* @param pParent The {@link OutlineNode} where the children should be added.
*/
private final void createType ( Type pType, OutlineNode pParent )
{
// Type
MonoType [] types = null;
int [] typesIndex = null;
// Identifier
Identifier [] identifiers = null;
int [] identifiersIndex = null;
// Sorted children
ExpressionOrType [] sortedChildren = null;
// TypeName
TypeName [] typeNames = null;
int [] typeNamesIndex = null;
// Bound TypeName
ArrayList < ArrayList < TypeName >> typeNamesBound = null;
// The Type has one or more Types.
if ( pType instanceof DefaultTypes )
{
typesIndex = ( ( DefaultTypes ) pType ).getTypesIndex ();
types = ( ( DefaultTypes ) pType ).getTypes ();
}
// The Type has one or more Identifiers
if ( pType instanceof DefaultIdentifiers )
{
identifiersIndex = ( ( DefaultIdentifiers ) pType )
.getIdentifiersIndex ();
identifiers = ( ( DefaultIdentifiers ) pType ).getIdentifiers ();
}
// The Type has one or more TypeNames
if ( pType instanceof DefaultTypeNames )
{
typeNamesIndex = ( ( DefaultTypeNames ) pType ).getTypeNamesIndex ();
typeNames = ( ( DefaultTypeNames ) pType ).getTypeNames ();
}
// The Type has one or more TypeNames which bind other TypeNames
if ( pType instanceof BoundTypeNames )
{
typeNamesBound = ( ( BoundTypeNames ) pType ).getTypeNamesBound ();
}
// The Type has sorted children.
if ( pType instanceof SortedChildren )
{
sortedChildren = ( ( SortedChildren ) pType ).getSortedChildren ();
}
OutlineNode outlineNodeType;
OutlineNode outlineNodeTypeName;
OutlineNode outlineNodeId;
OutlineBinding < TypeName > outlineBinding;
// No sorted children
if ( sortedChildren == null )
{
// Identifier
if ( ( identifiers != null ) && ( identifiersIndex != null ) )
{
for ( int i = 0 ; i < identifiers.length ; i++ )
{
outlineNodeId = new OutlineNode ( identifiers [ i ],
identifiersIndex [ i ], null );
pParent.add ( outlineNodeId );
}
}
// TypeName
if ( ( typeNames != null ) && ( typeNamesIndex != null ) )
{
for ( int i = 0 ; i < typeNames.length ; i++ )
{
if ( typeNamesBound == null )
{
outlineBinding = null;
}
else
{
outlineBinding = new OutlineBinding < TypeName > ( typeNamesBound
.get ( i ) );
}
outlineNodeTypeName = new OutlineNode ( typeNames [ i ],
typeNamesIndex [ i ], outlineBinding );
pParent.add ( outlineNodeTypeName );
}
}
// Type
if ( ( types != null ) && ( typesIndex != null ) )
{
for ( int i = 0 ; i < types.length ; i++ )
{
outlineNodeType = new OutlineNode ( types [ i ], this.outlineUnbound,
typesIndex [ i ] );
createType ( types [ i ], outlineNodeType );
pParent.add ( outlineNodeType );
}
}
}
// Sorted children
else
{
ArrayList < ExpressionOrType > notFound = new ArrayList < ExpressionOrType > (
sortedChildren.length );
for ( int i = 0 ; i < sortedChildren.length ; i++ )
{
ExpressionOrType current = sortedChildren [ i ];
boolean found = false;
// Identifier
if ( ( identifiers != null ) && ( identifiersIndex != null ) )
{
for ( int j = 0 ; j < identifiers.length ; j++ )
{
if ( current == identifiers [ j ] )
{
outlineNodeId = new OutlineNode ( identifiers [ j ],
identifiersIndex [ j ], null );
pParent.add ( outlineNodeId );
found = true;
break;
}
}
}
// TypeName
if ( ( !found ) && ( typeNames != null ) && ( typeNamesIndex != null ) )
{
for ( int j = 0 ; j < typeNames.length ; j++ )
{
if ( current == typeNames [ j ] )
{
if ( typeNamesBound == null )
{
outlineBinding = null;
}
else
{
outlineBinding = new OutlineBinding < TypeName > (
typeNamesBound.get ( j ) );
}
outlineNodeTypeName = new OutlineNode ( typeNames [ j ],
typeNamesIndex [ j ], outlineBinding );
pParent.add ( outlineNodeTypeName );
}
}
}
// Type
if ( ( !found ) && ( types != null ) && ( typesIndex != null ) )
{
for ( int j = 0 ; j < types.length ; j++ )
{
if ( current == types [ j ] )
{
outlineNodeType = new OutlineNode ( types [ j ],
this.outlineUnbound, typesIndex [ j ] );
createType ( types [ j ], outlineNodeType );
pParent.add ( outlineNodeType );
found = true;
break;
}
}
}
if ( !found )
{
notFound.add ( current );
}
}
// Not found PrettyPrintables
if ( notFound.size () > 0 )
{
for ( ExpressionOrType current : notFound )
{
if ( current instanceof Identifier )
{
outlineNodeId = new OutlineNode ( ( Identifier ) current, -1, null );
pParent.add ( outlineNodeId );
}
else
if ( current instanceof TypeName )
{
outlineNodeId = new OutlineNode ( ( TypeName ) current, -1, null );
pParent.add ( outlineNodeId );
}
else
if ( current instanceof Type )
{
outlineNodeType = new OutlineNode ( ( Type ) current,
this.outlineUnbound, -1 );
createType ( ( Type ) current, outlineNodeType );
pParent.add ( outlineNodeType );
}
}
}
}
}
/**
* Execute the rebuild of a new tree in the {@link Outline}.
*/
public final synchronized void execute ()
{
// If nothing is loaded, nothing is done
if ( this.loadedExpressionOrType == null )
{
return;
}
// Load a new Expression into the outline
if ( this.loadedExpressionOrType instanceof Expression )
{
Expression expression = ( Expression ) this.loadedExpressionOrType;
this.outlineUnbound = new OutlineUnbound ( expression );
this.rootNode = new OutlineNode ( expression, this.outlineUnbound,
OutlineNode.NO_CHILD_INDEX );
createExpression ( expression, this.rootNode );
}
// Load a new Type into the outline
else
if ( this.loadedExpressionOrType instanceof Type )
{
Type type = ( Type ) this.loadedExpressionOrType;
this.outlineUnbound = new OutlineUnbound ( type );
this.rootNode = new OutlineNode ( type, this.outlineUnbound,
OutlineNode.NO_CHILD_INDEX );
createType ( type, this.rootNode );
}
// Throw an exception if something different should be loaded.
else
{
throw new IllegalArgumentException (
"Outline: The input is not an Expression or Type!" ); //$NON-NLS-1$
}
updateCaption ( this.rootNode );
setError ( false );
SwingUtilities.invokeLater ( new OutlineDisplayTree ( this ) );
}
/**
* Cancels the execute <code>Timer</code>.
*/
private final synchronized void executeTimerCancel ()
{
if ( this.outlineTimer != null )
{
this.outlineTimer.cancel ();
this.outlineTimer = null;
}
}
/**
* Starts the execute <code>Timer</code>, which will execute the rebuild of
* a new tree in the {@link Outline} after the given delay, if it is not
* canceled during this time.
*
* @param pDelay Delay in milliseconds before task is to be executed.
*/
private final synchronized void executeTimerStart ( int pDelay )
{
if ( pDelay < 0 )
{
throw new IllegalArgumentException ( "Delay is smaller than 0" ); //$NON-NLS-1$
}
this.outlineTimer = new Timer ();
this.outlineTimer.schedule ( new OutlineTimerTask ( this ), pDelay );
}
/**
* Returns the outlineItemListener.
*
* @return The outlineItemListener.
* @see #itemListener
*/
public final OutlineItemListener getItemListener ()
{
return this.itemListener;
}
/**
* Returns the <code>JPanel</code> of the {@link OutlineUI}.
*
* @return The <code>JPanel</code> of the {@link OutlineUI}.
* @see de.unisiegen.tpml.graphics.outline.Outline#getPanel()
*/
public final JPanel getPanel ()
{
return this.uI.getJPanelMain ();
}
/**
* Returns the <code>JPanel</code> of the {@link OutlineUI} preferences.
*
* @return The <code>JPanel</code> of the {@link OutlineUI} preferences.
*/
public final JPanel getPanelPreferences ()
{
return this.uI.getJPanelPreferences ();
}
/**
* Returns the {@link OutlinePreferences}.
*
* @return The {@link OutlinePreferences}.
* @see #preferences
*/
public final OutlinePreferences getPreferences ()
{
return this.preferences;
}
/**
* Returns the syncOutline.
*
* @return The syncOutline.
* @see #syncOutline
*/
public final DefaultOutline getSyncOutline ()
{
return this.syncOutline;
}
/**
* Returns the <code>JScrollPane</code> of the {@link OutlineUI} tree.
*
* @return The <code>JScrollPane</code> of the {@link OutlineUI} tree.
*/
public final JScrollPane getTree ()
{
return this.uI.getJScrollPaneOutline ();
}
/**
* Returns the {@link OutlineUI}.
*
* @return The {@link OutlineUI}.
* @see #uI
*/
public final OutlineUI getUI ()
{
return this.uI;
}
/**
* This method loads a new {@link ExpressionOrType} into the {@link Outline}.
* It does nothing if the auto update is disabled and the change does not come
* from a <code>MouseEvent</code>.
*
* @param pExpressionOrType The new {@link ExpressionOrType}.
* @param pExecute The {@link Outline.Execute}.
*/
public final void load ( ExpressionOrType pExpressionOrType,
Outline.Execute pExecute )
{
/*
* If the invoke comes from a mouse click on the editor or the auto change
* is active, the error is set and nothing is loaded.
*/
if ( pExpressionOrType == null )
{
executeTimerCancel ();
if ( ( this.preferences.isAutoUpdate () )
|| ( Outline.ExecuteMouseClick.EDITOR.equals ( pExecute ) )
|| ( Outline.ExecuteMouseClick.SUBTYPING_SOURCE.equals ( pExecute ) ) )
{
setError ( true );
}
return;
}
if ( pExecute instanceof Outline.ExecuteAutoChange )
{
Outline.ExecuteAutoChange execute = ( Outline.ExecuteAutoChange ) pExecute;
switch ( execute )
{
case EDITOR :
case SMALLSTEP :
case SUBTYPING_SOURCE :
{
if ( !this.preferences.isAutoUpdate () )
{
return;
}
break;
}
case BIGSTEP :
case TYPECHECKER :
case TYPEINFERENCE :
case MINIMALTYPING :
case SUBTYPING :
{
return;
}
}
}
// Cancel the maybe running timer
executeTimerCancel ();
setError ( false );
this.loadedExpressionOrType = pExpressionOrType;
/*
* Execute the new load of the Expression or the Type immediately, if the
* change is an init change or a change because of a mouse click.
*/
if ( pExecute instanceof Outline.ExecuteInit )
{
Outline.ExecuteInit execute = ( Outline.ExecuteInit ) pExecute;
switch ( execute )
{
case EDITOR :
case SMALLSTEP :
case BIGSTEP :
case TYPECHECKER :
case TYPEINFERENCE :
case MINIMALTYPING :
case SUBTYPING_SOURCE :
case SUBTYPING :
{
execute ();
break;
}
}
}
else
if ( pExecute instanceof Outline.ExecuteMouseClick )
{
Outline.ExecuteMouseClick execute = ( Outline.ExecuteMouseClick ) pExecute;
switch ( execute )
{
case EDITOR :
case SMALLSTEP :
case BIGSTEP :
case TYPECHECKER :
case TYPEINFERENCE :
case MINIMALTYPING :
case SUBTYPING_SOURCE :
case SUBTYPING :
{
execute ();
break;
}
}
}
else
if ( pExecute instanceof Outline.ExecuteAutoChange )
{
Outline.ExecuteAutoChange execute = ( Outline.ExecuteAutoChange ) pExecute;
switch ( execute )
{
case EDITOR :
case SUBTYPING_SOURCE :
{
executeTimerStart ( 500 );
break;
}
case SMALLSTEP :
case BIGSTEP :
case TYPECHECKER :
case TYPEINFERENCE :
case MINIMALTYPING :
case SUBTYPING :
{
executeTimerStart ( 250 );
break;
}
}
}
}
/**
* Repaints the root node and all of its children with the new color settings.
*/
public final void propertyChanged ()
{
updateHighlighSourceCode ( true );
propertyChanged ( this.rootNode );
}
/**
* Repaints the root node and all of its children with the new color settings
* and resets the caption.
*
* @param pOutlineNode The node, which should be repainted.
*/
private final void propertyChanged ( OutlineNode pOutlineNode )
{
if ( pOutlineNode == null )
{
return;
}
pOutlineNode.propertyChanged ();
pOutlineNode.updateCaption ();
this.uI.getTreeModel ().nodeChanged ( pOutlineNode );
for ( int i = 0 ; i < pOutlineNode.getChildCount () ; i++ )
{
propertyChanged ( ( OutlineNode ) pOutlineNode.getChildAt ( i ) );
}
}
/**
* Repaints the given node and all its children.
*
* @param pOutlineNode The node, which should be repainted.
*/
private final void repaintNode ( OutlineNode pOutlineNode )
{
this.uI.getTreeModel ().nodeChanged ( pOutlineNode );
for ( int i = 0 ; i < pOutlineNode.getChildCount () ; i++ )
{
repaintNode ( ( OutlineNode ) pOutlineNode.getChildAt ( i ) );
}
}
/**
* Resets the root node and all its children.
*/
public final void resetNode ()
{
if ( this.rootNode == null )
{
return;
}
resetNode ( this.rootNode );
}
/**
* Resets the given node and all its children.
*
* @param pOutlineNode The node, which should be reseted.
*/
private final void resetNode ( OutlineNode pOutlineNode )
{
pOutlineNode.setReplaceInThisNode ( false );
pOutlineNode.setOutlineBinding ( null );
pOutlineNode.setBindingIdentifier ( null );
pOutlineNode.updateCaption ();
for ( int i = 0 ; i < pOutlineNode.getChildCount () ; i++ )
{
resetNode ( ( OutlineNode ) pOutlineNode.getChildAt ( i ) );
}
}
/**
* Updates the UI mit or without an error.
*
* @param pStatus True, if the error should be set.
*/
private final void setError ( boolean pStatus )
{
this.error = pStatus;
if ( pStatus )
{
this.uI.getJScrollPaneOutline ().setBorder (
new LineBorder ( Color.RED, 3 ) );
// updateHighlighSourceCode ( false ) ;
}
else
{
this.uI.getJScrollPaneOutline ().setBorder (
new LineBorder ( Color.WHITE, 3 ) );
}
}
/**
* Sets the root node in the {@link OutlineUI}.
*/
public final synchronized void setRootNode ()
{
this.uI.setRootNode ( this.rootNode );
updateBreaks ();
}
/**
* Sets the sync outline.
*
* @param pSyncOutline The sync outline.
*/
public final void setSyncOutline ( DefaultOutline pSyncOutline )
{
if ( pSyncOutline == null )
{
throw new IllegalArgumentException (
"The sync outline should not be null" ); //$NON-NLS-1$
}
if ( this.syncOutline != pSyncOutline )
{
this.syncOutline = pSyncOutline;
this.syncOutline.setSyncOutline ( this );
}
}
/**
* Updates the caption of the selected node and its higher nodes.
*
* @param pTreePath The selected <code>TreePath</code>.
*/
public final void update ( TreePath pTreePath )
{
if ( this.rootNode == null )
{
return;
}
resetNode ();
if ( pTreePath == null )
{
repaintNode ( this.rootNode );
return;
}
ArrayList < OutlineNode > list = new ArrayList < OutlineNode > ();
Object [] path = pTreePath.getPath ();
for ( int i = 0 ; i < pTreePath.getPathCount () ; i++ )
{
list.add ( ( OutlineNode ) path [ i ] );
}
OutlineNode selectedNode = list.get ( list.size () - 1 );
// Expression
if ( selectedNode.isExpression () )
{
updateExpression ( list, pTreePath );
}
// Identifier
else
if ( selectedNode.isIdentifier () )
{
updateIdentifier ( list, pTreePath );
}
// Type
else
if ( selectedNode.isType () )
{
updateType ( list, pTreePath );
}
// TypeName
else
if ( selectedNode.isTypeName () )
{
updateTypeName ( list, pTreePath );
}
updateBreaks ();
}
/**
* Updates the breaks in the {@link OutlineNode}.
*/
public final void updateBreaks ()
{
if ( this.rootNode == null )
{
return;
}
final int distance = 20;
JScrollPane jScrollPaneOutline = this.uI.getJScrollPaneOutline ();
OutlineNode currentNode;
TreePath currentTreePath;
Rectangle rectangle;
Enumeration < ? > enumeration = this.rootNode.breadthFirstEnumeration ();
while ( enumeration.hasMoreElements () )
{
currentNode = ( OutlineNode ) enumeration.nextElement ();
currentTreePath = new TreePath ( currentNode.getPath () );
rectangle = this.uI.getJTreeOutline ().getPathBounds ( currentTreePath );
if ( rectangle != null )
{
/*
* Remove a break from the node, if it is to small and a break can be
* removed. If the node is after the remove to big, a break is added.
*/
boolean removed = false;
while ( ( currentNode.breaksCanRemove () )
&& ( ( rectangle.x + rectangle.width ) < ( jScrollPaneOutline
.getSize ().width - distance ) ) )
{
currentNode.breakCountRemove ();
this.uI.getTreeModel ().nodeChanged ( currentNode );
rectangle = this.uI.getJTreeOutline ().getPathBounds (
currentTreePath );
/*
* If the node is after the remove to big, a break is added.
*/
if ( ( rectangle.x + rectangle.width ) > ( jScrollPaneOutline
.getSize ().width - distance ) )
{
currentNode.breakCountAdd ();
this.uI.getTreeModel ().nodeChanged ( currentNode );
rectangle = this.uI.getJTreeOutline ().getPathBounds (
currentTreePath );
break;
}
removed = true;
}
/*
* Add a break to the node, if it is to big and more breaks can be
* added.
*/
while ( ( !removed )
&& ( currentNode.breaksCanAdd () )
&& ( ( rectangle.x + rectangle.width ) > ( jScrollPaneOutline
.getSize ().width - distance ) ) )
{
currentNode.breakCountAdd ();
this.uI.getTreeModel ().nodeChanged ( currentNode );
rectangle = this.uI.getJTreeOutline ().getPathBounds (
currentTreePath );
}
}
}
}
/**
* Repaints the given node and all of its children and resets the caption.
*
* @param pOutlineNode The node, which should be repainted.
*/
private final void updateCaption ( OutlineNode pOutlineNode )
{
pOutlineNode.updateCaption ();
this.uI.getTreeModel ().nodeChanged ( pOutlineNode );
for ( int i = 0 ; i < pOutlineNode.getChildCount () ; i++ )
{
updateCaption ( ( OutlineNode ) pOutlineNode.getChildAt ( i ) );
}
}
/**
* Updates the caption of the selected node and its higher nodes.
*
* @param pList The parent nodes of the selected node.
* @param pTreePath The selected <code>TreePath</code>.
*/
private final void updateExpression ( ArrayList < OutlineNode > pList,
TreePath pTreePath )
{
OutlineNode selectedNode = pList.get ( pList.size () - 1 );
for ( int i = 0 ; i < pList.size () ; i++ )
{
if ( ( selectedNode.getExpressionOrType () instanceof Identifier )
&& ( i < pList.size () - 1 )
&& ( ( ( Identifier ) selectedNode.getExpressionOrType () )
.getBoundToExpression () != null ) )
{
try
{
Identifier identifier = ( Identifier ) selectedNode
.getExpressionOrType ();
/*
* Highlight the bound Identifiers in the other childs of a parent
* row.
*/
if ( ( pList.get ( i ).getExpressionOrType () instanceof Attribute )
|| ( pList.get ( i ).getExpressionOrType () instanceof Method )
|| ( pList.get ( i ).getExpressionOrType () instanceof CurriedMethod ) )
{
OutlineNode nodeRowChild = ( OutlineNode ) pTreePath.getPath () [ i ];
OutlineNode nodeRow = ( OutlineNode ) pTreePath.getPath () [ i - 1 ];
for ( int j = nodeRow.getIndex ( nodeRowChild ) ; j >= 0 ; j-- )
{
OutlineNode currentOutlineNode = ( OutlineNode ) nodeRow
.getChildAt ( j );
if ( currentOutlineNode.getExpressionOrType () == identifier
.getBoundToExpression () )
{
/*
* Highlight the first identifier
*/
currentOutlineNode.setBindingIdentifier ( identifier
.getBoundToIdentifier () );
currentOutlineNode.updateCaption ();
/*
* Highlight the Identifier in the first child
*/
for ( int k = 0 ; k < currentOutlineNode.getChildCount () ; k++ )
{
OutlineNode nodeId = ( OutlineNode ) currentOutlineNode
.getChildAt ( k );
if ( nodeId.getExpressionOrType () == identifier
.getBoundToIdentifier () )
{
nodeId.setBindingIdentifier ( identifier
.getBoundToIdentifier () );
nodeId.updateCaption ();
break;
}
}
}
}
}
else
{
/*
* Highlight the Identifier in the child node with the bound
* Identifier index.
*/
if ( pList.get ( i ).getExpressionOrType () == identifier
.getBoundToExpression () )
{
for ( int j = 0 ; j < pList.get ( i ).getChildCount () ; j++ )
{
OutlineNode nodeId = ( OutlineNode ) pList.get ( i )
.getChildAt ( j );
if ( nodeId.getExpressionOrType () == identifier
.getBoundToIdentifier () )
{
nodeId.setBindingIdentifier ( identifier
.getBoundToIdentifier () );
nodeId.updateCaption ();
break;
}
}
}
/*
* Highlight the Identifier in the node.
*/
pList.get ( i ).setBindingIdentifier (
identifier.getBoundToIdentifier () );
}
}
catch ( IllegalArgumentException e )
{
// Do nothing
}
}
/*
* It should be replaced in higher nodes, but not the selected node
*/
if ( i < pList.size () - 1 )
{
pList.get ( i ).setReplaceInThisNode ( true );
}
/*
* If only the root is selected, there should not be replaced
*/
if ( pList.size () == 1 )
{
pList.get ( i ).setReplaceInThisNode ( false );
}
/*
* Update the caption of the node
*/
PrettyAnnotation prettyAnnotation = pList.get ( i )
.getExpressionOrType ().toPrettyString ().getAnnotationForPrintable (
selectedNode.getExpressionOrType () );
pList.get ( i ).updateCaption ( prettyAnnotation.getStartOffset (),
prettyAnnotation.getEndOffset () );
/*
* Node has changed and can be repainted
*/
this.uI.getTreeModel ().nodeChanged (
( ( OutlineNode ) pTreePath.getPath () [ i ] ) );
}
}
/**
* Updates the highlighting of the source code.
*
* @param pHighlight True, if the source code should be highlighted. False, if
* if the source code should be reseted.
*/
public final void updateHighlighSourceCode ( boolean pHighlight )
{
StyledLanguageDocument document;
if ( this.sourceView != null )
{
document = this.sourceView.getDocument ();
}
else
if ( this.typeEditorPanel != null )
{
if ( this.typeEditorPanel.getOutline1 () == this )
{
document = ( StyledLanguageDocument ) this.typeEditorPanel
.getEditor ().getDocument ();
}
else
if ( this.typeEditorPanel.getOutline2 () == this )
{
document = ( StyledLanguageDocument ) this.typeEditorPanel
.getEditor2 ().getDocument ();
}
else
{
return;
}
}
else
{
return;
}
try
{
document.processChanged ();
}
catch ( BadLocationException e )
{
// Do nothing
}
if ( ( pHighlight ) && ( !this.error ) )
{
TreePath treePath = this.uI.getJTreeOutline ().getSelectionPath ();
if ( treePath == null )
{
return;
}
OutlineNode outlineNode = ( OutlineNode ) treePath
.getLastPathComponent ();
if ( outlineNode.getExpressionOrType () instanceof Identifier )
{
Identifier identifier = ( Identifier ) outlineNode
.getExpressionOrType ();
if ( identifier.getBoundToIdentifier () != null )
{
identifier = identifier.getBoundToIdentifier ();
}
if ( ( identifier.getParent () ) != null
&& ( identifier.getParent () instanceof BoundIdentifiers ) )
{
// Binding
SimpleAttributeSet bindingSet = new SimpleAttributeSet ();
StyleConstants.setForeground ( bindingSet, Theme.currentTheme ()
.getBindingIdColor () );
StyleConstants.setBold ( bindingSet, true );
bindingSet.addAttribute ( IDENTIFER, IDENTIFER );
document.setCharacterAttributes ( identifier.getParserStartOffset (),
identifier.getParserEndOffset ()
- identifier.getParserStartOffset (), bindingSet, false );
BoundIdentifiers parent = ( BoundIdentifiers ) identifier
.getParent ();
ArrayList < ArrayList < Identifier >> identifiersBound = parent
.getIdentifiersBound ();
for ( int i = 0 ; i < parent.getIdentifiers ().length ; i++ )
{
if ( identifier == parent.getIdentifiers () [ i ] )
{
for ( Identifier current : identifiersBound.get ( i ) )
{
// Bound
SimpleAttributeSet boundSet = new SimpleAttributeSet ();
StyleConstants.setForeground ( boundSet, Theme.currentTheme ()
.getBoundIdColor () );
StyleConstants.setBold ( boundSet, true );
boundSet.addAttribute ( IDENTIFER, IDENTIFER );
document.setCharacterAttributes ( current
.getParserStartOffset (), current.getParserEndOffset ()
- current.getParserStartOffset (), boundSet, false );
}
break;
}
}
}
}
if ( outlineNode.getExpressionOrType () instanceof Expression )
{
Expression expression = ( Expression ) outlineNode
.getExpressionOrType ();
SimpleAttributeSet freeSet = new SimpleAttributeSet ();
StyleConstants.setBackground ( freeSet, Theme.currentTheme ()
.getHighlightSourceCodeColor () );
freeSet.addAttribute ( SELECTED, SELECTED );
document.setCharacterAttributes ( expression.getParserStartOffset (),
expression.getParserEndOffset ()
- expression.getParserStartOffset (), freeSet, false );
}
if ( outlineNode.getExpressionOrType () instanceof TypeName )
{
TypeName typeName = ( TypeName ) outlineNode.getExpressionOrType ();
if ( typeName.getBoundToTypeName () != null )
{
typeName = typeName.getBoundToTypeName ();
}
if ( ( typeName.getParent () ) != null
&& ( typeName.getParent () instanceof BoundTypeNames ) )
{
// Binding
SimpleAttributeSet bindingSet = new SimpleAttributeSet ();
StyleConstants.setForeground ( bindingSet, Theme.currentTheme ()
.getBindingIdColor () );
StyleConstants.setBold ( bindingSet, true );
bindingSet.addAttribute ( TYPE_NAME, TYPE_NAME );
document
.setCharacterAttributes ( typeName.getParserStartOffset (),
typeName.getParserEndOffset ()
- typeName.getParserStartOffset (), bindingSet, false );
BoundTypeNames parent = ( BoundTypeNames ) typeName.getParent ();
ArrayList < ArrayList < TypeName >> typeNamesBound = parent
.getTypeNamesBound ();
for ( int i = 0 ; i < parent.getTypeNames ().length ; i++ )
{
if ( typeName == parent.getTypeNames () [ i ] )
{
for ( TypeName current : typeNamesBound.get ( i ) )
{
// Bound
SimpleAttributeSet boundSet = new SimpleAttributeSet ();
StyleConstants.setForeground ( boundSet, Theme.currentTheme ()
.getBoundIdColor () );
StyleConstants.setBold ( boundSet, true );
boundSet.addAttribute ( TYPE_NAME, TYPE_NAME );
document.setCharacterAttributes ( current
.getParserStartOffset (), current.getParserEndOffset ()
- current.getParserStartOffset (), boundSet, false );
}
break;
}
}
}
}
if ( outlineNode.getExpressionOrType () instanceof Type )
{
Type type = ( Type ) outlineNode.getExpressionOrType ();
SimpleAttributeSet freeSet = new SimpleAttributeSet ();
StyleConstants.setBackground ( freeSet, Theme.currentTheme ()
.getHighlightSourceCodeColor () );
freeSet.addAttribute ( SELECTED, SELECTED );
document.setCharacterAttributes ( type.getParserStartOffset (), type
.getParserEndOffset ()
- type.getParserStartOffset (), freeSet, false );
}
}
}
/**
* Updates the caption of the selected node and its higher nodes.
*
* @param pList The parent nodes of the selected node.
* @param pTreePath The selected <code>TreePath</code>.
*/
private final void updateIdentifier ( ArrayList < OutlineNode > pList,
TreePath pTreePath )
{
OutlineNode selectedNode = pList.get ( pList.size () - 1 );
OutlineNode nodeAttribute = pList.get ( pList.size () - 2 );
/*
* Highlight the bound Identifiers of an Attribute in the other childs of
* the parent row.
*/
if ( nodeAttribute.getExpressionOrType () instanceof Attribute )
{
OutlineNode nodeRow = pList.get ( pList.size () - 3 );
for ( int i = nodeRow.getIndex ( nodeAttribute ) + 1 ; i < nodeRow
.getChildCount () ; i++ )
{
OutlineNode currentRowChild = ( OutlineNode ) nodeRow.getChildAt ( i );
currentRowChild.setOutlineBinding ( selectedNode.getOutlineBinding () );
currentRowChild.updateCaption ();
}
}
for ( int i = 0 ; i < pList.size () ; i++ )
{
/*
* Sets the new binding in higher nodes
*/
pList.get ( i ).setOutlineBinding ( selectedNode.getOutlineBinding () );
/*
* Sets the BoundToIdentifier value.
*/
pList.get ( i ).setBindingIdentifier (
( ( Identifier ) selectedNode.getExpressionOrType () )
.getBoundToIdentifier () );
/*
* It should be replaced in higher nodes
*/
pList.get ( i ).setReplaceInThisNode ( true );
/*
* Update the caption of the node
*/
PrettyAnnotation prettyAnnotation = pList.get ( i )
.getExpressionOrType ().toPrettyString ().getAnnotationForPrintable (
selectedNode.getExpressionOrType () );
pList.get ( i ).updateCaption ( prettyAnnotation.getStartOffset (),
prettyAnnotation.getEndOffset () );
/*
* Node has changed and can be repainted
*/
this.uI.getTreeModel ().nodeChanged (
( ( OutlineNode ) pTreePath.getPath () [ i ] ) );
}
}
/**
* Updates the caption of the selected node and its higher nodes.
*
* @param pList The parent nodes of the selected node.
* @param pTreePath The selected <code>TreePath</code>.
*/
private final void updateType ( ArrayList < OutlineNode > pList,
TreePath pTreePath )
{
OutlineNode selectedNode = pList.get ( pList.size () - 1 );
for ( int i = 0 ; i < pList.size () ; i++ )
{
if ( ( selectedNode.getExpressionOrType () instanceof TypeName )
&& ( i < pList.size () - 1 )
&& ( ( ( TypeName ) selectedNode.getExpressionOrType () )
.getBoundToType () != null ) )
{
try
{
TypeName typeName = ( TypeName ) selectedNode.getExpressionOrType ();
/*
* Highlight the TypeName in the child node with the bound TypeName
* index.
*/
if ( pList.get ( i ).getExpressionOrType () == typeName
.getBoundToType () )
{
for ( int j = 0 ; j < pList.get ( i ).getChildCount () ; j++ )
{
OutlineNode nodeTypeName = ( OutlineNode ) pList.get ( i )
.getChildAt ( j );
if ( nodeTypeName.getExpressionOrType () == typeName
.getBoundToTypeName () )
{
nodeTypeName.setBindingTypeName ( typeName
.getBoundToTypeName () );
nodeTypeName.updateCaption ();
break;
}
}
}
/*
* Highlight the TypeName in the node.
*/
pList.get ( i ).setBindingTypeName ( typeName.getBoundToTypeName () );
}
catch ( IllegalArgumentException e )
{
// Do nothing
}
}
/*
* It should be replaced in higher nodes, but not the selected node
*/
if ( i < pList.size () - 1 )
{
pList.get ( i ).setReplaceInThisNode ( true );
}
/*
* If only the root is selected, there should not be replaced
*/
if ( pList.size () == 1 )
{
pList.get ( i ).setReplaceInThisNode ( false );
}
/*
* Update the caption of the node
*/
if ( pList.get ( i ).isIdentifier () )
{
continue;
}
PrettyAnnotation prettyAnnotation = pList.get ( i )
.getExpressionOrType ().toPrettyString ().getAnnotationForPrintable (
selectedNode.getExpressionOrType () );
pList.get ( i ).updateCaption ( prettyAnnotation.getStartOffset (),
prettyAnnotation.getEndOffset () );
/*
* Node has changed and can be repainted
*/
this.uI.getTreeModel ().nodeChanged (
( ( OutlineNode ) pTreePath.getPath () [ i ] ) );
}
}
/**
* Updates the caption of the selected node and its higher nodes.
*
* @param pList The parent nodes of the selected node.
* @param pTreePath The selected <code>TreePath</code>.
*/
private final void updateTypeName ( ArrayList < OutlineNode > pList,
TreePath pTreePath )
{
OutlineNode selectedNode = pList.get ( pList.size () - 1 );
for ( int i = 0 ; i < pList.size () ; i++ )
{
/*
* Sets the new binding in higher nodes
*/
pList.get ( i ).setOutlineBinding ( selectedNode.getOutlineBinding () );
/*
* Sets the setBindingTypeName value.
*/
pList.get ( i ).setBindingTypeName (
( ( TypeName ) selectedNode.getExpressionOrType () )
.getBoundToTypeName () );
/*
* It should be replaced in higher nodes
*/
pList.get ( i ).setReplaceInThisNode ( true );
/*
* Update the caption of the node
*/
PrettyAnnotation prettyAnnotation = pList.get ( i )
.getExpressionOrType ().toPrettyString ().getAnnotationForPrintable (
selectedNode.getExpressionOrType () );
pList.get ( i ).updateCaption ( prettyAnnotation.getStartOffset (),
prettyAnnotation.getEndOffset () );
/*
* Node has changed and can be repainted
*/
this.uI.getTreeModel ().nodeChanged (
( ( OutlineNode ) pTreePath.getPath () [ i ] ) );
}
}
}