/*
* Copyright (C) 2014 Alfons Wirtz
* website www.freerouting.net
*
* 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.
*
* ViaWindow.java
*
* Created on 31. Maerz 2005, 08:36
*/
package gui;
import rules.ViaRule;
import rules.BoardRules;
import board.Layer;
/**
* Window for interactive editing of via rules.
*
* @author Alfons Wirtz
*/
public class WindowVia extends BoardSavableSubWindow
{
/** Creates a new instance of ViaWindow */
public WindowVia(BoardFrame p_board_frame)
{
this.resources = java.util.ResourceBundle.getBundle("gui.resources.WindowVia", p_board_frame.get_locale());
this.setTitle(resources.getString("title"));
this.board_frame = p_board_frame;
this.main_panel = new javax.swing.JPanel();
main_panel.setBorder(javax.swing.BorderFactory.createEmptyBorder(20,20,20,20));
main_panel.setLayout(new java.awt.BorderLayout());
javax.swing.JPanel north_panel = new javax.swing.JPanel();
main_panel.add(north_panel, java.awt.BorderLayout.NORTH);
java.awt.GridBagLayout gridbag = new java.awt.GridBagLayout();
north_panel.setLayout(gridbag);
java.awt.GridBagConstraints gridbag_constraints = new java.awt.GridBagConstraints();
gridbag_constraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
javax.swing.JLabel available_via_padstack_label = new javax.swing.JLabel(resources.getString("available_via_padstacks"));
available_via_padstack_label.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,0,10,10));
gridbag.setConstraints(available_via_padstack_label, gridbag_constraints);
north_panel.add(available_via_padstack_label, gridbag_constraints);
javax.swing.JPanel padstack_button_panel = new javax.swing.JPanel();
padstack_button_panel.setLayout(new java.awt.FlowLayout());
gridbag.setConstraints(padstack_button_panel, gridbag_constraints);
north_panel.add(padstack_button_panel, gridbag_constraints);
final javax.swing.JButton show_padstack_button = new javax.swing.JButton(resources.getString("info"));
show_padstack_button.setToolTipText(resources.getString("info_tooltip"));
show_padstack_button.addActionListener(new ShowPadstacksListener());
padstack_button_panel.add(show_padstack_button);
final javax.swing.JButton add_padstack_button = new javax.swing.JButton(resources.getString("create"));
add_padstack_button.setToolTipText(resources.getString("create_tooltip"));
add_padstack_button.addActionListener(new AddPadstackListener());
padstack_button_panel.add(add_padstack_button);
final javax.swing.JButton remove_padstack_button = new javax.swing.JButton(resources.getString("remove"));
remove_padstack_button.setToolTipText(resources.getString("remove_tooltip"));
remove_padstack_button.addActionListener(new RemovePadstackListener());
padstack_button_panel.add(remove_padstack_button);
javax.swing.JLabel separator_label = new javax.swing.JLabel("---------------------------------------------------------");
separator_label.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,0,10,0));
gridbag.setConstraints(separator_label, gridbag_constraints);
north_panel.add(separator_label, gridbag_constraints);
javax.swing.JLabel available_vias_label = new javax.swing.JLabel(resources.getString("available_vias"));
available_vias_label.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,0,10,10));
gridbag.setConstraints(available_vias_label, gridbag_constraints);
north_panel.add(available_vias_label, gridbag_constraints);
javax.swing.JPanel via_button_panel = new javax.swing.JPanel();
via_button_panel.setLayout(new java.awt.FlowLayout());
gridbag.setConstraints(via_button_panel, gridbag_constraints);
north_panel.add(via_button_panel, gridbag_constraints);
final javax.swing.JButton show_vias_button = new javax.swing.JButton(resources.getString("info"));
show_vias_button.setToolTipText(resources.getString("info_tooltip_2"));
show_vias_button.addActionListener(new ShowViasListener());
via_button_panel.add(show_vias_button);
final javax.swing.JButton edit_vias_button = new javax.swing.JButton(resources.getString("edit"));
edit_vias_button.setToolTipText(resources.getString("edit_tooltip"));
edit_vias_button.addActionListener(new EditViasListener());
via_button_panel.add(edit_vias_button);
separator_label = new javax.swing.JLabel("---------------------------------------------------------");
separator_label.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,0,10,0));
gridbag.setConstraints(separator_label, gridbag_constraints);
north_panel.add(separator_label, gridbag_constraints);
javax.swing.JLabel via_rule_list_name = new javax.swing.JLabel(resources.getString("via_rules"));
via_rule_list_name.setBorder(javax.swing.BorderFactory.createEmptyBorder(10,0,10,10));
gridbag.setConstraints(via_rule_list_name, gridbag_constraints);
north_panel.add(via_rule_list_name, gridbag_constraints);
north_panel.add(via_rule_list_name, gridbag_constraints);
this.rule_list_model = new javax.swing.DefaultListModel();
this.rule_list = new javax.swing.JList(this.rule_list_model);
this.rule_list.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
this.rule_list.setSelectedIndex(0);
this.rule_list.setVisibleRowCount(5);
javax.swing.JScrollPane list_scroll_pane = new javax.swing.JScrollPane(this.rule_list);
list_scroll_pane.setPreferredSize(new java.awt.Dimension(200, 100));
this.main_panel.add(list_scroll_pane, java.awt.BorderLayout.CENTER);
// fill the list
BoardRules board_rules = board_frame.board_panel.board_handling.get_routing_board().rules;
for (ViaRule curr_rule : board_rules.via_rules)
{
this.rule_list_model.addElement(curr_rule);
}
// Add buttons to edit the via rules.
javax.swing.JPanel via_rule_button_panel = new javax.swing.JPanel();
via_rule_button_panel.setLayout(new java.awt.FlowLayout());
this.add(via_rule_button_panel,java.awt.BorderLayout.SOUTH);
final javax.swing.JButton show_rule_button = new javax.swing.JButton(resources.getString("info"));
show_rule_button.setToolTipText(resources.getString("info_tooltip_3"));
show_rule_button.addActionListener(new ShowViaRuleListener());
via_rule_button_panel.add(show_rule_button);
final javax.swing.JButton add_rule_button = new javax.swing.JButton(resources.getString("create"));
add_rule_button.setToolTipText(resources.getString("create_tooltip_2"));
add_rule_button.addActionListener(new AddViaRuleListener());
via_rule_button_panel.add(add_rule_button);
final javax.swing.JButton edit_rule_button = new javax.swing.JButton(resources.getString("edit"));
edit_rule_button.setToolTipText(resources.getString("edit_tooltip_2"));
edit_rule_button.addActionListener(new EditViaRuleListener());
via_rule_button_panel.add(edit_rule_button);
final javax.swing.JButton remove_rule_button = new javax.swing.JButton(resources.getString("remove"));
remove_rule_button.setToolTipText(resources.getString("remove_tooltip_2"));
remove_rule_button.addActionListener(new RemoveViaRuleListener());
via_rule_button_panel.add(remove_rule_button);
p_board_frame.set_context_sensitive_help(this, "WindowVia");
this.add(main_panel);
this.pack();
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
}
public void refresh()
{
// reinsert the elements in the rule list
this.rule_list_model.removeAllElements();
BoardRules board_rules = board_frame.board_panel.board_handling.get_routing_board().rules;
for (ViaRule curr_rule : board_rules.via_rules)
{
this.rule_list_model.addElement(curr_rule);
}
// Dispose all subwindows because they may be no longer uptodate.
java.util.Iterator<javax.swing.JFrame> it = this.subwindows.iterator();
while (it.hasNext())
{
javax.swing.JFrame curr_subwindow = it.next();
if (curr_subwindow != null)
{
curr_subwindow.dispose();
}
it.remove();
}
}
public void dispose()
{
for (javax.swing.JFrame curr_subwindow : this.subwindows)
{
if (curr_subwindow != null)
{
curr_subwindow.dispose();
}
}
if (board_frame.edit_vias_window != null)
{
board_frame.edit_vias_window.dispose();
}
super.dispose();
}
private final BoardFrame board_frame;
private final java.util.ResourceBundle resources;
private final javax.swing.JList rule_list;
private final javax.swing.DefaultListModel rule_list_model;
private final javax.swing.JPanel main_panel;
/** The subwindows with information about selected object*/
private final java.util.Collection<javax.swing.JFrame> subwindows = new java.util.LinkedList<javax.swing.JFrame>();
private static final int WINDOW_OFFSET = 30;
private class ShowPadstacksListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
java.util.Collection<WindowObjectInfo.Printable> object_list = new java.util.LinkedList<WindowObjectInfo.Printable>();
library.BoardLibrary board_library = board_frame.board_panel.board_handling.get_routing_board().library;
for (int i = 0; i < board_library.via_padstack_count(); ++i)
{
object_list.add( board_library.get_via_padstack(i));
}
board.CoordinateTransform coordinate_transform = board_frame.board_panel.board_handling.coordinate_transform;
WindowObjectInfo new_window =
WindowObjectInfo.display(resources.getString("available_via_padstacks"), object_list, board_frame, coordinate_transform);
java.awt.Point loc = getLocation();
java.awt.Point new_window_location =
new java.awt.Point((int) (loc.getX() + WINDOW_OFFSET), (int) (loc.getY() + WINDOW_OFFSET));
new_window.setLocation(new_window_location);
subwindows.add(new_window);
}
}
private class AddPadstackListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
board.BasicBoard pcb = board_frame.board_panel.board_handling.get_routing_board();
if (pcb.layer_structure.arr.length <= 1)
{
return;
}
String padstack_name = javax.swing.JOptionPane.showInputDialog(resources.getString("message_1"));
if (padstack_name == null)
{
return;
}
while (pcb.library.padstacks.get(padstack_name) != null)
{
padstack_name = javax.swing.JOptionPane.showInputDialog(resources.getString("message_2"), padstack_name);
if (padstack_name == null)
{
return;
}
}
Layer start_layer = pcb.layer_structure.arr[0];
Layer end_layer = pcb.layer_structure.arr[pcb.layer_structure.arr.length - 1];
boolean layers_selected = false;
if (pcb.layer_structure.arr.length == 2)
{
layers_selected = true;
}
else
{
Layer[] possible_start_layers = new board.Layer[pcb.layer_structure.arr.length - 1];
for (int i = 0; i < possible_start_layers.length; ++i)
{
possible_start_layers[i] = pcb.layer_structure.arr[i];
}
Object selected_value = javax.swing.JOptionPane.showInputDialog(null, resources.getString("select_start_layer"),
resources.getString("start_layer_selection"),
javax.swing.JOptionPane.INFORMATION_MESSAGE, null, possible_start_layers, possible_start_layers[0]);
if (selected_value == null)
{
return;
}
start_layer = (Layer)selected_value;
if (start_layer == possible_start_layers[possible_start_layers.length - 1])
{
layers_selected = true;
}
}
if (!layers_selected)
{
int first_possible_end_layer_no = pcb.layer_structure.get_no(start_layer) + 1;
Layer[] possible_end_layers = new board.Layer[pcb.layer_structure.arr.length - first_possible_end_layer_no];
for (int i = first_possible_end_layer_no; i < pcb.layer_structure.arr.length; ++i)
{
possible_end_layers[i - first_possible_end_layer_no] = pcb.layer_structure.arr[i];
}
Object selected_value = javax.swing.JOptionPane.showInputDialog(null, resources.getString("select_end_layer"),
resources.getString("end_layer_selection"),
javax.swing.JOptionPane.INFORMATION_MESSAGE, null, possible_end_layers,
possible_end_layers[possible_end_layers.length - 1]);
if (selected_value == null)
{
return;
}
end_layer = (Layer)selected_value;
}
Double default_radius = 100.0;
// ask for the default radius
javax.swing.JPanel default_radius_input_panel = new javax.swing.JPanel();
default_radius_input_panel.add(new javax.swing.JLabel(resources.getString("message_3")));
java.text.NumberFormat number_format = java.text.NumberFormat.getInstance(board_frame.get_locale());
number_format.setMaximumFractionDigits(7);
javax.swing.JFormattedTextField default_radius_input_field = new javax.swing.JFormattedTextField(number_format);
default_radius_input_field.setColumns(7);
default_radius_input_panel.add(default_radius_input_field);
javax.swing.JOptionPane.showMessageDialog(board_frame, default_radius_input_panel,
null, javax.swing.JOptionPane.PLAIN_MESSAGE);
Object input_value = default_radius_input_field.getValue();
if (input_value instanceof Number)
{
default_radius = ((Number)input_value).doubleValue();
}
// input panel to make the default radius layer-depemdent
PadstackInputPanel padstack_input_panel = new PadstackInputPanel(start_layer, end_layer, default_radius);
javax.swing.JOptionPane.showMessageDialog(board_frame, padstack_input_panel,
resources.getString("adjust_circles"), javax.swing.JOptionPane.PLAIN_MESSAGE);
int from_layer_no = pcb.layer_structure.get_no(start_layer);
int to_layer_no = pcb.layer_structure.get_no(end_layer);
geometry.planar.ConvexShape[] padstack_shapes = new geometry.planar.ConvexShape[pcb.layer_structure.arr.length];
board.CoordinateTransform coordinate_transform = board_frame.board_panel.board_handling.coordinate_transform;
boolean shape_exists = false;
for (int i = from_layer_no; i <= to_layer_no; ++i)
{
Object input = padstack_input_panel.circle_radius[i - from_layer_no].getValue();
double radius = default_radius;
if (input instanceof Number)
{
radius = ((Number)input).doubleValue();
}
int circle_radius = (int) Math.round(coordinate_transform.user_to_board(radius));
if (circle_radius > 0)
{
padstack_shapes[i] = new geometry.planar.Circle(geometry.planar.Point.ZERO, circle_radius);
shape_exists = true;
}
}
if (!shape_exists)
{
return;
}
library.Padstack new_padstack = pcb.library.padstacks.add(padstack_name, padstack_shapes, true, true);
pcb.library.add_via_padstack(new_padstack);
}
}
/** Internal class used in AddPadstackListener */
private class PadstackInputPanel extends javax.swing.JPanel
{
PadstackInputPanel(Layer p_from_layer, Layer p_to_layer, Double p_default_radius)
{
java.awt.GridBagLayout gridbag = new java.awt.GridBagLayout();
this.setLayout(gridbag);
java.awt.GridBagConstraints gridbag_constraints = new java.awt.GridBagConstraints();
board.LayerStructure layer_structure = board_frame.board_panel.board_handling.get_routing_board().layer_structure;
int from_layer_no = layer_structure.get_no(p_from_layer);
int to_layer_no = layer_structure.get_no(p_to_layer);
int layer_count = to_layer_no - from_layer_no + 1;
layer_names = new javax.swing.JLabel[layer_count];
circle_radius = new javax.swing.JFormattedTextField [layer_count];
for (int i = 0; i < layer_count; ++i)
{
String label_string = resources.getString("radius_on_layer") + " " + layer_structure.arr[from_layer_no + i].name + ": ";
layer_names[i] = new javax.swing.JLabel(label_string);
java.text.NumberFormat number_format = java.text.NumberFormat.getInstance(board_frame.get_locale());
number_format.setMaximumFractionDigits(7);
circle_radius[i] = new javax.swing.JFormattedTextField(number_format);
circle_radius[i].setColumns(7);
circle_radius[i].setValue(p_default_radius);
gridbag.setConstraints(layer_names[i], gridbag_constraints);
gridbag_constraints.gridwidth = 2;
this.add(layer_names[i], gridbag_constraints);
gridbag.setConstraints(circle_radius[i], gridbag_constraints);
gridbag_constraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
this.add(circle_radius[i], gridbag_constraints);
}
}
private final javax.swing.JLabel [] layer_names;
private final javax.swing.JFormattedTextField [] circle_radius;
}
private class RemovePadstackListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
board.BasicBoard pcb = board_frame.board_panel.board_handling.get_routing_board();
library.Padstack[] via_padstacks = pcb.library.get_via_padstacks();
Object selected_value = javax.swing.JOptionPane.showInputDialog(null,
resources.getString("choose_padstack_to_remove"), resources.getString("remove_via_padstack"),
javax.swing.JOptionPane.INFORMATION_MESSAGE, null, via_padstacks, via_padstacks[0]);
if (selected_value == null)
{
return;
}
library.Padstack selected_padstack = (library.Padstack)selected_value;
rules.ViaInfo via_with_selected_padstack = null;
for (int i = 0; i < pcb.rules.via_infos.count(); ++i)
{
if (pcb.rules.via_infos.get(i).get_padstack() == selected_padstack)
{
via_with_selected_padstack = pcb.rules.via_infos.get(i);
break;
}
}
if (via_with_selected_padstack != null)
{
String message =
resources.getString("message_4") + " " + via_with_selected_padstack.get_name();
board_frame.screen_messages.set_status_message(message);
return;
}
pcb.library.remove_via_padstack(selected_padstack, pcb);
}
}
private class ShowViasListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
java.util.Collection<WindowObjectInfo.Printable> object_list = new java.util.LinkedList<WindowObjectInfo.Printable>();
rules.ViaInfos via_infos = board_frame.board_panel.board_handling.get_routing_board().rules.via_infos;
for (int i = 0; i < via_infos.count(); ++i)
{
object_list.add(via_infos.get(i));
}
board.CoordinateTransform coordinate_transform = board_frame.board_panel.board_handling.coordinate_transform;
WindowObjectInfo new_window =
WindowObjectInfo.display(resources.getString("available_vias"), object_list, board_frame, coordinate_transform);
java.awt.Point loc = getLocation();
java.awt.Point new_window_location =
new java.awt.Point((int) (loc.getX() + WINDOW_OFFSET), (int) (loc.getY() + WINDOW_OFFSET));
new_window.setLocation(new_window_location);
subwindows.add(new_window);
}
}
private class EditViasListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
board_frame.edit_vias_window.setVisible(true);
}
}
private class ShowViaRuleListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
Object[] selected_objects = rule_list.getSelectedValuesList().toArray();
if (selected_objects.length <= 0)
{
return;
}
java.util.Collection<WindowObjectInfo.Printable> object_list = new java.util.LinkedList<WindowObjectInfo.Printable>();
for (int i = 0; i < selected_objects.length; ++i)
{
object_list.add((WindowObjectInfo.Printable)(selected_objects[i]));
}
board.CoordinateTransform coordinate_transform = board_frame.board_panel.board_handling.coordinate_transform;
WindowObjectInfo new_window =
WindowObjectInfo.display(resources.getString("selected_rule"), object_list, board_frame, coordinate_transform);
java.awt.Point loc = getLocation();
java.awt.Point new_window_location =
new java.awt.Point((int) (loc.getX() + WINDOW_OFFSET), (int) (loc.getY() + WINDOW_OFFSET));
new_window.setLocation(new_window_location);
subwindows.add(new_window);
}
}
private class EditViaRuleListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
Object selected_object = rule_list.getSelectedValue();
if (selected_object == null || !(selected_object instanceof ViaRule))
{
return;
}
rules.BoardRules board_rules = board_frame.board_panel.board_handling.get_routing_board().rules;
WindowViaRule new_window = new WindowViaRule((ViaRule) selected_object, board_rules.via_infos, board_frame);
java.awt.Point loc = getLocation();
java.awt.Point new_window_location =
new java.awt.Point((int) (loc.getX() + WINDOW_OFFSET), (int) (loc.getY() + WINDOW_OFFSET));
new_window.setLocation(new_window_location);
subwindows.add(new_window);
}
}
private class AddViaRuleListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
String new_name = javax.swing.JOptionPane.showInputDialog(resources.getString("message_5"));
if (new_name == null)
{
return;
}
new_name = new_name.trim();
if (new_name.equals(""))
{
return;
}
ViaRule new_via_rule = new ViaRule(new_name);
rules.BoardRules board_rules = board_frame.board_panel.board_handling.get_routing_board().rules;
board_rules.via_rules.add(new_via_rule);
rule_list_model.addElement(new_via_rule);
board_frame.refresh_windows();
}
}
private class RemoveViaRuleListener implements java.awt.event.ActionListener
{
public void actionPerformed(java.awt.event.ActionEvent p_evt)
{
Object selected_object = rule_list.getSelectedValue();
if (selected_object == null || !(selected_object instanceof ViaRule))
{
return;
}
ViaRule selected_rule = (ViaRule) selected_object;
String message = resources.getString("remove_via_rule") + " " + selected_rule.name + "?";
if (WindowMessage.confirm(message))
{
rules.BoardRules board_rules = board_frame.board_panel.board_handling.get_routing_board().rules;
board_rules.via_rules.remove(selected_rule);
rule_list_model.removeElement(selected_rule);
}
}
}
}