diff -urN projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryModel.java /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryModel.java --- projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryModel.java 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryModel.java 2005-01-03 15:00:55.000000000 +0100 @@ -0,0 +1,112 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; + + +/** Maintains current category in the customizer. + * + * @author Petr Hrebejk + */ +public class CategoryModel { + + public static final String PROP_CURRENT_CATEGORY = "propCurrentCategory"; + + private ProjectCustomizer.Category[] categories; + + private ProjectCustomizer.Category currentCategory; + + // Might be vetoable later + private PropertyChangeSupport pcs; + + public CategoryModel( ProjectCustomizer.Category[] categories ) { + + if ( categories == null || categories.length == 0 ) { + throw new IllegalArgumentException( "Must provide at least one category" ); // NOI18N + } + + this.categories = categories; + this.currentCategory = categories[0]; + this.pcs = new PropertyChangeSupport( this ); + } + + + public ProjectCustomizer.Category getCurrentCategory() { + return this.currentCategory; + } + + public ProjectCustomizer.Category getCategory( String name ) { + return findCategoryByName( name, categories ); + } + + public void setCurrentCategory( ProjectCustomizer.Category category ) { + + if ( currentCategory != category ) { + ProjectCustomizer.Category oldValue = currentCategory; + this.currentCategory = category; + firePropertyChange( PROP_CURRENT_CATEGORY, oldValue, category ); + } + + } + + public ProjectCustomizer.Category[] getCategories() { + return this.categories; + } + + public void addPropertyChangeListener( String propertyName, PropertyChangeListener l ) { + pcs.addPropertyChangeListener( propertyName, l ); + } + + public void addPropertyChangeListener( PropertyChangeListener l ) { + pcs.addPropertyChangeListener( l ); + } + + public void removePropertyChangeListener( String propertyName, PropertyChangeListener l ) { + pcs.removePropertyChangeListener( propertyName, l ); + } + + public void removePropertyChangeListener( PropertyChangeListener l ) { + pcs.removePropertyChangeListener( l ); + } + + public void firePropertyChange( String propertyName, Object oldValue, Object newValue ) { + pcs.firePropertyChange( propertyName, oldValue, newValue ); + } + + // Private methods --------------------------------------------------------- + + private static ProjectCustomizer.Category findCategoryByName( String name, ProjectCustomizer.Category[] categories ) { + + for( int i = 0; i < categories.length; i++ ) { + if ( name.equals( categories[i].getName() ) ) { + return categories[i]; + } + + ProjectCustomizer.Category[] subcategories = categories[i].getSubcategories(); + if ( subcategories != null ) { + ProjectCustomizer.Category category = findCategoryByName( name, subcategories ); + if ( category != null ) { + return category; + } + } + + } + + return null; + } + +} diff -urN projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryView.java~ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryView.java~ --- projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryView.java~ 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CategoryView.java~ 2005-01-03 15:10:36.000000000 +0100 @@ -0,0 +1,224 @@ +/*4 + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Image; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import javax.swing.JPanel; +import javax.swing.tree.TreeSelectionModel; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.openide.explorer.ExplorerManager; +import org.openide.explorer.view.BeanTreeView; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.NbBundle; +import org.openide.util.Utilities; +import org.openide.util.lookup.Lookups; + +/** + * + * @author Petr Hrebejk + */ +public class CategoryView extends JPanel implements ExplorerManager.Provider, PropertyChangeListener { + + private ExplorerManager manager; + private BeanTreeView btv; + private CategoryModel categoryModel; + + private ProjectCustomizer.Category currentCategory; + + public CategoryView( CategoryModel categoryModel ) { + + this.categoryModel = categoryModel; + + // See #36315 + manager = new ExplorerManager(); + + setLayout( new BorderLayout() ); + + Dimension size = new Dimension( 220, 4 ); + btv = new BeanTreeView(); // Add the BeanTreeView + btv.setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ); + btv.setPopupAllowed( false ); + btv.setRootVisible( false ); + btv.setDefaultActionAllowed( false ); + btv.setMinimumSize( size ); + btv.setPreferredSize( size ); + btv.setMaximumSize( size ); + btv.setDragSource (false); + this.add( btv, BorderLayout.CENTER ); + manager.setRootContext( createRootNode( categoryModel ) ); + manager.addPropertyChangeListener( this ); + categoryModel.addPropertyChangeListener( this ); + btv.expandAll(); + + getAccessibleContext().setAccessibleName(NbBundle.getMessage(CategoryView.class,"AN_CatgoryView")); + getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(CategoryView.class,"AD_CategoryView")); + + } + + public ExplorerManager getExplorerManager() { + return manager; + } + + + public void addNotify() { + super.addNotify(); + btv.expandAll(); + } + + + // Private methods ----------------------------------------------------- + + private void selectNode( ProjectCustomizer.Category category ) { + + Node node = findNode( category, manager.getRootContext() ); + + if ( node != null ) { + try { + manager.setSelectedNodes( new Node[] { node } ); + } + catch ( PropertyVetoException e ) { + // No node will be selected + } + } + + } + + private Node findNode( ProjectCustomizer.Category category, Node node ) { + + Children ch = node.getChildren();; + + if ( ch != null && ch != Children.LEAF ) { + Node nodes[] = ch.getNodes( true ); + + if ( nodes != null ) { + for( int i = 0; i < nodes.length; i++ ) { + ProjectCustomizer.Category cc = (ProjectCustomizer.Category)nodes[i].getLookup().lookup( ProjectCustomizer.Category.class ); + + if ( cc == category ) { + return nodes[i]; + } + else { + Node n = findNode( category, nodes[i] ); + if ( n != null ) { + return n; + } + } + } + } + } + + return null; + } + + + private Node createRootNode( CategoryModel categoryModel ) { + ProjectCustomizer.Category rootCategory = ProjectCustomizer.Category.create( "root", "root", null, categoryModel.getCategories() ); // NOI18N + return new CategoryNode( rootCategory ); + } + + // Implementation of property change listener -------------------------- + + public void propertyChange(PropertyChangeEvent evt) { + + Object source = evt.getSource(); + String propertyName = evt.getPropertyName(); + + if ( source== manager && ExplorerManager.PROP_SELECTED_NODES.equals( propertyName ) ) { + Node nodes[] = manager.getSelectedNodes(); + if ( nodes == null || nodes.length <= 0 ) { + return; + } + Node node = nodes[0]; + + ProjectCustomizer.Category category = (ProjectCustomizer.Category) node.getLookup().lookup( ProjectCustomizer.Category.class ); + if ( category != categoryModel.getCurrentCategory() ) { + categoryModel.setCurrentCategory( category ); + } + } + + if ( source == categoryModel && CategoryModel.PROP_CURRENT_CATEGORY.equals( propertyName ) ) { + selectNode( (ProjectCustomizer.Category)evt.getNewValue() ); + } + + } + + + // Private Inner classes ----------------------------------------------- + + /** Node to be used for configuration + */ + private static class CategoryNode extends AbstractNode { + + private Image icon = Utilities.loadImage( "org/netbeans/modules/project/uiapi/defaultCategory.gif" ); // NOI18N + + public CategoryNode( ProjectCustomizer.Category category ) { + super( ( category.getSubcategories() == null || category.getSubcategories().length == 0 ) ? + Children.LEAF : new CategoryChildren( category.getSubcategories() ), + Lookups.fixed( new Object[] { category } ) ); + setName( category.getName() ); + setDisplayName( category.getDisplayName() ); + + if ( category.getIcon() != null ) { + this.icon = category.getIcon(); + } + + } + + public Image getIcon( int type ) { + return this.icon; + } + + public Image getOpenedIcon( int type ) { + return getIcon( type ); + } + } + + /** Children used for configuration + */ + private static class CategoryChildren extends Children.Keys { + + private Collection descriptions; + + public CategoryChildren( ProjectCustomizer.Category[] descriptions ) { + this.descriptions = Arrays.asList( descriptions ); + } + + // Children.Keys impl -------------------------------------------------- + + public void addNotify() { + setKeys( descriptions ); + } + + public void removeNotify() { + setKeys( Collections.EMPTY_LIST ); + } + + protected Node[] createNodes( Object key ) { + return new Node[] { new CategoryNode( (ProjectCustomizer.Category)key ) }; + } + } + +} + + diff -urN projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerDialog.java /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerDialog.java --- projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerDialog.java 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerDialog.java 2005-01-03 12:25:40.000000000 +0100 @@ -0,0 +1,109 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.awt.Dialog; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JPanel; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.util.NbBundle; + + +/** Implementation of standard customizer dialog. + * + * @author Petr Hrebejk + */ +public class CustomizerDialog { + + /** Factory class only + */ + private CustomizerDialog() {} + + // Option indexes + private static final int OPTION_OK = 0; + private static final int OPTION_CANCEL = OPTION_OK + 1; + + // Option command names + private static final String COMMAND_OK = "OK"; // NOI18N + private static final String COMMAND_CANCEL = "CANCEL"; // NOI18N + + public static Dialog createDialog( ActionListener okOptionListener, JPanel innerPane ) { + + // Create options + JButton options[] = new JButton[] { + new JButton( NbBundle.getMessage( CustomizerDialog.class, "LBL_Customizer_Ok_Option") ), // NOI18N + new JButton( NbBundle.getMessage( CustomizerDialog.class, "LBL_Customizer_Cancel_Option" ) ) , // NOI18N + }; + + // Set commands + options[ OPTION_OK ].setActionCommand( COMMAND_OK ); + options[ OPTION_CANCEL ].setActionCommand( COMMAND_CANCEL ); + + //A11Y + options[ OPTION_OK ].getAccessibleContext().setAccessibleDescription ( NbBundle.getMessage( CustomizerDialog.class, "AD_Customizer_Ok_Option") ); // NOI18N + options[ OPTION_CANCEL ].getAccessibleContext().setAccessibleDescription ( NbBundle.getMessage( CustomizerDialog.class, "AD_Customizer_Cancel_Option") ); // NOI18N + + + // RegisterListener + ActionListener optionsListener = new OptionListener( okOptionListener ); + options[ OPTION_OK ].addActionListener( optionsListener ); + options[ OPTION_CANCEL ].addActionListener( optionsListener ); + + innerPane.getAccessibleContext().setAccessibleName( NbBundle.getMessage( CustomizerDialog.class, "AN_ProjectCustomizer") ); //NOI18N + innerPane.getAccessibleContext().setAccessibleDescription( NbBundle.getMessage( CustomizerDialog.class, "AD_ProjectCustomizer") ); //NOI18N + + DialogDescriptor dialogDescriptor = new DialogDescriptor( + innerPane, // innerPane + NbBundle.getMessage( CustomizerDialog.class, "LBL_Customizer_Title" ), // NOI18N // displayName + false, // modal + options, // options + options[OPTION_OK], // initial value + DialogDescriptor.BOTTOM_ALIGN, // options align + null, // helpCtx + null ); // listener + + // XXX HelpCtx problem innerPane.setDialogDescriptor( dialogDescriptor ); + dialogDescriptor.setClosingOptions( new Object[] { options[ OPTION_OK ], options[ OPTION_CANCEL ] } ); + + Dialog dialog = DialogDisplayer.getDefault().createDialog( dialogDescriptor ); + return dialog; + + } + + /** Listens to the actions on the Customizer's option buttons */ + private static class OptionListener implements ActionListener { + + private ActionListener okOptionListener; + + OptionListener( ActionListener okOptionListener ) { + this.okOptionListener = okOptionListener; + } + + public void actionPerformed( ActionEvent e ) { + String command = e.getActionCommand(); + + if ( COMMAND_OK.equals( command ) ) { + // Call the OK option listener + okOptionListener.actionPerformed( e ); // XXX maybe create new event + } + + } + + } + + +} diff -urN projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.form /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.form --- projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.form 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.form 2005-01-03 12:28:16.000000000 +0100 @@ -0,0 +1,52 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -urN projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.java /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.java --- projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.java 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/modules/project/uiapi/CustomizerPane.java 2005-01-03 12:28:17.000000000 +0100 @@ -0,0 +1,181 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2005 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package org.netbeans.modules.project.uiapi; + +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JComponent; +import javax.swing.JPanel; +import org.netbeans.spi.project.ui.support.ProjectCustomizer; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; + +/** + * + * @author phrebejk + */ +public class CustomizerPane extends javax.swing.JPanel implements HelpCtx.Provider { + + + private Component currentCustomizer; + + private GridBagConstraints fillConstraints; + + //private DialogDescriptor dialogDescriptor; + + /** Creates new form J2SECustomizer */ + public CustomizerPane( JPanel categoryView, CategoryModel categoryModel, ProjectCustomizer.CategoryComponentProvider componentProvider ) { + initComponents(); + // HelpCtx.setHelpIDString( customizerPanel, "org.netbeans.modules.java.j2seproject.ui.customizer.J2SECustomizer" ); // NOI18N + this.getAccessibleContext().setAccessibleDescription (NbBundle.getMessage(CustomizerPane.class,"AD_CustomizerPane")); // NOI18N + fillConstraints = new GridBagConstraints(); + fillConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + fillConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; + fillConstraints.fill = java.awt.GridBagConstraints.BOTH; + fillConstraints.weightx = 1.0; + fillConstraints.weighty = 1.0; + categoryModel.addPropertyChangeListener( new CategoryChangeListener( componentProvider ) ); + categoryPanel.add( categoryView, fillConstraints ); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + private void initComponents() {//GEN-BEGIN:initComponents + java.awt.GridBagConstraints gridBagConstraints; + + categoryPanel = new javax.swing.JPanel(); + customizerPanel = new javax.swing.JPanel(); + + setLayout(new java.awt.GridBagLayout()); + + setPreferredSize(new java.awt.Dimension(750, 450)); + categoryPanel.setLayout(new java.awt.GridBagLayout()); + + categoryPanel.setBorder(new javax.swing.border.EtchedBorder()); + categoryPanel.setMinimumSize(new java.awt.Dimension(220, 4)); + categoryPanel.setPreferredSize(new java.awt.Dimension(220, 4)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 11, 8, 11); + add(categoryPanel, gridBagConstraints); + categoryPanel.getAccessibleContext().setAccessibleName(null); + categoryPanel.getAccessibleContext().setAccessibleDescription(null); + + customizerPanel.setLayout(new java.awt.GridBagLayout()); + + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 1.0; + gridBagConstraints.weighty = 1.0; + gridBagConstraints.insets = new java.awt.Insets(8, 0, 8, 11); + add(customizerPanel, gridBagConstraints); + + }//GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel categoryPanel; + private javax.swing.JPanel customizerPanel; + // End of variables declaration//GEN-END:variables + + + /* XXX HELP IS NOT WORKING + public void setDialogDescriptor( DialogDescriptor dialogDescriptor ) { + this.dialogDescriptor = dialogDescriptor; + } + */ + + // HelpCtx.Provider implementation ----------------------------------------- + + public HelpCtx getHelpCtx() { + /* + if ( currentCustomizer != null ) { + return HelpCtx.findHelp( currentCustomizer ); + } + else { + return HelpCtx.findHelp( customizerPanel ); + } + */ + + // XXX + return null; + } + + // Private innerclasses ---------------------------------------------------- + + /** Listens to selection change and shows the customizers as + * panels + */ + private class CategoryChangeListener implements PropertyChangeListener { + + private ProjectCustomizer.CategoryComponentProvider componentProvider; + + + public CategoryChangeListener( ProjectCustomizer.CategoryComponentProvider componentProvider ) { + this.componentProvider = componentProvider; + } + + public void propertyChange(PropertyChangeEvent evt) { + + if ( CategoryModel.PROP_CURRENT_CATEGORY.equals( evt.getPropertyName() ) ) { + + ProjectCustomizer.Category newCategory = (ProjectCustomizer.Category)evt.getNewValue(); + + if ( newCategory == null ) { + return; + } + + if ( currentCustomizer != null ) { + customizerPanel.remove( currentCustomizer ); + } + + JComponent newCustomizer = componentProvider.create( newCategory ); + + if ( newCustomizer != null ) { + currentCustomizer = newCustomizer; + + /* + if ( currentCustomizer instanceof javax.swing.JComponent ) { + ((javax.swing.JComponent)currentCustomizer).setPreferredSize( new java.awt.Dimension( 600, 0 ) ); + } + */ + customizerPanel.add( currentCustomizer, fillConstraints ); + customizerPanel.validate(); + customizerPanel.repaint(); + + /* XXX HELP DOES NOT WORK IN DIALOGS + if ( ImplCustomizerPane.this.dialogDescriptor != null ) { + ImplCustomizerPane.this.dialogDescriptor.setHelpCtx( ImplCustomizerPane.this.getHelpCtx() ); + } + */ + } + else { + currentCustomizer = null; + } + + return; + } + } + } + +} diff -urN projectuiapi/src/org/netbeans/spi/project/ui/support/ProjectCustomizer.java /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/spi/project/ui/support/ProjectCustomizer.java --- projectuiapi/src/org/netbeans/spi/project/ui/support/ProjectCustomizer.java 1970-01-01 01:00:00.000000000 +0100 +++ /netbeans/trunk/nb_all/projects/projectuiapi/src/org/netbeans/spi/project/ui/support/ProjectCustomizer.java 2005-01-03 15:10:43.000000000 +0100 @@ -0,0 +1,151 @@ +/* + * Support.java + * + * Created on December 9, 2004, 1:09 PM + */ + +package org.netbeans.spi.project.ui.support; + +import java.awt.Dialog; +import java.awt.Image; +import java.awt.event.ActionListener; +import javax.swing.JComponent; +import javax.swing.JPanel; + +import org.netbeans.modules.project.uiapi.CategoryModel; +import org.netbeans.modules.project.uiapi.CategoryView; +import org.netbeans.modules.project.uiapi.CustomizerDialog; +import org.netbeans.modules.project.uiapi.CustomizerPane; + +/** Support for creating standard ProjectCustomizer dialog. + * + * @author Petr Hrebejk + */ +public final class ProjectCustomizer { + + /** Factory/Namespace class only. */ + private ProjectCustomizer() { + } + + /** Creates standard ProjectCutomizer dialog. Can be used for implementation + * of CustomizerProvider. + * @param categories Array of Categories to be shown in the dialog. + * @param componentProvider Implementation of CategoryProvider which creates + * components for each category. + * @param preselectedCategory name of the category which should be selected. + * @param okOptionListener ActionListener which will be notified when the user presses + * the OK button. + * @return Standard customizer dialog. + */ + public static Dialog createCustomizerDialog( Category[] categories, + CategoryComponentProvider componentProvider, + String preselectedCategory, + ActionListener okOptionListener ) { + JPanel innerPane = createCustomizerPane( categories, componentProvider, preselectedCategory ); + Dialog dialog = CustomizerDialog.createDialog( okOptionListener, innerPane ); + return dialog; + } + + /** Creates standard innerPane for customizer dialog. + */ + private static JPanel createCustomizerPane( Category[] categories, + CategoryComponentProvider componentProvider, + String preselectedCategory ) { + + CategoryModel categoryModel = new CategoryModel( categories ); + JPanel categoryView = new CategoryView( categoryModel ); + JPanel customizerPane = new CustomizerPane( categoryView, categoryModel, componentProvider ); + + if ( preselectedCategory == null ) { + preselectedCategory = categories[0].getName(); + } + + Category c = categoryModel.getCategory( preselectedCategory ); + if ( c != null ) { + categoryModel.setCurrentCategory( c ); + } + + return customizerPane; + } + + /** Provides components for categories. + */ + public static interface CategoryComponentProvider { + + /** Creates component which has to be shown for given category + * @param category The Category + * @return UI component for category customization + */ + public JComponent create( Category category ); + + } + + /** Describes category of properties to be customized by given component + */ + public static final class Category { + + private String name; + private String displayName; + private Image icon; + private Category[] subcategories; + + /** Private constructor. See the factory method. + */ + private Category( String name, + String displayName, + Image icon, + Category[] subcategories ) { + + this.name = name; + this.displayName = displayName; + this.icon = icon; + this.subcategories = subcategories; + } + + /** Factory method which creates new category description. + * @param name Prograatic name of the category + * @param displayName Name to be shown to the user + * @param icon Icon for given category. Will use default icon if null. + * @param subcategories Subcategories to be shown under given category. + * Category won't be expandable if null or empty array. + */ + public static Category create( String name, + String displayName, + Image icon, + Category[] subcategories ) { + return new Category( name, displayName, icon, subcategories ); + } + + + // Public methods ------------------------------------------------------ + + /** Gets programmatic name of given category. + * @return Programmatic name of the category + */ + public String getName() { + return this.name; + } + + /** Gets display name of given category. + * @return Display name of the category + */ + public String getDisplayName() { + return this.displayName; + } + + /** Gets icon of given category. + * @return Icon name of the category or null + */ + public Image getIcon() { + return this.icon; + } + + /** Gets subcategories of given category. + * @return Subcategories of the category or null + */ + public Category[] getSubcategories() { + return this.subcategories; + } + } + +}