001package com.ganteater.ae.desktop.editor; 002 003import java.awt.BorderLayout; 004import java.awt.CardLayout; 005import java.awt.Color; 006import java.awt.Component; 007import java.awt.Desktop; 008import java.awt.Dimension; 009import java.awt.FileDialog; 010import java.awt.Font; 011import java.awt.Point; 012import java.awt.Toolkit; 013import java.awt.event.ActionEvent; 014import java.awt.event.ActionListener; 015import java.awt.event.KeyAdapter; 016import java.awt.event.KeyEvent; 017import java.awt.event.MouseAdapter; 018import java.awt.event.MouseEvent; 019import java.io.File; 020import java.io.FileOutputStream; 021import java.io.IOException; 022import java.lang.reflect.Constructor; 023import java.lang.reflect.InvocationTargetException; 024import java.util.ArrayList; 025import java.util.HashMap; 026import java.util.Map; 027import java.util.Properties; 028import java.util.Set; 029import java.util.Vector; 030 031import javax.swing.AbstractAction; 032import javax.swing.BorderFactory; 033import javax.swing.JButton; 034import javax.swing.JCheckBox; 035import javax.swing.JLabel; 036import javax.swing.JMenu; 037import javax.swing.JMenuBar; 038import javax.swing.JMenuItem; 039import javax.swing.JOptionPane; 040import javax.swing.JPanel; 041import javax.swing.JScrollPane; 042import javax.swing.JSeparator; 043import javax.swing.JSlider; 044import javax.swing.JSplitPane; 045import javax.swing.JTabbedPane; 046import javax.swing.JToolBar; 047import javax.swing.JTree; 048import javax.swing.JTree.DynamicUtilTreeNode; 049import javax.swing.KeyStroke; 050import javax.swing.SwingConstants; 051import javax.swing.SwingUtilities; 052import javax.swing.table.AbstractTableModel; 053import javax.swing.tree.DefaultMutableTreeNode; 054import javax.swing.tree.DefaultTreeModel; 055import javax.swing.tree.TreePath; 056import javax.swing.tree.TreeSelectionModel; 057 058import org.apache.commons.io.FilenameUtils; 059import org.apache.commons.lang.StringUtils; 060import org.apache.commons.lang.SystemUtils; 061import org.apache.commons.lang.exception.ExceptionUtils; 062 063import com.ganteater.ae.AEManager; 064import com.ganteater.ae.AEWorkspace; 065import com.ganteater.ae.CommandException; 066import com.ganteater.ae.ConfigurationException; 067import com.ganteater.ae.ILogger; 068import com.ganteater.ae.desktop.WorkPlace; 069import com.ganteater.ae.desktop.ui.AEFrame; 070import com.ganteater.ae.desktop.ui.AEPanel; 071import com.ganteater.ae.desktop.ui.DialogPopupMenu; 072import com.ganteater.ae.desktop.ui.TaskPanel; 073import com.ganteater.ae.desktop.view.ListLogPresenter; 074import com.ganteater.ae.desktop.view.LogPresenter; 075import com.ganteater.ae.desktop.view.PresentationPanel; 076import com.ganteater.ae.processor.BaseProcessor; 077import com.ganteater.ae.processor.Processor; 078import com.ganteater.ae.util.xml.easyparser.EasyParser; 079import com.ganteater.ae.util.xml.easyparser.EasyUtils; 080import com.ganteater.ae.util.xml.easyparser.Node; 081import com.ganteater.ae.util.xml.easyparser.Node.TreeVector; 082 083/** 084 * @author victort 085 * @version 1.0, 29-Jul-2005 086 */ 087public class TaskEditor extends WorkPlace implements AEPanel, AeEditPanel { 088 089 private static final String EDITOR_STD_PACKAGE = "com.ganteater.ae.desktop.editor."; 090 private static final String ABOUT = "About"; 091 private static final Color ACTIVE_COLOR = Color.GREEN.darker(); 092 private static final Font font = new Font("Monospaced", Font.PLAIN, 12); 093 094 private static final String TASK_EDITOR = "Editor"; 095 private static final String TASK_TREE = "Processing"; 096 097 private String fTaskFile; 098 private Vector<?> fTreeVector; 099 private Map<String, Object> fPresentationPanels = new HashMap<String, Object>(); 100 101 private AEFrame frame; 102 private JTree taskTree; 103 private TextEditor fTaskText = new TextEditor(); 104 private JTabbedPane fOutputTabbedPane; 105 private TaskPanel thePanel; 106 private JMenuItem fRunMenuItem = new JMenuItem("Run"); 107 private JMenuItem fContinueMenuItem = new JMenuItem("Continue"); 108 private JMenuItem fStopMenuItem = new JMenuItem("Stop"); 109 private JMenuItem fPauseMenuItem = new JMenuItem("Pause"); 110 private JButton fRunButton = new JButton("Run"); 111 private JCheckBox notifyMeCheckBox = new JCheckBox(); 112 private JMenuItem saveMenuItem; 113 private JSplitPane fOutputSplitPanel; 114 private JSlider speed = new JSlider(0, 100, 100); 115 private JTabbedPane createEditorPanel; 116 private JLabel changedLabel = new JLabel(""); 117 118 private JLabel lblTitle = new JLabel(); 119 private JTabbedPane tabbedPanel; 120 121 private boolean openIn; 122 123 private CodeHelper codeHelper = new CodeHelper(this, getLogger()); 124 125 public TaskEditor(AEFrame aFrame, Node aConfigNode, Map<String, Object> aSystemVariables) { 126 super(aFrame, aConfigNode, aSystemVariables); 127 this.frame = aFrame; 128 129 this.thePanel = new TaskPanel(this); 130 131 fOutputTabbedPane = new JTabbedPane(); 132 fOutputTabbedPane.setPreferredSize(new Dimension(200, 800)); 133 fOutputTabbedPane.addKeyListener(new KeyAdapter() { 134 @Override 135 public void keyReleased(KeyEvent e) { 136 if (e.getKeyCode() == KeyEvent.VK_F4 && e.isControlDown()) { 137 removeActivePresentationPanel(); 138 } 139 } 140 }); 141 142 fOutputTabbedPane.addMouseListener(new MouseAdapter() { 143 @Override 144 public void mouseClicked(MouseEvent e) { 145 JTabbedPane outputTabbedPane = (JTabbedPane) e.getSource(); 146 if (e.getButton() == MouseEvent.BUTTON2) { 147 if (outputTabbedPane.findComponentAt(e.getX(), e.getY()) == outputTabbedPane 148 && outputTabbedPane.indexAtLocation(e.getX(), e.getY()) != -1) { 149 150 Component selectedComponent = outputTabbedPane.getSelectedComponent(); 151 Object frameId = ((PresentationPanel) selectedComponent).getName(); 152 removeActivePresentationPanel(); 153 fPresentationPanels.remove(frameId); 154 } 155 } 156 if (e.getButton() == MouseEvent.BUTTON3) { 157 if (outputTabbedPane.findComponentAt(e.getX(), e.getY()) == outputTabbedPane 158 && outputTabbedPane.indexAtLocation(e.getX(), e.getY()) != -1) { 159 160 LogPresenter selectedComponent = (LogPresenter) outputTabbedPane.getSelectedComponent(); 161 162 if (!selectedComponent.isEmpty()) { 163 if (fLoggers.contains(selectedComponent)) { 164 String frameId = selectedComponent.getName(); 165 LogPresenter findLogger = findLogger(frameId); 166 LogPresenter bakPresenter = findLogger.copyAndClean(); 167 outputTabbedPane.addTab(frameId, AEFrame.getIcon("copied.png"), bakPresenter); 168 } 169 } 170 } 171 } 172 } 173 }); 174 createEditorPanel = createEditorPanel(); 175 176 fOutputSplitPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createEditorPanel, fOutputTabbedPane); 177 fOutputSplitPanel.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, e -> { 178 int dividerLocation = fOutputSplitPanel.getDividerLocation(); 179 String divider = Integer.toString(dividerLocation); 180 int selectedIndex = createEditorPanel.getSelectedIndex(); 181 AEWorkspace.getInstance().setDefaultUserConfiguration("splitPanel.divider." + selectedIndex, divider); 182 }); 183 184 setSplitPanel(); 185 186 thePanel.add(fOutputSplitPanel, BorderLayout.CENTER); 187 JMenuBar menuBar = new JMenuBar(); 188 189 createFileMenu(menuBar); 190 createProcessMenu(menuBar); 191 192 Node taskNode = getTaskNode(); 193 if (taskNode != null && taskNode.findNode(ABOUT, null, null) != null) { 194 showAbout(); 195 } 196 197 JToolBar panel2 = new JToolBar(); 198 panel2.setBorderPainted(false); 199 panel2.setFloatable(false); 200 panel2.add(fRunButton); 201 notifyMeCheckBox.setIcon(AEFrame.getIcon("shout-off.png")); 202 notifyMeCheckBox.setSelectedIcon(AEFrame.getIcon("shout.png")); 203 panel2.add(notifyMeCheckBox); 204 205 notifyMeCheckBox.addActionListener(e -> { 206 if (getTaskName() != null) { 207 String aName = getTaskName() + ".notifyMe"; 208 String value = Boolean.toString(notifyMeCheckBox.isSelected()); 209 AEWorkspace.getInstance().setDefaultUserConfiguration(aName, value); 210 AEWorkspace.getInstance().setDefaultUserConfiguration("notifyMe", value); 211 } 212 }); 213 214 speed.setPreferredSize(new Dimension(30, 18)); 215 speed.setToolTipText("Action speed"); 216 217 speed.addChangeListener(e -> { 218 String text; 219 long traceDelay = getTraceDelay(); 220 if (traceDelay < 1000) { 221 text = traceDelay + "ms."; 222 } else { 223 text = String.format("%.2f", traceDelay / 1000.0) + "s"; 224 } 225 226 speed.setToolTipText("Delay: " + text); 227 fTitleTest.setText("Slow motion time: " + text); 228 }); 229 230 JPanel panel = new JPanel(new BorderLayout(4, 4)); 231 panel.setBorder(BorderFactory.createEtchedBorder()); 232 panel.add(menuBar, BorderLayout.WEST); 233 234 JButton closeBtn = new JButton(AEFrame.getIcon("close.png")); 235 closeBtn.addActionListener(e -> { 236 stopTest(); 237 closeTab(); 238 }); 239 panel.add(closeBtn, BorderLayout.EAST); 240 241 thePanel.add(panel, BorderLayout.NORTH); 242 243 JPanel aboutPanel = new JPanel(new BorderLayout(0, 0)); 244 aboutButtonPanel.setBorderPainted(false); 245 aboutButtonPanel.setFloatable(false); 246 aboutPanel.add(panel2, BorderLayout.WEST); 247 248 JPanel titlePanel = new JPanel(new BorderLayout(0, 0)); 249 titlePanel.add(aboutButtonPanel, BorderLayout.WEST); 250 titlePanel.add(fTitleTest, BorderLayout.CENTER); 251 aboutPanel.add(titlePanel, BorderLayout.CENTER); 252 panel.add(aboutPanel, BorderLayout.CENTER); 253 } 254 255 public void setSplitPanel() { 256 fOutputSplitPanel.setOneTouchExpandable(true); 257 } 258 259 private String getTaskName() { 260 String name = null; 261 if (getTaskNode() != null) { 262 name = getTaskNode().getAttribute("name"); 263 } 264 return name; 265 } 266 267 public TaskEditor(AEFrame aeFrame) { 268 this(aeFrame, aeFrame.getWorkspace().getConfigNode(), aeFrame.getWorkspace().getSystemVariables()); 269 setRunButtonAction(true); 270 } 271 272 private void createFileMenu(JMenuBar menuBar) { 273 JMenu menu = new JMenu("File"); 274 275 JMenuItem menuItem; 276 menuItem = new JMenuItem("Save"); 277 try { 278 menuItem.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 279 } catch (Exception e) { 280 } 281 282 this.saveMenuItem = menuItem; 283 menuItem.addActionListener(new ActionListener() { 284 public void actionPerformed(ActionEvent arg0) { 285 286 SwingUtilities.invokeLater(() -> { 287 try { 288 save(); 289 } catch (IOException e) { 290 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), 291 "Error: Unable to Save File: " + fTaskFile); 292 } 293 }); 294 } 295 }); 296 menu.add(menuItem); 297 298 menuItem = new JMenuItem("Reload"); 299 final JMenuItem reloadmenuItem = menuItem; 300 try { 301 menuItem.setAccelerator(KeyStroke.getKeyStroke('R', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 302 } catch (Exception e) { 303 } 304 menuItem.addActionListener(arg0 -> { 305 reload(); 306 }); 307 menu.add(menuItem); 308 309 menuItem = new JMenuItem("Format"); 310 try { 311 menuItem.setAccelerator(KeyStroke.getKeyStroke('F', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 312 } catch (Exception e) { 313 } 314 menuItem.addActionListener(arg0 -> { 315 format(); 316 }); 317 menu.add(menuItem); 318 319 menuItem = new JMenuItem("System TextEditor"); 320 try { 321 menuItem.setAccelerator(KeyStroke.getKeyStroke('E', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 322 } catch (Exception e) { 323 } 324 menuItem.addActionListener(arg0 -> { 325 File file = new File(fTaskFile); 326 if (file.exists()) { 327 try { 328 Desktop.getDesktop().open(file); 329 openIn = true; 330 reloadmenuItem.setText("Reload [Before Run]"); 331 332 } catch (IOException e) { 333 getLogger().error(e.getMessage(), e); 334 } 335 } 336 }); 337 menu.add(menuItem); 338 339 menu.add(new JSeparator()); 340 menuItem = new JMenuItem("Close"); 341 try { 342 menuItem.setAccelerator(KeyStroke.getKeyStroke('X', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 343 } catch (Exception e) { 344 } 345 menuItem.addActionListener(e -> { 346 closeTab(); 347 }); 348 menu.add(menuItem); 349 menuBar.add(menu); 350 } 351 352 public void reload() { 353 openTaskFile(fTaskFile); 354 } 355 356 public void save() throws IOException { 357 changedLabel.setText(""); 358 format(); 359 saveTask(); 360 361 try { 362 frame.getWorkspace().refreshTaskPath(); 363 } catch (IOException e) { 364 getLogger().error("Failed to update recipe list.", e); 365 } 366 } 367 368 public void format() { 369 try { 370 compileTask(); 371 refreshTaskTree(); 372 373 Node taskNode = getTaskNode(); 374 applyText(taskNode); 375 376 if (taskNode != null && taskNode.findNode(ABOUT, null, null) != null) { 377 showAbout(); 378 } 379 380 } catch (Exception e) { 381 getLogger().error("Save action failed.", e); 382 } 383 } 384 385 private void createProcessMenu(JMenuBar menuBar) { 386 JMenu menu = new JMenu("Process"); 387 388 JMenuItem compileMenuItem = new JMenuItem("Compile"); 389 menu.add(compileMenuItem); 390 compileMenuItem.addActionListener(arg0 -> { 391 try { 392 compileTask(); 393 } catch (Exception e) { 394 getLogger().error("Compilation failed.", e); 395 } 396 }); 397 398 menu.add(fRunMenuItem); 399 400 try { 401 fRunMenuItem.setAccelerator( 402 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 403 } catch (Exception e) { 404 } 405 406 fRunMenuItem.addActionListener(e -> { 407 runTask(); 408 }); 409 menu.add(speed); 410 411 fRunButton.addActionListener(e -> { 412 boolean isCurrentRunAction = "Run".equals(e.getActionCommand()); 413 414 if (isCurrentRunAction) { 415 runTask(); 416 } else { 417 stopTest(); 418 if (getTaskProcessor().isStoppedTest()) { 419 setRunButtonAction(true); 420 } 421 } 422 }); 423 424 menu.add(fPauseMenuItem); 425 426 try { 427 fPauseMenuItem 428 .setAccelerator(KeyStroke.getKeyStroke('P', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 429 } catch (Exception e) { 430 } 431 432 fPauseMenuItem.addActionListener(e -> { 433 getTaskProcessor().pause(); 434 }); 435 436 menu.add(fContinueMenuItem); 437 438 try { 439 fContinueMenuItem 440 .setAccelerator(KeyStroke.getKeyStroke('P', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 441 } catch (Exception e) { 442 } 443 444 fContinueMenuItem.addActionListener(arg0 -> getTaskProcessor().resume()); 445 446 try { 447 fStopMenuItem.setAccelerator( 448 KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); 449 } catch (Exception e) { 450 } 451 452 fStopMenuItem.addActionListener(arg0 -> stopTask()); 453 menu.add(fStopMenuItem); 454 menuBar.add(menu); 455 } 456 457 @Override 458 public void setProgress(String message, long aMaxTags, long aCurrTags, boolean aErrorState) { 459 manager.progressValue((int) (((double) aCurrTags / aMaxTags) * 100), 100, true); 460 fTitleTest.setText(message); 461 } 462 463 public void stopTask() { 464 super.stopTest(); 465 } 466 467 private JTabbedPane createEditorPanel() { 468 JTabbedPane editorPanel = new JTabbedPane(); 469 editorPanel.setTabPlacement(SwingConstants.BOTTOM); 470 471 JScrollPane scrollPane = new JScrollPane(); 472 scrollPane.getViewport().add(fTaskText); 473 474 fTaskText.addKeyListener(codeHelper); 475 fTaskText.addMouseListener(codeHelper); 476 477 fTaskText.setEditable(true); 478 fTaskText.addKeyListener(new KeyAdapter() { 479 @Override 480 public void keyTyped(KeyEvent e) { 481 changedLabel.setText("*"); 482 } 483 }); 484 485 fTaskText.setFont(font); 486 487 JScrollPane theScroll = new JScrollPane(); 488 theScroll.getViewport().removeAll(); 489 taskTree = new JTree(); 490 taskTree.setRootVisible(false); 491 taskTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 492 493 taskTree.addMouseListener(new MouseAdapter() { 494 @Override 495 public void mousePressed(MouseEvent e) { 496 if (e.getClickCount() == 2) { 497 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) taskTree 498 .getLastSelectedPathComponent(); 499 TreeVector userObject = (TreeVector) selectedNode.getUserObject(); 500 Node node = userObject.getNode(); 501 502 String tagName = node.getTag(); 503 if ("Task".equals(tagName)) { 504 String name = node.getAttribute("name"); 505 TaskEditor editTask = getAeFrame().editTask(name); 506 editTask.setRunButtonAction(true); 507 } 508 } 509 } 510 }); 511 512 theScroll.getViewport().add(taskTree); 513 514 editorPanel.addTab(TASK_TREE, theScroll); 515 editorPanel.addTab(TASK_EDITOR, scrollPane); 516 517 editorPanel.addChangeListener(e -> { 518 519 int selectedIndex = editorPanel.getSelectedIndex(); 520 String divider = AEWorkspace.getInstance() 521 .getDefaultUserConfiguration("splitPanel.divider." + selectedIndex, null); 522 if (divider != null) { 523 fOutputSplitPanel.setDividerLocation(Integer.parseInt(divider)); 524 } 525 526 Component selectedComponent = editorPanel.getSelectedComponent(); 527 if (selectedComponent instanceof VariableViewPanel) { 528 VariableViewPanel panel = (VariableViewPanel) selectedComponent; 529 panel.refreshData(); 530 } 531 }); 532 533 return editorPanel; 534 } 535 536 public void compileTask() { 537 try { 538 Node object = new EasyParser().getObject(fTaskText.getText()); 539 setTaskNode(object); 540 541 } catch (Exception e1) { 542 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "Incorrect code!\nError: " + e1.getMessage()); 543 throw e1; 544 } 545 } 546 547 public void showPanel(JTabbedPane panel, String name) { 548 if (name == null) { 549 name = getPanelName(); 550 } 551 tabbedPanel = panel; 552 String tabNameId = Integer.toString(thePanel.hashCode()); 553 panel.addTab(tabNameId, thePanel); 554 panel.setSelectedComponent(thePanel); 555 556 JPanel pnlTab = new JPanel(new BorderLayout()); 557 pnlTab.setOpaque(false); 558 pnlTab.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0)); 559 560 setTitle(name); 561 lblTitle.addMouseListener(new MouseAdapter() { 562 @Override 563 public void mouseClicked(MouseEvent var1) { 564 int index = tabbedPanel.indexOfTab(tabNameId); 565 int button = var1.getButton(); 566 if (button == MouseEvent.BUTTON2) { 567 TaskEditor.this.frame.removeTab(TaskEditor.this); 568 } else { 569 tabbedPanel.setSelectedIndex(index); 570 } 571 } 572 }); 573 574 pnlTab.add(lblTitle, BorderLayout.CENTER); 575 pnlTab.add(changedLabel, BorderLayout.EAST); 576 577 int index = tabbedPanel.indexOfTab(tabNameId); 578 tabbedPanel.setTabComponentAt(index, pnlTab); 579 } 580 581 private void setTitle(String name) { 582 lblTitle.setText(StringUtils.abbreviate(name, 12)); 583 lblTitle.setToolTipText(name); 584 } 585 586 public JPanel getMainPanel() { 587 return thePanel; 588 } 589 590 @Override 591 public void endTask(boolean aErrorState) { 592 super.endTask(aErrorState); 593 fRunMenuItem.setEnabled(true); 594 setRunButtonAction(true); 595 } 596 597 private void openTaskFile(String filePath) { 598 fTaskFile = filePath; 599 if (new File(fTaskFile).exists() && !openIn) { 600 setEditable(true); 601 } 602 603 try { 604 Node node = new EasyParser().load(filePath); 605 applyText(node); 606 } catch (Exception e1) { 607 throw new ConfigurationException("Invalide recipe file.", e1); 608 } 609 610 } 611 612 private void applyText(Node node) { 613 setTaskNode(node); 614 int caretPosition = fTaskText.getCaretPosition(); 615 EasyUtils.removeTagId(node); 616 617 fTaskText.setOriginalText(node.getXMLText()); 618 fTaskText.setCaretPosition(caretPosition); 619 refreshTaskTree(); 620 } 621 622 private void addExternTabs() { 623 Node taskNode = getConfigNode(); 624 if (taskNode != null) { 625 Node[] editors = taskNode.getNodes(TASK_EDITOR); 626 createEditors(editors); 627 } 628 629 taskNode = getTaskNode(); 630 if (taskNode != null) { 631 Node[] editors = taskNode.getNodes(TASK_EDITOR); 632 createEditors(editors); 633 } 634 } 635 636 private void createEditors(Node[] editors) { 637 for (Node editorNode : editors) { 638 String className = editorNode.getAttribute("class"); 639 if (className != null) { 640 Class<?> filterClass; 641 try { 642 if (!className.startsWith(EDITOR_STD_PACKAGE)) { 643 className = EDITOR_STD_PACKAGE + className; 644 } 645 646 filterClass = Class.forName(className); 647 Constructor<?> constructor = filterClass.getConstructor(); 648 649 String name = editorNode.getAttribute("name"); 650 String tabName = StringUtils.defaultIfEmpty(name, StringUtils.substringAfterLast(className, ".")); 651 652 JPanel editor = (JPanel) constructor.newInstance(); 653 if (editor instanceof Editor) { 654 ((Editor) editor).init(this, editorNode); 655 } 656 createEditorPanel.addTab(tabName, editor); 657 658 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException 659 | IllegalAccessException | IllegalArgumentException | InvocationTargetException 660 | CommandException e) { 661 e.printStackTrace(); 662 JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), 663 "The creation of the extended panel failed.\nError: " 664 + ExceptionUtils.getRootCauseMessage(e)); 665 } 666 } 667 } 668 } 669 670 private void setEditable(boolean editable) { 671 saveMenuItem.setEnabled(editable); 672 fTaskText.setEditable(editable); 673 } 674 675 protected void refreshTaskTree() { 676 if (getTaskNode() != null) { 677 fTreeVector = getTaskNode().getVector(true); 678 679 DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); 680 DynamicUtilTreeNode.createChildren(root, fTreeVector); 681 DefaultTreeModel model = new DefaultTreeModel(root, false); 682 taskTree.setModel(model); 683 684 taskTree.setEditable(false); 685 taskTree.setEnabled(true); 686 687 taskTree.setFont(font); 688 taskTree.setForeground(ACTIVE_COLOR); 689 for (int i = 0; i < taskTree.getRowCount(); i++) { 690 taskTree.expandRow(i); 691 } 692 } 693 } 694 695 @Override 696 public void changeVariable(String aAttribut, Object aValue) { 697 } 698 699 static class JBorderedPanel extends JPanel { 700 private static final long serialVersionUID = 1L; 701 702 public JBorderedPanel(Component aNorth, Component aWest, Component aCenter, Component aEast, Component aSouth) { 703 setLayout(new BorderLayout()); 704 if (aNorth != null) { 705 add(aNorth, BorderLayout.NORTH); 706 } 707 if (aWest != null) { 708 add(aWest, BorderLayout.WEST); 709 } 710 if (aCenter != null) { 711 add(aCenter, BorderLayout.CENTER); 712 } 713 if (aEast != null) { 714 add(aEast, BorderLayout.EAST); 715 } 716 if (aSouth != null) { 717 add(aSouth, BorderLayout.SOUTH); 718 } 719 } 720 } 721 722 @Override 723 public void startCommand(int aNumberCommand) { 724 setRunButtonAction(false); 725 try { 726 if (taskTree != null) { 727 taskTree.setSelectionRow(aNumberCommand); 728 long delay = getTraceDelay(); 729 if (delay > 0) { 730 try { 731 Thread.sleep(delay); 732 } catch (Exception e) { 733 Thread.currentThread().interrupt(); 734 } 735 } 736 } 737 } catch (Exception e) { 738 // 739 } 740 } 741 742 private long getTraceDelay() { 743 return (int) ((Math.pow(1.5, (double) (100 - speed.getValue()) / 4)) - 1); 744 } 745 746 @Override 747 public void aboutTest(String theTaskName, Node aCurrentAction) { 748 try { 749 setAbout(theTaskName, aCurrentAction); 750 aboutButtonPanel.setVisible(true); 751 } catch (Exception e) { 752 getLogger().error("Error", e); 753 } 754 } 755 756 @Override 757 public void runCommandFrame(Properties params) { 758 String theFrameId = params.getProperty("frameId"); 759 String title = params.getProperty("title"); 760 761 String reuse = params.getProperty("reuse"); 762 if ("true".equals(reuse)) { 763 PresentationPanel thePPanel = (PresentationPanel) fPresentationPanels.get(theFrameId); 764 if (thePPanel != null && thePPanel.isValid()) { 765 return; 766 } 767 } 768 769 createFrame(theFrameId, params, title); 770 } 771 772 private PresentationPanel createFrame(String theFrameId, Properties linkedMap, String title) { 773 774 if (title == null) { 775 title = theFrameId; 776 } 777 778 String className = linkedMap.getProperty("type", "TextPanel"); 779 780 if (className.indexOf('.') < 0) { 781 className = "com.ganteater.ae.desktop.view." + className; 782 } 783 784 Class<?> ppClass; 785 try { 786 ppClass = Class.forName(className); 787 Constructor<?> constructor = ppClass.getConstructor(Properties.class, AEManager.class); 788 PresentationPanel pPanel = (PresentationPanel) constructor.newInstance(linkedMap, manager); 789 790 fPresentationPanels.put(theFrameId, pPanel); 791 fOutputTabbedPane.add(title, pPanel); 792 793 fOutputTabbedPane.setSelectedComponent(pPanel); 794 return pPanel; 795 796 } catch (Exception e) { 797 throw new IllegalArgumentException(e); 798 } 799 } 800 801 @Override 802 public void outToFrame(Processor processor, Properties properties, Object value) { 803 String frameId = processor.replaceProperties((String) properties.get("frameId")); 804 if (frameId != null) { 805 PresentationPanel panel = (PresentationPanel) fPresentationPanels.get(frameId); 806 if (panel != null) { 807 Properties params = panel.getParams(); 808 809 if (fOutputTabbedPane.getComponentZOrder(panel) < 0) { 810 fPresentationPanels.remove(frameId); 811 panel = null; 812 } 813 814 if (panel == null) { 815 createFrame(frameId, params, null); 816 } else { 817 panel.out(value, properties); 818 } 819 } 820 } 821 } 822 823 public void removeActivePresentationPanel() { 824 int selectedIndex = fOutputTabbedPane.getSelectedIndex(); 825 826 Component theComp = fOutputTabbedPane.getComponent(selectedIndex); 827 if (theComp instanceof PresentationPanel) { 828 PresentationPanel thePPanel = (PresentationPanel) theComp; 829 fPresentationPanels.remove(thePPanel.getName()); 830 } 831 832 fOutputTabbedPane.remove(selectedIndex); 833 fLoggers.remove(findLogger(theComp)); 834 } 835 836 int fNumberLog = 1; 837 838 private ArrayList<LogPresenter> fLoggers = new ArrayList<LogPresenter>(); 839 private boolean isRunning; 840 841 public ILogger createLog(String aLogName, boolean mainLog) { 842 843 LogPresenter loggPanel = findLogger(aLogName); 844 845 if (loggPanel == null) { 846 if (aLogName == null || aLogName.length() == 0) 847 aLogName = "Log #" + String.valueOf(fNumberLog++); 848 loggPanel = new ListLogPresenter(this, aLogName, mainLog); 849 outputPaneAdd(loggPanel); 850 } 851 852 setLog(loggPanel); 853 return loggPanel; 854 } 855 856 public void setLog(ILogger log) { 857 super.setLog(log); 858 codeHelper.setLog(log); 859 } 860 861 private LogPresenter findLogger(String aLogName) { 862 if (aLogName == null && fLoggers.size() > 0) { 863 return fLoggers.get(0); 864 } 865 866 int tabCount = fLoggers.size(); 867 for (int i = 0; i < tabCount; i++) { 868 LogPresenter logger = (LogPresenter) fLoggers.get(i); 869 if (logger.getName().equals(aLogName)) { 870 return logger; 871 } 872 } 873 874 return null; 875 } 876 877 private LogPresenter findLogger(Component comp) { 878 int tabCount = fLoggers.size(); 879 for (int i = 0; i < tabCount; i++) { 880 LogPresenter logger = (LogPresenter) fLoggers.get(i); 881 if (logger == comp) { 882 return logger; 883 } 884 } 885 return null; 886 } 887 888 @Override 889 public void errorInformation(Processor processor, Throwable exception, Node command) throws CommandException { 890 try { 891 frame.errorInformation(processor, exception, command, notifyMeCheckBox.isSelected()); 892 } catch (CommandException e) { 893 throw e; 894 } catch (Throwable e) { 895 throw new CommandException(e, processor, command); 896 } 897 } 898 899 class VarTableModel extends AbstractTableModel { 900 private static final long serialVersionUID = 1L; 901 private String[][] fRows; 902 903 public VarTableModel() throws Exception { 904 Set<String> enumeration = getSystemVariables().keySet(); 905 fRows = new String[getSystemVariables().size()][2]; 906 int i = 0; 907 for (String theName : enumeration) { 908 String theValue = (String) getSystemVariables().get(theName); 909 fRows[i][0] = theName; 910 fRows[i][1] = theValue; 911 i++; 912 } 913 } 914 915 public int getColumnCount() { 916 return 2; 917 } 918 919 public int getRowCount() { 920 return getSystemVariables().size(); 921 } 922 923 public Class<String> getColumnClass(int columnIndex) { 924 return String.class; 925 } 926 927 public Object getValueAt(int row, int col) { 928 return fRows[row][col]; 929 } 930 931 public boolean isCellEditable(int rowIndex, int columnIndex) { 932 return columnIndex > 0; 933 } 934 935 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 936 if (columnIndex == 1) { 937 getSystemVariables().put(fRows[rowIndex][0], aValue); 938 fRows[rowIndex][1] = (String) aValue; 939 } 940 } 941 942 public String getColumnName(int column) { 943 if (column == 0) { 944 return "Name"; 945 } else { 946 return "Value"; 947 } 948 } 949 950 } 951 952 public void outputPaneAdd(LogPresenter logPanel) { 953 fLoggers.add(logPanel); 954 LogPresenter panel = logPanel; 955 fOutputTabbedPane.add(logPanel.getName(), panel); 956 fPresentationPanels.put(logPanel.getName(), logPanel); 957 fOutputTabbedPane.setSelectedComponent(panel); 958 } 959 960 @Override 961 public void setActiveTest(String theActiveTest) { 962 String fileName = manager.getTestPath(theActiveTest); 963 if (fileName == null) { 964 throw new IllegalArgumentException("Task file is not found. Recipe: " + theActiveTest); 965 } 966 967 setActiveTestFile(fileName); 968 969 addExternTabs(); 970 } 971 972 private void setActiveTestFile(String fileName) { 973 openTaskFile(fileName); 974 recipeFilePath = fileName; 975 976 boolean editable = new File(fTaskFile).exists(); 977 saveMenuItem.setEnabled(editable); 978 fTaskText.setEditable(editable); 979 980 Node taskNode = getTaskNode(); 981 boolean c = taskNode != null && taskNode.findNode(ABOUT, null, null) != null; 982 if (c) { 983 showAbout(); 984 } 985 } 986 987 public void runTaskNode() { 988 989 Thread thread = new Thread() { 990 public void run() { 991 try { 992 Processor processor; 993 994 File parentFile = SystemUtils.getUserDir(); 995 if (fTaskFile != null) { 996 parentFile = new File(fTaskFile).getParentFile(); 997 } 998 999 String selectedText = fTaskText.getSelectedText(); 1000 1001 Node taskNode; 1002 Map<String, Object> hashtable; 1003 if (selectedText == null) { 1004 compileTask(); 1005 taskNode = getTaskNode(); 1006 processor = createProcessor(); 1007 hashtable = processor.startVariables; 1008 } else { 1009 String code = fTaskText.getText(0, fTaskText.getSelectionStart()); 1010 code = StringUtils.substringAfterLast(code, "<Extern "); 1011 if (!StringUtils.isEmpty(code)) { 1012 code = "<Extern " + code; 1013 selectedText = StringUtils.substringBefore(code, ">") + ">" + selectedText + "</Extern>"; 1014 } 1015 1016 code = "<Task>" + selectedText + "</Task>"; 1017 1018 taskNode = new EasyParser().getObject(code); 1019 setRunButtonAction(false); 1020 1021 processor = getTaskProcessor(); 1022 hashtable = processor.getVariables(); 1023 } 1024 taskNode.getVector(true); 1025 1026 processor.processTesting(taskNode, hashtable, parentFile); 1027 processor.getListener().endTask(false); 1028 endTask(false); 1029 setRunButtonAction(true); 1030 1031 } catch (Exception e) { 1032 e.printStackTrace(); 1033 } 1034 } 1035 1036 }; 1037 1038 thread.start(); 1039 } 1040 1041 private void runProcessTreeLine() { 1042 TreePath[] selectedPaths = taskTree.getSelectionPaths(); 1043 if (createEditorPanel.getSelectedIndex() == 0 && selectedPaths != null) { 1044 Processor processor = getTaskProcessor(); 1045 Node taskNode = new Node("Task"); 1046 setRunButtonAction(false); 1047 for (TreePath path : selectedPaths) { 1048 DefaultMutableTreeNode lastPathComponent = (DefaultMutableTreeNode) path.getLastPathComponent(); 1049 TreeVector userObject = (TreeVector) lastPathComponent.getUserObject(); 1050 Node node = userObject.getNode(); 1051 if ("Recipe".equals(node.getTag())) { 1052 taskNode = node; 1053 processor = createProcessor(); 1054 Map<String, Object> hashtable = processor.startVariables; 1055 } else { 1056 taskNode.add(node); 1057 processor = getTaskProcessor(); 1058 } 1059 } 1060 } 1061 } 1062 1063 private Processor createProcessor() { 1064 String attribute = getTaskNode().getAttribute("name"); 1065 if (attribute == null || attribute.isEmpty()) 1066 attribute = getTaskNode().getAttribute("description"); 1067 1068 ILogger createLog = createLog(attribute, true); 1069 setProcessor(null); 1070 Processor processor = new BaseProcessor(getManager(), createLog, getManager().getStartDir()); 1071 processor.init(fConfigNode, getSystemVariables(), this, getManager().getStartDir(), createLog); 1072 processor.setTestListener(this); 1073 1074 setProcessor(processor); 1075 return processor; 1076 } 1077 1078 public void start(String name) { 1079 if (StringUtils.isNotBlank(name)) { 1080 setActiveTest(name); 1081 runTaskNode(); 1082 } 1083 fRunMenuItem.setEnabled(false); 1084 } 1085 1086 public void setRunButtonAction(boolean runAction) { 1087 this.isRunning = !runAction; 1088 if (runAction) { 1089 try { 1090 fRunButton.setText("Run"); 1091 fRunButton.setToolTipText("Run"); 1092 fContinueMenuItem.setEnabled(false); 1093 fRunMenuItem.setEnabled(true); 1094 fStopMenuItem.setEnabled(false); 1095 fPauseMenuItem.setEnabled(false); 1096 lblTitle.setBorder(BorderFactory.createEmptyBorder()); 1097 } catch (Exception e) { 1098 e.printStackTrace(); 1099 } 1100 1101 } else { 1102 try { 1103 fRunButton.setText("Stop"); 1104 fRunButton.setToolTipText("Stop"); 1105 fContinueMenuItem.setEnabled(false); 1106 fRunMenuItem.setEnabled(false); 1107 fStopMenuItem.setEnabled(true); 1108 fPauseMenuItem.setEnabled(true); 1109 lblTitle.setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, ACTIVE_COLOR)); 1110 } catch (Exception e) { 1111 e.printStackTrace(); 1112 } 1113 } 1114 } 1115 1116 public void edit(String name) { 1117 ListLogPresenter log = new ListLogPresenter(this, name); 1118 setLog(log); 1119 outputPaneAdd(log); 1120 fRunMenuItem.setEnabled(true); 1121 } 1122 1123 public void create(String name) { 1124 ListLogPresenter log = new ListLogPresenter(this, name); 1125 setLog(log); 1126 1127 fRunMenuItem.setEnabled(true); 1128 Node node = new EasyParser().getObject("<Recipe name=\"" + name + "\">\n<!-- your recipe code -->\n</Recipe>"); 1129 applyText(node); 1130 1131 runTest(new Node[] { node }); 1132 fContinueMenuItem.setEnabled(false); 1133 } 1134 1135 public String getPanelName() { 1136 Processor processor = getTaskProcessor(); 1137 return processor.getTestName(); 1138 } 1139 1140 public void saveTask() throws IOException { 1141 String recipeName = getTaskNode().getAttribute("name"); 1142 if (fTaskFile == null || !fTaskFile.startsWith("jar:")) { 1143 1144 if (fTaskFile == null) { 1145 FileDialog theFileDialog = new FileDialog(JOptionPane.getRootFrame(), "Save Recipe File", 1146 FileDialog.SAVE); 1147 if (getTaskNode() != null) { 1148 theFileDialog.setFile(recipeName + ".recipe"); 1149 } 1150 theFileDialog.setVisible(true); 1151 if (theFileDialog.getFile() == null) 1152 return; 1153 fTaskFile = new File(theFileDialog.getDirectory() + theFileDialog.getFile()).getAbsolutePath(); 1154 } 1155 1156 if (getTaskNode() != null) { 1157 File file = new File(fTaskFile); 1158 String name = FilenameUtils.getBaseName(file.getName()); 1159 String oldName = getTaskNode().getAttribute("name"); 1160 if (!StringUtils.equals(name, oldName)) { 1161 File newfile = new File(file.getParent(), oldName + ".recipe"); 1162 if (file.renameTo(newfile)) { 1163 file = newfile; 1164 fTaskFile = file.getAbsolutePath(); 1165 } 1166 } 1167 1168 Node theNode = (Node) getTaskNode().clone(); 1169 String newName = theNode.getAttribute("name"); 1170 1171 getManager().getRemoveTestPath(oldName); 1172 getManager().setTestPath(newName, fTaskFile); 1173 1174 EasyUtils.removeTagId(theNode); 1175 1176 byte[] bytes = getTaskNode().getXMLText().getBytes("UTF-8"); 1177 1178 try (FileOutputStream theFileOutputStream = new FileOutputStream(fTaskFile)) { 1179 theFileOutputStream.write(bytes); 1180 } 1181 1182 setTitle(recipeName); 1183 } 1184 } 1185 } 1186 1187 public void runTask() { 1188 try { 1189 final String selectedText = fTaskText.getSelectedText(); 1190 1191 if (openIn && selectedText == null) { 1192 reload(); 1193 } 1194 1195 getManager().startTaskNotify(this); 1196 runTaskNode(); 1197 1198 } catch (Exception e) { 1199 getLogger().error("Running failed.", e); 1200 } 1201 } 1202 1203 @Override 1204 public void criticalError(final CommandException exception, final Processor processor) { 1205 frame.criticalError(TaskEditor.this); 1206 lblTitle.setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, Color.RED)); 1207 1208 if (isNotifyMe()) { 1209 getFrame().fireBuzzAction(() -> super.criticalError(exception, processor)); 1210 } else { 1211 super.criticalError(exception, processor); 1212 } 1213 } 1214 1215 @Override 1216 public void checkFailure(final CommandException exception, final Processor processor) { 1217 frame.checkFailure(TaskEditor.this); 1218 1219 if (isNotifyMe()) { 1220 getFrame().fireBuzzAction(() -> super.checkFailure(exception, processor)); 1221 } else { 1222 super.checkFailure(exception, processor); 1223 } 1224 } 1225 1226 public void closeTab() { 1227 frame.removeTab(TaskEditor.this); 1228 } 1229 1230 public void showAbout() { 1231 Node taskNode = getTaskNode(); 1232 aboutTest(taskNode.getAttribute("name"), taskNode.findNode(ABOUT, null, null)); 1233 } 1234 1235 public void showTaskTreePane() { 1236 CardLayout cl = (CardLayout) (createEditorPanel.getLayout()); 1237 cl.show(createEditorPanel, TASK_TREE); 1238 } 1239 1240 public int getCaretPosition() { 1241 return fTaskText.getCaretPosition(); 1242 } 1243 1244 public Point getMagicCaretPosition() { 1245 return fTaskText.getCaret().getMagicCaretPosition(); 1246 } 1247 1248 public String getText() { 1249 return fTaskText.getText(); 1250 } 1251 1252 public void replaceRange(String text, int i, int caretPosition2) { 1253 fTaskText.replaceRange(text, i, caretPosition2); 1254 } 1255 1256 public DialogPopupMenu contextHelp(DialogPopupMenu menu) { 1257 return menu; 1258 } 1259 1260 @Override 1261 public void runTest(Node testNode[]) { 1262 Node object = testNode[0]; 1263 object.getVector(true); 1264 setTaskNode(object); 1265 refreshTaskTree(); 1266 runTaskNode(); 1267 } 1268 1269 public AEFrame getFrame() { 1270 return frame; 1271 } 1272 1273 public void pause() { 1274 fRunMenuItem.setEnabled(false); 1275 fContinueMenuItem.setEnabled(true); 1276 fPauseMenuItem.setEnabled(false); 1277 1278 fTitleTest.setText(" Suspended execution ..."); 1279 fTitleTest.setForeground(Color.YELLOW.darker()); 1280 lblTitle.setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, Color.YELLOW)); 1281 } 1282 1283 @Override 1284 public void resume() { 1285 fRunMenuItem.setEnabled(false); 1286 fContinueMenuItem.setEnabled(false); 1287 fPauseMenuItem.setEnabled(true); 1288 1289 fTitleTest.setText(""); 1290 fTitleTest.setForeground(Color.GRAY.darker()); 1291 lblTitle.setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, ACTIVE_COLOR)); 1292 } 1293 1294 public boolean isRunning() { 1295 return isRunning; 1296 } 1297 1298 public TextEditor getEditor() { 1299 return fTaskText; 1300 } 1301 1302 public void select() { 1303 getFrame().setSelectedComponent(getMainPanel()); 1304 } 1305 1306 @Override 1307 public void setTaskNode(Node taskNode) { 1308 super.setTaskNode(taskNode); 1309 String aName = getTaskName() + ".notifyMe"; 1310 String defaultNotify = AEWorkspace.getInstance().getDefaultUserConfiguration("notifyMe", "true"); 1311 boolean notify = Boolean 1312 .parseBoolean(AEWorkspace.getInstance().getDefaultUserConfiguration(aName, defaultNotify)); 1313 notifyMeCheckBox.setSelected(notify); 1314 } 1315 1316 public boolean isNotifyMe() { 1317 return notifyMeCheckBox.isSelected(); 1318 } 1319 1320}