/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.studio.ldapbrowser.common.wizards; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import org.apache.directory.studio.common.ui.widgets.BaseWidgetUtils; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** * The AttributeOptionsWizardPageprovides input elements for various options * and a preview field. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class AttributeOptionsWizardPage extends WizardPage { /** The wizard. */ private AttributeWizard wizard; /** The shell */ private Shell shell; /** The possible languages. */ private String[] possibleLanguages; /** The possible language to countries map. */ private Map<String, String[]> possibleLangToCountriesMap; /** The parsed lang list. */ private List<String> parsedLangList; /** The parsed option list. */ private List<String> parsedOptionList; /** The parsed binary option. */ private boolean parsedBinary; /** The language group. */ private Group langGroup; /** The lang line list. */ private ArrayList<LangLine> langLineList; /** The options group. */ private Group optionsGroup; /** The option line list. */ private ArrayList<OptionLine> optionLineList; /** The binary option button. */ private Button binaryOptionButton; /** The preview text. */ private Text previewText; /** * Creates a new instance of AttributeOptionsWizardPage. * * @param pageName the page name * @param initialAttributeDescription the initial attribute description * @param wizard the wizard */ public AttributeOptionsWizardPage( String pageName, String initialAttributeDescription, AttributeWizard wizard ) { super( pageName ); super.setTitle( Messages.getString( "AttributeOptionsWizardPage.Options" ) ); //$NON-NLS-1$ super.setDescription( Messages.getString( "AttributeOptionsWizardPage.OptionsDescription" ) ); //$NON-NLS-1$ // super.setImageDescriptor(BrowserUIPlugin.getDefault().getImageDescriptor(BrowserUIConstants.IMG_ATTRIBUTE_WIZARD)); super.setPageComplete( false ); this.wizard = wizard; // init possible languages and countries SortedSet<String> languageSet = new TreeSet<String>(); Map<String, SortedSet<String>> languageToCountrySetMap = new HashMap<String, SortedSet<String>>(); Locale[] locales = Locale.getAvailableLocales(); for ( int i = 0; i < locales.length; i++ ) { Locale locale = locales[i]; languageSet.add( locale.getLanguage() ); if ( !languageToCountrySetMap.containsKey( locale.getLanguage() ) ) { languageToCountrySetMap.put( locale.getLanguage(), new TreeSet<String>() ); } SortedSet<String> countrySet = languageToCountrySetMap.get( locale.getLanguage() ); countrySet.add( locale.getCountry() ); } possibleLanguages = languageSet.toArray( new String[languageSet.size()] ); possibleLangToCountriesMap = new HashMap<String, String[]>(); for ( Iterator<String> it = languageToCountrySetMap.keySet().iterator(); it.hasNext(); ) { String language = it.next(); SortedSet<String> countrySet = languageToCountrySetMap.get( language ); String[] countries = countrySet.toArray( new String[countrySet.size()] ); possibleLangToCountriesMap.put( language, countries ); } // parse options if ( initialAttributeDescription == null ) { initialAttributeDescription = ""; //$NON-NLS-1$ } String[] attributeDescriptionComponents = initialAttributeDescription.split( ";" ); //$NON-NLS-1$ parsedLangList = new ArrayList<String>(); parsedOptionList = new ArrayList<String>(); parsedBinary = false; for ( int i = 1; i < attributeDescriptionComponents.length; i++ ) { if ( attributeDescriptionComponents[i].startsWith( "lang-" ) ) //$NON-NLS-1$ { parsedLangList.add( attributeDescriptionComponents[i] ); } else if ( attributeDescriptionComponents[i].equals( "binary" ) ) //$NON-NLS-1$ { parsedBinary = true; } else { parsedOptionList.add( attributeDescriptionComponents[i] ); } } } /** * Validates the options. */ private void validate() { previewText.setText( wizard.getAttributeDescription() ); setPageComplete( true ); } /** * {@inheritDoc} */ public void setVisible( boolean visible ) { super.setVisible( visible ); if ( visible ) { validate(); } } /** * {@inheritDoc} */ public void createControl( Composite parent ) { shell = parent.getShell(); Composite composite = new Composite( parent, SWT.NONE ); GridLayout gl = new GridLayout( 2, false ); composite.setLayout( gl ); composite.setLayoutData( new GridData( GridData.FILL_BOTH ) ); // Lang group langGroup = BaseWidgetUtils.createGroup( composite, Messages .getString( "AttributeOptionsWizardPage.LanguageTags" ), 2 ); //$NON-NLS-1$ GridData gd = new GridData( GridData.FILL_HORIZONTAL ); gd.horizontalSpan = 2; langGroup.setLayoutData( gd ); Composite langComposite = BaseWidgetUtils.createColumnContainer( langGroup, 6, 1 ); langLineList = new ArrayList<LangLine>(); BaseWidgetUtils.createSpacer( composite, 2 ); // Options group with binary option optionsGroup = BaseWidgetUtils.createGroup( composite, Messages .getString( "AttributeOptionsWizardPage.OtherOptions" ), 2 ); //$NON-NLS-1$ gd = new GridData( GridData.FILL_HORIZONTAL ); gd.horizontalSpan = 2; optionsGroup.setLayoutData( gd ); Composite optionsComposite = BaseWidgetUtils.createColumnContainer( optionsGroup, 3, 1 ); optionLineList = new ArrayList<OptionLine>(); Composite binaryComposite = BaseWidgetUtils.createColumnContainer( optionsGroup, 1, 1 ); binaryOptionButton = BaseWidgetUtils.createCheckbox( binaryComposite, Messages .getString( "AttributeOptionsWizardPage.BinaryOption" ), 1 ); //$NON-NLS-1$ binaryOptionButton.setSelection( parsedBinary ); Label la = new Label( composite, SWT.NONE ); gd = new GridData( GridData.GRAB_VERTICAL ); gd.horizontalSpan = 2; la.setLayoutData( gd ); // Preview text BaseWidgetUtils.createLabel( composite, Messages.getString( "AttributeOptionsWizardPage.Preview" ), 1 ); //$NON-NLS-1$ previewText = BaseWidgetUtils.createReadonlyText( composite, "", 1 ); //$NON-NLS-1$ // fill lang if ( parsedLangList.isEmpty() ) { addLangLine( langComposite, 0 ); } else { for ( int i = 0; i < parsedLangList.size(); i++ ) { addLangLine( langComposite, i ); String l = parsedLangList.get( i ); String[] ls = l.split( "-", 3 ); //$NON-NLS-1$ if ( ls.length > 1 ) { langLineList.get( i ).languageCombo.setText( ls[1] ); } if ( ls.length > 2 ) { langLineList.get( i ).countryCombo.setText( ls[2] ); } } } // fill options if ( parsedOptionList.isEmpty() ) { addOptionLine( optionsComposite, 0 ); } else { for ( int i = 0; i < parsedOptionList.size(); i++ ) { addOptionLine( optionsComposite, i ); optionLineList.get( i ).optionText.setText( parsedOptionList.get( i ) ); } } // binary listener binaryOptionButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { validate(); } } ); validate(); setControl( composite ); } /** * Gets the attribute options. * * @return the attribute options */ String getAttributeOptions() { if ( binaryOptionButton == null || binaryOptionButton.isDisposed() ) { return ""; //$NON-NLS-1$ } // attribute type StringBuffer sb = new StringBuffer(); // options // sort and unique options Comparator<String> comparator = new Comparator<String>() { public int compare( String s1, String s2 ) { if ( s1 == null || s2 == null ) { throw new ClassCastException( Messages.getString( "AttributeOptionsWizardPage.MustNotBeNull" ) ); //$NON-NLS-1$ } return s1.compareToIgnoreCase( s2 ); } }; SortedSet<String> options = new TreeSet<String>( comparator ); if ( binaryOptionButton.getSelection() ) { options.add( "binary" ); //$NON-NLS-1$ } for ( int i = 0; i < optionLineList.size(); i++ ) { OptionLine optionLine = optionLineList.get( i ); if ( !"".equals( optionLine.optionText.getText() ) ) //$NON-NLS-1$ { options.add( optionLine.optionText.getText() ); } if ( optionLineList.size() > 1 ) { optionLine.optionDeleteButton.setEnabled( true ); } else { optionLine.optionDeleteButton.setEnabled( false ); } } for ( int i = 0; i < langLineList.size(); i++ ) { LangLine langLine = langLineList.get( i ); String l = langLine.languageCombo.getText(); String c = langLine.countryCombo.getText(); if ( !"".equals( l ) ) //$NON-NLS-1$ { String s = "lang-" + l; //$NON-NLS-1$ if ( !"".equals( c ) ) //$NON-NLS-1$ { s += "-" + c; //$NON-NLS-1$ } options.add( s ); } if ( langLineList.size() > 1 ) { langLine.deleteButton.setEnabled( true ); } else { langLine.deleteButton.setEnabled( false ); } } // append options for ( Iterator<String> it = options.iterator(); it.hasNext(); ) { String option = it.next(); sb.append( ';' ); sb.append( option ); } return sb.toString(); } /** * Adds an option line at the given index. * * @param optionComposite the option composite * @param index the index */ private void addOptionLine( Composite optionComposite, int index ) { OptionLine[] optionLines = optionLineList.toArray( new OptionLine[optionLineList.size()] ); if ( optionLines.length > 0 ) { for ( int i = 0; i < optionLines.length; i++ ) { OptionLine oldOptionLine = optionLines[i]; // remember values String oldValue = oldOptionLine.optionText.getText(); // delete old oldOptionLine.optionText.dispose(); oldOptionLine.optionAddButton.dispose(); oldOptionLine.optionDeleteButton.dispose(); optionLineList.remove( oldOptionLine ); // add new OptionLine newOptionLine = createOptionLine( optionComposite ); optionLineList.add( newOptionLine ); // restore value newOptionLine.optionText.setText( oldValue ); // check if ( index == i + 1 ) { OptionLine optionLine = createOptionLine( optionComposite ); optionLineList.add( optionLine ); } } } else { OptionLine optionLine = createOptionLine( optionComposite ); optionLineList.add( optionLine ); } shell.layout( true, true ); } /** * Creates the option line. * * @param optionComposite the option composite * * @return the option line */ private OptionLine createOptionLine( final Composite optionComposite ) { OptionLine optionLine = new OptionLine(); optionLine.optionText = new Text( optionComposite, SWT.BORDER ); GridData gd = new GridData( GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL ); optionLine.optionText.setLayoutData( gd ); optionLine.optionAddButton = new Button( optionComposite, SWT.PUSH ); optionLine.optionAddButton.setText( " + " ); //$NON-NLS-1$ optionLine.optionAddButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { int index = optionLineList.size(); for ( int i = 0; i < optionLineList.size(); i++ ) { OptionLine optionLine = optionLineList.get( i ); if ( optionLine.optionAddButton == e.widget ) { index = i + 1; } } addOptionLine( optionComposite, index ); validate(); } } ); optionLine.optionDeleteButton = new Button( optionComposite, SWT.PUSH ); optionLine.optionDeleteButton.setText( " \u2212 " ); //$NON-NLS-1$ optionLine.optionDeleteButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { int index = 0; for ( int i = 0; i < optionLineList.size(); i++ ) { OptionLine optionLine = optionLineList.get( i ); if ( optionLine.optionDeleteButton == e.widget ) { index = i; } } deleteOptionLine( optionComposite, index ); validate(); } } ); optionLine.optionText.addModifyListener( new ModifyListener() { public void modifyText( ModifyEvent e ) { validate(); } } ); return optionLine; } /** * Deletes the option line at the given index. * * @param optionComposite the option composite * @param index the index */ private void deleteOptionLine( Composite optionComposite, int index ) { OptionLine optionLine = optionLineList.remove( index ); if ( optionLine != null ) { optionLine.optionText.dispose(); optionLine.optionAddButton.dispose(); optionLine.optionDeleteButton.dispose(); if ( !optionComposite.isDisposed() ) { shell.layout( true, true ); } } } /** * The class OptionLine is a wrapper for all input elements of an option. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class OptionLine { /** The option text. */ public Text optionText; /** The option add button. */ public Button optionAddButton; /** The option delete button. */ public Button optionDeleteButton; } /** * Adds a language line at the given index. * * @param langComposite the language composite * @param index the index */ private void addLangLine( Composite langComposite, int index ) { LangLine[] langLines = langLineList.toArray( new LangLine[langLineList.size()] ); if ( langLines.length > 0 ) { for ( int i = 0; i < langLines.length; i++ ) { LangLine oldLangLine = langLines[i]; // remember values String oldLanguage = oldLangLine.languageCombo.getText(); String oldCountry = oldLangLine.countryCombo.getText(); // delete old oldLangLine.langLabel.dispose(); oldLangLine.languageCombo.dispose(); oldLangLine.minusLabel.dispose(); oldLangLine.countryCombo.dispose(); oldLangLine.addButton.dispose(); oldLangLine.deleteButton.dispose(); langLineList.remove( oldLangLine ); // add new LangLine newLangLine = createLangLine( langComposite ); langLineList.add( newLangLine ); // restore value newLangLine.languageCombo.setText( oldLanguage ); newLangLine.countryCombo.setText( oldCountry ); // check if ( index == i + 1 ) { LangLine langLine = createLangLine( langComposite ); langLineList.add( langLine ); } } } else { LangLine langLine = createLangLine( langComposite ); langLineList.add( langLine ); } shell.layout( true, true ); } /** * Creates a language line. * * @param langComposite the language composite * * @return the language line */ private LangLine createLangLine( final Composite langComposite ) { final LangLine langLine = new LangLine(); langLine.langLabel = BaseWidgetUtils.createLabel( langComposite, "lang-", 1 ); //$NON-NLS-1$ langLine.languageCombo = BaseWidgetUtils.createCombo( langComposite, possibleLanguages, -1, 1 ); langLine.minusLabel = BaseWidgetUtils.createLabel( langComposite, "-", 1 ); //$NON-NLS-1$ langLine.countryCombo = BaseWidgetUtils.createCombo( langComposite, new String[0], -1, 1 ); langLine.countryCombo.setEnabled( false ); langLine.addButton = new Button( langComposite, SWT.PUSH ); langLine.addButton.setText( " + " ); //$NON-NLS-1$ langLine.addButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { int index = langLineList.size(); for ( int i = 0; i < langLineList.size(); i++ ) { LangLine langLine = langLineList.get( i ); if ( langLine.addButton == e.widget ) { index = i + 1; } } addLangLine( langComposite, index ); validate(); } } ); langLine.deleteButton = new Button( langComposite, SWT.PUSH ); langLine.deleteButton.setText( " \u2212 " ); //$NON-NLS-1$ langLine.deleteButton.addSelectionListener( new SelectionAdapter() { public void widgetSelected( SelectionEvent e ) { int index = 0; for ( int i = 0; i < langLineList.size(); i++ ) { LangLine langLine = langLineList.get( i ); if ( langLine.deleteButton == e.widget ) { index = i; } } deleteLangLine( langComposite, index ); validate(); } } ); langLine.languageCombo.addModifyListener( new ModifyListener() { public void modifyText( ModifyEvent e ) { if ( "".equals( langLine.languageCombo.getText() ) ) //$NON-NLS-1$ { langLine.countryCombo.setEnabled( false ); } else { langLine.countryCombo.setEnabled( true ); String oldValue = langLine.countryCombo.getText(); if ( possibleLangToCountriesMap.containsKey( langLine.languageCombo.getText() ) ) { langLine.countryCombo.setItems( possibleLangToCountriesMap.get( langLine.languageCombo .getText() ) ); } else { langLine.countryCombo.setItems( new String[0] ); } langLine.countryCombo.setText( oldValue ); } validate(); } } ); langLine.countryCombo.addModifyListener( new ModifyListener() { public void modifyText( ModifyEvent e ) { validate(); } } ); return langLine; } /** * Deletes the language line at the given index. * * @param langComposite the language composite * @param index the index */ private void deleteLangLine( Composite langComposite, int index ) { LangLine langLine = langLineList.remove( index ); if ( langLine != null ) { langLine.langLabel.dispose(); langLine.languageCombo.dispose(); langLine.minusLabel.dispose(); langLine.countryCombo.dispose(); langLine.addButton.dispose(); langLine.deleteButton.dispose(); if ( !langComposite.isDisposed() ) { shell.layout( true, true ); } } } /** * The class LangLine is a wrapper for all input elements of a language tag. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class LangLine { /** The lang label. */ public Label langLabel; /** The language combo. */ public Combo languageCombo; /** The minus label. */ public Label minusLabel; /** The country combo. */ public Combo countryCombo; /** The add button. */ public Button addButton; /** The delete button. */ public Button deleteButton; } }