diff -r dfca5ea7b2f1 openide.text/apichanges.xml --- a/openide.text/apichanges.xml Wed Jul 29 15:32:49 2009 +0200 +++ b/openide.text/apichanges.xml Wed Aug 12 16:49:00 2009 +0200 @@ -46,6 +46,25 @@ Text API + + + Add Document.findRecentEditorPane + + + + + +

+ Add NbDocument.findRecentEditorPane to allow non blocking retrieval of recently selected editor pane. + Method returns null when editor pane initialization is not finished. Client is notified about finished pane + initialization by property change event EditorCookie.Observable.PROP_OPENED_PANES. + NbDocument.findRecentEditorPane is replacement for EditorCookie.getOpenedPanes which waits till all editor + panes are initialized. It is nonblocking only when EditorCookie is instanceof CloneableEditorSupport. +

+
+ + +
Improve Line.show diff -r dfca5ea7b2f1 openide.text/manifest.mf --- a/openide.text/manifest.mf Wed Jul 29 15:32:49 2009 +0200 +++ b/openide.text/manifest.mf Wed Aug 12 16:49:00 2009 +0200 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.text -OpenIDE-Module-Specification-Version: 6.23 +OpenIDE-Module-Specification-Version: 6.24 OpenIDE-Module-Localizing-Bundle: org/openide/text/Bundle.properties AutoUpdate-Essential-Module: true diff -r dfca5ea7b2f1 openide.text/src/org/openide/text/CloneableEditor.java --- a/openide.text/src/org/openide/text/CloneableEditor.java Wed Jul 29 15:32:49 2009 +0200 +++ b/openide.text/src/org/openide/text/CloneableEditor.java Wed Aug 12 16:49:00 2009 +0200 @@ -78,6 +78,9 @@ /** Flag indicating it was initialized this CloneableEditor */ private boolean initialized; + /** Flag indicating progress of DoInitialize tasks */ + private boolean initVisualFinished; + /** Position of cursor. Used to keep the value between deserialization * and initialization time. */ private int cursorPosition = -1; @@ -533,6 +536,13 @@ } }); isInInitVisual = false; + initVisualFinished = true; + + //#168415: Notify clients that pane creation is finished. + CloneableEditorSupport ces = cloneableEditorSupport(); + if (ces != null) { + ces.firePropertyChange(EditorCookie.Observable.PROP_OPENED_PANES, null, null); + } } private void initRest() { @@ -593,6 +603,7 @@ customToolbar = null; pane = null; initialized = false; + initVisualFinished = false; } } ); @@ -921,6 +932,15 @@ return this; } + /** + * #168415: Returns true if creation of editor pane is finished. It is used + * to avoid blocking AWT thread by call of getEditorPane. + */ + boolean isEditorPaneReady () { + assert SwingUtilities.isEventDispatchThread(); + return initVisualFinished; + } + public JEditorPane getEditorPane() { assert SwingUtilities.isEventDispatchThread(); initialize(); diff -r dfca5ea7b2f1 openide.text/src/org/openide/text/CloneableEditorSupport.java --- a/openide.text/src/org/openide/text/CloneableEditorSupport.java Wed Jul 29 15:32:49 2009 +0200 +++ b/openide.text/src/org/openide/text/CloneableEditorSupport.java Wed Aug 12 16:49:00 2009 +0200 @@ -1092,6 +1092,53 @@ return ll.isEmpty() ? null : ll.toArray(new JEditorPane[ll.size()]); } + /** + * Gets recently selected editor pane opened by this support + * Can be called from AWT event thread only. It is nonblocking. It returns either pane + * if pane intialization is finished or null if initialization is still in progress. + * + * @return pane or null + * + */ + JEditorPane getRecentPane () { + // expected in AWT only + assert SwingUtilities.isEventDispatchThread() + : "CloneableEditorSupport.getOpenedPaneForTC must be called from AWT thread only"; // NOI18N + CloneableEditorSupport redirect = CloneableEditorSupportRedirector.findRedirect(this); + if (redirect != null) { + return redirect.getRecentPane(); + } + + Enumeration en = allEditors.getComponents(); + + while (en.hasMoreElements()) { + CloneableTopComponent ctc = (CloneableTopComponent) en.nextElement(); + Pane ed = (Pane) ctc.getClientProperty(PROP_PANE); + + if ((ed == null) && ctc instanceof Pane) { + ed = (Pane) ctc; + } + + if (ed != null) { + JEditorPane p = null; + if (getLastSelected() == ed) { + if (ed instanceof CloneableEditor) { + if (((CloneableEditor) ed).isEditorPaneReady()) { + p = ed.getEditorPane(); + } + } else { + p = ed.getEditorPane(); + } + } + return p; + } else { + throw new IllegalStateException("No reference to Pane. Please file a bug against openide/text"); + } + } + + return null; + } + /** Returns the lastly selected Pane or null */ final Pane getLastSelected() { diff -r dfca5ea7b2f1 openide.text/src/org/openide/text/NbDocument.java --- a/openide.text/src/org/openide/text/NbDocument.java Wed Jul 29 15:32:49 2009 +0200 +++ b/openide.text/src/org/openide/text/NbDocument.java Wed Aug 12 16:49:00 2009 +0200 @@ -43,12 +43,12 @@ import java.awt.Color; import java.awt.Component; -import java.beans.*; import javax.swing.JEditorPane; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.text.*; +import org.openide.cookies.EditorCookie; /** Dummy class holding utility methods for working with NetBeans document conventions. @@ -367,7 +367,32 @@ doc.setLogicalStyle(offset, st); } } - + + /** + * Gets recently selected editor pane opened by editor cookie + * Can be called from AWT event thread only. + * + * @param ec EditorCookie used to find out recently selected editor pane + * @return pane or null + * + */ + public static JEditorPane findRecentEditorPane (EditorCookie ec) { + // expected in AWT only + assert SwingUtilities.isEventDispatchThread() + : "NbDocument.findInitializedPaneForActiveTC must be called from AWT thread only"; // NOI18N + if (ec instanceof CloneableEditorSupport) { + // find if initialized or return null immediately + JEditorPane pane = ((CloneableEditorSupport) ec).getRecentPane(); + return pane; + } else { + JEditorPane [] panes = ec.getOpenedPanes(); + if (panes != null) { + return panes[0]; + } + return null; + } + } + /** Locks the document to have exclusive access to it. * Documents implementing {@link Lockable} can specify exactly how to do this. * diff -r dfca5ea7b2f1 openide.text/test/unit/src/org/openide/text/CloneableEditorCreationFinishedTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.text/test/unit/src/org/openide/text/CloneableEditorCreationFinishedTest.java Wed Aug 12 16:49:00 2009 +0200 @@ -0,0 +1,253 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ + +package org.openide.text; + + +import java.beans.*; +import java.io.*; +import java.util.*; +import javax.swing.JEditorPane; +import javax.swing.text.EditorKit; +import org.netbeans.junit.NbTestCase; +import org.openide.cookies.EditorCookie; +import org.openide.util.Exceptions; +import org.openide.util.Lookup; +import org.openide.windows.*; + +public class CloneableEditorCreationFinishedTest extends NbTestCase +implements CloneableEditorSupport.Env { + static { + System.setProperty("org.openide.windows.DummyWindowManager.VISIBLE", "false"); + } + /** the support to work with */ + private transient CES support; + + // Env variables + private transient String content = ""; + private transient boolean valid = true; + private transient boolean modified = false; + /** if not null contains message why this document cannot be modified */ + private transient String cannotBeModified; + private transient Date date = new Date (); + private transient List/**/ propL = new ArrayList (); + private transient VetoableChangeListener vetoL; + + private static CloneableEditorCreationFinishedTest RUNNING; + + private boolean continueFlag; + private int eventCounter; + + public CloneableEditorCreationFinishedTest(String s) { + super(s); + } + + protected void setUp () { + support = new CES (this, Lookup.EMPTY); + RUNNING = this; + } + + protected boolean runInEQ() { + return true; + } + + private Object writeReplace () { + return new Replace (); + } + + private boolean continueExecution () { + return continueFlag; + } + + public void testEditorPaneFinished () throws Exception { + support.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(EditorCookie.Observable.PROP_OPENED_PANES)) { + CloneableEditor ed = (CloneableEditor)support.getRef ().getAnyComponent (); + if (eventCounter == 0) { + assertFalse("First event. isEditorPaneReady must return false", ed.isEditorPaneReady()); + eventCounter++; + } else if (eventCounter == 1) { + assertTrue("Second event. isEditorPaneReady must return true", ed.isEditorPaneReady()); + } + } + } + }); + support.open (); + JEditorPane pane = support.getRecentPane(); + assertNull("Must return null", pane); + + continueFlag = true; + + JEditorPane[] panes = support.getOpenedPanes(); + + pane = support.getRecentPane(); + assertNotNull("Must return not null", pane); + } + + + // + // Implementation of the CloneableEditorSupport.Env + // + + public synchronized void addPropertyChangeListener(PropertyChangeListener l) { + propL.add (l); + } + public synchronized void removePropertyChangeListener(PropertyChangeListener l) { + propL.remove (l); + } + + public synchronized void addVetoableChangeListener(VetoableChangeListener l) { + assertNull ("This is the first veto listener", vetoL); + vetoL = l; + } + public void removeVetoableChangeListener(VetoableChangeListener l) { + assertEquals ("Removing the right veto one", vetoL, l); + vetoL = null; + } + + public CloneableOpenSupport findCloneableOpenSupport() { + return RUNNING.support; + } + + public String getMimeType() { + return "text/plain"; + } + + public Date getTime() { + return date; + } + + public InputStream inputStream() throws IOException { + return new ByteArrayInputStream (content.getBytes ()); + } + public OutputStream outputStream() throws IOException { + class ContentStream extends ByteArrayOutputStream { + public void close () throws IOException { + super.close (); + content = new String (toByteArray ()); + } + } + + return new ContentStream (); + } + + public boolean isValid() { + return valid; + } + + public boolean isModified() { + return modified; + } + + public void markModified() throws IOException { + if (cannotBeModified != null) { + final String notify = cannotBeModified; + IOException e = new IOException () { + public String getLocalizedMessage () { + return notify; + } + }; + Exceptions.attachLocalizedMessage(e, cannotBeModified); + throw e; + } + + modified = true; + } + + public void unmarkModified() { + modified = false; + } + + /** Implementation of the CES */ + private final class CES extends CloneableEditorSupport { + public CES (Env env, Lookup l) { + super (env, l); + } + + public CloneableTopComponent.Ref getRef () { + return allEditors; + } + + protected String messageName() { + return "Name"; + } + + protected String messageOpened() { + return "Opened"; + } + + protected String messageOpening() { + return "Opening"; + } + + protected String messageSave() { + return "Save"; + } + + protected String messageToolTip() { + return "ToolTip"; + } + + protected EditorKit createEditorKit () { + return new NbLikeEditorKit () { + public Void call() throws Exception { + while (true) { + Thread.sleep(100); + if (continueExecution()) { + break; + } + } + super.call(); + return null; + } + + }; + } + + } + + private static final class Replace implements Serializable { + public Object readResolve () { + return RUNNING; + } + } +} diff -r dfca5ea7b2f1 spi.debugger.ui/nbproject/project.xml --- a/spi.debugger.ui/nbproject/project.xml Wed Jul 29 15:32:49 2009 +0200 +++ b/spi.debugger.ui/nbproject/project.xml Wed Aug 12 16:49:00 2009 +0200 @@ -150,7 +150,7 @@ - 6.16 + 6.24 diff -r dfca5ea7b2f1 spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EditorContextDispatcher.java --- a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EditorContextDispatcher.java Wed Jul 29 15:32:49 2009 +0200 +++ b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EditorContextDispatcher.java Wed Aug 12 16:49:00 2009 +0200 @@ -588,7 +588,7 @@ } } - private void updateCurrentOpenedPane(TopComponent activeComponnet, Object source) { + private void updateCurrentOpenedPane(TopComponent activeComponent, Object source) { JEditorPane oldEditor = null; JEditorPane newEditor = null; String MIMEType = null; @@ -597,7 +597,7 @@ EditorCookie ec = currentEditorCookie.get(); if ((source == null || source == ec)) { oldEditor = currentOpenedPane.get(); - if (ec != null && activeComponnet != null) { + if (ec != null && activeComponent != null) { if (ec.getDocument() == null && // !currentEditorCookie.prepareDocument().isFinished() && (ec instanceof EditorCookie.Observable)) { // Document is not yet loaded, wait till we're notified that it is. @@ -607,18 +607,13 @@ } logger.fine("Document " + ec + " loaded, updating..."); // NOI18N long t1 = System.nanoTime(); - JEditorPane[] openedPanes = ec.getOpenedPanes(); + JEditorPane openedPane = NbDocument.findRecentEditorPane(ec); long t2 = System.nanoTime(); logger.fine("Time to find opened panes = "+(t2 - t1)+" ns = "+(t2 - t1)/1000000+" ms."); // NOI18N - if (openedPanes != null && openedPanes.length >= 1) { - for (JEditorPane openedPane : openedPanes) { - if (activeComponnet.isAncestorOf(openedPane)) { - //System.err.println("\n"+newComponnet+".isAncestorOf("+openedPane+")\n"); - newEditor = openedPane; - isSetPane = true; - break; - } - } + if (openedPane != null) { + assert activeComponent.isAncestorOf(openedPane) : "Active component must contain opened pane."; + newEditor = openedPane; + isSetPane = true; } } if (!isSetPane && source == null) {