/* * Copyright 2005 by Oracle USA * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A. * All rights reserved. */ package javax.ide.editor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.ide.model.Document; import javax.ide.Service; import javax.ide.spi.ProviderNotFoundException; import javax.ide.command.Context; import javax.ide.editor.spi.EditorHook; import javax.ide.extension.ExtensionRegistry; import javax.ide.util.MetaClass; /** * The EditorManager manages the life cycle of {@link Editor}s. * It is also the registry of information about what editors can be used with * particular documents.

* * Clients use this class to open an editor on a {@link javax.ide.model.Document}. * When clients request to open an editor on a specific document, the editor * manager performs the following tasks:

* *

* * Similarly, the editor manager {@link #closeEditor} method should be called * by clients to request closing an editor. When closing an editor the * editor manager performs the following tasks:

* *

* * Extensions that need to know when editors are opened, closed, activated, * and/or deactivated can add {@link EditorListener}s to the editor manager. * Listener implementations are declared in the editor-listener * section of the extension manifest.

* * IDE service providers must provide a concrete implementation of this class. */ public abstract class EditorManager extends Service { /** * Map of String:List. Keys are ids of editor types, values are lists of * EditorListener. */ private final Map _listenerMap = new HashMap(); private boolean _initializedHookListeners = false; /** * Returns the Editor that is currently active. * * @return the currently active editor, or null if no editor is currently * active. */ public abstract Editor getActiveEditor(); /** * Returns all currently open editors. * * @return a set of Editor instances for all currently open editors. Must not * return null, may return an empty collection. The collection is immutable. */ public abstract Set /**/ getAllOpenEditors(); /** * Get whether the specified document is open. * * @param document a document. Must not be null. * @return true if there is at least one open editor on this document. */ public boolean isOpen( Document document ) { if ( document == null ) { throw new NullPointerException( "document is null." ); } for ( Iterator i = getAllOpenEditors().iterator(); i.hasNext(); ) { Editor thisEditor = (Editor) i.next(); if ( document.equals( thisEditor.getContext().getDocument() ) ) { return true; } } return false; } /** * Get all open editors on a specific document. * * @param document a document instance. Must not be null. * @return an unmodifiable collection of all open editors on the specified * document. Must never be null, but may be empty. */ public Set /**/ getOpenEditors( Document document ) { if ( document == null ) { throw new NullPointerException( "document is null." ); } Set editors = new HashSet(); for ( Iterator i = getAllOpenEditors().iterator(); i.hasNext(); ) { Editor thisEditor = (Editor) i.next(); if ( document.equals( thisEditor.getContext().getDocument() ) ) { editors.add( thisEditor ); } } return Collections.unmodifiableSet( editors ); } /** * Opens a document in the editor identified by the given editor * type identifier. If type is null, the IDE will open the * document with the most appropriate editor.

* * If the document is already open using that editor, the editor will be * made active. * * @param context the context to open an editor for. Must not be null. * @param typeID the id of an editor type to open the context document in. If * null, the IDE will open the document with the default editor. * @return the editor that was opened or activated. * @throws UnsupportedOperationException when the document cannot be * opened by any editor. */ public abstract Editor openEditor( Context context, String typeID ); /** * Close the specified {@link Editor}. * * @param editor The editor to be closed. Must not be null. */ public abstract void closeEditor( Editor editor ); /** * Add an {@link EditorListener}. * * @param listener the {@link EditorListener} to add. Must not be null. * @param editorClass Only events for this class of editor will be dispatched * to the specified listener. May be null, indicating that all editor events * will be dispatched. */ public final void addEditorListener( EditorListener listener, String editorClass ) { if ( listener == null ) { throw new NullPointerException( "listener is null" ); } if ( editorClass == null ) { editorClass = EditorHook.ANY_EDITOR_CLASS; } List listeners = (List) _listenerMap.get( editorClass ); if ( listeners == null ) { listeners = new ArrayList(); _listenerMap.put( editorClass, listeners ); } listeners.add( listener ); } /** * Remove an {@link EditorListener}. * * @param l The {@link EditorListener} to remove. * @param editorClass The class of editors from which listener should be * removed. May be null, indicating that all editor events * will be dispatched. */ public final void removeEditorListener( EditorListener l, String editorClass ) { if ( editorClass == null ) { editorClass = EditorHook.ANY_EDITOR_CLASS; } List listeners = (List) _listenerMap.get( editorClass ); if ( listeners != null ) { listeners.remove( l ); } else { throw new IllegalArgumentException( "No listeners are registered for editor type "+editorClass ); } } private final Collection getListeners( Editor editor ) { initializeHookListeners(); List listeners = (List) _listenerMap.get( editor.getClass().getName() ); List allListeners = (List) _listenerMap.get( EditorHook.ANY_EDITOR_CLASS ); List fullList = new ArrayList(); if ( listeners != null ) { fullList.addAll( listeners ); } if ( allListeners != null ) { fullList.addAll( allListeners ); } return fullList; } /** * Notifies all editor listeners that the specified editor was * opened. * * @param editor the editor which was opened. */ protected final void fireEditorOpened( Editor editor ) { Collection listeners = getListeners( editor ); if ( !listeners.isEmpty() ) { EditorEvent event = new EditorEvent( editor ); for ( Iterator i = listeners.iterator(); i.hasNext(); ) { ((EditorListener)i.next()).opened( event ); } } } /** * Notifies all editor listeners that the specified editor was * closed. * * @param editor the editor which was closed. */ protected final void fireEditorClosed( Editor editor ) { Collection listeners = getListeners( editor ); if ( !listeners.isEmpty() ) { EditorEvent event = new EditorEvent( editor ); for ( Iterator i = listeners.iterator(); i.hasNext(); ) { ((EditorListener)i.next()).closed( event ); } } } /** * Notifies all editor listeners that the specified editor was * activated. * * @param editor the editor which was activated. */ protected final void fireEditorActivated( Editor editor ) { Collection listeners = getListeners( editor ); if ( !listeners.isEmpty() ) { EditorEvent event = new EditorEvent( editor ); for ( Iterator i = listeners.iterator(); i.hasNext(); ) { ((EditorListener)i.next()).activated( event ); } } } /** * Notifies all editor listeners that the specified editor was * deactivated. * * @param editor the editor which was deactivated. */ protected final void fireEditorDeactivated( Editor editor ) { Collection listeners = getListeners( editor ); if ( !listeners.isEmpty() ) { EditorEvent event = new EditorEvent( editor ); for ( Iterator i = listeners.iterator(); i.hasNext(); ) { ((EditorListener)i.next()).deactivated( event ); } } } private void initializeHookListeners() { if ( !_initializedHookListeners ) { try { EditorHook editorHook = (EditorHook) ExtensionRegistry.getExtensionRegistry().getHook( EditorHook.ELEMENT ); Map listeners = editorHook.getListeners(); for ( Iterator i = listeners.keySet().iterator(); i.hasNext(); ) { String key = (String) i.next(); Collection listenerClasses = (Collection) listeners.get( key ); for ( Iterator j = listenerClasses.iterator(); j.hasNext(); ) { MetaClass thisClass = (MetaClass) j.next(); try { EditorListener el = (EditorListener) thisClass.newInstance(); addEditorListener( el, key ); } catch ( Exception e ) { e.printStackTrace(); } } } } finally { _initializedHookListeners = true; } } } /** * Get the editor manager implementation for this IDE. * * @return the editor manager implementation. */ public static EditorManager getEditorManager() { try { return (EditorManager) getService( EditorManager.class ); } catch ( ProviderNotFoundException nse ) { nse.printStackTrace(); throw new IllegalStateException( "No editor manager." ); } } }