001 /* 002 * $Id: HighlighterPropertyEditor.java,v 1.1 2006/03/11 01:11:52 rbair Exp $ 003 * 004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021 package org.jdesktop.swingx.editors; 022 023 import java.awt.BorderLayout; 024 import java.awt.Color; 025 import java.awt.Container; 026 import java.awt.GridBagConstraints; 027 import java.awt.GridBagLayout; 028 import java.awt.Insets; 029 import java.awt.event.ActionEvent; 030 import java.beans.PropertyEditorSupport; 031 import java.beans.XMLDecoder; 032 import java.beans.XMLEncoder; 033 import java.io.ByteArrayInputStream; 034 import java.io.ByteArrayOutputStream; 035 import javax.swing.AbstractAction; 036 import javax.swing.AbstractListModel; 037 import javax.swing.BorderFactory; 038 import javax.swing.ButtonGroup; 039 import javax.swing.ImageIcon; 040 import javax.swing.JButton; 041 import javax.swing.JComboBox; 042 import javax.swing.JComponent; 043 import javax.swing.JDialog; 044 import javax.swing.JLabel; 045 import javax.swing.JRadioButton; 046 import javax.swing.JScrollPane; 047 import javax.swing.JSplitPane; 048 import javax.swing.JTextField; 049 import javax.swing.event.ListDataEvent; 050 import javax.swing.event.ListDataListener; 051 import javax.swing.event.ListSelectionEvent; 052 import javax.swing.event.ListSelectionListener; 053 //import org.jdesktop.jdnc.incubator.rlopes.colorcombo.ColorComboBox; 054 import org.jdesktop.swingx.JXList; 055 import org.jdesktop.swingx.JXPanel; 056 import org.jdesktop.swingx.JXTitledPanel; 057 import org.jdesktop.swingx.decorator.AlternateRowHighlighter; 058 import org.jdesktop.swingx.decorator.Highlighter; 059 import org.jdesktop.swingx.decorator.HighlighterPipeline; 060 import org.jdesktop.swingx.decorator.PatternHighlighter; 061 //import org.jdesktop.swingx.expression.ExpressionHighlighter; 062 //import org.netbeans.modules.form.NamedPropertyEditor; 063 //import org.openide.windows.WindowManager; 064 065 066 /** 067 * 068 * @author rbair 069 */ 070 public class HighlighterPropertyEditor extends PropertyEditorSupport { //implements NamedPropertyEditor { 071 private HighlighterPipeline pipeline = new HighlighterPipeline(); 072 private Editor editor; 073 074 /** Creates a new instance of HighlighterPropertyEditor */ 075 public HighlighterPropertyEditor() { 076 editor = new Editor(); 077 editor.highlightersList.setModel(new AbstractListModel() { 078 public Object getElementAt(int index) { 079 return pipeline.getHighlighters()[index]; 080 } 081 082 public int getSize() { 083 return pipeline.getHighlighters().length; 084 } 085 }); 086 editor.highlightersList.getModel().addListDataListener(new ListDataListener() { 087 public void contentsChanged(ListDataEvent e) { 088 HighlighterPropertyEditor.this.firePropertyChange(); 089 } 090 091 public void intervalAdded(ListDataEvent e) { 092 HighlighterPropertyEditor.this.firePropertyChange(); 093 } 094 095 public void intervalRemoved(ListDataEvent e) { 096 HighlighterPropertyEditor.this.firePropertyChange(); 097 } 098 }); 099 } 100 101 public boolean supportsCustomEditor() { 102 return true; 103 } 104 105 public String getJavaInitializationString() { 106 StringBuffer buffer = new StringBuffer(); 107 ByteArrayOutputStream baos = new ByteArrayOutputStream(300); 108 XMLEncoder e = new XMLEncoder(baos); 109 e.writeObject(pipeline.getHighlighters()); 110 e.close(); 111 Highlighter[] blar = (Highlighter[])new XMLDecoder(new ByteArrayInputStream(baos.toString().getBytes())).readObject(); 112 buffer.append("new org.jdesktop.swingx.decorator.HighlighterPipeline(\n"); 113 buffer.append("\t(org.jdesktop.swingx.decorator.Highlighter[])new java.beans.XMLDecoder(new java.io.ByteArrayInputStream(\""); 114 buffer.append(escapeString(baos.toString())); 115 buffer.append("\".getBytes())).readObject())"); 116 return buffer.toString(); 117 } 118 119 private String escapeString(String s) { 120 return s.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"").replaceAll("\n", ""); 121 } 122 123 public String getDisplayName() { 124 return "Highlighter Editor"; 125 } 126 127 public void setAsText(String text) throws IllegalArgumentException { 128 } 129 130 public void setValue(Object value) { 131 //if the value is a HighlighterPipeline, hold on to this. The 132 //editor is going to need it 133 if (value instanceof HighlighterPipeline) { 134 pipeline = new HighlighterPipeline(((HighlighterPipeline)value).getHighlighters()); 135 } else { 136 pipeline = new HighlighterPipeline(); 137 } 138 super.setValue(value); 139 } 140 141 public Object getValue() { 142 return pipeline; 143 } 144 145 public String getAsText() { 146 return pipeline.toString(); 147 } 148 149 public java.awt.Component getCustomEditor() { 150 return editor; 151 } 152 153 private class Editor extends JXPanel { 154 private JXList highlightersList; 155 private AlternateRowDetailPanel alternateRowDetailPanel = new AlternateRowDetailPanel(); 156 private ExpressionDetailPanel expressionDetailPanel = new ExpressionDetailPanel(); 157 private PatternDetailPanel patternDetailPanel = new PatternDetailPanel(); 158 159 public Editor() { 160 setLayout(new BorderLayout()); 161 162 JSplitPane mainsp = new JSplitPane(); 163 mainsp.setBorder(BorderFactory.createEmptyBorder()); 164 JXTitledPanel tp = new JXTitledPanel("Highlighters"); 165 JXPanel buttonPanel = new JXPanel(); 166 buttonPanel.setOpaque(false); 167 JButton btn = new JButton(new AddAction()); 168 btn.setOpaque(false); 169 btn.setBorder(BorderFactory.createEmptyBorder()); 170 buttonPanel.add(btn); 171 btn = new JButton(new DeleteAction()); 172 btn.setOpaque(false); 173 btn.setBorder(BorderFactory.createEmptyBorder()); 174 buttonPanel.add(btn); 175 tp.addRightDecoration(buttonPanel); 176 highlightersList = new JXList(); 177 JScrollPane sp = new JScrollPane(highlightersList); 178 sp.setBorder(BorderFactory.createEmptyBorder()); 179 tp.setContentContainer(sp); 180 mainsp.setLeftComponent(tp); 181 final JXTitledPanel details = new JXTitledPanel("Highlighter Details"); 182 mainsp.setRightComponent(details); 183 add(mainsp); 184 185 highlightersList.addListSelectionListener(new ListSelectionListener() { 186 public void valueChanged(ListSelectionEvent e) { 187 if (!e.getValueIsAdjusting()) { 188 //get the first selected value... 189 Highlighter h = (Highlighter)highlightersList.getSelectedValue(); 190 //load the proper detail panel 191 Container c = details.getContentContainer(); 192 HighlighterDetailPanel content = null; 193 if (c instanceof HighlighterDetailPanel) { 194 content = (HighlighterDetailPanel)c; 195 content.save(); 196 } 197 if (h instanceof AlternateRowHighlighter) { 198 alternateRowDetailPanel.init((AlternateRowHighlighter)h); 199 content = alternateRowDetailPanel; 200 // } else if (h instanceof ExpressionHighlighter) { 201 // expressionDetailPanel.init((ExpressionHighlighter)h); 202 // content = expressionDetailPanel; 203 } else if (h instanceof PatternHighlighter) { 204 patternDetailPanel.init((PatternHighlighter)h); 205 content = patternDetailPanel; 206 } 207 details.setContentContainer(content == null ? new JXPanel() : content); 208 details.revalidate(); 209 details.repaint(); 210 } 211 } 212 }); 213 } 214 215 private class DeleteAction extends AbstractAction { 216 public DeleteAction() { 217 super(); 218 super.putValue(AddAction.SMALL_ICON, new ImageIcon(HighlighterPropertyEditor.class.getResource("deleteHighlighter.gif"))); 219 } 220 public void actionPerformed(ActionEvent ae) { 221 //get the selected items 222 Object[] values = highlightersList.getSelectedValues(); 223 for (int i=0; i<values.length; i++) { 224 pipeline.removeHighlighter((Highlighter)values[i]); 225 } 226 ListDataListener[] listeners = ((AbstractListModel)highlightersList.getModel()).getListDataListeners(); 227 ListDataEvent evt = new ListDataEvent(highlightersList, ListDataEvent.CONTENTS_CHANGED, 0, pipeline.getHighlighters().length-1); 228 for (int i=0; i<listeners.length; i++) { 229 listeners[i].contentsChanged(evt); 230 } 231 } 232 } 233 234 private class AddAction extends AbstractAction { 235 public AddAction() { 236 super(); 237 super.putValue(AddAction.SMALL_ICON, new ImageIcon(HighlighterPropertyEditor.class.getResource("newHighlighter.gif"))); 238 } 239 public void actionPerformed(ActionEvent ae) { 240 //show a true popup 241 final JDialog dlg = new JDialog(/*WindowManager.getDefault().getMainWindow()*/(JDialog)null, true); 242 JXPanel cp = new JXPanel(new GridBagLayout()); 243 final JRadioButton newRB = new JRadioButton("New Highlighter"); 244 final JRadioButton formRB = new JRadioButton("From Form"); 245 ButtonGroup bg = new ButtonGroup(); 246 bg.add(newRB); 247 bg.add(formRB); 248 newRB.setSelected(true); 249 cp.add(newRB, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 5, 11), 0, 0)); 250 JLabel label = new JLabel("Type: "); 251 final JComboBox typeCB = new JComboBox(new String[]{"Alternate Row", "Expression", "Pattern"}); 252 label.setLabelFor(typeCB); 253 cp.add(label, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 24, 7, 3), 0, 0)); 254 cp.add(typeCB, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 7, 11), 0, 0)); 255 label = new JLabel("Name: "); 256 final JTextField nameTF = new JTextField("<auto-generate>"); 257 label.setLabelFor(nameTF); 258 cp.add(label, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 24, 7, 3), 0, 0)); 259 cp.add(nameTF, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 7, 11), 0, 0)); 260 cp.add(formRB, new GridBagConstraints(0, 3, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 12, 5, 11), 0, 0)); 261 label = new JLabel("Choose Highlighter: "); 262 final JComboBox highlighterCB = new JComboBox(new Object[0]); 263 cp.add(label, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 24, 7, 3), 0, 0)); 264 cp.add(highlighterCB, new GridBagConstraints(1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 17, 11), 0, 0)); 265 JButton okButton = new JButton(new AbstractAction("OK") { 266 public void actionPerformed(ActionEvent ae) { 267 if (newRB.isSelected()) { 268 String type = (String)typeCB.getSelectedItem(); 269 Highlighter h = null; 270 if (type == null || type == "Alternate Row") { 271 h = new AlternateRowHighlighter(); 272 // } else if (type == "Expression") { 273 // h = new ExpressionHighlighter(); 274 } else if (type == "Pattern") { 275 h = new PatternHighlighter(); 276 } 277 //TODO deal with the name 278 pipeline.addHighlighter(h); 279 ListDataListener[] listeners = ((AbstractListModel)highlightersList.getModel()).getListDataListeners(); 280 int size = pipeline.getHighlighters().length; 281 ListDataEvent evt = new ListDataEvent(highlightersList, ListDataEvent.CONTENTS_CHANGED, size -1, size -1); 282 for (int i=0; i<listeners.length; i++) { 283 listeners[i].contentsChanged(evt); 284 } 285 } 286 dlg.setVisible(false); 287 } 288 }); 289 JXPanel buttonPanel = new JXPanel(new GridBagLayout()); 290 buttonPanel.add(okButton, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.SOUTHEAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); 291 cp.add(buttonPanel, new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 12, 11, 11), 0, 0)); 292 dlg.setContentPane(cp); 293 dlg.pack(); 294 //TODO need to to center... 295 dlg.setVisible(true); 296 } 297 } 298 299 private JComboBox createColorComboBox() { 300 // try { 301 // return new ColorComboBox(); 302 // } catch (Exception e) { 303 return new JComboBox(new Color[]{Color.BLACK, Color.BLUE, 304 Color.CYAN, Color.DARK_GRAY, Color.GRAY, 305 Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, 306 Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, 307 Color.YELLOW}); 308 // } 309 } 310 311 private class HighlighterDetailPanel extends JXPanel { 312 private int rowCounter = 0; 313 protected JComboBox backgroundCB; 314 protected JComboBox selectedBackgroundCB; 315 protected JComboBox foregroundCB; 316 protected JComboBox selectedForegroundCB; 317 private Highlighter h; 318 319 public HighlighterDetailPanel() { 320 setLayout(new GridBagLayout()); 321 backgroundCB = createColorComboBox(); 322 add("Background: ", backgroundCB, false); 323 selectedBackgroundCB = createColorComboBox(); 324 add("Selected Background: ", selectedBackgroundCB, false); 325 foregroundCB = createColorComboBox(); 326 add("Foreground: ", foregroundCB, false); 327 selectedForegroundCB = createColorComboBox(); 328 add("Selected Foreground: ", selectedForegroundCB, false); 329 } 330 331 protected void add(String labelText, JComponent component, boolean isLast) { 332 JLabel label = new JLabel(labelText); 333 label.setLabelFor(component); 334 Insets insets = rowCounter == 0 ? new Insets(12, 12, 5, 5) : new Insets(0, 12, 5, 5); 335 add(label, new GridBagConstraints(0, rowCounter, 1, 1, 0.0, 0.0, isLast ? GridBagConstraints.NORTHWEST : GridBagConstraints.WEST, GridBagConstraints.NONE, insets, 0, 0)); 336 insets = rowCounter == 0 ? new Insets(12, 0, 5, 11) : new Insets(0, 0, isLast ? 11 : 5, 11); 337 add(component, new GridBagConstraints(1, rowCounter, 1, 1, 1.0, isLast ? 1.0 : 0.0, isLast ? GridBagConstraints.NORTHWEST : GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, insets, 0, 0)); 338 rowCounter++; 339 } 340 341 protected void init(Highlighter h) { 342 this.h = h; 343 backgroundCB.setSelectedItem(h.getBackground()); 344 selectedBackgroundCB.setSelectedItem(h.getSelectedBackground()); 345 foregroundCB.setSelectedItem(h.getForeground()); 346 selectedForegroundCB.setSelectedItem(h.getSelectedForeground()); 347 } 348 349 public void save() { 350 this.h.setBackground((Color)backgroundCB.getSelectedItem()); 351 this.h.setSelectedBackground((Color)selectedBackgroundCB.getSelectedItem()); 352 this.h.setForeground((Color)foregroundCB.getSelectedItem()); 353 this.h.setSelectedForeground((Color)selectedForegroundCB.getSelectedItem()); 354 ListDataListener[] listeners = ((AbstractListModel)highlightersList.getModel()).getListDataListeners(); 355 int size = pipeline.getHighlighters().length; 356 ListDataEvent evt = new ListDataEvent(highlightersList, ListDataEvent.CONTENTS_CHANGED, size -1, size-1); 357 for (int i=0; i<listeners.length; i++) { 358 listeners[i].contentsChanged(evt); 359 } 360 } 361 } 362 363 private class AlternateRowDetailPanel extends HighlighterDetailPanel { 364 private JComboBox evenRowCB; 365 private JComboBox oddRowCB; 366 private AlternateRowHighlighter h; 367 368 public AlternateRowDetailPanel() { 369 evenRowCB = createColorComboBox(); 370 add("Even Row Background: ", evenRowCB, false); 371 oddRowCB = createColorComboBox(); 372 add("Odd Row Background: ", oddRowCB, true); 373 } 374 375 public void init(AlternateRowHighlighter h) { 376 super.init(h); 377 this.h = h; 378 evenRowCB.setSelectedItem(h.getEvenRowBackground()); 379 oddRowCB.setSelectedItem(h.getOddRowBackground()); 380 } 381 382 public void save() { 383 this.h.setEvenRowBackground((Color)evenRowCB.getSelectedItem()); 384 this.h.setOddRowBackground((Color)oddRowCB.getSelectedItem()); 385 super.save(); 386 } 387 } 388 389 private class ExpressionDetailPanel extends HighlighterDetailPanel { 390 private JTextField bgExpressionTF; 391 private JTextField fgExpressionTF; 392 // private ExpressionHighlighter h; 393 394 public ExpressionDetailPanel() { 395 bgExpressionTF = new JTextField(); 396 add("Background Expression: ", bgExpressionTF, false); 397 fgExpressionTF = new JTextField(); 398 add("Foreground Expression: ", fgExpressionTF, true); 399 } 400 401 public void init(/*Expression*/Highlighter h) { 402 super.init(h); 403 // this.h = h; 404 // bgExpressionTF.setText(h.getBackgroundExpression()); 405 // fgExpressionTF.setText(h.getForegroundExpression()); 406 } 407 408 public void save() { 409 // this.h.setBackgroundExpression(bgExpressionTF.getText()); 410 // this.h.setForegroundExpression(fgExpressionTF.getText()); 411 super.save(); 412 } 413 } 414 415 private class PatternDetailPanel extends HighlighterDetailPanel { 416 private JTextField patternTF; 417 // private JCheckBox matchFlagsCB; 418 private PatternHighlighter h; 419 420 public PatternDetailPanel() { 421 patternTF = new JTextField(); 422 add("Pattern: ", patternTF, true); 423 // matchFlagsCB = new JCheckBox("Match Flags?"); 424 // add("", matchFlagsCB, true); 425 } 426 427 public void init(PatternHighlighter h) { 428 super.init(h); 429 this.h = h; 430 patternTF.setText(h.getPattern().pattern()); 431 // matchFlagsCB.setSelected(...); 432 } 433 434 public void save() { 435 this.h.setPattern(patternTF.getText(), 0); //TODO 436 super.save(); 437 } 438 } 439 440 } 441 }