001package com.ganteater.ae.desktop.editor; 002 003import java.awt.event.ActionEvent; 004import java.awt.event.KeyAdapter; 005import java.awt.event.KeyEvent; 006import java.lang.reflect.Constructor; 007 008import javax.swing.AbstractAction; 009import javax.swing.JPopupMenu; 010import javax.swing.JTextArea; 011import javax.swing.text.BadLocationException; 012import javax.swing.text.DefaultCaret; 013import javax.swing.text.Document; 014import javax.swing.undo.UndoManager; 015 016import org.apache.commons.lang.StringUtils; 017 018import com.ganteater.ae.CommandException; 019import com.ganteater.ae.desktop.util.UIUtils; 020import com.ganteater.ae.util.xml.easyparser.Node; 021 022public class TextEditor extends JTextArea implements Editor { 023 024 private static final long serialVersionUID = -298735473495909314L; 025 private final UndoManager undo = new UndoManager(); 026 private TaskEditor recipePanel; 027 private Node editorNode; 028 private CodeHelper codeHelper; 029 030 public TextEditor() { 031 super(); 032 setTabSize(4); 033 Document doc = getDocument(); 034 doc.addUndoableEditListener((evt) -> undo.addEdit(evt.getEdit())); 035 addKeyListener(new KeyAdapter() { 036 @Override 037 public void keyPressed(KeyEvent e) { 038 if (e.getKeyCode() == KeyEvent.VK_Z && e.isControlDown()) { 039 undo(); 040 } else if (e.getKeyCode() == KeyEvent.VK_Y && e.isControlDown()) { 041 redo(); 042 } 043 } 044 }); 045 046 setCaret(new DefaultCaret() { 047 @Override 048 public void setSelectionVisible(boolean visible) { 049 super.setSelectionVisible(true); 050 } 051 }); 052 053 initPopupMenu(); 054 } 055 056 protected void initPopupMenu() { 057 JPopupMenu popup = new JPopupMenu(); 058 059 popup.add(new AbstractAction("Code Helper") { 060 private static final long serialVersionUID = 1L; 061 062 @Override 063 public void actionPerformed(ActionEvent ae) { 064 codeHelper.showCommandsMenu(); 065 } 066 }); 067 popup.add(new AbstractAction("Run Selection") { 068 private static final long serialVersionUID = 1L; 069 070 @Override 071 public void actionPerformed(ActionEvent ae) { 072 try { 073 getRecipePanel().runCode(true); 074 } catch (BadLocationException | CommandException e) { 075 // TODO Auto-generated catch block 076 e.printStackTrace(); 077 } 078 } 079 }); 080 popup.addSeparator(); 081 082 UIUtils.addJPopupMenuTo(this, popup); 083 } 084 085 @Override 086 public void init(TaskEditor taskEditor) throws CommandException { 087 this.recipePanel = taskEditor; 088 setFont(TaskEditor.font); 089 090 String helper = null; 091 if (editorNode != null) { 092 helper = taskEditor.getTaskProcessor().attr(editorNode, "helper"); 093 } 094 if (helper == null) { 095 helper = CodeHelper.class.getName(); 096 } 097 if (!helper.startsWith(TaskEditor.EDITOR_STD_PACKAGE)) { 098 helper = TaskEditor.EDITOR_STD_PACKAGE + helper; 099 } 100 101 try { 102 @SuppressWarnings("unchecked") 103 Class<? extends CodeHelper> filterClass = (Class<? extends CodeHelper>) Class.forName(helper); 104 Constructor<? extends CodeHelper> constructor = filterClass.getConstructor(TextEditor.class); 105 codeHelper = constructor.newInstance(this); 106 addKeyListener(codeHelper); 107 108 } catch (Exception e) { 109 throw new IllegalArgumentException(e); 110 } 111 } 112 113 public void redo() { 114 try { 115 int caretPosition = getCaretPosition(); 116 if (undo.canRedo()) { 117 undo.redo(); 118 if (getDocument().getLength() == 0) { 119 if (undo.canRedo()) { 120 undo.redo(); 121 } else if (undo.canUndo()) { 122 undo.undo(); 123 } 124 } 125 } 126 setCaretPosition(caretPosition); 127 } catch (Exception e) { 128 // no nothing. 129 } 130 } 131 132 public void undo() { 133 try { 134 int caretPosition = getCaretPosition(); 135 if (undo.canUndo()) { 136 undo.undo(); 137 if (getDocument().getLength() == 0) { 138 if (undo.canUndo()) { 139 undo.undo(); 140 } else if (undo.canRedo()) { 141 undo.redo(); 142 } 143 } 144 } 145 setCaretPosition(caretPosition); 146 } catch (Exception e) { 147 // no nothing. 148 } 149 } 150 151 public void removeLine() { 152 int caretPosition = getCaretPosition(); 153 String text = getText(); 154 int start = StringUtils.lastIndexOf(text, "\n", caretPosition - 1); 155 start = start < 0 ? 0 : start + 1; 156 int end = StringUtils.indexOf(text, "\n", caretPosition); 157 end = end < 0 ? text.length() - 1 : end + 1; 158 start = start < end ? start : end; 159 replaceRange("", start, end); 160 setCaretPosition(start == 0 ? 0 : start); 161 } 162 163 public void setOriginalText(String xmlText) { 164 setText(xmlText); 165 } 166 167 public TaskEditor getRecipePanel() { 168 return recipePanel; 169 } 170 171 public Node getEditorNode() { 172 return editorNode; 173 } 174 175 public void setEditorNode(Node editorNode) { 176 this.editorNode = editorNode; 177 } 178 179}