482 lines
20 KiB
Java
482 lines
20 KiB
Java
/*
|
|
* Copyright (C) 2014 Alfons Wirtz
|
|
* website www.freerouting.net
|
|
*
|
|
* Copyright (C) 2017 Michael Hoffer <info@michaelhoffer.de>
|
|
* Website www.freerouting.mihosoft.eu
|
|
*
|
|
* 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 3 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 at <http://www.gnu.org/licenses/>
|
|
* for more details.
|
|
*
|
|
* MainApplication.java
|
|
*
|
|
* Created on 19. Oktober 2002, 17:58
|
|
*
|
|
*/
|
|
package eu.mihosoft.freerouting.gui;
|
|
|
|
import eu.mihosoft.freerouting.board.TestLevel;
|
|
import eu.mihosoft.freerouting.interactive.InteractiveActionThread;
|
|
import eu.mihosoft.freerouting.interactive.ThreadActionListener;
|
|
import eu.mihosoft.freerouting.logger.FRLogger;
|
|
|
|
import javax.swing.UIManager;
|
|
import javax.swing.UnsupportedLookAndFeelException;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
|
|
/**
|
|
*
|
|
* Main application for creating frames with new or existing board designs.
|
|
*
|
|
* @author Alfons Wirtz
|
|
*/
|
|
public class MainApplication extends javax.swing.JFrame
|
|
{
|
|
/**
|
|
* Main function of the Application
|
|
* @param args
|
|
*/
|
|
public static void main(String args[])
|
|
{
|
|
FRLogger.traceEntry("MainApplication.main()");
|
|
|
|
try {
|
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
} catch (ClassNotFoundException ex) {
|
|
FRLogger.error(ex.getLocalizedMessage(), ex);
|
|
} catch (InstantiationException ex) {
|
|
FRLogger.error(ex.getLocalizedMessage(), ex);
|
|
} catch (IllegalAccessException ex) {
|
|
FRLogger.error(ex.getLocalizedMessage(), ex);
|
|
} catch (UnsupportedLookAndFeelException ex) {
|
|
FRLogger.error(ex.getLocalizedMessage(), ex);
|
|
}
|
|
|
|
FRLogger.info("Freerouting application is started.");
|
|
|
|
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
|
|
StartupOptions startupOptions = StartupOptions.parse(args);
|
|
|
|
if (startupOptions.single_design_option)
|
|
{
|
|
java.util.ResourceBundle resources =
|
|
java.util.ResourceBundle.getBundle("eu.mihosoft.freerouting.gui.MainApplication", startupOptions.current_locale);
|
|
BoardFrame.Option board_option;
|
|
if (startupOptions.session_file_option)
|
|
{
|
|
board_option = BoardFrame.Option.SESSION_FILE;
|
|
}
|
|
else
|
|
{
|
|
board_option = BoardFrame.Option.SINGLE_FRAME;
|
|
}
|
|
|
|
FRLogger.info("Opening '"+startupOptions.design_input_filename+"'...");
|
|
DesignFile design_file = DesignFile.get_instance(startupOptions.design_input_filename, false);
|
|
if (design_file == null)
|
|
{
|
|
FRLogger.warn(resources.getString("message_6") + " " + startupOptions.design_input_filename + " " + resources.getString("message_7"));
|
|
return;
|
|
}
|
|
String message = resources.getString("loading_design") + " "
|
|
+ startupOptions.design_input_filename;
|
|
WindowMessage welcome_window = WindowMessage.show(message);
|
|
final BoardFrame new_frame =
|
|
create_board_frame(design_file, null, board_option,
|
|
startupOptions.test_version_option,
|
|
startupOptions.current_locale,
|
|
startupOptions.design_rules_filename);
|
|
welcome_window.dispose();
|
|
if (new_frame == null)
|
|
{
|
|
FRLogger.warn("Couldn't create window frame");
|
|
System.exit(1);
|
|
return;
|
|
}
|
|
|
|
new_frame.board_panel.board_handling.settings.autoroute_settings.set_stop_pass_no(new_frame.board_panel.board_handling.settings.autoroute_settings.get_start_pass_no() + startupOptions.max_passes - 1);
|
|
if (startupOptions.max_passes < 99999)
|
|
{
|
|
InteractiveActionThread thread = new_frame.board_panel.board_handling.start_batch_autorouter();
|
|
|
|
thread.addListener(new ThreadActionListener() {
|
|
@Override
|
|
public void autorouterStarted() {
|
|
}
|
|
|
|
@Override
|
|
public void autorouterAborted() {
|
|
ExportBoardToFile(startupOptions.design_output_filename);
|
|
}
|
|
|
|
@Override
|
|
public void autorouterFinished() {
|
|
ExportBoardToFile(startupOptions.design_output_filename);
|
|
}
|
|
|
|
private void ExportBoardToFile(String filename) {
|
|
if ((filename != null)
|
|
&& ((filename.toLowerCase().endsWith(".dsn"))
|
|
|| (filename.toLowerCase().endsWith(".ses"))
|
|
|| (filename.toLowerCase().endsWith(".scr")))) {
|
|
|
|
FRLogger.info("Saving '" + filename + "'...");
|
|
try {
|
|
String filename_only = new File(filename).getName();
|
|
String design_name = filename_only.substring(0, filename_only.length() - 4);
|
|
|
|
java.io.OutputStream output_stream = new java.io.FileOutputStream(filename);
|
|
|
|
if (filename.toLowerCase().endsWith(".dsn")) {
|
|
new_frame.board_panel.board_handling.export_to_dsn_file(output_stream, design_name, false);
|
|
} else if (filename.toLowerCase().endsWith(".ses")) {
|
|
new_frame.board_panel.board_handling.export_specctra_session_file(design_name, output_stream);
|
|
} else if (filename.toLowerCase().endsWith(".scr")) {
|
|
java.io.ByteArrayOutputStream session_output_stream = new ByteArrayOutputStream();
|
|
new_frame.board_panel.board_handling.export_specctra_session_file(filename, session_output_stream);
|
|
java.io.InputStream input_stream = new ByteArrayInputStream(session_output_stream.toByteArray());
|
|
new_frame.board_panel.board_handling.export_eagle_session_file(input_stream, output_stream);
|
|
}
|
|
|
|
Runtime.getRuntime().exit(0);
|
|
} catch (Exception e) {
|
|
FRLogger.error("Couldn't export board to file", e);
|
|
}
|
|
} else {
|
|
FRLogger.warn("Couldn't export board to '" + filename + "'.");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
new_frame.addWindowListener(new java.awt.event.WindowAdapter()
|
|
{
|
|
@Override
|
|
public void windowClosed(java.awt.event.WindowEvent evt)
|
|
{
|
|
Runtime.getRuntime().exit(0);
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
new MainApplication(startupOptions).setVisible(true);
|
|
}
|
|
|
|
FRLogger.traceExit("MainApplication.main()");
|
|
}
|
|
|
|
/**
|
|
* Creates new form MainApplication
|
|
* It takes the directory of the board designs as optional argument.
|
|
* @param startupOptions
|
|
*/
|
|
public MainApplication(StartupOptions startupOptions)
|
|
{
|
|
this.design_dir_name = startupOptions.getDesignDir();
|
|
this.is_test_version = startupOptions.isTestVersion();
|
|
this.is_webstart = startupOptions.getWebstartOption();
|
|
this.locale = startupOptions.getCurrentLocale();
|
|
this.resources =
|
|
java.util.ResourceBundle.getBundle("eu.mihosoft.freerouting.gui.MainApplication", locale);
|
|
main_panel = new javax.swing.JPanel();
|
|
getContentPane().add(main_panel);
|
|
java.awt.GridBagLayout gridbag = new java.awt.GridBagLayout();
|
|
main_panel.setLayout(gridbag);
|
|
|
|
java.awt.GridBagConstraints gridbag_constraints = new java.awt.GridBagConstraints();
|
|
gridbag_constraints.insets = new java.awt.Insets(10, 10, 10, 10);
|
|
gridbag_constraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
|
|
|
|
demonstration_button = new javax.swing.JButton();
|
|
sample_board_button = new javax.swing.JButton();
|
|
open_board_button = new javax.swing.JButton();
|
|
restore_defaults_button = new javax.swing.JButton();
|
|
message_field = new javax.swing.JTextField();
|
|
message_field.setText("Neither '-de <design file>' nor '-di <design directory>' are specified.");
|
|
this.window_net_demonstrations = new WindowNetDemonstrations(locale);
|
|
java.awt.Point location = getLocation();
|
|
this.window_net_demonstrations.setLocation((int) location.getX() + 50, (int) location.getY() + 50);
|
|
this.window_net_sample_designs = new WindowNetSampleDesigns(locale);
|
|
this.window_net_sample_designs.setLocation((int) location.getX() + 90, (int) location.getY() + 90);
|
|
|
|
setTitle(resources.getString("title") + " " + VERSION_NUMBER_STRING);
|
|
boolean add_buttons = true;
|
|
|
|
if (startupOptions.getWebstartOption())
|
|
{
|
|
|
|
if (add_buttons)
|
|
{
|
|
demonstration_button.setText(resources.getString("router_demonstrations"));
|
|
demonstration_button.setToolTipText(resources.getString("router_demonstrations_tooltip"));
|
|
demonstration_button.addActionListener((java.awt.event.ActionEvent evt) -> {
|
|
window_net_demonstrations.setVisible(true);
|
|
});
|
|
|
|
gridbag.setConstraints(demonstration_button, gridbag_constraints);
|
|
main_panel.add(demonstration_button, gridbag_constraints);
|
|
|
|
sample_board_button.setText(resources.getString("sample_designs"));
|
|
sample_board_button.setToolTipText(resources.getString("sample_designs_tooltip"));
|
|
sample_board_button.addActionListener((java.awt.event.ActionEvent evt) -> {
|
|
window_net_sample_designs.setVisible(true);
|
|
});
|
|
|
|
gridbag.setConstraints(sample_board_button, gridbag_constraints);
|
|
main_panel.add(sample_board_button, gridbag_constraints);
|
|
}
|
|
}
|
|
|
|
open_board_button.setText(resources.getString("open_own_design"));
|
|
open_board_button.setToolTipText(resources.getString("open_own_design_tooltip"));
|
|
open_board_button.addActionListener((java.awt.event.ActionEvent evt) -> {
|
|
open_board_design_action(evt);
|
|
});
|
|
|
|
gridbag.setConstraints(open_board_button, gridbag_constraints);
|
|
if (add_buttons)
|
|
{
|
|
main_panel.add(open_board_button, gridbag_constraints);
|
|
}
|
|
|
|
if (startupOptions.getWebstartOption() && add_buttons)
|
|
{
|
|
restore_defaults_button.setText(resources.getString("restore_defaults"));
|
|
restore_defaults_button.setToolTipText(resources.getString("restore_defaults_tooltip"));
|
|
restore_defaults_button.addActionListener((java.awt.event.ActionEvent evt) -> {
|
|
if (is_webstart)
|
|
{
|
|
restore_defaults_action(evt);
|
|
}
|
|
});
|
|
|
|
gridbag.setConstraints(restore_defaults_button, gridbag_constraints);
|
|
main_panel.add(restore_defaults_button, gridbag_constraints);
|
|
}
|
|
|
|
message_field.setPreferredSize(new java.awt.Dimension(400, 20));
|
|
message_field.setRequestFocusEnabled(false);
|
|
gridbag.setConstraints(message_field, gridbag_constraints);
|
|
main_panel.add(message_field, gridbag_constraints);
|
|
|
|
this.addWindowListener(new WindowStateListener());
|
|
pack();
|
|
setSize(450,250);
|
|
}
|
|
|
|
/** opens a board design from a binary file or a specctra dsn file. */
|
|
private void open_board_design_action(java.awt.event.ActionEvent evt)
|
|
{
|
|
DesignFile design_file = DesignFile.open_dialog(this.design_dir_name);
|
|
|
|
if (design_file == null)
|
|
{
|
|
message_field.setText(resources.getString("message_3"));
|
|
return;
|
|
}
|
|
|
|
FRLogger.info("Opening '"+design_file.get_name()+"'...");
|
|
|
|
BoardFrame.Option option;
|
|
if (this.is_webstart)
|
|
{
|
|
option = BoardFrame.Option.WEBSTART;
|
|
}
|
|
else
|
|
{
|
|
option = BoardFrame.Option.FROM_START_MENU;
|
|
}
|
|
String message = resources.getString("loading_design") + " " + design_file.get_name();
|
|
message_field.setText(message);
|
|
WindowMessage welcome_window = WindowMessage.show(message);
|
|
welcome_window.setTitle(message);
|
|
BoardFrame new_frame =
|
|
create_board_frame(design_file, message_field, option, this.is_test_version, this.locale, null);
|
|
welcome_window.dispose();
|
|
if (new_frame == null)
|
|
{
|
|
return;
|
|
}
|
|
message_field.setText(resources.getString("message_4") + " " + design_file.get_name() + " " + resources.getString("message_5"));
|
|
board_frames.add(new_frame);
|
|
new_frame.addWindowListener(new BoardFrameWindowListener(new_frame));
|
|
}
|
|
|
|
/** Exit the Application */
|
|
private void exitForm(java.awt.event.WindowEvent evt)
|
|
{
|
|
System.exit(0);
|
|
}
|
|
|
|
/** deletes the setting stored by the user if the application is run by Java Web Start */
|
|
private void restore_defaults_action(java.awt.event.ActionEvent evt)
|
|
{
|
|
// webstart is gone, nothing to do
|
|
// TODO maybe add alternative
|
|
}
|
|
|
|
/**
|
|
* Creates a new board frame containing the data of the input design file.
|
|
* Returns null, if an error occurred.
|
|
*/
|
|
static private BoardFrame create_board_frame(DesignFile p_design_file, javax.swing.JTextField p_message_field,
|
|
BoardFrame.Option p_option, boolean p_is_test_version, java.util.Locale p_locale, String p_design_rules_file)
|
|
{
|
|
java.util.ResourceBundle resources =
|
|
java.util.ResourceBundle.getBundle("eu.mihosoft.freerouting.gui.MainApplication", p_locale);
|
|
|
|
java.io.InputStream input_stream = p_design_file.get_input_stream();
|
|
if (input_stream == null)
|
|
{
|
|
if (p_message_field != null)
|
|
{
|
|
p_message_field.setText(resources.getString("message_8") + " " + p_design_file.get_name());
|
|
}
|
|
return null;
|
|
}
|
|
|
|
TestLevel test_level;
|
|
if (p_is_test_version)
|
|
{
|
|
test_level = DEBUG_LEVEL;
|
|
}
|
|
else
|
|
{
|
|
test_level = TestLevel.RELEASE_VERSION;
|
|
}
|
|
BoardFrame new_frame = new BoardFrame(p_design_file, p_option, test_level, p_locale, !p_is_test_version);
|
|
boolean read_ok = new_frame.read(input_stream, p_design_file.is_created_from_text_file(), p_message_field);
|
|
if (!read_ok)
|
|
{
|
|
return null;
|
|
}
|
|
new_frame.menubar.add_design_dependent_items();
|
|
if (p_design_file.is_created_from_text_file())
|
|
{
|
|
// Read the file with the saved rules, if it is existing.
|
|
|
|
String file_name = p_design_file.get_name();
|
|
String[] name_parts = file_name.split("\\.");
|
|
|
|
String design_name = name_parts[0];
|
|
|
|
String parent_folder_name = null;
|
|
String rules_file_name = null;
|
|
String confirm_import_rules_message = null;
|
|
if (p_design_rules_file == null) {
|
|
parent_folder_name = p_design_file.get_parent();
|
|
rules_file_name = design_name + ".rules";
|
|
confirm_import_rules_message = resources.getString("confirm_import_rules");
|
|
} else {
|
|
rules_file_name = p_design_rules_file;
|
|
}
|
|
|
|
DesignFile.read_rules_file(design_name, parent_folder_name, rules_file_name,
|
|
new_frame.board_panel.board_handling, p_option == BoardFrame.Option.WEBSTART,
|
|
confirm_import_rules_message);
|
|
new_frame.refresh_windows();
|
|
}
|
|
return new_frame;
|
|
}
|
|
private final java.util.ResourceBundle resources;
|
|
private final javax.swing.JButton demonstration_button;
|
|
private final javax.swing.JButton sample_board_button;
|
|
private final javax.swing.JButton open_board_button;
|
|
private final javax.swing.JButton restore_defaults_button;
|
|
private final javax.swing.JTextField message_field;
|
|
private final javax.swing.JPanel main_panel;
|
|
/**
|
|
* A Frame with routing demonstrations in the net.
|
|
*/
|
|
private final WindowNetSamples window_net_demonstrations;
|
|
/**
|
|
* A Frame with sample board designs in the net.
|
|
*/
|
|
private final WindowNetSamples window_net_sample_designs;
|
|
/** The list of open board frames */
|
|
private final java.util.Collection<BoardFrame> board_frames
|
|
= new java.util.LinkedList<>();
|
|
private String design_dir_name = null;
|
|
private final boolean is_test_version;
|
|
private final boolean is_webstart;
|
|
private final java.util.Locale locale;
|
|
private static final TestLevel DEBUG_LEVEL = TestLevel.CRITICAL_DEBUGGING_OUTPUT;
|
|
|
|
private class BoardFrameWindowListener extends java.awt.event.WindowAdapter
|
|
{
|
|
|
|
public BoardFrameWindowListener(BoardFrame p_board_frame)
|
|
{
|
|
this.board_frame = p_board_frame;
|
|
}
|
|
|
|
@Override
|
|
public void windowClosed(java.awt.event.WindowEvent evt)
|
|
{
|
|
if (board_frame != null)
|
|
{
|
|
// remove this board_frame from the list of board frames
|
|
board_frame.dispose();
|
|
board_frames.remove(board_frame);
|
|
board_frame = null;
|
|
}
|
|
}
|
|
private BoardFrame board_frame;
|
|
}
|
|
|
|
private class WindowStateListener extends java.awt.event.WindowAdapter
|
|
{
|
|
|
|
@Override
|
|
public void windowClosing(java.awt.event.WindowEvent evt)
|
|
{
|
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
boolean exit_program = true;
|
|
if (!is_test_version && board_frames.size() > 0)
|
|
{
|
|
int option = javax.swing.JOptionPane.showConfirmDialog(null,
|
|
resources.getString("confirm_cancel"),
|
|
null, javax.swing.JOptionPane.YES_NO_OPTION);
|
|
if (option == javax.swing.JOptionPane.NO_OPTION)
|
|
{
|
|
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
|
exit_program = false;
|
|
}
|
|
}
|
|
if (exit_program)
|
|
{
|
|
exitForm(evt);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void windowIconified(java.awt.event.WindowEvent evt)
|
|
{
|
|
window_net_sample_designs.parent_iconified();
|
|
}
|
|
|
|
@Override
|
|
public void windowDeiconified(java.awt.event.WindowEvent evt)
|
|
{
|
|
window_net_sample_designs.parent_deiconified();
|
|
}
|
|
}
|
|
static final String WEB_FILE_BASE_NAME = "http://www.freerouting.mihosoft.eu";
|
|
/**
|
|
* Change this string when creating a new version
|
|
* todo: maybe migrate to 2020.03 version convention?
|
|
*/
|
|
static final String VERSION_NUMBER_STRING = "v1.4.1";
|
|
}
|