~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to editor/hints/src/org/netbeans/modules/editor/hints/ui/ProblemTopComponent.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 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
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
package org.netbeans.modules.editor.hints.ui;
 
42
 
 
43
import java.awt.Component;
 
44
import java.io.IOException;
 
45
import java.io.Serializable;
 
46
import java.util.ArrayList;
 
47
import java.util.Collection;
 
48
import java.util.Collections;
 
49
import java.util.HashSet;
 
50
import java.util.List;
 
51
import java.util.Set;
 
52
import javax.swing.JList;
 
53
import javax.swing.JTable;
 
54
import javax.swing.event.ChangeListener;
 
55
import javax.swing.table.AbstractTableModel;
 
56
import javax.swing.table.TableCellRenderer;
 
57
import org.netbeans.api.project.FileOwnerQuery;
 
58
import org.netbeans.api.project.Project;
 
59
import org.netbeans.api.project.Project;
 
60
import org.netbeans.modules.editor.hints.HintsControllerImpl;
 
61
import org.netbeans.modules.editor.hints.HintsControllerImpl;
 
62
import org.netbeans.modules.editor.hints.options.SeverityComboRenderer;
 
63
import org.netbeans.spi.editor.hints.ErrorDescription;
 
64
import org.openide.ErrorManager;
 
65
import org.openide.awt.HtmlRenderer;
 
66
import org.openide.filesystems.FileObject;
 
67
import org.openide.loaders.DataObject;
 
68
import org.openide.util.Lookup.Result;
 
69
import org.openide.util.Lookup.Template;
 
70
import org.openide.util.LookupEvent;
 
71
import org.openide.util.LookupListener;
 
72
import org.openide.util.NbBundle;
 
73
import org.openide.util.Utilities;
 
74
import org.openide.util.lookup.Lookups;
 
75
import org.openide.windows.TopComponent;
 
76
import org.openide.windows.WindowManager;
 
77
 
 
78
/**
 
79
 * Top component which displays something.
 
80
 */
 
81
final class ProblemTopComponent extends TopComponent {
 
82
    
 
83
    private static Object PTC_TAG = new Object();
 
84
    
 
85
    private static ProblemTopComponent instance;
 
86
    /** path to the icon used by the component and its open action */
 
87
//    static final String ICON_PATH = "SET/PATH/TO/ICON/HERE";
 
88
    
 
89
    private static final String PREFERRED_ID = "ProblemTopComponent";
 
90
    
 
91
    private ProblemTableModel model;
 
92
    
 
93
    private ProblemTopComponent() {
 
94
        super(Lookups.singleton(PTC_TAG));
 
95
        initComponents();
 
96
        setName(NbBundle.getMessage(ProblemTopComponent.class, "CTL_ProblemTopComponent"));
 
97
        setToolTipText(NbBundle.getMessage(ProblemTopComponent.class, "HINT_ProblemTopComponent"));
 
98
        
 
99
        jTable1.setDefaultRenderer(Integer.class, new SeverityComboRenderer());
 
100
        jTable1.setDefaultRenderer(ErrorDescription.class, new PositionCellRenderer());
 
101
        
 
102
        jTable1.setModel(model = new ProblemTableModel());
 
103
        
 
104
//        jTable1.a
 
105
//        setIcon(Utilities.loadImage(ICON_PATH, true));
 
106
    }
 
107
    
 
108
    /** This method is called from within the constructor to
 
109
     * initialize the form.
 
110
     * WARNING: Do NOT modify this code. The content of this method is
 
111
     * always regenerated by the Form Editor.
 
112
     */
 
113
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
 
114
    private void initComponents() {
 
115
        jScrollPane1 = new javax.swing.JScrollPane();
 
116
        jTable1 = new javax.swing.JTable();
 
117
 
 
118
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
 
119
            new Object [][] {
 
120
                {null, null, null, null},
 
121
                {null, null, null, null},
 
122
                {null, null, null, null},
 
123
                {null, null, null, null}
 
124
            },
 
125
            new String [] {
 
126
                "Title 1", "Title 2", "Title 3", "Title 4"
 
127
            }
 
128
        ));
 
129
        jScrollPane1.setViewportView(jTable1);
 
130
 
 
131
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
 
132
        this.setLayout(layout);
 
133
        layout.setHorizontalGroup(
 
134
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
 
135
            .add(layout.createSequentialGroup()
 
136
                .addContainerGap()
 
137
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE)
 
138
                .addContainerGap())
 
139
        );
 
140
        layout.setVerticalGroup(
 
141
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
 
142
            .add(layout.createSequentialGroup()
 
143
                .addContainerGap()
 
144
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE)
 
145
                .addContainerGap())
 
146
        );
 
147
    }// </editor-fold>//GEN-END:initComponents
 
148
    
 
149
    
 
150
    // Variables declaration - do not modify//GEN-BEGIN:variables
 
151
    private javax.swing.JScrollPane jScrollPane1;
 
152
    private javax.swing.JTable jTable1;
 
153
    // End of variables declaration//GEN-END:variables
 
154
    
 
155
    /**
 
156
     * Gets default instance. Do not use directly: reserved for *.settings files only,
 
157
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
 
158
     * To obtain the singleton instance, use {@link findInstance}.
 
159
     */
 
160
    public static synchronized ProblemTopComponent getDefault() {
 
161
        if (instance == null) {
 
162
            instance = new ProblemTopComponent();
 
163
        }
 
164
        return instance;
 
165
    }
 
166
    
 
167
    /**
 
168
     * Obtain the ProblemTopComponent instance. Never call {@link #getDefault} directly!
 
169
     */
 
170
    public static synchronized ProblemTopComponent findInstance() {
 
171
        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
 
172
        if (win == null) {
 
173
            ErrorManager.getDefault().log(ErrorManager.WARNING,
 
174
                    "Cannot find MyWindow component. It will not be located properly in the window system.");
 
175
            return getDefault();
 
176
        }
 
177
        if (win instanceof ProblemTopComponent) {
 
178
            return (ProblemTopComponent)win;
 
179
        }
 
180
        ErrorManager.getDefault().log(ErrorManager.WARNING,
 
181
                "There seem to be multiple components with the '" + PREFERRED_ID +
 
182
                "' ID. That is a potential source of errors and unexpected behavior.");
 
183
        return getDefault();
 
184
    }
 
185
    
 
186
    public int getPersistenceType() {
 
187
        return TopComponent.PERSISTENCE_ALWAYS;
 
188
    }
 
189
    
 
190
    public void componentOpened() {
 
191
        resultDO = Utilities.actionsGlobalContext().lookupResult(DataObject.class);
 
192
        resultTag = Utilities.actionsGlobalContext().lookup(new Template<Object>(null, null, PTC_TAG));
 
193
        resultProject = Utilities.actionsGlobalContext().lookupResult(Project.class);
 
194
        listener = new ProjectListener();
 
195
        resultDO.addLookupListener(listener);
 
196
        resultTag.addLookupListener(listener);
 
197
        HintsControllerImpl.addChangeListener(changeListener = new ChangeListenerImpl());
 
198
        listener.resultChanged(null);
 
199
        // TODO add custom code on component opening
 
200
    }
 
201
    
 
202
    public void componentClosed() {
 
203
        HintsControllerImpl.removeChangeListener(changeListener);
 
204
        changeListener = null;
 
205
        resultDO.removeLookupListener(listener);
 
206
        resultTag.removeLookupListener(listener);
 
207
        resultProject.removeLookupListener(listener);
 
208
        listener = null;
 
209
        resultDO = null;
 
210
        resultTag = null;
 
211
        resultProject = null;
 
212
        // TODO add custom code on component closing
 
213
    }
 
214
    
 
215
    /** replaces this in object stream */
 
216
    public Object writeReplace() {
 
217
        return new ResolvableHelper();
 
218
    }
 
219
    
 
220
    protected String preferredID() {
 
221
        return PREFERRED_ID;
 
222
    }
 
223
    
 
224
    final static class ResolvableHelper implements Serializable {
 
225
        private static final long serialVersionUID = 1L;
 
226
        public Object readResolve() {
 
227
            return ProblemTopComponent.getDefault();
 
228
        }
 
229
    }
 
230
    
 
231
    private Result<DataObject> resultDO = null;
 
232
    private Result resultTag = null;
 
233
    private Result<Project> resultProject = null;
 
234
    private ProjectListener listener = null;
 
235
    private Set<Project> activeProjects = null;
 
236
    private ChangeListenerImpl changeListener = null;
 
237
    
 
238
    private synchronized void updateErrors() {
 
239
        if (activeProjects == null)
 
240
            return;
 
241
        
 
242
        List<ErrorDescription> errors = new ArrayList<ErrorDescription>();
 
243
        
 
244
        for (FileObject f : HintsControllerImpl.coveredFiles()) {
 
245
            if (activeProjects.contains(FileOwnerQuery.getOwner(f))) {
 
246
                errors.addAll(HintsControllerImpl.getErrors(f));
 
247
            }
 
248
        }
 
249
        
 
250
        model.errors = errors;
 
251
        model.fireTableDataChanged();
 
252
    }
 
253
    
 
254
    private synchronized void setActiveProjects(Set<Project> activeProjects) {
 
255
        this.activeProjects = activeProjects;
 
256
        updateErrors();
 
257
    }
 
258
    
 
259
    private class ProjectListener implements LookupListener {
 
260
        
 
261
        public void resultChanged(LookupEvent evt) {
 
262
            assert resultDO != null && resultTag != null && resultProject != null;
 
263
            
 
264
            if (!resultTag.allInstances().isEmpty())
 
265
                return ;
 
266
            
 
267
            Set<Project> projects = new HashSet<Project>();
 
268
            
 
269
            for (DataObject file : resultDO.allInstances()) {
 
270
                projects.add(FileOwnerQuery.getOwner(file.getPrimaryFile()));
 
271
            }
 
272
            
 
273
            projects.addAll(resultProject.allInstances());
 
274
            
 
275
            setActiveProjects(projects);
 
276
        }
 
277
        
 
278
    }
 
279
    
 
280
    private class ChangeListenerImpl implements ChangeListener {
 
281
        
 
282
        public void stateChanged(javax.swing.event.ChangeEvent evt) {
 
283
            updateErrors();
 
284
        }
 
285
    
 
286
    }
 
287
    
 
288
    private static class ProblemTableModel extends AbstractTableModel {
 
289
        
 
290
        private List<ErrorDescription> errors = Collections.<ErrorDescription>emptyList();
 
291
        
 
292
        public int getRowCount() {
 
293
            return errors.size();
 
294
        }
 
295
        
 
296
        public int getColumnCount() {
 
297
            //description
 
298
            //severity
 
299
            //kind?
 
300
            //position
 
301
            return 3;
 
302
        }
 
303
        
 
304
        public @Override String getColumnName(int column) {
 
305
            switch (column) {
 
306
                case 0:
 
307
                    return "Description";
 
308
                case 1:
 
309
                    return "Severity";
 
310
                case 2:
 
311
                    return "Position";
 
312
            }
 
313
            
 
314
            throw new IllegalArgumentException("Invalid column: " + column); // NOI18N
 
315
        }
 
316
        
 
317
        public @Override Class<?> getColumnClass(int column) {
 
318
            switch (column) {
 
319
                case 0:
 
320
                    return String.class;
 
321
                case 1:
 
322
                    return Integer.class;
 
323
                case 2:
 
324
                    return ErrorDescription.class;
 
325
            }
 
326
            
 
327
            throw new IllegalArgumentException("Invalid column: " + column); // NOI18N
 
328
        }
 
329
        
 
330
        public Object getValueAt(int row, int column) {
 
331
            if (row >= errors.size())
 
332
                throw new IllegalArgumentException("Invalid row: " + row + ", max=" + errors.size());
 
333
            
 
334
            ErrorDescription desc = errors.get(row);
 
335
            
 
336
            assert desc != null;
 
337
            
 
338
            switch (column) {
 
339
                case 0:
 
340
                    return desc.getDescription();
 
341
                case 1:
 
342
                    return desc.getSeverity();
 
343
                case 2:
 
344
                    return desc;
 
345
            }
 
346
            
 
347
            throw new IllegalArgumentException("Invalid column: " + column); // NOI18N
 
348
        }
 
349
        
 
350
    }
 
351
    
 
352
    private static final class PositionCellRenderer implements TableCellRenderer {
 
353
        private TableCellRenderer delegateTo;
 
354
        
 
355
        public PositionCellRenderer() {
 
356
            delegateTo = HtmlRenderer.createRenderer();
 
357
        }
 
358
        
 
359
        public Component getTableCellRendererComponent(JTable table,
 
360
                Object value,
 
361
                boolean isSelected,
 
362
                boolean hasFocus,
 
363
                int row,
 
364
                int column) {
 
365
            ErrorDescription desc = (ErrorDescription) value;
 
366
            
 
367
            try {
 
368
                String position = desc.getFile().getNameExt() + ":" + desc.getRange().getBegin().getLine();
 
369
                
 
370
                return delegateTo.getTableCellRendererComponent(table, position, isSelected, hasFocus, row, column);
 
371
            } catch (IOException e) {
 
372
                return delegateTo.getTableCellRendererComponent(table, e.getLocalizedMessage(), isSelected, hasFocus, row, column);
 
373
            }
 
374
        }
 
375
    }
 
376
    
 
377
}