// 
//     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 do I identify the "main project"?
:jbake-type: wikidev
:jbake-tags: wiki, devfaq, needsreview
:jbake-status: published
:keywords: Apache NetBeans wiki DevFaqIdentifyMain
:description: Apache NetBeans wiki DevFaqIdentifyMain
:toc: left
:toc-title:
:syntax: true
:wikidevsection: _project_types
:position: 5

[source,java]
----

Project mainProject = org.netbeans.api.project.ui.OpenProjects.getDefault().getMainProject();
----

For this, you need to declare dependencies on Project UI API, Project API and File System API.

As an example usage of the above line of code, here is an action that display a JOptionPane containing the path to the main project, if a project is selected:

[source,java]
----

public final class ShowMainProjectAction extends CookieAction {

    protected void performAction(Node[] activatedNodes) {
        String projectPath = OpenProjects.getDefault().getMainProject().getProjectDirectory().getPath();
        JOptionPane.showMessageDialog(null, projectPath);
    }

    protected int mode() {
        return CookieAction.MODE_EXACTLY_ONE;
    }

    public String getName() {
        return NbBundle.getMessage(ShowMainProjectAction.class, "CTL_ShowMainProjectAction");
    }

    protected Class[] cookieClasses() {
        return new Class[]{Project.class};
    }

    @Override
    protected void initialize() {
        super.initialize();
        // see org.openide.util.actions.SystemAction.iconResource() Javadoc for more details
        putValue("noIconInMenu", Boolean.TRUE);
    }

    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }

    @Override
    protected boolean asynchronous() {
        return false;
    }
}
----

////
== 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/DevFaqIdentifyMain[http://wiki.netbeans.org/DevFaqIdentifyMain] , 
that was last modified by NetBeans user Admin 
on 2009-11-06T15:46:33Z.


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