]> Dogcows Code - chaz/vimcoder/blobdiff - src/com/dogcows/VimCoder.java
cleaned up the preferences dialog
[chaz/vimcoder] / src / com / dogcows / VimCoder.java
index 489e78960499154a4b657f59d0c657b9ee9a29ce..a38bb2153f7eca4c053970707c6bd8daf79854b3 100644 (file)
@@ -3,6 +3,9 @@ package com.dogcows;
 
 import javax.swing.*;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeListener;
 import java.io.*;
 import java.text.SimpleDateFormat;
 import java.util.*;
@@ -10,6 +13,8 @@ import com.topcoder.client.contestant.ProblemComponentModel;
 import com.topcoder.shared.language.*;
 import com.topcoder.shared.problem.*;
 import com.topcoder.shared.problem.Renderer;
+import com.topcoder.client.contestApplet.common.Common;
+import com.topcoder.client.contestApplet.common.LocalPreferences;
 
 /**
  * @author Charles McGarvey
@@ -21,273 +26,96 @@ import com.topcoder.shared.problem.Renderer;
 public class VimCoder
 {
     /**
-     * 
+     * The name and version of this plugin.
      */
-    private final static String     version = "VimCoder 0.1";
-    private final static String     website = "http://www.dogcows.com/vimcoder";
+    public final static String     version = "VimCoder 0.2";
     
-    private JPanel      panel;
-    private JTextArea   logArea;
+    /**
+     * The website of the plugin project.
+     */
+    public final static String     website = "http://www.dogcows.com/vimcoder";
     
-    private Editor      editor;
     
+    /**
+     * The first part of the command used to invoke the Vim server.
+     */
+    private static String   vimCommand = "gvim";
     
-    private static final Map<String,String> languageExtension = new HashMap<String,String>();
+    /**
+     * The path to the main VimCoder directory.
+     */
+    private static File     rootDir;
     static
     {
-        languageExtension.put("Java",   "java");
-        languageExtension.put("C++",    "cc");
-        languageExtension.put("C#",     "cs");
-        languageExtension.put("VB",     "vb");
-        languageExtension.put("Python", "py");
-    }
-    
-    
-    private class Editor
-    {
-        private String  id;
-        private String  name;
-        
-        private File    sourceFile;
-        private File    directory;
-        
-        
-        public Editor(ProblemComponentModel component, Language language, Renderer renderer) throws IOException
-        {
-            this.id     = String.valueOf(component.getProblem().getProblemID());
-            this.name   = component.getClassName();
-            
-            File topDir = new File(System.getProperty("user.home"), ".vimcoder");
-            if (!topDir.isDirectory())
-            {
-                if (!topDir.mkdirs()) throw new IOException(topDir.getPath());
-            }
-            
-            this.directory = new File(topDir, String.valueOf(component.getProblem().getProblemID()));
-            if (!directory.isDirectory())
-            {
-                if (!directory.mkdirs()) throw new IOException(directory.getPath());
-            }
-            
-            String lang = language.getName();
-            String ext  = languageExtension.get(lang);
-            
-            HashMap<String,String> terms = new HashMap<String,String>();
-            terms.put("RETURNTYPE", component.getReturnType().getDescriptor(language));
-            terms.put("CLASSNAME",  component.getClassName());
-            terms.put("METHODNAME", component.getMethodName());
-            terms.put("METHODPARAMS", getMethodParams(component.getParamTypes(), component.getParamNames(), language));
-            terms.put("METHODPARAMNAMES", join(component.getParamNames(), ", "));
-            
-            File problemFile = new File(directory, "Problem.html");
-            if (!problemFile.canRead())
-            {
-                FileWriter writer = new FileWriter(problemFile);
-                try
-                {
-                    writer.write(renderer.toHTML(language));
-                }
-                catch (Exception exception)
-                {
-                }
-                writer.close();
-            }
-            
-            sourceFile = new File(directory, terms.get("CLASSNAME") + "." + ext);
-            if (!sourceFile.canRead())
-            {
-                String text = expandTemplate(readResource(lang + "Template"), terms);
-                FileWriter writer = new FileWriter(sourceFile);
-                writer.write(text);
-                writer.close();
-            }
-
-            File driverFile = new File(directory, "driver" + "." + ext);
-            if (!driverFile.canRead())
-            {
-                StringBuilder testCases = new StringBuilder();
-                if (component.hasTestCases())
-                {
-                    HashMap<String,String> testTerms = new HashMap<String,String>();
-                    testTerms.putAll(terms);
-                    String template = readResource(lang + "Test");
-                    for (TestCase testCase : component.getTestCases())
-                    {
-                        testTerms.put("TESTOUTPUT", "\"" + quote(testCase.getOutput()) + "\"");
-                        testTerms.put("TESTINPUTS", join(testCase.getInput(), ", "));
-                        testCases.append(expandTemplate(template, testTerms));
-                    }
-                }
-                terms.put("TESTCASES", testCases.toString());
-                
-                String text = expandTemplate(readResource(lang + "Driver"), terms);
-                FileWriter writer = new FileWriter(driverFile);
-                writer.write(text);
-                writer.close();
-            }
-            
-            File makeFile = new File(directory, "Makefile");
-            {
-                String text = expandTemplate(readResource(lang + "Makefile"), terms);
-                FileWriter writer = new FileWriter(makeFile);
-                writer.write(text);
-                writer.close();
-            }
-        }
-        
-        public void setSource(String source) throws IOException
+        if (System.getProperty("os.name").toLowerCase().equals("win"))
         {
-            String actualSource = readFile(sourceFile);
-            if (!actualSource.equals(source))
-            {
-                File actualFile = new File(directory, name);
-                FileWriter writer = new FileWriter(actualFile);
-                writer.write(source);
-                writer.close();
-            }
-            doVimCommand("--remote-tab-silent", sourceFile.getPath());
-            doVimCommand("--remote-send", "<C-\\><C-N>:if search('\\$CARAT\\\\$') != 0<CR>normal df$<CR>endif<CR>:redraw<CR>");
-        }
-
-        public String getSource() throws IOException
-        {
-            return readFile(sourceFile) + "\n// Edited by " + version + "\n// " + website + "\n\n";
-        }
-        
-        public void setTextEnabled(boolean enable)
-        {
-            doVimCommand("--remote-send", "<C-\\><C-N>:set readonly<CR>:echo \"The contest is over.\"<CR>");
-        }
-        
-        
-        private boolean doVimCommand(String command, String argument)
-        {
-            String[] arguments = {argument};
-            return doVimCommand(command, arguments);
-        }
-        
-        private boolean doVimCommand(String command, String[] arguments)
-        {
-            try
-            {
-                String[] exec = {"gvim", "--servername", "VimCoder" + id, command};
-                exec = concat(exec, arguments);
-                
-                Process child = Runtime.getRuntime().exec(exec);
-                if (child.waitFor() == 0)
-                {
-                    return true;
-                }
-                else
-                {
-                    logError("vim command failed");
-                }
-            }
-            catch (IOException exception)
-            {
-                logError("failed to launch external vim process");
-                return false;
-            }
-            catch (InterruptedException exception)
-            {
-                logWarning("interrupted while waiting on vim process");
-            }
-            return false;
-        }
-        
-        private String getMethodParams(DataType[] types, String[] names, Language language)
-        {
-            StringBuilder text = new StringBuilder();
-            
-            text.append(types[0].getDescriptor(language) + " " + names[0]);
-            for (int i = 1; i < names.length; ++i)
-            {
-                text.append(", " + types[i].getDescriptor(language) + " " + names[i]);
-            }
-            
-            return text.toString();
-        }
-        
-        private String readFile(File file) throws IOException
-        {
-            StringBuilder text = new StringBuilder();
-        
-            BufferedReader reader = new BufferedReader(new FileReader(file.getPath()));
-            try
-            {
-                String line = null;
-                
-                while ((line = reader.readLine()) != null)
-                {
-                    text.append(line + System.getProperty("line.separator"));
-                }
-            }
-            finally
-            {
-                reader.close();
-            }
-        
-            return text.toString();
-        }
-        
-        private String readResource(String path) throws IOException
-        {
-            StringBuilder text = new StringBuilder();
-            
-            InputStream stream = getClass().getResourceAsStream("resources/" + path);
-            if (stream != null)
-            {
-                try
-                {
-                    byte[]  buffer = new byte[4096];
-                    int     numBytes = 0;
-                    while (0 < (numBytes = stream.read(buffer))) text.append(new String(buffer, 0, numBytes));
-                }
-                finally
-                {
-                    stream.close();
-                }
-            }
-            
-            return text.toString();
-        }
-        
-        private String expandTemplate(String template, Map<String,String> terms)
-        {
-            String text = template;
-            for (String key : terms.keySet())
-            {
-                text = text.replaceAll("\\$" + key + "\\$", quote(terms.get(key)));
-            }
-            return text;
+            vimCommand = "C:\\WINDOWS\\gvim.bat";
         }
+        rootDir = new File(System.getProperty("user.home") +
+                           System.getProperty("file.separator") + ".vimcoder");
     }
     
     
-    public static <T> T[] concat(T[] a, T[] b)
-    {
-        T[] result = Arrays.copyOf(a, a.length + b.length);
-        System.arraycopy(b, 0, result, a.length, b.length);
-        return result;
-    }
+    /**
+     * The panel given to the Arena applet when it is requested.
+     */
+    private JPanel      panel;
     
-    public static String join(String[] a, String glue)
+    /**
+     * The text widget where log messages are appended.
+     */
+    private JTextArea   logArea;
+    
+    /**
+     * The current editor object (or null if there is none).
+     */
+    private Editor      editor;
+    
+    /**
+     * The configuration panel.
+     */
+    private JDialog     configDialog;
+    
+    
+    /**
+     * The key for the vim command preference.
+     */
+    private final static String VIMCOMMAND = "com.dogcows.VimCoder.config.vimcommand";
+    
+    /**
+     * The key for the root directory preference.
+     */
+    private final static String ROOTDIR = "com.dogcows.VimCoder.config.rootdir";
+    
+    /**
+     * The preferences object for storing plugin settings.
+     */
+    private static LocalPreferences prefs = LocalPreferences.getInstance();
+    
+    
+    /**
+     * Get the command for invoking vim.
+     * @return The command.
+     */
+    public static String getVimCommand()
     {
-        if (a.length == 0) return "";
-        StringBuilder result = new StringBuilder();
-        result.append(a[0]);
-        for (int i = 1; i < a.length; ++i) result.append(glue).append(a[i]);
-        return result.toString();
+        return vimCommand;
     }
     
-    public static String quote(String a)
+    /**
+     * Get the storage directory.
+     * @return The directory.
+     */
+    public static File getStorageDirectory()
     {
-        a = a.replaceAll("\\\\", "\\\\\\\\");
-        a = a.replaceAll("\"",   "\\\\\\\"");
-        return a;
+        return rootDir;
     }
 
    
+    /**
+     * Instantiate the entry point of the editor plugin.  Sets up the log widget
+     * and panel.
+     */
     public VimCoder()
     {
         logArea = new JTextArea();
@@ -302,22 +130,54 @@ public class VimCoder
     }
 
     
+    /**
+     * Called by the Arena when the plugin is about to be used.
+     */
     public void startUsing()
     {
-        logArea.setText("");
+        Runnable task = new Runnable()
+        {
+            public void run()
+            {
+                logArea.setText("");
+            }
+        };
+        if (SwingUtilities.isEventDispatchThread())
+        {
+            task.run();
+        }
+        else
+        {
+            SwingUtilities.invokeLater(task);
+        }
+        loadConfiguration();
     }
     
+    /**
+     * Called by the Arena when the plugin is no longer needed.
+     */
     public void stopUsing()
     {
         editor = null;
     }
     
+    /**
+     * Called by the Arena to obtain the editor panel which we will use to show
+     * log messages.
+     * @return The editor panel.
+     */
     public JPanel getEditorPanel()
     {
         return panel;
     }
    
-    public String getSource()
+    /**
+     * Called by the Arena to obtain the current source.  This happens when the
+     * user is saving, compiling, and/or submitting.
+     * @return The current source code.
+     * @throws Exception If the source file edited by Vim couldn't be read.
+     */
+    public String getSource() throws Exception
     {
         try
         {
@@ -325,79 +185,217 @@ public class VimCoder
             logInfo("Source code uploaded to server.");
             return source;
         }
-        catch (IOException exception)
+        catch (Exception exception)
         {
-            logError("failed to open file source file for reading");
-            return "";
+            logError("Failed to get source code: " +
+                     exception.getLocalizedMessage());
+            throw exception;
         }
     }
-   
+    
+    /**
+     * Called by the Arena to pass the source it has.
+     * @param source The source code.
+     */
     public void setSource(String source)
     {
         try
         {
             editor.setSource(source);
-            logInfo("source set");
+            logInfo("Source code downloaded from server.");
         }
-        catch (IOException exception)
+        catch (Exception exception)
         {
-            logError("failed setting the source");
+            logError("Failed to save the source given by the server: " +
+                     exception.getLocalizedMessage());
             return;
         }
     }
     
-    public void setProblemComponent(ProblemComponentModel component, Language language, Renderer renderer)
+    /**
+     * Called by the Arena to pass along information about the current problem.
+     * @param component A container for the particulars of the problem.
+     * @param language The currently selected language.
+     * @param renderer A helper object to help format the problem statement.
+     */
+    public void setProblemComponent(ProblemComponentModel component, 
+                                    Language language,
+                                    Renderer renderer)
     {
         try
         {
             editor = new Editor(component, language, renderer);
         }
-        catch (IOException exception)
+        catch (Exception exception)
         {
-            logError("failed while loading the problem");
+            logError("An error occured while loading the problem: " +
+                     exception.getLocalizedMessage());
         }
     }
-
-    public void setTextEnabled(Boolean enable)
+    
+    /**
+     * Called by the Arena when it's time to show our configuration panel.
+     */
+    public void configure()
     {
-        editor.setTextEnabled(enable);
+        loadConfiguration();
+        
+        configDialog = new JDialog();
+        Container pane = configDialog.getContentPane();
+        
+        pane.setPreferredSize(new Dimension(550, 135));
+        pane.setLayout(new GridBagLayout());
+        pane.setForeground(Common.FG_COLOR);
+        pane.setBackground(Common.WPB_COLOR);
+        GridBagConstraints c = new GridBagConstraints();
+        
+        JLabel rootDirLabel = new JLabel("Storage Directory:", SwingConstants.RIGHT);
+        rootDirLabel.setForeground(Common.FG_COLOR);
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.insets = new Insets(5, 5, 5, 5);
+        c.gridx = 0;
+        c.gridy = 0;
+        c.gridwidth = 1;
+        pane.add(rootDirLabel, c);
+        
+        final JTextField rootDirField = new JTextField(rootDir.getPath(), 25);
+        c.gridx = 1;
+        c.gridy = 0;
+        pane.add(rootDirField, c);
+        
+        JButton browseButton = new JButton("Browse");
+        c.gridx = 2;
+        c.gridy = 0;
+        c.anchor = GridBagConstraints.BASELINE_LEADING;
+        pane.add(browseButton, c);
+        
+        JLabel vimCommandLabel = new JLabel("Vim Command:", SwingConstants.RIGHT);
+        vimCommandLabel.setForeground(Common.FG_COLOR);
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.gridx = 0;
+        c.gridy = 1;
+        pane.add(vimCommandLabel, c);
+        
+        final JTextField vimCommandField = new JTextField(vimCommand, 25);
+        c.gridx = 1;
+        c.gridy = 1;
+        c.gridwidth = 2;
+        pane.add(vimCommandField, c);
+        
+        JButton closeButton = new JButton("Cancel");
+        c.fill = GridBagConstraints.NONE;
+        c.gridx = 1;
+        c.gridy = 2;
+        c.gridwidth = 1;
+        c.anchor = GridBagConstraints.EAST;
+        pane.add(closeButton, c);
+        
+        JButton saveButton = new JButton("Save");
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.gridx = 2;
+        c.gridy = 2;
+        c.anchor = GridBagConstraints.EAST;
+        pane.add(saveButton, c);
+        configDialog.getRootPane().setDefaultButton(saveButton);
+        
+        browseButton.addActionListener(new ActionListener()
+        {
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                JFileChooser chooser = new JFileChooser();
+                chooser.setCurrentDirectory(new File("."));
+                chooser.setDialogTitle("Choose Storage Directory");
+                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+                chooser.setAcceptAllFileFilterUsed(false);
+                
+                if (chooser.showOpenDialog(configDialog) == JFileChooser.APPROVE_OPTION)
+                {
+                    rootDirField.setText(chooser.getSelectedFile().getPath());
+                }
+            }
+        });
+        
+        closeButton.addActionListener(new ActionListener()
+        {
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                configDialog.dispose();
+            }
+        });
+        
+        saveButton.addActionListener(new ActionListener()
+        {
+            public void actionPerformed(ActionEvent actionEvent)
+            {
+                prefs.setProperty(VIMCOMMAND, vimCommandField.getText());
+                prefs.setProperty(ROOTDIR, rootDirField.getText());
+                configDialog.dispose();
+            }
+        });
+         
+        configDialog.setTitle("VimCoder Preferences");
+        configDialog.pack();
+        configDialog.setLocationByPlatform(true);
+        configDialog.setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
+        configDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+        configDialog.setVisible(true);
     }
     
     
-    private void log(String what)
+    /**
+     * Load the local preferences related to this plugin.
+     */
+    private void loadConfiguration()
     {
-        SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
-        String time = format.format(new Date());
-        logArea.append(time + ", " + what);
+        String vc  = prefs.getProperty(VIMCOMMAND);
+        if (vc != null) vimCommand = vc;
+        
+        String dir = prefs.getProperty(ROOTDIR);
+        if (dir != null) rootDir = new File(dir);
     }
+
     
-    private void logInfo(String what)
+    /**
+     * A generic logging function, appends text to the text area.  A timestamp
+     * is also prepended to the next text.
+     * @param what The text to append.
+     */
+    private void log(final String what)
     {
-        log(" INFO: " + what + "\n");
+        Runnable task = new Runnable()
+        {
+            public void run()
+            {
+                SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
+                logArea.append(format.format(new Date()) + ", " + what);
+            }
+        };
+        if (SwingUtilities.isEventDispatchThread())
+        {
+            task.run();
+        }
+        else
+        {
+            SwingUtilities.invokeLater(task);
+        }
     }
     
-    private void logWarning(String what)
+    /**
+     * Output non-critical messages to the log.
+     * @param what The text of the message.
+     */
+    private void logInfo(String what)
     {
-        log(" WARN: " + what + "\n");
+        log(" INFO: " + what + System.getProperty("line.separator"));
     }
-    
+
+    /**
+     * Output critical messages and errors to the log.
+     * @param what The text of the message.
+     */
     private void logError(String what)
     {
-        log("ERROR: " + what + "\n");
-    }
-    
-    
-    public static void main(String args[])
-    {
-        VimCoder plugin = new VimCoder();
-        
-        JFrame frame = new JFrame("VimCoder");
-        frame.add(plugin.getEditorPanel());
-        frame.setSize(640, 480);
-        frame.setVisible(true);
-        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-        
-        plugin.startUsing();
+        log("ERROR: " + what + System.getProperty("line.separator"));
     }
 }
 
This page took 0.033348 seconds and 4 git commands to generate.