1 19 package org.netbeans.modules.editor.hints.ui; 20 21 import java.awt.Component ; 22 import java.io.IOException ; 23 import java.io.Serializable ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.HashSet ; 28 import java.util.List ; 29 import java.util.Set ; 30 import javax.swing.JList ; 31 import javax.swing.JTable ; 32 import javax.swing.event.ChangeListener ; 33 import javax.swing.table.AbstractTableModel ; 34 import javax.swing.table.TableCellRenderer ; 35 import org.netbeans.api.project.FileOwnerQuery; 36 import org.netbeans.api.project.Project; 37 import org.netbeans.api.project.Project; 38 import org.netbeans.modules.editor.hints.HintsControllerImpl; 39 import org.netbeans.modules.editor.hints.HintsControllerImpl; 40 import org.netbeans.modules.editor.hints.options.SeverityComboRenderer; 41 import org.netbeans.spi.editor.hints.ErrorDescription; 42 import org.openide.ErrorManager; 43 import org.openide.awt.HtmlRenderer; 44 import org.openide.filesystems.FileObject; 45 import org.openide.loaders.DataObject; 46 import org.openide.util.Lookup.Result; 47 import org.openide.util.Lookup.Template; 48 import org.openide.util.LookupEvent; 49 import org.openide.util.LookupListener; 50 import org.openide.util.NbBundle; 51 import org.openide.util.Utilities; 52 import org.openide.util.lookup.Lookups; 53 import org.openide.windows.TopComponent; 54 import org.openide.windows.WindowManager; 55 56 59 final class ProblemTopComponent extends TopComponent { 60 61 private static Object PTC_TAG = new Object (); 62 63 private static ProblemTopComponent instance; 64 65 67 private static final String PREFERRED_ID = "ProblemTopComponent"; 68 69 private ProblemTableModel model; 70 71 private ProblemTopComponent() { 72 super(Lookups.singleton(PTC_TAG)); 73 initComponents(); 74 setName(NbBundle.getMessage(ProblemTopComponent.class, "CTL_ProblemTopComponent")); 75 setToolTipText(NbBundle.getMessage(ProblemTopComponent.class, "HINT_ProblemTopComponent")); 76 77 jTable1.setDefaultRenderer(Integer .class, new SeverityComboRenderer()); 78 jTable1.setDefaultRenderer(ErrorDescription.class, new PositionCellRenderer()); 79 80 jTable1.setModel(model = new ProblemTableModel()); 81 82 } 85 86 91 private void initComponents() { 93 jScrollPane1 = new javax.swing.JScrollPane (); 94 jTable1 = new javax.swing.JTable (); 95 96 jTable1.setModel(new javax.swing.table.DefaultTableModel ( 97 new Object [][] { 98 {null, null, null, null}, 99 {null, null, null, null}, 100 {null, null, null, null}, 101 {null, null, null, null} 102 }, 103 new String [] { 104 "Title 1", "Title 2", "Title 3", "Title 4" 105 } 106 )); 107 jScrollPane1.setViewportView(jTable1); 108 109 org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); 110 this.setLayout(layout); 111 layout.setHorizontalGroup( 112 layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 113 .add(layout.createSequentialGroup() 114 .addContainerGap() 115 .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 376, Short.MAX_VALUE) 116 .addContainerGap()) 117 ); 118 layout.setVerticalGroup( 119 layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) 120 .add(layout.createSequentialGroup() 121 .addContainerGap() 122 .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE) 123 .addContainerGap()) 124 ); 125 } 127 128 private javax.swing.JScrollPane jScrollPane1; 130 private javax.swing.JTable jTable1; 131 133 138 public static synchronized ProblemTopComponent getDefault() { 139 if (instance == null) { 140 instance = new ProblemTopComponent(); 141 } 142 return instance; 143 } 144 145 148 public static synchronized ProblemTopComponent findInstance() { 149 TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); 150 if (win == null) { 151 ErrorManager.getDefault().log(ErrorManager.WARNING, 152 "Cannot find MyWindow component. It will not be located properly in the window system."); 153 return getDefault(); 154 } 155 if (win instanceof ProblemTopComponent) { 156 return (ProblemTopComponent)win; 157 } 158 ErrorManager.getDefault().log(ErrorManager.WARNING, 159 "There seem to be multiple components with the '" + PREFERRED_ID + 160 "' ID. That is a potential source of errors and unexpected behavior."); 161 return getDefault(); 162 } 163 164 public int getPersistenceType() { 165 return TopComponent.PERSISTENCE_ALWAYS; 166 } 167 168 public void componentOpened() { 169 resultDO = Utilities.actionsGlobalContext().lookupResult(DataObject.class); 170 resultTag = Utilities.actionsGlobalContext().lookup(new Template<Object >(null, null, PTC_TAG)); 171 resultProject = Utilities.actionsGlobalContext().lookupResult(Project.class); 172 listener = new ProjectListener(); 173 resultDO.addLookupListener(listener); 174 resultTag.addLookupListener(listener); 175 HintsControllerImpl.addChangeListener(changeListener = new ChangeListenerImpl()); 176 listener.resultChanged(null); 177 } 179 180 public void componentClosed() { 181 HintsControllerImpl.removeChangeListener(changeListener); 182 changeListener = null; 183 resultDO.removeLookupListener(listener); 184 resultTag.removeLookupListener(listener); 185 resultProject.removeLookupListener(listener); 186 listener = null; 187 resultDO = null; 188 resultTag = null; 189 resultProject = null; 190 } 192 193 194 public Object writeReplace() { 195 return new ResolvableHelper(); 196 } 197 198 protected String preferredID() { 199 return PREFERRED_ID; 200 } 201 202 final static class ResolvableHelper implements Serializable { 203 private static final long serialVersionUID = 1L; 204 public Object readResolve() { 205 return ProblemTopComponent.getDefault(); 206 } 207 } 208 209 private Result<DataObject> resultDO = null; 210 private Result resultTag = null; 211 private Result<Project> resultProject = null; 212 private ProjectListener listener = null; 213 private Set <Project> activeProjects = null; 214 private ChangeListenerImpl changeListener = null; 215 216 private synchronized void updateErrors() { 217 if (activeProjects == null) 218 return; 219 220 List <ErrorDescription> errors = new ArrayList <ErrorDescription>(); 221 222 for (FileObject f : HintsControllerImpl.coveredFiles()) { 223 if (activeProjects.contains(FileOwnerQuery.getOwner(f))) { 224 errors.addAll(HintsControllerImpl.getErrors(f)); 225 } 226 } 227 228 model.errors = errors; 229 model.fireTableDataChanged(); 230 } 231 232 private synchronized void setActiveProjects(Set <Project> activeProjects) { 233 this.activeProjects = activeProjects; 234 updateErrors(); 235 } 236 237 private class ProjectListener implements LookupListener { 238 239 public void resultChanged(LookupEvent evt) { 240 assert resultDO != null && resultTag != null && resultProject != null; 241 242 if (!resultTag.allInstances().isEmpty()) 243 return ; 244 245 Set <Project> projects = new HashSet <Project>(); 246 247 for (DataObject file : resultDO.allInstances()) { 248 projects.add(FileOwnerQuery.getOwner(file.getPrimaryFile())); 249 } 250 251 projects.addAll(resultProject.allInstances()); 252 253 setActiveProjects(projects); 254 } 255 256 } 257 258 private class ChangeListenerImpl implements ChangeListener { 259 260 public void stateChanged(javax.swing.event.ChangeEvent evt) { 261 updateErrors(); 262 } 263 264 } 265 266 private static class ProblemTableModel extends AbstractTableModel { 267 268 private List <ErrorDescription> errors = Collections.<ErrorDescription>emptyList(); 269 270 public int getRowCount() { 271 return errors.size(); 272 } 273 274 public int getColumnCount() { 275 return 3; 280 } 281 282 public @Override String getColumnName(int column) { 283 switch (column) { 284 case 0: 285 return "Description"; 286 case 1: 287 return "Severity"; 288 case 2: 289 return "Position"; 290 } 291 292 throw new IllegalArgumentException ("Invalid column: " + column); } 294 295 public @Override Class <?> getColumnClass(int column) { 296 switch (column) { 297 case 0: 298 return String .class; 299 case 1: 300 return Integer .class; 301 case 2: 302 return ErrorDescription.class; 303 } 304 305 throw new IllegalArgumentException ("Invalid column: " + column); } 307 308 public Object getValueAt(int row, int column) { 309 if (row >= errors.size()) 310 throw new IllegalArgumentException ("Invalid row: " + row + ", max=" + errors.size()); 311 312 ErrorDescription desc = errors.get(row); 313 314 assert desc != null; 315 316 switch (column) { 317 case 0: 318 return desc.getDescription(); 319 case 1: 320 return desc.getSeverity(); 321 case 2: 322 return desc; 323 } 324 325 throw new IllegalArgumentException ("Invalid column: " + column); } 327 328 } 329 330 private static final class PositionCellRenderer implements TableCellRenderer { 331 private TableCellRenderer delegateTo; 332 333 public PositionCellRenderer() { 334 delegateTo = HtmlRenderer.createRenderer(); 335 } 336 337 public Component getTableCellRendererComponent(JTable table, 338 Object value, 339 boolean isSelected, 340 boolean hasFocus, 341 int row, 342 int column) { 343 ErrorDescription desc = (ErrorDescription) value; 344 345 try { 346 String position = desc.getFile().getNameExt() + ":" + desc.getRange().getBegin().getLine(); 347 348 return delegateTo.getTableCellRendererComponent(table, position, isSelected, hasFocus, row, column); 349 } catch (IOException e) { 350 return delegateTo.getTableCellRendererComponent(table, e.getLocalizedMessage(), isSelected, hasFocus, row, column); 351 } 352 } 353 } 354 355 } 356 | Popular Tags |