001 /* 002 * LAPIS lightweight structured text processing system 003 * 004 * Copyright (C) 1998-2002 Carnegie Mellon University, 005 * Copyright (C) 2003 Massachusetts Institute of Technology. 006 * All rights reserved. 007 * 008 * This library is free software; you can redistribute it 009 * and/or modify it under the terms of the GNU General 010 * Public License as published by the Free Software 011 * Foundation, version 2. 012 * 013 * LAPIS homepage: http://graphics.lcs.mit.edu/lapis/ 014 */ 015 016 package lapis.swing; 017 018 import lapis.*; 019 import lapis.tc.*; 020 import java.awt.event.*; 021 import java.io.*; 022 import javax.swing.*; 023 import lapisx.swing.*; 024 025 public abstract class ToolAction extends AcceleratedAction { 026 public static lapisx.util.Debug debug = lapisx.util.Debug.QUIET; 027 028 Browser browser; 029 Tool tool; 030 BrowserArguments args; 031 boolean usesSelection; 032 033 public ToolAction (Browser browser, Tool tool, String label, boolean usesSelection) { 034 super (label); 035 this.browser = browser; 036 this.tool = tool; 037 this.usesSelection = usesSelection; 038 } 039 040 public class BrowserArguments extends Arguments { 041 String command; 042 043 public BrowserArguments () { 044 super (browser.getInterpreter ()); 045 } 046 } 047 048 public abstract BrowserArguments makeArguments (); 049 050 public NamedRegionSet getSelection () { 051 return browser.getSelection (); 052 } 053 054 public String quote (TC pat) { 055 return pat != null 056 ? quote (pat.getExpression ()) 057 : "selection"; 058 } 059 060 public String quote (String s) { 061 if (s == null) 062 return "selection"; 063 064 String t = browser.getInterpreter ().quote (s); 065 debug.println ("quoted '" + s + "' to get '" + t + "'"); 066 return t; 067 } 068 069 070 public void actionPerformed (ActionEvent event) { 071 browser.stop (); 072 073 if (usesSelection && getSelection ().isEmpty ()) { 074 browser.getToolkit ().beep (); 075 return; 076 } 077 078 args = makeArguments (); 079 if (args == null) 080 return; 081 082 // Set the interpreter's input document 083 browser.getInterpreter ().setVar (Interpreter.DOCUMENT_VAR, 084 browser.getDocument ()); 085 086 browser.run (new RunnableWithExceptions () { 087 public void run () throws Exception { 088 final Document result = tool.invoke (args); 089 if (result instanceof StatusWriter) { 090 ((StatusWriter) result).close (); 091 } else if (result != null) { 092 if (args.command != null) { 093 if (result.getProperty (SwingDocument.CommandProperty) == null) 094 result.putProperty (SwingDocument.CommandProperty, 095 args.command); 096 } 097 098 SwingUtilities.invokeLater (new Runnable () { 099 public void run () { 100 if (args.command != null) 101 browser.setCommand (args.command, true); 102 browser.setDocument (result); 103 browser.getActivePane ().requestFocus (); 104 } 105 }); 106 } 107 } 108 }); 109 } 110 111 static class ToolboxAction extends ToolAction { 112 public ToolboxAction (Browser browser, Toolbox.Info info) { 113 super (browser, info.getTool (), info.getName (), false); 114 115 String tooltip = info.getDescription (); 116 if (tooltip != null) 117 putValue (SHORT_DESCRIPTION, tooltip); 118 119 File iconFile = info.getIcon (); 120 if (iconFile != null) 121 putValue (SMALL_ICON, new ImageIcon (iconFile.toString ())); 122 } 123 124 public BrowserArguments makeArguments () { 125 return new BrowserArguments (); 126 } 127 } 128 129 130 static class ToolboxChange implements Toolbox.ToolBoxListener { 131 Browser browser; 132 133 public ToolboxChange (Browser browser) { 134 this.browser = browser; 135 } 136 137 public void toolAdded(Toolbox toolBox, Toolbox.Info info){ 138 debug.println("Calling " + info.getName() + " to toolbar."); 139 browser.addToToolBar(info); 140 141 } 142 143 public void toolChanged(Toolbox toolBox, Toolbox.Info info){ 144 // browser.removeFromToolBar(info); 145 // browser.addToToolBar(info); 146 browser.changeInTool(info); 147 148 } 149 public void toolRemoved(Toolbox toolBox, Toolbox.Info info){ 150 debug.println("Calling " + info.getName() + " to toolbar."); 151 browser.removeFromTools(info); 152 } 153 } 154 155 156 157 /** 158 * Action for Keep tool. 159 */ 160 public static class Keep extends ToolAction { 161 public Keep (Browser browser) { 162 super (browser, new lapis.tools.Keep (), "&Keep", true); 163 } 164 165 public BrowserArguments makeArguments () { 166 NamedRegionSet sel = getSelection (); 167 BrowserArguments args = (BrowserArguments) new BrowserArguments () 168 .add ("query", sel) 169 .add ("outof", sel.getPattern ().getUniversePattern ()) 170 ; 171 args.command = "keep " + quote (sel.getPattern ()); 172 return args; 173 } 174 } 175 176 177 /** 178 * Action for Sort tool. Sorts selection 179 * to create a new document, and displays that. 180 */ 181 public static class Sort extends ToolAction { 182 public Sort (Browser browser) { 183 super (browser, new lapis.tools.Sort (), "&Sort...", true); 184 } 185 186 public BrowserArguments makeArguments () { 187 SortDialog dialog = new SortDialog (); 188 dialog.show (); 189 return dialog.args; 190 } 191 192 class SortDialog extends OkCancelDialog { 193 ButtonGroup keyGroup; 194 JRadioButton useEntireRecord; // use entire record as sort key 195 JRadioButton usePattern; // use specified pattern as sort key 196 TCEditor keyPattern; 197 198 JComboBox order; // alphabetic, numeric, etc. 199 BrowserArguments args; // null until created by ok() 200 201 public SortDialog () { 202 super (browser, "Sort"); 203 204 Layout layout = Layout.gridbag (getControlsPane ()) 205 .setAlignment (Layout.NORTHWEST) 206 .setSize (Layout.FIXED_SIZE); 207 208 layout 209 .add (new JLabel ("Sort Key: ")) 210 .add (useEntireRecord = new JRadioButton ("Full record")) 211 .nextRow () 212 .nextColumn () 213 .add (usePattern = new JRadioButton ("Part of record matching: ")) 214 .nextRow () 215 .nextColumn () 216 .add (keyPattern = new TCEditor (true), Layout.ANY_SIZE) 217 .nextRow (); 218 219 keyGroup = new ButtonGroup (); 220 keyGroup.add (useEntireRecord); 221 keyGroup.add (usePattern); 222 useEntireRecord.setSelected (true); 223 keyPattern.setEnabled (false); 224 225 keyPattern.addMouseListener (new MouseAdapter () { 226 public void mousePressed (MouseEvent event) { 227 usePattern.setSelected (true); 228 keyPattern.setEnabled (true); 229 keyPattern.requestFocus (); 230 } 231 }); 232 ActionListener enabler = new ActionListener () { 233 public void actionPerformed (ActionEvent event) { 234 boolean usingPattern = usePattern.isSelected (); 235 keyPattern.setEnabled (usingPattern); 236 if (usingPattern) 237 keyPattern.requestFocus (); 238 } 239 }; 240 useEntireRecord.addActionListener (enabler); 241 usePattern.addActionListener (enabler); 242 243 String yourLanguage = 244 java.util.Locale.getDefault ().getDisplayLanguage (); 245 if (yourLanguage.equals ("")) 246 yourLanguage = "Dictionary"; 247 layout 248 .add (new JLabel ("Order: ")) 249 .add (order = new JComboBox (new String[] { 250 yourLanguage + " (a b c ...)", 251 "Reverse " + yourLanguage + " (z y x ...)", 252 "Numeric (1 2 3 ...)", 253 "Reverse Numeric (9 8 7 ...)", 254 "Unicode (A B C ... a b c ...)", 255 "Reverse Unicode (z y x ... Z Y X ...)", 256 "Random" })) 257 .nextRow (); 258 order.setEditable (false); 259 260 SortDialog.this.pack (); 261 } 262 263 public void ok () { 264 try { 265 // Create arguments 266 NamedRegionSet sel = getSelection (); 267 args = (BrowserArguments)new BrowserArguments () 268 .add ("query", sel) 269 ; 270 args.command = "sort " + quote (sel.getPattern ()); 271 272 if (usePattern.isSelected ()) { 273 TC keys = PatternPane.makeTCFromTextComponent (keyPattern, 274 true); 275 args.add ("by", keys); 276 args.command += " -by " + quote (keyPattern.getText ()); 277 } 278 279 boolean reversed; 280 String orderCode; 281 args.addName ("order"); 282 switch (order.getSelectedIndex ()) { 283 case 0: 284 reversed = false; 285 orderCode = "dictionary"; 286 break; 287 case 1: 288 reversed = true; 289 orderCode = "dictionary"; 290 break; 291 case 2: 292 reversed = false; 293 orderCode = "numeric"; 294 break; 295 case 3: 296 reversed = true; 297 orderCode = "numeric"; 298 break; 299 case 4: 300 reversed = false; 301 orderCode = "unicode"; 302 break; 303 case 5: 304 reversed = true; 305 orderCode = "unicode"; 306 break; 307 case 6: 308 reversed = false; 309 orderCode = "random"; 310 break; 311 default: 312 throw new RuntimeException ("illegal sort order: " + order.getSelectedIndex ()); 313 } 314 315 if (reversed) 316 args.addValue ("reverse"); 317 args.addValue (orderCode); 318 319 if (! ("dictionary".equals (orderCode) && !reversed)) 320 args.command += " -order " + (reversed ? "reverse " : "") + orderCode; 321 322 323 super.ok (); 324 } catch (TCParseException e) { 325 FeedbackForm.showMessageDialog (browser, 326 e.getMessage (), 327 "Parse Error", 328 JOptionPane.ERROR_MESSAGE); 329 args = null; 330 } 331 } 332 } 333 } 334 335 336 /** 337 * Action for Replace tool. 338 */ 339 public static class Replace extends ToolAction { 340 public Replace (Browser browser) { 341 super (browser, new lapis.tools.Replace (), "&Replace...", true); 342 } 343 344 public BrowserArguments makeArguments () { 345 ReplaceDialog dialog = new ReplaceDialog (); 346 dialog.show (); 347 return dialog.args; 348 } 349 350 class ReplaceDialog extends OkCancelDialog { 351 352 JTextArea template; 353 JCheckBox isTemplate; 354 BrowserArguments args; // null until created by ok() 355 356 public ReplaceDialog () { 357 super (browser, "Replace"); 358 359 Layout.gridbag (getControlsPane ()) 360 .setAlignment (Layout.WEST) 361 .add (new JLabel ("Replace Each Selection With: "), Layout.FIXED_SIZE) 362 .nextRow () 363 .add (template = new JTextArea (5, 40)) 364 .nextRow () 365 .add (isTemplate = 366 new JCheckBox ("Substitute curly braces", false)) 367 .nextRow () 368 ; 369 ReplaceDialog.this.pack (); 370 } 371 372 public void ok () { 373 try { 374 // Configure arguments 375 NamedRegionSet sel = getSelection (); 376 args = (BrowserArguments) new BrowserArguments () 377 .add ("query", sel) 378 ; 379 String tclCommand = "replace " + quote (sel.getPattern ()); 380 381 try { 382 String tmplt = template.getText (); 383 args.add ("replace", 384 lapis.tools.Template.makeFromString (tmplt)); 385 tclCommand += " " + quote (tmplt); 386 } catch (TCParseException e) { 387 // Select the error, then re-throw the exception 388 TCEditor.selectParseError (template, e); 389 throw e; 390 } 391 392 args.command = tclCommand; 393 394 super.ok (); 395 } catch (TCParseException e) { 396 FeedbackForm.showMessageDialog (browser, 397 e.getMessage (), 398 "Parse Error", 399 JOptionPane.ERROR_MESSAGE); 400 args = null; 401 } 402 } 403 } 404 } 405 406 407 408 /** 409 * Action for Delete tool (called "Omit" in UI). 410 */ 411 public static class Omit extends ToolAction { 412 public Omit (Browser browser) { 413 super (browser, new lapis.tools.Delete (), "&Omit", true); 414 } 415 416 public BrowserArguments makeArguments () { 417 NamedRegionSet sel = getSelection (); 418 BrowserArguments args = (BrowserArguments) new BrowserArguments () 419 .add ("query", sel) 420 ; 421 args.command = "omit " + quote (sel.getPattern ()); 422 return args; 423 } 424 } 425 426 427 /** 428 * Action for Extract tool. 429 */ 430 public static class Extract extends ToolAction { 431 public Extract (Browser browser) { 432 super (browser, new lapis.tools.Extract (), "&Extract", true); 433 } 434 435 public BrowserArguments makeArguments () { 436 NamedRegionSet sel = getSelection (); 437 BrowserArguments args = 438 (BrowserArguments) new BrowserArguments () 439 .add ("query", sel) 440 ; 441 args.command = "extract " + quote (sel.getPattern ()); 442 return args; 443 } 444 } 445 446 447 /** 448 * Action for Calc tool. 449 */ 450 public static class Calc extends ToolAction { 451 public Calc (Browser browser) { 452 super (browser, new lapis.tools.Calc (), "&Calc", true); 453 } 454 455 public BrowserArguments makeArguments () { 456 NamedRegionSet sel = getSelection (); 457 BrowserArguments args = (BrowserArguments) new BrowserArguments () 458 .add ("query", sel) 459 ; 460 args.command = "calc " + quote (sel.getPattern ()); 461 return args; 462 } 463 } 464 465 } 466