/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.processeditor; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.io.IOException; import java.util.List; import java.util.logging.Level; import javax.swing.BorderFactory; import javax.swing.JPanel; import javax.swing.JToolBar; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rtextarea.RTextScrollPane; import com.rapidminer.Process; import com.rapidminer.gui.MainFrame; import com.rapidminer.gui.RapidMinerGUI; import com.rapidminer.gui.look.Colors; import com.rapidminer.gui.tools.ExtendedJToolBar; import com.rapidminer.gui.tools.ResourceAction; import com.rapidminer.gui.tools.ResourceDockKey; import com.rapidminer.operator.Operator; import com.rapidminer.tools.LogService; import com.rapidminer.tools.XMLException; import com.vlsolutions.swing.docking.DockKey; import com.vlsolutions.swing.docking.Dockable; /** * A text area for editing the process as XML. This editor is the second possible way to edit or * create RapidMiner processes. All changes are reflected by the process. However, it should be more * convenient to use the tree view for process design. <br/> * * This XML editor support very simple syntax highlighting based on keyword parsing. * * @author Ingo Mierswa, Simon Fischer */ public class XMLEditor extends JPanel implements ProcessEditor, Dockable { private static final long serialVersionUID = 4172143138689034659L; public static final String XML_EDITOR_DOCK_KEY = "xml_editor"; private final DockKey DOCK_KEY = new ResourceDockKey(XML_EDITOR_DOCK_KEY); { DOCK_KEY.setDockGroup(MainFrame.DOCK_GROUP_ROOT); } private final RSyntaxTextArea editor; private final MainFrame mainFrame; public XMLEditor(MainFrame mainFrame) { super(new BorderLayout()); this.mainFrame = mainFrame; // create text area this.editor = new RSyntaxTextArea(new RSyntaxDocument(SyntaxConstants.SYNTAX_STYLE_XML)); this.editor.setAnimateBracketMatching(true); this.editor.setAutoIndentEnabled(true); this.editor.setSelectionColor(Colors.TEXT_HIGHLIGHT_BACKGROUND); this.editor.setBorder(null); JToolBar toolBar = new ExtendedJToolBar(); toolBar.setBorder(null); toolBar.add(new ResourceAction(true, "xml_editor.apply_changes") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { try { validateProcess(); } catch (IOException | XMLException e1) { LogService.getRoot().log(Level.WARNING, "com.rapidminer.gui.processeditor.XMLEditor.failed_to_parse_process"); } } }); toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Colors.TEXTFIELD_BORDER)); add(toolBar, BorderLayout.NORTH); RTextScrollPane rTextScrollPane = new RTextScrollPane(editor); rTextScrollPane.setBorder(null); add(rTextScrollPane, BorderLayout.CENTER); } public void setText(String text) { this.editor.setText(text); } @Override public void processUpdated(Process process) { setText(process.getRootOperator().getXML(true)); } @Override public void processChanged(Process process) { processUpdated(process); } /** Just jumps to the position of the currently selected operator. */ @Override public void setSelection(List<Operator> selection) { if (!selection.isEmpty()) { Operator currentOperator = selection.get(0); String name = currentOperator.getName(); String text = this.editor.getText(); int result = text.indexOf("\"" + name + "\""); if (result >= 0) { this.editor.select(result + 1, result + name.length() + 1); this.editor.setCaretPosition(result + name.length() + 1); } } } public synchronized void validateProcess() throws IOException, XMLException { Process newExp = new Process(editor.getText().trim()); if (!newExp.getRootOperator().getXML(true) .equals(RapidMinerGUI.getMainFrame().getProcess().getRootOperator().getXML(true))) { Process old = RapidMinerGUI.getMainFrame().getProcess(); newExp.setProcessLocation(old.getProcessLocation()); mainFrame.setProcess(newExp, false); } } public String getXMLFromEditor() { return this.editor.getText().trim(); } @Override public Component getComponent() { return this; } @Override public DockKey getDockKey() { return DOCK_KEY; } }