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 }