1 19 20 package org.netbeans.spi.project.ui.support; 21 22 import java.awt.Dialog ; 23 import java.awt.Image ; 24 import java.awt.event.ActionListener ; 25 import java.io.IOException ; 26 import java.util.ArrayList ; 27 import java.util.Collections ; 28 import java.util.HashMap ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.logging.Level ; 32 import java.util.logging.Logger ; 33 import javax.swing.JComponent ; 34 import javax.swing.JPanel ; 35 36 import org.netbeans.modules.project.uiapi.CategoryModel; 37 import org.netbeans.modules.project.uiapi.CategoryView; 38 import org.netbeans.modules.project.uiapi.CategoryChangeSupport; 39 import org.netbeans.modules.project.uiapi.CustomizerDialog; 40 import org.netbeans.modules.project.uiapi.CustomizerPane; 41 import org.netbeans.modules.project.uiapi.Utilities; 42 import org.netbeans.spi.project.ui.support.ProjectCustomizer.Category; 43 import org.openide.cookies.InstanceCookie; 44 import org.openide.filesystems.FileObject; 45 import org.openide.filesystems.FileStateInvalidException; 46 import org.openide.filesystems.Repository; 47 import org.openide.loaders.DataFolder; 48 import org.openide.loaders.DataObject; 49 import org.openide.util.HelpCtx; 50 import org.openide.util.Lookup; 51 52 59 public final class ProjectCustomizer { 60 61 62 private ProjectCustomizer() { 63 } 64 65 91 public static Dialog createCustomizerDialog( Category[] categories, 92 CategoryComponentProvider componentProvider, 93 String preselectedCategory, 94 ActionListener okOptionListener, 95 HelpCtx helpCtx ) { 96 CustomizerPane innerPane = createCustomizerPane(categories, componentProvider, preselectedCategory); 97 Dialog dialog = CustomizerDialog.createDialog( okOptionListener, innerPane, helpCtx, categories ); 98 return dialog; 99 } 100 101 126 public static Dialog createCustomizerDialog( String folderPath, 127 Lookup context, 128 String preselectedCategory, 129 ActionListener okOptionListener, 130 HelpCtx helpCtx) { 131 FileObject root = Repository.getDefault().getDefaultFileSystem().findResource(folderPath); 132 if (root == null) { 133 throw new IllegalArgumentException ("The designated path " + folderPath + " doesn't exist. Cannot create customizer."); 134 } 135 DataFolder def = DataFolder.findFolder(root); 136 assert def != null : "Cannot find DataFolder for " + folderPath; 137 DelegateCategoryProvider prov = new DelegateCategoryProvider(def, context); 138 return createCustomizerDialog(prov.getSubCategories(), 139 prov, 140 preselectedCategory, okOptionListener, helpCtx); 141 142 } 143 144 146 private static CustomizerPane createCustomizerPane( Category[] categories, 147 CategoryComponentProvider componentProvider, 148 String preselectedCategory ) { 149 150 CategoryChangeSupport changeSupport = new CategoryChangeSupport(); 151 registerCategoryChangeSupport(changeSupport, categories); 152 153 CategoryModel categoryModel = new CategoryModel( categories ); 154 JPanel categoryView = new CategoryView( categoryModel ); 155 CustomizerPane customizerPane = new CustomizerPane( categoryView, categoryModel, componentProvider ); 156 157 if ( preselectedCategory == null ) { 158 preselectedCategory = categories[0].getName(); 159 } 160 161 Category c = categoryModel.getCategory( preselectedCategory ); 162 if ( c != null ) { 163 categoryModel.setCurrentCategory( c ); 164 } 165 166 return customizerPane; 167 } 168 169 private static void registerCategoryChangeSupport(final CategoryChangeSupport changeSupport, 170 final Category[] categories) { 171 for (int i = 0; i < categories.length; i++) { 172 Utilities.putCategoryChangeSupport(categories[i], changeSupport); 173 Category[] subCategories = categories[i].getSubcategories(); 174 if (subCategories != null) { 175 registerCategoryChangeSupport(changeSupport, subCategories); 176 } 177 } 178 } 179 180 181 183 public static interface CategoryComponentProvider { 184 185 189 JComponent create( Category category ); 190 191 } 192 193 207 public static interface CompositeCategoryProvider { 208 209 216 Category createCategory( Lookup context ); 217 218 227 JComponent createComponent (Category category, Lookup context ); 228 } 229 230 232 public static final class Category { 233 234 private String name; 235 private String displayName; 236 private Image icon; 237 private Category[] subcategories; 238 private boolean valid; 239 private String errorMessage; 240 private ActionListener okListener; 241 242 244 private Category( String name, 245 String displayName, 246 Image icon, 247 Category[] subcategories ) { 248 249 this.name = name; 250 this.displayName = displayName; 251 this.icon = icon; 252 this.subcategories = subcategories; 253 this.valid = true; } 255 256 264 public static Category create( String name, 265 String displayName, 266 Image icon, 267 Category... subcategories ) { 268 return new Category( name, displayName, icon, subcategories ); 269 } 270 271 273 276 public String getName() { 277 return this.name; 278 } 279 280 283 public String getDisplayName() { 284 return this.displayName; 285 } 286 287 290 public Image getIcon() { 291 return this.icon; 292 } 293 294 297 public Category[] getSubcategories() { 298 return this.subcategories; 299 } 300 301 305 public String getErrorMessage() { 306 return errorMessage; 307 } 308 309 314 public boolean isValid() { 315 return valid; 316 } 317 318 323 public void setValid(boolean valid) { 324 if (this.valid != valid) { 325 this.valid = valid; 326 Utilities.getCategoryChangeSupport(this).firePropertyChange( 327 CategoryChangeSupport.VALID_PROPERTY, !valid, valid); 328 } 329 } 330 331 340 public void setErrorMessage(String message) { 341 if (message == null) { 342 message = ""; 343 } 344 if (!message.equals(this.errorMessage)) { 345 String oldMessage = this.errorMessage; 346 this.errorMessage = message; 347 Utilities.getCategoryChangeSupport(this).firePropertyChange( 348 CategoryChangeSupport.ERROR_MESSAGE_PROPERTY, oldMessage, message); 349 } 350 } 351 352 358 public void setOkButtonListener(ActionListener okButtonListener) { 359 okListener = okButtonListener; 360 } 361 362 368 public ActionListener getOkButtonListener() { 369 return okListener; 370 } 371 372 } 373 374 static class DelegateCategoryProvider implements CategoryComponentProvider, CompositeCategoryProvider { 375 376 private final Lookup context; 377 private final Map <ProjectCustomizer.Category,CompositeCategoryProvider> category2provider; 378 private final DataFolder folder; 379 private final CompositeCategoryProvider selfProvider; 380 381 public DelegateCategoryProvider(DataFolder folder, Lookup context) { 382 this(folder, context, new HashMap <ProjectCustomizer.Category,CompositeCategoryProvider>()); 383 } 384 385 private DelegateCategoryProvider(DataFolder folder, Lookup context, Map <ProjectCustomizer.Category,CompositeCategoryProvider> cat2Provider) { 386 this(folder, context, cat2Provider, null); 387 } 388 389 private DelegateCategoryProvider(DataFolder folder, Lookup context, Map <ProjectCustomizer.Category,CompositeCategoryProvider> cat2Provider, CompositeCategoryProvider sProv) { 390 this.context = context; 391 this.folder = folder; 392 category2provider = cat2Provider; 393 selfProvider = sProv; 394 } 395 396 public JComponent create(ProjectCustomizer.Category category) { 397 CompositeCategoryProvider prov = category2provider.get(category); 398 assert prov != null : "Category doesn't have a provider associated."; 399 return prov.createComponent(category, context); 400 } 401 402 public ProjectCustomizer.Category[] getSubCategories() { 403 try { 404 return readCategories(folder); 405 } catch (IOException exc) { 406 Logger.getAnonymousLogger().log(Level.WARNING, "Cannot construct Project UI panels", exc); 407 return new ProjectCustomizer.Category[0]; 408 } catch (ClassNotFoundException ex) { 409 Logger.getAnonymousLogger().log(Level.WARNING, "Cannot construct Project UI panels", ex); 410 return new ProjectCustomizer.Category[0]; 411 } 412 } 413 414 415 ProjectCustomizer.Category[] readCategories(DataFolder folder) throws IOException , ClassNotFoundException { 416 List <ProjectCustomizer.Category> toRet = new ArrayList <ProjectCustomizer.Category>(); 417 for (DataObject dob : folder.getChildren()) { 418 if (dob instanceof DataFolder) { 419 CompositeCategoryProvider sProvider = null; 420 DataObject subDobs[] = ((DataFolder) dob).getChildren(); 421 for (DataObject subDob : subDobs) { 422 if (subDob.getName().equals("Self")) { InstanceCookie cookie = subDob.getCookie(InstanceCookie.class); 424 if (cookie != null && CompositeCategoryProvider.class.isAssignableFrom(cookie.instanceClass())) { 425 sProvider = (CompositeCategoryProvider) cookie.instanceCreate(); 426 } 427 } 428 } 429 CompositeCategoryProvider prov = null; 430 if (sProvider != null) { 431 prov = new DelegateCategoryProvider((DataFolder) dob, context, category2provider, sProvider); 432 } else { 433 prov = new DelegateCategoryProvider((DataFolder) dob, context, category2provider); 434 } 435 ProjectCustomizer.Category cat = prov.createCategory(context); 436 toRet.add(cat); 437 category2provider.put(cat, prov); 438 } 439 if (!dob.getName().equals("Self")) { InstanceCookie cook = dob.getCookie(InstanceCookie.class); 441 if (cook != null && CompositeCategoryProvider.class.isAssignableFrom(cook.instanceClass())) { 442 CompositeCategoryProvider provider = (CompositeCategoryProvider)cook.instanceCreate(); 443 ProjectCustomizer.Category cat = provider.createCategory(context); 444 if (cat != null) { 445 toRet.add(cat); 446 category2provider.put(cat, provider); 447 includeSubcats(cat.getSubcategories(), provider); 448 } 449 } 450 } 451 } 452 return toRet.toArray(new ProjectCustomizer.Category[toRet.size()]); 453 } 454 455 private void includeSubcats(ProjectCustomizer.Category[] cats, ProjectCustomizer.CompositeCategoryProvider provider) { 456 if (cats != null) { 457 for (ProjectCustomizer.Category cat : cats) { 458 category2provider.put(cat, provider); 459 includeSubcats(cat.getSubcategories(), provider); 460 } 461 } 462 } 463 464 467 public ProjectCustomizer.Category createCategory(Lookup context) { 468 FileObject fo = folder.getPrimaryFile(); 469 String dn = fo.getNameExt(); 470 try { 471 dn = fo.getFileSystem().getStatus().annotateName(fo.getNameExt(), Collections.singleton(fo)); 472 } catch (FileStateInvalidException ex) { 473 Logger.getAnonymousLogger().log(Level.WARNING, "Cannot retrieve display name for folder " + fo.getPath(), ex); 474 } 475 return ProjectCustomizer.Category.create(folder.getName(), dn, null, getSubCategories()); 476 } 477 478 481 public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) { 482 if (selfProvider != null) { 483 return selfProvider.createComponent(category, context); 484 } 485 return new JPanel (); 486 } 487 } 488 } 489 | Popular Tags |