22 package org.matsim.run.gui;
24 import com.google.common.base.Preconditions;
33 import javax.swing.GroupLayout.Alignment;
34 import javax.swing.LayoutStyle.ComponentPlacement;
37 import java.io.IOException;
38 import java.util.LinkedHashMap;
40 import java.util.concurrent.Future;
41 import java.util.concurrent.FutureTask;
42 import java.util.concurrent.RunnableFuture;
47 public class Gui extends JFrame {
52 "Filepaths must either be absolute or relative to the location of the config file.");
56 private static final JLabel
lblMemory =
new JLabel(
"Memory:");
57 private static final JLabel
lblMb =
new JLabel(
"MB");
75 Map<String, JButton> preprocessButtons =
new LinkedHashMap<>();
76 Map<String, JButton> postprocessButtons =
new LinkedHashMap<>();
102 private Gui(
final String title,
final Class<?> mainClass) {
104 this.mainClass = mainClass.getCanonicalName();
105 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
109 this.lastUsedDirectory =
new File(
".");
111 txtConfigfilename =
new JTextField();
112 txtConfigfilename.setText(
"");
113 txtConfigfilename.setColumns(10);
115 btnStartMatsim =
new JButton(
"Start MATSim");
116 btnStartMatsim.setEnabled(
false);
118 for (JButton button : preprocessButtons.values()) {
119 button.setEnabled(
false);
121 for (JButton button : postprocessButtons.values()) {
122 button.setEnabled(
false);
125 JButton btnChoose =
new JButton(
"Choose");
126 btnChoose.addActionListener(e -> {
127 JFileChooser chooser =
new JFileChooser();
128 chooser.setCurrentDirectory(lastUsedDirectory);
129 int result = chooser.showOpenDialog(null);
130 if (result == JFileChooser.APPROVE_OPTION) {
131 File f = chooser.getSelectedFile();
132 lastUsedDirectory = f.getParentFile();
134 if (editor != null) {
135 editor.closeEditor();
141 this.btnEdit =
new JButton(
"Edit…");
142 this.btnEdit.setEnabled(
false);
143 this.btnEdit.addActionListener(e -> {
144 if (editor == null) {
145 this.editor =
new ConfigEditor(
this, configFile,
Gui.this::loadConfigFile);
151 txtMatsimversion =
new JTextField();
152 txtMatsimversion.setEditable(
false);
154 txtMatsimversion.setColumns(10);
156 txtRam =
new JTextField();
157 txtRam.setText(
"1024");
158 txtRam.setColumns(10);
160 String javaVersion = System.getProperty(
"java.version")
162 + System.getProperty(
"java.vm.vendor")
164 + System.getProperty(
"java.vm.info")
166 + System.getProperty(
"sun.arch.data.model")
169 txtJvmversion =
new JTextField();
170 txtJvmversion.setEditable(
false);
171 txtJvmversion.setText(javaVersion);
172 txtJvmversion.setColumns(10);
175 if (System.getProperty(
"os.name").startsWith(
"Win")) {
176 jvmLocation = System.getProperties().getProperty(
"java.home")
182 jvmLocation = System.getProperties().getProperty(
"java.home")
189 txtJvmlocation =
new JTextField();
190 txtJvmlocation.setEditable(
false);
191 txtJvmlocation.setText(jvmLocation);
192 txtJvmlocation.setColumns(10);
194 txtOutput =
new JTextField();
195 txtOutput.setEditable(
false);
196 txtOutput.setText(
"");
197 txtOutput.setColumns(10);
199 progressBar =
new JProgressBar();
200 progressBar.setEnabled(
false);
201 progressBar.setIndeterminate(
true);
202 progressBar.setVisible(
false);
204 btnStartMatsim.addActionListener(e -> {
205 if (exeRunner == null) {
212 JButton btnOpen =
new JButton(
"Open");
213 btnOpen.addActionListener(e -> {
214 if (!txtOutput.getText().isEmpty()) {
216 File f =
new File(txtOutput.getText());
217 Desktop.getDesktop().open(f);
218 }
catch (IOException ex) {
219 ex.printStackTrace();
224 JButton btnDelete =
new JButton(
"Delete");
225 btnDelete.addActionListener(e -> {
226 if (!txtOutput.getText().isEmpty()) {
227 int i = JOptionPane.showOptionDialog(
Gui.this,
228 "Do you really want to delete the output directory? This action cannot be undone.",
229 "Delete Output Directory", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null,
230 new String[] {
"Cancel",
"Delete" },
"Cancel");
235 ex.printStackTrace();
241 JTabbedPane tabbedPane =
new JTabbedPane(JTabbedPane.TOP);
244 GroupLayout groupLayout =
new GroupLayout(getContentPane());
246 final GroupLayout.SequentialGroup prebuttonsSequentialGroup = groupLayout.createSequentialGroup();
247 final GroupLayout.ParallelGroup prebuttonsParallelGroup = groupLayout.createParallelGroup();
248 for (JButton button : preprocessButtons.values()) {
249 prebuttonsSequentialGroup.addComponent(button);
250 prebuttonsParallelGroup.addComponent(button);
253 final GroupLayout.SequentialGroup postbuttonsSequentialGroup = groupLayout.createSequentialGroup();
254 final GroupLayout.ParallelGroup postbuttonsParallelGroup = groupLayout.createParallelGroup();
255 for (JButton button : postprocessButtons.values()) {
256 postbuttonsSequentialGroup.addComponent(button);
257 postbuttonsParallelGroup.addComponent(button);
260 groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
261 .addGroup(Alignment.LEADING, groupLayout.createSequentialGroup()
263 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
265 .addComponent(tabbedPane, GroupLayout.DEFAULT_SIZE, 729, Short.MAX_VALUE)
266 .addComponent(lblFilepaths)
267 .addGroup(prebuttonsSequentialGroup)
268 .addGroup(postbuttonsSequentialGroup)
269 .addGroup(groupLayout.createSequentialGroup()
270 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
272 .addComponent(lblYouAreUsingMATSimVersion)
273 .addComponent(lblYouAreUsingJavaVersion)
274 .addComponent(lblJavaLocation)
275 .addComponent(lblConfigurationFile)
276 .addComponent(lblOutputDirectory)
277 .addComponent(lblMemory)
278 .addComponent(btnStartMatsim))
280 .addPreferredGap(ComponentPlacement.RELATED)
281 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
283 .addGroup(groupLayout.createSequentialGroup()
284 .addComponent(txtRam, GroupLayout.PREFERRED_SIZE, 69,
285 GroupLayout.PREFERRED_SIZE)
286 .addPreferredGap(ComponentPlacement.RELATED)
287 .addComponent(lblMb))
288 .addComponent(txtMatsimversion, GroupLayout.DEFAULT_SIZE, 285,
290 .addComponent(txtJvmversion, GroupLayout.DEFAULT_SIZE, 285,
292 .addComponent(txtJvmlocation, GroupLayout.DEFAULT_SIZE, 285,
294 .addGroup(groupLayout.createSequentialGroup()
295 .addComponent(txtConfigfilename, GroupLayout.DEFAULT_SIZE, 188,
297 .addPreferredGap(ComponentPlacement.RELATED)
298 .addComponent(btnChoose)
299 .addPreferredGap(ComponentPlacement.RELATED)
300 .addComponent(btnEdit))
301 .addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 285,
303 .addGroup(groupLayout.createSequentialGroup()
304 .addComponent(txtOutput, GroupLayout.DEFAULT_SIZE, 112,
306 .addPreferredGap(ComponentPlacement.RELATED)
307 .addComponent(btnOpen)
308 .addPreferredGap(ComponentPlacement.RELATED)
309 .addComponent(btnDelete)))))
310 .addContainerGap()));
311 groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING)
312 .addGroup(groupLayout.createSequentialGroup()
314 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
315 .addComponent(lblYouAreUsingMATSimVersion)
316 .addComponent(txtMatsimversion, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
317 GroupLayout.PREFERRED_SIZE))
318 .addPreferredGap(ComponentPlacement.RELATED)
319 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
320 .addComponent(lblYouAreUsingJavaVersion)
321 .addComponent(txtJvmversion, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
322 GroupLayout.PREFERRED_SIZE))
323 .addPreferredGap(ComponentPlacement.RELATED)
324 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
325 .addComponent(lblJavaLocation)
326 .addComponent(txtJvmlocation, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
327 GroupLayout.PREFERRED_SIZE))
328 .addPreferredGap(ComponentPlacement.RELATED)
329 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
330 .addComponent(lblConfigurationFile)
331 .addComponent(txtConfigfilename, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
332 GroupLayout.PREFERRED_SIZE)
333 .addComponent(btnChoose)
334 .addComponent(btnEdit))
335 .addPreferredGap(ComponentPlacement.RELATED)
336 .addComponent(lblFilepaths)
337 .addPreferredGap(ComponentPlacement.RELATED)
338 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
339 .addComponent(lblOutputDirectory)
340 .addComponent(txtOutput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
341 GroupLayout.PREFERRED_SIZE)
342 .addComponent(btnDelete)
343 .addComponent(btnOpen))
344 .addPreferredGap(ComponentPlacement.RELATED)
345 .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE)
346 .addComponent(lblMemory)
347 .addComponent(txtRam, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
348 GroupLayout.PREFERRED_SIZE)
349 .addComponent(lblMb))
350 .addPreferredGap(ComponentPlacement.UNRELATED)
351 .addGroup(prebuttonsParallelGroup)
352 .addPreferredGap(ComponentPlacement.UNRELATED)
353 .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
354 .addComponent(btnStartMatsim)
355 .addComponent(progressBar, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
356 GroupLayout.PREFERRED_SIZE))
357 .addPreferredGap(ComponentPlacement.UNRELATED)
358 .addGroup(postbuttonsParallelGroup)
359 .addPreferredGap(ComponentPlacement.RELATED)
360 .addComponent(tabbedPane, GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE)
361 .addContainerGap()));
363 textStdOut =
new JTextArea();
364 textStdOut.setWrapStyleWord(
true);
365 textStdOut.setTabSize(4);
366 textStdOut.setEditable(
false);
367 scrollPane =
new JScrollPane(textStdOut);
368 tabbedPane.addTab(
"Output", null, scrollPane, null);
370 JScrollPane scrollPane_1 =
new JScrollPane();
371 tabbedPane.addTab(
"Warnings & Errors", null, scrollPane_1, null);
373 textErrOut =
new JTextArea();
374 textErrOut.setWrapStyleWord(
true);
375 textErrOut.setTabSize(4);
376 textErrOut.setEditable(
false);
377 scrollPane_1.setViewportView(textErrOut);
379 getContentPane().setLayout(groupLayout);
381 menuBar =
new JMenuBar();
382 setJMenuBar(menuBar);
384 mnTools =
new JMenu(
"Tools");
385 menuBar.add(mnTools);
387 mntmCompressFile =
new JMenuItem(
"Compress File…");
388 mnTools.add(mntmCompressFile);
389 mntmCompressFile.addActionListener(e -> GUnZipper.gzipFile());
391 mntmUncompressFile =
new JMenuItem(
"Uncompress File…");
392 mnTools.add(mntmUncompressFile);
393 mntmUncompressFile.addActionListener(e -> GUnZipper.gunzipFile());
395 mnTools.addSeparator();
397 mntmCreateDefaultConfig =
new JMenuItem(
"Create Default config.xml…");
398 mnTools.add(mntmCreateDefaultConfig);
399 mntmCreateDefaultConfig.addActionListener(e -> {
400 SaveFileSaver chooser =
new SaveFileSaver();
401 chooser.setSelectedFile(
new File(
"defaultConfig.xml"));
402 int saveResult = chooser.showSaveDialog(null);
403 if (saveResult == JFileChooser.APPROVE_OPTION) {
404 File destFile = chooser.getSelectedFile();
410 mntmCreateSamplePopulation =
new JMenuItem(
"Create Sample Population…");
411 mnTools.add(mntmCreateSamplePopulation);
412 mntmCreateSamplePopulation.addActionListener(e -> {
413 if (popSampler == null) {
414 popSampler =
new PopulationSampler(
this);
417 popSampler.setVisible(
true);
420 JMenuItem mntmTransitValidator =
new JMenuItem(
"Validate TransitSchedule…");
421 this.mnTools.add(mntmTransitValidator);
422 mntmTransitValidator.addActionListener(e -> {
423 if (this.transitValidator == null) {
426 String configFilename = this.txtConfigfilename.getText();
427 if (!configFilename.isEmpty()) {
431 this.transitValidator.
loadFromConfig(config,
new File(configFilename).getParentFile());
435 this.transitValidator.setVisible(
true);
440 progressBar.setVisible(
true);
441 progressBar.setEnabled(
true);
442 this.btnStartMatsim.setEnabled(
false);
444 textStdOut.setText(
"");
445 textErrOut.setText(
"");
447 String cwd = workingDirectory == null ?
new File(txtConfigfilename.getText()).getParent() : workingDirectory.getAbsolutePath();
450 String classpath = System.getProperty(
"java.class.path");
451 String[] cpParts = classpath.split(File.pathSeparator);
452 StringBuilder absoluteClasspath =
new StringBuilder();
453 for (String cpPart : cpParts) {
454 if (absoluteClasspath.length() > 0) {
455 absoluteClasspath.append(File.pathSeparatorChar);
457 absoluteClasspath.append(
new File(cpPart).getAbsolutePath());
459 String[] cmdArgs =
new String[] { txtJvmlocation.getText(),
460 "-cp", absoluteClasspath.toString(),
461 "-Xmx" + txtRam.getText() +
"m",
462 "--add-exports",
"java.base/java.lang=ALL-UNNAMED",
463 "--add-exports",
"java.desktop/sun.awt=ALL-UNNAMED",
464 "--add-exports",
"java.desktop/sun.java2d=ALL-UNNAMED",
465 mainClass, txtConfigfilename.getText() };
467 exeRunner = ExeRunner.run(cmdArgs, textStdOut, textErrOut, cwd);
468 int exitcode = exeRunner.waitForFinish();
471 SwingUtilities.invokeLater(() -> {
472 progressBar.setVisible(
false);
473 btnStartMatsim.setText(
"Start MATSim");
474 btnStartMatsim.setEnabled(
true);
476 textStdOut.append(
"\n");
477 textStdOut.append(
"The simulation did not run properly. Error/Exit code: " + exitcode);
478 textStdOut.setCaretPosition(textStdOut.getDocument().getLength());
479 textErrOut.append(
"\n");
480 textErrOut.append(
"The simulation did not run properly. Error/Exit code: " + exitcode);
481 textErrOut.setCaretPosition(textErrOut.getDocument().getLength());
486 throw new RuntimeException(
"There was a problem running MATSim. exit code: " + exitcode);
491 btnStartMatsim.setText(
"Stop MATSim");
492 btnStartMatsim.setEnabled(
true);
497 String configFilename = configFile.getAbsolutePath();
503 textStdOut.setText(
"");
504 textStdOut.append(
"The configuration file could not be loaded. Error message:\n");
505 textStdOut.append(e.getMessage());
506 textErrOut.setText(
"");
507 textErrOut.append(
"The configuration file could not be loaded. Error message:\n");
508 textErrOut.append(e.getMessage());
511 txtConfigfilename.setText(configFilename);
513 File par = configFile.getParentFile();
516 txtOutput.setText(outputDir.getCanonicalPath());
517 }
catch (IOException e1) {
518 txtOutput.setText(outputDir.getAbsolutePath());
521 btnStartMatsim.setEnabled(
true);
522 btnEdit.setEnabled(
true);
523 for (JButton button : preprocessButtons.values()) {
524 button.setEnabled(
true);
526 for (JButton button : postprocessButtons.values()) {
527 button.setEnabled(
true);
533 if (runner != null) {
534 runner.killProcess();
539 progressBar.setVisible(
false);
540 btnStartMatsim.setText(
"Start MATSim");
541 btnStartMatsim.setEnabled(
true);
543 textStdOut.append(
"\n");
544 textStdOut.append(
"The simulation was stopped forcefully.");
545 textStdOut.setCaretPosition(textStdOut.getDocument().getLength());
546 textErrOut.append(
"\n");
547 textErrOut.append(
"The simulation was stopped forcefully.");
548 textErrOut.setCaretPosition(textErrOut.getDocument().getLength());
552 public static Future<Gui>
show(
final String title,
final Class<?> mainClass) {
553 return show(title, mainClass, null);
559 public static Future<Gui>
show(
final String title,
final Class<?> mainClass, File configFile) {
560 System.setProperty(
"apple.laf.useScreenMenuBar",
"true");
562 RunnableFuture<Gui> rf =
new FutureTask<>(() -> {
563 Gui gui =
new Gui(title, mainClass);
566 gui.setLocationByPlatform(
true);
567 gui.setVisible(
true);
568 if (configFile != null && configFile.exists()) {
575 SwingUtilities.invokeLater(rf);
579 public static void main(String[] args) {
580 Preconditions.checkArgument(args.length < 2);
581 Gui.
show(
"MATSim",
RunMatsim.class, args.length == 1 ?
new File(args[0]) : null);
585 this.workingDirectory = cwd;
static final JLabel lblConfigurationFile
static void deleteDirectoryRecursively(Path path)
static final JLabel lblFilepaths
static final JLabel lblOutputDirectory
static Config loadConfig(final String filename, ConfigGroup... customModules)
final void write(final String filename)
void loadFromConfig(Config config, File configDirectory)
void setWorkingDirectory(File cwd)
JMenuItem mntmCreateDefaultConfig
JTextField txtConfigfilename
void loadConfigFile(final File configFile)
PopulationSampler popSampler
JMenuItem mntmCreateSamplePopulation
static void main(String[] args)
JMenuItem mntmUncompressFile
volatile ExeRunner exeRunner
ScheduleValidatorWindow transitValidator
static final long serialVersionUID
static final JLabel lblMemory
static Future< Gui > show(final String title, final Class<?> mainClass)
static final String getBuildInfoString()
static final JLabel lblJavaLocation
static final JLabel lblYouAreUsingMATSimVersion
JTextField txtMatsimversion
Gui(final String title, final Class<?> mainClass)
JMenuItem mntmCompressFile
static final JLabel lblYouAreUsingJavaVersion
JTextField txtJvmlocation
final ControllerConfigGroup controller()
static final JLabel lblMb
String getOutputDirectory()
static Config createConfig(final String context)
static Future< Gui > show(final String title, final Class<?> mainClass, File configFile)