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

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

= How do you invoke the View/IDE Log Action programmatically?

Problem: In a NetBeans Platform application, it is conceivable that the Output window's only use could be to show logging messages to the user. In this case, since the Output TopComponent is always persisted, and the IDE log is only attached via an Action, the Action should be invoked whenever the Output window is open.

Solution: We can create an Installer class which will search for the existence of the Output window, and conditionally fire the action which attaches the IDE Log.

=== Waiting for the Windows System to be ready

Installer classes (those that extend ModuleInstall) will fire their restored() methods before the Windows System is available. This is a problem, since we need to be able to interrogate the TopComponent.Registry to determine if the Output window is open.

The answer is to use the WindowManager.getDefault().invokeWhenUIReady() method.

[source,java]
----

    @Override
    public void restored()
    {
        //The TopComponent we're interested in isn't immediately available. 
        //This method allows us to delay start of our procedure until later.
        WindowManager.getDefault().invokeWhenUIReady(new Runnable()
        {
            @Override
            public void run()
            {
                 //Do something
            }
        });
    }
----

=== Finding the Output TopComponent

We find the Output TopComponent by the WindowManager.getDefault().findTopComponent() method. We must know the ID of the TopComponent we are searching for. In this case, it is "output".

[source,java]
----

            @Override
            public void run()
            {
                //Locate the Output Window instance                
                final String OUTPUT_ID = "output";
                TopComponent outputWindow = WindowManager.getDefault().findTopComponent(OUTPUT_ID);
----

=== Determining if the Output window is open

This is easily accomplished by using the methods of the TopComponent class.

[source,java]
----

               if (outputWindow != null &amp;&amp; outputWindow.isOpened())
----

=== Locating our Action from the System Filesystem (Layer)

We can get a Lookup for a portion of the System Filesystem using Lookups.forPath(). Browse your layer file in context to determine where the instance of the action is stored. In our case, it is in Actions/View.

[source,java]
----

                   final String FOLDER = "Actions/View/";
                   Lookup pathLookup = Lookups.forPath(FOLDER);
----

==== Getting the Instance from our Lookup

Now that we have a lookup to the appropriate folder of the System Filesystem, we need to know the instance file name of the Action we want to retrieve and invoke. We get this information from browsing our layer file in context. In our case, it is "org-netbeans-core-actions-LogAction".
We then invoke actionPerformed() to fire the action.

[source,java]
----

Action a = FileUtil.getConfigObject("Actions/org-netbeans-core-actions-LogAction.instance", Action.class);
if (a != null) {
    action.actionPerformed(null);
}
----

== Putting it all together

Here is the completed Installer class, with logging.

[source,java]
----

/**
 * This class makes it so that the action View/IDE-Logs is performed upon startup
 * whenever the Output window is open.
 */
public class ViewLogsInstaller extends ModuleInstall
{
    private static final Logger logger = Logger.getLogger(ViewLogsInstaller.class.getName(), ViewLogsInstaller.class.getPackage().getName() + ".Log");

    @Override
    public void restored()
    {
        //The TopComponent we're interested in isn't immediately available. 
        //This method allows us to delay start of our procedure until later.
        WindowManager.getDefault().invokeWhenUIReady(new Runnable()
        {
            @Override
            public void run()
            {
                //Locate the Output Window instance                
                final String OUTPUT_ID = "output";
                logger.log(Level.FINE, "LOG_FindingWindow", OUTPUT_ID);
                TopComponent outputWindow = WindowManager.getDefault().findTopComponent(OUTPUT_ID);
                
                //Determine if it is opened
                if (outputWindow != null &amp;&amp; outputWindow.isOpened())
                {
                    logger.log(Level.FINE, "LOG_WindowOpen", OUTPUT_ID);
                    final String FOLDER = "Actions/View/";
                    final String INSTANCE_FILE = "org-netbeans-core-actions-LogAction";

                    //Use Lookup to find the instance in the file system
                    logger.log(Level.FINE, "LOG_LookupAction", new Object[]{FOLDER, INSTANCE_FILE});
                    Lookup pathLookup = Lookups.forPath(FOLDER);
                    Template<Action> actionTemplate = new Template<Action>(Action.class, FOLDER + INSTANCE_FILE, null);
                    Result<Action> lookupResult = pathLookup.lookup(actionTemplate);
                    Collection<? extends Action> foundActions = lookupResult.allInstances();
                    
                    //For each instance (should ony be one) call actionPerformed()
                    for (Action action : foundActions)
                    {
                        logger.log(Level.FINE, "LOG_FoundAction", action);
                        action.actionPerformed(null);
                    } 
                }
                else
                {
                    logger.log(Level.FINE, "LOG_WindowClosed", OUTPUT_ID);
                }
            }
        });
    }
}
----

=== Log.properties file

Place this file in the root package of your installer.

[source,java]
----

LOG_FindingWindow=Attempting to locate TopComponent with ID ''{0}''
LOG_WindowOpen=TopComponent with ID ''{0}'' is open
LOG_LookupAction=Attempting to find Action instance at {0}{1}
LOG_FoundAction=Found Action ''{0}''; calling actionPerformed()
LOG_WindowClosed=TopComponent with ID ''{0}'' is closed or not instantiated
----

=== 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/DevFaqLogActionStartup[http://wiki.netbeans.org/DevFaqLogActionStartup] , 
that was last modified by NetBeans user Jglick 
on 2011-12-14T00:23:24Z.


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