/*
* Datei: AllgemeinerDialog.java
* Autor(en): Lukas König
* Java-Version: 6.0
* Erstellt (vor): 26.06.2007
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.miscellaneous.system.windowFrames;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextComponent;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.miscellaneous.system.FileNamePostfixFilter;
import eas.startSetup.GlobalVariables;
import eas.startSetup.marbBuilder.MultiLineLabel;
/**
* Implementierung eines allgemeinen Dialogsfensters.
*
* @author Lukas König
*/
public class GeneralDialog extends JDialog implements ActionListener, KeyListener {
/**
* Der OK-String.
*/
public static final String OK = "Ok";
/**
* Der YES-String.
*/
public static final String YES = "Yes";
/**
* Der YES-Remember-String.
*/
public static final String YES_REM = YES + " (remember decision)";
/**
* Der NO-String.
*/
public static final String NO = "No";
/**
* Der YES-Remember-String.
*/
public static final String NO_REM = NO + " (remember decision)";
/**
* Der Cancel-String.
*/
public static final String CANCEL = "Cancel";
/**
* Allgemeine OK-Dialog-Buttons.
*/
public static final String[] OK_BUTT = {OK};
/**
* Allgemeine OK-Abbrechen-Dialog-Buttons.
*/
public static final String[] OK_CANCEL_BUTT = {OK, CANCEL};
/**
* Allgemeine Ja-Nein-Dialog-Buttons.
*/
public static final String[] YES_NO = {YES, NO};
/**
* Allgemeine Ja-Nein-Abbrechen-Dialog-Buttons.
*/
public static final String[] YES_NO_CANCEL = {YES, NO, CANCEL};
/**
* Allgemeine Ja-Nein-Abbrechen-Dialog-Buttons.
*/
public static final String[] YES_NO_REM = {YES, NO, NO_REM};
/**
* Allgemeine Ja-Nein-Abbrechen-Dialog-Buttons.
*/
public static final String[] YES_REM_NO = {YES, YES_REM, NO};
/**
* Allgemeine Ja-Nein-Abbrechen-Dialog-Buttons.
*/
public static final String[] YES_REM_NO_REM = {YES, YES_REM, NO, NO_REM};
/**
* Die Serial-Version-ID vom 28. April 2007
*/
private static final long serialVersionUID = 2504188077455833733L;
/**
* Das gewählte Element.
*/
private String result;
/**
* Die Textbox deren Wert zum Zeitpunkt des Klicks auf einen Button zurück-
* gegeben wird.
*/
private TextComponent text;
/**
* Eine Liste.
*/
private java.awt.List liste;
/**
* zusätzliche Textbox deren Wert zum Zeitpunkt des Klicks auf einen
* Button zurückgegeben wird, falls sie angefordert war.
*/
private TextComponent zusatzText;
/**
* Konstruktor mit Vektor statt ArrayList für Buttons.
*
* @param owner Das Vaterfenster.
* @param msg Anzuzeigende Nachricht.
* @param titel Der Titel des Fensters.
* @param buttons Liste von Strings, die von den anzuzeigenden
* Buttons dargestellt werden.
* @param textBox In einer Textbox darzustellender String.
* @param einzeilig Ob die Textbox einzeilig ist.
*/
public GeneralDialog(
final Frame owner,
final String msg,
final String titel,
final String[] buttons,
final String textBox) {
this(
owner,
msg,
titel,
GeneralDialog.arrToArrList(buttons),
textBox);
}
/**
* Konvertiert einen Vektor aus Strings in eine ArrayList.
*
* @param liste Die Liste.
*
* @return Die konvertierte Liste.
*/
private static ArrayList<String> arrToArrList(final String[] liste) {
ArrayList<String> arrListe = new ArrayList<String>(liste.length);
for (String s : liste) {
arrListe.add(s);
}
return arrListe;
}
public GeneralDialog(
final Frame owner,
final String msg,
final String titel,
final String[] buttons,
final String textBox,
final int textBoxHeight,
final int textBoxWidth,
final boolean einzeilig) {
this(owner, msg, titel, convert(buttons), textBox, textBoxHeight, textBoxWidth, einzeilig);
this.text.selectAll();
}
private static ArrayList<String> convert(final String[] buttons) {
ArrayList<String> butts = new ArrayList<String>(buttons.length);
for (String s : buttons) {
butts.add(s);
}
return butts;
}
/**
* Der Konstruktor.
*
* @param owner Das Vaterfenster.
* @param msg Anzuzeigende Nachricht.
* @param titel Der Titel des Fensters.
* @param buttons Liste von Strings, die von den anzuzeigenden
* Buttons dargestellt werden.
* @param textBox In einer Textbox darzustellender String.
* @param textBoxHeight Höhe der Textbox in ZEILEN!
* @param textBoxWidth Breite der Textbox in ZEICHEN!.
* @param einzeilig Ob die Textbox einzeilig ist.
*/
public GeneralDialog(
final Frame owner,
final String msg,
final String titel,
final ArrayList<String> buttons,
final String textBox,
final int textBoxHeight,
final int textBoxWidth,
final boolean einzeilig) {
super(owner, titel, true);
final int locationX = 200;
final int locationY = 200;
final int borderX = 4;
final int borderY = 4;
final int lrMargin = 20;
final int tbMargin = 10;
Iterator<String> it;
Button butt;
this.result = "";
this.zusatzText = null;
this.setAlwaysOnTop(true);
//Fenster
this.setLayout(new BorderLayout(borderX, borderY));
this.setResizable(true);
this.setLocation(locationX, locationY);
//Message
if (textBox == null) {
MultiLineLabel lab = new MultiLineLabel(msg);
lab.setLeftRightMargin(lrMargin);
lab.setTopBottomMargin(tbMargin);
this.add(lab, BorderLayout.CENTER);
} else {
if (einzeilig) {
this.text = new TextField(textBox,
textBoxWidth);
this.text.addKeyListener(this);
this.text.setSelectionStart(0);
this.text.setSelectionEnd(Integer.MAX_VALUE);
} else {
this.text = new TextArea(textBox,
textBoxHeight,
textBoxWidth);
}
this.add(this.text, BorderLayout.CENTER);
this.text.selectAll();
this.text.setCaretPosition(0);
}
//Buttons
Panel panel = new Panel();
panel.setLayout(new FlowLayout(FlowLayout.CENTER));
this.stdButton = buttons.get(0);
it = buttons.iterator();
while (it.hasNext()) {
butt = new Button(it.next());
butt.addActionListener(this);
panel.add(butt);
}
this.add(panel, BorderLayout.SOUTH);
this.pack();
this.setSize(Math.max(this.getWidth(), 400), Math.max(this.getHeight(), 100));
}
private String stdButton = "";
/**
* Resets the cursor in the depicted text box to the top left position.
*/
public void resetTextBoxCaret() {
this.text.setCaretPosition(0);
}
/**
* Erzeugt einen Dialog basierend auf einer Liste.
*
* @param owner Elternfenster.
* @param title Der Titel des Fensters.
* @param message Anzuzeigende Nachricht.
* @param elemente Die Listenelemente.
* @param button1 Ein Button.
* @param button2 Ein Button.
* @param multi Ob Mehrfachselektion möglich ist.
* @param zusatzTextFeld Ob ein zusätzliches Textfeld angezeigt werden
* soll (>= 0) oder nicht (< 0). Gleichzeitig die
* Voreinstellung des Textfeldes.
*/
public GeneralDialog(
final Frame owner,
final String title,
final String message,
final java.util.List<String> elemente,
final String button1,
final String button2,
final boolean multi,
final int zusatzTextFeld) {
super(owner, title, true);
this.setAlwaysOnTop(true);
if (zusatzTextFeld >= 0) {
this.zusatzText = new TextField();
this.zusatzText.setText("" + zusatzTextFeld);
} else {
this.zusatzText = null;
}
this.result = "";
this.liste = new java.awt.List(elemente.size(), multi);
Button but1 = new Button(button1);
Button but2 = new Button(button2);
MultiLineLabel lab = new MultiLineLabel(message);
this.setLayout(new GridLayout(2, 2));
this.add(this.liste);
if (this.zusatzText == null) {
this.add(lab);
} else {
this.add(this.zusatzText);
this.setTitle(this.getTitle() + " (" + message + ")");
}
lab.setLeftRightMargin(50);
this.add(but1);
this.add(but2);
but1.addActionListener(this);
but2.addActionListener(this);
this.setBounds(100, 100, 500, 150);
Iterator<String> it = elemente.iterator();
while (it.hasNext()) {
this.liste.add(it.next().toString());
}
}
/**
* Der Konstruktor.
*
* @param owner Das Vaterfenster.
* @param msg Anzuzeigende Nachricht.
* @param titel Der Titel des Fensters.
* @param buttons Liste von Strings, die von den anzuzeigenden Buttons
* dargestellt werden.
* @param textBox In einer Textbox darzustellender String.
*/
public GeneralDialog(
final Frame owner,
final String msg,
final String titel,
final ArrayList<String> buttons,
final String textBox) {
this(owner,
msg,
titel,
buttons,
textBox,
20,
100,
false);
}
/**
* Fängt das Klicken auf einen Button ab.
*
* @param event Das ausgelöste Ereignis.
*/
@Override
public void actionPerformed(final ActionEvent event) {
this.result = event.getActionCommand();
this.setVisible(false);
this.dispose();
}
/**
* Gibt die Wahl des Benutzers zurück.
*
* @return Das Ergebnis des Benutzers.
*/
public String getResult() {
return this.result;
}
public void setResult(final String res) {
this.result = res;
}
/**
* Gibt den Text der Textbox zum Klickzeitpunkt zurück.
*
* @return Text der Textbox zum Klickzeitpunkt.
*/
public String getText() {
return this.text.getText();
}
/**
* Gibt den Text der Zusatztextbox zum Klickzeitpunkt zurück.
*
* @return Text der Zusatztextbox zum Klickzeitpunkt.
*/
public String getZusatzText() {
if (this.zusatzText != null) {
return this.zusatzText.getText();
} else {
return null;
}
}
/**
* @return Returns the liste.
*/
public java.awt.List getListe() {
return this.liste;
}
/**
* Sets the position of the window.
*
* @param pos Position vector.
*/
public void setPosition(final Vector2D pos) {
this.setBounds((int) pos.x, (int) pos.y,
this.getWidth(), this.getHeight());
}
/**
* Sets the size of the window.
*
* @param size Size vector.
*/
public void setSize(final Vector2D size) {
this.setBounds(this.getX(), this.getY(),
(int) size.x, (int) size.y);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
this.result = this.stdButton;
this.setVisible(false);
this.dispose();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
public static boolean yesNoAnswer(String title, String question) {
GeneralDialog dia = new GeneralDialog(null, question, title, GeneralDialog.YES_NO, null);
dia.setVisible(true);
return dia.getResult().equals(GeneralDialog.YES);
}
private static HashMap<String, String> yesNoRem = new HashMap<String, String>();
public static boolean yesRememberNoAnswer(String title, String question, String id) {
if (yesNoRem.get(id) != null && yesNoRem.get(id).equals(GeneralDialog.YES_REM)) {
return true;
}
GeneralDialog dia = new GeneralDialog(null, question, title, GeneralDialog.YES_REM_NO, null);
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.YES_REM)) {
yesNoRem.put(id, GeneralDialog.YES_REM);
}
return dia.getResult().equals(GeneralDialog.YES) || dia.getResult().equals(GeneralDialog.YES_REM);
}
public static boolean yesNoRememberAnswer(String title, String question, String id) {
if (yesNoRem.get(id) != null && yesNoRem.get(id).equals(GeneralDialog.NO_REM)) {
return false;
}
GeneralDialog dia = new GeneralDialog(null, question, title, GeneralDialog.YES_NO_REM, null);
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.NO_REM)) {
yesNoRem.put(id, GeneralDialog.NO_REM);
}
return dia.getResult().equals(GeneralDialog.YES) || dia.getResult().equals(GeneralDialog.YES_REM);
}
public static boolean yesRememberNoRememberAnswer(String title, String question, String id) {
if (yesNoRem.get(id) != null && yesNoRem.get(id).equals(GeneralDialog.NO_REM)) {
return false;
}
if (yesNoRem.get(id) != null && yesNoRem.get(id).equals(GeneralDialog.YES_REM)) {
return true;
}
GeneralDialog dia = new GeneralDialog(null, question, title, GeneralDialog.YES_REM_NO_REM, null);
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.NO_REM)) {
yesNoRem.put(id, GeneralDialog.NO_REM);
}
if (dia.getResult().equals(GeneralDialog.YES_REM)) {
yesNoRem.put(id, GeneralDialog.YES_REM);
}
return dia.getResult().equals(GeneralDialog.YES) || dia.getResult().equals(GeneralDialog.YES_REM);
}
public static void resetRememberedDecision(String id) {
yesNoRem.put(id, null);
}
public static void resetRememberedDecisions() {
yesNoRem.clear();
}
private static HashMap<String, Integer> intUserDecisions = new HashMap<String, Integer>();
private static HashMap<String, String> stringUserDecisions = new HashMap<String, String>();
public static Integer getNumberFromUser(String title, String questionToAsk, String id) {
String question = questionToAsk;
if (intUserDecisions.get(id) != null) {
question = "" + intUserDecisions.get(id);
}
try {
GeneralDialog dia = new GeneralDialog(
null,
null,
title,
GeneralDialog.OK_CANCEL_BUTT,
question,
10,
10,
true);
dia.text.selectAll();
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.OK)) {
intUserDecisions.put(id, Integer.parseInt(dia.getText()));
return Integer.parseInt(dia.getText());
}
return null;
} catch (NumberFormatException e) {
return null;
}
}
public static String getStringFromUser(String title, String questionToAsk, String id) {
String question = questionToAsk;
if (stringUserDecisions.get(id) != null) {
question = "" + stringUserDecisions.get(id);
}
GeneralDialog dia = new GeneralDialog(
null,
null,
title,
GeneralDialog.OK_CANCEL_BUTT,
question,
10,
10,
true);
dia.text.selectAll();
dia.setVisible(true);
if (dia.getResult().equals(GeneralDialog.OK)) {
stringUserDecisions.put(id, dia.getText());
return dia.getText();
}
return null;
}
public static void resetLongTimeOperationID(String id) {
maxTimeStartingTimes.remove(id);
GeneralDialog.resetRememberedDecision(id);
}
private static HashMap<String, Long> maxTimeStartingTimes = new HashMap<String, Long>();
public static boolean continueLongOperation(String title, String question, long maxTime, String id) {
Long startingTime = maxTimeStartingTimes.get(id);
if (startingTime == null) {
maxTimeStartingTimes.put(id, System.currentTimeMillis());
} else {
if (System.currentTimeMillis() - startingTime > maxTime) {
if (yesRememberNoAnswer(title, question, id)) {
maxTimeStartingTimes.put(id, System.currentTimeMillis());
} else {
resetLongTimeOperationID(id);
return false;
}
}
}
return true;
}
public static void message(String message, String title) {
GeneralDialog dia = new GeneralDialog(
null,
message,
title,
GeneralDialog.OK_BUTT,
null);
dia.setVisible(true);
}
private static HashMap<String, File> externalFiles = new HashMap<>();
/**
* If the file path is already known, it will just be returned.
* If not, the file path will be tried to be loaded from a config file
* in the tempDir. If it exists there, this path will be remembered
* for next time and returned. If not, the user will be prompted to
* select the file path. Afterward, the path will be stored in the
* tempDir to avoid a prompt next time, and as well it will
* be remembered for the next call during the current session.
*
* @param fileID The id that identifies the required path.
* @param tempDir The directory where the path is stored in a config file.
* @param fileSel If a file is to be returned (or else a directory).
* @return The file containing the path to the external file.
*/
public static File promptForExternalFile(String fileID, String tempDir, boolean fileSel) {
if (externalFiles.containsKey(fileID)) {
if (externalFiles.get(fileID).exists()) {
return externalFiles.get(fileID);
}
}
// File not yet existing.
String dsf = null;
File file = new File(tempDir + "/externalFilePaths.dat");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException("Could not create file: " + file);
}
}
LinkedList<String> paths = StaticMethods.liesTextArray(file, GlobalVariables.getPrematureParameters());
for (String s : paths) {
try {
String part1 = s.split("--")[0];
String part2 = s.split("--")[1];
externalFiles.put(part1, new File(part2));
if (part1.equals(fileID)) {
dsf = part2;
}
} catch (Exception e) {}
}
if (dsf == null) {
dsf = "";
}
File dotStarterFileFile = new File(dsf);
externalFiles.put(fileID, dotStarterFileFile);
if (!dotStarterFileFile.exists()) {
if (fileSel) {
FileDialog dia = new FileDialog((JFrame) null, "Please show me the path to " + fileID + " (select the file and confirm)", FileDialog.LOAD);
dia.setFilenameFilter(new FileNamePostfixFilter(".eas"));
dia.setVisible(true);
if (dia.getDirectory() == null || dia.getFile() == null) {
GeneralDialog.message(fileID + " is not available, sorry I will not be able to perform the according actions.", fileID + " not available");
throw new RuntimeException(fileID + " not available: " + dsf);
}
dotStarterFileFile = new File(dia.getDirectory() + File.separator + dia.getFile());
} else {
JFileChooser dia = new JFileChooser(".");
dia.setCurrentDirectory(new File(System.getProperty("user.home")));
dia.setDialogTitle("Please show me the path to " + fileID + " (select the directory and confirm)");
dia.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = dia.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
dotStarterFileFile = dia.getSelectedFile();
} else {
GeneralDialog.message(fileID + " is not available, sorry I will not be able to perform the according actions.", fileID + " not available");
throw new RuntimeException(fileID + " not available: " + dsf);
}
}
externalFiles.put(fileID, dotStarterFileFile);
LinkedList<String> storeInFile = new LinkedList<>();
for (String id : externalFiles.keySet()) {
storeInFile.add(id + "--" + externalFiles.get(id));
}
StaticMethods.speichereTextAusArray(tempDir, "externalFilePaths.dat", storeInFile, GlobalVariables.getPrematureParameters());
}
return dotStarterFileFile;
}
}