1/*
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24package com.sun.hotspot.igv.bytecodes;
25
26import com.sun.hotspot.igv.data.Group;
27import com.sun.hotspot.igv.data.InputGraph;
28import com.sun.hotspot.igv.data.services.InputGraphProvider;
29import com.sun.hotspot.igv.util.LookupHistory;
30import java.awt.BorderLayout;
31import java.io.Serializable;
32import javax.swing.SwingUtilities;
33import org.openide.ErrorManager;
34import org.openide.explorer.ExplorerManager;
35import org.openide.explorer.ExplorerUtils;
36import org.openide.explorer.view.BeanTreeView;
37import org.openide.util.*;
38import org.openide.windows.TopComponent;
39import org.openide.windows.WindowManager;
40
41/**
42 * @author Thomas Wuerthinger
43 */
44final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
45
46    private static BytecodeViewTopComponent instance;
47    private static final String PREFERRED_ID = "BytecodeViewTopComponent";
48    private ExplorerManager manager;
49    private BeanTreeView treeView;
50    private Lookup.Result result = null;
51    private MethodNode rootNode;
52
53    private BytecodeViewTopComponent() {
54        initComponents();
55        setName(NbBundle.getMessage(BytecodeViewTopComponent.class, "CTL_BytecodeViewTopComponent"));
56        setToolTipText(NbBundle.getMessage(BytecodeViewTopComponent.class, "HINT_BytecodeViewTopComponent"));
57
58        manager = new ExplorerManager();
59        rootNode = new MethodNode(null, null, "");
60        manager.setRootContext(rootNode);
61
62        setLayout(new BorderLayout());
63
64        treeView = new BeanTreeView();
65        treeView.setRootVisible(false);
66        this.add(BorderLayout.CENTER, treeView);
67        associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
68    }
69
70    /** This method is called from within the constructor to
71     * initialize the form.
72     * WARNING: Do NOT modify this code. The content of this method is
73     * always regenerated by the Form Editor.
74     */
75    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
76    private void initComponents() {
77
78        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
79        this.setLayout(layout);
80        layout.setHorizontalGroup(
81            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
82            .add(0, 400, Short.MAX_VALUE)
83        );
84        layout.setVerticalGroup(
85            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
86            .add(0, 300, Short.MAX_VALUE)
87        );
88    }// </editor-fold>//GEN-END:initComponents
89    // Variables declaration - do not modify//GEN-BEGIN:variables
90    // End of variables declaration//GEN-END:variables
91
92    /**
93     * Gets default instance. Do not use directly: reserved for *.settings files only,
94     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
95     * To obtain the singleton instance, use {@link findInstance}.
96     */
97    public static synchronized BytecodeViewTopComponent getDefault() {
98        if (instance == null) {
99            instance = new BytecodeViewTopComponent();
100        }
101        return instance;
102    }
103
104    /**
105     * Obtain the BytecodeViewTopComponent instance. Never call {@link #getDefault} directly!
106     */
107    public static synchronized BytecodeViewTopComponent findInstance() {
108        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
109        if (win == null) {
110            ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find BytecodeView component. It will not be located properly in the window system.");
111            return getDefault();
112        }
113        if (win instanceof BytecodeViewTopComponent) {
114            return (BytecodeViewTopComponent) win;
115        }
116        ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior.");
117        return getDefault();
118    }
119
120    @Override
121    public int getPersistenceType() {
122        return TopComponent.PERSISTENCE_ALWAYS;
123    }
124
125    @Override
126    public void componentOpened() {
127        Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
128        result = Utilities.actionsGlobalContext().lookup(tpl);
129        result.addLookupListener(this);
130    }
131
132    @Override
133    public void componentClosed() {
134        result.removeLookupListener(this);
135        result = null;
136    }
137
138    @Override
139    public Object writeReplace() {
140        return new ResolvableHelper();
141    }
142
143    @Override
144    protected String preferredID() {
145        return PREFERRED_ID;
146    }
147
148    @Override
149    public ExplorerManager getExplorerManager() {
150        return manager;
151    }
152
153    @Override
154    public void requestActive() {
155        super.requestActive();
156        this.treeView.requestFocus();
157    }
158
159    @Override
160    public boolean requestFocus(boolean temporary) {
161        this.treeView.requestFocus();
162        return super.requestFocus(temporary);
163    }
164
165    @Override
166    protected boolean requestFocusInWindow(boolean temporary) {
167        this.treeView.requestFocus();
168        return super.requestFocusInWindow(temporary);
169    }
170
171    @Override
172    public void resultChanged(LookupEvent lookupEvent) {
173        final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
174            SwingUtilities.invokeLater(new Runnable() {
175                @Override
176                public void run() {
177                if (p != null) {
178                    InputGraph graph = p.getGraph();
179                    if (graph != null) {
180                        Group g = graph.getGroup();
181                        rootNode.update(graph, g.getMethod());
182                        return;
183                    }
184                }
185                        rootNode.update(null, null);
186                    }
187            });
188
189    }
190
191    final static class ResolvableHelper implements Serializable {
192
193        private static final long serialVersionUID = 1L;
194
195        public Object readResolve() {
196            return BytecodeViewTopComponent.getDefault();
197        }
198    }
199}
200