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 262312
Collapse All | Expand All

(-)a/spi.debugger.ui/apichanges.xml (+20 lines)
Lines 248-253 Link Here
248
        <issue number="251531"/>
248
        <issue number="251531"/>
249
    </change>
249
    </change>
250
250
251
    <change id="tooltip-ui">
252
        <api name="DebuggerCoreSPI"/>
253
        <summary>Tooltip view added.</summary>
254
        <version major="2" minor="54"/>
255
        <date day="14" month="6" year="2016"/>
256
        <author login="mentlicher"/>
257
        <compatibility binary="compatible" source="compatible" modification="yes" semantic="compatible"/>
258
        <description>
259
            <p>
260
                Tooltip view is added into APIs.
261
                It's accessible via <code>createToolTip</code> method in <code>ViewFactory</code>,
262
                or <code>AbstractExpandToolTipAction</code>.
263
                Default model filters are pre-registered under <code>ToolTipView</code> name
264
                and they define the expanded tooltip node.
265
            </p>
266
        </description>
267
        <class package="org.netbeans.spi.debugger.ui" name="ToolTipUI"/>
268
        <issue number="262312"/>
269
    </change>
270
251
</changes>
271
</changes>
252
272
253
  <!-- Now the surrounding HTML text and document structure: -->
273
  <!-- Now the surrounding HTML text and document structure: -->
(-)a/spi.debugger.ui/manifest.mf (-1 / +1 lines)
Lines 2-7 Link Here
2
OpenIDE-Module: org.netbeans.spi.debugger.ui/1
2
OpenIDE-Module: org.netbeans.spi.debugger.ui/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/debugger/ui/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/debugger/ui/Bundle.properties
4
OpenIDE-Module-Layer: org/netbeans/modules/debugger/resources/mf-layer.xml
4
OpenIDE-Module-Layer: org/netbeans/modules/debugger/resources/mf-layer.xml
5
OpenIDE-Module-Specification-Version: 2.53
5
OpenIDE-Module-Specification-Version: 2.54
6
OpenIDE-Module-Provides: org.netbeans.spi.debugger.ui
6
OpenIDE-Module-Provides: org.netbeans.spi.debugger.ui
7
OpenIDE-Module-Install: org/netbeans/modules/debugger/ui/DebuggerModule.class
7
OpenIDE-Module-Install: org/netbeans/modules/debugger/ui/DebuggerModule.class
(-)03b2f960a7c3 (+82 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2012 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.debugger.ui.models;
43
44
import org.netbeans.modules.debugger.ui.views.ToolTipView;
45
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
46
import org.netbeans.spi.viewmodel.ModelListener;
47
import org.netbeans.spi.viewmodel.TreeExpansionModel;
48
import org.netbeans.spi.viewmodel.TreeExpansionModelFilter;
49
import org.netbeans.spi.viewmodel.UnknownTypeException;
50
51
/**
52
 * Assures that the variable in tooltip is expanded automatically.
53
 * 
54
 * @author Martin Entlicher
55
 */
56
@DebuggerServiceRegistration(path="ToolTipView",
57
                             types=TreeExpansionModelFilter.class,
58
                             position=10200)
59
public class ToolTipExpansionFilter implements TreeExpansionModelFilter {
60
61
    @Override
62
    public boolean isExpanded(TreeExpansionModel original, Object node) throws UnknownTypeException {
63
        if (node == ToolTipView.getVariable()) {
64
            return true;
65
        } else {
66
            return original.isExpanded(node);
67
        }
68
    }
69
70
    @Override
71
    public void nodeExpanded(Object node) {}
72
73
    @Override
74
    public void nodeCollapsed(Object node) {}
75
76
    @Override
77
    public void addModelListener(ModelListener l) {}
78
79
    @Override
80
    public void removeModelListener(ModelListener l) {}
81
82
}
(-)03b2f960a7c3 (+138 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.debugger.ui.models;
44
45
import java.awt.datatransfer.Transferable;
46
import java.io.IOException;
47
import org.netbeans.modules.debugger.ui.views.ToolTipView;
48
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
49
import org.netbeans.spi.viewmodel.ExtendedNodeModel;
50
import org.netbeans.spi.viewmodel.ExtendedNodeModelFilter;
51
import org.netbeans.spi.viewmodel.ModelListener;
52
import org.netbeans.spi.viewmodel.NodeModel;
53
import org.netbeans.spi.viewmodel.UnknownTypeException;
54
import org.openide.util.datatransfer.PasteType;
55
56
/**
57
 *
58
 * @author martin
59
 */
60
@DebuggerServiceRegistration(path="ToolTipView",
61
                             types=ExtendedNodeModelFilter.class,
62
                             position=10100)
63
public class ToolTipNodeModelFilter implements ExtendedNodeModelFilter {
64
65
    @Override
66
    public String getDisplayName(NodeModel original, Object node) throws UnknownTypeException {
67
        String dn;
68
        try {
69
            dn = original.getDisplayName(node);
70
        } catch (UnknownTypeException utex) {
71
            dn = "";
72
        }
73
        if (node == ToolTipView.getVariable() && dn.length() == 0) {
74
            return ToolTipView.getExpression();
75
        } else {
76
            return dn;
77
        }
78
    }
79
80
    @Override
81
    public String getIconBase(NodeModel original, Object node) throws UnknownTypeException {
82
        return original.getIconBase(node);
83
    }
84
85
    @Override
86
    public String getShortDescription(NodeModel original, Object node) throws UnknownTypeException {
87
        return original.getShortDescription(node);
88
    }
89
90
    @Override
91
    public void addModelListener(ModelListener l) {
92
    }
93
94
    @Override
95
    public void removeModelListener(ModelListener l) {
96
    }
97
98
    @Override
99
    public boolean canRename(ExtendedNodeModel original, Object node) throws UnknownTypeException {
100
        return original.canRename(node);
101
    }
102
103
    @Override
104
    public boolean canCopy(ExtendedNodeModel original, Object node) throws UnknownTypeException {
105
        return original.canCopy(node);
106
    }
107
108
    @Override
109
    public boolean canCut(ExtendedNodeModel original, Object node) throws UnknownTypeException {
110
        return original.canCut(node);
111
    }
112
113
    @Override
114
    public Transferable clipboardCopy(ExtendedNodeModel original, Object node) throws IOException, UnknownTypeException {
115
        return original.clipboardCopy(node);
116
    }
117
118
    @Override
119
    public Transferable clipboardCut(ExtendedNodeModel original, Object node) throws IOException, UnknownTypeException {
120
        return original.clipboardCut(node);
121
    }
122
123
    @Override
124
    public PasteType[] getPasteTypes(ExtendedNodeModel original, Object node, Transferable t) throws UnknownTypeException {
125
        return original.getPasteTypes(node, t);
126
    }
127
128
    @Override
129
    public void setName(ExtendedNodeModel original, Object node, String name) throws UnknownTypeException {
130
        original.setName(node, name);
131
    }
132
133
    @Override
134
    public String getIconBaseWithExtension(ExtendedNodeModel original, Object node) throws UnknownTypeException {
135
        return original.getIconBaseWithExtension(node);
136
    }
137
138
}
(-)03b2f960a7c3 (+98 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2010 Sun Microsystems, Inc.
41
 */
42
43
package org.netbeans.modules.debugger.ui.models;
44
45
import org.netbeans.modules.debugger.ui.views.ToolTipView;
46
import org.netbeans.spi.debugger.DebuggerServiceRegistration;
47
import org.netbeans.spi.viewmodel.ModelListener;
48
import org.netbeans.spi.viewmodel.TreeModel;
49
import org.netbeans.spi.viewmodel.TreeModelFilter;
50
import org.netbeans.spi.viewmodel.UnknownTypeException;
51
52
/**
53
 *
54
 * @author martin
55
 */
56
@DebuggerServiceRegistration(path="ToolTipView",
57
                             types=TreeModelFilter.class,
58
                             position=10000)
59
public class ToolTipTreeModelFilter implements TreeModelFilter {
60
61
    @Override
62
    public Object getRoot(TreeModel original) {
63
        return original.getRoot();
64
    }
65
66
    @Override
67
    public Object[] getChildren(TreeModel original, Object parent, int from, int to) throws UnknownTypeException {
68
        if (parent == TreeModel.ROOT) {
69
            Object tooltipVar = ToolTipView.getVariable();
70
            if (tooltipVar != null) {
71
                return new Object[] { tooltipVar };
72
            } else {
73
                return new Object[] { };
74
            }
75
        } else {
76
            return original.getChildren(parent, from, to);
77
        }
78
    }
79
80
    @Override
81
    public int getChildrenCount(TreeModel original, Object node) throws UnknownTypeException {
82
        return Integer.MAX_VALUE;
83
    }
84
85
    @Override
86
    public boolean isLeaf(TreeModel original, Object node) throws UnknownTypeException {
87
        return original.isLeaf(node);
88
    }
89
90
    @Override
91
    public void addModelListener(ModelListener l) {
92
    }
93
94
    @Override
95
    public void removeModelListener(ModelListener l) {
96
    }
97
98
}
(-)03b2f960a7c3 (+336 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2016 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * Contributor(s):
28
 *
29
 * The Original Software is NetBeans. The Initial Developer of the Original
30
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
31
 * Microsystems, Inc. All Rights Reserved.
32
 *
33
 * If you wish your version of this file to be governed by only the CDDL
34
 * or only the GPL Version 2, indicate your decision by adding
35
 * "[Contributor] elects to include this software in this distribution
36
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37
 * single choice of license, a recipient has the option to distribute
38
 * your version of this file under either the CDDL, the GPL Version 2 or
39
 * to extend the choice of license to its licensees as provided above.
40
 * However, if you add GPL Version 2 code and therefore, elected the GPL
41
 * Version 2 license, then the option applies only if the new code is
42
 * made subject to such option by the copyright holder.
43
 */
44
45
package org.netbeans.modules.debugger.ui.views;
46
47
import java.awt.BorderLayout;
48
import java.awt.Color;
49
import java.awt.Dimension;
50
import java.awt.Font;
51
import java.awt.Insets;
52
import java.awt.Point;
53
import java.awt.event.ActionEvent;
54
import java.awt.event.ActionListener;
55
import java.awt.event.KeyEvent;
56
import javax.swing.AbstractAction;
57
import javax.swing.ActionMap;
58
import javax.swing.BorderFactory;
59
import javax.swing.BoxLayout;
60
import javax.swing.Icon;
61
import javax.swing.InputMap;
62
import javax.swing.JButton;
63
import javax.swing.JComponent;
64
import static javax.swing.JComponent.WHEN_FOCUSED;
65
import javax.swing.JPanel;
66
import javax.swing.JTextArea;
67
import javax.swing.KeyStroke;
68
import javax.swing.SwingUtilities;
69
import javax.swing.UIManager;
70
import javax.swing.text.BadLocationException;
71
import javax.swing.text.Document;
72
import javax.swing.text.Keymap;
73
import org.netbeans.spi.debugger.ui.ViewFactory;
74
import org.openide.util.ImageUtilities;
75
76
public final class ToolTipView extends JComponent implements org.openide.util.HelpCtx.Provider {
77
78
    public static final String TOOLTIP_VIEW_NAME = "ToolTipView";               // NOI18N
79
    private static final String TOOLTIP_HELP_ID = "NetbeansDebuggerToolTipNode";// NOI18N
80
81
    private static volatile String expression;
82
    private static volatile Object variable;
83
84
    private transient JComponent contentComponent;
85
86
    private ToolTipView(String expression, Object v, String icon) {
87
        ToolTipView.expression = expression;
88
        variable = v;
89
        JComponent c = ViewFactory.getDefault().createViewComponent(
90
                icon,
91
                ToolTipView.TOOLTIP_VIEW_NAME,
92
                TOOLTIP_HELP_ID,
93
                null);
94
        setLayout (new BorderLayout ());
95
        add (c, BorderLayout.CENTER);  //NOI18N
96
    }
97
98
    public static String getExpression() {
99
        return expression;
100
    }
101
102
    public static Object getVariable() {
103
        return variable;
104
    }
105
106
    @Override
107
    public void removeNotify() {
108
        super.removeNotify();
109
        variable = null;
110
    }
111
112
    // <RAVE>
113
    // Implement getHelpCtx() with the correct help ID
114
    @Override
115
    public org.openide.util.HelpCtx getHelpCtx() {
116
        return new org.openide.util.HelpCtx(TOOLTIP_HELP_ID);
117
    }
118
    // </RAVE>
119
120
    @Override
121
    public boolean requestFocusInWindow () {
122
        super.requestFocusInWindow ();
123
        if (contentComponent == null) {
124
            return false;
125
        }
126
        return contentComponent.requestFocusInWindow ();
127
    }
128
129
    /** Creates the view. */
130
    public static synchronized ToolTipView createToolTipView(String expression, Object variable) {
131
        return new ToolTipView(
132
                expression,
133
                variable,
134
                "org/netbeans/modules/debugger/resources/localsView/local_variable_16.png"
135
        );
136
    }
137
138
    public static class ExpandableTooltip extends JPanel {
139
140
        private static final String UI_PREFIX = "ToolTip"; // NOI18N
141
142
        private JButton expButton;
143
        private JButton pinButton;
144
        private JComponent textToolTip;
145
        private boolean widthCheck = true;
146
        private boolean sizeSet = false;
147
148
        public ExpandableTooltip(String toolTipText, boolean expandable, boolean pinnable) {
149
            Font font = UIManager.getFont(UI_PREFIX + ".font");                 // NOI18N
150
            Color backColor = UIManager.getColor(UI_PREFIX + ".background");    // NOI18N
151
            Color foreColor = UIManager.getColor(UI_PREFIX + ".foreground");    // NOI18N
152
153
            if (backColor != null) {
154
                setBackground(backColor);
155
            }
156
            setOpaque(true);
157
            setBorder(BorderFactory.createCompoundBorder(
158
                BorderFactory.createLineBorder(getForeground()),
159
                BorderFactory.createEmptyBorder(0, 3, 0, 3)
160
            ));
161
162
            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
163
            if (pinnable) {
164
                pinButton = new JButton(ImageUtilities.loadImageIcon("org/netbeans/editor/resources/pin.png", false));
165
                pinButton.setBorder(new javax.swing.border.EmptyBorder(0, 3, 0, 0));
166
                pinButton.setBorderPainted(false);
167
                pinButton.setContentAreaFilled(false);
168
                add(pinButton);
169
            }
170
            if (expandable) {
171
                Icon expIcon = UIManager.getIcon ("Tree.collapsedIcon");        // NOI18N
172
                expButton = new JButton(expIcon);
173
                expButton.setBorder(new javax.swing.border.EmptyBorder(0, 0, 0, 5));
174
                expButton.setBorderPainted(false);
175
                expButton.setContentAreaFilled(false);
176
                add(expButton);
177
            }
178
            //JLabel l = new JLabel(toolTipText);
179
            // Multi-line tooltip:
180
            JTextArea l = createMultiLineToolTip(toolTipText, true);
181
            if (font != null) {
182
                l.setFont(font);
183
            }
184
            if (foreColor != null) {
185
                l.setForeground(foreColor);
186
            }
187
            if (backColor != null) {
188
                l.setBackground(backColor);
189
            }
190
            l.setBorder(new javax.swing.border.EmptyBorder(0, 3, 0, 3));
191
            textToolTip = l;
192
            add(l);
193
            if (expandable || pinnable) {
194
                InputMap im = new InputMap();
195
                im.setParent(getInputMap());
196
                setInputMap(WHEN_FOCUSED, im);
197
                ActionMap am = new ActionMap();
198
                am.setParent(getActionMap());
199
                setActionMap(am);
200
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "expand"); // NOI18N
201
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "pin");    // NOI18N
202
                if (expandable) {
203
                    am.put("expand", new AbstractAction() {                     // NOI18N
204
                        @Override
205
                        public void actionPerformed(ActionEvent e) {
206
                            expButton.doClick();
207
                        }
208
                    });
209
                }
210
                if (pinnable) {
211
                    am.put("pin", new AbstractAction() {                        // NOI18N
212
                        @Override
213
                        public void actionPerformed(ActionEvent e) {
214
                            SwingUtilities.invokeLater(() -> pinButton.doClick());
215
                        }
216
                    });
217
                }
218
            }
219
        }
220
221
        public void addExpansionListener(ActionListener treeExpansionListener) {
222
            expButton.addActionListener(treeExpansionListener);
223
        }
224
225
        public void addPinListener(ActionListener treeExpansionListener) {
226
            pinButton.addActionListener(treeExpansionListener);
227
        }
228
229
        public void setWidthCheck(boolean widthCheck) {
230
            this.widthCheck = widthCheck;
231
        }
232
233
        @Override
234
        public Dimension getPreferredSize() {
235
            if (!sizeSet) {
236
                // Be big enough initially.
237
                return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
238
            }
239
            Dimension preferredSize = super.getPreferredSize();
240
            // Let the width be as long as it can be
241
            return new Dimension(Integer.MAX_VALUE, preferredSize.height);
242
        }
243
244
        @Override
245
        public void setSize(int width, int height) {
246
            Dimension prefSize = getPreferredSize();
247
            Dimension button1Size = (expButton != null) ? expButton.getPreferredSize() : new Dimension(0, 0);
248
            Dimension button2Size = pinButton.getPreferredSize();
249
            if (widthCheck) {
250
                Insets insets = getInsets();
251
                int textWidth = width - insets.left - button1Size.width - button2Size.width - insets.right;
252
                height = Math.max(Math.max(height, button1Size.height), button2Size.height);
253
                textToolTip.setSize(textWidth, height);
254
                Dimension textPreferredSize = textToolTip.getPreferredSize();
255
                super.setSize(
256
                        insets.left + button1Size.width + button2Size.width + textPreferredSize.width + insets.right,
257
                        insets.top + Math.max(Math.max(button1Size.height, textPreferredSize.height), button2Size.height) + insets.bottom);
258
            } else {
259
                if (height >= prefSize.height) { // enough height
260
                    height = prefSize.height;
261
                }
262
                super.setSize(width, height);
263
            }
264
            sizeSet = true;
265
        }
266
267
        private static JTextArea createMultiLineToolTip(String toolTipText, boolean wrapLines) {
268
            JTextArea ta = new TextToolTip(wrapLines);
269
            ta.setText(toolTipText);
270
            return ta;
271
        }
272
273
        private static class TextToolTip extends JTextArea {
274
275
            private static final String ELIPSIS = "..."; //NOI18N
276
277
            private final boolean wrapLines;
278
279
            public TextToolTip(boolean wrapLines) {
280
                this.wrapLines = wrapLines;
281
                setLineWrap(false); // It's necessary to have a big width of preferred size first.
282
            }
283
284
            public @Override void setSize(int width, int height) {
285
                Dimension prefSize = getPreferredSize();
286
                if (width >= prefSize.width) {
287
                    width = prefSize.width;
288
                } else { // smaller available width
289
                    // Set line wrapping and do super.setSize() to determine
290
                    // the real height (it will change due to line wrapping)
291
                    if (wrapLines) {
292
                        setLineWrap(true);
293
                        setWrapStyleWord(true);
294
                    }
295
                    
296
                    super.setSize(width, Integer.MAX_VALUE); // the height is unimportant
297
                    prefSize = getPreferredSize(); // re-read new pref width
298
                }
299
                if (height >= prefSize.height) { // enough height
300
                    height = prefSize.height;
301
                } else { // smaller available height
302
                    // Check how much can be displayed - cannot rely on line count
303
                    // because line wrapping may display single physical line
304
                    // into several visual lines
305
                    // Before using viewToModel() a setSize() must be called
306
                    // because otherwise the viewToModel() would return -1.
307
                    super.setSize(width, Integer.MAX_VALUE);
308
                    int offset = viewToModel(new Point(0, height));
309
                    Document doc = getDocument();
310
                    try {
311
                        if (offset > ELIPSIS.length()) {
312
                            offset -= ELIPSIS.length();
313
                            doc.remove(offset, doc.getLength() - offset);
314
                            doc.insertString(offset, ELIPSIS, null);
315
                        }
316
                    } catch (BadLocationException ble) {
317
                        // "..." will likely not be displayed but otherwise should be ok
318
                    }
319
                    // Recalculate the prefSize as it may be smaller
320
                    // than the present preferred height
321
                    height = Math.min(height, getPreferredSize().height);
322
                }
323
                super.setSize(width, height);
324
            }
325
326
            @Override
327
            public void setKeymap(Keymap map) {
328
                //#181722: keymaps are shared among components with the same UI
329
                //a default action will be set to the Keymap of this component below,
330
                //so it is necessary to use a Keymap that is not shared with other JTextAreas
331
                super.setKeymap(addKeymap(null, map));
332
            }
333
        }
334
    }
335
336
}
(-)03b2f960a7c3 (+144 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2016 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2016 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.debugger.ui;
43
44
import java.awt.event.ActionEvent;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
47
import javax.swing.AbstractAction;
48
import javax.swing.Action;
49
import javax.swing.Icon;
50
import javax.swing.JEditorPane;
51
import javax.swing.UIManager;
52
import org.netbeans.editor.EditorUI;
53
import org.netbeans.editor.Utilities;
54
import org.netbeans.editor.ext.ToolTipSupport;
55
import org.netbeans.modules.debugger.ui.views.ToolTipView;
56
57
/**
58
 * A base class for an action that shows an expanded tooltip.
59
 * It can be used as a
60
 * {@link PinWatchUISupport.ValueProvider#getHeadActions(org.netbeans.api.debugger.Watch) head action}
61
 * for a pin watch to display the structured value of a watch.
62
 * 
63
 * @since 2.54
64
 * @author Martin Entlicher
65
 */
66
public abstract class AbstractExpandToolTipAction extends AbstractAction {
67
68
    private final Icon toExpandIcon = UIManager.getIcon ("Tree.collapsedIcon"); // NOI18N
69
    private final Icon toCollapsIcon = UIManager.getIcon ("Tree.expandedIcon"); // NOI18N
70
    private boolean expanded;
71
72
    /**
73
     * Create a new expand tooltip action.
74
     */
75
    protected AbstractExpandToolTipAction() {
76
        putValue(Action.SMALL_ICON, toExpandIcon);
77
        putValue(Action.LARGE_ICON_KEY, toExpandIcon);
78
    }
79
80
    /**
81
     * Open a tooltip view.
82
     * Call {@link #openTooltipView(java.lang.String, java.lang.Object)} method
83
     * to open the tooltip view.
84
     */
85
    protected abstract void openTooltipView();
86
87
    /**
88
     * Open a tooltip view for the expression and variable the expression evaluates to.
89
     * @param expression the tooltip's expression
90
     * @param var the evaluated variable
91
     * @return An instance of tooltip support that allows to control the display
92
     * of the tooltip, or <code>null</code> when it's not possible to show it.
93
     * It can be used e.g. to close the tooltip when it's no longer applicable,
94
     * when the debugger resumes, etc.
95
     */
96
    protected final ToolTipSupport openTooltipView(String expression, Object var) {
97
        ToolTipView toolTipView = ToolTipView.createToolTipView(expression, var);
98
        JEditorPane currentEditor = EditorContextDispatcher.getDefault().getMostRecentEditor();
99
        EditorUI eui = Utilities.getEditorUI(currentEditor);
100
        if (eui != null) {
101
            final ToolTipSupport toolTipSupport = eui.getToolTipSupport();
102
            toolTipSupport.setToolTipVisible(true, false);
103
            toolTipSupport.setToolTip(toolTipView);
104
            toolTipSupport.addPropertyChangeListener(new PropertyChangeListener() {
105
                @Override
106
                public void propertyChange(PropertyChangeEvent evt) {
107
                    if (ToolTipSupport.PROP_STATUS.equals(evt.getPropertyName())) {
108
                        if (!toolTipSupport.isToolTipVisible()) {
109
                            expanded = false;
110
                            putValue(Action.SMALL_ICON, toExpandIcon);
111
                            putValue(Action.LARGE_ICON_KEY, toExpandIcon);
112
                            toolTipSupport.removePropertyChangeListener(this);
113
                        }
114
                    }
115
                }
116
            });
117
            return toolTipSupport;
118
        } else {
119
            return null;
120
        }
121
    }
122
123
    @Override
124
    public final void actionPerformed(ActionEvent e) {
125
        expanded = !expanded;
126
        if (expanded) {
127
            openTooltipView();
128
            putValue(Action.SMALL_ICON, toCollapsIcon);
129
            putValue(Action.LARGE_ICON_KEY, toCollapsIcon);
130
        } else {
131
            hideTooltipView();
132
            putValue(Action.SMALL_ICON, toExpandIcon);
133
            putValue(Action.LARGE_ICON_KEY, toExpandIcon);
134
        }
135
    }
136
137
    private void hideTooltipView() {
138
        JEditorPane currentEditor = EditorContextDispatcher.getDefault().getMostRecentEditor();
139
        EditorUI eui = Utilities.getEditorUI(currentEditor);
140
        if (eui != null) {
141
            eui.getToolTipSupport().setToolTipVisible(false, false);
142
        }
143
    }
144
}
(-)03b2f960a7c3 (+214 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2016 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2016 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.spi.debugger.ui;
43
44
import java.awt.Point;
45
import java.awt.event.ActionEvent;
46
import java.awt.event.ActionListener;
47
import javax.swing.BorderFactory;
48
import javax.swing.JEditorPane;
49
import javax.swing.SwingUtilities;
50
import javax.swing.text.Document;
51
import org.netbeans.api.debugger.DebuggerManager;
52
import org.netbeans.api.debugger.Watch;
53
import org.netbeans.editor.BaseDocument;
54
import org.netbeans.editor.EditorUI;
55
import org.netbeans.editor.PopupManager;
56
import org.netbeans.editor.Utilities;
57
import org.netbeans.editor.ext.ToolTipSupport;
58
import org.netbeans.modules.debugger.ui.views.ToolTipView;
59
import org.netbeans.modules.debugger.ui.views.ToolTipView.ExpandableTooltip;
60
import org.openide.filesystems.FileObject;
61
import org.openide.loaders.DataObject;
62
import org.openide.util.Exceptions;
63
64
/**
65
 * A representation of a tooltip with actions.
66
 * The actions are described by {@link Expandable} and {@link Pinnable} classes.
67
 * 
68
 * @since 2.54
69
 * @author Martin Entlicher
70
 */
71
public final class ToolTipUI {
72
73
    private final ExpandableTooltip et;
74
    private JEditorPane editorPane; // Editor pane the tooltip is showing on
75
76
    ToolTipUI(String toolTipText, Expandable expandable, Pinnable pinnable) {
77
        et = new ExpandableTooltip(toolTipText, expandable != null, pinnable != null);
78
        if (expandable != null) {
79
            et.addExpansionListener(new ExpansionListener(expandable));
80
        }
81
        if (pinnable != null) {
82
            et.addPinListener(new PinListener(pinnable));
83
        }
84
    }
85
86
    /**
87
     * Show the tooltip on the given editor pane.
88
     * @param editorPane The editor pane to show the tooltip on.
89
     * @return An instance of tooltip support that allows to control the display
90
     * of the tooltip, or <code>null</code> when it's not possible to show the
91
     * tooltip on the editor pane.
92
     * It can be used e.g. to close the tooltip when it's no longer applicable,
93
     * when the debugger resumes, etc.
94
     */
95
    public ToolTipSupport show(JEditorPane editorPane) {
96
        EditorUI eui = Utilities.getEditorUI(editorPane);
97
        if (eui != null) {
98
            eui.getToolTipSupport().setToolTip(et);
99
            this.editorPane = editorPane;
100
            return eui.getToolTipSupport();
101
        } else {
102
            return null;
103
        }
104
    }
105
106
    /**
107
     * Description of an expandable tooltip.
108
     * The expanded tooltip is a view created from models registered under
109
     * <code>ToolTipView</code> name. Default model filters are provided, which define
110
     * the expanded first node with <code>expression</code> name and <code>variable</code>
111
     * being the node's value.
112
     */
113
    public static final class Expandable {
114
        
115
        private final String expression;
116
        private final Object variable;
117
        
118
        /**
119
         * Create a description of expandable tooltip.
120
         * @param expression the tooltip's expression
121
         * @param variable the evaluated variable
122
         */
123
        public Expandable(String expression, Object variable) {
124
            this.expression = expression;
125
            this.variable = variable;
126
        }
127
    }
128
129
    /**
130
     * Description of a pinnable watch.
131
     * The pin watch is created from the provided parameters.
132
     */
133
    public static final class Pinnable {
134
        
135
        private final String expression;
136
        private final int line;
137
        private final String valueProviderId;
138
        
139
        /**
140
         * Create a description of pin watch
141
         * @param expression The pin watch expression
142
         * @param line Line to create the pin watch at
143
         * @param valueProviderId ID of the registered {@link PinWatchUISupport.ValueProvider value provider}
144
         */
145
        public Pinnable(String expression, int line, String valueProviderId) {
146
            this.expression = expression;
147
            this.line = line;
148
            this.valueProviderId = valueProviderId;
149
        }
150
    }
151
152
    private class ExpansionListener implements ActionListener {
153
154
        private final Expandable expandable;
155
        
156
        ExpansionListener(Expandable expandable) {
157
            this.expandable = expandable;
158
        }
159
        
160
        @Override
161
        public void actionPerformed(ActionEvent e) {
162
            et.setBorder(BorderFactory.createLineBorder(et.getForeground()));
163
            et.removeAll();
164
            et.setWidthCheck(false);
165
            final ToolTipView ttView = ToolTipView.createToolTipView(
166
                    expandable.expression,
167
                    expandable.variable);
168
            et.add(ttView);
169
            et.revalidate();
170
            et.repaint();
171
            SwingUtilities.invokeLater(() -> {
172
                EditorUI eui = Utilities.getEditorUI(editorPane);
173
                if (eui != null) {
174
                    eui.getToolTipSupport().setToolTip(et, PopupManager.ViewPortBounds,
175
                                                       PopupManager.AbovePreferred, 0, 0,
176
                                                       ToolTipSupport.FLAGS_HEAVYWEIGHT_TOOLTIP);
177
                } else {
178
                    throw new IllegalStateException("Have no EditorUI for "+editorPane);
179
                }
180
            });
181
        }
182
    }
183
184
    private class PinListener implements ActionListener {
185
        
186
        private final Pinnable pinnable;
187
188
        public PinListener(Pinnable pinnable) {
189
            this.pinnable = pinnable;
190
        }
191
192
        @Override
193
        public void actionPerformed(ActionEvent e) {
194
            EditorUI eui = Utilities.getEditorUI(editorPane);
195
            Point location = et.getLocation();
196
            location = eui.getStickyWindowSupport().convertPoint(location);
197
            eui.getToolTipSupport().setToolTipVisible(false);
198
            DebuggerManager dbMgr = DebuggerManager.getDebuggerManager();
199
            BaseDocument document = Utilities.getDocument(editorPane);
200
            DataObject dobj = (DataObject) document.getProperty(Document.StreamDescriptionProperty);
201
            FileObject fo = dobj.getPrimaryFile();
202
            Watch.Pin pin = new EditorPin(fo, pinnable.line, location);
203
            final Watch w = dbMgr.createPinnedWatch(pinnable.expression, pin);
204
            SwingUtilities.invokeLater(() -> {
205
                try {
206
                    PinWatchUISupport.getDefault().pin(w, pinnable.valueProviderId);
207
                } catch (IllegalArgumentException ex) {
208
                    Exceptions.printStackTrace(ex);
209
                }
210
            });
211
        }
212
    }
213
214
}
(-)a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewFactory.java (+17 lines)
Lines 113-116 Link Here
113
        return new ViewLifecycle(vml, cmul);
113
        return new ViewLifecycle(vml, cmul);
114
    }
114
    }
115
    
115
    
116
    /**
117
     * Create a tooltip with additional actions.
118
     * The tooltip can be expandable to a structured tooltip view, or pinnable as a pin watch.
119
     * @param toolTipText The text to display as a tooltip
120
     * @param expandable Description of an expanded tooltip,
121
     *                   or <code>null</code> when the tooltip is not expandable
122
     * @param pinnable Description of a pin watch created from this tooltip,
123
     *                 or <code>null</code> when the tooltip is not pinnable
124
     * @return A tooltip UI to be shown.
125
     * @since 2.54
126
     */
127
    public ToolTipUI createToolTip(String toolTipText,
128
                                   ToolTipUI.Expandable expandable,
129
                                   ToolTipUI.Pinnable pinnable) {
130
        return new ToolTipUI(toolTipText, expandable, pinnable);
131
    }
132
116
}
133
}

Return to bug 262312