]> Dogcows Code - chaz/vimcoder/blob - src/com/dogcows/VimCoder.java
a12846174651fe88062d54c0b399ebd19e3eeac2
[chaz/vimcoder] / src / com / dogcows / VimCoder.java
1
2 package com.dogcows;
3
4 import javax.swing.*;
5 import java.awt.*;
6 import java.awt.event.ActionEvent;
7 import java.awt.event.ActionListener;
8 import java.beans.PropertyChangeListener;
9 import java.io.*;
10 import java.text.SimpleDateFormat;
11 import java.util.*;
12 import com.topcoder.client.contestant.ProblemComponentModel;
13 import com.topcoder.shared.language.*;
14 import com.topcoder.shared.problem.*;
15 import com.topcoder.shared.problem.Renderer;
16 import com.topcoder.client.contestApplet.common.Common;
17 import com.topcoder.client.contestApplet.common.LocalPreferences;
18
19 /**
20 * @author Charles McGarvey
21 * The TopCoder Arena editor plug-in providing support for Vim.
22 *
23 * Distributable under the terms and conditions of the 2-clause BSD license;
24 * see the file COPYING for a complete text of the license.
25 */
26 public class VimCoder
27 {
28 /**
29 * The name and version of this plugin.
30 */
31 public final static String version = "VimCoder 0.3";
32
33 /**
34 * The website of the plugin project.
35 */
36 public final static String website = "http://www.dogcows.com/vimcoder";
37
38
39 /**
40 * The first part of the command used to invoke the Vim server.
41 */
42 private static String vimCommand = "gvim";
43
44 /**
45 * The path to the main VimCoder directory.
46 */
47 private static File rootDir;
48 static
49 {
50 if (System.getProperty("os.name").toLowerCase().equals("win"))
51 {
52 vimCommand = "C:\\WINDOWS\\gvim.bat";
53 }
54 rootDir = new File(System.getProperty("user.home") +
55 System.getProperty("file.separator") + ".vimcoder");
56 }
57
58
59 /**
60 * The panel given to the Arena applet when it is requested.
61 */
62 private JPanel panel;
63
64 /**
65 * The text widget where log messages are appended.
66 */
67 private JTextArea logArea;
68
69 /**
70 * The current editor object (or null if there is none).
71 */
72 private Editor editor;
73
74 /**
75 * The configuration panel.
76 */
77 private JDialog configDialog;
78
79
80 /**
81 * The key for the vim command preference.
82 */
83 private final static String VIMCOMMAND = "com.dogcows.VimCoder.config.vimcommand";
84
85 /**
86 * The key for the root directory preference.
87 */
88 private final static String ROOTDIR = "com.dogcows.VimCoder.config.rootdir";
89
90 /**
91 * The preferences object for storing plugin settings.
92 */
93 private static LocalPreferences prefs = LocalPreferences.getInstance();
94
95
96 /**
97 * Get the command for invoking vim.
98 * @return The command.
99 */
100 public static String getVimCommand()
101 {
102 return vimCommand;
103 }
104
105 /**
106 * Get the storage directory.
107 * @return The directory.
108 */
109 public static File getStorageDirectory()
110 {
111 return rootDir;
112 }
113
114
115 /**
116 * Instantiate the entry point of the editor plugin. Sets up the log widget
117 * and panel.
118 */
119 public VimCoder()
120 {
121 logArea = new JTextArea();
122 logArea.setForeground(Color.GREEN);
123 logArea.setBackground(Color.BLACK);
124 logArea.setEditable(false);
125 Font font = new Font("Courier", Font.PLAIN, 12);
126 if (font != null) logArea.setFont(font);
127
128 panel = new JPanel(new BorderLayout());
129 panel.add(new JScrollPane(logArea), BorderLayout.CENTER);
130 }
131
132
133 /**
134 * Called by the Arena when the plugin is about to be used.
135 */
136 public void startUsing()
137 {
138 Runnable task = new Runnable()
139 {
140 public void run()
141 {
142 logArea.setText("");
143 }
144 };
145 if (SwingUtilities.isEventDispatchThread())
146 {
147 task.run();
148 }
149 else
150 {
151 SwingUtilities.invokeLater(task);
152 }
153 loadConfiguration();
154 }
155
156 /**
157 * Called by the Arena when the plugin is no longer needed.
158 */
159 public void stopUsing()
160 {
161 editor = null;
162 }
163
164 /**
165 * Called by the Arena to obtain the editor panel which we will use to show
166 * log messages.
167 * @return The editor panel.
168 */
169 public JPanel getEditorPanel()
170 {
171 return panel;
172 }
173
174 /**
175 * Called by the Arena to obtain the current source. This happens when the
176 * user is saving, compiling, and/or submitting.
177 * @return The current source code.
178 * @throws Exception If the source file edited by Vim couldn't be read.
179 */
180 public String getSource() throws Exception
181 {
182 try
183 {
184 String source = editor.getSource();
185 logInfo("Source code uploaded to server.");
186 return source;
187 }
188 catch (Exception exception)
189 {
190 logError("Failed to get source code: " +
191 exception.getLocalizedMessage());
192 throw exception;
193 }
194 }
195
196 /**
197 * Called by the Arena to pass the source it has.
198 * @param source The source code.
199 */
200 public void setSource(String source)
201 {
202 try
203 {
204 editor.setSource(source);
205 logInfo("Source code downloaded from server.");
206 }
207 catch (Exception exception)
208 {
209 logError("Failed to save the source given by the server: " +
210 exception.getLocalizedMessage());
211 return;
212 }
213 }
214
215 /**
216 * Called by the Arena to pass along information about the current problem.
217 * @param component A container for the particulars of the problem.
218 * @param language The currently selected language.
219 * @param renderer A helper object to help format the problem statement.
220 */
221 public void setProblemComponent(ProblemComponentModel component,
222 Language language,
223 Renderer renderer)
224 {
225 try
226 {
227 editor = new Editor(component, language, renderer);
228 }
229 catch (Exception exception)
230 {
231 logError("An error occured while loading the problem: " +
232 exception.getLocalizedMessage());
233 }
234 }
235
236 /**
237 * Called by the Arena when it's time to show our configuration panel.
238 */
239 public void configure()
240 {
241 loadConfiguration();
242
243 configDialog = new JDialog();
244 Container pane = configDialog.getContentPane();
245
246 pane.setPreferredSize(new Dimension(550, 135));
247 pane.setLayout(new GridBagLayout());
248 pane.setForeground(Common.FG_COLOR);
249 pane.setBackground(Common.WPB_COLOR);
250 GridBagConstraints c = new GridBagConstraints();
251
252 JLabel rootDirLabel = new JLabel("Storage Directory:", SwingConstants.RIGHT);
253 rootDirLabel.setForeground(Common.FG_COLOR);
254 c.fill = GridBagConstraints.HORIZONTAL;
255 c.insets = new Insets(5, 5, 5, 5);
256 c.gridx = 0;
257 c.gridy = 0;
258 c.gridwidth = 1;
259 pane.add(rootDirLabel, c);
260
261 final JTextField rootDirField = new JTextField(rootDir.getPath(), 25);
262 c.gridx = 1;
263 c.gridy = 0;
264 pane.add(rootDirField, c);
265
266 JButton browseButton = new JButton("Browse");
267 c.gridx = 2;
268 c.gridy = 0;
269 c.anchor = GridBagConstraints.BASELINE_LEADING;
270 pane.add(browseButton, c);
271
272 JLabel vimCommandLabel = new JLabel("Vim Command:", SwingConstants.RIGHT);
273 vimCommandLabel.setForeground(Common.FG_COLOR);
274 c.fill = GridBagConstraints.HORIZONTAL;
275 c.gridx = 0;
276 c.gridy = 1;
277 pane.add(vimCommandLabel, c);
278
279 final JTextField vimCommandField = new JTextField(vimCommand, 25);
280 c.gridx = 1;
281 c.gridy = 1;
282 c.gridwidth = 2;
283 pane.add(vimCommandField, c);
284
285 JButton closeButton = new JButton("Cancel");
286 c.fill = GridBagConstraints.NONE;
287 c.gridx = 1;
288 c.gridy = 2;
289 c.gridwidth = 1;
290 c.anchor = GridBagConstraints.EAST;
291 pane.add(closeButton, c);
292
293 JButton saveButton = new JButton("Save");
294 c.fill = GridBagConstraints.HORIZONTAL;
295 c.gridx = 2;
296 c.gridy = 2;
297 c.anchor = GridBagConstraints.EAST;
298 pane.add(saveButton, c);
299 configDialog.getRootPane().setDefaultButton(saveButton);
300
301 browseButton.addActionListener(new ActionListener()
302 {
303 public void actionPerformed(ActionEvent actionEvent)
304 {
305 JFileChooser chooser = new JFileChooser();
306 chooser.setCurrentDirectory(new File("."));
307 chooser.setDialogTitle("Choose Storage Directory");
308 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
309 chooser.setAcceptAllFileFilterUsed(false);
310
311 if (chooser.showOpenDialog(configDialog) == JFileChooser.APPROVE_OPTION)
312 {
313 rootDirField.setText(chooser.getSelectedFile().getPath());
314 }
315 }
316 });
317
318 closeButton.addActionListener(new ActionListener()
319 {
320 public void actionPerformed(ActionEvent actionEvent)
321 {
322 configDialog.dispose();
323 }
324 });
325
326 saveButton.addActionListener(new ActionListener()
327 {
328 public void actionPerformed(ActionEvent actionEvent)
329 {
330 prefs.setProperty(VIMCOMMAND, vimCommandField.getText());
331 prefs.setProperty(ROOTDIR, rootDirField.getText());
332 configDialog.dispose();
333 }
334 });
335
336 configDialog.setTitle("VimCoder Preferences");
337 configDialog.pack();
338 configDialog.setLocationByPlatform(true);
339 configDialog.setModalityType(Dialog.DEFAULT_MODALITY_TYPE);
340 configDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
341 configDialog.setVisible(true);
342 }
343
344
345 /**
346 * Load the local preferences related to this plugin.
347 */
348 private void loadConfiguration()
349 {
350 String vc = prefs.getProperty(VIMCOMMAND);
351 if (vc != null) vimCommand = vc;
352
353 String dir = prefs.getProperty(ROOTDIR);
354 if (dir != null) rootDir = new File(dir);
355 }
356
357
358 /**
359 * A generic logging function, appends text to the text area. A timestamp
360 * is also prepended to the next text.
361 * @param what The text to append.
362 */
363 private void log(final String what)
364 {
365 Runnable task = new Runnable()
366 {
367 public void run()
368 {
369 SimpleDateFormat format = new SimpleDateFormat("kk:mm:ss");
370 logArea.append(format.format(new Date()) + ", " + what);
371 }
372 };
373 if (SwingUtilities.isEventDispatchThread())
374 {
375 task.run();
376 }
377 else
378 {
379 SwingUtilities.invokeLater(task);
380 }
381 }
382
383 /**
384 * Output non-critical messages to the log.
385 * @param what The text of the message.
386 */
387 private void logInfo(String what)
388 {
389 log(" INFO: " + what + System.getProperty("line.separator"));
390 }
391
392 /**
393 * Output critical messages and errors to the log.
394 * @param what The text of the message.
395 */
396 private void logError(String what)
397 {
398 log("ERROR: " + what + System.getProperty("line.separator"));
399 }
400 }
401
This page took 0.052466 seconds and 3 git commands to generate.