Package net.sf.jeters.components.DefaultGUI

Source Code of net.sf.jeters.components.DefaultGUI.DefaultGUI$GBC

/*
* JETERS – Java Extensible Text Replacement System
* Copyright (C) 2006–2008  Tobias Knerr
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/

package net.sf.jeters.components.DefaultGUI;

import net.sf.jeters.util.*;
import net.sf.jeters.componentInterface.Component;
import net.sf.jeters.componentInterface.ComponentManager;
import net.sf.jeters.componentInterface.InputComponent;
import net.sf.jeters.componentInterface.OutputComponent;
import net.sf.jeters.componentInterface.ReplacerComponent;
import net.sf.jeters.componentInterface.UIComponent_HomeView;
import net.sf.jeters.componentInterface.dataStructs.NamedDataSet;
import net.sf.jeters.componentInterface.dataStructs.UIRequest;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_Boolean;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_Float;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_Integer;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_Output;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_Selection;
import net.sf.jeters.componentInterface.dataStructs.UIRequest_String;
import net.sf.jeters.configuration.Conf;
import net.sf.jeters.configuration.NotifiedConfigurable;
import static net.sf.jeters.componentInterface.dataStructs.UIRequest.Type.*;
import static net.sf.jeters.componentInterface.dataStructs.UIRequest_String.LayoutFlag.*;

import java.util.regex.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.*;

import java.awt.*;
import java.awt.event.*;

import static java.awt.GridBagConstraints.*;

/**
* the default implementation of a graphical UI component for JETERS.
* For a command line UI, see {@link DefaultCLI}.
*
* @author Tobias Knerr
*/
public class DefaultGUI extends AssistedTranslatable
                        implements UIComponent_HomeView, NotifiedConfigurable {

  /**
   * characters that (in addition to whitespace) break a string into words
   * when marking changes for the diff view
   */
  private static final List<Character> DIFF_SEPARATOR_CHARS =
    Arrays.asList( new Character[] {'>', '<', '|'} );
 
  /**
   * local class for extending GridBagConstraints
   * that has constructors with exactly those values needed here
   */ 
  private static class GBC extends GridBagConstraints {
    public GBC(int gridx, int gridy, int gridwidth, int anchor, int fill, double weightx, double weighty, Insets insets){
      this.gridx = gridx;
      this.gridy = gridy;
      this.gridwidth = gridwidth;
      this.anchor = anchor;
      this.fill = fill;
      this.weightx = weightx;
      this.weighty = weighty;
      this.insets = insets;
    }
    public GBC(int gridx, int gridy, int gridwidth, int anchor, int fill, double weightx, double weighty){
      this(gridx, gridy, gridwidth, anchor, fill, weightx, weighty, new Insets(0,0,0,0));
    }
    public GBC(int gridx, int gridy, int gridwidth, int anchor, int fill){
      this(gridx, gridy, gridwidth, anchor, fill, 0, 0);
      if( fill == HORIZONTAL || fill == BOTH ){ this.weightx = 1; }
      if( fill == VERTICAL || fill == BOTH ){ this.weighty = 1; }
    }

    public GBC(int gridx, int gridy, int gridwidth, int anchor, int fill, Insets insets){
      this(gridx, gridy, gridwidth, anchor, fill);
      this.insets = insets;
    }   
  }
   
  //action command strings
  //note that it may cause problems if one of them is a substring,
  //especially prefix, of another
  private static final String ACTION_OK = "ACTION_OK";
  private static final String ACTION_CANCEL = "ACTION_CANCEL";
  private static final String ACTION_ADD = "Action_ADD"
  private static final String ACTION_REMOVE = "Action_REMOVE_";
 
  /**
   * a listener class, some calls are directly processed,
   * others are stored until they are returned by getNextActionCommand
   */ 
  private class GUIListener implements ActionListener {
   
    private String lastActionCommand = null; /*++ TODO: replace with FIFO (?) ++*/
   
    public void actionPerformed(ActionEvent event){
           
      lastActionCommand = event.getActionCommand();
     
    }
 
    public boolean hasNewActionCommand(){
     
      return (lastActionCommand != null );
     
    }   
   
    public String getNextActionCommand(){
     
      String nextActionCommand = lastActionCommand;
     
      lastActionCommand = null;
     
      return nextActionCommand;
     
    }
   
  }
 
 
 
 
  //the instance of the ListenerThread-class
  private GUIListener listener = new GUIListener();
 
 
  //the frame (~window) and the panel used by the GUI
  private JFrame mainFrame;
  private JPanel mainPanel;
 
 
  //settings
  @Conf private boolean useSystemLookAndFeel = true;
  @Conf private boolean showToolTips = true;
  @Conf private boolean cutUnchangedParts = true;
  @Conf private int cutUnchangedPartsPadding = 10; //number of unchanged chars that are left before and after each changed char
  @Conf private boolean forceShowChanges = false;
  @Conf private float uiFontScaleFactor = 1.0f; //does not work for all System L&Fs
  @Conf private int editorFontSizePt = 0;
  @Conf private String editorFontFamily = "";
  @Conf private String changesFontColorOld = "white"; //can be a html-color-value, either a word ("white", "red", "silver" etc.) or a rgb color code ("#rrggbb", where r,g,b are between 0 and f)
  @Conf private String changesBgColorOld = "red";
  @Conf private String changesFontColorNew = "white";
  @Conf private String changesBgColorNew = "blue";
  @Conf private boolean editFrameLineWrap = true;
  @Conf private int mainFrameSizeX = 600;
  @Conf private int mainFrameSizeY = 400;
  @Conf private int mainFramePositionX = 100;
  @Conf private int mainFramePositionY = 100;
  @Conf private int editFrameSizeX = 300;
  @Conf private int editFrameSizeY = 200;
  @Conf private boolean showLabelInDiffView = true;
 
 
  private boolean refreshHomeView;
 
  synchronized private boolean getRefreshHomeView() {
    return refreshHomeView;
  }

  synchronized void setRefreshHomeView(boolean refreshHomeView) {
    this.refreshHomeView = refreshHomeView;
  }
 

  private static String[] markChanges(String textVersion1, String textVersion2, String beginChangeMarker, String endChangeMarker){
   
    String resultStrings[] = new String[2];
   
    int lengthTextVersion1 = (textVersion1!=null)?(textVersion1.length()):(0);
    int lengthTextVersion2 = (textVersion2!=null)?(textVersion2.length()):(0);
   
    //check if the strings contain content
   
    if( lengthTextVersion1 == 0 || lengthTextVersion2 == 0 ){
           
      if( lengthTextVersion1 == 0 ){
       
        if( lengthTextVersion2 == 0 ){
       
          resultStrings[0] = beginChangeMarker + endChangeMarker;
          resultStrings[1] = beginChangeMarker + endChangeMarker;
         
        }
       
        else{ //lengthTextVersion1 == 0 && lengthTextVersion2 != 0
       
          resultStrings[0] = beginChangeMarker + endChangeMarker;
          resultStrings[1] = beginChangeMarker + textVersion2 + endChangeMarker;         
       
        }
       
      }
     
      else{ //lengthTextVersion1 != 0 && lengthTextVersion2 == 0
     
        resultStrings[0] = beginChangeMarker + textVersion1 + endChangeMarker;         
        resultStrings[1] = beginChangeMarker + endChangeMarker;
               
      }
     
    }
   
    else{   

      /* TODO: maybe treat split chars as own words (don't mark them if
       * adjacent words have changed). Problem: changed whitespace must still be visible */
     
      //Split textVersion1 into words and separating strings (whitespace, >, < or |)
      //result of the following lines of code is a Vector with Strings containing the "words" (every sequence of characters not interrupted by whitespace or |) and another Vector with Strings containing the characters between the words     
   
      List<String> stringsVersion1 = new ArrayList<String>();
               
      boolean firstStringIsWordVersion1 = !( ( Character.isWhitespace(textVersion1.charAt(0)) ) || DIFF_SEPARATOR_CHARS.contains(textVersion1.charAt(0)) );
     
      boolean inWord = firstStringIsWordVersion1;
      String nextString = new String();
     
      for(int charNumber = 0; charNumber < lengthTextVersion1; ++ charNumber ){
     
        Character c = textVersion1.charAt(charNumber);
       
        if( Character.isWhitespace(c) || DIFF_SEPARATOR_CHARS.contains(c) ){
         
          if( inWord ){
           
            stringsVersion1.add(nextString);
           
            nextString = new String();
           
            inWord = false;           
           
          }
                 
        }
       
        else if( !inWord ){
         
            stringsVersion1.add(nextString);
           
            nextString = new String();
           
            inWord = true;             
         
        }
       
        nextString += c;

      }       
     
      stringsVersion1.add(nextString);           
     
      //Split textVersion2 into words (separated by whitespace or |)
      //the same as above 
      // TODO: then why don't you put it into a method?
   
      List<String> stringsVersion2 = new ArrayList<String>();
     
      boolean firstStringIsWordVersion2 = !( ( Character.isWhitespace(textVersion2.charAt(0)) ) || DIFF_SEPARATOR_CHARS.contains(textVersion2.charAt(0)) );
     
      inWord = firstStringIsWordVersion2;
      nextString = new String();
     
      for(int charNumber = 0; charNumber < lengthTextVersion2; ++ charNumber ){
     
        Character c = textVersion2.charAt(charNumber);
       
        if( Character.isWhitespace(c) || DIFF_SEPARATOR_CHARS.contains(c) ){
         
          if( inWord ){
           
            stringsVersion2.add(nextString);
           
            nextString = new String();
           
            inWord = false;           
           
          }
                 
        }
       
        else if( !inWord ){
         
            stringsVersion2.add(nextString);
           
            nextString = new String();
           
            inWord = true;             
         
        }
       
        nextString += c;

      }
     
      stringsVersion2.add(nextString);
     
      //compare the words of version 1 with those of version 2
     
      int numberStringsVersion1 = stringsVersion1.size();
      int numberStringsVersion2 = stringsVersion2.size();
     
      boolean unchangedVersion1[] = new boolean[numberStringsVersion1];
      for( int i = 0; i < numberStringsVersion1; ++ i ){ unchangedVersion1[i] = false; }       
      boolean unchangedVersion2[] = new boolean[numberStringsVersion2];
      for( int i = 0; i < numberStringsVersion2; ++ i ){ unchangedVersion2[i] = false; }       

      int indexVersion1 = firstStringIsWordVersion1 ? 0 : 1;
      int indexVersion2 = 0;
     
      while( indexVersion1 < numberStringsVersion1 && indexVersion2 < numberStringsVersion2 ){
       
        boolean wordFoundInVersion2Strings = false;
       
        int checkedIndexVersion2 = indexVersion2;
       
        while( !wordFoundInVersion2Strings && checkedIndexVersion2 < numberStringsVersion2 ){
         
          if( stringsVersion1.get(indexVersion1).equals(stringsVersion2.get(checkedIndexVersion2)) ){
               
            wordFoundInVersion2Strings = true;
           
            unchangedVersion1[indexVersion1] = true;
            unchangedVersion2[checkedIndexVersion2] = true;
           
            //also check the space before the matching words
            /*++ TODO: (same as in DefaultCLI) after, too??? what's about a space at the end of the text – it won't be checked at all! ++*/
           
            if( indexVersion1 > 0 && checkedIndexVersion2 > 0 && stringsVersion1.get(indexVersion1-1).equals(stringsVersion2.get(checkedIndexVersion2-1)) ){
             
              unchangedVersion1[indexVersion1-1] = true;
              unchangedVersion2[checkedIndexVersion2-1] = true;
             
            }
             
          }         

          checkedIndexVersion2 += 1;
         
        }
                     
        if( wordFoundInVersion2Strings ){ indexVersion2 = checkedIndexVersion2; }
       
        indexVersion1 += 2;
       
      }
   
      //recombine the stings, but add markers for changes
         
      boolean lastStringWasUnchanged = true;
     
      resultStrings[0] = new String();
     
      for( indexVersion1 = 0; indexVersion1 < numberStringsVersion1; ++ indexVersion1 ){
       
        if( !unchangedVersion1[indexVersion1] && lastStringWasUnchanged ){
         
          resultStrings[0] += beginChangeMarker;
         
          lastStringWasUnchanged = false;
 
        }
     
        else if ( unchangedVersion1[indexVersion1] && !lastStringWasUnchanged ){
         
          resultStrings[0] += endChangeMarker;
         
          lastStringWasUnchanged = true;
         
       
       
        resultStrings[0] += stringsVersion1.get(indexVersion1);
               
      }
     
      if( !lastStringWasUnchanged ){ resultStrings[0] += endChangeMarker; }
     
      //recombining – the same for version 2
     
      lastStringWasUnchanged = true;
     
      resultStrings[1] = new String();
     
      for( indexVersion2 = 0; indexVersion2 < numberStringsVersion2; ++ indexVersion2 ){
       
        if( !unchangedVersion2[indexVersion2] && lastStringWasUnchanged ){
         
          resultStrings[1] += beginChangeMarker;
         
          lastStringWasUnchanged = false;
 
        }
     
        else if ( unchangedVersion2[indexVersion2] && !lastStringWasUnchanged ){
         
          resultStrings[1] += endChangeMarker;
         
          lastStringWasUnchanged = true;
         
       
       
        resultStrings[1] += stringsVersion2.get(indexVersion2);
               
      }
     
      if( !lastStringWasUnchanged ){ resultStrings[1] += endChangeMarker; }
 
    }

    return resultStrings;   
   
  }
 
  /**
   * set the content of the main frame.
   *
   * @param contentPanel   the panel containing the new content
   */ 
  private void setMainFrameContent(JPanel contentPanel){
   
    if( mainPanel != null ){
      mainFrame.remove(mainPanel);
    }
   
    mainPanel = contentPanel;
   
    mainFrame.add(contentPanel);   
   
    mainFrame.setVisible(true);   
   
  }
 
 
  public void presentHomeView(ComponentManager componentManager) {
  
    this.setRefreshHomeView(false);
   
    List<Class<? extends Component>> inputClasses = componentManager
      .getAvailableComponentClasses(InputComponent.class);
    List<Class<? extends Component>> outputClasses = componentManager
      .getAvailableComponentClasses(OutputComponent.class);
    List<Class<? extends Component>> replacerClasses = componentManager
      .getAvailableComponentClasses(ReplacerComponent.class);

    assert inputClasses != null
           && outputClasses != null
           && replacerClasses != null;
   
    Class<? extends Component> activeInputClass = null;
    if (componentManager.getInputComponent() != null) {
      activeInputClass = componentManager.getInputComponent().getClass();
    }
   
    Class<? extends Component> activeOutputClass = null;
    if (componentManager.getOutputComponent() != null) {
      activeOutputClass =
        componentManager.getOutputComponent().getClass();
    }
   
    ArrayList<Class<? extends Component>> activeReplacerClasses =
      new ArrayList<Class<? extends Component>>();
    List<ReplacerComponent<?,?>> activeReplacerComponents =
      componentManager.getReplacerComponents();
    if (activeReplacerComponents != null) {
      for (ReplacerComponent<?,?> replacer : activeReplacerComponents) {
        activeReplacerClasses.add(replacer.getClass());
      }
    }

    //explanatory text
    /*++ TODO: include somewhere ++*/
    String helpText;
    if ( inputClasses.size() == 0 || outputClasses.size() == 0
        || replacerClasses.size() == 0
    ) {
      //help text for lacking components
      helpText = str("helpMissingComp");      
    } else {
      //normal help text
      helpText = str("helpNormal");       
    }

    /* set menu */
   
    mainFrame.setJMenuBar(createHomeViewMenuBar(componentManager));

    /* create the GUI panel */
   
    JPanel homePanel = new JPanel();     
    GridBagLayout gbLayout = new GridBagLayout();     
    homePanel.setLayout(gbLayout);   

    //labels      
    JLabel inputLabel = new JLabel(str("labelInput"));
    JLabel outputLabel = new JLabel(str("labelOutput"));
    JLabel replacerLabel = new JLabel(str("labelReplacer"));
    gbLayout.setConstraints(inputLabel,new GBC(0,0,3,SOUTHWEST,NONE,new Insets(5,0,1,0)));
    gbLayout.setConstraints(outputLabel,new GBC(0,2,3,SOUTHWEST,NONE,new Insets(5,0,1,0)));
    gbLayout.setConstraints(replacerLabel,new GBC(0,4,3,SOUTHWEST,NONE,new Insets(5,0,1,0)));
    if(showToolTips){
      inputLabel.setToolTipText(str("toolTipInput"));
      outputLabel.setToolTipText(str("toolTipOutput"));
      replacerLabel.setToolTipText(str("toolTipReplacers"));
    }     
    homePanel.add(inputLabel);     
    homePanel.add(outputLabel);     
    homePanel.add(replacerLabel);

    //selection box for input component
    JComboBox comboBoxInput =
      createComponentClassComboBox(inputClasses, activeInputClass, componentManager);
    if (showToolTips) {
      comboBoxInput.setToolTipText(str("toolTipInput"));
    }
    gbLayout.setConstraints(comboBoxInput,new GBC(0,1,3,NORTHWEST,HORIZONTAL));
    homePanel.add(comboBoxInput);

    //selection box for output component
    JComboBox comboBoxOutput =
      createComponentClassComboBox(outputClasses, activeOutputClass, componentManager);
    if( showToolTips ){
      comboBoxOutput.setToolTipText(str("toolTipOutput"));
    }
    gbLayout.setConstraints(comboBoxOutput,new GBC(0,3,3,NORTHWEST,HORIZONTAL));
    homePanel.add(comboBoxOutput);

    //selection boxes and minus buttons for replacer components

    ArrayList<JComboBox> comboBoxListReplacer
      = new ArrayList<JComboBox>();     
    ArrayList<JButton> buttonListReplacer
      = new ArrayList<JButton>();

    for (int repNum = 0; repNum < activeReplacerClasses.size(); repNum++) {

      JComboBox comboBox = createComponentClassComboBox(replacerClasses,
          activeReplacerClasses.get(repNum), componentManager);
      if (showToolTips) {
        comboBox.setToolTipText(str("toolTipReplacer"));
      }
      gbLayout.setConstraints(comboBox,
          new GBC(0,5+repNum,3,WEST,HORIZONTAL,new Insets(1,0,1,0)));

      homePanel.add(comboBox);

      comboBoxListReplacer.add(comboBox);       

      //place minus button removing this replacer

      JButton minusButton = new JButton(str("buttonRemove"));

      minusButton.setActionCommand(ACTION_REMOVE + repNum);

      minusButton.addActionListener(listener);

      gbLayout.setConstraints(minusButton,
          new GBC(3,5+repNum,1,CENTER,NONE) );

      homePanel.add(minusButton);

      buttonListReplacer.add(minusButton);

    }

    //plus button adding an replacer component

    JButton addButton = new JButton(str("buttonAdd"));

    addButton.setActionCommand(ACTION_ADD);

    addButton.addActionListener(listener);

    gbLayout.setConstraints(addButton,
        new GBC(0,5+comboBoxListReplacer.size(),
            1,WEST,NONE,new Insets(3,0,0,0)) );

    homePanel.add(addButton);


    //ok-Button

    JButton okButton = new JButton(str("buttonOK"));

    okButton.setActionCommand(ACTION_OK);

    okButton.addActionListener(listener);

    gbLayout.setConstraints(okButton,
        new GBC(2,6+comboBoxListReplacer.size(),
            2,SOUTHEAST,NONE,0,0.01,new Insets(3,0,0,0)) );

    homePanel.add(okButton);


    //put the panel into the main frame

    setMainFrameContent(homePanel);



    /* respond to user's actions */

    boolean validComponentSelectionConfirmed = false;

    while( !validComponentSelectionConfirmed ){

      /* process actions, repeat until OK is pressed */

      boolean buttonOKPressed = false;

      while( !buttonOKPressed ){

        try {
          Thread.sleep(100);
        }
        catch (InterruptedException ie){}

        if (this.getRefreshHomeView()) {
          this.presentHomeView(componentManager);
          return;
        }
       
        if ( listener.hasNewActionCommand() ) {

          String actionCommand = listener.getNextActionCommand();

          if ( actionCommand.equals(ACTION_OK) ) {

            buttonOKPressed = true;

          } else if ( actionCommand.equals(ACTION_ADD)) {

            /* add a selection box and a minus button */

            int repNum = comboBoxListReplacer.size();

            /*++ TODO: simply copied => own method ++*/

            JComboBox comboBox = createComponentClassComboBox(
                replacerClasses, null, componentManager);
            if (showToolTips) {
              comboBox.setToolTipText(str("toolTipReplacer"));
            }
            gbLayout.setConstraints(comboBox,
                new GBC(0,5+repNum,3,WEST,HORIZONTAL,
                    new Insets(1,0,1,0)) );

            homePanel.add(comboBox);

            if( showToolTips ){
              comboBox.setToolTipText(str("toolTipReplacer"));
            }
            comboBoxListReplacer.add(comboBox);       


            JButton minusButton = new JButton(str("buttonRemove"));

            minusButton.setActionCommand(ACTION_REMOVE + repNum);

            minusButton.addActionListener(listener);

            gbLayout.setConstraints(minusButton,
                new GBC(3,5+repNum,1,CENTER,NONE) );

            homePanel.add(minusButton);

            buttonListReplacer.add(minusButton);

            /* update add and ok button placement
             * (new comboBoxListReplacer.size()) */

            gbLayout.setConstraints(addButton,
                new GBC(0,5+comboBoxListReplacer.size(),
                    1,WEST,NONE,new Insets(3,0,0,0)) );   

            gbLayout.setConstraints(okButton,
                new GBC(2,6+comboBoxListReplacer.size(),
                    2,SOUTHEAST,NONE,0,0.01,
                    new Insets(3,0,0,0)) );   

            /* update panel */

            homePanel.updateUI();             

          } else if ( actionCommand.startsWith(ACTION_REMOVE) ) {

            //get number of the component that should be removed
            int rmIndex = Integer.parseInt(
                actionCommand.substring(ACTION_REMOVE.length())
            );

            //remove the corresponding box and button

            homePanel.remove(comboBoxListReplacer.get(rmIndex));

            comboBoxListReplacer.remove(rmIndex);             

            homePanel.remove(buttonListReplacer.get(rmIndex));

            buttonListReplacer.remove(rmIndex)

            //change other boxes' and buttons' action commands
            //and positions

            for (int i=rmIndex; i < comboBoxListReplacer.size();
            i++ ) {

              JComboBox cb = comboBoxListReplacer.get(i);

              gbLayout.setConstraints(cb,
                  new GBC(0,5+i,3,WEST,HORIZONTAL,new Insets(1,0,1,0)) );

              JButton button = buttonListReplacer.get(i);

              button.setActionCommand(ACTION_REMOVE + i);

              gbLayout.setConstraints(button,
                  new GBC(3,5+i,1,CENTER,NONE) );

            }


            /* update panel */

            homePanel.updateUI();

          }             

        }

      } 

      /* if this point is reached, ok has been pressed */

      /* check whether the components are a valid selection */

      validComponentSelectionConfirmed = true;

      //input  component

      if ( validComponentSelectionConfirmed ) {

        int inputClassIndex = comboBoxInput.getSelectedIndex();

        if ( inputClassIndex < 0 ) {
          output(str("errorNoInputComponentSelected"));
          validComponentSelectionConfirmed = false;
        } else {

          Class<? extends Component> selectedInputClass =
            inputClasses.get(inputClassIndex);

          assert InputComponent.class.isAssignableFrom(selectedInputClass);

          @SuppressWarnings("unchecked")
          Class<? extends InputComponent<?>> selectedInputClassCast =
            (Class<? extends InputComponent<?>>)selectedInputClass;
         
          componentManager.setInputComponent(selectedInputClassCast);

        }

      }

      //replacer components
      if ( validComponentSelectionConfirmed ) {

        List<Class<? extends ReplacerComponent<?,?>>> selectedReplacerClasses =
          new ArrayList<Class<? extends ReplacerComponent<?,?>>>();

        for (JComboBox comboBoxReplacer : comboBoxListReplacer ) {

          int replacerClassIndex =
            comboBoxReplacer.getSelectedIndex();

          if ( replacerClassIndex < 0 ) {
            output(str("errorNoReplacerComponentSelected"));
            validComponentSelectionConfirmed = false;
            break;
          }

          else {

            assert ReplacerComponent.class.isAssignableFrom(replacerClasses.get(replacerClassIndex));

            @SuppressWarnings("unchecked")
            Class<? extends ReplacerComponent<?,?>> replacerComponent =
              (Class<? extends ReplacerComponent<?,?>>) replacerClasses.get(replacerClassIndex);
           
            selectedReplacerClasses.add(replacerComponent);

          }

        }

        if (validComponentSelectionConfirmed) {

          componentManager.setReplacerComponent(
              selectedReplacerClasses);

        }

      }

      //output component       
      if ( validComponentSelectionConfirmed ) {

        int outputClassIndex = comboBoxOutput.getSelectedIndex();

        if ( outputClassIndex < 0 ) {
          output(str("errorNoOutputComponentSelected"));
          validComponentSelectionConfirmed = false;
        } else {

          Class<? extends Component> selectedOutputClass = outputClasses.get(outputClassIndex);

          assert OutputComponent.class.isAssignableFrom(selectedOutputClass);

          @SuppressWarnings("unchecked")
          Class<? extends OutputComponent<?>> selectedOutputClassCast =
            (Class<? extends OutputComponent<?>>)selectedOutputClass;
                   
          componentManager.setOutputComponent(selectedOutputClassCast);

        }

      }

    } 
       
    mainFrame.setJMenuBar(null);
   
 
 
  /**
   * creates a combo box that allows to choose
   * from a list of component classes
   *
   * @param classes      list of classes to choose from
   * @param activeClass  initially selected class, may be null (nono active)
   * @return             new combo box
   */
  private JComboBox createComponentClassComboBox(
      List<Class<? extends Component>> classes, Class<? extends Component> activeClass,
      ComponentManager componentManager) {

    assert classes != null;
   
    JComboBox comboBox = new JComboBox();
       
    for (Class<? extends Component> c : classes) {     
     
      String itemString;
           
      String localizedName =
        componentManager.getLocalizedComponentName(c);

      if (localizedName != null) {
        itemString = str("localizedComponentName", localizedName, c.getSimpleName());
      } else {
        itemString = c.getSimpleName();
      }
     
      comboBox.addItem(itemString);
     
      if (activeClass != null && c.equals(activeClass)) {
        comboBox.setSelectedItem(itemString);
      }
     
    }   
   
    return comboBox;
  }
 
 
 
  /**
   * creates a html document string for use in a JEditorPane
   * from an unformatted string
   *
   * @param inputString  unformatted string, != null
   */
  private String stringToHTML(String inputString) {
   
    assert inputString != null;
   
    String s = inputString;
   
    //characters with special meaning in html should be shown directly (e. g. as &nbsp;, not as a non-breaking-space)
   
    /*++ TODO: other solutions possible? (e.g. existing method for replacing those characters) ++*/
   
    //& / &amp;
    Pattern ampPattern = Pattern.compile("&");
    Matcher ampMatcher = ampPattern.matcher(s);
    s = ampMatcher.replaceAll("&amp;");
   
    //" / &quot;
    Pattern quotPattern = Pattern.compile("\"");
    Matcher quotMatcher = quotPattern.matcher(s);
    s = quotMatcher.replaceAll("&quot;");
   
    //< / &lt;
    Pattern ltPattern = Pattern.compile("<");
    Matcher ltMatcher = ltPattern.matcher(s);
    s = ltMatcher.replaceAll("&lt;");
   
    //> / &gt;
    Pattern gtPattern = Pattern.compile(">");
    Matcher gtMatcher = gtPattern.matcher(s);
    s = gtMatcher.replaceAll("&gt;");
   
    //replacement of newline characters with <br>
    Pattern newlinePattern = Pattern.compile("\n")
    Matcher newlineMatcher = newlinePattern.matcher(s);
    s = newlineMatcher.replaceAll("<br>");   
                         
   
    //add html + body tags with inline css file string
   
    StringBuilder style = new StringBuilder();   
   
    if (editorFontSizePt > 0) {
      if (style.length() > 0) { style.append(";"); }
      style.append("font-size:").append(editorFontSizePt).append("pt");     
    }
   
    if (! "".equals(editorFontFamily)) {
      if (style.length() != 0) { style.append(";"); }
      style.append("font-family:").append(editorFontFamily);     
    }
   
    StringBuilder result = new StringBuilder();
   
    result.append("<html><body");
    if (style.length() > 0) {
      result.append(" style='").append(style).append("'");
    }   
    result.append(">");
    result.append(s);
    result.append("</body></html>");
     
    return result.toString();   
  }
 
 
  /**
   * {@inheritDoc}
   */
  public String confirmChanges(String label, String oldVersion, String newVersion, String descriptionOfChanges, boolean allowCancel){
   
    if( newVersion.equals(oldVersion) || ( descriptionOfChanges.equals("") && !forceShowChanges ) ){
     
      return newVersion;
     
    }
   
    else{
     
      //prepare strings for presentation
     
      /*++ TODO: instead of â‹™ : use any unicode character not part of the text ++*/
     
      String cleanedStrings[];
     
      if( cutUnchangedParts ){
        cleanedStrings = StringDiffHelper.removeEqualSentences(
            oldVersion, newVersion, cutUnchangedPartsPadding);
      }
      else{
        cleanedStrings = new String[2];
        cleanedStrings[0] = oldVersion;
        cleanedStrings[1] = newVersion;
      }
     
      cleanedStrings = markChanges(cleanedStrings[0],cleanedStrings[1],"â‹™","⋘");
     
     
      for( int i = 0; i < cleanedStrings.length; ++ i ){
   
        cleanedStrings[i] = stringToHTML(cleanedStrings[i]);
       
        //mark changes with colors instead of â‹™ ⋘
                         
        String fontColor = (i==0)?(changesFontColorOld):(changesFontColorNew);
        String bgColor = (i==0)?(changesBgColorOld):(changesBgColorNew);
       
        Pattern changesPattern = Pattern.compile("(.*)â‹™([^⋘]*)⋘(.*)",Pattern.DOTALL|Pattern.MULTILINE)
       
        String stringBeforeReplacement;     
       
        do{
 
          Matcher changesMatcher = changesPattern.matcher(cleanedStrings[i]);
         
          stringBeforeReplacement = new String(cleanedStrings[i]);
       
          cleanedStrings[i] = changesMatcher.replaceFirst("$1<font color="+fontColor+" bgcolor="+bgColor+">$2</font>$3");
         
        } while( ! cleanedStrings[i].equals(stringBeforeReplacement) );
       
      }
     
     
      //create the panel
     
      JPanel changesPanel = new JPanel();
   
      GridBagLayout changesLayout = new GridBagLayout();
     
      changesPanel.setLayout(changesLayout);   
                 
     
      //add content to the panel
       
      //Current text's name ("label")
      if( showLabelInDiffView ){
        //label
        JLabel nameLabel = new JLabel(str("labelTextLabel"));
        if(showToolTips){nameLabel.setToolTipText(str("tooltipTextLabel"));}
        changesLayout.setConstraints(nameLabel,new GBC(0,0,6,WEST,NONE));     
        changesPanel.add(nameLabel)
        //text field
        JTextField nameTextField = new JTextField(label,50);
        if(showToolTips){nameTextField.setToolTipText(str("tooltipTextLabel"));}
        changesLayout.setConstraints(nameTextField,new GBC(0,1,6,WEST,HORIZONTAL));   
        changesPanel.add(nameTextField);     
      }
     
      //description of changes
      //label
      JLabel descriptionLabel = new JLabel(str("labelChanges"));
      if(showToolTips){descriptionLabel.setToolTipText(str("tooltipChanges"));}
      changesLayout.setConstraints(descriptionLabel,new GBC(0,2,6,WEST,NONE));     
      changesPanel.add(descriptionLabel);     
      //text field
      JTextField descriptionTextField = new JTextField(descriptionOfChanges,50);
      if(showToolTips){descriptionTextField.setToolTipText(str("tooltipChanges"));}
      changesLayout.setConstraints(descriptionTextField,new GBC(0,3,6,WEST,HORIZONTAL));   
      changesPanel.add(descriptionTextField);     
       
      //old version
      //label
      JLabel oldVersionLabel = new JLabel(str("labelOldVersion"));
      if(showToolTips){oldVersionLabel.setToolTipText(str("tooltipOldVersion"));}
      changesLayout.setConstraints(oldVersionLabel,new GBC(0,4,6,WEST,NONE));
      changesPanel.add(oldVersionLabel);
      //text area     
      JEditorPane oldVersionEditorPane = new JEditorPane("text/html",cleanedStrings[0]);
      if(showToolTips){oldVersionEditorPane.setToolTipText(str("tooltipOldVersion"));}
      JScrollPane oldVersionScrollPane = new JScrollPane(oldVersionEditorPane);
      changesLayout.setConstraints(oldVersionScrollPane,new GBC(0,5,6,WEST,BOTH))
      changesPanel.add(oldVersionScrollPane);
 
      //new version
      //label
      JLabel newVersionLabel = new JLabel(str("labelNewVersion"));
      if(showToolTips){newVersionLabel.setToolTipText(str("tooltipNewVersion"));}
      changesLayout.setConstraints(newVersionLabel,new GBC(0,6,6,WEST,NONE));   
      changesPanel.add(newVersionLabel);   
      //text area
      JEditorPane newVersionEditorPane = new JEditorPane("text/html",cleanedStrings[1]);
      if(showToolTips){newVersionEditorPane.setToolTipText(str("tooltipNewVersion"));}
      JScrollPane newVersionScrollPane = new JScrollPane(newVersionEditorPane,ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);     
      changesLayout.setConstraints(newVersionScrollPane,new GBC(0,7,6,WEST,BOTH));   
      changesPanel.add(newVersionScrollPane);
 
      //question
      JLabel questionLabel = new JLabel(str("labelAcceptChanges"));
      changesLayout.setConstraints(questionLabel,new GBC(0,8,6,WEST,NONE));   
      changesPanel.add(questionLabel);
           
      //buttons
      //yes
      JButton yesButton = new JButton(str("buttonYes"));
      yesButton.setActionCommand("Action_Yes");     
      yesButton.addActionListener(listener);
      changesLayout.setConstraints(yesButton,new GBC(0,9,1,CENTER,NONE))
      changesPanel.add(yesButton);
      //yes + edit
      JButton yesEditButton = new JButton(str("buttonYesAndEdit"));
      yesEditButton.setActionCommand("Action_YesEdit");     
      yesEditButton.addActionListener(listener);
      changesLayout.setConstraints(yesEditButton,new GBC(1,9,1,CENTER,NONE));
      changesPanel.add(yesEditButton);
      //no + edit
      JButton noEditButton = new JButton(str("buttonNoAndEdit"));
      noEditButton.setActionCommand("Action_NoEdit");     
      noEditButton.addActionListener(listener);
      changesLayout.setConstraints(noEditButton,new GBC(2,9,1,CENTER,NONE));
      changesPanel.add(noEditButton);
      //no
      JButton noButton = new JButton(str("buttonNo"));
      noButton.setActionCommand("Action_No");     
      noButton.addActionListener(listener);
      changesLayout.setConstraints(noButton,new GBC(3,9,1,CENTER,NONE));
      changesPanel.add(noButton);   
     
      if (allowCancel) {
        //cancel
        JButton cancelButton = new JButton(str("buttonCancel"));
        cancelButton.setActionCommand(ACTION_CANCEL);
        cancelButton.addActionListener(listener);
        changesLayout.setConstraints(cancelButton,new GBC(5,9,1,EAST,NONE));
        changesPanel.add(cancelButton);
      }
     
      //show main frame (with new content)
   
      setMainFrameContent(changesPanel);

     
      //wait for a button being pressed
                 
      String chosenVersion = null;

                         
      while( chosenVersion == null ){
             
        boolean edit = false;
     
        try{
          Thread.sleep(100);
        }
        catch(InterruptedException ie){}
             
        if( listener.hasNewActionCommand() ){
         
          String actionCommand = listener.getNextActionCommand();
         
          if( actionCommand.equals("Action_Yes") ){
            chosenVersion = newVersion;
          }
 
          else if( actionCommand.equals("Action_YesEdit") ){
            chosenVersion = newVersion;
            edit = true;
          }   
         
          else if( actionCommand.equals("Action_NoEdit") ){
            chosenVersion = oldVersion;
            edit = true;
          }   
         
          else if( actionCommand.equals("Action_No") ){
            chosenVersion = oldVersion;
          }     
         
          else if( actionCommand.equals(ACTION_CANCEL) ){
            return null;
          }       
         
        }
       
       
        if( edit ){
         
          //deactivate all components
     
          descriptionLabel.setEnabled(false);
          descriptionTextField.setEnabled(false);
          oldVersionLabel.setEnabled(false);
          oldVersionEditorPane.setEnabled(false);
          newVersionLabel.setEnabled(false);
          newVersionEditorPane.setEnabled(false);
          questionLabel.setEnabled(false);
          yesButton.setEnabled(false);
          yesEditButton.setEnabled(false);
          noEditButton.setEnabled(false);
          noButton.setEnabled(false);
               
          //create an edit-window
         
          JFrame editFrame = new JFrame(str("edit"));
         
          editFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         
          JPanel editPanel = new JPanel();
         
          GridBagLayout editPanelGridBagLayout = new GridBagLayout();
         
          editPanel.setLayout(editPanelGridBagLayout);   
     
     
          JTextArea textArea = new JTextArea(chosenVersion);   
          textArea.setLineWrap(editFrameLineWrap);
          if( editFrameLineWrap ){ textArea.setWrapStyleWord(true); }
          JScrollPane scrollPane = new JScrollPane(textArea);
          editPanelGridBagLayout.setConstraints(scrollPane,new GBC(0,0,2,WEST,BOTH));
          editPanel.add(scrollPane);
 
          JButton cancelButton = new JButton(str("buttonCancel"));
          cancelButton.setActionCommand(ACTION_CANCEL);     
          cancelButton.addActionListener(listener);
          editPanelGridBagLayout.setConstraints(cancelButton,new GBC(0,1,1,CENTER,NONE,1,0));
          editPanel.add(cancelButton);       
         
          JButton okButton = new JButton(str("buttonOK"));
          okButton.setActionCommand(ACTION_OK);     
          okButton.addActionListener(listener);
          okButton.setPreferredSize( cancelButton.getPreferredSize() );
          editPanelGridBagLayout.setConstraints(okButton,new GBC(1,1,1,CENTER,NONE,1,0));
          editPanel.add(okButton);

          editFrame.add(editPanel);
             
          //place it in the middle of the main frame, with the specified size
          int locationX = mainFrame.getLocation().x + ( mainFrame.getSize().width  - editFrameSizeX )/2;
          int locationY = mainFrame.getLocation().y + ( mainFrame.getSize().height - editFrameSizeY )/2;
          editFrame.setLocation( locationX, locationY );
          editFrame.setSize(editFrameSizeX,editFrameSizeY);
         
          editFrame.setVisible(true);
         
         
          //wait for button action
   
          boolean buttonPressed = false;
                             
          while( !buttonPressed ){
         
            try{
              Thread.sleep(100);
            }
            catch(InterruptedException ie){}
                 
            if( listener.hasNewActionCommand() ){
             
              String actionCommand = listener.getNextActionCommand();
             
              if( actionCommand.equals(ACTION_OK) ){
               
                buttonPressed = true;
               
                //get the edited text       
                chosenVersion = textArea.getText();
               
              else if( actionCommand.equals(ACTION_CANCEL) ){
               
                buttonPressed = true;
               
                //activate all components
                descriptionLabel.setEnabled(true);
                descriptionTextField.setEnabled(true);
                oldVersionLabel.setEnabled(true);
                oldVersionEditorPane.setEnabled(true);
                newVersionLabel.setEnabled(true);
                newVersionEditorPane.setEnabled(true);
                questionLabel.setEnabled(true);
                yesButton.setEnabled(true);
                yesEditButton.setEnabled(true);
                noEditButton.setEnabled(true);
                noButton.setEnabled(true);

                //prevent the while-loop from terminating               
                chosenVersion = null;
               
              }
             
            }
           
          }
         
          //close the edit frame       
          editFrame.dispose();
         
        }             

       
      }  //end of while(chosenVersion==null)-loop
     
         
      //return the result
     
      return chosenVersion;

    }             
 
  }
 
 
  public NamedDataSet request(UIRequest... requests){

    NamedDataSet reply = new NamedDataSet();

    //if only one value is requested, sometimes a dialog box can be used
    //(for boolean values, pure output and file paths)
   
    /*++ TODO: problem: help texts ?! ++*/

    //single boolean request
   
    if( requests.length == 1 && requests[0].getType() == Request_Boolean ){     
     
      int response = JOptionPane.showConfirmDialog(mainFrame,requests[0].label,str("titleWindow"),JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
       
      if( response == JOptionPane.YES_OPTION ){

        reply.add(requests[0].name,true);
       
      }
     
      else{

        reply.add(requests[0].name,false);
       
      }
     
    }   
   
    //output-"request"
   
    else if( requests.length == 1 && requests[0].getType() == Request_Output ){ 
     
      output(requests[0].label);     
     
    }
       
    //request for a file path
     
    else if( requests.length == 1 && requests[0].getType() == UIRequest.Type.Request_String
             && ((UIRequest_String)requests[0]).layoutFlags != null
             && ( ((UIRequest_String)requests[0]).layoutFlags.contains(readPath)
                || ((UIRequest_String)requests[0]).layoutFlags.contains(writePath) ) ){
                
      String response = null;
     
      //create a file chooser dialog
               
      JFileChooser chooser = new JFileChooser();
     
      chooser.setDialogTitle(requests[0].label);
     
      //show the dialog
     
      int returnVal;
     
      if( ((UIRequest_String)requests[0]).layoutFlags.contains(readPath) ){
        returnVal = chooser.showOpenDialog(mainFrame);
      } else {
        returnVal = chooser.showSaveDialog(mainFrame);
      }
           
      //get the result
     
      if(returnVal == JFileChooser.APPROVE_OPTION) {
         response = chooser.getSelectedFile().getPath();
      }
      else{ //cancelled
         return null;
      }

      if( response != null ){
        reply.add(requests[0].name,response);
      }
     
    }   
   
   
    //other requests: full window
   
    else{     
     
      //prepare panel and layout-object
   
      JPanel requestPanel = new JPanel();
 
      GridBagLayout gbLayout = new GridBagLayout();
     
      requestPanel.setLayout(gbLayout);   
           
           
      listener = new GUIListener();

   
     
      //variable for finding out whether this is an output-only request
     
      boolean outputOnly = true;
     
     
      //create arrays where the GUI's components are stored so they can be accessed later
     
      JLabel guiLabelArray[] = new JLabel[requests.length];
      JComponent guiObjectArray[] = new JComponent[requests.length];
       
     
      //arrange GUI
           
      for( int requestIndex = 0; requestIndex < requests.length; ++ requestIndex ){
       
        UIRequest request = requests[requestIndex];
       
        //modify the outputOnly-variable
       
        if( request.name != null ){ outputOnly = false; }
       
        //place the label (unless type is UIRequest_Boolean or UIRequest_Output)
               
        if( request.getType() != Request_Boolean && request.getType() != Request_Output ){

          guiLabelArray[requestIndex] = new JLabel(request.label);

          if(showToolTips && request.help != null && !request.help.equals("") ){
            guiLabelArray[requestIndex].setToolTipText(request.help);
          }
         
          gbLayout.setConstraints(guiLabelArray[requestIndex],new GBC(0,(2*requestIndex),3,SOUTHWEST,NONE,new Insets(5,0,1,0)));
         
          requestPanel.add(guiLabelArray[requestIndex]);
         
        }     
       
        //place the other objects for the request
       
        switch( requests[requestIndex].getType() ){
         
          case Request_Output:  {
   
            UIRequest_Output outputRequest = (UIRequest_Output)request;
                       
            //create a not-editable text area (with line wrap at word boundaries)
            //that has the same color as the panel (indicating read-only) 
           
            JTextArea outputTextArea = new JTextArea(outputRequest.label);

            outputTextArea.setEditable(false);
           
            outputTextArea.setLineWrap(true);
            outputTextArea.setWrapStyleWord(true);
         
            if(showToolTips && outputRequest.help != null && !outputRequest.help.equals("") ){
              outputTextArea.setToolTipText(outputRequest.help);
            }
           
            outputTextArea.setBackground( requestPanel.getBackground() );
           
            //create a scroll pane for the text area and put it on the panel
             
            JScrollPane textScrollPane = new JScrollPane(outputTextArea);
             
            gbLayout.setConstraints(textScrollPane,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,BOTH,new Insets(10,0,3,0)))
             
            requestPanel.add(textScrollPane);
               
          } break;
           
          case Request_Boolean:
         
            UIRequest_Boolean booleanRequest = (UIRequest_Boolean)request;
         
            //create the check box
           
            JCheckBox checkBoxBooleanRequest = new JCheckBox(booleanRequest.label);

            if(showToolTips && booleanRequest.help != null && !booleanRequest.help.equals("") ){
              checkBoxBooleanRequest.setToolTipText(booleanRequest.help);
            }
           
            if( booleanRequest.startingValue != null ){
              checkBoxBooleanRequest.setSelected(booleanRequest.startingValue);
            }
           
            if( booleanRequest.name == null ){
              //setEditable impossible for checkboxes, setEnabled used instead
              checkBoxBooleanRequest.setEnabled(false);
            }
           
            gbLayout.setConstraints(checkBoxBooleanRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,NONE,new Insets(5,0,0,0)))
         
            requestPanel.add(checkBoxBooleanRequest);
           
            guiObjectArray[requestIndex] = checkBoxBooleanRequest;
           
            break;   

          case Request_String:
   
            UIRequest_String stringRequest = (UIRequest_String)request;
                       
            //create the text field / password field / text area (depending on the flags)
           
            JTextComponent textComponentStringRequest;
           
            if( stringRequest.layoutFlags != null &&
                stringRequest.layoutFlags.contains( multipleLines ) ){
           
              textComponentStringRequest = new JTextArea(stringRequest.startingValue);

              ((JTextArea)textComponentStringRequest).setLineWrap(stringRequest.layoutFlags.contains(lineWrap));
              ((JTextArea)textComponentStringRequest).setWrapStyleWord(true);
             
              JScrollPane textScrollPane = new JScrollPane(textComponentStringRequest);
             
              gbLayout.setConstraints(textScrollPane,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,BOTH))
             
              requestPanel.add(textScrollPane);
               
            else if( stringRequest.layoutFlags != null &&
                       stringRequest.layoutFlags.contains( hideInput ) ){
             
              textComponentStringRequest = new JPasswordField(stringRequest.startingValue);
             
              gbLayout.setConstraints(textComponentStringRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,HORIZONTAL))

              requestPanel.add(textComponentStringRequest);
             
            else{
           
              textComponentStringRequest = new JTextField(stringRequest.startingValue);
   
              gbLayout.setConstraints(textComponentStringRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,HORIZONTAL))
             
              requestPanel.add(textComponentStringRequest);
             
            }

            if(showToolTips && stringRequest.help != null && !stringRequest.help.equals("") ){
              textComponentStringRequest.setToolTipText(stringRequest.help);
            }
           
            if( stringRequest.name == null ){
              textComponentStringRequest.setEditable(false);
            }
           
            guiObjectArray[requestIndex] = textComponentStringRequest;             
           
            break;
           
          case Request_Integer:

            UIRequest_Integer integerRequest = (UIRequest_Integer)request;
                 
            //create the text field
           
            JTextField textFieldIntegerRequest = new JTextField();

            if(showToolTips && integerRequest.help != null && !integerRequest.help.equals("") ){
              textFieldIntegerRequest.setToolTipText(integerRequest.help);
            }
           
            if( integerRequest.startingValue != null ){
              textFieldIntegerRequest.setText(integerRequest.startingValue.toString());
            }
           
            if( integerRequest.name == null ){
              textFieldIntegerRequest.setEditable(false);
            }
       
            gbLayout.setConstraints(textFieldIntegerRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,HORIZONTAL));
           
            requestPanel.add(textFieldIntegerRequest);

            guiObjectArray[requestIndex] = textFieldIntegerRequest;           
           
            break;
         
          case Request_Float:

            UIRequest_Float floatRequest = (UIRequest_Float)request;
       
            //create the text field
           
            JTextField textFieldFloatRequest = new JTextField();

            if( showToolTips && floatRequest.help != null && !floatRequest.help.equals("") ){
              textFieldFloatRequest.setToolTipText(floatRequest.help);
            }
           
            if( floatRequest.startingValue != null ){
              textFieldFloatRequest.setText(floatRequest.startingValue.toString());
            }
           
            if( floatRequest.name == null ){
              textFieldFloatRequest.setEditable(false);
            }
           
            requestPanel.add(textFieldFloatRequest);

            gbLayout.setConstraints(textFieldFloatRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,HORIZONTAL));

            guiObjectArray[requestIndex] = textFieldFloatRequest;           
           
            break;           
                     
          case Request_Selection:
   
            UIRequest_Selection selectionRequest = (UIRequest_Selection)request;
       
            //create the combo box
           
            JComboBox comboBoxSelectionRequest = new JComboBox();

            if( showToolTips && selectionRequest.help != null && !selectionRequest.help.equals("") ){
              comboBoxSelectionRequest.setToolTipText(selectionRequest.help);
            }   
           
            for( String selectionName : selectionRequest.selectionNames ){
           
              comboBoxSelectionRequest.addItem(selectionName);
           
            }

            if( selectionRequest.startingValue != null
             && selectionRequest.startingValue >= 0 && selectionRequest.startingValue < selectionRequest.selectionNames.length ){
              comboBoxSelectionRequest.setSelectedIndex(selectionRequest.startingValue);
            } else {
              comboBoxSelectionRequest.setSelectedIndex(-1);
            }
           
            if( selectionRequest.name == null ){           
              comboBoxSelectionRequest.setEditable(false);
            }
           
            gbLayout.setConstraints(comboBoxSelectionRequest,new GBC(0,(2*requestIndex)+1,3,NORTHWEST,HORIZONTAL));

            requestPanel.add(comboBoxSelectionRequest);

            guiObjectArray[requestIndex] = comboBoxSelectionRequest;           
           
            break

        }
           
      }
     
      //cancel-Button (only if at least one component requiring input exists)
      //it will always be created because it's used for size calculation of the OK button.
           
      JButton cancelButton = new JButton(str("buttonCancel"));
     
      cancelButton.setActionCommand(ACTION_CANCEL);
 
      if( !outputOnly ){   
       
        cancelButton.addActionListener(listener);
     
        gbLayout.setConstraints(cancelButton,new GBC(1,(2*requests.length),1,SOUTHEAST,NONE,1,0.01,new Insets(3,0,0,5)));
     
        requestPanel.add(cancelButton);
      }
     
      //ok-Button
     
      JButton okButton = new JButton(str("buttonOK"));
     
      okButton.setActionCommand(ACTION_OK);
     
      okButton.addActionListener(listener);
     
      okButton.setPreferredSize( cancelButton.getPreferredSize() ); //same size as Cancel-button
           
      gbLayout.setConstraints(okButton,new GBC(2,(2*requests.length),1,SOUTHEAST,NONE,0,0.01,new Insets(3,0,0,0)));
     
      requestPanel.add(okButton);
       
     
      //put the request panel into the main frame
     
      setMainFrameContent(requestPanel);
     
     
      //wait for valid user replies
      //if Cancel is pressed, the method is left immediately, returning null !!!
     
      boolean validRepliesEntered = false;
     
      while( !validRepliesEntered ){
              
        //wait for OK or Cancel being pressed
             
        boolean buttonOKPressed = false;
       
        while( !buttonOKPressed ){
       
          try{
            Thread.sleep(100);
          }
          catch(InterruptedException ie){}
         
          if( listener.hasNewActionCommand() ){
           
            String actionCommand = listener.getNextActionCommand();
           
            if( actionCommand.equals(ACTION_OK) ){
           
              buttonOKPressed = true;
           
            }

            else if( actionCommand.equals(ACTION_CANCEL) ){
           
              return null;   // #### !! return-point !! ####
           
            }
           
          }
         
        }     
       
        //get replies
       
        validRepliesEntered = true;
       
        for( int requestIndex = 0; requestIndex < requests.length && validRepliesEntered == true; ++ requestIndex ){
         
          if( requests[requestIndex].name != null ){
         
            switch( requests[requestIndex].getType() ){
   
              case Request_Boolean:
             
                reply.add(requests[requestIndex].name,((JCheckBox)guiObjectArray[requestIndex]).isSelected());
               
                break;   
   
              case Request_String:
   
                reply.add(requests[requestIndex].name,((JTextComponent)guiObjectArray[requestIndex]).getText());
   
                break;
               
              case Request_Integer:
           
                String integerAsString = ((JTextField)guiObjectArray[requestIndex]).getText();
               
                try{
                 
                  int integerValue = Integer.parseInt(integerAsString);
                 
                  if( integerValue < ((UIRequest_Integer)requests[requestIndex]).range_min
                   || integerValue > ((UIRequest_Integer)requests[requestIndex]).range_max ){
                    
                    output(str("errorRange", integerAsString, ((UIRequest_Integer)requests[requestIndex]).range_min, ((UIRequest_Integer)requests[requestIndex]).range_max));
                                   
                    validRepliesEntered = false;         
                   
                  }
 
                  reply.add(requests[requestIndex].name,integerValue);
                 
                }
               
                catch( NumberFormatException nfe ){
                 
                  output(str("errorNoValidInteger", integerAsString));
                                   
                  validRepliesEntered = false;
                 
                }
               
                break;
             
              case Request_Float:
             
                String floatAsString = ((JTextField)guiObjectArray[requestIndex]).getText();
               
                try{
                 
                  float floatValue = Float.parseFloat(floatAsString);
                 
                  if( floatValue < ((UIRequest_Float)requests[requestIndex]).range_min
                   || floatValue > ((UIRequest_Float)requests[requestIndex]).range_max ){
                    
                    output(str("errorRange", floatAsString, ((UIRequest_Float)requests[requestIndex]).range_min, ((UIRequest_Float)requests[requestIndex]).range_max));
                                   
                    validRepliesEntered = false;         
                   
                  }
                 
                  reply.add(requests[requestIndex].name,floatValue);
                 
                }
               
                catch( NumberFormatException nfe ){
                 
                  output(str("errorNoValidFloat", floatAsString));
                                   
                  validRepliesEntered = false;
                 
                }
                             
                break;           
             
              case Request_Selection:
             
                int selectedIndex = ((JComboBox)guiObjectArray[requestIndex]).getSelectedIndex();
               
                if( selectedIndex < 0 || selectedIndex > ((UIRequest_Selection)requests[requestIndex]).selectionNames.length ){
                 
                  output(str("errorNoValidOption"));
                                   
                  validRepliesEntered = false;
                 
                }                 
       
                reply.add(requests[requestIndex].name,selectedIndex);
                           
                break
   
            }
         
          }
       
        }
       
      }
 
      //disable the buttons and all the gui objects (for the time until the next request)
   
      for( JComponent guiComponent : guiObjectArray ){
        if( guiComponent != null ){
          guiComponent.setEnabled(false);
        }
      }            
     
      okButton.setEnabled(false);
      cancelButton.setEnabled(false);
       
    }
   
 
    //return the reply

    return reply;
   
  }
   
 
  private void output(String message) {
   
    JOptionPane.showMessageDialog(mainFrame, message, str("titleWindow"),
                              JOptionPane.PLAIN_MESSAGE);   
   
  }
 
  @Override
  public void handleConfigurationUpdate() {
    updateLookAndFeel();   
    updateMainFrameSize();   
  }
 
  public void setLanguageResourceBundle(ResourceBundle langRB) {

    super.setLanguageResourceBundle(langRB);
   
    if (mainFrame != null) {
      mainFrame.setTitle(str("titleWindow"));
    }
  }
 
  private void updateLookAndFeel() {
   
    boolean success = true;
   
    try {
     
      String lookAndFeel = useSystemLookAndFeel
                           ? UIManager.getSystemLookAndFeelClassName()
                           : UIManager.getCrossPlatformLookAndFeelClassName();
     
                        
      /* set font sizes */
      /* TODO: This depends on the naming conventions of the L&F.
       * Replace this with factory methods for swing components
       * that also modify font size
       */
                          
      Object[] objs = UIManager.getLookAndFeel().getDefaults().keySet().toArray();
     
      for( int i = 0; i < objs.length; i++ )
      {
        if( objs[i].toString().toUpperCase().indexOf( ".FONT" ) != -1 )
        {
          Font font = UIManager.getFont( objs[i] );
          font = font.deriveFont( (float)font.getSize() * uiFontScaleFactor );
          UIManager.put( objs[i], new FontUIResource(font) );
        }
      }
                          
      UIManager.setLookAndFeel(lookAndFeel);
     
      if (mainFrame != null) {
        SwingUtilities.updateComponentTreeUI(mainFrame);
      }
     
    } catch (InstantiationException e) {
      success = false;
    } catch (IllegalAccessException e) {
      success = false;
    } catch (UnsupportedLookAndFeelException e) {
      success = false;
    } catch (ClassNotFoundException e) {
      success = false;
    }   
   
    if (!success) {
      output(str("errorLookAndFeel"));
   
   
  }
 
  private void updateMainFrameSize() {
   
    mainFrame.setBounds(
        mainFramePositionX,
        mainFramePositionY,
        mainFrameSizeX,mainFrameSizeY);
   
  }
 
  public DefaultGUI(){
   
    updateLookAndFeel();
   
    //create the main frame (empty)
   
    mainFrame = new JFrame();
   
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   
    updateMainFrameSize();
           
 
   
  private JMenuBar createHomeViewMenuBar(final ComponentManager componentManager) {
   
    JMenuBar menuBar = new JMenuBar();
   
    JMenuItem manageComponents = new JMenuItem(str("manageComponents"));
    manageComponents.addActionListener(new ActionListener() {     
      @Override public void actionPerformed(ActionEvent e) {
        ComponentManagementFrame cmf =
          new ComponentManagementFrame(DefaultGUI.this, mainFrame, componentManager);
        cmf.setVisible(true);
      }
    });
    menuBar.add(manageComponents);
   
    return menuBar;
   
  }
 
  //make translation methods available to other classes in the package
 
  @Override
  protected String str(String key) {
    return super.str(key);
  }
 
  @Override
  protected String str(String key, Object... arguments) {
    return super.str(key, arguments);
  }
 
}

TOP

Related Classes of net.sf.jeters.components.DefaultGUI.DefaultGUI$GBC

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
-20639858-1', 'auto'); ga('send', 'pageview');