Source code: ide/VeriSimDocumentFrame.java
1
2 /* **********************************
3 File: VeriSimDocumentFrame.java
4 Author: Felix(felix@ulise.cs.pub.ro)
5 Created on ??
6 Comments: Part of the vIDE Project
7 Copyright 1999 the vIDE Team.
8 ***********************************/
9
10 package ide;
11
12 import java.awt.*;
13 import java.awt.event.*;
14 import java.beans.*;
15 import java.io.*;
16 import java.net.URL;
17 import java.util.*;
18
19 import javax.swing.text.*;
20 import javax.swing.undo.*;
21 import javax.swing.event.*;
22 import javax.swing.*;
23 import javax.swing.plaf.*;
24
25 /**
26 * Sample JInternalFrame using the simple text editor component that
27 * supports only one font. (for now)
28 *
29 * @author Lucian Felix Ghita
30 * @bugfixes Alec <-+
31 * @alecfixes fEliX |
32 * @-----------------+
33 * @version 1.0
34 */
35 class VeriSimDocumentFrame
36 extends JInternalFrame implements UndoableEditListener
37 {
38
39 private static int editorCount = 1;
40 private static ResourceBundle resources;
41 private String fileName;
42 public Project theProject; //null means that this file is not included in the current project
43 //the comment from above means nothing.
44
45 private JScrollPane scroller;
46 private int fontHeight;
47 public boolean focused;
48 public int windowID;
49
50 public VerilogTextArea editor;
51 private Hashtable commands;
52 private Hashtable menuItems;
53 private JMenuBar menubar;
54 private JToolBar toolbar;
55 private JComponent status;
56
57 public NumberedBorder numberedBorder;
58
59
60 /** UndoManager that we add edits to. */
61 protected UndoManager undo = new UndoManager();
62
63 private UndoAction undoAction = new UndoAction();
64 private RedoAction redoAction = new RedoAction();
65
66 /**
67 * File information
68 */
69 public static String fileDataProp = "fileData";
70
71 static {
72 //set the appropriate UI for editor:
73 //veriLogTextUI is the UI class ID for UIDefaults
74 UIManager.put(VerilogTextArea.uiClassID, "ide.VerilogTextUI");
75 }
76
77 VeriSimDocumentFrame(Project project, File file) throws IOException
78 {
79 super("New editor frame", true, true, true, true);
80 this.theProject = project;
81
82 //focused = true;
83 //open existing file or creates a new file if file == null;
84 initEditor();
85
86 if (file == null) {//new file
87 setTitle("Untitled" + editorCount + ".v");
88 fileName = "Untitled" + editorCount + ".v";
89 editorCount++;
90 } else {
91 setTitle("" + file);
92 fileName = "" + file;
93 if (file.exists())
94 loadFile();
95 }
96
97 editor.getDocument().addUndoableEditListener(this); // Add this as a listener for undoable edits.
98 FileData fileData = new FileData(fileName);
99 editor.getDocument().putProperty(fileDataProp, fileData);
100 }
101
102 /**
103 * Makes a new view based on the document from 'original'.
104 * NOTE: since from this moment the document will have both views as
105 * change listeners, the undo command will ... I don't know..
106 */
107 VeriSimDocumentFrame(Project project, Document doc) {
108 super("New editor frame", true, true, true, true);
109 this.theProject = project;
110
111 //focused = true;
112 //open existing file or creates a new file if file == null;
113 initEditor();
114 FileData fd = (FileData) doc.getProperty(fileDataProp);
115 fd.openCount++;
116 fileName = fd.fileName;
117
118 setTitle(fileName + " (" + fd.openCount + ")");
119 editor.setDocument(doc);
120 doc.addUndoableEditListener(this); // Add this as a listener for undoable edits.
121 }
122 /* sa-l ia dracu' de JIT compiler.Crapa mashina virtuala cu totul! (GPF in Msvcrt.dll sau in Kernel32.dll)
123 JAVA caused an invalid page fault in module KERNEL32.DLL at 014f:bff85fe2.
124 Registers:
125 EAX=c00211fc CS=014f EIP=bff85fe2 EFLGS=00010202
126 EBX=00000000 SS=0157 ESP=01ca0000 EBP=01ca0098
127 ECX=c00211f8 DS=0157 ESI=01ca00cc FS=3867
128 EDX=c00211fc ES=0157 EDI=01ca00b0 GS=0000
129 Bytes at CS:EIP: 56 8b 19 57 8b 30 55 83 7e 54 00 0f 84 1c 01 00
130 Stack dump: 00000000 00000000 bff85812 00000001 0000000e 01ca00b0 01ca00cc 81572840 8156a1bc 00000000 00000000 00000000 00000000 00000000 00000000 00000000
131 */
132
133 private void initEditor() {
134 //editor.setFont(new Font("FixedSys", Font.PLAIN, 12)); //e cumva prea mult 12 ?
135 //todo -> the font should be chosed from the preferences dialog from the getFontList() list;
136 scroller = new JScrollPane(editor = new VerilogTextArea());
137 JViewport vport = scroller. getColumnHeader();
138 getContentPane().add("Center", scroller);
139 setSize( 325, 200);
140 setLocation( 20 + editorCount * 20, 55 + editorCount * 20);
141 fontHeight = editor.getFont().getSize(); //shi cu spatiile dintre linii ce fac?
142 addInternalFrameListener(new EditorInternalFrameAdapter(this, theProject));
143 editor.getCaret().
144 addChangeListener(new CaretPositionChangeListener(theProject.sb,
145 editor));
146 editor.getCaret().setBlinkRate(0);
147 //fara blink scap de repainturi la tot editorul..!
148 editor.setBorder(numberedBorder =
149 new NumberedBorder(35, scroller.getViewport(), editor.getRowHeight()));
150 setCursor(new Cursor(Cursor.TEXT_CURSOR));
151
152 //din motive necunoscute (*#!?) JTextArea.getRowHeight() nu e publica..;
153 //deci nu pot afla inaltimea unei linii,
154 //ceea ce e un lucru foarte frustrant la ora 5 am...
155 }
156
157
158
159 public void loadFile() throws IOException{
160 editor.read(new FileReader(fileName), null);
161 }
162
163 public void saveFile() throws IOException{
164 //todo : System.setProperty("line.separator", optiunea din ...);
165 editor.write(new FileWriter(fileName));
166 getFileData().isModified = false;
167 }
168
169 public String getFileName() {
170 return fileName;
171 }
172
173 public FileData getFileData() {
174 return (FileData) editor.getDocument().getProperty(fileDataProp);
175 }
176
177 /**
178 * Renames the file associated with this editor. This implies
179 * creating a new PlainDocument for this editor.
180 * @return the old document
181 */
182 public Document setFileName(String fileName) throws IOException {
183 Document newDoc = null, oldDoc = editor.getDocument();
184 String oldFileName = fileName;
185 try {
186 setTitle(this.fileName = fileName);
187 saveFile(); //create the new file
188 loadFile(); //create a new Document for it
189 newDoc = editor.getDocument();
190 FileData fd = new FileData(fileName);
191 newDoc.putProperty(fileDataProp, fd);
192 newDoc.addUndoableEditListener(this);
193 return oldDoc;
194 } catch (IOException ioex) {
195 fileName = oldFileName;
196 if (editor.getDocument() != oldDoc)editor.setDocument(oldDoc);
197 throw ioex; //notify that we failed here
198 }
199 }
200
201
202 /**
203 * Messaged when the Document has created an edit, the edit is
204 * added to <undo>, an instance of UndoManager.
205 */
206 public void undoableEditHappened(UndoableEditEvent e) {
207 undo.addEdit(e.getEdit());
208 undoAction.update();
209 redoAction.update();
210 FileData fileData = (FileData) editor.getDocument().getProperty(fileDataProp);
211 if (!fileData.isModified) { //WHY the f.. do you modify the main title from
212 //here????
213 //if the same document will be opened in multiple views, only some of them
214 //will have the modified marker active....
215 fileData.isModified = true;
216 }
217 }
218
219 public void jumpToLine(int line) {
220 highlightLine(line-1);
221 System.out.println("rows: " + editor.getRows());
222 scroller.getViewport().setViewPosition(new Point(0,
223 editor.getRowHeight() *
224 (line - 1)));
225 //todo ! - > fontHeigth != lineHeigth
226 }
227
228 public int getCurrentLine() {
229 try {
230 return editor.getLineOfOffset(editor.getCaretPosition());
231 } catch (Exception e) {
232 theProject.error("Internal error in \n VeriSimDocumentFrame.getCurrentLine :\n" + e);
233 return 0; // sau mai bine null
234 }
235 }
236
237 public void highlightLine(int line) {
238 //todo; method for highlight in NumberedBorder
239 numberedBorder.bulletPosition = line;
240 }
241
242 public void undo() {
243 (new UndoAction()).actionPerformed(null);
244 }
245
246 public void redo() {
247 (new RedoAction()).actionPerformed(null);
248 }
249
250 class UndoAction extends AbstractAction {
251 //todo -> something wrong here.
252 public UndoAction() {
253 super("Undo");
254 setEnabled(false);
255 }
256
257 public void actionPerformed(ActionEvent e) {
258 try {
259 undo.undo();
260 } catch (CannotUndoException ex) {
261 System.out.println("Unable to undo.");
262 ex.printStackTrace();
263 }
264 update();
265 redoAction.update();
266 }
267 protected void update() {
268 if(undo.canUndo()) {
269 setEnabled(true);
270 putValue(Action.NAME, undo.getUndoPresentationName());
271 }
272 else {
273 setEnabled(false);
274 putValue(Action.NAME, "Undo");
275 }
276 }
277 } //UndoAction class
278
279
280 class RedoAction extends AbstractAction {
281 public RedoAction() {
282 super("Redo");
283 setEnabled(false);
284 }
285
286 public void actionPerformed(ActionEvent e) {
287 try {
288 undo.redo();
289 }
290 catch (CannotRedoException ex) {
291 System.out.println("Unable to redo.");
292 ex.printStackTrace();
293 }
294 update();
295 undoAction.update();
296 }
297
298 protected void update() {
299 if(undo.canRedo()) {
300 setEnabled(true);
301 putValue(Action.NAME, undo.getRedoPresentationName());
302 }
303 else {
304 setEnabled(false);
305 putValue(Action.NAME, "Redo");
306 }
307 }
308 }// class RedoAction
309
310
311 /**
312 * Project.focusedEditor modifier.
313 *
314 */
315
316 class EditorInternalFrameAdapter
317 extends javax.swing.event.InternalFrameAdapter
318 {
319 protected Project prj;
320 protected VeriSimDocumentFrame editor;
321
322 public EditorInternalFrameAdapter(VeriSimDocumentFrame editor,
323 Project prj) {
324 this.prj = prj;
325 this.editor = editor;
326 }
327
328 public void internalFrameActivated(InternalFrameEvent ev ) {
329 prj.focusedEditor = editor;
330 prj.god.setTitle(prj.name + " - vide - [ " + editor.getTitle() + " ]");
331 editor.focused = true;
332 prj.enableEditActions(true);
333 }
334
335 public void internalFrameClosing(InternalFrameEvent ev) {
336 if(getFileData().isModified) {
337 Object[] options = { "Yes", "No"};
338 if (JOptionPane.showOptionDialog(null, "File is modified. Save?\n" +
339 editor.getFileName(),
340 "File is modified. Save?",
341 JOptionPane.DEFAULT_OPTION,
342 JOptionPane.WARNING_MESSAGE,
343 null,
344 options, options[0]) == 0)
345 try {
346 editor.saveFile();
347 } catch (IOException ioex) {
348 prj.error("could not save \"" + getFileName() + "\": " +
349 ioex);
350 }
351 }
352
353 editor.focused = false;
354 prj.removeVeriSimDocFrame(editor);
355 prj.removeFromWindowsList(editor);
356 editor.editor.getDocument().removeUndoableEditListener(editor); //vezi
357 //comentariul de la declaratie
358
359 prj.enableEditActions(false);
360 }
361
362 public void internalFrameDeactivated(InternalFrameEvent e) {
363 prj.god.setTitle(prj.name + " - vide");
364 prj.enableEditActions(false);
365 }
366
367 } //EditorInternalFrameAdapter class
368
369
370 /**
371 * Displays line numbers on the left of editor
372 * todo -> must be a inner class of Project and alocated only once.
373 */
374
375 class NumberedBorder extends javax.swing.border.EmptyBorder {
376
377 int fontHeight;
378 int startHeight = 0;
379 int left;
380 int endHeight = 0;
381 JViewport vport;
382 public int bulletPosition = 1;
383
384 public NumberedBorder(int left, JViewport vport, int fontHeight) {
385 super(0, left, 0, 0);
386 this.left = left;
387 this.vport = vport;
388 this.fontHeight = fontHeight;
389 }
390
391 public void paintBorder(Component c, Graphics g, int x,
392 int y, int width, int height)
393 {
394 //bug >> if (vport.getViewPosition().x > left + 5) return; //the border is not shown.
395
396 startHeight = vport.getViewPosition().y;
397 endHeight = vport.getExtentSize().height + startHeight;
398 g.setColor(Color.lightGray);
399 g.fillRect(0, startHeight, left, endHeight);
400 g.setColor(Color.black);
401 int j = startHeight / fontHeight;
402 for (int i = (j +1) * fontHeight - fontHeight/2; i < endHeight + 25; i += fontHeight, j++){ //j++ ?? whadda bad dream !
403 g.drawString(j +1 + "", 0, i + 3);
404 }
405
406 g.setColor(Color.red);
407 g.fillOval(left - 12, bulletPosition * fontHeight + 1, 10, 10);
408 }
409
410 void setFontHeight(int newH){
411 fontHeight = newH;
412 }
413 }//NumberedBorder class
414
415
416
417 /**
418 * Displays caret position in the status bar.
419 * todo -> alocate only once.
420 */
421
422 class CaretPositionChangeListener implements ChangeListener {
423 VeriSimFrame.StatusBar sb;
424 DefaultCaret _caret;
425 JTextArea _editor;
426 int line;
427
428 public CaretPositionChangeListener(VeriSimFrame.StatusBar sb,
429 JTextArea _editor)
430 {
431 this._caret = (DefaultCaret) _editor.getCaret();
432 this._editor = _editor;
433 this.sb = sb;
434 }
435
436 public void stateChanged(ChangeEvent event) {
437 int offset = _caret.getDot();
438 try {
439 line =_editor. getLineOfOffset(offset);
440 sb.setLnCol(line, offset - _editor.getLineStartOffset(line));
441 if(!_caret.isVisible())_caret.setVisible(true);
442 } catch (Exception e) {
443 System.out.println("Exception in caretListener.stateChanged:" + e);
444 }
445 }
446 }//CaretPositionChangeListener class
447 }//VeriSimDocumentFrame class
448 //sa le ia dracu' de acolade.
449
450