1/*
2 * Copyright (c) 2008, 2016, 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.coordinator;
25
26import com.sun.hotspot.igv.connection.Server;
27import com.sun.hotspot.igv.coordinator.actions.*;
28import com.sun.hotspot.igv.data.GraphDocument;
29import com.sun.hotspot.igv.data.Group;
30import com.sun.hotspot.igv.data.services.GroupCallback;
31import java.awt.BorderLayout;
32import java.io.IOException;
33import java.io.ObjectInput;
34import java.io.ObjectOutput;
35import java.io.Serializable;
36import javax.swing.UIManager;
37import javax.swing.border.Border;
38import org.openide.ErrorManager;
39import org.openide.actions.GarbageCollectAction;
40import org.openide.awt.Toolbar;
41import org.openide.awt.ToolbarPool;
42import org.openide.explorer.ExplorerManager;
43import org.openide.explorer.ExplorerUtils;
44import org.openide.explorer.view.BeanTreeView;
45import org.openide.util.LookupEvent;
46import org.openide.util.LookupListener;
47import org.openide.util.NbBundle;
48import org.openide.util.actions.NodeAction;
49import org.openide.windows.TopComponent;
50import org.openide.windows.WindowManager;
51
52/**
53 *
54 * @author Thomas Wuerthinger
55 */
56public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
57
58    public static OutlineTopComponent instance;
59    public static final String PREFERRED_ID = "OutlineTopComponent";
60    private ExplorerManager manager;
61    private GraphDocument document;
62    private FolderNode root;
63    private Server server;
64    private Server binaryServer;
65
66    private OutlineTopComponent() {
67        initComponents();
68
69        setName(NbBundle.getMessage(OutlineTopComponent.class, "CTL_OutlineTopComponent"));
70        setToolTipText(NbBundle.getMessage(OutlineTopComponent.class, "HINT_OutlineTopComponent"));
71
72        document = new GraphDocument();
73        initListView();
74        initToolbar();
75        initReceivers();
76    }
77
78    private void initListView() {
79        manager = new ExplorerManager();
80        root = new FolderNode(document);
81        manager.setRootContext(root);
82        ((BeanTreeView) this.treeView).setRootVisible(false);
83
84        associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
85    }
86
87    private void initToolbar() {
88
89        Toolbar toolbar = new Toolbar();
90        Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N
91        toolbar.setBorder(b);
92        this.add(toolbar, BorderLayout.NORTH);
93
94        toolbar.add(ImportAction.get(ImportAction.class));
95
96        toolbar.add(((NodeAction) SaveAsAction.get(SaveAsAction.class)).createContextAwareInstance(this.getLookup()));
97        toolbar.add(SaveAllAction.get(SaveAllAction.class));
98
99        toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
100        toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
101
102        toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
103
104        for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
105            tb.setVisible(false);
106        }
107    }
108
109    private void initReceivers() {
110
111        final GroupCallback callback = new GroupCallback() {
112
113            @Override
114            public void started(Group g) {
115                synchronized(OutlineTopComponent.this) {
116                    getDocument().addElement(g);
117                }
118            }
119        };
120
121        server = new Server(getDocument(), callback, false);
122        binaryServer = new Server(getDocument(), callback, true);
123    }
124
125    public void clear() {
126        document.clear();
127        root = new FolderNode(document);
128        manager.setRootContext(root);
129    }
130
131    @Override
132    public ExplorerManager getExplorerManager() {
133        return manager;
134    }
135
136    public GraphDocument getDocument() {
137        return document;
138    }
139
140    /**
141     * Gets default instance. Do not use directly: reserved for *.settings files only,
142     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
143     * To obtain the singleton instance, use {@link findInstance}.
144     */
145    public static synchronized OutlineTopComponent getDefault() {
146        if (instance == null) {
147            instance = new OutlineTopComponent();
148        }
149        return instance;
150    }
151
152    /**
153     * Obtain the OutlineTopComponent instance. Never call {@link #getDefault} directly!
154     */
155    public static synchronized OutlineTopComponent findInstance() {
156        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
157        if (win == null) {
158            ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Outline component. It will not be located properly in the window system.");
159            return getDefault();
160        }
161        if (win instanceof OutlineTopComponent) {
162            return (OutlineTopComponent) win;
163        }
164        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.");
165        return getDefault();
166    }
167
168    @Override
169    public int getPersistenceType() {
170        return TopComponent.PERSISTENCE_ALWAYS;
171    }
172
173    @Override
174    public void componentOpened() {
175        this.requestActive();
176    }
177
178    @Override
179    public void componentClosed() {
180    }
181
182    @Override
183    protected String preferredID() {
184        return PREFERRED_ID;
185    }
186
187    @Override
188    public void requestActive() {
189        super.requestActive();
190        treeView.requestFocus();
191    }
192
193    @Override
194    public boolean requestFocus(boolean temporary) {
195        treeView.requestFocus();
196        return super.requestFocus(temporary);
197    }
198
199    @Override
200    protected boolean requestFocusInWindow(boolean temporary) {
201        treeView.requestFocus();
202        return super.requestFocusInWindow(temporary);
203    }
204
205    @Override
206    public void resultChanged(LookupEvent lookupEvent) {
207    }
208
209    @Override
210    public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
211        // Not called when user starts application for the first time
212        super.readExternal(objectInput);
213        ((BeanTreeView) this.treeView).setRootVisible(false);
214    }
215
216    @Override
217    public void writeExternal(ObjectOutput objectOutput) throws IOException {
218        super.writeExternal(objectOutput);
219    }
220
221    static final class ResolvableHelper implements Serializable {
222
223        private static final long serialVersionUID = 1L;
224
225        public Object readResolve() {
226            return OutlineTopComponent.getDefault();
227        }
228    }
229
230    /** This method is called from within the constructor to
231     * initialize the form.
232     * WARNING: Do NOT modify this code. The content of this method is
233     * always regenerated by the Form Editor.
234     */
235    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
236    private void initComponents() {
237
238        treeView = new BeanTreeView();
239
240        setLayout(new java.awt.BorderLayout());
241        add(treeView, java.awt.BorderLayout.CENTER);
242    }// </editor-fold>//GEN-END:initComponents
243
244    // Variables declaration - do not modify//GEN-BEGIN:variables
245    private javax.swing.JScrollPane treeView;
246    // End of variables declaration//GEN-END:variables
247}
248