/*
* 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 , not as a non-breaking-space)
/*++ TODO: other solutions possible? (e.g. existing method for replacing those characters) ++*/
//& / &
Pattern ampPattern = Pattern.compile("&");
Matcher ampMatcher = ampPattern.matcher(s);
s = ampMatcher.replaceAll("&");
//" / "
Pattern quotPattern = Pattern.compile("\"");
Matcher quotMatcher = quotPattern.matcher(s);
s = quotMatcher.replaceAll(""");
//< / <
Pattern ltPattern = Pattern.compile("<");
Matcher ltMatcher = ltPattern.matcher(s);
s = ltMatcher.replaceAll("<");
//> / >
Pattern gtPattern = Pattern.compile(">");
Matcher gtMatcher = gtPattern.matcher(s);
s = gtMatcher.replaceAll(">");
//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);
}
}