/* * (c) 2005-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved. * Licencia en license/bsd.txt / License in license/bsd.txt * * Created at regulus on 22-jul-2005 23:55:11 * as file DescriptionListPanel.java on package org.f2o.absurdum.puck.gui.panels */ package org.f2o.absurdum.puck.gui.panels; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.ScrollPaneConstants; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.text.JTextComponent; import org.f2o.absurdum.puck.gui.SpacingPanel; import org.f2o.absurdum.puck.gui.util.GUIUtils; import org.f2o.absurdum.puck.i18n.UIMessages; import org.f2o.absurdum.puck.util.swing.EnhancedJList; import org.f2o.absurdum.puck.util.swing.EnhancedJTextArea; import org.f2o.absurdum.puck.util.swing.EnhancedJTextField; import org.f2o.absurdum.puck.util.swing.SwingComponentHighlighter; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * @author carlos * * Created at regulus, 22-jul-2005 23:55:11 */ public class DescriptionListPanel extends JPanel { //TODO: Completar soporte de nombre propio. //Para ello, hacer que el checkbox correspondiente meta un texto "Proper:" o lo que sea en la descripci�n, //que �ste sirva para que al clickearla se ponga el checkbox como debe, //pero luego que a XML se escriba m�s bien: //<Description properName="true"> si es propio, o sin el atributo si no lo es. private JList theList; private JTextField condTextField = new EnhancedJTextField(20); //private JTextField descTextField = new EnhancedJTextField(20); private JTextComponent descTextField; private JButton delButton = new JButton(UIMessages.getInstance().getMessage("button.del")); private JButton addButton = new JButton(UIMessages.getInstance().getMessage("button.add")); private JButton modButton = new JButton(UIMessages.getInstance().getMessage("button.mod")); private JButton topButton = new JButton(UIMessages.getInstance().getMessage("button.top")); private JLabel descLabel; private JLabel condLabel; //privatize it public DefaultListModel listContent = new DefaultListModel(); //support for SUCCESS: and FAIL: descriptions on openables, closeables, etc. //added 2007-04-07 private boolean succFail = false; private JCheckBox succCheckBox = new JCheckBox(UIMessages.getInstance().getMessage("checkbox.success")); //support for proper name //beginning to add, as of 2009-01-31 private boolean propNamesEnabled = false; private JCheckBox propCheckBox = new JCheckBox(UIMessages.getInstance().getMessage("checkbox.propername")); private Vector /*of Boolean*/ propList = new Vector(); private static int MED_SKIP = 6; private static int SMALL_SKIP = 3; //debugging private DefaultListModel devVector = new DefaultListModel(); //se le pasa el texto del borde y el que dice "Description:" o similar. public DescriptionListPanel ( String borderTitle , String descLabelText , int rows ) { this(borderTitle,descLabelText,false,rows); } //�dem que DescriptionListPanel ( String borderTitle , String descLabelText ), pero se le pasa //un tercer par�metro booleano indicando si las descripciones soportan SUCCESS: y FAIL: public DescriptionListPanel ( String borderTitle , String descLabelText , boolean succFail , int rows ) { this(succFail,false,rows); this.setBorder(BorderFactory.createTitledBorder(borderTitle)); descLabel.setText(descLabelText); } public DescriptionListPanel ( String borderTitle , String descLabelText , String condLabelText , boolean succFail , int rows ) { this( borderTitle , descLabelText , condLabelText , succFail , false , rows ); } public DescriptionListPanel ( String borderTitle , String descLabelText , String condLabelText , boolean succFail , boolean propNamesEnabled , int rows ) { this(succFail,propNamesEnabled,rows); this.setBorder(BorderFactory.createTitledBorder(borderTitle)); descLabel.setText(descLabelText); condLabel.setText(condLabelText); } public DescriptionListPanel ( String borderTitle , String descLabelText , boolean succFail , boolean propNamesEnabled , int rows ) { this(succFail,propNamesEnabled,rows); this.setBorder(BorderFactory.createTitledBorder(borderTitle)); descLabel.setText(descLabelText); } public DescriptionListPanel ( ) { this(1); } public DescriptionListPanel ( int rows ) { this(false,false,rows); } public DescriptionListPanel ( final boolean succFail , final boolean propNamesEnabled , int rows ) { if ( rows <= 1 ) descTextField = new EnhancedJTextField(20); else { descTextField = new EnhancedJTextArea(rows,20); // Enable line-wrapping ((EnhancedJTextArea)descTextField).setLineWrap(true); ((EnhancedJTextArea)descTextField).setWrapStyleWord(true); } JScrollPane scroller = new JScrollPane(descTextField); scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); this.succFail = succFail; this.propNamesEnabled = propNamesEnabled; //listContent.setSize(100); theList = new EnhancedJList( listContent ); //listContent.setSize(2); theList.setCellRenderer ( new TwoStringCellRenderer() { public Component getListCellRendererComponent( JList list, Object value, // value to display int index, // cell index boolean isSelected, // is the cell selected boolean cellHasFocus) // the list and the cell have the focus { super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus); if ( propNamesEnabled && propList.size() > index && ((Boolean)propList.get(index)).booleanValue() ) { this.setText(this.getText() + " " + UIMessages.getInstance().getMessage("text.propname")); } return this; } } ); setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); //this.add(new JScrollPane(theList)); theList.setVisibleRowCount(4); final JScrollPane jsp = new JScrollPane(theList); jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); jsp.setPreferredSize(new Dimension(80,45)); /* final JPanel jp = new JPanel(); jp.setLayout(new BorderLayout()); jp.add(jsp,BorderLayout.CENTER); //jp.add(new JPanel(),BorderLayout.WEST); //jp.add(new JPanel(),BorderLayout.EAST); this.add(jp); */ this.add(new SpacingPanel(jsp)); //this.add(theList); this.setBorder(BorderFactory.createTitledBorder(UIMessages.getInstance().getMessage("label.des"))); this.add(Box.createVerticalStrut(MED_SKIP)); //JPanel p1and2 = new JPanel(); //p1and2.setLayout(new BorderLayout()); condLabel = new JLabel(UIMessages.getInstance().getMessage("label.condition")); descLabel = new JLabel(UIMessages.getInstance().getMessage("label.description")); JPanel p1 = new JPanel(); p1.setLayout (new BoxLayout(p1,BoxLayout.LINE_AXIS)); p1.add ( condLabel ); /* int difference = (int)(descLabel.getPreferredSize().getWidth()-condLabel.getPreferredSize().getWidth()); if ( difference > 0 ) p1.add ( Box.createHorizontalStrut(difference) ); */ p1.add(Box.createHorizontalStrut(MED_SKIP)); p1.add ( condTextField ); p1.add(Box.createVerticalStrut(MED_SKIP)); GUIUtils.limitVertically(p1); SpacingPanel sp1 = new SpacingPanel(p1,true,true,true,true); GUIUtils.limitVertically(sp1); //p1and2.add(sp1,BorderLayout.NORTH); add(sp1); JPanel p2 = new JPanel(); p2.setLayout(new BoxLayout(p2,BoxLayout.LINE_AXIS)); p2.add ( descLabel ); //p2.add ( descTextField ); //if ( difference < 0 ) p1.add ( Box.createHorizontalStrut(-difference) ); p2.add(Box.createHorizontalStrut(MED_SKIP)); if ( rows > 1 ) p2.add(scroller); else p2.add(descTextField); SpacingPanel sp2 = new SpacingPanel(p2,true,true,true,true); if ( rows < 2 ) { GUIUtils.limitVertically(p2); GUIUtils.limitVertically(sp2); GUIUtils.limitHorizontally(p2); GUIUtils.limitHorizontally(sp2); } add(sp2); /* if ( rows > 1 ) p1and2.add(new SpacingPanel(p2,true,true,true,true),BorderLayout.CENTER); else { SpacingPanel sp2 = new SpacingPanel(p2,true,true,true,true); p1and2.add(sp2,BorderLayout.SOUTH); int w = (int)p1and2.getPreferredSize().getWidth(); int h = (int)(sp1.getPreferredSize().getHeight()+sp2.getPreferredSize().getHeight()); //p1and2.setPreferredSize(new Dimension(w,h)); p1and2.setMaximumSize(p1and2.getPreferredSize()); } */ //add(p1and2); if ( succFail ) { JPanel p3 = new JPanel(); p3.add ( succCheckBox ); succCheckBox.setSelected(true); add(p3); } if ( propNamesEnabled ) { JPanel p4 = new JPanel(); p4.add ( propCheckBox ); propCheckBox.setSelected(false); add(p4); } JPanel buttonsPanel = new JPanel(); buttonsPanel.add(addButton); buttonsPanel.add(modButton); buttonsPanel.add(delButton); buttonsPanel.add(topButton); add(buttonsPanel); addButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent evt) { if ( descTextField.getText() == null || descTextField.getText().length() == 0 ) { SwingComponentHighlighter.temporalRedBackground(descTextField); return; } String[] nu; if ( !succFail ) nu = new String[] { // "re","doxon" condTextField.getText(), descTextField.getText() }; else nu = new String[] { condTextField.getText(), succCheckBox.isSelected() ? "SUCCESS:"+descTextField.getText() : "FAIL:"+descTextField.getText() }; listContent.addElement(nu); if ( propNamesEnabled ) propList.add(Boolean.valueOf(propCheckBox.isSelected())); jsp.repaint(); condTextField.setText(""); descTextField.setText(""); } } ); delButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent evt) { int[] indices = theList.getSelectedIndices(); for ( int i = indices.length-1 ; i >= 0 ; i-- ) { listContent.remove(indices[i]); if ( propNamesEnabled ) propList.remove(indices[i]); } //repaint(); //DescriptionListPanel.this.setVisible(false); //DescriptionListPanel.this.setVisible(true); jsp.repaint(); } } ); modButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent evt) { int ind = theList.getSelectedIndex(); String[] nu; if ( !succFail ) nu = new String[] { // "re","doxon" condTextField.getText(), descTextField.getText() }; else nu = new String[] { condTextField.getText(), succCheckBox.isSelected() ? "SUCCESS:"+descTextField.getText() : "FAIL:"+descTextField.getText() }; if ( ind < 0 ) return; //nada que cambiar. listContent.set(ind,nu); //repaint(); //theList.repaint(); //DescriptionListPanel.this.setVisible(false); //DescriptionListPanel.this.setVisible(true); jsp.repaint(); int selListIndex = theList.getSelectedIndex(); if ( selListIndex >= 0 && propNamesEnabled ) propList.set(selListIndex, Boolean.valueOf(propCheckBox.isSelected()) ); } } ); topButton.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent evt) { String[] it = (String[]) theList.getSelectedValue(); int ind = theList.getSelectedIndex(); boolean propVal = false; if ( propNamesEnabled ) propVal = ((Boolean)propList.get(ind)).booleanValue(); if ( ind > 0 ) { String[] prev = (String[]) theList.getModel().getElementAt(ind-1); listContent.set(ind-1,it); listContent.set(ind,prev); theList.setSelectedIndex(ind-1); if ( propNamesEnabled ) { boolean prevProp = ((Boolean)propList.get(ind-1)).booleanValue(); propList.set(ind-1 , Boolean.valueOf(propVal) ); propList.set(ind , Boolean.valueOf(prevProp) ); } //repaint(); //theList.repaint(); //DescriptionListPanel.this.setVisible(false); //DescriptionListPanel.this.setVisible(true); jsp.repaint(); } } } ); theList.addListSelectionListener( new ListSelectionListener() { public void valueChanged(ListSelectionEvent arg0) { String[] ar = (String[]) theList.getSelectedValue(); String desc; if ( ar == null ) return; if ( ar[1] == null ) desc = ""; else desc = ar[1]; if ( succFail ) { if ( ar[1].startsWith("SUCCESS:") ) { succCheckBox.setSelected(true); desc = ar[1].substring("SUCCESS:".length()); } else if ( ar[1].startsWith("FAIL:") ) { succCheckBox.setSelected(false); desc = ar[1].substring("FAIL:".length()); } } if ( propNamesEnabled ) { propCheckBox.setSelected( ((Boolean)propList.get(theList.getSelectedIndex())).booleanValue() ); } condTextField.setText(ar[0]); descTextField.setText(desc); } } ); /* propCheckBox.addChangeListener( //nope, only on press modify new ChangeListener() { public void stateChanged(ChangeEvent arg0) { int selListIndex = theList.getSelectedIndex(); if ( selListIndex >= 0 ) propList.set(selListIndex, propCheckBox.isSelected() ); } } ); */ updateButtonEnabledness(); theList.getModel().addListDataListener(new ListDataListener() { public void intervalAdded(ListDataEvent e) { updateButtonEnabledness(); } public void intervalRemoved(ListDataEvent e) { updateButtonEnabledness(); } public void contentsChanged(ListDataEvent e) { } } ); } /** * Disables all buttons but "add" if the list is empty, and enables them otherwise */ public void updateButtonEnabledness() { if ( theList.getModel().getSize() > 0 ) { delButton.setEnabled(true); modButton.setEnabled(true); topButton.setEnabled(true); } else { delButton.setEnabled(false); modButton.setEnabled(false); topButton.setEnabled(false); } } public Node getXML ( Document d ) { return getXML ( d , "DescriptionList" ); } public Node getXML ( Document d , String name ) { Element result = d.createElement(name); for ( int i = 0 ; i < listContent.size() ; i++ ) { String[] desc = (String[]) listContent.get(i); Element descNode = d.createElement("Description"); if ( desc[0] != null && desc[0].length() > 0 ) { Element condNode = d.createElement("Condition"); condNode.setAttribute("language","BeanShell"); condNode.appendChild(d.createTextNode(desc[0])); descNode.appendChild(condNode); } String theText = desc[1]; if ( propNamesEnabled ) { boolean isProper = ((Boolean)propList.get(i)).booleanValue(); if ( isProper ) { descNode.setAttribute("properName", "true"); } } Text textNode = d.createTextNode(theText); descNode.appendChild(textNode); result.appendChild(descNode); } return result; } //from DescriptionList node public void initFromXML ( org.w3c.dom.Node n ) { Element e = (Element) n; //have to init ListContent as a Model of String[] { cond , desc } NodeList nl = e.getElementsByTagName("Description"); for ( int i = 0 ; i < nl.getLength() ; i++ ) { Element descElt = (Element) nl.item(i); NodeList condNl = descElt.getElementsByTagName("Condition"); String conditionText = ""; String descriptionText = ""; if ( condNl.getLength() > 0 ) { Element condElt = (Element)condNl.item(0); NodeList condChildren = condElt.getChildNodes(); for ( int j = 0 ; j < condChildren.getLength() ; j++ ) { Node condChild = condChildren.item(j); if ( condChild instanceof Text ) conditionText = conditionText + condChild.getNodeValue(); } } NodeList descChildren = descElt.getChildNodes(); for ( int j = 0 ; j < descChildren.getLength() ; j++ ) { Node descChild = descChildren.item(j); if ( descChild instanceof Text ) descriptionText = descriptionText + descChild.getNodeValue(); } if ( propNamesEnabled ) { if ( descElt.hasAttribute("properName") && descElt.getAttribute("properName").equalsIgnoreCase("true") ) { propList.add(Boolean.TRUE); } else propList.add(Boolean.FALSE); } listContent.addElement(new String[]{conditionText.trim(),descriptionText.trim()}); //alternatively, ignore text nodes containing only whitespace and there will be no need to trim here. } } }