View Javadoc

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  		//this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
53  		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
54  		this.setBorder(BorderFactory.createTitledBorder("Template Editor"));
55  		this.setOpaque(true);
56  
57  		
58  		// make it a small text area so the LineNumbered Border generates
59  		// correct listing in adequate alignment
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 	   // line number goes to the left sied
165 	   public final static int LEFT_SIDE = -2;
166 
167 	   // line number goes to the right side
168 	   public final static int RIGHT_SIDE = -1;
169 
170 	   // line number is displayed right justified
171 	   public final static int RIGHT_JUSTIFY = 0;
172 
173 	   // line number is displayed left justified
174 	   public final static int LEFT_JUSTIFY = 1;
175 
176 	   // default setting
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 	      // if c is not a JTextArea...nothing is done...
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 	      // starting location at the "top" of the page
265 	      // y is the starting baseline for the font
266 	      int ybaseline = y + fm.getAscent();
267 
268 	      
269 	      // now determine if it is the "top" of the page, or somewhere else
270 	      int startingLineNumber = (clip.y / fontHeight) + 1;
271 
272 	      if (ybaseline < clip.y) {
273 	         //
274 	         // not within the clip rectangle...move it...
275 	         // determine how many fontHeight's there are between
276 	         // y and clip.y...then add that many fontHeights
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 	      // base x position of the line number
293 	      int lnxstart = x;
294 	      if (location == LEFT_SIDE) {
295 	         // x (LEFT) or (x + lineWidth) (RIGHT)
296 	         // depends upon justification
297 	         if (lineNumberJustification == LEFT_JUSTIFY) {
298 	            lnxstart = x;
299 	         } else {
300 	            // RIGHT JUSTIFY
301 	            lnxstart = x + lineWidth;
302 	         }
303 	      } else {
304 	         // RIGHT SIDE
305 	         // (y + width) - lineWidth (LEFT) or (y + width) (RIGHT)
306 	         // depends upon justification
307 	         if (lineNumberJustification == LEFT_JUSTIFY) {
308 	            lnxstart = (y + width) - lineWidth;
309 	         } else {
310 	            // RIGHT JUSTIFY
311 	            lnxstart = (y + width);
312 	         }
313 	      }
314 
315 	      graphics.setColor(Color.LIGHT_GRAY);
316 	      
317 	      //
318 	      // loop until out of the "visible" region...
319 	      //
320 	      int length = ("" + Math.max(jta.getRows(), jta.getLineCount() + 1)).length();
321 	      while (ybaseline < yend) {
322 	         //
323 	         // options:
324 	         // . left justify the line numbers
325 	         // . right justify the line numbers
326 	    	 // for either side
327 	         //
328 
329 	         if (lineNumberJustification == LEFT_JUSTIFY) {
330 	            graphics.drawString(startingLineNumber + " ", lnxstart, ybaseline);
331 	         } else {
332 	            // right justify
333 	            String label = padLabel(startingLineNumber, length, true);
334 	            //graphics.drawString(label, lnxstart - fm.stringWidth(label), ybaseline);
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 }