// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= DevFaqGetOpenEditorWindows
:jbake-type: wiki
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqGetOpenEditorWindows
:description: Apache NetBeans wiki DevFaqGetOpenEditorWindows
:toc: left
:toc-title:
:syntax: true

=== How can I get a list of open editor windows?

==== To obtain a reference to the currently selected editor

[source,java]
----

Node[] arr = TopComponent.getRegistry().getCurrentNodes();
for (int i = 0; i < arr.length; i++) {
    EditorCookie ec = (EditorCookie) arr[i].getCookie(EditorCookie.class);
    if (ec != null) {
        JEditorPane[] panes = ec.getOpenedPanes();
        if (panes != null) {
            // USE panes
        }
    }
}
----

Note that EditorCookie.getOpenPanes() is deprecated (link:https://netbeans.org/bugzilla/show_bug.cgi?id=223383[https://netbeans.org/bugzilla/show_bug.cgi?id=223383]). Use `org.openide.text.NbDocument.findRecentEditorPane(EditorCookie)` instead.

==== To obtain references to all opened editors

[source,java]
----

Set<TopComponent> comps = TopComponent.getRegistry().getOpened();
for (TopComponent tc: comps) {
    Node[] arr = tc.getActivatedNodes();
    for (int j = 0; j < arr.length; j++) {
        EditorCookie ec = (EditorCookie) arr[j].getCookie(EditorCookie.class);
        if (ec != null) {
            JEditorPane[] panes = ec.getOpenedPanes();
            if (panes != null) {
                // USE panes
            }
        }
    }
}
----

==== Variants to get the Editor TopComponents

===== Variant A)

[source,java]
----

    private Collection<TopComponent> getCurrentOpenedEditors() {
        final ArrayList<TopComponent> result = new ArrayList<TopComponent>();
        final WindowManager wm = WindowManager.getDefault();
        for (Mode mode : wm.getModes()) {
            if (wm.isEditorMode(mode)) {
                //result.addAll(Arrays.asList(mode.getTopComponents())); OR even faster
                result.addAll(Arrays.asList(wm.getOpenedTopComponents(mode)));
            }
        }
        return result;
    }

----

===== Variant B)

[source,java]
----

    private TopComponent getCurrentEditor() {
	Set<? extends Mode> modes = WindowManager.getDefault().getModes();
	for (Mode mode : modes) {
	    if ("editor".equals(mode.getName())) {
		return mode.getSelectedTopComponent();
	    }
	}
	return null;
    }

    //or 
    private TopComponent getCurrentEditor() {
        Mode editor = WindowManager.getDefault().findMode("editor");
        return editor.getSelectedTopComponent();
    }
----

<hr/>
*Reference-* link:http://nbguru.wordpress.com/2008/07/25/tat-editor-windows-reactivated-8/[Editor Windows Reactivated]
<hr/>

=== Apache Migration Information

The content in this page was kindly donated by Oracle Corp. to the
Apache Software Foundation.

This page was exported from link:http://wiki.netbeans.org/DevFaqGetOpenEditorWindows[http://wiki.netbeans.org/DevFaqGetOpenEditorWindows] , 
that was last modified by NetBeans user Markiewb 
on 2016-10-26T20:35:35Z.


*NOTE:* This document was automatically converted to the AsciiDoc format on 2018-02-07, and needs to be reviewed.
