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