// 
//     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.
//

= How can I get a list of open editor windows?
:jbake-type: wikidev
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqGetOpenEditorWindows
:description: Apache NetBeans wiki DevFaqGetOpenEditorWindows
:toc: left
:toc-title:
:syntax: true
:wikidevsection: _editor_and_edited_files
:position: 1

== 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://bz.apache.org/netbeans/show_bug.cgi?id=223383[https://bz.apache.org/netbeans/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();
    }
----


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

////
== 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.
////