1 package gov.nasa.pds.ltdt.gui;
2
3 import gov.nasa.pds.ltdt.gui.configuration.LTDTKeys;
4 import gov.nasa.pds.ltdt.gui.util.Utility;
5
6 import java.awt.Color;
7 import java.awt.Component;
8 import java.awt.Dimension;
9 import java.awt.Font;
10 import java.awt.FontMetrics;
11 import java.awt.Graphics;
12 import java.awt.Insets;
13 import java.awt.event.KeyEvent;
14 import java.awt.event.KeyListener;
15 import java.util.HashMap;
16 import java.util.Properties;
17
18 import javax.swing.BorderFactory;
19 import javax.swing.Box;
20 import javax.swing.BoxLayout;
21 import javax.swing.JLabel;
22 import javax.swing.JPanel;
23 import javax.swing.JScrollPane;
24 import javax.swing.JTextArea;
25 import javax.swing.SwingConstants;
26 import javax.swing.border.AbstractBorder;
27 import javax.swing.event.CaretEvent;
28 import javax.swing.event.CaretListener;
29 import javax.swing.event.DocumentEvent;
30 import javax.swing.event.DocumentListener;
31 import javax.swing.text.BadLocationException;
32
33
34 /***
35 * Create a panel to handle template editing
36 * @author jwang
37 *
38 */
39 public class TemplateEditorPane extends JPanel {
40
41 public JTextArea jtaLineNm, jta;
42 public JScrollPane jsp;
43
44 public JLabel jlbCaretPosition;
45
46 private Properties props;
47
48 public TemplateEditorPane(Properties props, MainWindow window) {
49
50 this.props = props;
51
52
53 this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
54 this.setBorder(BorderFactory.createTitledBorder("Template Editor"));
55 this.setOpaque(true);
56
57
58
59
60 jta = new JTextArea();
61
62 jta.setBorder(new LineNumberedBorder(LineNumberedBorder.LEFT_SIDE, LineNumberedBorder.RIGHT_JUSTIFY));
63
64 jta.setEditable(true);
65 jta.setLineWrap(false);
66 jta.setWrapStyleWord(true);
67 jta.setDragEnabled(true);
68 jta.setFont(new Font("monospaced",Font.PLAIN, 12));
69 jta.setFocusable(true);
70 jta.setCaretColor(Color.MAGENTA);
71
72
73 this.jta.getDocument().addDocumentListener( new DocumentListener() {
74
75 public void changedUpdate(DocumentEvent arg0) {
76 templateUpdated();
77
78 }
79
80 public void insertUpdate(DocumentEvent e) {
81 templateUpdated();
82
83 }
84
85 public void removeUpdate(DocumentEvent e) {
86 templateUpdated();
87
88 }});
89
90
91 jta.addCaretListener(new CaretListener() {
92
93 public void caretUpdate(CaretEvent arg0) {
94
95 try {
96
97 int cursorIndex = jta.getCaretPosition();
98 int cursorLineIndex = jta.getLineOfOffset(cursorIndex);
99 int cursorLineStartIndex = jta.getLineStartOffset(cursorLineIndex);
100
101 jlbCaretPosition.setText ("Line: "+(cursorLineIndex+1)+" Column: "+(cursorIndex-cursorLineStartIndex+1));
102 }
103 catch (BadLocationException ex) {
104 System.err.println ("BadLocationException "+ex.getMessage());
105 }
106 }
107
108 } );
109
110 jlbCaretPosition = new JLabel();
111
112 jlbCaretPosition.setFont(new Font("monospaced",Font.PLAIN, 12));
113 jlbCaretPosition.setAlignmentX(Component.CENTER_ALIGNMENT);
114 jlbCaretPosition.setPreferredSize(new Dimension(100, 20));
115
116 jsp = new JScrollPane(jta);
117 jsp.setPreferredSize(new Dimension(620,400));
118
119
120 this.add(jsp);
121 this.add(jlbCaretPosition);
122 }
123
124 public TemplateEditorPane getListener() {
125 return this;
126 }
127
128 public JPanel getEPanel () {
129
130 return this;
131 }
132
133 private void templateUpdated() {
134 props.setProperty(LTDTKeys.PROJECTALTERED,"true");
135 props.setProperty(LTDTKeys.TEMPLATEEXISTS, "true");
136
137 }
138
139 private void updateLineNumber(){
140
141 int count=this.jta.getLineCount();
142 StringBuffer tempStr = new StringBuffer();
143 for (int i=1; i<=count;i++) {
144 if (i<count)
145 tempStr.append(Utility.formatInt(i,3)+"\n");
146 else
147 tempStr.append(Utility.formatInt(i, 3));
148 }
149 this.jtaLineNm.setText(tempStr.toString());
150
151 }
152
153
154
155
156
157
158 /***
159 * A customized border that displays line number left or right side of the panel, and
160 * aligned with left or right justification.
161 */
162 class LineNumberedBorder extends AbstractBorder {
163
164
165 public final static int LEFT_SIDE = -2;
166
167
168 public final static int RIGHT_SIDE = -1;
169
170
171 public final static int RIGHT_JUSTIFY = 0;
172
173
174 public final static int LEFT_JUSTIFY = 1;
175
176
177 private int lineNumberJustification = RIGHT_JUSTIFY;
178 private int location = LEFT_SIDE;
179
180 /***
181 * @param location left or right side
182 * @param justify left or right justified
183 */
184 public LineNumberedBorder(int location, int justify) {
185 setLocation(location);
186 setLineNumberJustification(justify);
187 }
188
189 /***
190 * get default border insets
191 */
192 public Insets getBorderInsets(Component c) {
193 return getBorderInsets(c, new Insets(0, 0, 0, 0));
194 }
195
196 /***
197 * This modifies border insets, add space for the line number on the
198 * left only. Not available for right side
199 *
200 *@param c Description of the Parameter
201 *@param insets Description of the Parameter
202 *@return The borderInsets value
203 */
204 public Insets getBorderInsets(Component c, Insets insets) {
205
206 if (c instanceof JTextArea) {
207 int width = lineNumberWidth((JTextArea) c);
208 if (location == LEFT_SIDE) {
209 insets.left = width;
210 } else {
211 insets.right = width;
212 }
213 }
214 return insets;
215 }
216
217 public int getLineNumberJustification() {
218 return lineNumberJustification;
219 }
220
221 public void setLineNumberJustification(int justify) {
222 if (justify == RIGHT_JUSTIFY || justify == LEFT_JUSTIFY) {
223 lineNumberJustification = justify;
224 }
225 }
226
227 public int getLocation() {
228 return location;
229 }
230
231 public void setLocation(int loc) {
232 if (loc == RIGHT_SIDE || loc == LEFT_SIDE) {
233 location = loc;
234 }
235 }
236
237 /***
238 * Returns the width, in pixels, of the maximum line number, plus a trailing
239 * space.
240 *
241 *@param textArea The text area
242 *@return line number width
243 */
244 private int lineNumberWidth(JTextArea textArea) {
245
246 int lineCount =
247 Math.max(textArea.getRows(), textArea.getLineCount() + 1);
248 return textArea.getFontMetrics(
249 textArea.getFont()).stringWidth(lineCount + " ");
250 }
251
252
253 /***
254 * Method called when the cursor blinks.
255 */
256 public void paintBorder(Component c, Graphics graphics, int x, int y,
257 int width, int height) {
258
259 java.awt.Rectangle clip = graphics.getClipBounds();
260
261 FontMetrics fm = graphics.getFontMetrics();
262 int fontHeight = fm.getHeight();
263
264
265
266 int ybaseline = y + fm.getAscent();
267
268
269
270 int startingLineNumber = (clip.y / fontHeight) + 1;
271
272 if (ybaseline < clip.y) {
273
274
275
276
277
278 ybaseline = y + startingLineNumber * fontHeight -
279 (fontHeight - fm.getAscent());
280 }
281
282
283 int yend = ybaseline + height;
284 if (yend > (y + height)) {
285 yend = y + height;
286 }
287
288 JTextArea jta = (JTextArea) c;
289
290 int lineWidth = lineNumberWidth(jta);
291
292
293 int lnxstart = x;
294 if (location == LEFT_SIDE) {
295
296
297 if (lineNumberJustification == LEFT_JUSTIFY) {
298 lnxstart = x;
299 } else {
300
301 lnxstart = x + lineWidth;
302 }
303 } else {
304
305
306
307 if (lineNumberJustification == LEFT_JUSTIFY) {
308 lnxstart = (y + width) - lineWidth;
309 } else {
310
311 lnxstart = (y + width);
312 }
313 }
314
315 graphics.setColor(Color.LIGHT_GRAY);
316
317
318
319
320 int length = ("" + Math.max(jta.getRows(), jta.getLineCount() + 1)).length();
321 while (ybaseline < yend) {
322
323
324
325
326
327
328
329 if (lineNumberJustification == LEFT_JUSTIFY) {
330 graphics.drawString(startingLineNumber + " ", lnxstart, ybaseline);
331 } else {
332
333 String label = padLabel(startingLineNumber, length, true);
334
335 graphics.drawString(label, 0, ybaseline);
336 }
337
338 ybaseline += fontHeight;
339 startingLineNumber++;
340 }
341 }
342
343
344 /***
345 * Create the string for the line number. NOTE: The length param
346 * does not include the optional space appended.
347 *
348 *@param lineNumber the line number to be formatted
349 *@param length the length desired of the string
350 *@param addSpace flag to signal whether to add some white space
351 *@return the line number in string format
352 */
353 private String padLabel(int lineNumber, int length, boolean addSpace) {
354 StringBuffer buffer = new StringBuffer();
355 buffer.append(lineNumber);
356 for (int count = (length - buffer.length()); count > 0; count--) {
357 buffer.insert(0, ' ');
358 }
359 if (addSpace) {
360
361 buffer.append(" ");
362 }
363 return buffer.toString();
364 }
365 }
366
367
368
369
370 }