This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 182698
Collapse All | Expand All

(-)1f7b91420663 (+5 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="api.menus">
3
    <description>Builds, tests, and runs the project org.netbeans.api.menus</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)1f7b91420663 (+7 lines)
Added Link Here
1
Manifest-Version: 1.0
2
AutoUpdate-Show-In-Client: false
3
OpenIDE-Module: org.netbeans.api.menus/1
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/menus/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.0
6
OpenIDE-Module-Recommends: org.netbeans.api.menus.MenuProvider
7
(-)1f7b91420663 (+4 lines)
Added Link Here
1
is.autoload=true
2
javac.source=1.6
3
javac.compilerargs=-Xlint -Xlint:-serial
4
nbm.module.author=Tim Boudreau
(-)1f7b91420663 (+30 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.api.menus</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.openide.util</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <specification-version>8.2</specification-version>
14
                    </run-dependency>
15
                </dependency>
16
                <dependency>
17
                    <code-name-base>org.openide.util.lookup</code-name-base>
18
                    <build-prerequisite/>
19
                    <compile-dependency/>
20
                    <run-dependency>
21
                        <specification-version>8.2</specification-version>
22
                    </run-dependency>
23
                </dependency>
24
            </module-dependencies>
25
            <public-packages>
26
                <package>org.netbeans.api.menus</package>
27
            </public-packages>
28
        </data>
29
    </configuration>
30
</project>
(-)1f7b91420663 (+7 lines)
Added Link Here
1
OpenIDE-Module-Display-Category=Infrastructure
2
OpenIDE-Module-Long-Description=\
3
    API which allows another module to inject a factory which creates the main window's menu bar.
4
OpenIDE-Module-Name=Main Menu API
5
FILE_MENU=File
6
EXIT_MENU_ITEM=Exit
7
OpenIDE-Module-Short-Description=API for generating the application's menu(s)
(-)1f7b91420663 (+142 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.api.menus;
40
41
import java.awt.EventQueue;
42
import java.awt.event.ActionEvent;
43
import java.util.logging.Level;
44
import java.util.logging.Logger;
45
import javax.swing.AbstractAction;
46
import javax.swing.Action;
47
import javax.swing.JFrame;
48
import javax.swing.JMenu;
49
import javax.swing.JMenuBar;
50
import org.openide.LifecycleManager;
51
import org.openide.util.Exceptions;
52
import org.openide.util.Lookup;
53
import org.openide.util.NbBundle;
54
import org.openide.util.Parameters;
55
56
/**
57
 * Factory for the application window main menu.  Registered in the default
58
 * lookup.
59
 *
60
 * @author Tim Boudreau
61
 * @since 1.0
62
 */
63
public abstract class MenuProvider {
64
65
    /**
66
     * Install a menu in a JFrame.  Called by the window system to set up the
67
     * main menu.  This method is not guaranteed to return the same JMenuBar
68
     * if called repeatedly, and should not be used as a way to look up the
69
     * main window's menu.
70
     * <p/>
71
     * This method must be called on the AWT event dispatch thread.
72
     * <p/>
73
     * If no MenuProvider is registered in the default lookup, will create a
74
     * menu which simply contains a File menu with an Exit menu item that
75
     * uses LifecycleManager to cleanly exit the application.
76
     *
77
     * @param frame A JFrame.  May not be null.
78
     * @return The JMenuBar which has been installed in the frame.
79
     */
80
    public static JMenuBar installMenu(JFrame frame) {
81
        Parameters.notNull("frame", frame); //NOI18N
82
        if (!EventQueue.isDispatchThread()) {
83
            throw new IllegalStateException("Not on event thread"); //NOI18N
84
        }
85
        MenuProvider p = Lookup.getDefault().lookup(MenuProvider.class);
86
        JMenuBar menu = p == null ? fallbackMenu() : p.createMenu(frame);
87
        if (p == null) {
88
            Logger.getLogger(MenuProvider.class.getName()).log (Level.WARNING,
89
                    "No instance of {0} registered in the default lookup. " + //NOI18N
90
                    "Using fallback.", MenuProvider.class.getName()); //NOI18N
91
        }
92
        if (menu == null) {
93
            if (p != null) {
94
                Exceptions.printStackTrace(new NullPointerException(p
95
                    + " returned null menu")); //NOI18N
96
            }
97
            menu = fallbackMenu();
98
        }
99
        frame.setJMenuBar(menu);
100
        return menu;
101
    }
102
103
    private static JMenuBar fallbackMenu() {
104
        String fileMenuName = NbBundle.getMessage(MenuProvider.class,
105
                "FILE_MENU"); //NOI18N
106
        String exitItemName = NbBundle.getMessage(MenuProvider.class,
107
                "EXIT_MENU_ITEM"); //NOI18N
108
        JMenuBar result = new JMenuBar();
109
        JMenu fileMenu = new JMenu(fileMenuName);
110
        Action exitAction = new ExitAction();
111
        exitAction.putValue(Action.NAME, exitItemName);
112
        fileMenu.add(exitAction);
113
        result.add(fileMenu);
114
        return result;
115
    }
116
117
    /**
118
     * Create a menu for the provided JFrame.  This method is not expected
119
     * to cache the return value.  It should not actually call the target frame's
120
     * <code>setJMenuBar()</code> method - the target frame is provided as a
121
     * convenience in case some multi-frame application provides menus for
122
     * multiple frames.
123
     * <p/>
124
     * This method will only be called by NetBeans from the event dispatch thread.
125
     * Constructing components is safe here, but it is preferable not to perform
126
     * heavy-duty I/O in this method, but rather to create the initial menu bar
127
     * quickly, and then populate its menus lazily or in the background.
128
     * <p/>
129
     * @param target The frame the menu should be created for
130
     * @since 1.0
131
     * @return A JMenuBar
132
     */
133
    protected abstract JMenuBar createMenu(JFrame target);
134
135
    private static final class ExitAction extends AbstractAction {
136
137
        @Override
138
        public void actionPerformed(ActionEvent e) {
139
            LifecycleManager.getDefault().exit();
140
        }
141
    }
142
}
(-)1f7b91420663 (+5 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="core.menu">
3
    <description>Builds, tests, and runs the project org.netbeans.core.menu</description>
4
    <import file="../nbbuild/templates/projectized.xml"/>
5
</project>
(-)1f7b91420663 (+7 lines)
Added Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.core.menu
3
OpenIDE-Module-Layer: org/netbeans/core/menu/layer.xml
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/core/menu/Bundle.properties
5
OpenIDE-Module-Specification-Version: 1.0
6
OpenIDE-Module-Provides: org.netbeans.api.menus.MenuProvider
7
(-)1f7b91420663 (+2 lines)
Added Link Here
1
javac.source=1.6
2
javac.compilerargs=-Xlint -Xlint:-serial
(-)1f7b91420663 (+83 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.core.menu</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.netbeans.api.menus</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.0</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.openide.awt</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <specification-version>7.21</specification-version>
23
                    </run-dependency>
24
                </dependency>
25
                <dependency>
26
                    <code-name-base>org.openide.filesystems</code-name-base>
27
                    <build-prerequisite/>
28
                    <compile-dependency/>
29
                    <run-dependency>
30
                        <specification-version>7.37</specification-version>
31
                    </run-dependency>
32
                </dependency>
33
                <dependency>
34
                    <code-name-base>org.openide.loaders</code-name-base>
35
                    <build-prerequisite/>
36
                    <compile-dependency/>
37
                    <run-dependency>
38
                        <specification-version>7.13</specification-version>
39
                    </run-dependency>
40
                </dependency>
41
                <dependency>
42
                    <code-name-base>org.openide.nodes</code-name-base>
43
                    <build-prerequisite/>
44
                    <compile-dependency/>
45
                    <run-dependency>
46
                        <specification-version>7.14</specification-version>
47
                    </run-dependency>
48
                </dependency>
49
                <dependency>
50
                    <code-name-base>org.openide.util</code-name-base>
51
                    <build-prerequisite/>
52
                    <compile-dependency/>
53
                    <run-dependency>
54
                        <specification-version>8.2</specification-version>
55
                    </run-dependency>
56
                </dependency>
57
                <dependency>
58
                    <code-name-base>org.openide.util.lookup</code-name-base>
59
                    <build-prerequisite/>
60
                    <compile-dependency/>
61
                    <run-dependency>
62
                        <specification-version>8.2</specification-version>
63
                    </run-dependency>
64
                </dependency>
65
            </module-dependencies>
66
            <test-dependencies>
67
                <test-type>
68
                    <name>unit</name>
69
                    <test-dependency>
70
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
71
                        <compile-dependency/>
72
                    </test-dependency>
73
                    <test-dependency>
74
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
75
                        <recursive/>
76
                        <compile-dependency/>
77
                    </test-dependency>
78
                </test-type>
79
            </test-dependencies>
80
            <public-packages/>
81
        </data>
82
    </configuration>
83
</project>
(-)1f7b91420663 (+125 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.io.IOException;
43
import javax.swing.Action;
44
import javax.swing.JCheckBoxMenuItem;
45
import javax.swing.JMenuItem;
46
import org.openide.awt.AcceleratorBinding;
47
import org.openide.awt.Actions;
48
import org.openide.awt.Mnemonics;
49
import org.openide.loaders.DataObject;
50
import org.openide.util.Exceptions;
51
import org.openide.util.actions.BooleanStateAction;
52
import org.openide.util.actions.Presenter;
53
import org.openide.util.actions.SystemAction;
54
55
/**
56
 *
57
 * @author Tim Boudreau
58
 */
59
final class ActionModelEntry extends ThreadUnconstrainedModelEntry<Action, JMenuItem> {
60
    ActionModelEntry(DataObject dob) {
61
        super (dob, JMenuItem.class, Action.class);
62
    }
63
64
    @Override
65
    protected JMenuItem refreshComponent(JMenuItem old) {
66
        Action a;
67
        try {
68
            a = get();
69
            if (old.getAction() == a) {
70
                configureName (a, old);
71
            }
72
        } catch (IOException ex) {
73
            Exceptions.printStackTrace(ex);
74
        } catch (ClassNotFoundException ex) {
75
            Exceptions.printStackTrace(ex);
76
        }
77
        return old;
78
    }
79
80
    private String getActionName(Action action) {
81
        String name = (String) action.getValue(Action.NAME);
82
        if (name == null && action instanceof SystemAction) {
83
            name = ((SystemAction) action).getName();
84
        }
85
        name = name == null ? getName() : name;
86
        return name;
87
    }
88
89
    private void configureName (Action action, JMenuItem item) {
90
        String txt = item.getText();
91
        if (txt == null || txt.length() == 0) {
92
            Mnemonics.setLocalizedText(item, getActionName(action));
93
            item.setToolTipText(null);
94
        }
95
    }
96
97
    @Override
98
    protected JMenuItem findComponent() {
99
        try {
100
            Action action = get();
101
            if (action instanceof Presenter.Menu) {
102
                throw new IllegalStateException("ActionModelEntry used for a menu presenter action");
103
            }
104
            JMenuItem item;
105
            if (action instanceof BooleanStateAction) {
106
                BooleanStateAction bse = (BooleanStateAction) action;
107
                JCheckBoxMenuItem cbItem = new JCheckBoxMenuItem();
108
                configureName (action, cbItem);
109
                Actions.connect(cbItem, bse, false);
110
                item = cbItem;
111
            } else {
112
                item = new JMenuItem();
113
                configureName (action, item);
114
                Actions.connect (item, action);
115
            }
116
            AcceleratorBinding.setAccelerator(action, file().getPrimaryFile());
117
            return item;
118
        } catch (IOException ex) {
119
            Exceptions.printStackTrace(ex);
120
        } catch (ClassNotFoundException ex) {
121
            Exceptions.printStackTrace(ex);
122
        }
123
        return new JMenuItem("Error from " + file().getName()); //XXX
124
    }
125
}
(-)1f7b91420663 (+1 lines)
Added Link Here
1
OpenIDE-Module-Name=Core Main Menu
(-)1f7b91420663 (+50 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.core.menu;
40
41
/**
42
 *
43
 * @author Tim Boudreau
44
 */
45
interface Callback {
46
47
    void onShow(ModelEntry<?, ?> entry);
48
49
    void onHide(ModelEntry<?, ?> entry);
50
}
(-)1f7b91420663 (+178 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.Component;
43
import java.lang.ref.Reference;
44
import java.lang.ref.WeakReference;
45
import java.util.Arrays;
46
import javax.swing.JComponent;
47
import javax.swing.JSeparator;
48
import org.openide.util.Parameters;
49
50
/**
51
 * Wrapper for an array of components which can be checked for value equality.
52
 *
53
 * @author Tim Boudreau
54
 */
55
final class ComponentList {
56
    private final JComponent[] comps;
57
    private final Reference<?>[] refs;
58
    private volatile boolean isWeak;
59
    ComponentList(JComponent[] comps) {
60
        Parameters.notNull("comps", comps);
61
        this.comps = new JComponent[comps.length];
62
        refs = new Reference<?>[comps.length];
63
        for (int i= 0; i < comps.length; i++) {
64
            if (comps[i] == null) {
65
                this.comps[i] = new JSeparator();
66
            } else {
67
                this.comps[i] = comps[i];
68
            }
69
            refs[i] = new WeakReference<Component>(this.comps[i]);
70
        }
71
    }
72
73
    JComponent get (int ix) {
74
        JComponent result = comps[ix];
75
        if (comps[ix] == null) {
76
            result = refs[ix] == null ? null : (JComponent) refs[ix].get();
77
        }
78
        return result;
79
    }
80
81
    private void set (int ix, JComponent comp) {
82
        Parameters.notNull("comp", comp); //NOI18N
83
        comps[ix] = comp;
84
        refs[ix] = new WeakReference<JComponent>(comps[ix]);
85
    }
86
87
    int size() {
88
        return comps.length;
89
    }
90
91
    public JComponent[] getComponents() {
92
        JComponent[] result = new JComponent[size()];
93
        for (int i= 0; i < result.length; i++) {
94
            result[i] = get(i);
95
        }
96
        return result;
97
    }
98
99
    boolean addNotify() {
100
        boolean result = false;
101
        if (!result) {
102
            result = true;
103
            for (int i= 0; i < comps.length; i++) {
104
                if (comps[i] == null) {
105
                    comps[i] = refs[i] == null ? null : (JComponent) refs[i].get();
106
                    if (comps[i] == null) {
107
                        result = false;
108
                    }
109
                }
110
            }
111
        }
112
        isWeak = result;
113
        return result;
114
    }
115
116
    void removeNotify() {
117
//        if (!isWeak) {
118
            for (int i = 0; i < comps.length; i++) {
119
                comps[i] = null;
120
            }
121
//        }
122
        isWeak = true;
123
    }
124
125
    boolean repair (JComponent[] nue) {
126
        Parameters.notNull("nue", nue);
127
        if (nue.length != comps.length) {
128
            return false;
129
        }
130
        boolean result = true;
131
        for (int i= 0; i < comps.length; i++) {
132
            JComponent c = get(i);
133
            if (c == null || c == nue[i]) {
134
                if (nue[i] == null) {
135
                    throw new NullPointerException ("Null element in component " + //NOI18N
136
                            "list at " + i); //NOI18N
137
                }
138
                set (i, nue[i]);
139
            } else {
140
                result = false;
141
            }
142
        }
143
        return result;
144
    }
145
146
    @Override
147
    public boolean equals(Object obj) {
148
        if (obj == null || obj.getClass() != ComponentList.class) {
149
            return false;
150
        }
151
        final ComponentList other = (ComponentList) obj;
152
        if (other == this) {
153
            return true;
154
        }
155
        if (other.comps == comps) {
156
            return true;
157
        }
158
        if (other.comps.length != comps.length) {
159
            return false;
160
        }
161
        for (int i=0; i < comps.length; i++) {
162
            //test only on exact equality
163
            JComponent a = get(i);
164
            JComponent b = other.get(i);
165
            if (a != b) {
166
                return false;
167
            }
168
        }
169
        return true;
170
    }
171
172
    @Override
173
    public int hashCode() {
174
        int hash = 7;
175
        hash = 97 * hash + Arrays.deepHashCode(this.comps);
176
        return hash;
177
    }
178
}
(-)1f7b91420663 (+82 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.Component;
43
import java.io.IOException;
44
import java.util.List;
45
import javax.swing.JComponent;
46
import javax.swing.JMenuItem;
47
import org.openide.loaders.DataObject;
48
import org.openide.util.Exceptions;
49
50
/**
51
 *
52
 * @author Tim Boudreau
53
 */
54
final class ComponentModelEntry extends FileModelEntry <JComponent, JComponent> {
55
    ComponentModelEntry (DataObject dob) {
56
        super (dob, JComponent.class, JComponent.class);
57
    }
58
59
    @Override
60
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
61
        return false;
62
    }
63
64
    @Override
65
    protected JComponent findComponent() {
66
        try {
67
            return get();
68
        } catch (IOException ex) {
69
            Exceptions.printStackTrace(ex);
70
        } catch (ClassNotFoundException ex) {
71
            Exceptions.printStackTrace(ex);
72
        }
73
        return new JMenuItem("Error getting comp for " + getName());
74
    }
75
76
    @Override
77
    protected JComponent refreshComponent(JComponent old) {
78
        return old;
79
    }
80
81
82
}
(-)1f7b91420663 (+85 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.io.IOException;
43
import javax.swing.JComponent;
44
import javax.swing.JMenuItem;
45
import org.openide.awt.DynamicMenuContent;
46
import org.openide.loaders.DataObject;
47
import org.openide.util.Exceptions;
48
49
/**
50
 *
51
 * @author Tim Boudreau
52
 */
53
public class DynamicModelEntry extends ThreadUnconstrainedModelEntry<DynamicMenuContent, JComponent> {
54
    DynamicModelEntry(DataObject dob) {
55
        super (dob, JComponent.class, DynamicMenuContent.class);
56
    }
57
58
    @Override
59
    protected JComponent[] findComponents() {
60
        try {
61
            DynamicMenuContent dyn = get();
62
            JComponent[] result = dyn.getMenuPresenters();
63
            //Necessary the first time, or we get bogus elements
64
            dyn.synchMenuPresenters(result);
65
            return result;
66
        } catch (IOException ex) {
67
            Exceptions.printStackTrace(ex);
68
        } catch (ClassNotFoundException ex) {
69
            Exceptions.printStackTrace(ex);
70
        }
71
        return new JComponent[] { new JMenuItem("Error getting " + file().getName()) }; //XXX
72
    }
73
74
    @Override
75
    protected JComponent[] refresh(JComponent[] old) {
76
        try {
77
            return get().synchMenuPresenters(old);
78
        } catch (IOException ex) {
79
            Exceptions.printStackTrace(ex);
80
        } catch (ClassNotFoundException ex) {
81
            Exceptions.printStackTrace(ex);
82
        }
83
        return old;
84
    }
85
}
(-)1f7b91420663 (+130 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.Component;
43
import java.awt.EventQueue;
44
import java.io.IOException;
45
import javax.swing.JComponent;
46
import org.openide.cookies.InstanceCookie;
47
import org.openide.loaders.DataFolder;
48
import org.openide.loaders.DataObject;
49
50
/**
51
 *
52
 * @author Tim Boudreau
53
 */
54
abstract class FileModelEntry<T, CompType extends JComponent> extends ModelEntry <CompType, DataObject> {
55
    protected final Class<T> modelObjectType;
56
    FileModelEntry(DataObject dob, Class<CompType> componentType, Class<T> modelObjectType) {
57
        super (dob, DataObject.class, componentType);
58
        this.modelObjectType = modelObjectType;
59
        assert !(dob instanceof DataFolder) : "Folder used for menu item"; //NOI18N
60
    }
61
62
    private final InstanceCookie cookie() {
63
        DataObject dob = file();
64
        InstanceCookie ck = dob.getLookup().lookup(InstanceCookie.class);
65
        if (ck == null) {
66
            ck = new EmptyInstanceCookie(dob.getName());
67
        }
68
        return ck;
69
    }
70
71
    final boolean requiresEq() {
72
        return Component.class.isAssignableFrom(dobType);
73
    }
74
75
    protected T get() throws IOException, ClassNotFoundException {
76
        if (requiresEq() && !EventQueue.isDispatchThread()) {
77
            throw new IllegalStateException ("Not on event thread");
78
        }
79
        return modelObjectType.cast(cookie().instanceCreate());
80
    }
81
82
    private static final class EmptyInstanceCookie implements InstanceCookie, InstanceCookie.Of {
83
        private final String name;
84
        EmptyInstanceCookie (String name) {
85
            this.name = name;
86
        }
87
88
        @Override
89
        public String instanceName() {
90
            return name;
91
        }
92
93
        @Override
94
        public Class<?> instanceClass() throws IOException, ClassNotFoundException {
95
            return Object.class;
96
        }
97
98
        @Override
99
        public Object instanceCreate() throws IOException, ClassNotFoundException {
100
            return null;
101
        }
102
103
        @Override
104
        public boolean instanceOf(Class<?> type) {
105
            return false;
106
        }
107
108
        @Override
109
        public boolean equals(Object obj) {
110
            if (obj == null) {
111
                return false;
112
            }
113
            if (getClass() != obj.getClass()) {
114
                return false;
115
            }
116
            final EmptyInstanceCookie other = (EmptyInstanceCookie) obj;
117
            if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
118
                return false;
119
            }
120
            return true;
121
        }
122
123
        @Override
124
        public int hashCode() {
125
            int hash = 7;
126
            hash = 17 * hash + (this.name != null ? this.name.hashCode() : 0);
127
            return hash;
128
        }
129
    }
130
}
(-)1f7b91420663 (+336 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.core.menu;
40
41
import java.awt.Component;
42
import java.awt.EventQueue;
43
import java.io.IOException;
44
import java.util.ArrayList;
45
import java.util.Arrays;
46
import java.util.HashMap;
47
import java.util.HashSet;
48
import java.util.Iterator;
49
import java.util.LinkedList;
50
import java.util.List;
51
import java.util.Map;
52
import java.util.Set;
53
import javax.swing.Action;
54
import javax.swing.JComponent;
55
import javax.swing.JSeparator;
56
import org.openide.awt.DynamicMenuContent;
57
import org.openide.cookies.InstanceCookie;
58
import org.openide.loaders.DataFolder;
59
import org.openide.loaders.DataObject;
60
import org.openide.util.Exceptions;
61
import org.openide.util.Parameters;
62
import org.openide.util.actions.Presenter;
63
64
/**
65
 *
66
 * @author Tim Boudreau
67
 */
68
abstract class FolderModelEntry<CompType extends JComponent> extends ModelEntry<CompType, DataFolder> implements Callback {
69
70
    private final List<ModelEntry<?, ?>> children = new ArrayList<ModelEntry<?, ?>>(15);
71
    private final Object childLock = new Object();
72
    private final Object mapLock = new Object();
73
    private final Map<ModelEntry<?, ?>, ComponentList> comps4model =
74
            new HashMap<ModelEntry<?, ?>, ComponentList>();
75
76
    FolderModelEntry(DataFolder fld, Class<CompType> compType) {
77
        super(fld, DataFolder.class, compType);
78
    }
79
80
    boolean setChildren(List<ModelEntry<?, ?>> l) {
81
        boolean result;
82
        synchronized (childLock) {
83
            result = !children.equals(l);
84
            if (result) {
85
                children.clear();
86
                children.addAll(l);
87
            }
88
        }
89
        synchronized (mapLock) {
90
            if (!comps4model.isEmpty()) {
91
                Set<ModelEntry<?,?>> known = new HashSet<ModelEntry<?, ?>>(comps4model.keySet());
92
                known.removeAll(l);
93
                for (ModelEntry<?,?> m : known) {
94
                    comps4model.remove(m);
95
                }
96
            }
97
        }
98
        return result;
99
    }
100
101
    @Override
102
    public final void onHide(ModelEntry<?, ?> entry) {
103
        synchronized (mapLock) {
104
            for (Map.Entry<ModelEntry<?,?>, ComponentList> e : comps4model.entrySet()) {
105
                e.getValue().removeNotify();
106
            }
107
        }
108
    }
109
110
    @Override
111
    public final void onShow(ModelEntry<?, ?> entry) {
112
        synchronized (mapLock) {
113
            for (Map.Entry<ModelEntry<?,?>, ComponentList> e : comps4model.entrySet()) {
114
                e.getValue().addNotify();
115
            }
116
        }
117
    }
118
119
    private ComponentList components(ModelEntry<?,?> e) {
120
        Parameters.notNull("e", e);
121
        synchronized (mapLock) {
122
            return comps4model.get(e);
123
        }
124
    }
125
126
    private void setComponents (ModelEntry<?,?> e, ComponentList comps) {
127
        Parameters.notNull("comps", comps);
128
        Parameters.notNull("e", e);
129
        synchronized (mapLock) {
130
            if (comps == null) {
131
                comps4model.remove(e);
132
            } else {
133
                comps4model.put(e, comps);
134
            }
135
        }
136
    }
137
138
    List<ModelEntry<?, ?>> children() {
139
        synchronized (childLock) {
140
            return new ArrayList<ModelEntry<?, ?>>(children);
141
        }
142
    }
143
144
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
145
        //do nothing - for subclasses to force init
146
    }
147
148
    @Override
149
    protected boolean initBackground(List<? super ModelEntry<?, ?>> children) {
150
//        System.err.println("initBackground " + getName());
151
        DataFolder fld = file();
152
        boolean changed = true;
153
        Set<ModelEntry<?, ?>> created = new HashSet<ModelEntry<?, ?>>();
154
        try {
155
            DataObject[] ch = fld.getChildren();
156
            if (ch != null) { //can be null
157
                outer:
158
                for (DataObject dob : ch) {
159
                    try {
160
                        for (Types t : Types.values()) {
161
                            if (t.accept(dob)) {
162
                                ModelEntry<?, ?> e = t.createEntry(dob, this);
163
                                created.add(e);
164
                                children.add(e);
165
                                //XXX defer or batch afterward?
166
                                List<ModelEntry<?, ?>> kids = new ArrayList<ModelEntry<?, ?>>();
167
                                boolean hasKids = e.initBackground(kids);
168
                                changed |= hasKids;
169
                                if (hasKids) {
170
                                    if (e instanceof FolderModelEntry) {
171
                                        FolderModelEntry<?> fme = FolderModelEntry.class.cast(e);
172
                                        changed |= fme.setChildren(kids);
173
                                    }
174
                                }
175
                                continue outer;
176
                            }
177
                        }
178
//                        System.err.println("No type accepted " + dob.getPrimaryFile().getPath() + " : " + ic(dob));
179
                    } catch (IOException ex) {
180
                        Exceptions.printStackTrace(ex);
181
                    } catch (ClassNotFoundException ex) {
182
                        Exceptions.printStackTrace(ex);
183
                    }
184
                }
185
            }
186
        } finally {
187
            onInitBackground(children);
188
        }
189
        return changed;
190
    }
191
192
//    private static String ic(DataObject dob) throws ClassNotFoundException, IOException {
193
//        InstanceCookie ck = dob.getCookie(InstanceCookie.class);
194
//        return ck == null ? " [no ic]" : ck.instanceClass().getName();
195
//    }
196
    @Override
197
    protected CompType refreshComponent(CompType old) {
198
        if (!EventQueue.isDispatchThread()) {
199
            throw new IllegalStateException("Not on event thread");
200
        }
201
//        long start = System.currentTimeMillis();
202
        Parameters.notNull("old", old);
203
        old.removeAll();
204
        List<JComponent> all = new LinkedList<JComponent>();
205
        List<ModelEntry<?, ?>> kids = children();
206
        Boolean expectHasIcon = false;
207
        for (ModelEntry<?, ?> e : kids) {
208
            ComponentList c = components(e);
209
            JComponent[] comps;
210
            if (c == null) {
211
                comps = e.getComponents();
212
                if (comps != null) {
213
                    all.addAll(Arrays.asList(comps));
214
                    setComponents(e, c = new ComponentList(comps));
215
                }
216
            } else {
217
                boolean allStillAlive = c.addNotify();
218
                if (allStillAlive) {
219
                    comps = e.refresh(c.getComponents());
220
                    ComponentList newComps;
221
                    if (comps != null && !((newComps = new ComponentList(comps)).equals(c))) {
222
                        setComponents(e, newComps);
223
                        c = newComps;
224
                    }
225
                } else {
226
                    comps = e.findComponents();
227
                    boolean fixed = c.repair(comps);
228
                    if (!fixed) {
229
                        setComponents(e, c = new ComponentList(comps));
230
                    }
231
                }
232
            }
233
            if (comps != null) {
234
                for (JComponent comp : comps) {
235
                    expectHasIcon = ModelEntry.defaultHasIcon(comp, expectHasIcon);
236
                }
237
            }
238
            if (c != null) {
239
                all.addAll(Arrays.asList(c.getComponents()));
240
            }
241
        }
242
        pruneSeparatorsAndFixIcons(all, expectHasIcon);
243
        installComponents(all, old);
244
//        long dur = System.currentTimeMillis() - start;
245
//        System.err.println("Refresh " + getName() + " took " + dur + " milliseconds");
246
        return old;
247
    }
248
249
    protected void installComponents(List<? extends JComponent> components, CompType into) {
250
        for (Component c : components) {
251
            if (c == null) {
252
                c = new JSeparator();
253
            }
254
            into.add(c);
255
        }
256
    }
257
258
    private void pruneSeparatorsAndFixIcons(List<JComponent> all, Boolean icons) {
259
        boolean lastWasSep = true;
260
        for (Iterator<JComponent> i = all.iterator(); i.hasNext();) {
261
            JComponent c = i.next();
262
            boolean isSep = c instanceof JSeparator;
263
            if ((lastWasSep && isSep) || (!i.hasNext() && isSep)) {
264
                i.remove();
265
            }
266
            lastWasSep = isSep;
267
            if (icons != null) {
268
                ModelEntry.configureIcon(c, icons);
269
            }
270
        }
271
    }
272
273
    private static enum Types {
274
275
        SEPARATOR(JSeparator.class),
276
        DYNAMIC_MENU_CONTENT(DynamicMenuContent.class),
277
        PRESENTER(Presenter.Menu.class),
278
        MENU,
279
        COMPONENT(Component.class),
280
        ACTION(Action.class);
281
        private final Class<?> type;
282
283
        Types(Class<?> type) {
284
            this.type = type;
285
        }
286
287
        Types() {
288
            this(Object.class);
289
        }
290
291
        boolean accept(DataObject dob) throws IOException, ClassNotFoundException {
292
            if (this == MENU) {
293
                DataFolder fld = dob instanceof DataFolder ? (DataFolder) dob
294
                        : dob.getLookup().lookup(DataFolder.class);
295
                return fld != null;
296
            }
297
            InstanceCookie ck = dob.getLookup().lookup(InstanceCookie.class);
298
            return ck instanceof InstanceCookie.Of ? ((InstanceCookie.Of) ck).instanceOf(type)
299
                    : ck == null ? false : type.isAssignableFrom(ck.instanceClass());
300
        }
301
302
        ModelEntry<?, ?> createEntry(DataObject ob, Callback callback) {
303
//            System.err.println("Create " + name() + " entry for " + ob.getPrimaryFile().getPath());
304
            switch (this) {
305
                case SEPARATOR:
306
                    return new SeparatorModelEntry(ob);
307
                case ACTION:
308
                    InstanceCookie ic = ob.getLookup().lookup(InstanceCookie.class);
309
                    try {
310
                        //This is a bit of a mess - some InstanceCookies lie
311
                        if (ic.instanceCreate() instanceof Presenter.Menu) {
312
                            return new PresenterEntry(ob);
313
                        }
314
                    } catch (IOException ex) {
315
                        Exceptions.printStackTrace(ex);
316
                    } catch (ClassNotFoundException ex) {
317
                        Exceptions.printStackTrace(ex);
318
                    }
319
                    return new ActionModelEntry(ob);
320
                case DYNAMIC_MENU_CONTENT:
321
                    return new DynamicModelEntry(ob);
322
                case PRESENTER:
323
                    return new PresenterEntry(ob);
324
                case MENU:
325
                    DataFolder fld = ob instanceof DataFolder ? (DataFolder) ob
326
                            : ob.getLookup().lookup(DataFolder.class);
327
                    Parameters.notNull("folder was non-null but is now null", fld);
328
                    return new MenuEntry(fld, null);
329
                case COMPONENT:
330
                    return new ComponentModelEntry(ob);
331
                default:
332
                    throw new AssertionError(this + "");
333
            }
334
        }
335
    }
336
}
(-)1f7b91420663 (+150 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.EventQueue;
43
import java.util.LinkedList;
44
import java.util.List;
45
import javax.swing.JMenuBar;
46
import org.openide.filesystems.FileAttributeEvent;
47
import org.openide.filesystems.FileChangeAdapter;
48
import org.openide.filesystems.FileEvent;
49
import org.openide.filesystems.FileRenameEvent;
50
import org.openide.loaders.DataFolder;
51
import org.openide.util.RequestProcessor;
52
53
/**
54
 *
55
 * @author Tim Boudreau
56
 */
57
final class MenuBarModel extends FolderModelEntry<JMenuBar> {
58
    private final JMenuBar bar;
59
    private FCA fca = new FCA();
60
    private final RequestProcessor.Task task;
61
    private static final int DELAY = 100;
62
    MenuBarModel (DataFolder rootFolder, JMenuBar bar, RequestProcessor rp) {
63
        super (rootFolder, JMenuBar.class);
64
        this.bar = bar;
65
        this.task = rp.create(fca);
66
        rootFolder.getPrimaryFile().addFileChangeListener(fca);
67
    }
68
69
    void init() {
70
        fca.refresh();
71
    }
72
73
    @Override
74
    protected JMenuBar findComponent() {
75
        return bar;
76
    }
77
78
    @Override
79
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
80
        super.onInitBackground(children);
81
        if (!refreshing) {
82
            EventQueue.invokeLater(fca);
83
        }
84
    }
85
86
    volatile boolean refreshing;
87
    private final class FCA extends FileChangeAdapter implements Runnable {
88
        private volatile boolean enqueued;
89
        boolean refresh() {
90
            boolean result;
91
            synchronized (this) {
92
                result = enqueued;
93
                if (!enqueued) {
94
                    enqueued = true;
95
                    task.schedule(DELAY);
96
                }
97
                return result;
98
            }
99
        }
100
101
        @Override
102
        public void run() {
103
            if (!EventQueue.isDispatchThread()) {
104
                refreshing = true;
105
                try {
106
                    List<ModelEntry<?,?>> l = new LinkedList<ModelEntry<?,?>>();
107
                    initBackground(l);
108
                    setChildren(l);
109
                } finally {
110
                    refreshing = false;
111
                    EventQueue.invokeLater(this);
112
                }
113
            } else {
114
                enqueued = false;
115
                bar.removeAll();
116
                MenuBarModel.this.refresh(new JMenuBar[] { bar });
117
            }
118
        }
119
120
        @Override
121
        public void fileAttributeChanged(FileAttributeEvent fe) {
122
            refresh();
123
        }
124
125
        @Override
126
        public void fileChanged(FileEvent fe) {
127
            refresh();
128
        }
129
130
        @Override
131
        public void fileDataCreated(FileEvent fe) {
132
            refresh();
133
        }
134
135
        @Override
136
        public void fileDeleted(FileEvent fe) {
137
            refresh();
138
        }
139
140
        @Override
141
        public void fileFolderCreated(FileEvent fe) {
142
            refresh();
143
        }
144
145
        @Override
146
        public void fileRenamed(FileRenameEvent fe) {
147
            refresh();
148
        }
149
    }
150
}
(-)1f7b91420663 (+106 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.EventQueue;
43
import java.lang.ref.Reference;
44
import java.lang.ref.WeakReference;
45
import javax.swing.ButtonModel;
46
import javax.swing.JMenu;
47
import javax.swing.event.ChangeEvent;
48
import javax.swing.event.ChangeListener;
49
import org.openide.awt.Mnemonics;
50
import org.openide.loaders.DataFolder;
51
52
/**
53
 *
54
 * @author Tim Boudreau
55
 */
56
final class MenuEntry extends FolderModelEntry<JMenu> implements ChangeListener {
57
58
    private Reference<JMenu> menu;
59
    private final Callback callback;
60
61
    MenuEntry (DataFolder fld, Callback callback) {
62
        super (fld, JMenu.class);
63
        this.callback = callback == null ? this : callback;
64
    }
65
66
    private JMenu menu() {
67
        JMenu result = menu == null ? null : menu.get();
68
        if (result == null) {
69
            result = new JMenu();
70
            Mnemonics.setLocalizedText(result, getName());
71
            result.getModel().addChangeListener(this);
72
            menu = new WeakReference<JMenu> (result);
73
        }
74
        return result;
75
    }
76
77
    @Override
78
    protected JMenu findComponent() {
79
        assert EventQueue.isDispatchThread();
80
        return menu();
81
    }
82
83
    private boolean wasSelected = false;
84
    @Override
85
    public void stateChanged(ChangeEvent e) {
86
        ButtonModel mdl = (ButtonModel) e.getSource();
87
        boolean selected = mdl.isSelected();
88
        //XXX wasSelected could be true if the old component was garbage collected
89
        //without resetting its model - possible?
90
        if (selected && !wasSelected) {
91
            if (callback != null) {
92
                callback.onShow(this);
93
            }
94
            refreshComponent(menu());
95
        } else if (wasSelected && !selected) {
96
            JMenu m = menu == null ? null : menu.get();
97
            if (m != null) {
98
                m.removeAll();
99
            }
100
            if (callback != null) {
101
                callback.onHide(this);
102
            }
103
        }
104
        wasSelected = selected;
105
    }
106
}
(-)1f7b91420663 (+63 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import javax.swing.JMenuBar;
43
import org.openide.loaders.DataFolder;
44
import org.openide.util.RequestProcessor;
45
46
/**
47
 *
48
 * @author Tim Boudreau
49
 */
50
final class MenuManager {
51
    private final JMenuBar bar;
52
    private final RequestProcessor rp = new RequestProcessor("Main Menu Refresh", 1, true);
53
    private final MenuBarModel model;
54
55
    MenuManager(DataFolder folder, JMenuBar bar) {
56
        this.bar = bar;
57
        model = new MenuBarModel (folder, bar, rp);
58
    }
59
60
    void init() {
61
        model.init();
62
    }
63
}
(-)1f7b91420663 (+81 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.EventQueue;
43
import javax.swing.JFrame;
44
import javax.swing.JMenuBar;
45
import org.netbeans.api.menus.MenuProvider;
46
import org.openide.filesystems.FileObject;
47
import org.openide.filesystems.FileUtil;
48
import org.openide.loaders.DataFolder;
49
import org.openide.util.lookup.ServiceProvider;
50
51
/**
52
 *
53
 * @author Tim Boudreau
54
 */
55
@ServiceProvider(service=MenuProvider.class)
56
public final class MenuProviderImpl extends MenuProvider {
57
    private static final String MENU_FOLDER = "Menu"; //NOI18N
58
    private FileObject menuFolder;
59
    public MenuProviderImpl () {
60
        this (FileUtil.getConfigFile(MENU_FOLDER));
61
    }
62
63
    MenuProviderImpl (FileObject menuFolder) { //used in unit tests w/ memfs
64
        this.menuFolder = menuFolder;
65
    }
66
67
    @Override
68
    protected JMenuBar createMenu(JFrame target) {
69
        if (!EventQueue.isDispatchThread()) {
70
            throw new IllegalStateException("Not on event thread"); //NOI18N
71
        }
72
        FileObject menuFO = menuFolder;
73
        DataFolder menuFolder = DataFolder.findFolder(menuFO);
74
        JMenuBar bar = new JMenuBar();
75
        bar.setBorderPainted(false);
76
        MenuManager mgr = new MenuManager(menuFolder, bar);
77
        mgr.init();
78
        return bar;
79
    }
80
81
}
(-)1f7b91420663 (+172 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.EventQueue;
43
import java.lang.reflect.Array;
44
import java.util.List;
45
import javax.swing.Icon;
46
import javax.swing.JComponent;
47
import javax.swing.JMenuItem;
48
import org.openide.loaders.DataObject;
49
import org.openide.util.ImageUtilities;
50
import org.openide.util.Parameters;
51
52
/**
53
 *
54
 * @author Tim Boudreau
55
 */
56
public abstract class ModelEntry<CompType extends JComponent, DataObjectType extends DataObject> {
57
    private final DataObjectType file;
58
    protected final Class<DataObjectType> dobType;
59
    private Class<CompType> compType;
60
    protected static final Icon BLANK_ICON = ImageUtilities.loadImageIcon("org/openide/loaders/empty.gif", false); // NOI18N
61
    public ModelEntry(DataObjectType file, Class<DataObjectType> dobType, Class<CompType> compType) {
62
        this.file = file;
63
        this.dobType = dobType;
64
        this.compType = compType;
65
        Parameters.notNull("compType", compType);
66
        Parameters.notNull("dobType", dobType);
67
        Parameters.notNull("file", file);
68
    }
69
    
70
    protected abstract boolean initBackground(List<? super ModelEntry<?,?>> children);
71
72
    public String getName() {
73
        return file().getNodeDelegate().getDisplayName();
74
    }
75
76
    protected final DataObjectType file() {
77
        return file;
78
    }
79
80
    final Class<CompType> componentType() {
81
        return compType;
82
    }
83
84
    final CompType[] getComponents() {
85
        if (!EventQueue.isDispatchThread()) {
86
            throw new IllegalStateException ("Not on event thread"); //NOI18N
87
        }
88
        return findComponents();
89
    }
90
91
    final CompType[] refreshComponents(CompType[] old) {
92
        if (!EventQueue.isDispatchThread()) {
93
            throw new IllegalStateException ("Not on event thread"); //NOI18N
94
        }
95
        return refresh (old);
96
    }
97
98
    protected CompType[] refresh (CompType[] old) {
99
        return toCompTypeArray(new Object[] { refreshComponent( old.length == 0 ? null : old[0]) });
100
    }
101
102
    protected CompType[] findComponents() {
103
        return toCompTypeArray (new Object[] { findComponent() });
104
    }
105
106
    protected final CompType[] toCompTypeArray(CompType type) {
107
        return toCompTypeArray (new Object[] { type });
108
    }
109
110
    protected final CompType[] toCompTypeArray(Object[] objs) {
111
        CompType[] c = (CompType[]) Array.newInstance(compType, objs == null ? 0 : objs.length);
112
        System.arraycopy(objs, 0, c, 0, objs.length);
113
        return c;
114
    }
115
116
    protected CompType findComponent() {
117
        throw new UnsupportedOperationException("Override findComponent() " + //NOI18N
118
                "or findComponents() in " + getClass().getName()); //NOI18N
119
    }
120
121
    protected CompType refreshComponent(CompType old) {
122
        throw new UnsupportedOperationException("Override refreshComponent() or " + //NOI18N
123
                "refreshComponents() in "  + getClass().getName()); //NOI18N
124
    }
125
126
    protected static void configureIcon (JComponent comp, boolean wantIcons) {
127
        if (comp instanceof JMenuItem) {
128
            JMenuItem item = (JMenuItem) comp;
129
            Icon icon = item.getIcon();
130
            if (!wantIcons && icon != null) {
131
                item.setIcon(null);
132
            } else if (wantIcons && icon == null) {
133
                item.setIcon (BLANK_ICON);
134
            }
135
        }
136
    }
137
138
    protected static Boolean defaultHasIcon (JComponent comp, Boolean hasIcon) {
139
        if (hasIcon != null && hasIcon) {
140
            return hasIcon;
141
        }
142
        if (comp instanceof JMenuItem) {
143
            Icon icon = ((JMenuItem) comp).getIcon();
144
            if (icon != null && BLANK_ICON != icon) {
145
                return true;
146
            }
147
        }
148
        return null;
149
    }
150
151
    @Override
152
    public boolean equals(Object obj) {
153
        if (obj == null) {
154
            return false;
155
        }
156
        if (getClass() != obj.getClass()) {
157
            return false;
158
        }
159
        final ModelEntry<?, ?> other = (ModelEntry<?, ?>) obj;
160
        if (this.file() != other.file() && (this.file() == null || !this.file().equals(other.file()))) {
161
            return false;
162
        }
163
        return true;
164
    }
165
166
    @Override
167
    public int hashCode() {
168
        int hash = 3;
169
        hash = 31 * hash + (this.file != null ? this.file.hashCode() : 0);
170
        return hash;
171
    }
172
}
(-)1f7b91420663 (+86 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.Component;
43
import java.io.IOException;
44
import javax.swing.JComponent;
45
import javax.swing.JMenuItem;
46
import org.openide.awt.DynamicMenuContent;
47
import org.openide.loaders.DataObject;
48
import org.openide.util.Exceptions;
49
import org.openide.util.actions.Presenter;
50
51
/**
52
 *
53
 * @author Tim Boudreau
54
 */
55
public class PresenterEntry extends ThreadUnconstrainedModelEntry<Presenter.Menu, JComponent> {
56
    private DynamicMenuContent dmc;
57
    PresenterEntry (DataObject dob) {
58
        super (dob, JComponent.class, Presenter.Menu.class);
59
    }
60
61
    @Override
62
    protected JComponent[] findComponents() {
63
        try {
64
            Presenter.Menu p = super.get();
65
            JMenuItem c = p.getMenuPresenter();
66
            if (c instanceof DynamicMenuContent) { //ToolsAction.Inline
67
                dmc = (DynamicMenuContent) c;
68
                return dmc.getMenuPresenters();
69
            }
70
            return new JComponent[] { c };
71
        } catch (IOException ex) {
72
            Exceptions.printStackTrace(ex);
73
        } catch (ClassNotFoundException ex) {
74
            Exceptions.printStackTrace(ex);
75
        }
76
        return new JComponent[] { new JMenuItem("Error fetching " + file().getName()) }; //XXX
77
    }
78
79
    @Override
80
    protected JComponent[] refresh(JComponent[] old) {
81
        if (dmc != null) {
82
            return dmc.synchMenuPresenters(old);
83
        }
84
        return old;
85
    }
86
}
(-)1f7b91420663 (+69 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.util.List;
43
import javax.swing.JSeparator;
44
import org.openide.loaders.DataObject;
45
46
/**
47
 *
48
 * @author Tim Boudreau
49
 */
50
final class SeparatorModelEntry extends FileModelEntry <JSeparator, JSeparator> {
51
    SeparatorModelEntry(DataObject dob) {
52
        super (dob, JSeparator.class, JSeparator.class);
53
    }
54
55
    @Override
56
    protected JSeparator findComponent() {
57
        return new JSeparator();
58
    }
59
60
    @Override
61
    protected JSeparator refreshComponent(JSeparator old) {
62
        return old == null ? findComponent() : old;
63
    }
64
65
    @Override
66
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
67
        return false;
68
    }
69
}
(-)1f7b91420663 (+83 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.io.IOException;
43
import java.util.List;
44
import java.util.concurrent.atomic.AtomicReference;
45
import javax.swing.JComponent;
46
import org.openide.loaders.DataObject;
47
import org.openide.util.Exceptions;
48
49
/**
50
 *
51
 * @author Tim Boudreau
52
 */
53
public abstract class ThreadUnconstrainedModelEntry<T, CompType extends JComponent> extends FileModelEntry<T, CompType> {
54
    private final AtomicReference<T> ref = new AtomicReference<T>();
55
56
    ThreadUnconstrainedModelEntry(DataObject dob, Class<CompType> componentType, Class<T> modelObjectType) {
57
        super(dob, componentType, modelObjectType);
58
    }
59
60
    @Override
61
    protected final T get() throws IOException, ClassNotFoundException {
62
        T result = ref.get();
63
        if (result == null) {
64
            result = super.get();
65
            ref.set(result);
66
        }
67
        return result;
68
    }
69
70
    @Override
71
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
72
        //Since it is non-gui, instantiate the Action in the background
73
        try {
74
            ref.set(super.get());
75
        } catch (IOException ex) {
76
            Exceptions.printStackTrace(ex);
77
        } catch (ClassNotFoundException ex) {
78
            Exceptions.printStackTrace(ex);
79
        }
80
        return false;
81
    }
82
83
}
(-)1f7b91420663 (+7 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        
6
    </folder>
7
</filesystem>
(-)1f7b91420663 (+84 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import javax.swing.JComponent;
43
import javax.swing.JMenu;
44
import javax.swing.JMenuItem;
45
import org.openide.awt.DynamicMenuContent;
46
47
/**
48
 *
49
 * @author Tim Boudreau
50
 */
51
public class DynAction implements DynamicMenuContent {
52
    private static final int count = 5;
53
    static int total;
54
    final int index;
55
    public DynAction() {
56
        index = total++;
57
    }
58
59
    @Override
60
    public JComponent[] getMenuPresenters() {
61
        JComponent[] result = new JComponent[count];
62
        for (int i= 0; i < result.length; i++) {
63
            JMenuItem j = new JMenuItem ("Dynamic " + index + ":" + i);
64
            j.putClientProperty("caption", j.getText());
65
            j.putClientProperty("syncCount", 0);
66
            result[i] = j;
67
        }
68
        return result;
69
    }
70
71
    @Override
72
    public JComponent[] synchMenuPresenters(JComponent[] items) {
73
        for (JComponent jc : items) {
74
            JMenuItem m = (JMenuItem) jc;
75
            String cap = (String) m.getClientProperty("caption");
76
            int syncs = ((Integer) m.getClientProperty("syncCount")).intValue();
77
            syncs ++;
78
            m.putClientProperty("syncCount", syncs);
79
            m.setText (cap + " (sync " + syncs + ")");
80
        }
81
        return items;
82
    }
83
84
}
(-)1f7b91420663 (+203 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.core.menu;
40
41
import java.awt.Component;
42
import java.awt.Dimension;
43
import java.awt.EventQueue;
44
import java.awt.event.ContainerEvent;
45
import java.awt.event.ContainerListener;
46
import java.awt.event.MouseEvent;
47
import java.lang.ref.Reference;
48
import java.lang.ref.WeakReference;
49
import java.util.ArrayList;
50
import java.util.List;
51
import java.util.concurrent.CountDownLatch;
52
import java.util.concurrent.TimeUnit;
53
import javax.swing.AbstractButton;
54
import javax.swing.JComponent;
55
import javax.swing.JFrame;
56
import javax.swing.JMenu;
57
import javax.swing.JMenuBar;
58
import javax.swing.JMenuItem;
59
import javax.swing.JPanel;
60
import javax.swing.JPopupMenu;
61
import org.junit.Test;
62
import org.netbeans.junit.NbTestCase;
63
import org.openide.filesystems.FileSystem;
64
import org.openide.filesystems.XMLFileSystem;
65
66
/**
67
 *
68
 * @author tim
69
 */
70
public class MenuProviderImplTest extends NbTestCase {
71
72
    private MenuProviderImpl m;
73
    private JMenuBar bar;
74
    private JFrame jf;
75
    private JMenu menu;
76
77
    public MenuProviderImplTest(String name) {
78
        super(name);
79
    }
80
81
    @Override
82
    protected boolean runInEQ() {
83
        return false;
84
    }
85
86
    @Override
87
    public void setUp() throws Exception {
88
        FileSystem fs = new XMLFileSystem(MenuProviderImplTest.class.getResource("fakelayer.xml"));
89
        m = new MenuProviderImpl(fs.getRoot().getFileObject("Menu"));
90
        R r = new R();
91
92
        EventQueue.invokeAndWait(r);
93
        r.latch.await(20000, TimeUnit.MILLISECONDS);
94
        while (!jf.isShowing()) {
95
            Thread.sleep(30);
96
        }
97
        assertFalse(bar.getMenuCount() == 0);
98
        menu = bar.getMenu(0);
99
    }
100
101
    @Override
102
    public void tearDown() {
103
        jf.dispose();
104
    }
105
106
    private void click(final JComponent comp, final boolean showMenu) throws Exception {
107
        EventQueue.invokeAndWait(new Runnable() {
108
109
            public void run() {
110
                ((AbstractButton) comp).getModel().setPressed(showMenu);
111
                MouseEvent evt = new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(),
112
                        0, 5, 5, 1, false, 0);
113
                comp.dispatchEvent(evt);
114
                evt = new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(),
115
                        0, 5, 5, 1, false, 0);
116
                comp.dispatchEvent(evt);
117
                evt = new MouseEvent(comp, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(),
118
                        0, 5, 5, 1, false, 0);
119
                comp.dispatchEvent(evt);
120
            }
121
        });
122
        if (comp instanceof JMenu) {
123
            JMenu m = (JMenu) comp;
124
            while (showMenu != m.getPopupMenu().isShowing()) {
125
                Thread.sleep (100);
126
            }
127
        }
128
    }
129
130
    @Test
131
    public void testMenuItemsAreNotStronglyReferenced() throws Exception {
132
        assertNotNull (menu);
133
        click (menu, true);
134
        JPopupMenu popup = menu.getPopupMenu();
135
        Component[] c = popup.getComponents();
136
        assertEquals (7, c.length);
137
        List<Reference<Component>> l = new ArrayList<Reference<Component>>();
138
        boolean presenterActionFound = false;
139
        boolean regularActionFound = false;
140
        int pActionIx = -1;
141
        int rActionIx = -1;
142
        for (int i=0; i < c.length; i++) {
143
            Component cc = c[i];
144
            boolean wasPactionFound = presenterActionFound;
145
            presenterActionFound |= cc instanceof PresenterAction.Marker;
146
            if (!wasPactionFound && presenterActionFound) {
147
                pActionIx = i;
148
            }
149
            l.add (new WeakReference<Component>(cc));
150
            boolean wasRactionFound = regularActionFound;
151
            regularActionFound |= cc instanceof JMenuItem && ((JMenuItem) cc).getText().equals("Regular Action");
152
            if (!wasRactionFound && regularActionFound) {
153
                rActionIx = i;
154
            }
155
        }
156
        //Test order while we're here
157
        assertTrue (presenterActionFound);
158
        assertTrue (regularActionFound);
159
        assertEquals ("Wrong index for presenter action", 5, pActionIx);
160
        assertEquals ("Wrong index for presenter action", 6, rActionIx);
161
        click (menu, false);
162
        c = null;
163
        for (Reference<?> r : l) {
164
            assertGC("Menu component not collected", r);
165
        }
166
    }
167
    private static final int EXPECTED_MENU_COUNT = 1; //update if more added to xml
168
169
    private class R implements Runnable, ContainerListener {
170
171
        private final CountDownLatch latch = new CountDownLatch(1);
172
173
        @Override
174
        public void run() {
175
            jf = new JFrame();
176
            bar = m.createMenu(jf);
177
            bar.addContainerListener(this);
178
            JPanel pnl = new JPanel();
179
            pnl.setMinimumSize(new Dimension(300, 300));
180
            pnl.setPreferredSize(new Dimension(300, 300));
181
            jf.setContentPane(pnl);
182
            jf.setJMenuBar(bar);
183
            jf.pack();
184
            jf.setVisible(true);
185
        }
186
187
        @Override
188
        public void componentAdded(ContainerEvent e) {
189
            int count = e.getContainer().getComponentCount();
190
            if (count == EXPECTED_MENU_COUNT) {
191
                latch.countDown();
192
                e.getContainer().invalidate();
193
                ((JMenuBar) e.getContainer()).revalidate();
194
                e.getContainer().repaint();
195
            }
196
        }
197
198
        @Override
199
        public void componentRemoved(ContainerEvent e) {
200
            //do nothing
201
        }
202
    }
203
}
(-)1f7b91420663 (+69 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
import javax.swing.JMenuItem;
45
import org.openide.util.actions.Presenter;
46
47
/**
48
 *
49
 * @author Tim Boudreau
50
 */
51
public class PresenterAction extends AbstractAction implements Presenter.Menu {
52
53
    @Override
54
    public JMenuItem getMenuPresenter() {
55
        return new Marker ("Menu Presenter");
56
    }
57
58
    @Override
59
    public void actionPerformed(ActionEvent e) {
60
        throw new UnsupportedOperationException("Not supported yet.");
61
    }
62
63
    public class Marker extends JMenuItem {
64
        Marker (String s) {
65
            super (s);
66
        }
67
    }
68
69
}
(-)1f7b91420663 (+59 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
45
/**
46
 *
47
 * @author Tim Boudreau
48
 */
49
public class RegularAction extends AbstractAction {
50
    private boolean performed;
51
    public RegularAction() {
52
        putValue (NAME, "Regular Action");
53
    }
54
55
    @Override
56
    public void actionPerformed(ActionEvent e) {
57
        performed = true;
58
    }
59
}
(-)1f7b91420663 (+17 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        <folder name="One">
6
            <file name="org-netbeans-core-menu-DynAction.instance">
7
                <attr name="position" intvalue="0"/>
8
            </file>
9
            <file name="org-netbeans-core-menu-PresenterAction.instance">
10
                <attr name="position" intvalue="1"/>
11
            </file>
12
            <file name="org-netbeans-core-menu-RegularAction.instance">
13
                <attr name="position" intvalue="2"/>
14
            </file>
15
        </folder>
16
    </folder>
17
</filesystem>
(-)a/nbbuild/cluster.properties (+2 lines)
Lines 184-189 Link Here
184
nb.cluster.platform.depends=
184
nb.cluster.platform.depends=
185
nb.cluster.platform=\
185
nb.cluster.platform=\
186
        api.annotations.common,\
186
        api.annotations.common,\
187
        api.menus,\
187
        api.progress,\
188
        api.progress,\
188
        api.visual,\
189
        api.visual,\
189
        applemenu,\
190
        applemenu,\
Lines 192-197 Link Here
192
        core.execution,\
193
        core.execution,\
193
        core.io.ui,\
194
        core.io.ui,\
194
        core.kit,\
195
        core.kit,\
196
        core.menu,\
195
        core.multiview,\
197
        core.multiview,\
196
        core.nativeaccess,\
198
        core.nativeaccess,\
197
        core.netigso,\
199
        core.netigso,\
(-)a/core.windows/manifest.mf (-1 / +1 lines)
Lines 6-10 Link Here
6
OpenIDE-Module-Recommends: org.netbeans.core.windows.nativeaccess.NativeWindowSystem
6
OpenIDE-Module-Recommends: org.netbeans.core.windows.nativeaccess.NativeWindowSystem
7
AutoUpdate-Show-In-Client: false
7
AutoUpdate-Show-In-Client: false
8
AutoUpdate-Essential-Module: true
8
AutoUpdate-Essential-Module: true
9
OpenIDE-Module-Specification-Version: 2.20
9
OpenIDE-Module-Specification-Version: 2.21
10
10
(-)a/core.windows/nbproject/project.xml (+9 lines)
Lines 47-52 Link Here
47
            <code-name-base>org.netbeans.core.windows</code-name-base>
47
            <code-name-base>org.netbeans.core.windows</code-name-base>
48
            <module-dependencies>
48
            <module-dependencies>
49
                <dependency>
49
                <dependency>
50
                    <code-name-base>org.netbeans.api.menus</code-name-base>
51
                    <build-prerequisite/>
52
                    <compile-dependency/>
53
                    <run-dependency>
54
                        <release-version>1</release-version>
55
                        <specification-version>1.0</specification-version>
56
                    </run-dependency>
57
                </dependency>
58
                <dependency>
50
                    <code-name-base>org.netbeans.core</code-name-base>
59
                    <code-name-base>org.netbeans.core</code-name-base>
51
                    <build-prerequisite/>
60
                    <build-prerequisite/>
52
                    <compile-dependency/>
61
                    <compile-dependency/>
(-)a/core.windows/src/org/netbeans/core/windows/WindowSystemImpl.java (-3 lines)
Lines 45-53 Link Here
45
45
46
import java.awt.EventQueue;
46
import java.awt.EventQueue;
47
import org.netbeans.core.WindowSystem;
47
import org.netbeans.core.WindowSystem;
48
import org.netbeans.core.windows.persistence.PersistenceManager;
49
import org.netbeans.core.windows.services.DialogDisplayerImpl;
48
import org.netbeans.core.windows.services.DialogDisplayerImpl;
50
import org.netbeans.core.windows.view.ui.MainWindow;
51
import org.openide.util.lookup.ServiceProvider;
49
import org.openide.util.lookup.ServiceProvider;
52
50
53
51
Lines 61-67 Link Here
61
59
62
    public void init() {
60
    public void init() {
63
        assert !EventQueue.isDispatchThread();
61
        assert !EventQueue.isDispatchThread();
64
        MainWindow.init();
65
    }
62
    }
66
63
67
    public void load() {
64
    public void load() {
(-)a/core.windows/src/org/netbeans/core/windows/view/ViewHierarchy.java (+1 lines)
Lines 122-127 Link Here
122
    public MainWindow getMainWindow() {
122
    public MainWindow getMainWindow() {
123
        if (mainWindow == null) {
123
        if (mainWindow == null) {
124
            mainWindow = new MainWindow();
124
            mainWindow = new MainWindow();
125
            mainWindow.init();
125
        }
126
        }
126
        return mainWindow;
127
        return mainWindow;
127
    }
128
    }
(-)a/core.windows/src/org/netbeans/core/windows/view/ui/MainWindow.java (-2 / +7 lines)
Lines 62-67 Link Here
62
import javax.swing.JPanel;
62
import javax.swing.JPanel;
63
import javax.swing.border.*;
63
import javax.swing.border.*;
64
import javax.swing.event.*;
64
import javax.swing.event.*;
65
import org.netbeans.api.menus.MenuProvider;
65
import org.netbeans.core.windows.*;
66
import org.netbeans.core.windows.*;
66
import org.netbeans.core.windows.view.ui.toolbars.ToolbarConfiguration;
67
import org.netbeans.core.windows.view.ui.toolbars.ToolbarConfiguration;
67
import org.openide.LifecycleManager;
68
import org.openide.LifecycleManager;
Lines 138-144 Link Here
138
        }
139
        }
139
    }
140
    }
140
141
141
    public static void init() {
142
    public void init() {
142
        if (mainMenuBar == null) {
143
        if (mainMenuBar == null) {
143
            mainMenuBar = createMenuBar();
144
            mainMenuBar = createMenuBar();
144
            ToolbarPool.getDefault().waitFinished();
145
            ToolbarPool.getDefault().waitFinished();
Lines 365-372 Link Here
365
        );
366
        );
366
    }
367
    }
367
368
369
    private JMenuBar createMenuBar() {
370
        return MenuProvider.installMenu(this);
371
    }
372
368
    /** Creates menu bar. */
373
    /** Creates menu bar. */
369
    private static JMenuBar createMenuBar() {
374
    private static JMenuBar xcreateMenuBar() {
370
        JMenuBar menu = getCustomMenuBar();
375
        JMenuBar menu = getCustomMenuBar();
371
        if (menu == null) {
376
        if (menu == null) {
372
             menu = new MenuBar (null);
377
             menu = new MenuBar (null);
(-)a/core.menu/src/org/netbeans/core/menu/FolderModelEntry.java (-2 / +6 lines)
Lines 52-57 Link Here
52
import java.util.Set;
52
import java.util.Set;
53
import javax.swing.Action;
53
import javax.swing.Action;
54
import javax.swing.JComponent;
54
import javax.swing.JComponent;
55
import javax.swing.JMenuItem;
55
import javax.swing.JSeparator;
56
import javax.swing.JSeparator;
56
import org.openide.awt.DynamicMenuContent;
57
import org.openide.awt.DynamicMenuContent;
57
import org.openide.cookies.InstanceCookie;
58
import org.openide.cookies.InstanceCookie;
Lines 267-272 Link Here
267
            if (icons != null) {
268
            if (icons != null) {
268
                ModelEntry.configureIcon(c, icons);
269
                ModelEntry.configureIcon(c, icons);
269
            }
270
            }
271
            if (c instanceof JMenuItem) {
272
                c.setToolTipText(null);
273
            }
270
        }
274
        }
271
    }
275
    }
272
276
Lines 299-305 Link Here
299
                    : ck == null ? false : type.isAssignableFrom(ck.instanceClass());
303
                    : ck == null ? false : type.isAssignableFrom(ck.instanceClass());
300
        }
304
        }
301
305
302
        ModelEntry<?, ?> createEntry(DataObject ob, Callback callback) {
306
        ModelEntry<?, ?> createEntry(DataObject ob, FolderModelEntry entry) {
303
//            System.err.println("Create " + name() + " entry for " + ob.getPrimaryFile().getPath());
307
//            System.err.println("Create " + name() + " entry for " + ob.getPrimaryFile().getPath());
304
            switch (this) {
308
            switch (this) {
305
                case SEPARATOR:
309
                case SEPARATOR:
Lines 325-331 Link Here
325
                    DataFolder fld = ob instanceof DataFolder ? (DataFolder) ob
329
                    DataFolder fld = ob instanceof DataFolder ? (DataFolder) ob
326
                            : ob.getLookup().lookup(DataFolder.class);
330
                            : ob.getLookup().lookup(DataFolder.class);
327
                    Parameters.notNull("folder was non-null but is now null", fld);
331
                    Parameters.notNull("folder was non-null but is now null", fld);
328
                    return new MenuEntry(fld, null);
332
                    return new MenuEntry(fld, MenuManager.rp);
329
                case COMPONENT:
333
                case COMPONENT:
330
                    return new ComponentModelEntry(ob);
334
                    return new ComponentModelEntry(ob);
331
                default:
335
                default:
(-)a/core.menu/src/org/netbeans/core/menu/MenuBarModel.java (-88 / +4 lines)
Lines 39-52 Link Here
39
39
40
package org.netbeans.core.menu;
40
package org.netbeans.core.menu;
41
41
42
import java.awt.EventQueue;
43
import java.util.LinkedList;
44
import java.util.List;
45
import javax.swing.JMenuBar;
42
import javax.swing.JMenuBar;
46
import org.openide.filesystems.FileAttributeEvent;
47
import org.openide.filesystems.FileChangeAdapter;
48
import org.openide.filesystems.FileEvent;
49
import org.openide.filesystems.FileRenameEvent;
50
import org.openide.loaders.DataFolder;
43
import org.openide.loaders.DataFolder;
51
import org.openide.util.RequestProcessor;
44
import org.openide.util.RequestProcessor;
52
45
Lines 54-73 Link Here
54
 *
47
 *
55
 * @author Tim Boudreau
48
 * @author Tim Boudreau
56
 */
49
 */
57
final class MenuBarModel extends FolderModelEntry<JMenuBar> {
50
final class MenuBarModel extends RefreshingFolderModelEntry<JMenuBar> {
58
    private final JMenuBar bar;
51
    private final JMenuBar bar;
59
    private FCA fca = new FCA();
60
    private final RequestProcessor.Task task;
61
    private static final int DELAY = 100;
62
    MenuBarModel (DataFolder rootFolder, JMenuBar bar, RequestProcessor rp) {
52
    MenuBarModel (DataFolder rootFolder, JMenuBar bar, RequestProcessor rp) {
63
        super (rootFolder, JMenuBar.class);
53
        super (rootFolder, JMenuBar.class, rp);
64
        this.bar = bar;
54
        this.bar = bar;
65
        this.task = rp.create(fca);
66
        rootFolder.getPrimaryFile().addFileChangeListener(fca);
67
    }
68
69
    void init() {
70
        fca.refresh();
71
    }
55
    }
72
56
73
    @Override
57
    @Override
Lines 76-150 Link Here
76
    }
60
    }
77
61
78
    @Override
62
    @Override
79
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
63
    JMenuBar cachedComponent() {
80
        super.onInitBackground(children);
64
        return bar;
81
        if (!refreshing) {
82
            EventQueue.invokeLater(fca);
83
        }
84
    }
85
86
    volatile boolean refreshing;
87
    private final class FCA extends FileChangeAdapter implements Runnable {
88
        private volatile boolean enqueued;
89
        boolean refresh() {
90
            boolean result;
91
            synchronized (this) {
92
                result = enqueued;
93
                if (!enqueued) {
94
                    enqueued = true;
95
                    task.schedule(DELAY);
96
                }
97
                return result;
98
            }
99
        }
100
101
        @Override
102
        public void run() {
103
            if (!EventQueue.isDispatchThread()) {
104
                refreshing = true;
105
                try {
106
                    List<ModelEntry<?,?>> l = new LinkedList<ModelEntry<?,?>>();
107
                    initBackground(l);
108
                    setChildren(l);
109
                } finally {
110
                    refreshing = false;
111
                    EventQueue.invokeLater(this);
112
                }
113
            } else {
114
                enqueued = false;
115
                bar.removeAll();
116
                MenuBarModel.this.refresh(new JMenuBar[] { bar });
117
            }
118
        }
119
120
        @Override
121
        public void fileAttributeChanged(FileAttributeEvent fe) {
122
            refresh();
123
        }
124
125
        @Override
126
        public void fileChanged(FileEvent fe) {
127
            refresh();
128
        }
129
130
        @Override
131
        public void fileDataCreated(FileEvent fe) {
132
            refresh();
133
        }
134
135
        @Override
136
        public void fileDeleted(FileEvent fe) {
137
            refresh();
138
        }
139
140
        @Override
141
        public void fileFolderCreated(FileEvent fe) {
142
            refresh();
143
        }
144
145
        @Override
146
        public void fileRenamed(FileRenameEvent fe) {
147
            refresh();
148
        }
149
    }
65
    }
150
}
66
}
(-)a/core.menu/src/org/netbeans/core/menu/MenuEntry.java (-13 / +15 lines)
Lines 42-66 Link Here
42
import java.awt.EventQueue;
42
import java.awt.EventQueue;
43
import java.lang.ref.Reference;
43
import java.lang.ref.Reference;
44
import java.lang.ref.WeakReference;
44
import java.lang.ref.WeakReference;
45
import java.util.concurrent.atomic.AtomicBoolean;
45
import javax.swing.ButtonModel;
46
import javax.swing.ButtonModel;
46
import javax.swing.JMenu;
47
import javax.swing.JMenu;
47
import javax.swing.event.ChangeEvent;
48
import javax.swing.event.ChangeEvent;
48
import javax.swing.event.ChangeListener;
49
import javax.swing.event.ChangeListener;
49
import org.openide.awt.Mnemonics;
50
import org.openide.awt.Mnemonics;
50
import org.openide.loaders.DataFolder;
51
import org.openide.loaders.DataFolder;
52
import org.openide.util.RequestProcessor;
51
53
52
/**
54
/**
53
 *
55
 *
54
 * @author Tim Boudreau
56
 * @author Tim Boudreau
55
 */
57
 */
56
final class MenuEntry extends FolderModelEntry<JMenu> implements ChangeListener {
58
final class MenuEntry extends RefreshingFolderModelEntry<JMenu> implements ChangeListener {
57
58
    private Reference<JMenu> menu;
59
    private Reference<JMenu> menu;
59
    private final Callback callback;
60
    MenuEntry (DataFolder fld, RequestProcessor rp) {
60
61
        super (fld, JMenu.class, rp);
61
    MenuEntry (DataFolder fld, Callback callback) {
62
        super (fld, JMenu.class);
63
        this.callback = callback == null ? this : callback;
64
    }
62
    }
65
63
66
    private JMenu menu() {
64
    private JMenu menu() {
Lines 81-86 Link Here
81
    }
79
    }
82
80
83
    private boolean wasSelected = false;
81
    private boolean wasSelected = false;
82
    private AtomicBoolean showing = new AtomicBoolean();
84
    @Override
83
    @Override
85
    public void stateChanged(ChangeEvent e) {
84
    public void stateChanged(ChangeEvent e) {
86
        ButtonModel mdl = (ButtonModel) e.getSource();
85
        ButtonModel mdl = (ButtonModel) e.getSource();
Lines 88-106 Link Here
88
        //XXX wasSelected could be true if the old component was garbage collected
87
        //XXX wasSelected could be true if the old component was garbage collected
89
        //without resetting its model - possible?
88
        //without resetting its model - possible?
90
        if (selected && !wasSelected) {
89
        if (selected && !wasSelected) {
91
            if (callback != null) {
90
            showing.set(true);
92
                callback.onShow(this);
91
            onShow(this);
93
            }
94
            refreshComponent(menu());
92
            refreshComponent(menu());
95
        } else if (wasSelected && !selected) {
93
        } else if (wasSelected && !selected) {
94
            showing.set(false);
96
            JMenu m = menu == null ? null : menu.get();
95
            JMenu m = menu == null ? null : menu.get();
97
            if (m != null) {
96
            if (m != null) {
98
                m.removeAll();
97
                m.removeAll();
99
            }
98
            }
100
            if (callback != null) {
99
            onHide(this);
101
                callback.onHide(this);
102
            }
103
        }
100
        }
104
        wasSelected = selected;
101
        wasSelected = selected;
105
    }
102
    }
103
104
    @Override
105
    JMenu cachedComponent() {
106
        return menu();
107
    }
106
}
108
}
(-)a/core.menu/src/org/netbeans/core/menu/MenuManager.java (-1 / +2 lines)
Lines 49-55 Link Here
49
 */
49
 */
50
final class MenuManager {
50
final class MenuManager {
51
    private final JMenuBar bar;
51
    private final JMenuBar bar;
52
    private final RequestProcessor rp = new RequestProcessor("Main Menu Refresh", 1, true);
52
    //XXX make this non-static and pass to model entries
53
    static final RequestProcessor rp = new RequestProcessor("Main Menu Refresh", 1, true);
53
    private final MenuBarModel model;
54
    private final MenuBarModel model;
54
55
55
    MenuManager(DataFolder folder, JMenuBar bar) {
56
    MenuManager(DataFolder folder, JMenuBar bar) {
(-)fa24874d2b7b (+155 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.core.menu;
40
41
import java.awt.EventQueue;
42
import java.util.LinkedList;
43
import java.util.List;
44
import javax.swing.JComponent;
45
import javax.swing.JMenuBar;
46
import org.openide.filesystems.FileAttributeEvent;
47
import org.openide.filesystems.FileChangeAdapter;
48
import org.openide.filesystems.FileEvent;
49
import org.openide.filesystems.FileObject;
50
import org.openide.filesystems.FileRenameEvent;
51
import org.openide.filesystems.FileUtil;
52
import org.openide.loaders.DataFolder;
53
import org.openide.util.RequestProcessor;
54
55
/**
56
 *
57
 * @author Tim Boudreau
58
 */
59
abstract class RefreshingFolderModelEntry<T extends JComponent> extends FolderModelEntry<T> {
60
61
    private final RequestProcessor.Task task;
62
    private FCA fca = new FCA();
63
    private static final int DELAY = 100;
64
65
    RefreshingFolderModelEntry(DataFolder dob, Class<T> compType, RequestProcessor rp) {
66
        super(dob, compType);
67
        this.task = rp.create(fca);
68
        FileObject fo = dob.getPrimaryFile();
69
        fo.addFileChangeListener(FileUtil.weakFileChangeListener(fca, fo));
70
    }
71
72
    @Override
73
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
74
        super.onInitBackground(children);
75
        if (!refreshing) {
76
            EventQueue.invokeLater(fca);
77
        }
78
    }
79
80
    abstract T cachedComponent();
81
82
    void init() {
83
        fca.refresh();
84
    }
85
    volatile boolean refreshing;
86
87
    private final class FCA extends FileChangeAdapter implements Runnable {
88
89
        private volatile boolean enqueued;
90
91
        boolean refresh() {
92
            boolean result;
93
            synchronized (this) {
94
                result = enqueued;
95
                if (!enqueued) {
96
                    enqueued = true;
97
                    task.schedule(DELAY);
98
                }
99
                return result;
100
            }
101
        }
102
103
        @Override
104
        public void run() {
105
            if (!EventQueue.isDispatchThread()) {
106
                refreshing = true;
107
                try {
108
                    List<ModelEntry<?, ?>> l = new LinkedList<ModelEntry<?, ?>>();
109
                    initBackground(l);
110
                    setChildren(l);
111
                } finally {
112
                    refreshing = false;
113
                    EventQueue.invokeLater(this);
114
                }
115
            } else {
116
                enqueued = false;
117
                T comp = cachedComponent();
118
                if (comp != null) {
119
                    comp.removeAll();
120
                    RefreshingFolderModelEntry.this.refresh(toCompTypeArray(new Object[]{comp}));
121
                }
122
            }
123
        }
124
125
        @Override
126
        public void fileAttributeChanged(FileAttributeEvent fe) {
127
            refresh();
128
        }
129
130
        @Override
131
        public void fileChanged(FileEvent fe) {
132
            refresh();
133
        }
134
135
        @Override
136
        public void fileDataCreated(FileEvent fe) {
137
            refresh();
138
        }
139
140
        @Override
141
        public void fileDeleted(FileEvent fe) {
142
            refresh();
143
        }
144
145
        @Override
146
        public void fileFolderCreated(FileEvent fe) {
147
            refresh();
148
        }
149
150
        @Override
151
        public void fileRenamed(FileRenameEvent fe) {
152
            refresh();
153
        }
154
    }
155
}
(-)a/core.menu/src/org/netbeans/core/menu/MenuEntry.java (+14 lines)
Lines 78-83 Link Here
78
        return menu();
78
        return menu();
79
    }
79
    }
80
80
81
    @Override
82
    protected void onRefresh(JMenu[] newComps) {
83
        if (showing.get()) {
84
            JMenu m = menu();
85
            if (m != null && m.isPopupMenuVisible()) {
86
                m.setPopupMenuVisible(false);
87
                m.invalidate();
88
                m.revalidate();
89
                m.repaint();
90
                m.setPopupMenuVisible(true);
91
            }
92
        }
93
    }
94
81
    private boolean wasSelected = false;
95
    private boolean wasSelected = false;
82
    private AtomicBoolean showing = new AtomicBoolean();
96
    private AtomicBoolean showing = new AtomicBoolean();
83
    @Override
97
    @Override
(-)a/core.menu/src/org/netbeans/core/menu/ModelEntry.java (-2 / +9 lines)
Lines 70-76 Link Here
70
    protected abstract boolean initBackground(List<? super ModelEntry<?,?>> children);
70
    protected abstract boolean initBackground(List<? super ModelEntry<?,?>> children);
71
71
72
    public String getName() {
72
    public String getName() {
73
        return file().getNodeDelegate().getDisplayName();
73
        DataObject file = file();
74
        return file.isValid() ? file.getNodeDelegate().getDisplayName() : file.getName();
74
    }
75
    }
75
76
76
    protected final DataObjectType file() {
77
    protected final DataObjectType file() {
Lines 95-102 Link Here
95
        return refresh (old);
96
        return refresh (old);
96
    }
97
    }
97
98
99
    protected void onRefresh (CompType[] newComps) {
100
        
101
    }
102
98
    protected CompType[] refresh (CompType[] old) {
103
    protected CompType[] refresh (CompType[] old) {
99
        return toCompTypeArray(new Object[] { refreshComponent( old.length == 0 ? null : old[0]) });
104
        CompType[] result = toCompTypeArray(new Object[] { refreshComponent( old.length == 0 ? null : old[0]) });
105
        onRefresh (result);
106
        return result;
100
    }
107
    }
101
108
102
    protected CompType[] findComponents() {
109
    protected CompType[] findComponents() {
(-)d76d479b5dc8 (+68 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
import org.netbeans.core.menu.FileChangeTest.Layers;
45
import org.openide.util.Exceptions;
46
import org.xml.sax.SAXException;
47
48
/**
49
 *
50
 * @author Tim Boudreau
51
 */
52
public class AAction extends AbstractAction {
53
    public AAction() {
54
        putValue (NAME, "A");
55
    }
56
57
    @Override
58
    public void actionPerformed(ActionEvent e) {
59
        try {
60
            FileChangeTest.MFS.INSTANCE.setLayers(Layers.A);
61
        } catch (SAXException ex) {
62
            Exceptions.printStackTrace(ex);
63
        }
64
    }
65
66
67
68
}
(-)d76d479b5dc8 (+68 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
import org.netbeans.core.menu.FileChangeTest.Layers;
45
import org.openide.util.Exceptions;
46
import org.xml.sax.SAXException;
47
48
/**
49
 *
50
 * @author Tim Boudreau
51
 */
52
public class ABAction extends AbstractAction {
53
    public ABAction() {
54
        putValue (NAME, "AB");
55
    }
56
57
    @Override
58
    public void actionPerformed(ActionEvent e) {
59
        try {
60
            FileChangeTest.MFS.INSTANCE.setLayers(Layers.A, Layers.B);
61
        } catch (SAXException ex) {
62
            Exceptions.printStackTrace(ex);
63
        }
64
    }
65
66
67
68
}
(-)d76d479b5dc8 (+68 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
import org.netbeans.core.menu.FileChangeTest.Layers;
45
import org.openide.util.Exceptions;
46
import org.xml.sax.SAXException;
47
48
/**
49
 *
50
 * @author Tim Boudreau
51
 */
52
public class ABCAction extends AbstractAction {
53
    public ABCAction() {
54
        putValue (NAME, "ABC");
55
    }
56
57
    @Override
58
    public void actionPerformed(ActionEvent e) {
59
        try {
60
            FileChangeTest.MFS.INSTANCE.setLayers(Layers.A, Layers.B, Layers.C);
61
        } catch (SAXException ex) {
62
            Exceptions.printStackTrace(ex);
63
        }
64
    }
65
66
67
68
}
(-)d76d479b5dc8 (+68 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.event.ActionEvent;
43
import javax.swing.AbstractAction;
44
import org.netbeans.core.menu.FileChangeTest.Layers;
45
import org.openide.util.Exceptions;
46
import org.xml.sax.SAXException;
47
48
/**
49
 *
50
 * @author Tim Boudreau
51
 */
52
public class ABCDAction extends AbstractAction {
53
    public ABCDAction() {
54
        putValue (NAME, "ABCD");
55
    }
56
57
    @Override
58
    public void actionPerformed(ActionEvent e) {
59
        try {
60
            FileChangeTest.MFS.INSTANCE.setLayers(Layers.A, Layers.B, Layers.C, Layers.D);
61
        } catch (SAXException ex) {
62
            Exceptions.printStackTrace(ex);
63
        }
64
    }
65
66
67
68
}
(-)d76d479b5dc8 (+96 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.core.menu;
41
42
import java.awt.AWTEvent;
43
import static java.awt.AWTEvent.*;
44
import java.awt.Component;
45
import java.awt.Toolkit;
46
import java.awt.event.AWTEventListener;
47
import java.awt.event.MouseEvent;
48
import java.lang.reflect.InvocationTargetException;
49
import java.lang.reflect.Method;
50
import org.openide.util.Exceptions;
51
52
/**
53
 * Blocks real input events from the user, so user's focus behavior cannot
54
 * affect tests
55
 *
56
 * @author Tim Boudreau
57
 */
58
public class EventBlocker implements AWTEventListener {
59
    private static final long MASK = FOCUS_EVENT_MASK | MOUSE_EVENT_MASK | MOUSE_MOTION_EVENT_MASK | MOUSE_WHEEL_EVENT_MASK | 
60
            KEY_EVENT_MASK | ACTION_EVENT_MASK | ADJUSTMENT_EVENT_MASK | 
61
            INPUT_METHOD_EVENT_MASK | ITEM_EVENT_MASK | TEXT_EVENT_MASK;
62
    static void init() {
63
        Toolkit.getDefaultToolkit().addAWTEventListener(new EventBlocker(), MASK);
64
    }
65
66
    @Override
67
    public void eventDispatched(AWTEvent event) {
68
        Class<?> c = event.getClass();
69
        if (event instanceof ME) {
70
            return;
71
        }
72
        try {
73
            Method m = c.getMethod("consume");
74
            try {
75
                m.invoke(event);
76
            } catch (IllegalAccessException ex) {
77
            } catch (IllegalArgumentException ex) {
78
            } catch (InvocationTargetException ex) {
79
            }
80
        } catch (NoSuchMethodException ex) {
81
        } catch (SecurityException ex) {
82
        }
83
    }
84
85
    public static MouseEvent mouseEvent (Component c, int id) {
86
        return new ME(c, id);
87
    }
88
89
    private static final class ME extends MouseEvent {
90
        ME(Component comp, int id) {
91
            super (comp, id, System.currentTimeMillis(),
92
                        0, 5, 5, 1, false, 0);
93
        }
94
    }
95
96
}
(-)d76d479b5dc8 (+303 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.core.menu;
40
41
import java.awt.Component;
42
import java.awt.Dimension;
43
import java.awt.EventQueue;
44
import java.awt.event.ContainerEvent;
45
import java.awt.event.ContainerListener;
46
import java.awt.event.MouseEvent;
47
import java.net.URL;
48
import java.util.Arrays;
49
import java.util.concurrent.CountDownLatch;
50
import java.util.concurrent.TimeUnit;
51
import java.util.concurrent.atomic.AtomicBoolean;
52
import java.util.concurrent.atomic.AtomicInteger;
53
import javax.swing.AbstractButton;
54
import javax.swing.JComponent;
55
import javax.swing.JFrame;
56
import javax.swing.JMenu;
57
import javax.swing.JMenuBar;
58
import javax.swing.JPanel;
59
import javax.swing.JPopupMenu;
60
import org.junit.Test;
61
import org.netbeans.junit.NbTestCase;
62
import org.openide.filesystems.FileSystem;
63
import org.openide.filesystems.MultiFileSystem;
64
import org.openide.filesystems.XMLFileSystem;
65
import org.xml.sax.SAXException;
66
67
/**
68
 *
69
 * @author tim
70
 */
71
public class FileChangeTest extends NbTestCase {
72
73
    private MenuProviderImpl m;
74
    private JMenuBar bar;
75
    private JFrame jf;
76
    private JMenu menu;
77
78
79
    public FileChangeTest(String name) {
80
        super(name);
81
    }
82
83
    @Override
84
    protected boolean runInEQ() {
85
        return false;
86
    }
87
88
    @Override
89
    public void setUp() throws Exception {
90
        FileSystem fs = new MFS();
91
        m = new MenuProviderImpl(fs.getRoot().getFileObject("Menu"));
92
        R r = new R();
93
94
        EventQueue.invokeAndWait(r);
95
        r.latch.await(20000, TimeUnit.MILLISECONDS);
96
        while (!jf.isShowing()) {
97
            Thread.sleep(30);
98
        }
99
        while (bar.getMenuCount() < 2) {
100
            Thread.sleep(30);
101
        }
102
        assertFalse(bar.getMenuCount() == 0);
103
        menu = bar.getMenu(0);
104
    }
105
106
    @Override
107
    public void tearDown() {
108
        jf.dispose();
109
    }
110
111
    private void click(final JComponent comp, final boolean showMenu) throws Exception {
112
        EventQueue.invokeAndWait(new Runnable() {
113
114
            public void run() {
115
                ((AbstractButton) comp).getModel().setPressed(showMenu);
116
                MouseEvent evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_PRESSED);
117
                comp.dispatchEvent(evt);
118
                evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_RELEASED);
119
                comp.dispatchEvent(evt);
120
                evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_CLICKED);
121
                comp.dispatchEvent(evt);
122
            }
123
        });
124
        if (comp instanceof JMenu) {
125
            JMenu m = (JMenu) comp;
126
            while (showMenu != m.getPopupMenu().isShowing()) {
127
                Thread.sleep (100);
128
            }
129
        }
130
    }
131
132
133
    @Test
134
    public void testMenusAreUpdatedWhenOpen() throws Exception {
135
        EventBlocker.init();
136
        assertNotNull (menu);
137
        click (menu, true);
138
        JPopupMenu popup = menu.getPopupMenu();
139
        Component[] c = popup.getComponents();
140
        assertTrue (menu.isPopupMenuVisible());
141
        assertEquals (4, popup.getComponentCount());
142
        final CountDownLatch l = new CountDownLatch(2);
143
        popup.addContainerListener(new ContainerListener() {
144
145
            @Override
146
            public void componentAdded(ContainerEvent e) {
147
//                System.err.println("added - count now " + e.getContainer().getComponentCount());
148
                if (e.getContainer().getComponentCount() == 5) {
149
                    l.countDown();
150
                }
151
            }
152
153
            @Override
154
            public void componentRemoved(ContainerEvent e) {
155
//                System.err.println("removed - count now " + e.getContainer().getComponentCount());
156
            }
157
158
        });
159
        bar.addContainerListener(new ContainerListener() {
160
161
            @Override
162
            public void componentAdded(ContainerEvent e) {
163
//                System.err.println("bar comp added - count now " + e.getContainer().getComponentCount());
164
                if (e.getContainer().getComponentCount() == 3) {
165
                    l.countDown();
166
                }
167
            }
168
169
            @Override
170
            public void componentRemoved(ContainerEvent e) {
171
//                System.err.println("bar comp removed - count now " + e.getContainer().getComponentCount());
172
            }
173
            
174
        });
175
176
        new ABCDAction().actionPerformed(null);
177
        l.await(20000, TimeUnit.MILLISECONDS);
178
        final AtomicInteger popupCompCount = new AtomicInteger(-1);
179
        final AtomicInteger barCompCount = new AtomicInteger(-1);
180
        final AtomicBoolean vis = new AtomicBoolean();
181
        EventQueue.invokeAndWait (new Runnable() {
182
183
            @Override
184
            public void run() {
185
                popupCompCount.set(menu.getPopupMenu().getComponentCount());
186
                barCompCount.set(bar.getComponentCount());
187
                vis.set(menu.getPopupMenu().isShowing());
188
            }
189
190
        });
191
        
192
        assertTrue (vis.get());
193
        assertEquals (5, popupCompCount.get());
194
        assertEquals (3, barCompCount.get());
195
196
        popupCompCount.set(-1);
197
        barCompCount.set(-1);
198
        vis.set(false);
199
200
        final CountDownLatch ll = new CountDownLatch(4);
201
        popup.addContainerListener(new ContainerListener() {
202
203
            @Override
204
            public void componentAdded(ContainerEvent e) {
205
//                System.err.println("added - count now " + e.getContainer().getComponentCount());
206
                ll.countDown();
207
            }
208
209
            @Override
210
            public void componentRemoved(ContainerEvent e) {
211
//                System.err.println("removed - count now " + e.getContainer().getComponentCount());
212
            }
213
214
        });
215
        new AAction().actionPerformed(null);
216
        ll.await(20000, TimeUnit.MILLISECONDS);
217
        EventQueue.invokeAndWait (new Runnable() {
218
219
            @Override
220
            public void run() {
221
                popupCompCount.set(menu.getPopupMenu().getComponentCount());
222
                barCompCount.set(bar.getComponentCount());
223
                vis.set(menu.getPopupMenu().isShowing());
224
            }
225
226
        });
227
228
        assertTrue (vis.get());
229
        assertEquals (4, popupCompCount.get());
230
        assertEquals (2, barCompCount.get());
231
232
//        Thread.sleep (40000);
233
234
    }
235
    private static final int EXPECTED_MENU_COUNT = 1; //update if more added to xml
236
237
    private class R implements Runnable, ContainerListener {
238
239
        private final CountDownLatch latch = new CountDownLatch(1);
240
241
        @Override
242
        public void run() {
243
            jf = new JFrame();
244
            bar = m.createMenu(jf);
245
            bar.addContainerListener(this);
246
            JPanel pnl = new JPanel();
247
            pnl.setMinimumSize(new Dimension(300, 300));
248
            pnl.setPreferredSize(new Dimension(300, 300));
249
            jf.setContentPane(pnl);
250
            jf.setJMenuBar(bar);
251
            jf.pack();
252
            jf.setVisible(true);
253
        }
254
255
        @Override
256
        public void componentAdded(ContainerEvent e) {
257
            int count = e.getContainer().getComponentCount();
258
            if (count == EXPECTED_MENU_COUNT) {
259
                latch.countDown();
260
                e.getContainer().invalidate();
261
                ((JMenuBar) e.getContainer()).revalidate();
262
                e.getContainer().repaint();
263
            }
264
        }
265
266
        @Override
267
        public void componentRemoved(ContainerEvent e) {
268
            //do nothing
269
        }
270
    }
271
272
    public static final class MFS extends MultiFileSystem {
273
        public static MFS INSTANCE;
274
        MFS() throws SAXException {
275
            setLayers (Layers.A);
276
            INSTANCE = this;
277
        }
278
279
        public void setLayers(Layers... l) throws SAXException {
280
            System.err.println("setLayers " + Arrays.asList(l));
281
            FileSystem[] xfs = new XMLFileSystem[l.length];
282
            for (int i = 0; i < xfs.length; i++) {
283
                xfs[i] = new XMLFileSystem(l[i].res());
284
            }
285
            setDelegates(xfs);
286
        }
287
    }
288
289
    public enum Layers {
290
        A("a.xml"),
291
        B("b.xml"),
292
        C("c.xml"),
293
        D("d.xml");
294
        private String resource;
295
        Layers (String resource) {
296
            this.resource = resource;
297
        }
298
299
        public URL res() {
300
            return Layers.class.getResource(resource);
301
        }
302
    }
303
}
(-)d76d479b5dc8 (+28 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        <folder name="One">
6
            <attr name="position" intvalue="0"/>
7
            <file name="org-netbeans-core-menu-AAction.instance">
8
                <attr name="position" intvalue="0"/>
9
            </file>
10
            <file name="org-netbeans-core-menu-ABAction.instance">
11
                <attr name="position" intvalue="1"/>
12
            </file>
13
            <file name="org-netbeans-core-menu-ABCAction.instance">
14
                <attr name="position" intvalue="2"/>
15
            </file>
16
            <file name="org-netbeans-core-menu-ABCDAction.instance">
17
                <attr name="position" intvalue="3"/>
18
            </file>
19
        </folder>
20
        <folder name="Two">
21
            <attr name="position" intvalue="1"/>
22
            <file name="org-netbeans-core-menu-PresenterAction.instance">
23
                <attr name="position" intvalue="0"/>
24
            </file>
25
        </folder>
26
27
    </folder>
28
</filesystem>
(-)d76d479b5dc8 (+11 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        <folder name="Two">
6
            <file name="org-netbeans-core-menu-DynAction.instance">
7
                <attr name="position" intvalue="1"/>
8
            </file>
9
        </folder>
10
    </folder>
11
</filesystem>
(-)d76d479b5dc8 (+11 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        <folder name="One">
6
            <file name="org-netbeans-core-menu-RegularAction.instance">
7
                <attr name="position" intvalue="4"/>
8
            </file>
9
        </folder>
10
    </folder>
11
</filesystem>
(-)d76d479b5dc8 (+12 lines)
Added Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
2
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
3
<filesystem>
4
    <folder name="Menu">
5
        <folder name="Three">
6
            <attr name="position" intvalue="2"/>
7
            <file name="org-netbeans-core-menu-RegularAction.instance">
8
                <attr name="position" intvalue="1"/>
9
            </file>
10
        </folder>
11
    </folder>
12
</filesystem>
(-)a/core.menu/src/org/netbeans/core/menu/DynamicModelEntry.java (-2 lines)
Lines 60-67 Link Here
60
        try {
60
        try {
61
            DynamicMenuContent dyn = get();
61
            DynamicMenuContent dyn = get();
62
            JComponent[] result = dyn.getMenuPresenters();
62
            JComponent[] result = dyn.getMenuPresenters();
63
            //Necessary the first time, or we get bogus elements
64
            dyn.synchMenuPresenters(result);
65
            return result;
63
            return result;
66
        } catch (IOException ex) {
64
        } catch (IOException ex) {
67
            Exceptions.printStackTrace(ex);
65
            Exceptions.printStackTrace(ex);
(-)a/core.ui/manifest.mf (-1 / +1 lines)
Lines 4-8 Link Here
4
OpenIDE-Module-Layer: org/netbeans/core/ui/resources/layer.xml
4
OpenIDE-Module-Layer: org/netbeans/core/ui/resources/layer.xml
5
AutoUpdate-Show-In-Client: false
5
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Essential-Module: true
6
AutoUpdate-Essential-Module: true
7
OpenIDE-Module-Specification-Version: 1.21
7
OpenIDE-Module-Specification-Version: 1.22
8
8
(-)a/core.ui/src/org/netbeans/core/ui/warmup/MenuWarmUpTask.java (-37 / +3 lines)
Lines 45-50 Link Here
45
45
46
import java.awt.Component;
46
import java.awt.Component;
47
import java.awt.Dimension;
47
import java.awt.Dimension;
48
import java.awt.EventQueue;
48
import java.awt.Frame;
49
import java.awt.Frame;
49
import java.awt.event.ActionEvent;
50
import java.awt.event.ActionEvent;
50
import java.awt.event.WindowAdapter;
51
import java.awt.event.WindowAdapter;
Lines 58-64 Link Here
58
import javax.swing.JFrame;
59
import javax.swing.JFrame;
59
import javax.swing.JLabel;
60
import javax.swing.JLabel;
60
import javax.swing.JMenu;
61
import javax.swing.JMenu;
61
import javax.swing.SwingUtilities;
62
import javax.swing.text.html.HTMLEditorKit;
62
import javax.swing.text.html.HTMLEditorKit;
63
import org.netbeans.api.progress.ProgressHandle;
63
import org.netbeans.api.progress.ProgressHandle;
64
import org.netbeans.api.progress.ProgressHandleFactory;
64
import org.netbeans.api.progress.ProgressHandleFactory;
Lines 74-131 Link Here
74
import org.openide.util.NbBundle;
74
import org.openide.util.NbBundle;
75
75
76
/**
76
/**
77
 * A menu preheating task. It is referenced from the layer and may be performed
77
 * Triggers filesystem refresh on main window activation.
78
 * by the core after the startup.
79
 * 
80
 * Plus hooked WindowListener on main window (see {@link NbWindowsAdapter})
81
 */
78
 */
82
public final class MenuWarmUpTask implements Runnable {
79
public final class MenuWarmUpTask implements Runnable {
83
80
84
    private Component[] comps;
85
    
86
    /** Actually performs pre-heat.
87
     */
88
    @Override
81
    @Override
89
    public void run() {
82
    public void run() {
90
        try {
83
        try {
91
            SwingUtilities.invokeAndWait(new Runnable() {
84
            EventQueue.invokeLater(new Runnable() {
92
                @Override
85
                @Override
93
                public void run() {
86
                public void run() {
94
                    Frame main = WindowManager.getDefault().getMainWindow();
87
                    Frame main = WindowManager.getDefault().getMainWindow();
95
                    
96
                    assert main != null;
88
                    assert main != null;
97
                    main.addWindowListener(new NbWindowsAdapter());
89
                    main.addWindowListener(new NbWindowsAdapter());
98
                    
99
                    if (main instanceof JFrame) {
100
                        comps = ((JFrame) main).getJMenuBar().getComponents();
101
                    }
102
                }
90
                }
103
            });
91
            });
104
        } catch (Exception e) { // bail out!
92
        } catch (Exception e) { // bail out!
105
            return;
93
            return;
106
        }
94
        }
107
108
109
        if (comps != null) {
110
            walkMenu(comps);
111
            comps = null;
112
        }
113
114
        // tackle the Tools menu now? How?
115
    }
116
117
    private void walkMenu(Component[] items) {
118
        for (int i=0; i<items.length; i++) {
119
            if (! (items[i] instanceof JMenu)) continue;
120
            try {
121
                Class<?> cls = items[i].getClass();
122
                Method m = cls.getDeclaredMethod("doInitialize");
123
                m.setAccessible(true);
124
                m.invoke(items[i]);
125
                walkMenu(((JMenu)items[i]).getMenuComponents()); // recursive?
126
            } catch (Exception e) {// do nothing, it may happen for user-provided menus
127
            }
128
        }
129
    }
95
    }
130
96
131
    /**
97
    /**
(-)a/core.menu/src/org/netbeans/core/menu/ComponentModelEntry.java (-1 / +1 lines)
Lines 57-63 Link Here
57
    }
57
    }
58
58
59
    @Override
59
    @Override
60
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
60
    protected boolean initBackground(List<? super ModelEntry<?,?>> children, int currDepth) {
61
        return false;
61
        return false;
62
    }
62
    }
63
63
(-)a/core.menu/src/org/netbeans/core/menu/FolderModelEntry.java (-4 / +4 lines)
Lines 142-153 Link Here
142
        }
142
        }
143
    }
143
    }
144
144
145
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
145
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children, int currDepth) {
146
        //do nothing - for subclasses to force init
146
        //do nothing - for subclasses to force init
147
    }
147
    }
148
148
149
    @Override
149
    @Override
150
    protected boolean initBackground(List<? super ModelEntry<?, ?>> children) {
150
    protected boolean initBackground(List<? super ModelEntry<?, ?>> children, int currDepth) {
151
//        System.err.println("initBackground " + getName());
151
//        System.err.println("initBackground " + getName());
152
        DataFolder fld = file();
152
        DataFolder fld = file();
153
        boolean changed = true;
153
        boolean changed = true;
Lines 165-171 Link Here
165
                                children.add(e);
165
                                children.add(e);
166
                                //XXX defer or batch afterward?
166
                                //XXX defer or batch afterward?
167
                                List<ModelEntry<?, ?>> kids = new ArrayList<ModelEntry<?, ?>>();
167
                                List<ModelEntry<?, ?>> kids = new ArrayList<ModelEntry<?, ?>>();
168
                                boolean hasKids = e.initBackground(kids);
168
                                boolean hasKids = e.initBackground(kids, currDepth+1);
169
                                changed |= hasKids;
169
                                changed |= hasKids;
170
                                if (hasKids) {
170
                                if (hasKids) {
171
                                    if (e instanceof FolderModelEntry) {
171
                                    if (e instanceof FolderModelEntry) {
Lines 185-191 Link Here
185
                }
185
                }
186
            }
186
            }
187
        } finally {
187
        } finally {
188
            onInitBackground(children);
188
            onInitBackground(children, currDepth);
189
        }
189
        }
190
        return changed;
190
        return changed;
191
    }
191
    }
(-)a/core.menu/src/org/netbeans/core/menu/MenuBarModel.java (+16 lines)
Lines 39-44 Link Here
39
39
40
package org.netbeans.core.menu;
40
package org.netbeans.core.menu;
41
41
42
import java.util.List;
43
import javax.swing.JComponent;
42
import javax.swing.JMenuBar;
44
import javax.swing.JMenuBar;
43
import org.openide.loaders.DataFolder;
45
import org.openide.loaders.DataFolder;
44
import org.openide.util.RequestProcessor;
46
import org.openide.util.RequestProcessor;
Lines 63-66 Link Here
63
    JMenuBar cachedComponent() {
65
    JMenuBar cachedComponent() {
64
        return bar;
66
        return bar;
65
    }
67
    }
68
69
    @Override
70
    protected void installComponents(List<? extends JComponent> components, JMenuBar into) {
71
        synchronized (bar.getTreeLock()) {
72
            super.installComponents(components, into);
73
        }
74
        bar.invalidate();
75
        bar.revalidate();
76
        bar.repaint();
77
    }
78
79
80
81
66
}
82
}
(-)a/core.menu/src/org/netbeans/core/menu/MenuProviderImpl.java (-4 / +17 lines)
Lines 40-45 Link Here
40
package org.netbeans.core.menu;
40
package org.netbeans.core.menu;
41
41
42
import java.awt.EventQueue;
42
import java.awt.EventQueue;
43
import java.awt.event.ComponentAdapter;
44
import java.awt.event.ComponentEvent;
45
import java.awt.event.HierarchyEvent;
46
import java.awt.event.HierarchyListener;
43
import javax.swing.JFrame;
47
import javax.swing.JFrame;
44
import javax.swing.JMenuBar;
48
import javax.swing.JMenuBar;
45
import org.netbeans.api.menus.MenuProvider;
49
import org.netbeans.api.menus.MenuProvider;
Lines 71-81 Link Here
71
        }
75
        }
72
        FileObject menuFO = menuFolder;
76
        FileObject menuFO = menuFolder;
73
        DataFolder menuFolder = DataFolder.findFolder(menuFO);
77
        DataFolder menuFolder = DataFolder.findFolder(menuFO);
74
        JMenuBar bar = new JMenuBar();
78
        final JMenuBar bar = new JMenuBar();
75
        bar.setBorderPainted(false);
79
        bar.setBorderPainted(false);
76
        MenuManager mgr = new MenuManager(menuFolder, bar);
80
        final MenuManager mgr = new MenuManager(menuFolder, bar);
77
        mgr.init();
81
        bar.addHierarchyListener(new HierarchyListener() {
82
83
            @Override
84
            public void hierarchyChanged(HierarchyEvent e) {
85
                if (bar.isShowing()) {
86
                    bar.removeHierarchyListener(this);
87
                    mgr.init();
88
                }
89
            }
90
        });
91
//        mgr.init();
78
        return bar;
92
        return bar;
79
    }
93
    }
80
81
}
94
}
(-)a/core.menu/src/org/netbeans/core/menu/ModelEntry.java (-1 / +35 lines)
Lines 67-73 Link Here
67
        Parameters.notNull("file", file);
67
        Parameters.notNull("file", file);
68
    }
68
    }
69
    
69
    
70
    protected abstract boolean initBackground(List<? super ModelEntry<?,?>> children);
70
    protected abstract boolean initBackground(List<? super ModelEntry<?,?>> children, int currDepth);
71
71
72
    public String getName() {
72
    public String getName() {
73
        DataObject file = file();
73
        DataObject file = file();
Lines 136-147 Link Here
136
            Icon icon = item.getIcon();
136
            Icon icon = item.getIcon();
137
            if (!wantIcons && icon != null) {
137
            if (!wantIcons && icon != null) {
138
                item.setIcon(null);
138
                item.setIcon(null);
139
                item.setDisabledIcon(null);
140
                item.setDisabledSelectedIcon(null);
139
            } else if (wantIcons && icon == null) {
141
            } else if (wantIcons && icon == null) {
140
                item.setIcon (BLANK_ICON);
142
                item.setIcon (BLANK_ICON);
143
                item.setDisabledIcon(BLANK_ICON);
144
                item.setDisabledSelectedIcon(BLANK_ICON);
141
            }
145
            }
146
//            String txt = item.getText();
147
//            if (txt != null && txt.contains("Find Issues")) {
148
//                Thread.dumpStack();
149
//                log (item);
150
//            }
142
        }
151
        }
143
    }
152
    }
144
153
154
//Useful for diagnosing strangely painting menu items
155
//    private static void log (JMenuItem item) {
156
//        System.err.println("FIND ISSUES ITEM: " + item);
157
//        logType (item);
158
//        System.err.println(" Action:");
159
//        logType (item.getAction());
160
//    }
161
//
162
//    private static void logType (Object o) {
163
//        if (o == null) return;
164
//        for (Class<?> c : o.getClass().getInterfaces()) {
165
//            System.err.println(" I:" + c.getName());
166
//        }
167
//        Class<?> x = o.getClass();
168
//        while (x != Object.class) {
169
//            System.err.println(" C: " + x.getName());
170
//            x = x.getSuperclass();
171
//        }
172
//    }
173
145
    protected static Boolean defaultHasIcon (JComponent comp, Boolean hasIcon) {
174
    protected static Boolean defaultHasIcon (JComponent comp, Boolean hasIcon) {
146
        if (hasIcon != null && hasIcon) {
175
        if (hasIcon != null && hasIcon) {
147
            return hasIcon;
176
            return hasIcon;
Lines 176-179 Link Here
176
        hash = 31 * hash + (this.file != null ? this.file.hashCode() : 0);
205
        hash = 31 * hash + (this.file != null ? this.file.hashCode() : 0);
177
        return hash;
206
        return hash;
178
    }
207
    }
208
209
    @Override
210
    public String toString() {
211
        return super.toString() + "[" + getName() + "]";
212
    }
179
}
213
}
(-)a/core.menu/src/org/netbeans/core/menu/RefreshingFolderModelEntry.java (-8 / +28 lines)
Lines 42-48 Link Here
42
import java.util.LinkedList;
42
import java.util.LinkedList;
43
import java.util.List;
43
import java.util.List;
44
import javax.swing.JComponent;
44
import javax.swing.JComponent;
45
import javax.swing.JMenuBar;
46
import org.openide.filesystems.FileAttributeEvent;
45
import org.openide.filesystems.FileAttributeEvent;
47
import org.openide.filesystems.FileChangeAdapter;
46
import org.openide.filesystems.FileChangeAdapter;
48
import org.openide.filesystems.FileEvent;
47
import org.openide.filesystems.FileEvent;
Lines 61-66 Link Here
61
    private final RequestProcessor.Task task;
60
    private final RequestProcessor.Task task;
62
    private FCA fca = new FCA();
61
    private FCA fca = new FCA();
63
    private static final int DELAY = 100;
62
    private static final int DELAY = 100;
63
    private static final boolean LOG_RUNNABLES = Boolean.getBoolean ("RefreshingFolderModelEntry.log");
64
64
65
    RefreshingFolderModelEntry(DataFolder dob, Class<T> compType, RequestProcessor rp) {
65
    RefreshingFolderModelEntry(DataFolder dob, Class<T> compType, RequestProcessor rp) {
66
        super(dob, compType);
66
        super(dob, compType);
Lines 70-79 Link Here
70
    }
70
    }
71
71
72
    @Override
72
    @Override
73
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children) {
73
    protected void onInitBackground(List<? super ModelEntry<?, ?>> children, int currDepth) {
74
        super.onInitBackground(children);
74
        super.onInitBackground(children, currDepth);
75
        if (!refreshing) {
75
        if (!refreshing && currDepth == 0) {
76
            EventQueue.invokeLater(fca);
76
            EventQueue.invokeLater(LOG_RUNNABLES ? new LogRunnable(fca) : fca);
77
        }
77
        }
78
    }
78
    }
79
79
Lines 84-89 Link Here
84
    }
84
    }
85
    volatile boolean refreshing;
85
    volatile boolean refreshing;
86
86
87
    private final class LogRunnable implements Runnable {
88
        Throwable t;
89
        private final Runnable real;
90
        LogRunnable (Runnable real) {
91
            this.real = real;
92
            t = new Exception("Refresh " + RefreshingFolderModelEntry.this).fillInStackTrace();
93
        }
94
95
        @Override
96
        public void run() {
97
            t.printStackTrace();
98
            real.run();
99
        }
100
    }
101
87
    private final class FCA extends FileChangeAdapter implements Runnable {
102
    private final class FCA extends FileChangeAdapter implements Runnable {
88
103
89
        private volatile boolean enqueued;
104
        private volatile boolean enqueued;
Lines 94-100 Link Here
94
                result = enqueued;
109
                result = enqueued;
95
                if (!enqueued) {
110
                if (!enqueued) {
96
                    enqueued = true;
111
                    enqueued = true;
97
                    task.schedule(DELAY);
112
                    if (!LOG_RUNNABLES) {
113
                        task.schedule(DELAY);
114
                    } else {
115
                        RequestProcessor.Task t = MenuManager.rp.create(new LogRunnable(this));
116
                        t.schedule(DELAY);
117
                    }
98
                }
118
                }
99
                return result;
119
                return result;
100
            }
120
            }
Lines 106-116 Link Here
106
                refreshing = true;
126
                refreshing = true;
107
                try {
127
                try {
108
                    List<ModelEntry<?, ?>> l = new LinkedList<ModelEntry<?, ?>>();
128
                    List<ModelEntry<?, ?>> l = new LinkedList<ModelEntry<?, ?>>();
109
                    initBackground(l);
129
                    initBackground(l, 0);
110
                    setChildren(l);
130
                    setChildren(l);
111
                } finally {
131
                } finally {
112
                    refreshing = false;
132
                    refreshing = false;
113
                    EventQueue.invokeLater(this);
133
                    EventQueue.invokeLater(LOG_RUNNABLES ? new LogRunnable(this) : this);
114
                }
134
                }
115
            } else {
135
            } else {
116
                enqueued = false;
136
                enqueued = false;
(-)a/core.menu/src/org/netbeans/core/menu/SeparatorModelEntry.java (-1 / +1 lines)
Lines 63-69 Link Here
63
    }
63
    }
64
64
65
    @Override
65
    @Override
66
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
66
    protected boolean initBackground(List<? super ModelEntry<?,?>> children, int currDepth) {
67
        return false;
67
        return false;
68
    }
68
    }
69
}
69
}
(-)a/core.menu/src/org/netbeans/core/menu/ThreadUnconstrainedModelEntry.java (-1 / +1 lines)
Lines 68-74 Link Here
68
    }
68
    }
69
69
70
    @Override
70
    @Override
71
    protected boolean initBackground(List<? super ModelEntry<?,?>> children) {
71
    protected boolean initBackground(List<? super ModelEntry<?,?>> children, int currDepth) {
72
        //Since it is non-gui, instantiate the Action in the background
72
        //Since it is non-gui, instantiate the Action in the background
73
        try {
73
        try {
74
            ref.set(super.get());
74
            ref.set(super.get());
(-)a/core.menu/test/unit/src/org/netbeans/core/menu/MenuProviderImplTest.java (-6 / +4 lines)
Lines 108-121 Link Here
108
108
109
            public void run() {
109
            public void run() {
110
                ((AbstractButton) comp).getModel().setPressed(showMenu);
110
                ((AbstractButton) comp).getModel().setPressed(showMenu);
111
                MouseEvent evt = new MouseEvent(comp, MouseEvent.MOUSE_PRESSED, System.currentTimeMillis(),
111
                MouseEvent evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_PRESSED);
112
                        0, 5, 5, 1, false, 0);
113
                comp.dispatchEvent(evt);
112
                comp.dispatchEvent(evt);
114
                evt = new MouseEvent(comp, MouseEvent.MOUSE_RELEASED, System.currentTimeMillis(),
113
                evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_RELEASED);
115
                        0, 5, 5, 1, false, 0);
116
                comp.dispatchEvent(evt);
114
                comp.dispatchEvent(evt);
117
                evt = new MouseEvent(comp, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(),
115
                evt = EventBlocker.mouseEvent(comp, MouseEvent.MOUSE_CLICKED);
118
                        0, 5, 5, 1, false, 0);
119
                comp.dispatchEvent(evt);
116
                comp.dispatchEvent(evt);
120
            }
117
            }
121
        });
118
        });
Lines 129-134 Link Here
129
126
130
    @Test
127
    @Test
131
    public void testMenuItemsAreNotStronglyReferenced() throws Exception {
128
    public void testMenuItemsAreNotStronglyReferenced() throws Exception {
129
        EventBlocker.init();
132
        assertNotNull (menu);
130
        assertNotNull (menu);
133
        click (menu, true);
131
        click (menu, true);
134
        JPopupMenu popup = menu.getPopupMenu();
132
        JPopupMenu popup = menu.getPopupMenu();

Return to bug 182698