/* * Copyright (C) 2010 Markus Echterhoff <tam@edu.uni-klu.ac.at> * * This file is part of EvoPaint. * * EvoPaint is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EvoPaint. If not, see <http://www.gnu.org/licenses/>. */ package evopaint.gui.rulesetmanager; import evopaint.Configuration; import evopaint.pixel.rulebased.interfaces.IDescribable; import evopaint.pixel.rulebased.interfaces.IDescribed; import evopaint.pixel.rulebased.interfaces.INameable; import evopaint.pixel.rulebased.interfaces.INamed; import evopaint.util.ExceptionHandler; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.border.BevelBorder; import javax.swing.border.LineBorder; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; /** * * @author Markus Echterhoff <tam@edu.uni-klu.ac.at> */ public class JDescriptionPanel extends JPanel implements TreeSelectionListener { private String title; // cos getName() was declared in super class private String description; private Configuration configuration; private JRuleSetTree tree; private JPanel contentPane; private JTextPane viewerTextPane; private JPanel viewerControlPanel; private JTextField editorTitleField; private JTextArea editorDescriptionArea; private JButton btnEdit; private String defaultTitle = "DON'T PANIC"; private String defaultDescription = "Things to remember:<ul>" + "<li>Every pixel follows a set of rules. <b>Only the first rule</b> whose conditions are met is ever executed (beginning from the top of the list). If none of the rules matches, your pixel will idle.</li><br>" + "<li>You can <b>reorder</b> the list of rules of any rule set using drag and drop.</li><br>" + "<li>To <b>rename</b> or <b>describe</b> a rule set, click the 'Edit' button of the description panel.</li></ul>"; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; render(); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; render(); } public void setBoth(String title, String description) { this.title = title; this.description = description; render(); } public String getEditedTitle() { return editorTitleField.getText(); } public String getEditedDescription() { return editorDescriptionArea.getText(); } public void clear() { title = null; description = null; render(); } private void render() { String heading = "<h1 style='text-align: center;'>" + title + "</h1>"; String html = "<html><body>" + heading + "<p>" + newLineToBreak(description) + "</p></body></html>"; viewerTextPane.setText(html); } private String newLineToBreak(String s) { return s.replaceAll("\n", "<br>"); } public void valueChanged(TreeSelectionEvent e) { ((CardLayout)contentPane.getLayout()).show(contentPane, "viewer"); DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.getPath().getLastPathComponent(); Object userObject = node.getUserObject(); if (userObject == null) { title = defaultTitle; description = defaultDescription; render(); viewerControlPanel.setVisible(false); return; } title = ((INamed)userObject).getName(); description = ((IDescribed)userObject).getDescription(); render(); viewerControlPanel.setVisible(true); viewerTextPane.setCaretPosition(0); } public JDescriptionPanel(Configuration configuration, JRuleSetTree tree) { this.configuration = configuration; this.tree = tree; this.contentPane = this; tree.addTreeSelectionListener(this); setBorder(new LineBorder(Color.GRAY)); setLayout(new CardLayout()); // viewer JPanel viewer = new JPanel(); viewer.setLayout(new BorderLayout()); viewerTextPane = new JTextPane(); viewerTextPane.setContentType("text/html"); viewerTextPane.setEditable(false); viewerTextPane.setBackground(Color.WHITE); viewerTextPane.addHyperlinkListener(new HyperlinkListener() { public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() != HyperlinkEvent.EventType.ACTIVATED) { return; } try { Desktop.getDesktop().browse(e.getURL().toURI()); } catch (URISyntaxException ex) { ExceptionHandler.handle(ex, false, "The URL \"" + e.getURL().toString() + "\" is invalid."); } catch (IOException ex) { ExceptionHandler.handle(ex, false, "Could not open the URI for some reason"); } } }); JScrollPane viewerScrollPane = new JScrollPane(viewerTextPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); viewerScrollPane.setBorder(null); viewerScrollPane.setViewportBorder(null); viewerControlPanel = new JPanel(); viewerControlPanel.setBackground(new Color(0xF2F2F5)); btnEdit = new JButton(new ImageIcon(getClass().getResource("icons/button-edit.png"))); btnEdit.setToolTipText("Edit name and description of this collection or rule set"); btnEdit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((CardLayout)contentPane.getLayout()).show(contentPane, "editor"); editorTitleField.setText(title); editorDescriptionArea.setText(description); editorDescriptionArea.setCaretPosition(0); } }); viewerControlPanel.add(btnEdit); viewerControlPanel.setVisible(false); viewer.add(viewerScrollPane, BorderLayout.CENTER); viewer.add(viewerControlPanel, BorderLayout.SOUTH); // editor JPanel editor = new JPanel(); editor.setBorder(new LineBorder(getBackground(), 10)); editor.setLayout(new BorderLayout(10, 10)); //editor.setBackground(new Color(0xF2F2F5)); editorTitleField = new JTextField(); editorTitleField.setBorder(new BevelBorder(BevelBorder.LOWERED)); editorDescriptionArea = new JTextArea(); editorDescriptionArea.setLineWrap(true); editorDescriptionArea.setWrapStyleWord(true); JScrollPane editorScrollPane = new JScrollPane(editorDescriptionArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); editorScrollPane.setBorder(null); editorScrollPane.setViewportBorder(new BevelBorder(BevelBorder.LOWERED)); JPanel editorControlPanel = new JPanel(); //editorControlPanel.setBackground(new Color(0xF2F2F5)); JButton btnSave = new JButton("Save"); btnSave.addActionListener(new DescriptionEditorBtnSaveListener()); btnSave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((CardLayout)contentPane.getLayout()).show(contentPane, "viewer"); } }); editorControlPanel.add(btnSave); JButton btnCancel = new JButton("Cancel"); btnCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ((CardLayout)contentPane.getLayout()).show(contentPane, "viewer"); } }); editorControlPanel.add(btnCancel); editor.add(editorTitleField, BorderLayout.NORTH); editor.add(editorScrollPane, BorderLayout.CENTER); editor.add(editorControlPanel, BorderLayout.SOUTH); add(viewer, "viewer"); add(editor, "editor"); title = defaultTitle; description = defaultDescription; render(); } private class DescriptionEditorBtnSaveListener implements ActionListener { public void actionPerformed(ActionEvent e) { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent(); DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) selectedNode.getParent(); String desiredName = editorTitleField.getText(); if (false == tree.isUniqueSiblingName(parentNode, selectedNode.getUserObject(), desiredName)) { return; } // edit name and description in tree Object userObject = selectedNode.getUserObject(); String oldName = ((INamed)userObject).getName(); ((INameable)userObject).setName(desiredName); ((IDescribable)userObject).setDescription(editorDescriptionArea.getText()); // fire node change event DefaultTreeModel model = (DefaultTreeModel)tree.getModel(); model.nodesChanged(parentNode, new int [] {parentNode.getIndex(selectedNode)}); // update our own display title = editorTitleField.getText(); description = editorDescriptionArea.getText(); render(); } } }