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!"); } }