KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > FormEditorSupport


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.form;
21
22 import java.awt.EventQueue JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.io.ObjectInput JavaDoc;
28 import java.io.ObjectOutput JavaDoc;
29 import java.io.OutputStream JavaDoc;
30 import java.io.Reader JavaDoc;
31 import java.io.Serializable JavaDoc;
32 import java.io.Writer JavaDoc;
33 import java.util.Collections JavaDoc;
34 import java.util.Enumeration JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.HashSet JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40 import javax.swing.JComponent JavaDoc;
41 import javax.swing.JEditorPane JavaDoc;
42 import javax.swing.JPanel JavaDoc;
43 import javax.swing.text.BadLocationException JavaDoc;
44 import javax.swing.text.Document JavaDoc;
45 import javax.swing.text.EditorKit JavaDoc;
46 import javax.swing.text.Position JavaDoc;
47 import javax.swing.text.StyledDocument JavaDoc;
48 import org.netbeans.api.editor.guards.GuardedSectionManager;
49 import org.netbeans.api.editor.guards.SimpleSection;
50 import org.netbeans.core.api.multiview.MultiViewHandler;
51 import org.netbeans.core.api.multiview.MultiViews;
52 import org.netbeans.core.spi.multiview.CloseOperationHandler;
53 import org.netbeans.core.spi.multiview.CloseOperationState;
54 import org.netbeans.core.spi.multiview.MultiViewDescription;
55 import org.netbeans.core.spi.multiview.MultiViewElement;
56 import org.netbeans.core.spi.multiview.MultiViewElementCallback;
57 import org.netbeans.core.spi.multiview.MultiViewFactory;
58 import org.netbeans.spi.editor.guards.GuardedEditorSupport;
59 import org.netbeans.spi.editor.guards.GuardedSectionsFactory;
60 import org.netbeans.spi.editor.guards.GuardedSectionsProvider;
61 import org.openide.DialogDisplayer;
62 import org.openide.ErrorManager;
63 import org.openide.NotifyDescriptor;
64 import org.openide.awt.UndoRedo;
65 import org.openide.cookies.CloseCookie;
66 import org.openide.cookies.EditorCookie;
67 import org.openide.cookies.PrintCookie;
68 import org.openide.cookies.SaveCookie;
69 import org.openide.filesystems.FileLock;
70 import org.openide.filesystems.FileObject;
71 import org.openide.filesystems.FileStateInvalidException;
72 import org.openide.filesystems.FileStatusEvent;
73 import org.openide.filesystems.FileStatusListener;
74 import org.openide.filesystems.FileSystem;
75 import org.openide.filesystems.FileUtil;
76 import org.openide.loaders.DataObject;
77 import org.openide.loaders.MultiDataObject;
78 import org.openide.nodes.CookieSet;
79 import org.openide.nodes.Node;
80 import org.openide.text.CloneableEditor;
81 import org.openide.text.CloneableEditorSupport;
82 import org.openide.text.DataEditorSupport;
83 import org.openide.text.NbDocument;
84 import org.openide.text.PositionRef;
85 import org.openide.util.UserQuestionException;
86 import org.openide.util.Utilities;
87 import org.openide.windows.CloneableOpenSupport;
88 import org.openide.windows.CloneableTopComponent;
89 import org.openide.windows.Mode;
90 import org.openide.windows.TopComponent;
91 import org.openide.windows.TopComponentGroup;
92 import org.openide.windows.WindowManager;
93
94 /**
95  *
96  * @author Ian Formanek, Tomas Pavek
97  */

98
99 public class FormEditorSupport extends DataEditorSupport implements EditorCookie.Observable, CloseCookie, PrintCookie {
100     
101     /** ID of the form designer (in the multiview) */
102     private static final String JavaDoc MV_FORM_ID = "form"; //NOI18N
103
/** ID of the java editor (in the multiview) */
104     private static final String JavaDoc MV_JAVA_ID = "java"; // NOI18N
105

106     private static final int JAVA_ELEMENT_INDEX = 0;
107     private static final int FORM_ELEMENT_INDEX = 1;
108     private int elementToOpen; // default element index when multiview TC is created
109

110     private static final String JavaDoc SECTION_INIT_COMPONENTS = "initComponents"; // NOI18N
111
private static final String JavaDoc SECTION_VARIABLES = "variables"; // NOI18N
112

113     /** Icon for the form editor multiview window */
114     private static final String JavaDoc iconURL =
115             "org/netbeans/modules/form/resources/form.gif"; // NOI18N
116

117     /** The DataObject of the form */
118     private FormDataObject formDataObject;
119     
120     /** The embracing multiview TopComponent (holds the form designer and
121      * java editor) - we remeber the last active TopComponent (not all clones) */

122     private CloneableTopComponent multiviewTC;
123     
124     // listeners
125
private static PropertyChangeListener JavaDoc topcompsListener;
126     
127     private UndoRedo.Manager editorUndoManager;
128     
129     private FormEditor formEditor;
130     
131     /** Set of opened FormEditorSupport instances (java or form opened) */
132     private static Set JavaDoc opened = Collections.synchronizedSet(new HashSet JavaDoc());
133     
134     private static Map JavaDoc fsToStatusListener = new HashMap JavaDoc();
135     
136     // --------------
137
// constructor
138

139     public FormEditorSupport(MultiDataObject.Entry javaEntry,
140             FormDataObject formDataObject,
141             CookieSet cookies) {
142         super(formDataObject, new Environment(formDataObject));
143         setMIMEType("text/x-java"); // NOI18N
144
this.formDataObject = formDataObject;
145         this.cookies = cookies;
146     }
147     
148     // ----------
149
// opening & saving interface methods
150

151     /** Main entry method. Called by OpenCookie implementation - opens the form.
152      * @see OpenCookie#open
153      */

154     public void openFormEditor(boolean forceFormElement) {
155         boolean alreadyOpened = opened.contains(this);
156         boolean switchToForm = forceFormElement || !alreadyOpened;
157         if (switchToForm) {
158             elementToOpen = FORM_ELEMENT_INDEX;
159         }
160         multiviewTC = openCloneableTopComponent();
161         multiviewTC.requestActive();
162         
163         if (switchToForm) {
164             MultiViewHandler handler = MultiViews.findMultiViewHandler(multiviewTC);
165             handler.requestActive(handler.getPerspectives()[FORM_ELEMENT_INDEX]);
166         }
167     }
168     
169     private void addStatusListener(FileSystem fs) {
170         FileStatusListener fsl = (FileStatusListener)fsToStatusListener.get(fs);
171         if (fsl == null) {
172             fsl = new FileStatusListener() {
173                 public void annotationChanged(FileStatusEvent ev) {
174                     Iterator JavaDoc iter = opened.iterator();
175                     while (iter.hasNext()) {
176                         FormEditorSupport fes = (FormEditorSupport)iter.next();
177                         if (ev.hasChanged(fes.getFormDataObject().getPrimaryFile())
178                                 || ev.hasChanged(fes.getFormDataObject().getFormFile())) {
179                             fes.updateMVTCDisplayName();
180                         }
181                     }
182                 }
183             };
184             fs.addFileStatusListener(fsl);
185             fsToStatusListener.put(fs, fsl);
186         } // else do nothing - the listener is already added
187
}
188     
189     private static void detachStatusListeners() {
190         Iterator JavaDoc iter = fsToStatusListener.entrySet().iterator();
191         while (iter.hasNext()) {
192             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iter.next();
193             FileSystem fs = (FileSystem)entry.getKey();
194             FileStatusListener fsl = (FileStatusListener)entry.getValue();
195             fs.removeFileStatusListener(fsl);
196         }
197         fsToStatusListener.clear();
198     }
199     
200     void selectJavaEditor(){
201         MultiViewHandler handler = MultiViews.findMultiViewHandler(multiviewTC);
202         handler.requestActive(handler.getPerspectives()[JAVA_ELEMENT_INDEX]);
203     }
204     
205     /** Overriden from JavaEditor - opens editor and ensures it is selected
206      * in the multiview.
207      */

208     public void open() {
209         if (EventQueue.isDispatchThread()) {
210             openInAWT();
211         } else {
212             EventQueue.invokeLater(new Runnable JavaDoc() {
213                 public void run() {
214                     openInAWT();
215                 }
216             });
217         }
218     }
219     
220     private void openInAWT() {
221         elementToOpen = JAVA_ELEMENT_INDEX;
222         super.open();
223         
224         // This method must be executed in AWT thread because
225
// otherwise multiview is opened in AWT using invokeLater
226
// and we don't have multiviewTC correctly set
227
MultiViewHandler handler = MultiViews.findMultiViewHandler(multiviewTC);
228         handler.requestActive(handler.getPerspectives()[JAVA_ELEMENT_INDEX]);
229     }
230     
231     /** Overriden from JavaEditor - opens editor at given position and ensures
232      * it is selected in the multiview.
233      */

234     public void openAt(PositionRef pos) {
235         elementToOpen = JAVA_ELEMENT_INDEX;
236         openCloneableTopComponent();
237         
238         MultiViewHandler handler = MultiViews.findMultiViewHandler(multiviewTC);
239         handler.requestActive(handler.getPerspectives()[JAVA_ELEMENT_INDEX]);
240         
241         openAt(pos, -1).getComponent().requestActive();
242     }
243     
244     public void openAt(Position JavaDoc pos) {
245         openAt(createPositionRef(pos.getOffset(), Position.Bias.Forward));
246     }
247     
248     /** Public method for loading form data from file. Does not open the
249      * source editor and designer, does not report errors and does not throw
250      * any exceptions. Runs in AWT event dispatch thread, returns after the
251      * form is loaded (even if not called from AWT thread).
252      * & @return whether the form is loaded (true also if it already was)
253      */

254     public boolean loadForm() {
255         // Ensure initialization of the formEditor
256
getFormEditor(true);
257         return formEditor.loadForm();
258     }
259     
260     /** @return true if the form is opened, false otherwise */
261     public boolean isOpened() {
262         return (formEditor != null) && formEditor.isFormLoaded();
263     }
264     
265     private boolean saving; // workaround for bug 75225
266

267     /** Save the document in this thread and start reparsing it.
268      * @exception IOException on I/O error
269      */

270     public void saveDocument() throws IOException JavaDoc {
271         IOException JavaDoc ioEx = null;
272         try {
273             if (formEditor != null) {
274                 formEditor.saveFormData();
275             }
276             saving = true; // workaround for bug 75225
277
super.saveDocument();
278         }
279         catch (PersistenceException ex) {
280             Throwable JavaDoc t = ex.getOriginalException();
281             if (t instanceof IOException JavaDoc)
282                 ioEx = (IOException JavaDoc) t;
283             else {
284                 ioEx = new IOException JavaDoc("Cannot save the form"); // NOI18N
285
ErrorManager.getDefault().annotate(ioEx, t != null ? t : ex);
286             }
287         }
288         finally {
289             saving = false; // workaround for bug 75225
290
}
291         if (formEditor != null) {
292             formEditor.reportErrors(FormEditor.SAVING);
293         }
294         
295         if (ioEx != null)
296             throw ioEx;
297     }
298     
299     void saveSourceOnly() throws IOException JavaDoc {
300         try {
301             saving = true; // workaround for bug 75225
302
super.saveDocument();
303         } finally {
304             saving = false; // workaround for bug 75225
305
}
306     }
307     
308     // ------------
309
// other interface methods
310

311     /** @return data object representing the form */
312     public final FormDataObject getFormDataObject() {
313         return formDataObject;
314     }
315     
316     // PENDING remove when form_new_layout is merged to trunk
317
public static FormDataObject getFormDataObject(FormModel formModel) {
318         return FormEditor.getFormDataObject(formModel);
319     }
320     public FormModel getFormModel() {
321         FormEditor fe = getFormEditor();
322         return (fe == null) ? null : fe.getFormModel();
323     }
324     // END of PENDING
325

326     public FormEditor getFormEditor() {
327         return getFormEditor(false);
328     }
329     
330     FormEditor getFormEditor(boolean initialize) {
331         if ((formEditor == null) && initialize) {
332             formEditor = new FormEditor(formDataObject);
333         }
334         return formEditor;
335     }
336     
337     /** Marks the form as modified if it's not yet. Used if changes made
338      * in form data don't affect the java source file (generated code). */

339     void markFormModified() {
340         if (formEditor.isFormLoaded() && !formDataObject.isModified()) {
341             notifyModified();
342         }
343     }
344     
345     protected UndoRedo.Manager createUndoRedoManager() {
346         editorUndoManager = super.createUndoRedoManager();
347         return editorUndoManager;
348     }
349     
350     void discardEditorUndoableEdits() {
351         if (editorUndoManager != null)
352             editorUndoManager.discardAllEdits();
353     }
354     
355     // ------------
356
// static getters
357

358     JEditorPane JavaDoc getEditorPane() {
359         return multiviewTC != null ?
360             ((CloneableEditorSupport.Pane)multiviewTC).getEditorPane() : null;
361     }
362     
363     // -----------
364
// closing/reloading
365

366     public void reloadForm() {
367         if (canClose())
368             reloadDocument();
369     }
370     
371     protected org.openide.util.Task reloadDocument() {
372         if (multiviewTC == null)
373             return super.reloadDocument();
374         
375         org.openide.util.Task docLoadTask = super.reloadDocument();
376         
377         if (saving) // workaround for bug 75225
378
return docLoadTask;
379         
380         // after reloading is done, open the form editor again
381
java.awt.EventQueue.invokeLater(new Runnable JavaDoc() {
382             public void run() {
383                 FormDesigner formDesigner = getFormEditor(true).getFormDesigner();
384                 if (formDesigner == null) {
385                     formDesigner = (FormDesigner)multiviewTC.getClientProperty("formDesigner"); // NOI18N
386
}
387                 if(formDesigner==null) {
388                     // if formDesigner is null then it haven't been activated yet...
389
return;
390                 }
391                 
392                 // close
393
getFormEditor().closeForm();
394                 formEditor = null;
395                 
396                 formDesigner.reset(getFormEditor(true));
397                 getFormEditor().setFormDesigner(formDesigner);
398                 
399                 if(formDesigner.isShowing()) {
400                     // load the form only if its open
401
loadForm();
402                     FormEditor formEditor = getFormEditor();
403                     formEditor.reportErrors(FormEditor.LOADING);
404                     if (!formEditor.isFormLoaded()) { // there was a loading error
405
formDesigner.removeAll();
406                     } else {
407                         formDesigner.initialize();
408                     }
409                     ComponentInspector.getInstance().focusForm(formEditor);
410                     formDesigner.revalidate();
411                     formDesigner.repaint();
412                 }
413             }
414         });
415         
416         return docLoadTask;
417     }
418     
419     protected void notifyClosed() {
420         opened.remove(this);
421         if (opened.isEmpty()) {
422             detachTopComponentsListener();
423             detachStatusListeners();
424         }
425         
426         super.notifyClosed(); // close java editor
427
if (formEditor != null) {
428             formEditor.closeForm();
429             formEditor = null;
430             multiviewTC = null;
431         }
432         elementToOpen = JAVA_ELEMENT_INDEX;
433     }
434     
435     private void multiViewClosed(CloneableTopComponent mvtc) {
436         Enumeration JavaDoc en = mvtc.getReference().getComponents();
437         boolean isLast = !en.hasMoreElements();
438         if (multiviewTC == mvtc) {
439             multiviewTC = null;
440             FormDesigner formDesigner = null;
441             // Find another multiviewTC, possibly with loaded formDesigner
442
while (en.hasMoreElements()) {
443                 multiviewTC = (CloneableTopComponent)en.nextElement();
444                 FormDesigner designer = (FormDesigner)multiviewTC.getClientProperty("formDesigner"); // NOI18N
445
if (designer != null) {
446                     formDesigner = designer;
447                     break;
448                 }
449             }
450             if (!isLast && (formDesigner == null)) {
451                 // Only Java elements are opened in the remaining clones
452
if (formEditor != null) {
453                     formEditor.closeForm();
454                     formEditor = null;
455                 }
456             }
457         }
458         
459         if (isLast) // last view of this form closed
460
notifyClosed();
461     }
462     
463     protected boolean notifyModified () {
464         boolean alreadyModified = isModified();
465         boolean retVal = super.notifyModified();
466         
467         if (retVal) { // java source modification
468
addSaveCookie();
469         }
470         
471         if (!alreadyModified) {
472             FileObject formFile = formDataObject.getFormFile();
473             if (!formFile.canWrite()) { // Issue 74092
474
FileLock lock = null;
475                 try {
476                     lock = formFile.lock();
477                 } catch (UserQuestionException uqex) {
478                     NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
479                             uqex.getLocalizedMessage(),
480                             FormUtils.getBundleString("TITLE_UserQuestion"), // NOI18N
481
NotifyDescriptor.YES_NO_OPTION);
482                     DialogDisplayer.getDefault().notify(nd);
483                     if (NotifyDescriptor.YES_OPTION.equals(nd.getValue())) {
484                         try {
485                             uqex.confirmed();
486                             EventQueue.invokeLater(new Runnable JavaDoc() {
487                                 public void run() {
488                                     reloadForm();
489                                 }
490                             });
491                         } catch (IOException JavaDoc ioex) {
492                             ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ioex);
493                         }
494                     }
495                 } catch (IOException JavaDoc ex) {
496                     ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
497                 } finally {
498                     if (lock != null) {
499                         lock.releaseLock();
500                     }
501                 }
502             }
503             updateMVTCDisplayName();
504         }
505         return retVal;
506     }
507     
508     protected void notifyUnmodified () {
509         super.notifyUnmodified();
510          // java source modification
511
removeSaveCookie();
512         updateMVTCDisplayName();
513     }
514     
515     private static void attachTopComponentsListener() {
516         if (topcompsListener != null)
517             return;
518         
519         topcompsListener = new PropertyChangeListener JavaDoc() {
520             public void propertyChange(PropertyChangeEvent JavaDoc ev) {
521                 if (TopComponent.Registry.PROP_ACTIVATED.equals(
522                                                 ev.getPropertyName()))
523                 { // activated TopComponent has changed
524
TopComponent active = TopComponent.getRegistry().getActivated();
525                     if (getSelectedElementType(active) != -1) { // it is our multiview
526
FormEditorSupport fes = getFormEditor(active);
527                         if (fes != null) {
528                             fes.multiviewTC = (CloneableTopComponent) active;
529                             FormDesigner designer = (FormDesigner)active.getClientProperty("formDesigner"); // NOI18N
530
if (designer != null)
531                                 fes.getFormEditor().setFormDesigner(designer);
532                         }
533                     }
534                     checkFormGroupVisibility();
535                 }
536                 else if (TopComponent.Registry.PROP_OPENED.equals(
537                                                 ev.getPropertyName()))
538                 { // set of opened TopComponents has changed - hasn't some
539
// of our views been closed?
540
CloneableTopComponent closedTC = null;
541                     Set JavaDoc oldSet = (Set JavaDoc) ev.getOldValue();
542                     Set JavaDoc newSet = (Set JavaDoc) ev.getNewValue();
543                     if (newSet.size() < oldSet.size()) {
544                         Iterator JavaDoc it = oldSet.iterator();
545                         while (it.hasNext()) {
546                             Object JavaDoc o = it.next();
547                             if (!newSet.contains(o)) {
548                                 if (o instanceof CloneableTopComponent)
549                                     closedTC = (CloneableTopComponent) o;
550                                 break;
551                             }
552                         }
553                     }
554                     if (getSelectedElementType(closedTC) != -1) { // it is our multiview
555
FormEditorSupport fes = getFormEditor(closedTC);
556                         if (fes != null)
557                             fes.multiViewClosed(closedTC);
558                     }
559                     TopComponent active = TopComponent.getRegistry().getActivated();
560                     if (active!=null && getSelectedElementType(active) != -1) { // it is our multiview
561
FormEditorSupport fes = getFormEditor(active);
562                         if (fes != null) {
563                             fes.updateMVTCDisplayName();
564                         }
565                     }
566                 }
567             }
568         };
569         
570         TopComponent.getRegistry().addPropertyChangeListener(topcompsListener);
571     }
572     
573     private static void detachTopComponentsListener() {
574         if (topcompsListener != null) {
575             TopComponent.getRegistry()
576                     .removePropertyChangeListener(topcompsListener);
577             topcompsListener = null;
578             
579             TopComponentGroup group = WindowManager.getDefault()
580                     .findTopComponentGroup("form"); // NOI18N
581
if (group != null)
582                 group.close();
583         }
584     }
585     
586     // -------
587
// window system & multiview
588

589     protected CloneableEditorSupport.Pane createPane() {
590         MultiViewDescription[] descs = new MultiViewDescription[] {
591             new JavaDesc(formDataObject), new FormDesc(formDataObject) };
592         
593         CloneableTopComponent mvtc =
594                 MultiViewFactory.createCloneableMultiView(
595                 descs,
596                 descs[elementToOpen],
597                 new CloseHandler(formDataObject));
598         
599         // #45665 - dock into editor mode if possible..
600
Mode editorMode = WindowManager.getDefault().findMode(CloneableEditorSupport.EDITOR_MODE);
601         if (editorMode != null) {
602             editorMode.dockInto(mvtc);
603         }
604         try {
605             addStatusListener(formDataObject.getPrimaryFile().getFileSystem());
606         } catch (FileStateInvalidException fsiex) {
607             fsiex.printStackTrace();
608         }
609         return (CloneableEditorSupport.Pane)mvtc;
610     }
611     
612     private static String JavaDoc getMVTCToolTipText(FormDataObject formDataObject) {
613         String JavaDoc name = FileUtil.getFileDisplayName(formDataObject.getFormFile());
614         if (name.endsWith(".form")) { // NOI18N
615
name = name.substring(0, name.length()-5);
616         }
617         return name;
618     }
619     
620     /**
621      * Returns display name of the multiview top component.
622      * The first item of the array is normal display name,
623      * the second item of the array is HTML display name.
624      *
625      * @param formDataObject form data object representing the multiview tc.
626      * @return display names of the MVTC. The second item can be <code>null</code>.
627      */

628     private static String JavaDoc[] getMVTCDisplayName(FormDataObject formDataObject) {
629         
630         boolean readonly = !formDataObject.getPrimaryFile().canWrite();
631         
632         TopComponent active = TopComponent.getRegistry().getActivated();
633         FormEditorSupport fes = formDataObject.getFormEditor();
634         FormModel fm = null;
635         if(fes!=null) {
636             fm = fes.getFormModel();
637         }
638         if( active!=null && getSelectedElementType(active) == FORM_ELEMENT_INDEX ) {
639             if(fm!=null) {
640                 readonly = readonly || fm.isReadOnly();
641             }
642         }
643         
644         int version;
645         if (formDataObject.isModified()) {
646             version = readonly ? 2 : 1;
647         } else {
648             version = readonly ? 0 : 3;
649         }
650         
651         Node node = formDataObject.getNodeDelegate();
652         String JavaDoc htmlTitle = node.getHtmlDisplayName();
653         String JavaDoc title = node.getDisplayName();
654         if(fm!=null) {
655             FormDesigner fd = FormEditor.getFormDesigner(formDataObject.getFormEditor().getFormModel());
656             if(fd!=null) {
657                 if( fd.isShowing() && !fd.isTopRADComponent() && fd.getTopDesignComponent() != null ) {
658                     title = FormUtils.getFormattedBundleString(
659                             "FMT_FormTitleWithContainerName", // NOI18N
660
new Object JavaDoc[] {title, fd.getTopDesignComponent().getName()});
661                 }
662             }
663         }
664         if (htmlTitle != null) {
665             if (!htmlTitle.trim().startsWith("<html>")) { // NOI18N
666
htmlTitle = "<html>" + htmlTitle; // NOI18N
667
}
668         }
669         return new String JavaDoc[] {
670             FormUtils.getFormattedBundleString("FMT_FormMVTCTitle", new Object JavaDoc[] {new Integer JavaDoc(version), title}), // NOI18N
671
(htmlTitle == null) ?
672                 null :
673                 FormUtils.getFormattedBundleString("FMT_FormMVTCTitle", new Object JavaDoc[] {new Integer JavaDoc(version), htmlTitle}) // NOI18N
674
};
675     }
676     
677     /** Updates title (display name) of all multiviews for given form. Replans
678      * to event queue thread if necessary. */

679     void updateMVTCDisplayName() {
680         if (java.awt.EventQueue.isDispatchThread()) {
681             updateMVTCDisplayNameInAWT();
682         } else {
683             java.awt.EventQueue.invokeLater(new Runnable JavaDoc() {
684                 public void run() {
685                     updateMVTCDisplayNameInAWT();
686                 }
687             });
688         }
689     }
690     
691     private void updateMVTCDisplayNameInAWT() {
692         if ((multiviewTC == null) || (!formDataObject.isValid())) // Issue 67544
693
return;
694         
695         String JavaDoc[] titles = getMVTCDisplayName(formDataObject);
696         Enumeration JavaDoc en = multiviewTC.getReference().getComponents();
697         while (en.hasMoreElements()) {
698             TopComponent tc = (TopComponent) en.nextElement();
699             tc.setDisplayName(titles[0]);
700             tc.setHtmlDisplayName(titles[1]);
701         }
702     }
703     
704     /** Updates tooltip of all multiviews for given form. Replans to even queue
705      * thread if necessary. */

706     void updateMVTCToolTipText() {
707         if (java.awt.EventQueue.isDispatchThread()) {
708             if (multiviewTC == null)
709                 return;
710             
711             String JavaDoc tooltip = getMVTCToolTipText(formDataObject);
712             Enumeration JavaDoc en = multiviewTC.getReference().getComponents();
713             while (en.hasMoreElements()) {
714                 TopComponent tc = (TopComponent) en.nextElement();
715                 tc.setToolTipText(tooltip);
716             }
717         }
718         else {
719             java.awt.EventQueue.invokeLater(new Runnable JavaDoc() {
720                 public void run() {
721                     if (multiviewTC == null)
722                         return;
723                     
724                     String JavaDoc tooltip = getMVTCToolTipText(formDataObject);
725                     Enumeration JavaDoc en = multiviewTC.getReference().getComponents();
726                     while (en.hasMoreElements()) {
727                         TopComponent tc = (TopComponent) en.nextElement();
728                         tc.setToolTipText(tooltip);
729                     }
730                 }
731             });
732         }
733     }
734     
735     static boolean isLastView(TopComponent tc) {
736         if (!(tc instanceof CloneableTopComponent))
737             return false;
738         
739         boolean oneOrLess = true;
740         Enumeration JavaDoc en = ((CloneableTopComponent)tc).getReference().getComponents();
741         if (en.hasMoreElements()) {
742             en.nextElement();
743             if (en.hasMoreElements())
744                 oneOrLess = false;
745         }
746         return oneOrLess;
747     }
748     
749     /** This is called by the multiview elements whenever they are created
750      * (and given a observer knowing their multiview TopComponent). It is
751      * important during deserialization and clonig the multiview - i.e. during
752      * the operations we have no control over. But anytime a multiview is
753      * created, this method gets called.
754      */

755     void setTopComponent(TopComponent topComp) {
756         multiviewTC = (CloneableTopComponent)topComp;
757         String JavaDoc[] titles = getMVTCDisplayName(formDataObject);
758         multiviewTC.setDisplayName(titles[0]);
759         multiviewTC.setHtmlDisplayName(titles[1]);
760         multiviewTC.setToolTipText(getMVTCToolTipText(formDataObject));
761         opened.add(this);
762         attachTopComponentsListener();
763     }
764     
765     public static FormEditorSupport getFormEditor(TopComponent tc) {
766         Object JavaDoc dobj = tc.getLookup().lookup(DataObject.class);
767         return dobj instanceof FormDataObject ?
768             ((FormDataObject)dobj).getFormEditorSupport() : null;
769     }
770     
771     private static Boolean JavaDoc groupVisible = null;
772     
773     static void checkFormGroupVisibility() {
774         // when active TopComponent changes, check if we should open or close
775
// the form editor group of windows (Inspector, Palette, Properties)
776
WindowManager wm = WindowManager.getDefault();
777         final TopComponentGroup group = wm.findTopComponentGroup("form"); // NOI18N
778
if (group == null)
779             return; // group not found (should not happen)
780

781         boolean designerSelected = false;
782         Iterator JavaDoc it = wm.getModes().iterator();
783         while (it.hasNext()) {
784             Mode mode = (Mode) it.next();
785             TopComponent selected = mode.getSelectedTopComponent();
786             if (getSelectedElementType(selected) == FORM_ELEMENT_INDEX) {
787                 designerSelected = true;
788                 break;
789             }
790         }
791         
792         if (designerSelected && !Boolean.TRUE.equals(groupVisible)) {
793             group.open();
794             final TopComponentGroup paletteGroup = wm.findTopComponentGroup( "commonpalette" ); // NOI18N
795
if( null != paletteGroup ) {
796                 paletteGroup.open();
797             }
798             ComponentInspector inspector = ComponentInspector.getInstance();
799             if (!Boolean.TRUE.equals(inspector.getClientProperty("isSliding"))) { // NOI18N
800
inspector.requestVisible();
801             }
802         }
803         else if (!designerSelected && !Boolean.FALSE.equals(groupVisible)) {
804             group.close();
805         }
806         
807         groupVisible = designerSelected ? Boolean.TRUE : Boolean.FALSE;
808     }
809     
810     /** @return 0 if java editor in form editor multiview is selected
811      * 1 if form designer in form editor multiview is selected
812      * -1 if the given TopComponent is not form editor multiview
813      */

814     static int getSelectedElementType(TopComponent tc) {
815         if (tc != null) {
816             MultiViewHandler handler = MultiViews.findMultiViewHandler(tc);
817             if (handler != null) {
818                 String JavaDoc prefId = handler.getSelectedPerspective().preferredID();
819                 if (MV_JAVA_ID.equals(prefId))
820                     return JAVA_ELEMENT_INDEX; // 0
821
if (MV_FORM_ID.equals(prefId))
822                     return FORM_ELEMENT_INDEX; // 1
823
}
824         }
825         return -1;
826     }
827     
828     public SimpleSection getVariablesSection() {
829         return getGuardedSectionManager().findSimpleSection(SECTION_VARIABLES);
830     }
831     
832     public SimpleSection getInitComponentSection() {
833         return getGuardedSectionManager().findSimpleSection(SECTION_INIT_COMPONENTS);
834     }
835     
836     public GuardedSectionManager getGuardedSectionManager() {
837         try {
838             StyledDocument JavaDoc doc = openDocument();
839             return GuardedSectionManager.getInstance(doc);
840         } catch (IOException JavaDoc ex) {
841             throw (IllegalStateException JavaDoc) new IllegalStateException JavaDoc("cannot open document").initCause(ex); // NOI18N
842
}
843     }
844
845     private final class FormGEditor implements GuardedEditorSupport {
846         
847         StyledDocument JavaDoc doc = null;
848         
849         public StyledDocument JavaDoc getDocument() {
850             return FormGEditor.this.doc;
851         }
852     }
853     
854     private FormGEditor guardedEditor;
855     private GuardedSectionsProvider guardedProvider;
856     
857     @Override JavaDoc
858     protected void loadFromStreamToKit(StyledDocument JavaDoc doc, InputStream JavaDoc stream, EditorKit JavaDoc kit) throws IOException JavaDoc, BadLocationException JavaDoc {
859         if (guardedEditor == null) {
860             guardedEditor = new FormGEditor();
861             guardedProvider = GuardedSectionsFactory.find(((DataEditorSupport.Env) env).getMimeType()).create(guardedEditor);
862         }
863         
864         if (guardedProvider != null) {
865             guardedEditor.doc = doc;
866             Reader JavaDoc reader = guardedProvider.createGuardedReader(stream, null);
867             try {
868                 kit.read(reader, doc, 0);
869             } finally {
870                 reader.close();
871             }
872         } else {
873             super.loadFromStreamToKit(doc, stream, kit);
874         }
875     }
876
877     @Override JavaDoc
878     protected void saveFromKitToStream(StyledDocument JavaDoc doc, EditorKit JavaDoc kit, OutputStream JavaDoc stream) throws IOException JavaDoc, BadLocationException JavaDoc {
879         if (guardedProvider != null) {
880             Writer JavaDoc writer = guardedProvider.createGuardedWriter(stream, null);
881             try {
882                 kit.write(writer, doc, 0, doc.getLength());
883             } finally {
884                 writer.close();
885             }
886         } else {
887             super.saveFromKitToStream(doc, kit, stream);
888         }
889     }
890     
891     // --------
892

893     /** A descriptor for the FormDesigner element of multiview. Allows lazy
894      * creation of the FormDesigner (and thus form loading). */

895     private static class FormDesc implements MultiViewDescription, Serializable JavaDoc {
896         
897         private static final long serialVersionUID =-3126744316624172415L;
898         
899         private DataObject dataObject;
900         
901         private FormDesc() {
902         }
903         
904         public FormDesc(DataObject formDO) {
905             dataObject = formDO;
906         }
907         
908         private FormEditorSupport getFormEditor() {
909             return dataObject != null && dataObject instanceof FormDataObject ?
910                 ((FormDataObject)dataObject).getFormEditorSupport() : null;
911         }
912         
913         public MultiViewElement createElement() {
914             FormEditorSupport formEditor = getFormEditor();
915             return new FormDesigner((formEditor == null) ? null : formEditor.getFormEditor(true));
916         }
917         
918         public String JavaDoc getDisplayName() {
919             return FormUtils.getBundleString("CTL_DesignTabCaption"); // NOI18N
920
}
921         
922         public org.openide.util.HelpCtx getHelpCtx() {
923             return org.openide.util.HelpCtx.DEFAULT_HELP;
924         }
925         
926         public java.awt.Image JavaDoc getIcon() {
927             return Utilities.loadImage(iconURL);
928         }
929         
930         public int getPersistenceType() {
931             return TopComponent.PERSISTENCE_NEVER;
932         }
933         
934         public String JavaDoc preferredID() {
935             return MV_FORM_ID;
936         }
937         
938         public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
939             out.writeObject(dataObject);
940         }
941         
942         public void readExternal(ObjectInput JavaDoc in)
943                 throws IOException JavaDoc, ClassNotFoundException JavaDoc
944         {
945             Object JavaDoc firstObject = in.readObject();
946             if (firstObject instanceof FormDataObject)
947                 dataObject = (DataObject) firstObject;
948         }
949     }
950     
951     // -------
952

953     /** A descriptor for the java editor as an element in multiview. */
954     private static class JavaDesc implements MultiViewDescription, Serializable JavaDoc {
955         
956         private static final long serialVersionUID =-3126744316624172415L;
957         
958         private DataObject dataObject;
959         
960         private JavaDesc() {
961         }
962         
963         public JavaDesc(DataObject formDO) {
964             dataObject = formDO;
965         }
966         
967         private FormEditorSupport getJavaEditor() {
968             return dataObject != null && dataObject instanceof FormDataObject ?
969                 ((FormDataObject)dataObject).getFormEditorSupport() : null;
970         }
971         
972         public MultiViewElement createElement() {
973             FormEditorSupport javaEditor = getJavaEditor();
974             if (javaEditor != null) {
975                 javaEditor.prepareDocument();
976                 JavaEditorTopComponent editor = new JavaEditorTopComponent(dataObject.getCookie(FormEditorSupport.class));
977                 Node[] nodes = editor.getActivatedNodes();
978                 if ((nodes == null) || (nodes.length == 0)) {
979                     editor.setActivatedNodes(new Node[] {dataObject.getNodeDelegate()});
980                 }
981                 return (MultiViewElement) editor;
982             }
983             return MultiViewFactory.BLANK_ELEMENT;
984         }
985         
986         public String JavaDoc getDisplayName() {
987             return FormUtils.getBundleString("CTL_SourceTabCaption"); // NOI18N
988
}
989         
990         public org.openide.util.HelpCtx getHelpCtx() {
991             return org.openide.util.HelpCtx.DEFAULT_HELP;
992         }
993         
994         public java.awt.Image JavaDoc getIcon() {
995             return Utilities.loadImage(iconURL);
996         }
997         
998         public int getPersistenceType() {
999             return TopComponent.PERSISTENCE_ONLY_OPENED;
1000        }
1001        
1002        public String JavaDoc preferredID() {
1003            return MV_JAVA_ID;
1004        }
1005        
1006        public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
1007            out.writeObject(dataObject);
1008        }
1009        
1010        public void readExternal(ObjectInput JavaDoc in)
1011                throws IOException JavaDoc, ClassNotFoundException JavaDoc
1012        {
1013            Object JavaDoc firstObject = in.readObject();
1014            if (firstObject instanceof FormDataObject)
1015                dataObject = (DataObject) firstObject;
1016        }
1017    }
1018    
1019    // --------
1020

1021    private static class JavaEditorTopComponent
1022                     extends CloneableEditor
1023                     implements MultiViewElement
1024    {
1025        private static final long serialVersionUID =-3126744316624172415L;
1026        
1027        private transient JComponent JavaDoc toolbar;
1028        
1029        private transient MultiViewElementCallback multiViewObserver;
1030        
1031        JavaEditorTopComponent() {
1032            super();
1033        }
1034        
1035        JavaEditorTopComponent(DataEditorSupport s) {
1036            super(s);
1037        }
1038        
1039        public JComponent JavaDoc getToolbarRepresentation() {
1040            if (toolbar == null) {
1041                JEditorPane JavaDoc pane = getEditorPane();
1042                if (pane != null) {
1043                    Document JavaDoc doc = pane.getDocument();
1044                    if (doc instanceof NbDocument.CustomToolbar) {
1045                        toolbar = ((NbDocument.CustomToolbar)doc).createToolbar(pane);
1046                    }
1047                }
1048                if (toolbar == null) {
1049                    // attempt to create own toolbar??
1050
toolbar = new JPanel JavaDoc();
1051                }
1052            }
1053            return toolbar;
1054        }
1055        
1056        public JComponent JavaDoc getVisualRepresentation() {
1057            return this;
1058        }
1059        
1060        public void componentDeactivated() {
1061            super.componentDeactivated();
1062        }
1063        
1064        public void componentActivated() {
1065            super.componentActivated();
1066        }
1067        
1068        public void setMultiViewCallback(MultiViewElementCallback callback) {
1069            multiViewObserver = callback;
1070            
1071            // needed for deserialization...
1072
if (((DataEditorSupport) cloneableEditorSupport ()).getDataObject() instanceof FormDataObject) { // [obj is from EditorSupport.Editor]
1073
// this is used (or misused?) to obtain the deserialized
1074
// multiview topcomponent and set it to FormEditorSupport
1075
((FormDataObject)((DataEditorSupport) cloneableEditorSupport ()).getDataObject()).getFormEditorSupport().setTopComponent(
1076                        callback.getTopComponent());
1077            }
1078        }
1079        
1080        public void requestVisible() {
1081            if (multiViewObserver != null)
1082                multiViewObserver.requestVisible();
1083            else
1084                super.requestVisible();
1085        }
1086        
1087        public void requestActive() {
1088            if (multiViewObserver != null)
1089                multiViewObserver.requestActive();
1090            else
1091                super.requestActive();
1092        }
1093        
1094        public void componentClosed() {
1095            // Issue 52286 & 55818
1096
super.canClose(null, true);
1097            super.componentClosed();
1098        }
1099        
1100        public void componentShowing() {
1101            super.componentShowing();
1102            DataObject dob = ((DataEditorSupport)cloneableEditorSupport()).getDataObject();
1103            FormDataObject formDO = (FormDataObject)dob;
1104            FormModel model = null;
1105            if (formDO != null) {
1106                FormEditorSupport fe = formDO.getFormEditor();
1107                if (fe != null) {
1108                    model = fe.getFormModel();
1109                    if (model != null) {
1110                        JavaCodeGenerator codeGen = (JavaCodeGenerator)FormEditor.getCodeGenerator(model);
1111                        codeGen.regenerateCode();
1112                    }
1113                }
1114            }
1115            
1116        }
1117        
1118        public void componentHidden() {
1119            super.componentHidden();
1120        }
1121        
1122        public void componentOpened() {
1123            super.componentOpened();
1124            DataObject dob = ((DataEditorSupport)cloneableEditorSupport()).getDataObject();
1125            if ((multiViewObserver != null) && !(dob instanceof FormDataObject)) {
1126                multiViewObserver.getTopComponent().close(); // Issue 67879
1127
EditorCookie ec = (EditorCookie)dob.getCookie(EditorCookie.class);
1128                ec.open();
1129            }
1130        }
1131        
1132        public void updateName() {
1133            super.updateName();
1134            if (multiViewObserver != null) {
1135                FormDataObject formDataObject = (FormDataObject)((DataEditorSupport) cloneableEditorSupport ()).getDataObject();
1136                String JavaDoc[] titles = getMVTCDisplayName(formDataObject);
1137                setDisplayName(titles[0]);
1138                setHtmlDisplayName(titles[1]);
1139            }
1140        }
1141        
1142        protected boolean closeLast() {
1143            return true;
1144        }
1145        
1146        public CloseOperationState canCloseElement() {
1147            // if this is not the last cloned java editor component, closing is OK
1148
if (!FormEditorSupport.isLastView(multiViewObserver.getTopComponent()))
1149                return CloseOperationState.STATE_OK;
1150            
1151            // return a placeholder state - to be sure our CloseHandler is called
1152
return MultiViewFactory.createUnsafeCloseState(
1153                    "ID_JAVA_CLOSING", // dummy ID // NOI18N
1154
MultiViewFactory.NOOP_CLOSE_ACTION,
1155                    MultiViewFactory.NOOP_CLOSE_ACTION);
1156        }
1157        
1158        protected boolean isActiveTC() {
1159            TopComponent selected = getRegistry().getActivated();
1160            
1161            if (selected == null)
1162                return false;
1163            if (selected == this)
1164                return true;
1165            
1166            MultiViewHandler handler = MultiViews.findMultiViewHandler(selected);
1167            if (handler != null
1168                    && MV_JAVA_ID.equals(handler.getSelectedPerspective()
1169                    .preferredID()))
1170                return true;
1171            
1172            return false;
1173        }
1174    }
1175    
1176    // ------
1177

1178    /** Implementation of CloseOperationHandler for multiview. Ensures both form
1179     * and java editor are correctly closed, data saved, etc. Holds a reference
1180     * to form DataObject only - to be serializable with the multiview
1181     * TopComponent without problems.
1182     */

1183    private static class CloseHandler implements CloseOperationHandler,
1184                                                 Serializable JavaDoc
1185    {
1186        private static final long serialVersionUID =-3126744315424172415L;
1187        
1188        private DataObject dataObject;
1189        
1190        private CloseHandler() {
1191        }
1192        
1193        public CloseHandler(DataObject formDO) {
1194            dataObject = formDO;
1195        }
1196        
1197        private FormEditorSupport getFormEditor() {
1198            return dataObject != null && dataObject instanceof FormDataObject ?
1199                ((FormDataObject)dataObject).getFormEditorSupport() : null;
1200        }
1201        
1202        public boolean resolveCloseOperation(CloseOperationState[] elements) {
1203            FormEditorSupport formEditor = getFormEditor();
1204            return formEditor != null ? formEditor.canClose() : true;
1205        }
1206    }
1207    
1208    // ------
1209

1210    private static final class Environment extends DataEditorSupport.Env {
1211        
1212        private static final long serialVersionUID = -1;
1213        
1214        public Environment(DataObject obj) {
1215            super(obj);
1216        }
1217        
1218        @Override JavaDoc
1219        protected FileObject getFile() {
1220            return this.getDataObject().getPrimaryFile();
1221        }
1222        
1223        @Override JavaDoc
1224        protected FileLock takeLock() throws java.io.IOException JavaDoc {
1225            return ((FormDataObject) getDataObject()).getPrimaryEntry().takeLock();
1226        }
1227        
1228        @Override JavaDoc
1229        public CloneableOpenSupport findCloneableOpenSupport() {
1230            return this.getDataObject().getCookie(FormEditorSupport.class);
1231        }
1232        
1233    }
1234        
1235    private final SaveCookie saveCookie = new SaveCookie() {
1236        public void save() throws java.io.IOException JavaDoc {
1237            DataObject dobj = getDataObject();
1238            dobj.getCookie(FormEditorSupport.class).saveDocument();
1239            dobj.setModified(false);
1240        }
1241    };
1242
1243    private final CookieSet cookies;
1244
1245    public void addSaveCookie() {
1246        DataObject javaData = this.getDataObject();
1247        if (javaData.getCookie(SaveCookie.class) == null) {
1248            cookies.add(saveCookie);
1249            javaData.setModified(true);
1250        }
1251    }
1252
1253    public void removeSaveCookie() {
1254        DataObject javaData = this.getDataObject();
1255        if (javaData.getCookie(SaveCookie.class) != null) {
1256            cookies.remove(saveCookie);
1257            javaData.setModified(false);
1258        }
1259    }
1260}
1261
Popular Tags