Source code: jplot/LabelPanel.java
1 /*
2 * JPLOT -- Java Plotting Interface for any programme or
3 * as an independent GUI
4 *
5 * Copyright (C) 1999 Jan van der Lee
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 * 02111-1307, USA.
21 *
22 * Send bugs, suggestions or queries to <jplot@cig.ensmp.fr>
23 * The latest releases are found at
24 * http://www.cig.ensmp.fr/~vanderlee/jplot.html
25 *
26 * Initally developed for use by the Centre d'Informatique Geologique
27 * Ecole des Mines de Paris, Fontainebleau, France.
28 */
29
30 package jplot;
31
32 import java.awt.*;
33 import java.util.*;
34 import javax.swing.*;
35 import java.awt.event.*;
36 import javax.swing.border.*;
37
38 /**
39 * Creates a panel with options to set labels (X-, Y-axis labels, a title,
40 * random labels or text in general). Note that the number of labels and
41 * names of the pre-defined labels may change as a function of the graph
42 * type: for ordinary 2D graphs, we typically pre-define a title, y-label
43 * and x-label but for a piper diagram we have 6 pre-defined labels...
44 *
45 * Calling the <code>show</code> method pops up a frame (dialog) which
46 * includes the panel.
47 */
48 public class LabelPanel extends GriddedPanel {
49
50 private int N;
51 private JTextField[] textField;
52
53 // this list contains the temporary labels with properties,
54 // replaces the list in the Data-class only if the user validates
55 // the current choice ---adds a kind of poor-man's undo capacity.
56 private GraphLabel[] gLabel;
57 // all other 'random' labels go in this vector and list
58 private Vector otherLabels = new Vector();
59 private JList labelList;
60
61 private JDialog dialog;
62
63 private LabelProperties labelProperties;
64 private int actualItemIndex;
65 private int[] actualItemIndices;
66
67 // buttons and tooltips which allow to set the label text properties:
68 private JButton[] edit;
69 private String[] toolTip;
70 private JLabel[] label;
71
72 // same thing for the otherLabels:
73 private JButton olAdd, olEdit, olDelete, xTicFont, yTicFont;
74 private JRadioButton xTicLabels, yTicLabels;
75 private FontPanel ticFontPanel;
76
77 //panels on which we pin the textfields and buttons:
78 private JPanel[] labelPanel;
79 private JPanel oLabelPanel;
80
81 private GraphPars gp;
82 private JRadioButton rb_reset; // resets all label positions
83
84 private final Dimension myDimension = new Dimension(100,50);
85 private final Insets insets = new Insets(0,0,0,0);
86
87 private JPlot jplot;
88
89 /**
90 * Principal constructor. Builds a panel from which the user can
91 * set text labels which will be drawn inside the graph.
92 * @param gp instance of the object containing all graphical parameters
93 */
94 public LabelPanel (JPlot jp, GraphPars _gp) {
95 int k=0;
96 gp = _gp;
97 jplot = jp;
98 dialog = null;
99 setBorder(new EmptyBorder(new Insets(5,5,5,5)));
100
101 rb_reset = new JRadioButton("reset all label positions");
102
103 // spacing between labels and fields:
104 EmptyBorder border = new EmptyBorder(new Insets(0,0,0,10));
105 ImageIcon editIcon = jplot.getImageIcon("Edit16.gif");
106
107 N = (gp.getGraphType() == gp.GRAPHTYPE_PIPER)? 6 : 3;
108 textField = new JTextField [N];
109 gLabel = new GraphLabel [N];
110 edit = new JButton [N];
111 toolTip = new String [N];
112 label = new JLabel [N];
113 labelPanel = new JPanel [N];
114
115 // make the labels in case it is a piper graph:
116 if (gp.getGraphType() == gp.GRAPHTYPE_PIPER) {
117 gLabel[0] = new GraphLabel(GraphLabel.PIPER_X1);
118 toolTip[0] = new String("Left X-label");
119 label[0] = new JLabel("X1-label:");
120 gLabel[1] = new GraphLabel(GraphLabel.PIPER_X2);
121 toolTip[1] = new String("Right X-label");
122 label[1] = new JLabel("X2-label:");
123 gLabel[2] = new GraphLabel(GraphLabel.PIPER_Y1);
124 toolTip[2] = new String("Lower left Y-label");
125 label[2] = new JLabel("Y1-label:");
126 gLabel[3] = new GraphLabel(GraphLabel.PIPER_Y2);
127 toolTip[3] = new String("Lower right Y-label");
128 label[3] = new JLabel("Y2-label:");
129 gLabel[4] = new GraphLabel(GraphLabel.PIPER_Y3);
130 toolTip[4] = new String("Upper left Y-label");
131 label[4] = new JLabel("Y3-label:");
132 gLabel[5] = new GraphLabel(GraphLabel.PIPER_Y4);
133 toolTip[5] = new String("Upper right Y-label");
134 label[5] = new JLabel("Y4-label:");
135 }
136
137 // make the labels in case it is a 2D graph:
138 else {
139 gLabel[0] = new GraphLabel(GraphLabel.TITLE);
140 gLabel[0].setFont(new Font("Helvetica",Font.BOLD,12));
141 toolTip[0] = new String("Edit the title properties");
142 label[0] = new JLabel("Graph title");
143 gLabel[1] = new GraphLabel(GraphLabel.XLABEL);
144 toolTip[1] = new String("Edit the X-label properties");
145 label[1] = new JLabel("X-axis label");
146 gLabel[2] = new GraphLabel(GraphLabel.YLABEL);
147 toolTip[2] = new String("Edit the Y-label properties");
148 label[2] = new JLabel("Y-axis label");
149 // set some default label properties:
150 gLabel[2].setRotation(-Math.PI/2.0);
151 }
152
153 // build the label-properties pop-up dialog:
154 labelProperties = new LabelProperties(jplot);
155
156 for (int i=0; i<N; i++,k++) {
157 final int j=i;
158 textField[i] = new JTextField();
159 edit[i] = new JButton(editIcon);
160 edit[i].setMargin(insets);
161 edit[i].setToolTipText(toolTip[i]);
162 edit[i].addActionListener(new ActionListener() {
163 public void actionPerformed(ActionEvent e) {
164 gLabel[j].setText(textField[j].getText());
165 labelProperties.refresh(gLabel[j]);
166 if (labelProperties.show(jplot.frame,100,100)) {
167 gLabel[j] = labelProperties.getGraphLabel();
168 update();
169 }
170 }
171 });
172 labelPanel[i] = new JPanel(new BorderLayout());
173 labelPanel[i].add(textField[i],BorderLayout.CENTER);
174 labelPanel[i].add(edit[i],BorderLayout.EAST);
175
176 label[i].setBorder(border);
177 addComponent(label[i],i,1);
178 addFilledComponent(labelPanel[i],i,2,3,1,GridBagConstraints.HORIZONTAL);
179 }
180
181 // list of 'other' (random) labels
182 actualItemIndex = -1;
183 otherLabels = new Vector();
184 labelList = new JList(new DefaultListModel());
185 labelList.addMouseListener(new MouseAdapter() {
186 public void mouseClicked(MouseEvent e) {
187 actualItemIndex = labelList.getSelectedIndex();
188 actualItemIndices = labelList.getSelectedIndices();
189 if (e.getClickCount() == 2) {
190 editOtherLabel();
191 }
192 }
193 });
194 JScrollPane sp_otherLabels = new JScrollPane(labelList);
195 sp_otherLabels.setPreferredSize(myDimension);
196 oLabelPanel = new JPanel(new BorderLayout());
197 oLabelPanel.add(sp_otherLabels,BorderLayout.CENTER);
198
199 // make a panel for the buttons:
200 JPanel bPanel = new JPanel(new GridLayout(3,1));
201
202 // add button for the 'other' labels
203 olAdd = new JButton(jplot.getImageIcon("insert.png"));
204 olAdd.setMargin(insets);
205 olAdd.setToolTipText("Add a random label");
206 olAdd.addActionListener(new ActionListener() {
207 public void actionPerformed(ActionEvent e) {
208 labelProperties.refresh(new GraphLabel(GraphLabel.OTHER));
209 if (labelProperties.show(jplot.frame,100,100)) {
210 otherLabels.add(labelProperties.getGraphLabel());
211 update();
212 }
213 }
214 });
215 bPanel.add(olAdd);
216
217 // edit button for the 'other' labels
218 olEdit = new JButton(editIcon);
219 olEdit.setMargin(insets);
220 olEdit.setToolTipText("Edit the selected label properties");
221 olEdit.addActionListener(new ActionListener() {
222 public void actionPerformed(ActionEvent e) {
223 editOtherLabel();
224 }
225 });
226 bPanel.add(olEdit);
227
228 // delete button for the 'other' labels
229 olDelete = new JButton(jplot.getImageIcon("Remove16.gif"));
230 olDelete.setMargin(insets);
231 olDelete.setToolTipText("Remove the selected label(s)");
232 olDelete.addActionListener(new ActionListener() {
233 public void actionPerformed(ActionEvent e) {
234 if (actualItemIndices != null) {
235 for (int i=actualItemIndices.length-1; i>=0; i--) {
236 otherLabels.removeElementAt(actualItemIndices[i]);
237 }
238 update();
239 }
240 }
241 });
242 bPanel.add(olDelete);
243 oLabelPanel.add(bPanel,BorderLayout.EAST);
244
245 JLabel l = new JLabel("Random labels");
246 l.setBorder(border);
247 addComponent(l,k,1);
248 addFilledComponent(oLabelPanel,k,2,3,3,GridBagConstraints.HORIZONTAL);
249 k += 4;
250 addComponent(rb_reset,k,2,2,1);
251
252 k++;
253 l = new JLabel("X tic-labels");
254 l.setBorder(border);
255 addComponent(l,k,1);
256 xTicLabels = new JRadioButton("show");
257 xTicLabels.addActionListener(new ActionListener() {
258 public void actionPerformed(ActionEvent e) {
259 gp.setDrawTicLabels(gp.X_AXIS,xTicLabels.isSelected());
260 }
261 });
262 xTicLabels.setSelected(true);
263 addComponent(xTicLabels,k,2);
264
265 xTicFont = new JButton("Change font...",editIcon);
266 //xTicFont.setMargin(insets);
267 //xTicFont.setPreferredSize(new Dimension(26,80));
268 xTicFont.addActionListener(new ActionListener() {
269 public void actionPerformed(ActionEvent e) {
270 if (ticFontPanel == null) {
271 ticFontPanel = new FontPanel(jplot,gp.getTicFont(gp.X_AXIS),
272 gp.getTicColor(gp.X_AXIS));
273 }
274 else ticFontPanel.refresh(gp.getTicFont(gp.X_AXIS),
275 gp.getTicColor(gp.X_AXIS));
276 ticFontPanel.show(jplot.frame,150,150);
277 gp.setTicFont(gp.X_AXIS,
278 ticFontPanel.getSelectedFont());
279 gp.setTicColor(gp.X_AXIS,
280 ticFontPanel.getSelectedColor());
281 }
282 });
283 addComponent(xTicFont,k,3);
284
285 k++;
286 l = new JLabel("Y tic-labels");
287 l.setBorder(border);
288 addComponent(l,k,1);
289 yTicLabels = new JRadioButton("show");
290 yTicLabels.addActionListener(new ActionListener() {
291 public void actionPerformed(ActionEvent e) {
292 gp.setDrawTicLabels(gp.Y_AXIS,yTicLabels.isSelected());
293 }
294 });
295 yTicLabels.setSelected(true);
296 addComponent(yTicLabels,k,2);
297
298 yTicFont = new JButton("Change font...",editIcon);
299 //yTicFont.setMargin(insets);
300 //yTicFont.setPreferredSize(new Dimension(26,80));
301 yTicFont.addActionListener(new ActionListener() {
302 public void actionPerformed(ActionEvent e) {
303 if (ticFontPanel == null) {
304 ticFontPanel = new FontPanel(jplot,gp.getTicFont(gp.Y_AXIS),
305 gp.getTicColor(gp.Y_AXIS));
306 }
307 else ticFontPanel.refresh(gp.getTicFont(gp.Y_AXIS),
308 gp.getTicColor(gp.Y_AXIS));
309 ticFontPanel.show(jplot.frame,150,150);
310 gp.setTicFont(gp.Y_AXIS,
311 ticFontPanel.getSelectedFont());
312 gp.setTicColor(gp.Y_AXIS,
313 ticFontPanel.getSelectedColor());
314 }
315 });
316 addComponent(yTicFont,k,3);
317 }
318
319 /*
320 * Open an editor for editing one of the random labels.
321 * Searches the label in the list of labels.
322 */
323 private void editOtherLabel() {
324 if (actualItemIndex > -1 && actualItemIndex < otherLabels.size()) {
325 labelProperties.refresh((GraphLabel)otherLabels.get(actualItemIndex));
326 if (labelProperties.show(jplot.frame,100,100)) {
327 otherLabels.set(actualItemIndex,labelProperties.getGraphLabel());
328 }
329 }
330 }
331
332 /*
333 * Update the label fields with the current labels.
334 */
335 private void update() {
336 for (int i=0; i<N; i++) {
337 textField[i].setText(gLabel[i].getText());
338 textField[i].setFont(gLabel[i].getFont());
339 textField[i].setForeground(gLabel[i].getColor());
340 if (gLabel[i].getFont().getSize() > 14) {
341 textField[i].setFont(gLabel[i].getFont().deriveFont(14f));
342 }
343 }
344 labelList.setListData(otherLabels);
345 }
346
347 /**
348 * Updates the panel with graph parameters.
349 */
350 public void refresh() {
351 otherLabels.clear();
352 for (Enumeration el=gp.getLabels().elements(); el.hasMoreElements();) {
353 GraphLabel gl = (GraphLabel) el.nextElement();
354 if (gp.getGraphType() == gp.GRAPHTYPE_PIPER) {
355 if (gl.getID() == GraphLabel.PIPER_X1) {
356 gLabel[0] = new GraphLabel(gl);
357 }
358 else if (gl.getID() == GraphLabel.PIPER_X2) {
359 gLabel[1] = new GraphLabel(gl);
360 }
361 else if (gl.getID() == GraphLabel.PIPER_Y1) {
362 gLabel[2] = new GraphLabel(gl);
363 }
364 else if (gl.getID() == GraphLabel.PIPER_Y2) {
365 gLabel[3] = new GraphLabel(gl);
366 }
367 else if (gl.getID() == GraphLabel.PIPER_Y3) {
368 gLabel[4] = new GraphLabel(gl);
369 }
370 else if (gl.getID() == GraphLabel.PIPER_Y4) {
371 gLabel[5] = new GraphLabel(gl);
372 }
373 else otherLabels.add(new GraphLabel(gl));
374 }
375 else {
376 if (gl.getID() == GraphLabel.TITLE) {
377 gLabel[0] = new GraphLabel(gl);
378 }
379 else if (gl.getID() == GraphLabel.XLABEL) {
380 gLabel[1] = new GraphLabel(gl);
381 }
382 else if (gl.getID() == GraphLabel.YLABEL) {
383 gLabel[2] = new GraphLabel(gl);
384 }
385 else otherLabels.add(new GraphLabel(gl));
386 }
387 }
388 update();
389 rb_reset.setSelected(false);
390 }
391
392 /**
393 * Return the current values. Note that the user may type the
394 * label text directly in the fields for xLabel, yLabel and title.
395 * If so, this text is copied in the label object.
396 */
397 public void setValues() {
398 gp.getLabels().clear();
399 for (int i=0; i<N; i++) {
400 gLabel[i].setText(textField[i].getText());
401 if (!gLabel[i].getText().equals("")) gp.addLabel(gLabel[i]);
402 }
403 for (Enumeration e=otherLabels.elements(); e.hasMoreElements();) {
404 GraphLabel gl = (GraphLabel)e.nextElement();
405 gp.addLabel(gl);
406 }
407 if (rb_reset.isSelected()) {
408 gp.resetLabels();
409 rb_reset.setSelected(false);
410 }
411 }
412
413 /**
414 * Return a modal JDialog.
415 */
416 public void show(Frame parent, int x, int y) {
417 if (dialog == null) {
418 dialog = new JDialog(parent,"Labels",false);
419 dialog.addWindowListener(new WindowAdapter() {
420 public void windowClosing(WindowEvent e) {
421 dialog.dispose();
422 }
423 });
424
425 JPanel p = new JPanel(new FlowLayout());
426 p.setBorder(BorderFactory.createEtchedBorder());
427 JButton b = new JButton("Apply");
428 b.addActionListener(new ActionListener() {
429 public void actionPerformed(ActionEvent e) {
430 setValues();
431 gp.setDataChanged(true);
432 jplot.updateGraphIfShowing();
433 }
434 });
435 p.add(b);
436 b = new JButton("Dismiss");
437 b.addActionListener(new ActionListener() {
438 public void actionPerformed(ActionEvent e) {
439 dialog.dispose();
440 }
441 });
442 p.add(b);
443 dialog.getContentPane().add(this,BorderLayout.CENTER);
444 dialog.getContentPane().add(p,BorderLayout.SOUTH);
445 dialog.setLocation(x,y);
446 dialog.pack();
447 }
448 refresh();
449 dialog.show(); // blocks until user brings dialog down.
450 }
451 }