Java tutorial
/* * Copyright 2013 Vanessa Aybar Rosales * This file is part of RITA. * RITA is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * RITA is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with * RITA. If not, see http://www.gnu.org/licenses/. */ package rita.widget; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Collection; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.border.BevelBorder; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter; import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import org.apache.commons.io.IOUtils; import renderable.RenderableBlock; import rita.battle.Batalla; import rita.battle.BatallaConfig; import rita.compiler.CompileString; import rita.settings.HelperEditor; import rita.settings.Language; import rita.settings.Settings; import rita.ui.component.DialogNewRobot; import rita.ui.component.DialogSelectEnemies; import rita.ui.component.MessageDialog; import rita.ui.component.MessageDialog.MessageType; import rita.ui.component.exception.NoEnemiesException; import rita.ui.sourcecodepane.ReadOnlySourceCodePane; import rita.widget.ScreenHelper.ScreenSize; import workspace.Workspace; import workspace.WorkspaceEvent; import workspace.WorkspaceListener; import workspace.WorkspaceWidget; import controller.WorkspaceController; /* TODO: Ver de usar http://code.google.com/p/jxtextpane/ para mostrar el codigo java con colores */ public class SourceCode extends JPanel implements MouseListener, WorkspaceWidget, ComponentListener, WorkspaceListener { private static final long serialVersionUID = 328149080275L; private final SourceCodeEnlargerTimer enlarger; private static int MIN_WIDTH = 106; /** the default height of a source code view button */ private static int MIN_HEIGHT = 40; /** this.width */ private static int CURRENT_WIDTH = MIN_WIDTH; /** this.height */ private static int CURRENT_HEIGHT = MIN_HEIGHT; private static int BUTTON_HEIGHT = MIN_HEIGHT; private static int MAX_WIDTH; private static int MAX_HEIGHT; static { MAX_WIDTH = 320; MAX_HEIGHT = 340 + BUTTON_HEIGHT; /* ajustar ancho y alto con valores de acuerdo a si el tamao de la * pantalla es comn o si es la de una netbook */ if (ScreenHelper.getSize().equals(ScreenSize.SMALL)) { MAX_WIDTH -= MAX_WIDTH / 5; MAX_HEIGHT -= MAX_HEIGHT / 5; } } /* distancia del lado derecho del widget al lado derecho de la ventana */ private static final int OFFSET_FROM_RIGHT = 50; /* distancia del lado inferior del widget al lado inferior de la ventana */ private static final int OFFSET_FROM_BOTTOM = 150; private static final Color COLOR_EVENT_HANDLER = new Color(149, 45, 45), COLOR_MOVEMENT = new Color(171, 80, 108), COLOR_ACTIONS = new Color(236, 45, 45), COLOR_INFO = new Color(236, 45, 236), COLOR_COLORIZE = new Color(236, 105, 45), COLOR_TEXT = new Color(74, 145, 48), COLOR_VALUE = new Color(236, 45, 236), COLOR_LOGIC = new Color(236, 161, 45), COLOR_MATH = new Color(56, 60, 210), COLOR_METHOD = new Color(141, 45, 141), COLOR_VARS = new Color(149, 52, 105), COLOR_EVENT = new Color(100, 100, 236); /** color de fondo de la linea de codigo conteniendo un error */ private static final Color ErrorLineColor = new Color(255, 128, 128); private ReadOnlySourceCodePane paneJavaCode; private boolean minimized = true; private JButton codeButton; private JButton compileButton; private boolean expanded = false; private Font smallButtonFont; private static final class SINGLETON { private static final SourceCode INSTANCE = new SourceCode(); } public JButton getCompileButton() { return compileButton; } public void setCompileButton(JButton theCompileButton) { this.compileButton = theCompileButton; } private void prepareCodeRegion() { paneJavaCode = new ReadOnlySourceCodePane(); paneJavaCode.setFont(paneJavaCode.getFont().deriveFont(12.0f)); // definir la colorizacion de la sintaxis de Java, coincidiendo con los colores de los bloques de RITA final ReadOnlySourceCodePane.RegExpHashMap syntax = new ReadOnlySourceCodePane.RegExpHashMap(); // PERERATARRAGONA syntax.put("run", COLOR_EVENT_HANDLER); syntax.put("onBattleEnded", COLOR_EVENT_HANDLER); syntax.put("onBulletHit", COLOR_EVENT_HANDLER); syntax.put("onBulletHitBullet", COLOR_EVENT_HANDLER); syntax.put("onBulletMissed", COLOR_EVENT_HANDLER); syntax.put("onHitByBullet", COLOR_EVENT_HANDLER); syntax.put("onHitRobot", COLOR_EVENT_HANDLER); syntax.put("onHitWall", COLOR_EVENT_HANDLER); syntax.put("onRobotDeath", COLOR_EVENT_HANDLER); syntax.put("onRoundEnded", COLOR_EVENT_HANDLER); syntax.put("onScannedRobot", COLOR_EVENT_HANDLER); syntax.put("onWin", COLOR_EVENT_HANDLER); syntax.put("event", COLOR_EVENT); syntax.put("ahead", COLOR_MOVEMENT); syntax.put("back", COLOR_MOVEMENT); syntax.put("turnAheadLeft", COLOR_MOVEMENT); syntax.put("turnAheadRight", COLOR_MOVEMENT); syntax.put("turnBackLeft", COLOR_MOVEMENT); syntax.put("turnBackRight", COLOR_MOVEMENT); syntax.put("turnLeft", COLOR_MOVEMENT); syntax.put("turnRight", COLOR_MOVEMENT); syntax.put("turnTo", COLOR_MOVEMENT); syntax.put("turnGunLeft", COLOR_ACTIONS); syntax.put("turnGunRight", COLOR_ACTIONS); syntax.put("turnGunTo", COLOR_ACTIONS); syntax.put("bearGunTo", COLOR_ACTIONS); syntax.put("doNothing", COLOR_ACTIONS); syntax.put("fire", COLOR_ACTIONS); syntax.put("resume", COLOR_ACTIONS); syntax.put("scan", COLOR_ACTIONS); syntax.put("setAdjustGunForRobotTurn", COLOR_ACTIONS); syntax.put("setAdjustRadarForGunTurn", COLOR_ACTIONS); syntax.put("setAdjustRadarForRobotTurn", COLOR_ACTIONS); syntax.put("stop", COLOR_ACTIONS); syntax.put("turnRadarLeft", COLOR_ACTIONS); syntax.put("turnRadarRight", COLOR_ACTIONS); syntax.put("energy", COLOR_INFO); syntax.put("fieldHeight", COLOR_INFO); syntax.put("fieldWidth", COLOR_INFO); syntax.put("gunBearing", COLOR_INFO); syntax.put("gunHeading", COLOR_INFO); syntax.put("gunReady", COLOR_INFO); syntax.put("heading", COLOR_INFO); syntax.put("hitByBulletAngle", COLOR_INFO); syntax.put("hitByBulletBearing", COLOR_INFO); syntax.put("hitRobotAngle", COLOR_INFO); syntax.put("hitRobotBearing", COLOR_INFO); syntax.put("hitWallAngle", COLOR_INFO); syntax.put("hitWallBearing", COLOR_INFO); syntax.put("others", COLOR_INFO); syntax.put("robotX", COLOR_INFO); syntax.put("robotY", COLOR_INFO); syntax.put("scannedAngle", COLOR_INFO); syntax.put("scannedBearing", COLOR_INFO); syntax.put("scannedDistance", COLOR_INFO); syntax.put("getBattleFieldHeight", COLOR_INFO); syntax.put("getBattleFieldWidth", COLOR_INFO); syntax.put("getEnergy", COLOR_INFO); syntax.put("getGunCoolingRate", COLOR_INFO); syntax.put("getGunHeading", COLOR_INFO); syntax.put("getGunHeat", COLOR_INFO); syntax.put("getHeading", COLOR_INFO); syntax.put("getHeight", COLOR_INFO); syntax.put("getName", COLOR_INFO); syntax.put("getNumRounds", COLOR_INFO); syntax.put("getOthers", COLOR_INFO); syntax.put("getRadarHeading", COLOR_INFO); syntax.put("getRoundNum", COLOR_INFO); syntax.put("getWidth", COLOR_INFO); syntax.put("getX", COLOR_INFO); syntax.put("getY", COLOR_INFO); paneJavaCode.setOperatorColor(COLOR_MATH); paneJavaCode.setNumberColor(COLOR_VALUE); paneJavaCode.setStringLiteralColor(COLOR_VALUE); syntax.put("print(\\w{2})", COLOR_TEXT); syntax.put("while", COLOR_LOGIC); syntax.put("if", COLOR_LOGIC); syntax.put("for", COLOR_LOGIC); syntax.put("true", COLOR_VALUE); syntax.put("false", COLOR_VALUE); syntax.put("setColors", COLOR_COLORIZE); syntax.put("setAllColors", COLOR_COLORIZE); syntax.put("setBodyColor", COLOR_COLORIZE); syntax.put("setBulletColor", COLOR_COLORIZE); syntax.put("setColors", COLOR_COLORIZE); syntax.put("setGunColor", COLOR_COLORIZE); syntax.put("setRadarColor", COLOR_COLORIZE); syntax.put("setScanColor", COLOR_COLORIZE); syntax.put("Integer", COLOR_VARS); syntax.put("String", COLOR_VARS); paneJavaCode.setKeywordColors(syntax); paneJavaCode.setBackground(Color.WHITE); paneJavaCode.getWrappingContainerWithLines().setBounds(0, BUTTON_HEIGHT, MAX_WIDTH, MAX_HEIGHT - BUTTON_HEIGHT); } private SourceCode() { this.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); this.setLocation(OFFSET_FROM_RIGHT - MIN_WIDTH, OFFSET_FROM_BOTTOM - BUTTON_HEIGHT); this.setSize(new Dimension(MIN_WIDTH, MIN_HEIGHT)); this.setPreferredSize(new Dimension(MIN_WIDTH, MIN_HEIGHT)); this.setLayout(null); smallButtonFont = this.getFont().deriveFont(Font.PLAIN, 9.0f); this.enlarger = new SourceCodeEnlargerTimer(); createHideCodeButton(); createCompileButton(); prepareCodeRegion(); add(codeButton); add(compileButton); add(paneJavaCode.getWrappingContainerWithLines()); Workspace.getInstance().addComponentListener(this); } private void createHideCodeButton() { this.codeButton = new JButton(createImageIcon("/images/sourcecode/source_code_small.png")); codeButton.addActionListener(new SourceCodeEnlargerTimer()); codeButton.addMouseListener(this); codeButton.setBounds(0, 0, MIN_WIDTH, BUTTON_HEIGHT); codeButton.setFont(smallButtonFont); codeButton.setAlignmentX(LEFT_ALIGNMENT); codeButton.setText(Language.get("codeButton.title.open")); codeButton.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 0, Color.BLACK)); } /** * @return El path del archivo con el codigo fuente java del robot * @throws FileNotFoundException * @throws IOException */ private File saveSourceCode() throws FileNotFoundException, IOException { final String fullPath = Settings.getRobotsPath() + File.separator + HelperEditor.currentRobotPackage.replace(".", File.separator); String fileSource = HelperEditor.currentRobotName + ".java"; File javaSourceFile = new File(fullPath, fileSource); writeSourceFile(javaSourceFile, this.getText()); return javaSourceFile; } private void writeSourceFile(File javaSourceFile, String javaSource) throws FileNotFoundException, IOException { OutputStream bos = new FileOutputStream(javaSourceFile); try { bos.write(javaSource.getBytes()); } finally { bos.close(); } } private String readSourceFile(File javaSourceFile) throws FileNotFoundException, IOException { FileInputStream inputStream = new FileInputStream(javaSourceFile); try { return IOUtils.toString(inputStream); } finally { IOUtils.closeQuietly(inputStream); } } private void createCompileButton() { ImageIcon imgIcon = new ImageIcon(getClass().getResource("/images/sourcecode/bytecode.png")); this.compileButton = new JButton(imgIcon); this.compileButton.setToolTipText(Language.get("compileButton.tooltip")); final File basePathRobots = new File(Settings.getRobotsPath()); compileButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { // guardar el codigo fuente File sourcePath = saveSourceCode(); // COMPILA EN EL DIRECTORIO POR DEFAULT + LA RUTA DEL PACKAGE Collection<File> inFiles = createClassFiles(sourcePath); if (inFiles != null) { /* transformar el codigo fuente, que no tiene errores, para que los println aparezcan en una ventana. * La transformacin no deberia generar errores. */ writeSourceFile(sourcePath, AgregadorDeConsola.getInstance().transformar(readSourceFile(sourcePath))); // volver a compilar, ahora con el codigo transformado inFiles = createClassFiles(sourcePath); if (inFiles != null) { createJarFile(inFiles); System.out.println("INSTALLPATH=" + Settings.getInstallPath()); System.out.println("SE ENVIA ROBOT:" + HelperEditor.currentRobotPackage + "." + HelperEditor.currentRobotName); // si quiere seleccionar enemigos if (Settings.getProperty("level.default").equals(Language.get("level.four"))) { try { DialogSelectEnemies.getInstance(); } catch (NoEnemiesException e2) { new MessageDialog(Language.get("robot.noEnemies"), MessageType.ERROR); } return; } else { callBatalla(null, null); } } else { System.out.println("Error en codigo transformado por AgregadorDeConsola"); } } } catch (Exception e1) { e1.printStackTrace(); } } /** Recibe un archivo conteniendo codigo fuente java, y crea el .class correspondiente * @param sourcePath El archivo .java * @return Un archivo conteniendo el path al .class generado, o null si no fue posible compilar porque hubo errores en el codigo fuente. */ private Collection<File> createClassFiles(File sourcePath) throws Exception, IOException { Collection<File> f = CompileString.compile(sourcePath, basePathRobots); if (CompileString.hasError()) { int cantErrores = 0; for (Diagnostic<?> diag : CompileString.diagnostics) { if (!diag.getKind().equals(Kind.WARNING)) { int line = (int) diag.getLineNumber(); int col = (int) diag.getColumnNumber(); if (line > 0 && col > 0) { highlightCode(line, col); cantErrores++; } } } if (cantErrores > 0) { new MessageDialog(Language.get("compile.error"), MessageType.ERROR); } return null; } else { return f; } } /* crea un jar con todas las clases del robot. el nombre del jar es el nombre del robot */ private void createJarFile(Collection<File> inFiles) throws FileNotFoundException, IOException { File jarFile = new File(basePathRobots, HelperEditor.currentRobotName + ".jar"); if (jarFile.exists()) { jarFile.delete(); } System.out.println("Path del JAR ==" + jarFile); jarFile.createNewFile(); FileOutputStream fos = new FileOutputStream(jarFile); BufferedOutputStream bo = new BufferedOutputStream(fos); Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); JarOutputStream jarOutput = new JarOutputStream(fos, manifest); int basePathLength = basePathRobots.getAbsolutePath().length() + 1; // +1 para incluir al "/" final byte[] buf = new byte[1024]; int anz; try { // para todas las clases... for (File inFile : inFiles) { BufferedInputStream bi = new BufferedInputStream(new FileInputStream(inFile)); try { String relative = inFile.getAbsolutePath().substring(basePathLength); // copia y agrega el archivo .class al jar JarEntry je2 = new JarEntry(relative); jarOutput.putNextEntry(je2); while ((anz = bi.read(buf)) != -1) { jarOutput.write(buf, 0, anz); } jarOutput.closeEntry(); } finally { try { bi.close(); } catch (IOException ignored) { } } } } finally { try { jarOutput.close(); } catch (IOException ignored) { } try { fos.close(); } catch (IOException ignored) { } try { bo.close(); } catch (IOException ignored) { } } } }); compileButton.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } @Override public void mouseExited(MouseEvent e) { e.getComponent().setCursor(Cursor.getDefaultCursor()); } }); compileButton.setBounds(MIN_WIDTH, 0, MAX_WIDTH - MIN_WIDTH, BUTTON_HEIGHT); compileButton.setFont(smallButtonFont); compileButton.setAlignmentX(LEFT_ALIGNMENT); compileButton.setText(Language.get("compileButton.title")); } protected static String[] getWindowsCommand(Integer roundsNumber, String initialPosition) { String[] cmd = new String[12]; cmd[0] = "cmd.exe"; cmd[1] = "/C"; cmd[2] = "java"; cmd[3] = "-cp"; try { cmd[4] = Settings.getPathTo("lib") + File.separator + "rita.jar;" + Settings.getPathTo("lib") + File.separator + "robocode.jar;" + Settings.getPathTo("lib") + File.separator + "robocode.ui-1.7.3.6.jar"; } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } cmd[5] = "-Xmx512M"; cmd[6] = "rita.battle.Batalla"; cmd[7] = Settings.getInstallPath(); //1er argumento cmd[8] = HelperEditor.currentRobotPackage + "." + HelperEditor.currentRobotName; //2do argumento cmd[9] = BatallaConfig.chooseEnemy(Settings.getProperty("level.default")); //3er argumento cmd[10] = roundsNumber != null ? roundsNumber.toString() : Integer.toString(Batalla.NUMBER_OF_ROUNDS); // 4to argumento Nmero de rondas cmd[11] = initialPosition; return cmd; } protected static String[] getUnixCommand(Integer roundsNumber, String initialPosition) { String[] cmd = new String[10]; cmd[0] = "java"; cmd[1] = "-cp"; cmd[2] = Settings.getInstallPath() + "lib/rita.jar:" + Settings.getInstallPath() + "lib/robocode.jar:" + Settings.getInstallPath() + "lib/robocode.ui-1.7.3.5.jar"; cmd[3] = "-Xmx512M"; cmd[4] = "rita.battle.Batalla"; cmd[5] = Settings.getInstallPath(); //1er argumento cmd[6] = HelperEditor.currentRobotPackage + "." + HelperEditor.currentRobotName; //2do argumento cmd[7] = BatallaConfig.chooseEnemy(Settings.getProperty("level.default")); //3er argumento cmd[8] = roundsNumber != null ? roundsNumber.toString() : Integer.toString(Batalla.NUMBER_OF_ROUNDS); // 4to argumento Nmero de rondas cmd[9] = initialPosition; return cmd; } public static void callBatalla(Integer roundsNumber, String initialPosition) { String[] cmd; final String os = System.getProperty("os.name"); if (os != null && os.toLowerCase().contains("windows")) { cmd = getWindowsCommand(roundsNumber, initialPosition); } else { cmd = getUnixCommand(roundsNumber, initialPosition); } System.out.print("["); for (String s : cmd) { System.out.print(s + " "); } System.out.println("]"); Process proc; InputStreamReader isr = null; BufferedReader br = null; try { proc = Runtime.getRuntime().exec(cmd); isr = new InputStreamReader(proc.getErrorStream()); br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println("ERROR" + ">" + line); } // any errors??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); } catch (IOException ioe) { ioe.printStackTrace(); } catch (InterruptedException ie) { ie.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException ignored) { } } else if (isr != null) { try { isr.close(); } catch (IOException ignored) { } } } } /** Component Listeners **/ public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { /* no importa que nos digan, el angulo inferior derecho del componente no se mueve! */ Point location = new Point(Workspace.getInstance().getWidth(), Workspace.getInstance().getHeight()); location.translate(-this.getWidth() - OFFSET_FROM_RIGHT, -this.getHeight() - OFFSET_FROM_BOTTOM); this.setLocation(location); } public void componentShown(ComponentEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseClicked(MouseEvent e) { if (minimized) { WorkspaceController.refreshCodeRegion(null); codeButton.setText(Language.get("codeButton.title.close")); expanded = true; enlarger.expand(); } else { codeButton.setText(Language.get("codeButton.title.open")); expanded = false; enlarger.shrink(); } minimized = !minimized; } public void mouseDragged(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseMoved(MouseEvent e) { } public void mouseEntered(MouseEvent e) { this.loadCursor(e); } public void mouseExited(MouseEvent e) { this.loadCursor(e); } public void loadCursor(MouseEvent e) { e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } private void maximizeSourceCode() { if (this.getParent() != null) { this.setBounds(this.getParent().getWidth() - MAX_WIDTH - OFFSET_FROM_RIGHT, this.getParent().getHeight() - MAX_HEIGHT - OFFSET_FROM_BOTTOM, MAX_WIDTH, MAX_HEIGHT); } } public void repositionSourceCode(int count) { if (this.getParent() != null) { this.setBounds(this.getParent().getWidth() - CURRENT_WIDTH - OFFSET_FROM_RIGHT, this.getParent().getHeight() - CURRENT_HEIGHT - OFFSET_FROM_BOTTOM, CURRENT_WIDTH, CURRENT_HEIGHT); } } /** * This animator is responsible for enlarging or shrinking the size of the * MiniMap when expand() or shrink() is called, respectively. */ private class SourceCodeEnlargerTimer implements ActionListener { /** Growth count */ private int count; /** Internal Timer used to animate the opening/closing of source view */ private javax.swing.Timer timer; private final int NUM_STEPS = 20; /** absolute value of width growth */ private final int WIDTH_GROWTH_PER_STEP = (MAX_WIDTH - MIN_WIDTH) / NUM_STEPS; /** absolute value of height Growth */ private final int HEIGHT_GROWTH_PER_STEP = (MAX_HEIGHT - MIN_HEIGHT) / NUM_STEPS; /** * Indicates whether the source code view is/was expanding (true) or shrinking * (false) */ private boolean expand; /** * Constuctors an animator that can enlarge or skrink the source code view */ public SourceCodeEnlargerTimer() { count = 0; this.expand = true; timer = new Timer(5, this); } /** * expands/shrinks the source code view untill count is 0 or 15. At 0, the map is * smallest as possible and at 15, the map is largest as possible */ public void actionPerformed(ActionEvent e) { if (count <= 0) { timer.stop(); } else if (count >= NUM_STEPS) { timer.stop(); maximizeSourceCode(); } else { if (expand) { count = count + 1; } else { count = count - 1; } CURRENT_WIDTH = MIN_WIDTH + count * WIDTH_GROWTH_PER_STEP; // para pantalla normal // if (ScreenHelper.getSize().equals(ScreenSize.NORMAL)) CURRENT_HEIGHT = MIN_HEIGHT + count * HEIGHT_GROWTH_PER_STEP; // para pantalla pequea se ajusta distinto // if (ScreenHelper.getSize().equals(ScreenSize.SMALL)) // MAPHEIGHT = DEFAULT_HEIGHT + (count - 5) * dy * 2 // - (MAPHEIGHT / 5); repositionSourceCode(count); repaint(); } } /** * enlarge this source code view */ public void expand() { this.expand = true; count++; this.timer.start(); } /** * shrinks this minimap */ public void shrink() { count--; this.expand = false; this.timer.start(); } } public String getText() { return paneJavaCode.getText(); } public void setText(String formatted) { paneJavaCode.setText(formatted); } // para indicar en rojo una linea de error. public void highlightCode(int line, int col) { try { // Convertir a una posicion X/Y paneJavaCode.getHighlighter().addHighlight(paneJavaCode.getLineStartOffset(line - 1), paneJavaCode.getLineEndOffset(line - 1), new DefaultHighlightPainter(ErrorLineColor)); } catch (BadLocationException e) { e.printStackTrace(); } } public void highlightCode(RenderableBlock renderableBlock) { try { paneJavaCode.getHighlighter().removeAllHighlights(); int startPos = 0; // encontrar la posicion en funcion del numero de repeticion del // LABEL String labelToFind = renderableBlock.getBlock().getBlockLabel(); for (int i = 0; i < renderableBlock.getLabelInstanceNumber(); i++) { if (startPos > 0) startPos += labelToFind.length(); startPos = paneJavaCode.getText().indexOf(labelToFind, startPos); } int lastPos = startPos + renderableBlock.getBlock().getBlockLabel().length(); paneJavaCode.getHighlighter().addHighlight(startPos, lastPos, new DefaultHighlightPainter(Color.ORANGE)); } catch (BadLocationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void addBlock(RenderableBlock block) { } @Override public void addBlocks(Collection<RenderableBlock> blocks) { } @Override public void blockDragged(RenderableBlock block) { } @Override public void blockDropped(RenderableBlock block) { } @Override public void blockEntered(RenderableBlock block) { } @Override public void blockExited(RenderableBlock block) { } @Override public Iterable<RenderableBlock> getBlocks() { return null; } @Override public JComponent getJComponent() { return this; } @Override public void removeBlock(RenderableBlock block) { } public void setInconsistentCode(boolean error) { if (error) { paneJavaCode.setBackground(Color.GRAY); compileButton.setEnabled(false); } else { paneJavaCode.setBackground(Color.WHITE); compileButton.setEnabled(true); } } @Override public void workspaceEventOccurred(WorkspaceEvent event) { update(); } public void update() { if (!minimized) { WorkspaceController.refreshCodeRegion(null); } } public static SourceCode getInstance() { return SINGLETON.INSTANCE; } public boolean isExpanded() { return expanded; } /** Returns an ImageIcon, or null if the path was invalid. */ protected static ImageIcon createImageIcon(String path) { java.net.URL imgURL = DialogNewRobot.class.getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println(Language.get("robot.error.fileNotFound") + " " + path); return null; } } }