package com.drawbridge.vl;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import com.drawbridge.jsengine.ast.ParserListener;
import com.drawbridge.utils.Palette;
import com.drawbridge.utils.SegmentPanel;
import com.drawbridge.utils.TitlePanel;
import com.drawbridge.utils.Utils;
import com.drawbridge.vl.blocks.Block;
import com.drawbridge.vl.blocks.BlockAssignment;
import com.drawbridge.vl.blocks.BlockDeclaration;
import com.drawbridge.vl.blocks.BlockFunctionCall;
import com.drawbridge.vl.blocks.BlockFunctionDefinition;
import com.drawbridge.vl.blocks.BlockIdentifier;
import com.drawbridge.vl.blocks.BlockOperator;
import com.drawbridge.vl.blocks.BlockOperator.SupportedOperationType;
import com.drawbridge.vl.blocks.BlockPrimitive;
import com.google.caja.lexer.FilePosition;
import com.google.caja.lexer.InputSource;
public class VLPanel extends SegmentPanel implements ParserListener
{
private static final long serialVersionUID = -2616598582025669531L;
private static VLPanel instance = null;
private Palette mPalette;
private JScrollPane mScrollPane;
private TitlePanel mTitlePanel;
public VLCanvas mCanvas;
public static boolean showSyntaxAnnotation = true;
// Do we have a separate AST here, or do we attach it straight to the
// JS-AST?
public static VLPanel getInstance()
{
if (instance == null)
{
instance = new VLPanel();
return instance;
}
return instance;
}
public static void reset(){
instance = null;
}
public JScrollPane getScrollBar(){
return mScrollPane;
}
public VLPanel() {
this.setLayout(new BorderLayout());
// Add Title Panel
mTitlePanel = new TitlePanel("Block Panel");
mTitlePanel.mHelpButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent me)
{
JOptionPane.showMessageDialog(VLPanel.this, "VLJPanel has no help associated with it.");
}
});
add(mTitlePanel, BorderLayout.NORTH);
// Add Scroll Pane
mCanvas = new VLCanvas();
mCanvas.setBackground(Color.white);
mScrollPane = new JScrollPane();
mScrollPane.getViewport().add(mCanvas);
mScrollPane.setBackground(Color.white);
mScrollPane.setEnabled(true);
mScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
mScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
mScrollPane.setBorder(null);
mScrollPane.getViewport().addChangeListener(Utils.synchronizedScrollingListener);
add(mScrollPane, BorderLayout.CENTER);
JButton toggleAnnotationButton = new JButton("Toggle Annotation");
toggleAnnotationButton.addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e)
{
if(showSyntaxAnnotation){
showSyntaxAnnotation = false;
mCanvas.repaint();
}
else{
mCanvas.addSyntaxAnnotation();
showSyntaxAnnotation = true;
mCanvas.repaint();
}
}
});
mTitlePanel.add(toggleAnnotationButton);
// Add Palette
mPalette = new Palette();
add(mPalette, BorderLayout.SOUTH);
FilePosition emptyFilePosition = FilePosition.fromLinePositions(InputSource.PREDEFINED, 0, 0, 0, 0);
// Load blocks into palette
final JComponent[] components = { new BlockDeclaration(null, null, "X"),
new BlockPrimitive(null, null, "2"),
new BlockIdentifier(null, null, "Y"),
new BlockFunctionDefinition(null, null, "play"),
new BlockFunctionCall(null, null, "play"),
new BlockOperator(emptyFilePosition, null, SupportedOperationType.ADDITION),
new BlockAssignment(emptyFilePosition, null)
};
// Add Tabs
new Thread(new Runnable() {
@Override
public void run()
{
while (mPalette.mTabbedPane == null)
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
mPalette.addPaletteTab("Components", components);
}
}).start();
}
@Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.black);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // Anti-alias!
RenderingHints.VALUE_ANTIALIAS_ON);
// Utils.out.println("Number of blocks: " + getBlocksInComponent(this));
}
// Handy recursive method to count number of blocks.
public int getBlocksInComponent(JComponent c){
int number = 0;
Component [] subComponents = c.getComponents();
for(Component sC : subComponents){
if(sC instanceof Block)
number++;
else if(sC instanceof JComponent)
number += getBlocksInComponent((JComponent)sC);
}
return number;
}
/**System.out.println
* Attempts to insert the component at a nearby place
*
* @param x
* @param y
*/
public void insertComponentAt(JComponent block, int x, int y)
{
mCanvas.addBlockToCanvasAndGrid((Block)block, x, y);
}
public void removeFromCanvas(Block block){
mCanvas.removeFromGrid(block);
}
public static boolean hasInstance()
{
return (instance != null);
}
public void moveToBottom()
{
JScrollBar bar = mScrollPane.getVerticalScrollBar();
bar.setValue(bar.getMaximum());
}
public void moveToTop()
{
JScrollBar bar = mScrollPane.getVerticalScrollBar();
bar.setValue(bar.getMinimum());
}
@Override
public void onParserException(int lineNumber, String exception)
{
Utils.err.println(getClass(), "onParserException() called, but no implementation yet!");
}
@Override
public void onParserChange()
{
Utils.err.println(getClass(), "onParserChange() called, but no implementation yet!");
}
}