$darkmode
DENOPTIM
ParametersForm.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2020 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.gui;
20
21import java.awt.Dimension;
22import java.awt.FlowLayout;
23import java.awt.Component;
24import java.awt.event.ActionEvent;
25import java.awt.event.ActionListener;
26import java.awt.event.FocusEvent;
27import java.awt.event.FocusListener;
28import java.awt.Color;
29import java.io.BufferedReader;
30import java.io.FileReader;
31import java.io.IOException;
32import java.util.HashMap;
33import java.util.Map;
34
35import javax.swing.BoxLayout;
36import javax.swing.JEditorPane;
37import javax.swing.JLabel;
38import javax.swing.JOptionPane;
39import javax.swing.JPanel;
40import javax.swing.JRadioButton;
41import javax.swing.JScrollPane;
42import javax.swing.JSeparator;
43import javax.swing.JSpinner;
44import javax.swing.JTable;
45import javax.swing.JTextArea;
46import javax.swing.JTextField;
47import javax.swing.SwingConstants;
48import javax.swing.UIManager;
49import javax.swing.event.ChangeEvent;
50import javax.swing.event.ChangeListener;
51import javax.swing.event.DocumentEvent;
52import javax.swing.event.DocumentListener;
53import javax.swing.event.TableModelEvent;
54import javax.swing.event.TableModelListener;
55
56import denoptim.constants.DENOPTIMConstants;
57import denoptim.files.FileUtils;
58
59
67public class ParametersForm extends JPanel implements IParametersForm
68{
69
73 private static final long serialVersionUID = 3787855399355076733L;
74
78 final Dimension fileLabelSize = new Dimension(250,28);
79
83 final int preferredHeight =
84 (int) (new JTextField()).getPreferredSize().getHeight();
85
89 final Dimension fileFieldSize = new Dimension(350,preferredHeight);
90
94 final Dimension strFieldSize = new Dimension(75,preferredHeight);
95
99 private final String NL = System.getProperty("line.separator");
100
104 protected boolean unsavedChanges = false;
105
110
115
120
125
131 protected Map<String,Boolean> checkedFlags = new HashMap<String,Boolean>();
132
136 protected JTextArea txtUnformattedInput = new JTextArea(5,20);
137
142 protected boolean foundCLIOnlyContent = false;
143
144 private final String UNSETUNFORMATTEDINPUTTXT =
145 "Write additional text for the input file here...";
146 private final Color UNSETUNFORMATTEDINPUTTXTCOLOR = Color.GRAY;
147 private final Color SETUNFORMATTEDINPUTTXTCOLOR = Color.BLACK;
148
149//-----------------------------------------------------------------------------
150
156 {
161 }
162
163//-----------------------------------------------------------------------------
164
175 protected String getStringIfNotEmpty(String key, JTextField field,
176 String prefix, String suffix)
177 {
178 StringBuilder sb = new StringBuilder();
179 if (!field.getText().equals(""))
180 {
181 sb.append(key).append("=");
182 sb.append(prefix).append(field.getText()).append(suffix).append(NL);
183 }
184 return sb.toString();
185 }
186
187//-----------------------------------------------------------------------------
188
199 protected String getStringIfNotEmpty(String key, JEditorPane field,
200 boolean multipleLines)
201 {
202 StringBuilder sb = new StringBuilder();
203 if (!field.getText().equals(""))
204 {
205 if (multipleLines)
206 {
207 String[] lines = field.getText().split(
208 System.getProperty("line.separator"));
209 for (int i=0; i<lines.length; i++)
210 {
211 sb.append(key).append("=").append(lines[i]).append(NL);
212 }
213 } else {
214 sb.append(key).append("=").append(field.getText()).append(NL);
215 }
216 }
217 return sb.toString();
218 }
219
220//-----------------------------------------------------------------------------
221
230 protected String getStringIfNotEmpty(String key, JTextField field)
231 {
232 StringBuilder sb = new StringBuilder();
233 if (!field.getText().equals(""))
234 {
235 sb.append(key).append("=").append(field.getText()).append(NL);
236 }
237 return sb.toString();
238 }
239
240//-----------------------------------------------------------------------------
241
250 protected String getStringForKVLine(String key, JSpinner spinner)
251 {
252 StringBuilder sb = new StringBuilder();
253 String value = spinner.getValue().toString();
254 if (!value.equals(""))
255 {
256 sb.append(key).append("=").append(value).append(NL);
257 }
258 return sb.toString();
259 }
260
261//-----------------------------------------------------------------------------
262
270 protected String getStringIfSelected(String key, JRadioButton btn)
271 {
272 StringBuilder sb = new StringBuilder();
273 if (btn.isSelected())
274 {
275 //sb.append(key).append("=").append("SELECTED_by_GUI").append(NL);
276 sb.append(key).append(NL);
277 }
278 return sb.toString();
279 }
280
281//-----------------------------------------------------------------------------
282
293 protected String getStringFromTable(String key, JTable tab)
294 {
295 return getStringFromTable(key, tab, new int[]{0}, false);
296 }
297
298//-----------------------------------------------------------------------------
299
311 protected String getStringFromTable(String key, JTable tab,
312 boolean skipHeader)
313 {
314 return getStringFromTable(key, tab, new int[]{0}, skipHeader);
315 }
316
317//-----------------------------------------------------------------------------
318
331 protected String getStringFromTable(String key, JTable tab, int[] fields,
332 boolean skipHeader)
333 {
334 return getStringFromTable(key, tab, fields, " ", skipHeader);
335 }
336
337//-----------------------------------------------------------------------------
338
352 protected String getStringFromTable(String key, JTable tab, int[] fields,
353 String sep, boolean skipHeader)
354 {
355 StringBuilder sb = new StringBuilder();
356 int firstRow = 0;
357 if (skipHeader)
358 {
359 firstRow = 1;
360 }
361 for (int i=firstRow; i<tab.getRowCount(); i++)
362 {
363 String val = "";
364 for (int j=0; j<fields.length; j++)
365 {
366 if (j==0)
367 {
368 val = tab.getValueAt(i, fields[j]).toString();
369 }
370 else
371 {
372 val = val + sep + tab.getValueAt(i, fields[j]).toString();
373 }
374 }
375 sb.append(key).append("=").append(val).append(NL);
376 }
377 return sb.toString();
378 }
379
380//-----------------------------------------------------------------------------
381
382 public void importParametersFromDenoptimParamsFile(String fileName)
383 throws Exception
384 {
385 System.err.println("WARNING: runnin empty method "
386 + "'importParametersFromDenoptimParamsFile'. "
387 + "A subclass is not overwriting it. "
388 + "Report this bug to the development team.");
389 }
390
391//-----------------------------------------------------------------------------
392
401 protected void importParametersFromDenoptimParamsFile(String fileName,
402 String keyRoot) throws Exception
403 {
404 if (keyRoot.equals("") || keyRoot == null)
405 {
406 throw new Exception("<html>Root of DENOPTIM keywords not defined."
407 + "<br>Bugus use of method "
408 + "'importParametersFromDenoptimParamsFile'!</html>");
409 }
410 String parType = keyRoot.replaceAll("-", "");
411 if (fileName.equals("") || !FileUtils.checkExists(fileName))
412 {
413 throw new Exception("<html>Source file for the " + parType
414 + " parameters is not found!<br>Please, specify another"
415 + " file name.");
416 }
417
419
420 String line;
421 BufferedReader br = null;
422 try
423 {
424 br = new BufferedReader(new FileReader(fileName));
425 while ((line = br.readLine()) != null)
426 {
427 if ((line.trim()).length() == 0)
428 {
429 continue;
430 }
431
432 if (line.startsWith("#"))
433 {
434 continue;
435 }
436
437 for (String flag : checkedFlags.keySet())
438 {
439 if (line.toUpperCase().startsWith(flag.toUpperCase()))
440 checkedFlags.put(flag,true);
441 }
442
443 if (line.toUpperCase().startsWith(keyRoot.toUpperCase()))
444 {
446 }
447 }
448 }
449 catch (IOException ioe)
450 {
451 throw new Exception("Unable to read file '" + fileName + "'", ioe);
452 }
453 finally
454 {
455 try
456 {
457 if (br != null)
458 {
459 br.close();
460 br = null;
461 }
462 }
463 catch (IOException ioe)
464 {
465 throw new Exception("Unable to close file '" + fileName + "'",
466 ioe);
467 }
468 }
469
470 //adapt visibility to imported parameters
472 }
473
474//------------------------------------------------------------------------------
475
481 {
482 }
483
484//------------------------------------------------------------------------------
485
490 protected void adaptVisibility()
491 {
492 }
493
494//-----------------------------------------------------------------------------
495
496 protected void importParameterFromLine(String line) throws Exception
497 {
498 String key = line.trim();
499 String value = "";
500 if (line.contains("="))
501 {
502 key = line.substring(0,line.indexOf("=")).trim();
503 value = line.substring(line.indexOf("=") + 1).trim();
504 }
505 importSingleParameter(key,value);
506 }
507
508//-----------------------------------------------------------------------------
509
510 @Override
511 public void importSingleParameter(String key, String value)
512 throws Exception
513 {
514 System.err.println("WARNING: running empty method "
515 + "'importSingleParameter'. "
516 + "A subclass is not overwriting it. "
517 + "Report this bug to the development team.");
518 }
519
520//-----------------------------------------------------------------------------
521
522 @Override
523 public void putParametersToString(StringBuilder sb) throws Exception
524 {
525 }
526
527//-----------------------------------------------------------------------------
528
534 @Override
535 public boolean hasUnsavedChanges()
536 {
537 return unsavedChanges;
538 }
539
540//-----------------------------------------------------------------------------
541
547 @Override
548 public void setUnsavedChanges(boolean val)
549 {
550 unsavedChanges = val;
551 }
552
553//-----------------------------------------------------------------------------
554
555 private class FieldListener implements DocumentListener
556 {
557 @Override
558 public void insertUpdate(DocumentEvent e)
559 {
560 unsavedChanges = true;
561 }
562
563 @Override
564 public void removeUpdate(DocumentEvent e)
565 {
566 unsavedChanges = true;
567 }
568
569 @Override
570 public void changedUpdate(DocumentEvent e)
571 {
572 unsavedChanges = true;
573 }
574 }
575
576//-----------------------------------------------------------------------------
577
578 private class RdbFieldChange implements ChangeListener
579 {
580 @Override
581 public void stateChanged(ChangeEvent e)
582 {
583 unsavedChanges = true;
584 }
585 }
586
587//-----------------------------------------------------------------------------
588
589 private class TabFieldChange implements TableModelListener
590 {
591 @Override
592 public void tableChanged(TableModelEvent e)
593 {
594 unsavedChanges = true;
595 }
596 }
597
598//-----------------------------------------------------------------------------
599
600 private class CmbFieldChange implements ActionListener
601 {
602 @Override
603 public void actionPerformed(ActionEvent e)
604 {
605 unsavedChanges = true;
606 }
607 }
608
609//-----------------------------------------------------------------------------
610
618 public void showUnknownKeyWarning(Component parent, String paramType)
619 {
621 {
622 JOptionPane.showMessageDialog(parent,
623 String.format("<html><body width='%1s'>"
624 + "Found text that is either not recognized "
625 + " as " + paramType + " parameters "
626 + "or pertains settings that cannot yet be "
627 + "controlled from the GUI. "
628 + "You can edit/delete this content in the "
629 + "parameter editor located at the bottom of the "
630 + "parameter's form. <br>"
631 + "Content of the unformatted content:"
632 + "</body></html>", 400)
634 + txtUnformattedInput.getText(),
635 "WARNING",
636 JOptionPane.WARNING_MESSAGE,
637 UIManager.getIcon("OptionPane.errorIcon"));
638 }
639 }
640
641//------------------------------------------------------------------------------
642
643 protected void addToUnformattedTxt(String key, String value)
644 {
645 foundCLIOnlyContent = true;
646 if (txtUnformattedInput.getText().equals(UNSETUNFORMATTEDINPUTTXT))
647 {
648 txtUnformattedInput.setText(key + "=" + value);
649 } else {
650 txtUnformattedInput.append(DENOPTIMConstants.EOL + key + "=" + value);
651 }
653 }
654
655//------------------------------------------------------------------------------
656
658 {
659 JPanel blockUnformatted = new JPanel();
660 blockUnformatted.setLayout(new BoxLayout(blockUnformatted,
661 SwingConstants.VERTICAL));
662 blockUnformatted.add(new JSeparator());
663 String toolTip = String.format(
664 "<html><body width='%1s'>Here you can find/write any "
665 + "further text lines that can be written/found in the "
666 + "parameter's file. Such text may contain comments (i.e., "
667 + "start with '#') and any keyword that is not controllable by "
668 + "the GUI.</body></html>", 400);
669 blockUnformatted.setToolTipText(toolTip);
670 JPanel lineHeader = new JPanel(new FlowLayout(FlowLayout.LEFT));
671 JLabel lbl = new JLabel(
672 "Additional input file content not controlled by GUI",
673 SwingConstants.LEFT);
674 lineHeader.add(lbl);
675 blockUnformatted.add(lineHeader);
676 txtUnformattedInput.setToolTipText(toolTip);
679 txtUnformattedInput.addFocusListener(new FocusListener() {
680
681 @Override
682 public void focusGained(FocusEvent e)
683 {
685 }
686
687 @Override
688 public void focusLost(FocusEvent e)
689 {
691 }
692
693 });
694 JScrollPane scroller = new JScrollPane(txtUnformattedInput);
695 blockUnformatted.add(scroller);
696
697 return blockUnformatted;
698 }
699
700//-----------------------------------------------------------------------------
701
703 {
704 return txtUnformattedInput.getText();
705 }
706
707//-----------------------------------------------------------------------------
708
709 private void showPromptIfEmpty()
710 {
711 String txt = txtUnformattedInput.getText();
712 if (txt.equals(UNSETUNFORMATTEDINPUTTXT))
713 {
714 txtUnformattedInput.setText("");
716 } else if (txt.isBlank()) {
719 } else {
721 }
722 }
723
724//-----------------------------------------------------------------------------
725
726 protected void clearUnformattedTxtArea()
727 {
730 }
731
732//-----------------------------------------------------------------------------
733
734}
General set of constants used in DENOPTIM.
static final String EOL
new line character
static boolean checkExists(String fileName)
Definition: FileUtils.java:241
General structure of a form for collecting input parameters of various nature.
String getStringFromTable(String key, JTable tab, int[] fields, String sep, boolean skipHeader)
Produced an overall string including one or more KEY:VALUE strings taken from a table.
CmbFieldChange cmbFieldChange
Listener for changes in combo box-bound parameters.
final String NL
The newline character.
void importParameterFromLine(String line)
final Dimension strFieldSize
Default sizes for short pathname fields (i.e., string or number)
void setUnsavedChanges(boolean val)
Set the status of the flag signaling unsaved changes.
boolean foundCLIOnlyContent
Flag recording we have imported text containing a line that is not interpreted as a GUI-controllable ...
String getStringIfNotEmpty(String key, JTextField field)
Produced the KEY:VALUE string for a general text field.
boolean hasUnsavedChanges()
Returns the flag signaling unsaved changes.
void adaptVisibility()
Overwritten by subclasses.
String getStringIfNotEmpty(String key, JEditorPane field, boolean multipleLines)
Produced the KEY:VALUE string for a general text editor pane The text can include numbers,...
FieldListener fieldListener
Listener for changes in parameters of this form.
TabFieldChange tabFieldChange
Listener for changes in table-bound parameters.
String getStringForKVLine(String key, JSpinner spinner)
Produced the KEY:VALUE string for a general spinner.
final Dimension fileLabelSize
Default sizes for file pathname labels.
final int preferredHeight
Default text field height.
String getStringFromTable(String key, JTable tab)
Produced an overall string including one or more KEY:VALUE strings taken from a table.
String getStringFromTable(String key, JTable tab, boolean skipHeader)
Produced an overall string including one or more KEY:VALUE strings taken from a table.
JTextArea txtUnformattedInput
Storage of unformatted text for input files.
Map< String, Boolean > checkedFlags
Map of keyword to search for when reading a parameters file.
void importParametersFromDenoptimParamsFile(String fileName)
String getStringIfSelected(String key, JRadioButton btn)
Produced the KEY:VALUE string for a on/off button.
void addToUnformattedTxt(String key, String value)
void showUnknownKeyWarning(Component parent, String paramType)
Shown a warning dialog that informs the user about having found text that is not present in the Param...
boolean unsavedChanges
Flag notifying that some data was not saved.
ParametersForm()
Empty constructor.
void importSingleParameter(String key, String value)
String getStringFromTable(String key, JTable tab, int[] fields, boolean skipHeader)
Produced an overall string including one or more KEY:VALUE strings taken from a table.
void importParametersFromDenoptimParamsFile(String fileName, String keyRoot)
Reads in the parameters from a text file collecting DENOPTIM parameters in the form of KEY=VALUE li...
final Dimension fileFieldSize
Default sizes for file pathname fields.
String getStringIfNotEmpty(String key, JTextField field, String prefix, String suffix)
Produced the KEY:VALUE string for a general text field.
RdbFieldChange rdbFieldChange
Listener for changes in radio button-bound parameters.
void preliminatyTasksUponImportingParams()
Overwritten by subclasses.
void putParametersToString(StringBuilder sb)
static final long serialVersionUID
Version.
Interface for parameter forms.