use of org.concord.energy3d.model.HousePart in project energy3d by concord-consortium.
the class PopupMenuForParabolicDish method getPopupMenu.
static JPopupMenu getPopupMenu() {
if (popupMenuForParabolicDish == null) {
final JMenuItem miMesh = new JMenuItem("Mesh...");
miMesh.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String partInfo = d.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Radial Direction: "));
final JTextField nRadialField = new JTextField("" + d.getNRadialSections());
inputPanel.add(nRadialField);
inputPanel.add(new JLabel("Axial Direction: "));
final JTextField nAxialField = new JTextField("" + d.getNAxialSections());
inputPanel.add(nAxialField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set mesh for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Mesh");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
int nRadialSections = 0, nAxialSections = 0;
boolean ok = true;
try {
nRadialSections = Integer.parseInt(nRadialField.getText());
nAxialSections = Integer.parseInt(nAxialField.getText());
} catch (final NumberFormatException nfe) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (nRadialSections < 4) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Number of radial sections must be at least 4.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (nAxialSections < 4) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Number of axial sections mesh must be at least 4.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (!Util.isPowerOfTwo(nRadialSections) || !Util.isPowerOfTwo(nAxialSections)) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Number of parabolic dish mesh sections in x or y direction must be power of two.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
if (rb1.isSelected()) {
// final SetPartSizeCommand c = new SetPartSizeCommand(t);
d.setNRadialSections(nRadialSections);
d.setNAxialSections(nAxialSections);
d.draw();
SceneManager.getInstance().refresh();
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
// final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setSectionsForParabolicDishes(nRadialSections, nAxialSections);
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
// final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setSectionsForAllParabolicDishes(nRadialSections, nAxialSections);
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
updateAfterEdit();
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miRib = new JMenuItem("Ribs...");
miRib.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String partInfo = d.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Rib Lines: "));
final JTextField nribField = new JTextField("" + d.getNumberOfRibs());
inputPanel.add(nribField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set rib lines for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Ribs");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
int nrib = 0;
boolean ok = true;
try {
nrib = Integer.parseInt(nribField.getText());
} catch (final NumberFormatException nfe) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (nrib < 0) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Number of ribs cannot be negative.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = nrib != d.getNumberOfRibs();
if (rb1.isSelected()) {
if (changed) {
final SetParabolicDishRibsCommand c = new SetParabolicDishRibsCommand(d);
d.setNumberOfRibs(nrib);
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (x.getNumberOfRibs() != nrib) {
changed = true;
break;
}
}
}
if (changed) {
final SetRibsForParabolicDishesOnFoundationCommand c = new SetRibsForParabolicDishesOnFoundationCommand(foundation);
foundation.setNumberOfRibsForParabolicDishes(nrib);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (x.getNumberOfRibs() != nrib) {
changed = true;
break;
}
}
}
if (changed) {
final SetRibsForAllParabolicDishesCommand c = new SetRibsForAllParabolicDishesCommand();
Scene.getInstance().setNumberOfRibsForAllParabolicDishes(nrib);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JCheckBoxMenuItem cbmiDisableEditPoint = new JCheckBoxMenuItem("Disable Edit Point");
cbmiDisableEditPoint.addItemListener(new ItemListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final boolean disabled = cbmiDisableEditPoint.isSelected();
final ParabolicDish dish = (ParabolicDish) selectedPart;
final String partInfo = dish.toString().substring(0, dish.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(0, 20));
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>" + (disabled ? "Disable" : "Enable") + " edit point for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Disable the edit point of a parabolic dish prevents it<br>from being unintentionally moved.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), (disabled ? "Disable" : "Enable") + " Edit Point");
dialog.setVisible(true);
if (optionPane.getValue() == options[0]) {
if (rb1.isSelected()) {
final LockEditPointsCommand c = new LockEditPointsCommand(dish);
dish.setLockEdit(disabled);
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = dish.getTopContainer();
final LockEditPointsOnFoundationCommand c = new LockEditPointsOnFoundationCommand(foundation, dish.getClass());
foundation.setLockEditForClass(disabled, dish.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final LockEditPointsForClassCommand c = new LockEditPointsForClassCommand(dish);
Scene.getInstance().setLockEditForClass(disabled, dish.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
final JCheckBoxMenuItem cbmiDrawSunBeams = new JCheckBoxMenuItem("Draw Sun Beams");
cbmiDrawSunBeams.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
final ShowSunBeamCommand c = new ShowSunBeamCommand(d);
d.setSunBeamVisible(cbmiDrawSunBeams.isSelected());
d.drawSunBeam();
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
}
});
final JMenuItem miRimRadius = new JMenuItem("Rim Radius...");
miRimRadius.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String partInfo = d.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Rim Radius (m): "));
final JTextField apertureRadiusField = new JTextField(threeDecimalsFormat.format(d.getRimRadius()));
inputPanel.add(apertureRadiusField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set rim radius for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Rim Radius");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double r = 0;
boolean ok = true;
try {
r = Double.parseDouble(apertureRadiusField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (r < 1 || r > 10) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic dish rim radius must be between 1 and 10 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(r - d.getRimRadius()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(d);
d.setRimRadius(r);
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(r - x.getRimRadius()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetRimRadiusForParabolicDishesOnFoundationCommand c = new SetRimRadiusForParabolicDishesOnFoundationCommand(foundation);
foundation.setRimRadiusForParabolicDishes(r);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(r - x.getRimRadius()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetRimRadiusForAllParabolicDishesCommand c = new SetRimRadiusForAllParabolicDishesCommand();
Scene.getInstance().setRimRadiusForAllParabolicDishes(r);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miFocalLength = new JMenuItem("Focal Length...");
miFocalLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String partInfo = d.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Focal Length (m): "));
final JTextField focalLengthField = new JTextField(threeDecimalsFormat.format(d.getFocalLength()));
inputPanel.add(focalLengthField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set focal length for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Focal Length");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double fl = 0;
boolean ok = true;
try {
fl = Double.parseDouble(focalLengthField.getText());
} catch (final NumberFormatException nfe) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (fl < 0.5 || fl > 10) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Focal length must be between 0.5 and 10 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(fl - d.getFocalLength()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetParabolicDishFocalLengthCommand c = new SetParabolicDishFocalLengthCommand(d);
d.setFocalLength(fl);
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(fl - x.getFocalLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetFocalLengthForParabolicDishesOnFoundationCommand c = new SetFocalLengthForParabolicDishesOnFoundationCommand(foundation);
foundation.setFocalLengthForParabolicDishes(fl);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(fl - x.getFocalLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetFocalLengthForAllParabolicDishesCommand c = new SetFocalLengthForAllParabolicDishesCommand();
Scene.getInstance().setFocalLengthForAllParabolicDishes(fl);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miBaseHeight = new JMenuItem("Base Height...");
miBaseHeight.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String title = "<html>Base Height (m) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(d.getBaseHeight() * Scene.getInstance().getAnnotationScale()));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Base Height");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText()) / Scene.getInstance().getAnnotationScale();
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
boolean changed = Math.abs(val - d.getBaseHeight()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeBaseHeightCommand c = new ChangeBaseHeightCommand(d);
d.setBaseHeight(val);
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarCollectorBaseHeightCommand c = new ChangeFoundationSolarCollectorBaseHeightCommand(foundation, d.getClass());
foundation.setBaseHeightForParabolicDishes(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBaseHeightForAllSolarCollectorsCommand c = new ChangeBaseHeightForAllSolarCollectorsCommand(d.getClass());
Scene.getInstance().setBaseHeightForAllParabolicDishes(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miStructureType = new JMenuItem("Structure Type...");
miStructureType.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final Foundation foundation = d.getTopContainer();
final String title = "<html>Structure Type of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JComboBox<String> comboBox = new JComboBox<String>(new String[] { "Central Pole", "Tripod" });
comboBox.setSelectedIndex(d.getStructureType());
gui.add(comboBox, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Structure Type");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final int structureType = comboBox.getSelectedIndex();
boolean changed = structureType != d.getStructureType();
if (rb1.isSelected()) {
if (changed) {
final SetParabolicDishStructureTypeCommand c = new SetParabolicDishStructureTypeCommand(d);
d.setStructureType(structureType);
d.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (structureType != x.getStructureType()) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationParabolicDishStructureTypeCommand c = new ChangeFoundationParabolicDishStructureTypeCommand(foundation);
foundation.setStructureTypeForParabolicDishes(structureType);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (structureType != x.getStructureType()) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeStructureTypeForAllParabolicDishesCommand c = new ChangeStructureTypeForAllParabolicDishesCommand();
Scene.getInstance().setStructureTypeForAllParabolicDishes(structureType);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenu labelMenu = new JMenu("Label");
final JCheckBoxMenuItem miLabelNone = new JCheckBoxMenuItem("None", true);
miLabelNone.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (miLabelNone.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicDish) {
final ParabolicDish d = (ParabolicDish) selectedPart;
final SetParabolicDishLabelCommand c = new SetParabolicDishLabelCommand(d);
d.clearLabels();
d.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
}
});
labelMenu.add(miLabelNone);
final JCheckBoxMenuItem miLabelCustom = new JCheckBoxMenuItem("Custom");
miLabelCustom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicDish) {
final ParabolicDish d = (ParabolicDish) selectedPart;
final SetParabolicDishLabelCommand c = new SetParabolicDishLabelCommand(d);
d.setLabelCustom(miLabelCustom.isSelected());
if (d.getLabelCustom()) {
d.setLabelCustomText(JOptionPane.showInputDialog(MainFrame.getInstance(), "Custom Text", d.getLabelCustomText()));
}
d.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCustom);
final JCheckBoxMenuItem miLabelId = new JCheckBoxMenuItem("ID");
miLabelId.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicDish) {
final ParabolicDish d = (ParabolicDish) selectedPart;
final SetParabolicDishLabelCommand c = new SetParabolicDishLabelCommand(d);
d.setLabelId(miLabelId.isSelected());
d.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelId);
final JCheckBoxMenuItem miLabelEnergyOutput = new JCheckBoxMenuItem("Energy Output");
miLabelEnergyOutput.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicDish) {
final ParabolicDish d = (ParabolicDish) selectedPart;
final SetParabolicDishLabelCommand c = new SetParabolicDishLabelCommand(d);
d.setLabelEnergyOutput(miLabelEnergyOutput.isSelected());
d.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelEnergyOutput);
popupMenuForParabolicDish = createPopupMenu(true, true, new Runnable() {
@Override
public void run() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final ParabolicDish d = (ParabolicDish) selectedPart;
Util.selectSilently(miLabelNone, !d.isLabelVisible());
Util.selectSilently(miLabelCustom, d.getLabelCustom());
Util.selectSilently(miLabelId, d.getLabelId());
Util.selectSilently(miLabelEnergyOutput, d.getLabelEnergyOutput());
Util.selectSilently(cbmiDrawSunBeams, d.isSunBeamVisible());
Util.selectSilently(cbmiDisableEditPoint, d.getLockEdit());
}
});
final JMenuItem miReflectance = new JMenuItem("Mirror Reflectance...");
miReflectance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final String title = "<html>Reflectance (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Reflectance can be affected by pollen and dust.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(d.getReflectance() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Mirror Reflectance");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 50 || val > 99) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic dish reflectance must be between 50% and 99%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - d.getReflectance()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorReflectanceCommand c = new ChangeSolarReflectorReflectanceCommand(d);
d.setReflectance(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = d.getTopContainer();
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getReflectance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorReflectanceCommand c = new ChangeFoundationSolarReflectorReflectanceCommand(foundation, d.getClass());
foundation.setReflectanceForSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getReflectance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeReflectanceForAllSolarReflectorsCommand c = new ChangeReflectanceForAllSolarReflectorsCommand(d.getClass());
Scene.getInstance().setReflectanceForAllSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miAbsorptance = new JMenuItem("Receiver Absorptance...");
miAbsorptance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final String title = "<html>Absorptance (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2><hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(d.getAbsorptance() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Receiver Absorptance");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 50 || val > 99) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic dish absorptance must be between 50% and 99%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - d.getAbsorptance()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorAbsorptanceCommand c = new ChangeSolarReflectorAbsorptanceCommand(d);
d.setAbsorptance(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = d.getTopContainer();
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getAbsorptance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorAbsorptanceCommand c = new ChangeFoundationSolarReflectorAbsorptanceCommand(foundation, d.getClass());
foundation.setAbsorptanceForSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getAbsorptance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeAbsorptanceForAllSolarReflectorsCommand c = new ChangeAbsorptanceForAllSolarReflectorsCommand(d.getClass());
Scene.getInstance().setAbsorptanceForAllSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miOpticalEfficiency = new JMenuItem("Optical Efficiency...");
miOpticalEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final String title = "<html>Opitical efficiency (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>For example, the percentage of the effective area for reflection after deducting<br>the area of facet gaps, module frames, absorber shadow, etc.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(d.getOpticalEfficiency() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Optical Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 50 || val > 100) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic dish optical efficiency must be between 50% and 100%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - d.getOpticalEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorOpticalEfficiencyCommand c = new ChangeSolarReflectorOpticalEfficiencyCommand(d);
d.setOpticalEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = d.getTopContainer();
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getOpticalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorOpticalEfficiencyCommand c = new ChangeFoundationSolarReflectorOpticalEfficiencyCommand(foundation, d.getClass());
foundation.setOpticalEfficiencyForSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getOpticalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeOpticalEfficiencyForAllSolarReflectorsCommand c = new ChangeOpticalEfficiencyForAllSolarReflectorsCommand(d.getClass());
Scene.getInstance().setOpticalEfficiencyForAllSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miThermalEfficiency = new JMenuItem("Thermal Efficiency...");
miThermalEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicDish)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicDish d = (ParabolicDish) selectedPart;
final String title = "<html>Thermal efficiency (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2><hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Dish", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Dishes on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Dishes");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(d.getThermalEfficiency() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Dish Thermal Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 5 || val > 80) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic dish thermal efficiency must be between 5% and 80%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - d.getThermalEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorThermalEfficiencyCommand c = new ChangeSolarReflectorThermalEfficiencyCommand(d);
d.setThermalEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = d.getTopContainer();
if (!changed) {
for (final ParabolicDish x : foundation.getParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getThermalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorThermalEfficiencyCommand c = new ChangeFoundationSolarReflectorThermalEfficiencyCommand(foundation, d.getClass());
foundation.setThermalEfficiencyForSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicDish x : Scene.getInstance().getAllParabolicDishes()) {
if (Math.abs(val * 0.01 - x.getThermalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeThermalEfficiencyForAllSolarReflectorsCommand c = new ChangeThermalEfficiencyForAllSolarReflectorsCommand(d.getClass());
Scene.getInstance().setThermalEfficiencyForAllSolarReflectors(val * 0.01, d.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
popupMenuForParabolicDish.addSeparator();
popupMenuForParabolicDish.add(cbmiDisableEditPoint);
popupMenuForParabolicDish.add(cbmiDrawSunBeams);
popupMenuForParabolicDish.add(labelMenu);
popupMenuForParabolicDish.addSeparator();
popupMenuForParabolicDish.add(miRimRadius);
popupMenuForParabolicDish.add(miFocalLength);
popupMenuForParabolicDish.add(miBaseHeight);
popupMenuForParabolicDish.add(miStructureType);
popupMenuForParabolicDish.addSeparator();
popupMenuForParabolicDish.add(miReflectance);
popupMenuForParabolicDish.add(miAbsorptance);
popupMenuForParabolicDish.add(miOpticalEfficiency);
popupMenuForParabolicDish.add(miThermalEfficiency);
popupMenuForParabolicDish.addSeparator();
popupMenuForParabolicDish.add(miMesh);
popupMenuForParabolicDish.add(miRib);
popupMenuForParabolicDish.addSeparator();
JMenuItem mi = new JMenuItem("Daily Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof ParabolicDish) {
new ParabolicDishDailyAnalysis().show();
}
}
});
popupMenuForParabolicDish.add(mi);
mi = new JMenuItem("Annual Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof ParabolicDish) {
new ParabolicDishAnnualAnalysis().show();
}
}
});
popupMenuForParabolicDish.add(mi);
}
return popupMenuForParabolicDish;
}
use of org.concord.energy3d.model.HousePart in project energy3d by concord-consortium.
the class PopupMenuForParabolicTrough method getPopupMenu.
static JPopupMenu getPopupMenu() {
if (popupMenuForParabolicTrough == null) {
final JMenuItem miMesh = new JMenuItem("Mesh...");
miMesh.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String partInfo = t.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Parabolic cross-section: "));
final JTextField nParabolaField = new JTextField("" + t.getNSectionParabola());
inputPanel.add(nParabolaField);
inputPanel.add(new JLabel("Axial direction: "));
final JTextField nAxisField = new JTextField("" + t.getNSectionAxis());
inputPanel.add(nAxisField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set mesh for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Mesh");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
int nSectionParabola = 0, nSectionAxis = 0;
boolean ok = true;
try {
nSectionParabola = Integer.parseInt(nParabolaField.getText());
nSectionAxis = Integer.parseInt(nAxisField.getText());
} catch (final NumberFormatException nfe) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (nSectionParabola < 4) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic sections must be at least 4.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (nSectionAxis < 4) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Axis mesh must be at least 4.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (!Util.isPowerOfTwo(nSectionParabola) || !Util.isPowerOfTwo(nSectionAxis)) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Number of parabolic trough mesh sections in x or y direction must be power of two.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
if (rb1.isSelected()) {
// final SetPartSizeCommand c = new SetPartSizeCommand(t);
t.setNSectionParabola(nSectionParabola);
t.setNSectionAxis(nSectionAxis);
t.draw();
SceneManager.getInstance().refresh();
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
// final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setSectionsForParabolicTroughs(nSectionParabola, nSectionAxis);
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
// final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setSectionsForAllParabolicTroughs(nSectionParabola, nSectionAxis);
// SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
updateAfterEdit();
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JCheckBoxMenuItem cbmiDisableEditPoints = new JCheckBoxMenuItem("Disable Edit Points");
cbmiDisableEditPoints.addItemListener(new ItemListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final boolean disabled = cbmiDisableEditPoints.isSelected();
final ParabolicTrough trough = (ParabolicTrough) selectedPart;
final String partInfo = trough.toString().substring(0, trough.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(0, 20));
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>" + (disabled ? "Disable" : "Enable") + " edit points for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Disable the edit points of a parabolic trough prevents it<br>from being unintentionally moved.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), (disabled ? "Disable" : "Enable") + " Edit Points");
dialog.setVisible(true);
if (optionPane.getValue() == options[0]) {
if (rb1.isSelected()) {
final LockEditPointsCommand c = new LockEditPointsCommand(trough);
trough.setLockEdit(disabled);
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = trough.getTopContainer();
final LockEditPointsOnFoundationCommand c = new LockEditPointsOnFoundationCommand(foundation, trough.getClass());
foundation.setLockEditForClass(disabled, trough.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final LockEditPointsForClassCommand c = new LockEditPointsForClassCommand(trough);
Scene.getInstance().setLockEditForClass(disabled, trough.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
final JCheckBoxMenuItem cbmiDrawSunBeams = new JCheckBoxMenuItem("Draw Sun Beams");
cbmiDrawSunBeams.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final ShowSunBeamCommand c = new ShowSunBeamCommand(t);
t.setSunBeamVisible(cbmiDrawSunBeams.isSelected());
t.drawSunBeam();
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
}
});
final JMenuItem miTroughLength = new JMenuItem("Trough Length...");
miTroughLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String partInfo = t.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Trough Length (m): "));
final JTextField lengthField = new JTextField(threeDecimalsFormat.format(t.getTroughLength()));
inputPanel.add(lengthField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set assembly length for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Assembly Length");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double l = 0;
boolean ok = true;
try {
l = Double.parseDouble(lengthField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (l < 1 || l > 1000) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough length must be between 1 and 1000 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(l - t.getTroughLength()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(t);
t.setTroughLength(l);
t.ensureFullModules(false);
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(l - x.getTroughLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setLengthForParabolicTroughs(l);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(l - x.getTroughLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setLengthForAllParabolicTroughs(l);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miApertureWidth = new JMenuItem("Aperture Width...");
miApertureWidth.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String partInfo = t.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Aperture Width (m): "));
final JTextField widthField = new JTextField(threeDecimalsFormat.format(t.getApertureWidth()));
inputPanel.add(widthField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set aperture width for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Aperture Width");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double w = 0;
boolean ok = true;
try {
w = Double.parseDouble(widthField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (w < 1 || w > 20) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough aperture width must be between 1 and 20 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(w - t.getApertureWidth()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(t);
t.setApertureWidth(w);
t.ensureFullModules(false);
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(w - x.getApertureWidth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setApertureForParabolicTroughs(w);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(w - x.getApertureWidth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setApertureForAllParabolicTroughs(w);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miModuleLength = new JMenuItem("Module Length...");
miModuleLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String partInfo = t.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Module Length (m): "));
final JTextField moduleLengthField = new JTextField(threeDecimalsFormat.format(t.getModuleLength()));
inputPanel.add(moduleLengthField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set module length for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Module Length");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double u = 0;
boolean ok = true;
try {
u = Double.parseDouble(moduleLengthField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (u < 1 || u > 100) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Solar collector module length must be between 1 and 100 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(u - t.getModuleLength()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(t);
t.setModuleLength(u);
t.ensureFullModules(false);
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(u - x.getModuleLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setModuleLengthForParabolicTroughs(u);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(u - x.getModuleLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setModuleLengthForAllParabolicTroughs(u);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miFocalLength = new JMenuItem("Focal Length...");
miFocalLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String partInfo = t.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(1, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Focal Length (m): "));
final JTextField focalLengthField = new JTextField(threeDecimalsFormat.format(t.getSemilatusRectum() / 2));
inputPanel.add(focalLengthField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set shape for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabola Shape");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double f = 0;
boolean ok = true;
try {
f = Double.parseDouble(focalLengthField.getText());
} catch (final NumberFormatException nfe) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (f < 0.5 || f > 5) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Focal length must be between 0.5 and 5 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(2 * f - t.getSemilatusRectum()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetParabolicTroughSemilatusRectumCommand c = new SetParabolicTroughSemilatusRectumCommand(t);
// semilatus rectum p = 2f
t.setSemilatusRectum(2 * f);
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(2 * f - x.getSemilatusRectum()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForParabolicTroughsOnFoundationCommand c = new SetShapeForParabolicTroughsOnFoundationCommand(foundation);
foundation.setSemilatusRectumForParabolicTroughs(2 * f);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(2 * f - x.getSemilatusRectum()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetShapeForAllParabolicTroughsCommand c = new SetShapeForAllParabolicTroughsCommand();
Scene.getInstance().setSemilatusRectumForAllParabolicTroughs(2 * f);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miBaseHeight = new JMenuItem("Base Height...");
miBaseHeight.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final Foundation foundation = t.getTopContainer();
final String title = "<html>Base Height (m) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(t.getBaseHeight() * Scene.getInstance().getAnnotationScale()));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Base Height");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText()) / Scene.getInstance().getAnnotationScale();
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
boolean changed = Math.abs(val - t.getBaseHeight()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeBaseHeightCommand c = new ChangeBaseHeightCommand(t);
t.setBaseHeight(val);
t.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarCollectorBaseHeightCommand c = new ChangeFoundationSolarCollectorBaseHeightCommand(foundation, t.getClass());
foundation.setBaseHeightForSolarCollectors(val, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBaseHeightForAllSolarCollectorsCommand c = new ChangeBaseHeightForAllSolarCollectorsCommand(t.getClass());
Scene.getInstance().setBaseHeightForAllParabolicTroughs(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miAzimuth = new JMenuItem("Azimuth...");
miAzimuth.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough trough = (ParabolicTrough) selectedPart;
final Foundation foundation = trough.getTopContainer();
final String title = "<html>Azimuth Angle (°) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>The azimuth angle is measured clockwise from the true north.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
double a = trough.getRelativeAzimuth() + foundation.getAzimuth();
if (a > 360) {
a -= 360;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(a));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Azimuth");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
a = val - foundation.getAzimuth();
if (a < 0) {
a += 360;
}
boolean changed = Math.abs(a - trough.getRelativeAzimuth()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeAzimuthCommand c = new ChangeAzimuthCommand(trough);
trough.setRelativeAzimuth(a);
trough.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(a - x.getRelativeAzimuth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationParabolicTroughAzimuthCommand c = new ChangeFoundationParabolicTroughAzimuthCommand(foundation);
foundation.setAzimuthForParabolicTroughs(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(a - x.getRelativeAzimuth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeAzimuthForAllParabolicTroughsCommand c = new ChangeAzimuthForAllParabolicTroughsCommand();
Scene.getInstance().setAzimuthForAllParabolicTroughs(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenu labelMenu = new JMenu("Label");
final JCheckBoxMenuItem miLabelNone = new JCheckBoxMenuItem("None", true);
miLabelNone.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (miLabelNone.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicTrough) {
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final SetParabolicTroughLabelCommand c = new SetParabolicTroughLabelCommand(t);
t.clearLabels();
t.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
}
});
labelMenu.add(miLabelNone);
final JCheckBoxMenuItem miLabelCustom = new JCheckBoxMenuItem("Custom");
miLabelCustom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicTrough) {
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final SetParabolicTroughLabelCommand c = new SetParabolicTroughLabelCommand(t);
t.setLabelCustom(miLabelCustom.isSelected());
if (t.getLabelCustom()) {
t.setLabelCustomText(JOptionPane.showInputDialog(MainFrame.getInstance(), "Custom Text", t.getLabelCustomText()));
}
t.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCustom);
final JCheckBoxMenuItem miLabelId = new JCheckBoxMenuItem("ID");
miLabelId.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicTrough) {
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final SetParabolicTroughLabelCommand c = new SetParabolicTroughLabelCommand(t);
t.setLabelId(miLabelId.isSelected());
t.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelId);
final JCheckBoxMenuItem miLabelEnergyOutput = new JCheckBoxMenuItem("Energy Output");
miLabelEnergyOutput.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof ParabolicTrough) {
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final SetParabolicTroughLabelCommand c = new SetParabolicTroughLabelCommand(t);
t.setLabelEnergyOutput(miLabelEnergyOutput.isSelected());
t.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelEnergyOutput);
popupMenuForParabolicTrough = createPopupMenu(true, true, new Runnable() {
@Override
public void run() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final ParabolicTrough t = (ParabolicTrough) selectedPart;
Util.selectSilently(miLabelNone, !t.isLabelVisible());
Util.selectSilently(miLabelCustom, t.getLabelCustom());
Util.selectSilently(miLabelId, t.getLabelId());
Util.selectSilently(miLabelEnergyOutput, t.getLabelEnergyOutput());
Util.selectSilently(cbmiDrawSunBeams, t.isSunBeamVisible());
Util.selectSilently(cbmiDisableEditPoints, t.getLockEdit());
}
});
final JMenuItem miReflectance = new JMenuItem("Mirror Reflectance...");
miReflectance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final String title = "<html>Reflectance (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Reflectance can be affected by pollen and dust.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(t.getReflectance() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Mirror Reflectance");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 50 || val > 99) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough reflectance must be between 50% and 99%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - t.getReflectance()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorReflectanceCommand c = new ChangeSolarReflectorReflectanceCommand(t);
t.setReflectance(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = t.getTopContainer();
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getReflectance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorReflectanceCommand c = new ChangeFoundationSolarReflectorReflectanceCommand(foundation, t.getClass());
foundation.setReflectanceForSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getReflectance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeReflectanceForAllSolarReflectorsCommand c = new ChangeReflectanceForAllSolarReflectorsCommand(t.getClass());
Scene.getInstance().setReflectanceForAllSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miAbsorptance = new JMenuItem("Receiver Absorptance...");
miAbsorptance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final String title = "<html>Absorptance (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2><hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(t.getAbsorptance() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Receiver Absorptance");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 20 || val > 100) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough absorptance must be between 20% and 100%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - t.getAbsorptance()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorAbsorptanceCommand c = new ChangeSolarReflectorAbsorptanceCommand(t);
t.setAbsorptance(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = t.getTopContainer();
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getAbsorptance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorAbsorptanceCommand c = new ChangeFoundationSolarReflectorAbsorptanceCommand(foundation, t.getClass());
foundation.setAbsorptanceForSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getAbsorptance()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeAbsorptanceForAllSolarReflectorsCommand c = new ChangeAbsorptanceForAllSolarReflectorsCommand(t.getClass());
Scene.getInstance().setAbsorptanceForAllSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miOpticalEfficiency = new JMenuItem("Optical Efficiency...");
miOpticalEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final String title = "<html>Opitical efficiency (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>For example, the percentage of the effective area for reflection after deducting<br>the area of facet gaps, module frames, absorber shadow, etc.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(t.getOpticalEfficiency() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Optical Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 50 || val > 100) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough optical efficiency must be between 50% and 100%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - t.getOpticalEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorOpticalEfficiencyCommand c = new ChangeSolarReflectorOpticalEfficiencyCommand(t);
t.setOpticalEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = t.getTopContainer();
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getOpticalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorOpticalEfficiencyCommand c = new ChangeFoundationSolarReflectorOpticalEfficiencyCommand(foundation, t.getClass());
foundation.setOpticalEfficiencyForSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getOpticalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeOpticalEfficiencyForAllSolarReflectorsCommand c = new ChangeOpticalEfficiencyForAllSolarReflectorsCommand(t.getClass());
Scene.getInstance().setOpticalEfficiencyForAllSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miThermalEfficiency = new JMenuItem("Thermal Efficiency...");
miThermalEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof ParabolicTrough)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final ParabolicTrough t = (ParabolicTrough) selectedPart;
final String title = "<html>Thermal efficiency (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2><hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Parabolic Trough", true);
final JRadioButton rb2 = new JRadioButton("All Parabolic Troughs on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Parabolic Troughs");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(t.getThermalEfficiency() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Parabolic Trough Thermal Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 5 || val > 80) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Parabolic trough thermal efficiency must be between 5% and 80%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - t.getThermalEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarReflectorThermalEfficiencyCommand c = new ChangeSolarReflectorThermalEfficiencyCommand(t);
t.setThermalEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = t.getTopContainer();
if (!changed) {
for (final ParabolicTrough x : foundation.getParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getThermalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarReflectorThermalEfficiencyCommand c = new ChangeFoundationSolarReflectorThermalEfficiencyCommand(foundation, t.getClass());
foundation.setThermalEfficiencyForSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final ParabolicTrough x : Scene.getInstance().getAllParabolicTroughs()) {
if (Math.abs(val * 0.01 - x.getThermalEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeThermalEfficiencyForAllSolarReflectorsCommand c = new ChangeThermalEfficiencyForAllSolarReflectorsCommand(t.getClass());
Scene.getInstance().setThermalEfficiencyForAllSolarReflectors(val * 0.01, t.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
popupMenuForParabolicTrough.addSeparator();
popupMenuForParabolicTrough.add(cbmiDisableEditPoints);
popupMenuForParabolicTrough.add(cbmiDrawSunBeams);
popupMenuForParabolicTrough.add(labelMenu);
popupMenuForParabolicTrough.addSeparator();
popupMenuForParabolicTrough.add(miTroughLength);
popupMenuForParabolicTrough.add(miApertureWidth);
popupMenuForParabolicTrough.add(miFocalLength);
popupMenuForParabolicTrough.add(miModuleLength);
popupMenuForParabolicTrough.add(miBaseHeight);
popupMenuForParabolicTrough.add(miAzimuth);
popupMenuForParabolicTrough.addSeparator();
popupMenuForParabolicTrough.add(miReflectance);
popupMenuForParabolicTrough.add(miAbsorptance);
popupMenuForParabolicTrough.add(miOpticalEfficiency);
popupMenuForParabolicTrough.add(miThermalEfficiency);
popupMenuForParabolicTrough.addSeparator();
popupMenuForParabolicTrough.add(miMesh);
popupMenuForParabolicTrough.addSeparator();
JMenuItem mi = new JMenuItem("Daily Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof ParabolicTrough) {
new ParabolicTroughDailyAnalysis().show();
}
}
});
popupMenuForParabolicTrough.add(mi);
mi = new JMenuItem("Annual Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof ParabolicTrough) {
new ParabolicTroughAnnualAnalysis().show();
}
}
});
popupMenuForParabolicTrough.add(mi);
}
return popupMenuForParabolicTrough;
}
use of org.concord.energy3d.model.HousePart in project energy3d by concord-consortium.
the class PopupMenuForRack method getPopupMenu.
static JPopupMenu getPopupMenu() {
if (popupMenuForRack == null) {
final JMenu trackerMenu = new JMenu("Tracker");
final JMenuItem miPaste = new JMenuItem("Paste");
miPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Config.isMac() ? KeyEvent.META_MASK : InputEvent.CTRL_MASK));
miPaste.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() throws Exception {
Scene.getInstance().pasteToPickedLocationOnRack();
Scene.getInstance().setEdited(true);
return null;
}
});
}
});
final JMenuItem miClear = new JMenuItem("Clear");
miClear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() {
if (rack.isMonolithic()) {
rack.setMonolithic(false);
rack.draw();
} else {
Scene.getInstance().removeAllSolarPanels(null);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MainPanel.getInstance().getEnergyButton().setSelected(false);
}
});
}
return null;
}
});
}
});
final JMenuItem miFixedTiltAngle = new JMenuItem("Fixed Tilt Angle...");
miFixedTiltAngle.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
if (rack.areMonthlyTiltAnglesSet()) {
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), "<html>Choosing the fixed tilt angle will remove existing settings for seasonal tilt angles.<br>Are you sure?", "Confirm", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.CANCEL_OPTION) {
return;
}
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final String title = "<html>Tilt Angle of " + partInfo + " (°)</html>";
final String footnote = "<html><hr><font size=2>The tilt angle of a rack is the angle between its surface and the ground surface.<br>The tilt angle must be between -90° and 90°.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on This Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(rack.getTiltAngle() + "");
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Tilt Angle");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < -90 || val > 90) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "The tilt angle must be between -90 and 90 degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
if (Util.isZero(val - 90)) {
val = 89.999;
} else if (Util.isZero(val + 90)) {
val = -89.999;
}
boolean changed = val != rack.getTiltAngle();
if (rb1.isSelected()) {
if (changed) {
final ChangeTiltAngleCommand c = new ChangeTiltAngleCommand(rack);
rack.setTiltAngle(val);
rack.draw();
if (rack.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "The rack cannot be tilted at such an angle as it would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTiltAngle() != val) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationRackTiltAngleCommand c = new ChangeFoundationRackTiltAngleCommand(foundation);
foundation.setTiltAngleForRacks(val);
if (foundation.checkContainerIntersectionForRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Racks cannot be tilted at such an angle as one or more would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTiltAngle() != val) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeTiltAngleForAllRacksCommand c = new ChangeTiltAngleForAllRacksCommand();
Scene.getInstance().setTiltAngleForAllRacks(val);
if (Scene.getInstance().checkContainerIntersectionForAllRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Racks cannot be tilted at such an angle as one or more would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miSeasonalTiltAngle = new JMenuItem("Seasonally Adjusted Tilt Angles...");
miSeasonalTiltAngle.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final Rack rack = (Rack) selectedPart;
final String title = "<html>Seasonally Adjusted Tilt Angles of " + partInfo + " (°)</html>";
final String footnote = "<html><hr><font size=2>The tilt angle of a rack is the angle between its surface and the ground surface.<br>The tilt angle must be between -90° and 90° and may be adjusted seasonally.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on This Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JPanel inputPanel = new JPanel(new SpringLayout());
final JTextField[] fields = new JTextField[12];
for (int i = 0; i < 12; i++) {
final JLabel l = new JLabel(AnnualGraph.THREE_LETTER_MONTH[i] + ": ", JLabel.LEFT);
inputPanel.add(l);
fields[i] = new JTextField(rack.getTiltAngleOfMonth(i) + "", 5);
l.setLabelFor(fields[i]);
inputPanel.add(fields[i]);
}
SpringUtilities.makeCompactGrid(inputPanel, 4, 6, 6, 6, 6, 6);
gui.add(inputPanel, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Seasonally Adjusted Tilt Angles");
while (true) {
fields[0].selectAll();
fields[0].requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final double[] val = new double[12];
boolean ok = true;
for (int i = 0; i < 12; i++) {
try {
val[i] = Double.parseDouble(fields[i].getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), AnnualGraph.THREE_LETTER_MONTH[i] + ": " + fields[i].getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val[i] < -90 || val[i] > 90) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), AnnualGraph.THREE_LETTER_MONTH[i] + ": The tilt angle must be between -90 and 90 degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
}
}
if (ok) {
boolean changed = false;
for (int i = 0; i < 12; i++) {
if (Util.isZero(val[i] - 90)) {
val[i] = 89.999;
} else if (Util.isZero(val[i] + 90)) {
val[i] = -89.999;
}
if (!changed) {
changed = val[i] != rack.getTiltAngleOfMonth(i);
}
}
if (rb1.isSelected()) {
if (changed) {
final ChangeMonthlyTiltAnglesCommand c = new ChangeMonthlyTiltAnglesCommand(rack);
rack.setMonthlyTiltAngles(val);
rack.draw();
if (rack.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "The rack cannot be tilted at such an angle as it would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
for (int i = 0; i < 12; i++) {
if (x.getTiltAngleOfMonth(i) != val[i]) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeFoundationRackMonthlyTiltAnglesCommand c = new ChangeFoundationRackMonthlyTiltAnglesCommand(foundation);
foundation.setMonthlyTiltAnglesForRacks(val);
if (foundation.checkContainerIntersectionForRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Racks cannot be tilted at such an angle as one or more would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
for (int i = 0; i < 12; i++) {
if (x.getTiltAngleOfMonth(i) != val[i]) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeMonthlyTiltAnglesForAllRacksCommand c = new ChangeMonthlyTiltAnglesForAllRacksCommand();
Scene.getInstance().setMonthlyTiltAnglesForAllRacks(val);
if (Scene.getInstance().checkContainerIntersectionForAllRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Racks cannot be tilted at such an angle as one or more would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miAzimuth = new JMenuItem("Azimuth...");
miAzimuth.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final Rack rack = (Rack) selectedPart;
final Foundation foundation = rack.getTopContainer();
final String title = "<html>Azimuth Angle of " + partInfo + " (°)</html>";
final String footnote = "<html><hr><font size=2>The azimuth angle is measured clockwise from the true north.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
double a = rack.getRelativeAzimuth() + foundation.getAzimuth();
if (a > 360) {
a -= 360;
}
final JTextField inputField = new JTextField(a + "");
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Azimuth Angle");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
try {
a = Double.parseDouble(inputField.getText()) - foundation.getAzimuth();
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (a < 0) {
a += 360;
}
boolean changed = a != rack.getRelativeAzimuth();
if (rb1.isSelected()) {
if (changed) {
final ChangeAzimuthCommand c = new ChangeAzimuthCommand(rack);
rack.setRelativeAzimuth(a);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getRelativeAzimuth() != a) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationRackAzimuthCommand c = new ChangeFoundationRackAzimuthCommand(foundation);
foundation.setAzimuthForRacks(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getRelativeAzimuth() != a) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeAzimuthForAllRacksCommand c = new ChangeAzimuthForAllRacksCommand();
Scene.getInstance().setAzimuthForAllRacks(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miRotate = new JMenuItem("Rotate 90\u00B0");
miRotate.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final Foundation foundation = rack.getTopContainer();
final String partInfo = rack.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Rotate 90\u00B0 for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Rotate Rack");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
if (rb1.isSelected()) {
double a = rack.getRelativeAzimuth() + 90;
if (a > 360) {
a -= 360;
}
final ChangeAzimuthCommand c = new ChangeAzimuthCommand(rack);
rack.setRelativeAzimuth(a);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final ChangeFoundationRackAzimuthCommand c = new ChangeFoundationRackAzimuthCommand(foundation);
final List<Rack> racks = foundation.getRacks();
for (final Rack r : racks) {
double a = r.getRelativeAzimuth() + 90;
if (a > 360) {
a -= 360;
}
r.setRelativeAzimuth(a);
r.draw();
}
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final ChangeAzimuthForAllRacksCommand c = new ChangeAzimuthForAllRacksCommand();
final List<Rack> racks = Scene.getInstance().getAllRacks();
for (final Rack r : racks) {
double a = r.getRelativeAzimuth() + 90;
if (a > 360) {
a -= 360;
}
r.setRelativeAzimuth(a);
r.draw();
}
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
updateAfterEdit();
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenuItem miRackWidth = new JMenuItem("Width...");
miRackWidth.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final Foundation foundation = rack.getTopContainer();
final String partInfo = rack.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new SpringLayout());
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
final JLabel label = new JLabel("Width (m): ", JLabel.TRAILING);
inputPanel.add(label);
// rack uses width and height, which should have been named length and width
final JTextField inputField = new JTextField(threeDecimalsFormat.format(rack.getRackHeight()));
label.setLabelFor(inputField);
inputPanel.add(inputField);
SpringUtilities.makeCompactGrid(inputPanel, 1, 2, 6, 6, 6, 6);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set width for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Rack Width");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 0.5 || val > 50) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Width must be between 0.5 and 50 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = val != rack.getRackHeight();
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(rack);
rack.setRackHeight(val);
rack.ensureFullSolarPanels(false);
rack.draw();
if (rack.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This width cannot be set as the rack would cut into the underlying surface.", "Illegal Size", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getRackHeight() != val) {
changed = true;
break;
}
}
}
if (changed) {
final SetSizeForRacksOnFoundationCommand c = new SetSizeForRacksOnFoundationCommand(foundation);
foundation.setWidthForRacks(val);
if (foundation.checkContainerIntersectionForRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This width cannot be set as one or more racks would cut into the underlying surface.", "Illegal Size", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getRackHeight() != val) {
changed = true;
break;
}
}
}
if (changed) {
final SetSizeForAllRacksCommand c = new SetSizeForAllRacksCommand();
Scene.getInstance().setWidthForAllRacks(val);
if (Scene.getInstance().checkContainerIntersectionForAllRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This width cannot be set as one or more racks would cut into the underlying surface.", "Illegal Size", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miRackLength = new JMenuItem("Length...");
miRackLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final Foundation foundation = rack.getTopContainer();
final String partInfo = rack.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new SpringLayout());
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
final JLabel label = new JLabel("Length (m): ", JLabel.TRAILING);
inputPanel.add(label);
// rack uses width and height, which should have been named length and width
final JTextField inputField = new JTextField(threeDecimalsFormat.format(rack.getRackWidth()));
label.setLabelFor(inputField);
inputPanel.add(inputField);
SpringUtilities.makeCompactGrid(inputPanel, 1, 2, 6, 6, 6, 6);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set length for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Rack Length");
while (true) {
dialog.setVisible(true);
inputField.selectAll();
inputField.requestFocusInWindow();
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 1 || val > 1000) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Length must be between 1 and 1000 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = val != rack.getRackWidth();
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(rack);
rack.setRackWidth(val);
rack.ensureFullSolarPanels(false);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getRackWidth() != val) {
changed = true;
break;
}
}
}
if (changed) {
final SetSizeForRacksOnFoundationCommand c = new SetSizeForRacksOnFoundationCommand(foundation);
foundation.setLengthForRacks(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getRackWidth() != val) {
changed = true;
break;
}
}
}
if (changed) {
final SetSizeForAllRacksCommand c = new SetSizeForAllRacksCommand();
Scene.getInstance().setLengthForAllRacks(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miBaseHeight = new JMenuItem("Base Height...");
miBaseHeight.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final Rack rack = (Rack) selectedPart;
final Foundation foundation = rack.getTopContainer();
final String title = "<html>Base Height (m) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2></html>";
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JPanel gui = new JPanel(new BorderLayout());
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(rack.getBaseHeight() * Scene.getInstance().getAnnotationScale() + "");
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Base Height");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
double val = 0;
try {
val = Double.parseDouble(inputField.getText()) / Scene.getInstance().getAnnotationScale();
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
boolean changed = val != rack.getBaseHeight();
if (rb1.isSelected()) {
if (changed) {
final ChangeBaseHeightCommand c = new ChangeBaseHeightCommand(rack);
rack.setBaseHeight(val);
rack.draw();
if (rack.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "The base height cannot be set this low as the rack would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getBaseHeight() != val) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarCollectorBaseHeightCommand c = new ChangeFoundationSolarCollectorBaseHeightCommand(foundation, rack.getClass());
foundation.setBaseHeightForRacks(val);
if (foundation.checkContainerIntersectionForRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Base heights cannot be set this low as one or more racks would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getBaseHeight() != val) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBaseHeightForAllSolarCollectorsCommand c = new ChangeBaseHeightForAllSolarCollectorsCommand(rack.getClass());
Scene.getInstance().setBaseHeightForAllRacks(val);
if (Scene.getInstance().checkContainerIntersectionForAllRacks()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Base heights cannot be set this low as one or more racks would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miPoleSpacing = new JMenuItem("Pole Settings...");
miPoleSpacing.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final String title = "<html>Pole Settings of " + partInfo + "</html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(3, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Distance X (m): "));
final JTextField dxField = new JTextField(threeDecimalsFormat.format(rack.getPoleDistanceX()));
inputPanel.add(dxField);
inputPanel.add(new JLabel("Distance Y (m): "));
final JTextField dyField = new JTextField(threeDecimalsFormat.format(rack.getPoleDistanceY()));
inputPanel.add(dyField);
inputPanel.add(new JLabel("Visible: "));
final JComboBox<String> visibleComboBox = new JComboBox<String>(new String[] { "Yes", "No" });
visibleComboBox.setSelectedIndex(rack.isPoleVisible() ? 0 : 1);
inputPanel.add(visibleComboBox);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Pole Settings");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
double dx = 0, dy = 0;
try {
dx = Double.parseDouble(dxField.getText());
dy = Double.parseDouble(dyField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (dx < 1 || dx > 50) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Dx must be between 1 and 50 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (dy < 1 || dy > 50) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Dy must be between 1 and 50 m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
final boolean visible = visibleComboBox.getSelectedIndex() == 0;
boolean changed = dx != rack.getPoleDistanceX() || dy != rack.getPoleDistanceY();
if (rb1.isSelected()) {
if (changed) {
final ChangeRackPoleSettingsCommand c = new ChangeRackPoleSettingsCommand(rack);
rack.setPoleDistanceX(dx);
rack.setPoleDistanceY(dy);
rack.setPoleVisible(visible);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getPoleDistanceX() != dx || x.getPoleDistanceY() != dy) {
changed = true;
break;
}
}
}
if (changed) {
final ChangePoleSettingsForRacksOnFoundationCommand c = new ChangePoleSettingsForRacksOnFoundationCommand(foundation);
foundation.setPoleSpacingForRacks(dx, dy, visible);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getPoleDistanceX() != dx || x.getPoleDistanceY() != dy) {
changed = true;
break;
}
}
}
if (changed) {
final ChangePoleSettingsForAllRacksCommand c = new ChangePoleSettingsForAllRacksCommand();
Scene.getInstance().setPoleSpacingForAllRacks(dx, dy, visible);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miSolarPanels = new JMenuItem("Select Solar Panels...");
miSolarPanels.addActionListener(new ActionListener() {
private Rack rack;
private JComboBox<String> modelComboBox;
private JComboBox<String> sizeComboBox;
private JComboBox<String> orientationComboBox;
private JComboBox<String> cellTypeComboBox;
private JComboBox<String> colorOptionComboBox;
private JComboBox<String> shadeToleranceComboBox;
private JTextField cellEfficiencyField;
private JTextField noctField;
private JTextField pmaxTcField;
private double cellEfficiency;
private double inverterEfficiency;
private double pmax;
private double noct;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
rack = (Rack) selectedPart;
final int n = rack.getChildren().size();
if (n > 0 && JOptionPane.showConfirmDialog(MainFrame.getInstance(), "All existing " + n + " solar panels on this rack must be removed before\na new layout can be applied. Do you want to continue?", "Confirmation", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
final SolarPanel solarPanel = rack.getSolarPanel();
final JPanel panel = new JPanel(new SpringLayout());
panel.add(new JLabel("Model"));
modelComboBox = new JComboBox<String>();
modelComboBox.addItem("Custom");
final Map<String, PvModuleSpecs> modules = PvModulesData.getInstance().getModules();
for (final String key : modules.keySet()) {
modelComboBox.addItem(key);
}
if (solarPanel.getModelName() != null) {
modelComboBox.setSelectedItem(solarPanel.getModelName());
}
modelComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final boolean isCustom = modelComboBox.getSelectedIndex() == 0;
sizeComboBox.setEnabled(isCustom);
cellTypeComboBox.setEnabled(isCustom);
colorOptionComboBox.setEnabled(isCustom);
shadeToleranceComboBox.setEnabled(isCustom);
cellEfficiencyField.setEnabled(isCustom);
noctField.setEnabled(isCustom);
pmaxTcField.setEnabled(isCustom);
if (!isCustom) {
final PvModuleSpecs specs = modules.get(modelComboBox.getSelectedItem());
cellTypeComboBox.setSelectedItem(specs.getCellType());
shadeToleranceComboBox.setSelectedItem(specs.getShadeTolerance());
cellEfficiencyField.setText(threeDecimalsFormat.format(specs.getCelLEfficiency() * 100));
noctField.setText(threeDecimalsFormat.format(specs.getNoct()));
pmaxTcField.setText(sixDecimalsFormat.format(specs.getPmaxTc()));
final String s = threeDecimalsFormat.format(specs.getNominalWidth()) + "m \u00D7 " + threeDecimalsFormat.format(specs.getNominalLength()) + "m (" + specs.getLayout().width + " \u00D7 " + specs.getLayout().height + " cells)";
sizeComboBox.setSelectedItem(s);
colorOptionComboBox.setSelectedItem(specs.getColor());
}
}
}
});
panel.add(modelComboBox);
// the following properties should be disabled when the model is not custom
panel.add(new JLabel("Panel Size:"));
sizeComboBox = new JComboBox<String>(solarPanelNominalSize.getStrings());
final PvModuleSpecs specs = solarPanel.getPvModuleSpecs();
final boolean isCustom = "Custom".equals(specs.getModel());
final double width = isCustom ? solarPanel.getPanelWidth() : specs.getNominalWidth();
final double height = isCustom ? solarPanel.getPanelHeight() : specs.getNominalLength();
final int nItems = sizeComboBox.getItemCount();
for (int i = 0; i < nItems; i++) {
if (Util.isZero(height - solarPanelNominalSize.getNominalHeights()[i]) && Util.isZero(width - solarPanelNominalSize.getNominalWidths()[i])) {
sizeComboBox.setSelectedIndex(i);
}
}
panel.add(sizeComboBox);
panel.add(new JLabel("Cell Type:"));
cellTypeComboBox = new JComboBox<String>(new String[] { "Polycrystalline", "Monocrystalline", "Thin Film" });
cellTypeComboBox.setSelectedIndex(solarPanel.getCellType());
panel.add(cellTypeComboBox);
panel.add(new JLabel("Color:"));
colorOptionComboBox = new JComboBox<String>(new String[] { "Blue", "Black", "Gray" });
colorOptionComboBox.setSelectedIndex(solarPanel.getColorOption());
panel.add(colorOptionComboBox);
panel.add(new JLabel("Solar Cell Efficiency (%):"));
cellEfficiencyField = new JTextField(threeDecimalsFormat.format(solarPanel.getCellEfficiency() * 100));
panel.add(cellEfficiencyField);
panel.add(new JLabel("<html>Nominal Operating Cell Temperature (°C):"));
noctField = new JTextField(threeDecimalsFormat.format(solarPanel.getNominalOperatingCellTemperature()));
panel.add(noctField);
panel.add(new JLabel("<html>Temperature Coefficient of Pmax (%/°C):"));
pmaxTcField = new JTextField(sixDecimalsFormat.format(solarPanel.getTemperatureCoefficientPmax() * 100));
panel.add(pmaxTcField);
panel.add(new JLabel("Shade Tolerance:"));
shadeToleranceComboBox = new JComboBox<String>(new String[] { "Partial", "High", "None" });
shadeToleranceComboBox.setSelectedIndex(solarPanel.getShadeTolerance());
panel.add(shadeToleranceComboBox);
if (modelComboBox.getSelectedIndex() != 0) {
sizeComboBox.setEnabled(false);
cellTypeComboBox.setEnabled(false);
colorOptionComboBox.setEnabled(false);
shadeToleranceComboBox.setEnabled(false);
cellEfficiencyField.setEnabled(false);
noctField.setEnabled(false);
pmaxTcField.setEnabled(false);
}
// the following properties are not related to the model
panel.add(new JLabel("Orientation:"));
orientationComboBox = new JComboBox<String>(new String[] { "Portrait", "Landscape" });
orientationComboBox.setSelectedIndex(solarPanel.isRotated() ? 1 : 0);
panel.add(orientationComboBox);
panel.add(new JLabel("Inverter Efficiency (%):"));
final JTextField inverterEfficiencyField = new JTextField(threeDecimalsFormat.format(solarPanel.getInverterEfficiency() * 100));
panel.add(inverterEfficiencyField);
SpringUtilities.makeCompactGrid(panel, 10, 2, 6, 6, 6, 6);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panels on this Rack");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
if (modelComboBox.getSelectedIndex() == 0) {
try {
cellEfficiency = Double.parseDouble(cellEfficiencyField.getText());
pmax = Double.parseDouble(pmaxTcField.getText());
noct = Double.parseDouble(noctField.getText());
inverterEfficiency = Double.parseDouble(inverterEfficiencyField.getText());
} catch (final NumberFormatException ex) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (cellEfficiency < SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE || cellEfficiency > SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Solar cell efficiency must be between " + SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "% and " + SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (inverterEfficiency < SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE || inverterEfficiency >= SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Inverter efficiency must be greater than " + SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE + "% and less than " + SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (pmax < -1 || pmax > 0) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Temperature coefficient of Pmax must be between -1% and 0% per Celsius degree.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (noct < 33 || noct > 58) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Nominal Cell Operating Temperature must be between 33 and 58 Celsius degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
setCustomSolarPanels();
if (choice == options[0]) {
break;
}
}
}
} else {
try {
inverterEfficiency = Double.parseDouble(inverterEfficiencyField.getText());
} catch (final NumberFormatException ex) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (inverterEfficiency < SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE || inverterEfficiency >= SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Inverter efficiency must be greater than " + SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE + "% and less than " + SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
setBrandSolarPanels((String) modelComboBox.getSelectedItem());
if (choice == options[0]) {
break;
}
}
}
}
}
}
}
private void setBrandSolarPanels(final String modelName) {
final SolarPanel s = rack.getSolarPanel();
final boolean changed = !modelName.equals(s.getPvModuleSpecs().getModel()) || Math.abs(inverterEfficiency * 0.01 - s.getInverterEfficiency()) > 0.000001 || ((orientationComboBox.getSelectedIndex() == 1) ^ s.isRotated());
if (changed) {
final SetSolarPanelArrayOnRackByModelCommand command = rack.isMonolithic() ? new SetSolarPanelArrayOnRackByModelCommand(rack) : null;
s.setRotated(orientationComboBox.getSelectedIndex() == 1);
s.setInverterEfficiency(inverterEfficiency * 0.01);
s.setPvModuleSpecs(PvModulesData.getInstance().getModuleSpecs(modelName));
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() {
rack.addSolarPanels();
if (command != null) {
SceneManager.getInstance().getUndoManager().addEdit(command);
}
return null;
}
});
updateAfterEdit();
}
}
private void setCustomSolarPanels() {
final SolarPanel s = rack.getSolarPanel();
final int i = sizeComboBox.getSelectedIndex();
boolean changed = !"Custom".equals(s.getModelName());
if (s.getPanelWidth() != solarPanelNominalSize.getNominalWidths()[i]) {
changed = true;
} else if (s.getPanelHeight() != solarPanelNominalSize.getNominalHeights()[i]) {
changed = true;
} else if (s.getNumberOfCellsInX() != solarPanelNominalSize.getCellNx()[i]) {
changed = true;
} else if (s.getNumberOfCellsInY() != solarPanelNominalSize.getCellNy()[i]) {
changed = true;
} else if (s.isRotated() ^ orientationComboBox.getSelectedIndex() == 1) {
changed = true;
} else if (s.getCellType() != cellTypeComboBox.getSelectedIndex()) {
changed = true;
} else if (s.getColorOption() != colorOptionComboBox.getSelectedIndex()) {
changed = true;
} else if (Math.abs(s.getCellEfficiency() - cellEfficiency * 0.01) > 0.000001) {
changed = true;
} else if (Math.abs(s.getInverterEfficiency() - inverterEfficiency * 0.01) > 0.000001) {
changed = true;
} else if (Math.abs(s.getTemperatureCoefficientPmax() - pmax * 0.01) > 0.000001) {
changed = true;
} else if (Math.abs(s.getNominalOperatingCellTemperature() - noct) > 0.000001) {
changed = true;
} else if (s.getShadeTolerance() != shadeToleranceComboBox.getSelectedIndex()) {
changed = true;
}
if (changed) {
s.setModelName("Custom");
s.setBrandName("Custom");
final SetSolarPanelArrayOnRackCustomCommand command = rack.isMonolithic() ? new SetSolarPanelArrayOnRackCustomCommand(rack) : null;
s.setPanelWidth(solarPanelNominalSize.getNominalWidths()[i]);
s.setPanelHeight(solarPanelNominalSize.getNominalHeights()[i]);
s.setNumberOfCellsInX(solarPanelNominalSize.getCellNx()[i]);
s.setNumberOfCellsInY(solarPanelNominalSize.getCellNy()[i]);
s.setRotated(orientationComboBox.getSelectedIndex() == 1);
s.setCellType(cellTypeComboBox.getSelectedIndex());
s.setColorOption(colorOptionComboBox.getSelectedIndex());
s.setCellEfficiency(cellEfficiency * 0.01);
s.setInverterEfficiency(inverterEfficiency * 0.01);
s.setTemperatureCoefficientPmax(pmax * 0.01);
s.setNominalOperatingCellTemperature(noct);
s.setShadeTolerance(shadeToleranceComboBox.getSelectedIndex());
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() {
rack.addSolarPanels();
if (command != null) {
SceneManager.getInstance().getUndoManager().addEdit(command);
}
return null;
}
});
updateAfterEdit();
}
}
});
final JMenu solarPanelMenu = new JMenu("Change Solar Panel Properties");
final JMenuItem miSolarPanelModel = new JMenuItem("Model...");
solarPanelMenu.add(miSolarPanelModel);
miSolarPanelModel.addActionListener(new ActionListener() {
private String modelName;
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final Map<String, PvModuleSpecs> modules = PvModulesData.getInstance().getModules();
final String[] models = new String[modules.size() + 1];
int i = 0;
models[i] = "Custom";
for (final String key : modules.keySet()) {
models[++i] = key;
}
final PvModuleSpecs specs = s.getPvModuleSpecs();
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Solar Panel Model for " + partInfo));
final JComboBox<String> typeComboBox = new JComboBox<String>(models);
typeComboBox.setSelectedItem(specs.getModel());
modelName = specs.getModel();
typeComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
modelName = (String) typeComboBox.getSelectedItem();
}
}
});
gui.add(typeComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Model");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = !modelName.equals(s.getModelName());
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarPanelModelForRackCommand c = new ChangeSolarPanelModelForRackCommand(r);
s.setPvModuleSpecs(PvModulesData.getInstance().getModuleSpecs(modelName));
r.ensureFullSolarPanels(false);
r.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (!modelName.equals(x.getSolarPanel().getModelName())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeSolarPanelModelForRacksOnFoundationCommand c = new ChangeSolarPanelModelForRacksOnFoundationCommand(foundation);
foundation.setSolarPanelModelForRacks(PvModulesData.getInstance().getModuleSpecs(modelName));
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (!modelName.equals(x.getSolarPanel().getModelName())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeSolarPanelModelForAllRacksCommand c = new ChangeSolarPanelModelForAllRacksCommand();
Scene.getInstance().setSolarPanelModelForAllRacks(PvModulesData.getInstance().getModuleSpecs(modelName));
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
solarPanelMenu.addSeparator();
final JMenuItem miSolarPanelSize = new JMenuItem("Size...");
solarPanelMenu.add(miSolarPanelSize);
miSolarPanelSize.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Solar Panel Size for " + partInfo));
final JComboBox<String> sizeComboBox = new JComboBox<String>(solarPanelNominalSize.getStrings());
final PvModuleSpecs specs = s.getPvModuleSpecs();
final boolean isCustom = "Custom".equals(specs.getModel());
final double width = isCustom ? s.getPanelWidth() : specs.getNominalWidth();
final double height = isCustom ? s.getPanelHeight() : specs.getNominalLength();
final int nItems = sizeComboBox.getItemCount();
for (int i = 0; i < nItems; i++) {
if (Util.isZero(height - solarPanelNominalSize.getNominalHeights()[i]) && Util.isZero(width - solarPanelNominalSize.getNominalWidths()[i])) {
sizeComboBox.setSelectedIndex(i);
}
}
gui.add(sizeComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Size");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final int i = sizeComboBox.getSelectedIndex();
final double w = solarPanelNominalSize.getNominalWidths()[i];
final double h = solarPanelNominalSize.getNominalHeights()[i];
final int numberOfCellsInX = solarPanelNominalSize.getCellNx()[i];
final int numberOfCellsInY = solarPanelNominalSize.getCellNy()[i];
boolean changed = numberOfCellsInX != s.getNumberOfCellsInX() || numberOfCellsInY != s.getNumberOfCellsInY();
if (Math.abs(s.getPanelWidth() - w) > 0.000001 || Math.abs(s.getPanelHeight() - h) > 0.000001) {
changed = true;
}
if (rb1.isSelected()) {
if (changed) {
final ChooseSolarPanelSizeForRackCommand c = new ChooseSolarPanelSizeForRackCommand(r);
s.setPanelWidth(w);
s.setPanelHeight(h);
s.setNumberOfCellsInX(numberOfCellsInX);
s.setNumberOfCellsInY(numberOfCellsInY);
r.ensureFullSolarPanels(false);
r.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
final SolarPanel p = x.getSolarPanel();
if (numberOfCellsInX != p.getNumberOfCellsInX() || numberOfCellsInY != p.getNumberOfCellsInY()) {
changed = true;
break;
}
if (Math.abs(p.getPanelWidth() - w) > 0.000001 || Math.abs(p.getPanelHeight() - h) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelSizeForRacksOnFoundationCommand c = new SetSolarPanelSizeForRacksOnFoundationCommand(foundation);
foundation.setSolarPanelSizeForRacks(w, h, numberOfCellsInX, numberOfCellsInY);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
final SolarPanel p = x.getSolarPanel();
if (numberOfCellsInX != p.getNumberOfCellsInX() || numberOfCellsInY != p.getNumberOfCellsInY()) {
changed = true;
break;
}
if (Math.abs(p.getPanelWidth() - w) > 0.000001 || Math.abs(p.getPanelHeight() - h) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelSizeForAllRacksCommand c = new SetSolarPanelSizeForAllRacksCommand();
Scene.getInstance().setSolarPanelSizeForAllRacks(w, h, numberOfCellsInX, numberOfCellsInY);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenuItem miSolarPanelCellType = new JMenuItem("Cell Type...");
solarPanelMenu.add(miSolarPanelCellType);
miSolarPanelCellType.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Choose Cell Type for " + partInfo));
final JComboBox<String> cellTypeComboBox = new JComboBox<String>(new String[] { "Polycrystalline", "Monocrystalline", "Thin Film" });
cellTypeComboBox.setSelectedIndex(s.getCellType());
gui.add(cellTypeComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Cell Type");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final int selectedIndex = cellTypeComboBox.getSelectedIndex();
boolean changed = selectedIndex != s.getCellType();
if (rb1.isSelected()) {
if (changed) {
final SetSolarPanelCellTypeForRackCommand c = new SetSolarPanelCellTypeForRackCommand(r);
s.setCellType(selectedIndex);
r.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getSolarPanel().getCellType() != selectedIndex) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelCellTypeForRacksOnFoundationCommand c = new SetSolarPanelCellTypeForRacksOnFoundationCommand(foundation);
foundation.setSolarPanelCellTypeForRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getSolarPanel().getCellType() != selectedIndex) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelCellTypeForAllRacksCommand c = new SetSolarPanelCellTypeForAllRacksCommand();
Scene.getInstance().setSolarPanelCellTypeForAllRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenuItem miSolarPanelColor = new JMenuItem("Color...");
solarPanelMenu.add(miSolarPanelColor);
miSolarPanelColor.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Choose Color for " + partInfo));
final JComboBox<String> colorComboBox = new JComboBox<String>(new String[] { "Blue", "Black", "Gray" });
colorComboBox.setSelectedIndex(s.getColorOption());
gui.add(colorComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Color");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final int selectedIndex = colorComboBox.getSelectedIndex();
boolean changed = selectedIndex != s.getColorOption();
if (rb1.isSelected()) {
if (changed) {
final SetSolarPanelColorForRackCommand c = new SetSolarPanelColorForRackCommand(r);
s.setColorOption(selectedIndex);
r.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getSolarPanel().getColorOption() != selectedIndex) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelColorForRacksOnFoundationCommand c = new SetSolarPanelColorForRacksOnFoundationCommand(foundation);
foundation.setSolarPanelColorForRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getSolarPanel().getColorOption() != selectedIndex) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelColorForAllRacksCommand c = new SetSolarPanelColorForAllRacksCommand();
Scene.getInstance().setSolarPanelColorForAllRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenuItem miSolarPanelCellEfficiency = new JMenuItem("Solar Cell Efficiency...");
solarPanelMenu.add(miSolarPanelCellEfficiency);
miSolarPanelCellEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String title = "Set Solar Cell Efficiency (%) for " + r.toString().substring(0, r.toString().indexOf(')') + 1);
final String footnote = "<html><hr><font size=2>How efficient can a solar panel be for converting light into electricity?<br>The Shockley-Queisser limit is 34%.<br>The theoretical limit for multilayer cells is 86%.<br>As of 2017, the best solar panel in the market has an efficiency of 24%.<br>The highest efficiency you can choose is limited to " + SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "%.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout(5, 5));
final JTextField inputField = new JTextField(threeDecimalsFormat.format(s.getCellEfficiency() * 100));
gui.add(inputField, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Cell Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
try {
solarCellEfficiencyPercentage = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (solarCellEfficiencyPercentage < SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE || solarCellEfficiencyPercentage > SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Solar cell efficiency must be between " + SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "% and " + SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(solarCellEfficiencyPercentage * 0.01 - s.getCellEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetSolarCellEfficiencyForRackCommand c = new SetSolarCellEfficiencyForRackCommand(r);
s.setCellEfficiency(solarCellEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (Math.abs(solarCellEfficiencyPercentage * 0.01 - x.getSolarPanel().getCellEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarCellEfficiencyForRacksOnFoundationCommand c = new SetSolarCellEfficiencyForRacksOnFoundationCommand(foundation);
foundation.setSolarCellEfficiencyForRacks(solarCellEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (Math.abs(solarCellEfficiencyPercentage * 0.01 - x.getSolarPanel().getCellEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarCellEfficiencyForAllRacksCommand c = new SetSolarCellEfficiencyForAllRacksCommand();
Scene.getInstance().setSolarCellEfficiencyForAllRacks(solarCellEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miSolarPanelNoct = new JMenuItem("Nominal Operating Cell Temperature...");
solarPanelMenu.add(miSolarPanelNoct);
miSolarPanelNoct.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String title = "<html>Nominal Operating Cell Temperature (°C) for " + r.toString().substring(0, r.toString().indexOf(')') + 1);
final String footnote = "<html><hr><font size=2>Increased temperature reduces solar cell efficiency.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout(5, 5));
final JTextField inputField = new JTextField(threeDecimalsFormat.format(s.getNominalOperatingCellTemperature()));
gui.add(inputField, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Nominal Operating Cell Temperature");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
try {
solarPanelNominalOperatingCellTemperature = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (solarPanelNominalOperatingCellTemperature < 33 || solarPanelNominalOperatingCellTemperature > 58) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Nominal Operating Cell Temperature must be between 33 and 58 degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(solarPanelNominalOperatingCellTemperature - s.getNominalOperatingCellTemperature()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetNoctForRackCommand c = new SetNoctForRackCommand(r);
s.setNominalOperatingCellTemperature(solarPanelNominalOperatingCellTemperature);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (Math.abs(solarPanelNominalOperatingCellTemperature - x.getSolarPanel().getNominalOperatingCellTemperature()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetNoctForRacksOnFoundationCommand c = new SetNoctForRacksOnFoundationCommand(foundation);
foundation.setNominalOperatingCellTemperatureForRacks(solarPanelNominalOperatingCellTemperature);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (Math.abs(solarPanelNominalOperatingCellTemperature - x.getSolarPanel().getNominalOperatingCellTemperature()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetNoctForAllRacksCommand c = new SetNoctForAllRacksCommand();
Scene.getInstance().setNominalOperatingCellTemperatureForAllRacks(solarPanelNominalOperatingCellTemperature);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miSolarPanelPmaxTc = new JMenuItem("Temperature Coefficient of Pmax...");
solarPanelMenu.add(miSolarPanelPmaxTc);
miSolarPanelPmaxTc.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String title = "<html>Temperature Coefficienct of Pmax (%/°C) for " + r.toString().substring(0, r.toString().indexOf(')') + 1);
final String footnote = "<html><hr><font size=2>Increased temperature reduces solar cell efficiency.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout(5, 5));
final JTextField inputField = new JTextField(threeDecimalsFormat.format(s.getTemperatureCoefficientPmax() * 100));
gui.add(inputField, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Temperature Coefficient of Pmax");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
try {
solarPanelTemperatureCoefficientPmaxPercentage = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (solarPanelTemperatureCoefficientPmaxPercentage < -1 || solarPanelTemperatureCoefficientPmaxPercentage > 0) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Temperature coefficient of Pmax must be between -1 and 0", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(solarPanelTemperatureCoefficientPmaxPercentage * 0.01 - s.getTemperatureCoefficientPmax()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetTemperatureCoefficientPmaxForRackCommand c = new SetTemperatureCoefficientPmaxForRackCommand(r);
s.setTemperatureCoefficientPmax(solarPanelTemperatureCoefficientPmaxPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (Math.abs(solarPanelTemperatureCoefficientPmaxPercentage * 0.01 - x.getSolarPanel().getTemperatureCoefficientPmax()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetTemperatureCoefficientPmaxForRacksOnFoundationCommand c = new SetTemperatureCoefficientPmaxForRacksOnFoundationCommand(foundation);
foundation.setTemperatureCoefficientPmaxForRacks(solarPanelTemperatureCoefficientPmaxPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (Math.abs(solarPanelTemperatureCoefficientPmaxPercentage * 0.01 - x.getSolarPanel().getTemperatureCoefficientPmax()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetTemperatureCoefficientPmaxForAllRacksCommand c = new SetTemperatureCoefficientPmaxForAllRacksCommand();
Scene.getInstance().setTemperatureCoefficientPmaxForAllRacks(solarPanelTemperatureCoefficientPmaxPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miSolarPanelShadeTolerance = new JMenuItem("Shade Tolerance...");
solarPanelMenu.add(miSolarPanelShadeTolerance);
miSolarPanelShadeTolerance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String title = "Set Solar Panel Shade Tolerance for " + r.toString().substring(0, r.toString().indexOf(')') + 1);
final String footnote = "<html><hr><font size=2>Use bypass diodes to direct current under shading conditions.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout(5, 5));
final JComboBox<String> toleranceComboBox = new JComboBox<String>(new String[] { "Partial", "High", "None" });
toleranceComboBox.setSelectedIndex(s.getShadeTolerance());
gui.add(toleranceComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Shade Tolerance");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final int selectedIndex = toleranceComboBox.getSelectedIndex();
boolean changed = selectedIndex != s.getShadeTolerance();
if (rb1.isSelected()) {
if (changed) {
final SetSolarPanelShadeToleranceForRackCommand c = new SetSolarPanelShadeToleranceForRackCommand(r);
s.setShadeTolerance(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (selectedIndex != x.getSolarPanel().getShadeTolerance()) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelShadeToleranceForRacksOnFoundationCommand c = new SetSolarPanelShadeToleranceForRacksOnFoundationCommand(foundation);
foundation.setSolarPanelShadeToleranceForRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (selectedIndex != x.getSolarPanel().getShadeTolerance()) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarPanelShadeToleranceForAllRacksCommand c = new SetSolarPanelShadeToleranceForAllRacksCommand();
Scene.getInstance().setSolarPanelShadeToleranceForAllRacks(selectedIndex);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
solarPanelMenu.addSeparator();
final JMenuItem miSolarPanelOrientation = new JMenuItem("Orientation...");
solarPanelMenu.add(miSolarPanelOrientation);
miSolarPanelOrientation.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Solar Panel Orientation for " + partInfo));
final JComboBox<String> orientationComboBox = new JComboBox<String>(new String[] { "Portrait", "Landscape" });
orientationComboBox.setSelectedIndex(s.isRotated() ? 1 : 0);
gui.add(orientationComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Orientation");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
final boolean b = orientationComboBox.getSelectedIndex() == 1;
boolean changed = b ^ s.isRotated();
if (rb1.isSelected()) {
if (changed) {
final RotateSolarPanelsForRackCommand c = new RotateSolarPanelsForRackCommand(r);
s.setRotated(orientationComboBox.getSelectedIndex() == 1);
r.ensureFullSolarPanels(false);
r.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (b ^ x.getSolarPanel().isRotated()) {
changed = true;
break;
}
}
}
if (changed) {
final RotateSolarPanelsForRacksOnFoundationCommand c = new RotateSolarPanelsForRacksOnFoundationCommand(foundation);
foundation.rotateSolarPanelsOnRacks(orientationComboBox.getSelectedIndex() == 1);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (b ^ x.getSolarPanel().isRotated()) {
changed = true;
break;
}
}
}
if (changed) {
final RotateSolarPanelsForAllRacksCommand c = new RotateSolarPanelsForAllRacksCommand();
Scene.getInstance().rotateSolarPanelsOnAllRacks(orientationComboBox.getSelectedIndex() == 1);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenuItem miInverterEfficiency = new JMenuItem("Inverter Efficiency...");
solarPanelMenu.add(miInverterEfficiency);
miInverterEfficiency.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack r = (Rack) selectedPart;
final Foundation foundation = r.getTopContainer();
final SolarPanel s = r.getSolarPanel();
final String title = "Set Inverter Efficiency (%) for " + r.toString().substring(0, r.toString().indexOf(')') + 1);
final String footnote = "<html><hr><font size=2>The efficiency of a micro inverter for converting electricity<br>from DC to AC is typically 95%.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout(5, 5));
final JTextField inputField = new JTextField(threeDecimalsFormat.format(s.getInverterEfficiency() * 100));
gui.add(inputField, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Inverter Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
try {
inverterEfficiencyPercentage = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (inverterEfficiencyPercentage < SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE || inverterEfficiencyPercentage > SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Inverter efficiency must be between " + SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE + "% and " + SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(inverterEfficiencyPercentage * 0.01 - s.getInverterEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetInverterEfficiencyForRackCommand c = new SetInverterEfficiencyForRackCommand(r);
s.setInverterEfficiency(inverterEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (Math.abs(inverterEfficiencyPercentage * 0.01 - x.getSolarPanel().getInverterEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetInverterEfficiencyForRacksOnFoundationCommand c = new SetInverterEfficiencyForRacksOnFoundationCommand(foundation);
foundation.setInverterEfficiencyForRacks(inverterEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (Math.abs(inverterEfficiencyPercentage * 0.01 - x.getSolarPanel().getInverterEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetInverterEfficiencyForAllRacksCommand c = new SetInverterEfficiencyForAllRacksCommand();
Scene.getInstance().setInverterEfficiencyForAllRacks(inverterEfficiencyPercentage * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final ButtonGroup trackerButtonGroup = new ButtonGroup();
final JRadioButtonMenuItem miNoTracker = new JRadioButtonMenuItem("No Tracker...", true);
trackerButtonGroup.add(miNoTracker);
miNoTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Remove tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>No tracker will be used.<hr></html>";
final Object[] params = { title, footnote, panel };
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), params, "Remove solar tracker", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
boolean changed = rack.getTracker() != Trackable.NO_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(rack, "No Tracker");
rack.setTracker(Trackable.NO_TRACKER);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTracker() != Trackable.NO_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, rack, "No Tracker for All Racks on Selected Foundation");
foundation.setTrackerForRacks(Trackable.NO_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTracker() != Trackable.NO_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(rack, "No Tracker for All Racks");
Scene.getInstance().setTrackerForAllRacks(Trackable.NO_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
}
});
final JRadioButtonMenuItem miHorizontalSingleAxisTracker = new JRadioButtonMenuItem("Horizontal Single-Axis Tracker...");
trackerButtonGroup.add(miHorizontalSingleAxisTracker);
miHorizontalSingleAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set horizontal single-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>A horizontal single-axis tracker (HSAT) rotates about the north-south axis<br>to follow the sun from east to west during the day.<hr></html>";
final Object[] params = { title, footnote, panel };
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), params, "Set horizontal single-axis solar tracker", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
boolean changed = rack.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(rack, "Horizontal Single-Axis Tracker");
rack.setTracker(Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, rack, "Horizontal Single-Axis Tracker for All Racks on Selected Foundation");
foundation.setTrackerForRacks(Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(rack, "Horizontal Single-Axis Tracker for All Racks");
Scene.getInstance().setTrackerForAllRacks(Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
}
});
final JRadioButtonMenuItem miVerticalSingleAxisTracker = new JRadioButtonMenuItem("Vertical Single-Axis Tracker...");
trackerButtonGroup.add(miVerticalSingleAxisTracker);
miVerticalSingleAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set vertical single-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>A vertical single-axis tracker (VSAT) rotates about an axis perpendicular to the ground<br>and follow the sun from east to west during the day.<hr></html>";
final Object[] params = { title, footnote, panel };
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), params, "Set vertical single-axis solar tracker", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
boolean changed = rack.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(rack, "Vertical Single-Axis Tracker");
rack.setTracker(Trackable.VERTICAL_SINGLE_AXIS_TRACKER);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, rack, "Vertical Single-Axis Tracker for All Racks on Selected Foundation");
foundation.setTrackerForRacks(Trackable.VERTICAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(rack, "Vertical Single-Axis Tracker for All Racks");
Scene.getInstance().setTrackerForAllRacks(Trackable.VERTICAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
}
});
final JRadioButtonMenuItem miTiltedSingleAxisTracker = new JRadioButtonMenuItem("Tilted Single-Axis Tracker...");
miTiltedSingleAxisTracker.setEnabled(false);
trackerButtonGroup.add(miTiltedSingleAxisTracker);
miTiltedSingleAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set tilted single-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>A tilted single-axis tracker (TSAT) rotates about an axis neither parallel nor perpendicular to the ground<br>and follow the sun from east to west during the day.<hr></html>";
final Object[] params = { title, footnote, panel };
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), params, "Set tilted single-axis solar tracker", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
boolean changed = rack.getTracker() != Trackable.TILTED_SINGLE_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(rack, "Tilted Single-Axis Tracker");
rack.setTracker(Trackable.TILTED_SINGLE_AXIS_TRACKER);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTracker() != Trackable.TILTED_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, rack, "Tilted Single-Axis Tracker for All Racks on Selected Foundation");
foundation.setTrackerForRacks(Trackable.TILTED_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTracker() != Trackable.TILTED_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(rack, "Tilted Single-Axis Tracker for All Racks");
Scene.getInstance().setTrackerForAllRacks(Trackable.TILTED_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
}
});
final JRadioButtonMenuItem miAltazimuthDualAxisTracker = new JRadioButtonMenuItem("Altazimuth Dual-Axis Tracker...");
trackerButtonGroup.add(miAltazimuthDualAxisTracker);
miAltazimuthDualAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final String partInfo = rack.toString().substring(0, rack.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set altitude-azimuth dual-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>The Alt/Az dual-axis solar tracker will rotate the solar panel to face the sun<br>all the time during the day.<hr></html>";
final Object[] params = { title, footnote, panel };
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), params, "Set altitude-azimuth dual-axis solar tracker", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
return;
}
boolean changed = rack.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(rack, "Dual-Axis Tracker");
rack.setTracker(Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER);
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = rack.getTopContainer();
if (!changed) {
for (final Rack x : foundation.getRacks()) {
if (x.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, rack, "Dual-Axis Tracker for All Racks on Selected Foundation");
foundation.setTrackerForRacks(Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Rack x : Scene.getInstance().getAllRacks()) {
if (x.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(rack, "Dual-Axis Tracker for All Racks");
Scene.getInstance().setTrackerForAllRacks(Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
}
});
trackerMenu.add(miNoTracker);
trackerMenu.add(miHorizontalSingleAxisTracker);
trackerMenu.add(miVerticalSingleAxisTracker);
trackerMenu.add(miTiltedSingleAxisTracker);
trackerMenu.add(miAltazimuthDualAxisTracker);
final JCheckBoxMenuItem cbmiDisableEditPoints = new JCheckBoxMenuItem("Disable Edit Points");
cbmiDisableEditPoints.addItemListener(new ItemListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final boolean disabled = cbmiDisableEditPoints.isSelected();
final Rack r = (Rack) selectedPart;
final String partInfo = r.toString().substring(0, r.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(0, 20));
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Rack", true);
final JRadioButton rb2 = new JRadioButton("All Racks on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Racks");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>" + (disabled ? "Disable" : "Enable") + " edit points for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Disable the edit points of a solar panel rack prevents it<br>from being unintentionally moved.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), (disabled ? "Disable" : "Enable") + " Edit Points");
dialog.setVisible(true);
if (optionPane.getValue() == options[0]) {
if (rb1.isSelected()) {
final LockEditPointsCommand c = new LockEditPointsCommand(r);
r.setLockEdit(disabled);
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = r.getTopContainer();
final LockEditPointsOnFoundationCommand c = new LockEditPointsOnFoundationCommand(foundation, r.getClass());
foundation.setLockEditForClass(disabled, r.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final LockEditPointsForClassCommand c = new LockEditPointsForClassCommand(r);
Scene.getInstance().setLockEditForClass(disabled, r.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
final JCheckBoxMenuItem cbmiDrawSunBeam = new JCheckBoxMenuItem("Draw Sun Beam");
cbmiDrawSunBeam.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final Rack rack = (Rack) selectedPart;
final ShowSunBeamCommand c = new ShowSunBeamCommand(rack);
rack.setSunBeamVisible(cbmiDrawSunBeam.isSelected());
rack.drawSunBeam();
rack.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
}
});
final JMenu labelMenu = new JMenu("Label");
final JCheckBoxMenuItem miLabelNone = new JCheckBoxMenuItem("None", true);
miLabelNone.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (miLabelNone.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.clearLabels();
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
}
});
labelMenu.add(miLabelNone);
final JCheckBoxMenuItem miLabelCustom = new JCheckBoxMenuItem("Custom");
miLabelCustom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelCustom(miLabelCustom.isSelected());
if (r.getLabelCustom()) {
r.setLabelCustomText(JOptionPane.showInputDialog(MainFrame.getInstance(), "Custom Text", r.getLabelCustomText()));
}
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCustom);
final JCheckBoxMenuItem miLabelId = new JCheckBoxMenuItem("ID");
miLabelId.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelId(miLabelId.isSelected());
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelId);
final JCheckBoxMenuItem miLabelCellEfficiency = new JCheckBoxMenuItem("Cell Efficiency");
miLabelCellEfficiency.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelCellEfficiency(miLabelCellEfficiency.isSelected());
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCellEfficiency);
final JCheckBoxMenuItem miLabelTiltAngle = new JCheckBoxMenuItem("Tilt Angle");
miLabelTiltAngle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelTiltAngle(miLabelTiltAngle.isSelected());
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelTiltAngle);
final JCheckBoxMenuItem miLabelTracker = new JCheckBoxMenuItem("Tracker");
miLabelTracker.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelTracker(miLabelTracker.isSelected());
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelTracker);
final JCheckBoxMenuItem miLabelEnergyOutput = new JCheckBoxMenuItem("Energy Output");
miLabelEnergyOutput.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Rack) {
final Rack r = (Rack) selectedPart;
final SetRackLabelCommand c = new SetRackLabelCommand(r);
r.setLabelEnergyOutput(miLabelEnergyOutput.isSelected());
r.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelEnergyOutput);
popupMenuForRack = createPopupMenu(true, true, new Runnable() {
@Override
public void run() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Rack)) {
return;
}
final HousePart copyBuffer = Scene.getInstance().getCopyBuffer();
miPaste.setEnabled(copyBuffer instanceof SolarPanel);
final Rack rack = (Rack) selectedPart;
switch(rack.getTracker()) {
case Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER:
Util.selectSilently(miAltazimuthDualAxisTracker, true);
break;
case Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER:
Util.selectSilently(miHorizontalSingleAxisTracker, true);
break;
case Trackable.VERTICAL_SINGLE_AXIS_TRACKER:
Util.selectSilently(miVerticalSingleAxisTracker, true);
break;
case Trackable.TILTED_SINGLE_AXIS_TRACKER:
Util.selectSilently(miTiltedSingleAxisTracker, true);
break;
case Trackable.NO_TRACKER:
Util.selectSilently(miNoTracker, true);
break;
}
miAltazimuthDualAxisTracker.setEnabled(true);
miHorizontalSingleAxisTracker.setEnabled(true);
miVerticalSingleAxisTracker.setEnabled(true);
if (rack.getContainer() instanceof Roof) {
final Roof roof = (Roof) rack.getContainer();
final boolean flat = Util.isZero(roof.getHeight());
miAltazimuthDualAxisTracker.setEnabled(flat);
miHorizontalSingleAxisTracker.setEnabled(flat);
miVerticalSingleAxisTracker.setEnabled(flat);
}
if (rack.getTracker() != Trackable.NO_TRACKER) {
// vertical and tilted single-axis trackers can adjust the tilt angle
miFixedTiltAngle.setEnabled(rack.getTracker() == Trackable.VERTICAL_SINGLE_AXIS_TRACKER || rack.getTracker() == Trackable.TILTED_SINGLE_AXIS_TRACKER);
miSeasonalTiltAngle.setEnabled(miFixedTiltAngle.isEnabled());
// any tracker that will alter the azimuth angle should disable the menu item
miAzimuth.setEnabled(rack.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER && rack.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER);
miRotate.setEnabled(miAzimuth.isEnabled());
} else {
miFixedTiltAngle.setEnabled(true);
miSeasonalTiltAngle.setEnabled(true);
miAzimuth.setEnabled(true);
miRotate.setEnabled(true);
miBaseHeight.setEnabled(true);
miPoleSpacing.setEnabled(true);
if (rack.getContainer() instanceof Roof) {
final Roof roof = (Roof) rack.getContainer();
if (roof.getHeight() > 0) {
miFixedTiltAngle.setEnabled(false);
miSeasonalTiltAngle.setEnabled(false);
miAzimuth.setEnabled(false);
miBaseHeight.setEnabled(false);
miPoleSpacing.setEnabled(false);
miRotate.setEnabled(false);
}
}
}
Util.selectSilently(cbmiDisableEditPoints, rack.getLockEdit());
Util.selectSilently(cbmiDrawSunBeam, rack.isSunBeamVisible());
Util.selectSilently(miLabelNone, !rack.isLabelVisible());
Util.selectSilently(miLabelCustom, rack.getLabelCustom());
Util.selectSilently(miLabelId, rack.getLabelId());
Util.selectSilently(miLabelCellEfficiency, rack.getLabelCellEfficiency());
Util.selectSilently(miLabelTiltAngle, rack.getLabelTiltAngle());
Util.selectSilently(miLabelTracker, rack.getLabelTracker());
Util.selectSilently(miLabelEnergyOutput, rack.getLabelEnergyOutput());
final boolean isCustom = "Custom".equals(rack.getSolarPanel().getModelName());
miSolarPanelCellEfficiency.setEnabled(isCustom);
miSolarPanelCellType.setEnabled(isCustom);
miSolarPanelColor.setEnabled(isCustom);
miSolarPanelSize.setEnabled(isCustom);
miSolarPanelShadeTolerance.setEnabled(isCustom);
miSolarPanelNoct.setEnabled(isCustom);
miSolarPanelPmaxTc.setEnabled(isCustom);
}
});
popupMenuForRack.add(miPaste);
popupMenuForRack.add(miClear);
popupMenuForRack.addSeparator();
popupMenuForRack.add(miSolarPanels);
popupMenuForRack.add(solarPanelMenu);
popupMenuForRack.addSeparator();
popupMenuForRack.add(miFixedTiltAngle);
popupMenuForRack.add(miSeasonalTiltAngle);
popupMenuForRack.add(miAzimuth);
popupMenuForRack.add(miRotate);
popupMenuForRack.add(miRackWidth);
popupMenuForRack.add(miRackLength);
popupMenuForRack.add(miBaseHeight);
popupMenuForRack.add(miPoleSpacing);
popupMenuForRack.add(trackerMenu);
popupMenuForRack.addSeparator();
popupMenuForRack.add(cbmiDisableEditPoints);
popupMenuForRack.add(cbmiDrawSunBeam);
popupMenuForRack.add(labelMenu);
popupMenuForRack.addSeparator();
JMenuItem mi = new JMenuItem("Daily Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof Rack) {
new PvDailyAnalysis().show();
}
}
});
popupMenuForRack.add(mi);
mi = new JMenuItem("Annual Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof Rack) {
new PvAnnualAnalysis().show();
}
}
});
popupMenuForRack.add(mi);
}
return popupMenuForRack;
}
use of org.concord.energy3d.model.HousePart in project energy3d by concord-consortium.
the class PopupMenuForSolarPanel method getPopupMenu.
static JPopupMenu getPopupMenu() {
if (popupMenuForSolarPanel == null) {
final JMenu trackerMenu = new JMenu("Tracker");
final JMenu shadeToleranceMenu = new JMenu("Shade Tolerance");
final ButtonGroup shadeToleranceButtonGroup = new ButtonGroup();
final JRadioButtonMenuItem miHighTolerance = new JRadioButtonMenuItem("High Tolerance...");
shadeToleranceButtonGroup.add(miHighTolerance);
miHighTolerance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Choose shade tolerance level for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>The energy generated by this panel comes from each cell proportionally (ideal case).<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "High Shade Tolerance");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getShadeTolerance() != SolarPanel.HIGH_SHADE_TOLERANCE;
if (rb1.isSelected()) {
if (changed) {
final SetShadeToleranceCommand c = new SetShadeToleranceCommand(sp);
sp.setShadeTolerance(SolarPanel.HIGH_SHADE_TOLERANCE);
sp.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.HIGH_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForSolarPanelsOnFoundationCommand c = new SetShadeToleranceForSolarPanelsOnFoundationCommand(foundation);
foundation.setShadeToleranceForSolarPanels(SolarPanel.HIGH_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.HIGH_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForAllSolarPanelsCommand c = new SetShadeToleranceForAllSolarPanelsCommand();
Scene.getInstance().setShadeToleranceForAllSolarPanels(SolarPanel.HIGH_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JRadioButtonMenuItem miPartialTolerance = new JRadioButtonMenuItem("Partial Tolerance...", true);
shadeToleranceButtonGroup.add(miPartialTolerance);
miPartialTolerance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Choose shade tolerance level for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Use bypass diodes to direct current under shading conditions.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Partial Shade Tolerance");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getShadeTolerance() != SolarPanel.PARTIAL_SHADE_TOLERANCE;
if (rb1.isSelected()) {
if (changed) {
final SetShadeToleranceCommand c = new SetShadeToleranceCommand(sp);
sp.setShadeTolerance(SolarPanel.PARTIAL_SHADE_TOLERANCE);
sp.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.PARTIAL_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForSolarPanelsOnFoundationCommand c = new SetShadeToleranceForSolarPanelsOnFoundationCommand(foundation);
foundation.setShadeToleranceForSolarPanels(SolarPanel.PARTIAL_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.PARTIAL_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForAllSolarPanelsCommand c = new SetShadeToleranceForAllSolarPanelsCommand();
Scene.getInstance().setShadeToleranceForAllSolarPanels(SolarPanel.PARTIAL_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JRadioButtonMenuItem miNoTolerance = new JRadioButtonMenuItem("No Tolerance...");
shadeToleranceButtonGroup.add(miNoTolerance);
miNoTolerance.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Choose shade tolerance level for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Shading greatly reduces the output of the entire panel.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "No Shade Tolerance");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getShadeTolerance() != SolarPanel.NO_SHADE_TOLERANCE;
if (rb1.isSelected()) {
if (changed) {
final SetShadeToleranceCommand c = new SetShadeToleranceCommand(sp);
sp.setShadeTolerance(SolarPanel.NO_SHADE_TOLERANCE);
sp.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.NO_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForSolarPanelsOnFoundationCommand c = new SetShadeToleranceForSolarPanelsOnFoundationCommand(foundation);
foundation.setShadeToleranceForSolarPanels(SolarPanel.NO_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getShadeTolerance() != SolarPanel.NO_SHADE_TOLERANCE) {
changed = true;
break;
}
}
}
if (changed) {
final SetShadeToleranceForAllSolarPanelsCommand c = new SetShadeToleranceForAllSolarPanelsCommand();
Scene.getInstance().setShadeToleranceForAllSolarPanels(SolarPanel.NO_SHADE_TOLERANCE);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final ButtonGroup trackerButtonGroup = new ButtonGroup();
final JRadioButtonMenuItem miNoTracker = new JRadioButtonMenuItem("No Tracker...", true);
trackerButtonGroup.add(miNoTracker);
miNoTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Remove tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>No tracker will be used.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "No Tracker");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getTracker() != Trackable.NO_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(sp, "No Tracker");
sp.setTracker(Trackable.NO_TRACKER);
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getTracker() != Trackable.NO_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, sp, "No Tracker for All Solar Panels on Selected Foundation");
foundation.setTrackerForSolarPanels(Trackable.NO_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getTracker() != Trackable.NO_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(sp, "No Tracker for All Solar Panels");
Scene.getInstance().setTrackerForAllSolarPanels(Trackable.NO_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JRadioButtonMenuItem miHorizontalSingleAxisTracker = new JRadioButtonMenuItem("Horizontal Single-Axis Tracker...");
trackerButtonGroup.add(miHorizontalSingleAxisTracker);
miHorizontalSingleAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set horizontal single-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>A horizontal single-axis tracker (HSAT) rotates about the north-south axis<br>to follow the sun from east to west during the day.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Horizontal Single-Axis Tracker");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(sp, "Horizontal Single-Axis Tracker");
sp.setTracker(SolarPanel.HORIZONTAL_SINGLE_AXIS_TRACKER);
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, sp, "Horizontal Single-Axis Tracker for All Solar Panels on Selected Foundation");
foundation.setTrackerForSolarPanels(SolarPanel.HORIZONTAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getTracker() != Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(sp, "Horizontal Single-Axis Tracker for All Solar Panels");
Scene.getInstance().setTrackerForAllSolarPanels(SolarPanel.HORIZONTAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JRadioButtonMenuItem miVerticalSingleAxisTracker = new JRadioButtonMenuItem("Vertical Single-Axis Tracker...");
trackerButtonGroup.add(miVerticalSingleAxisTracker);
miVerticalSingleAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set vertical single-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>A vertical single-axis tracker (VSAT) rotates about an axis perpendicular to the ground<br>and follow the sun from east to west during the day.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Vertical Single-Axis Tracker");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(sp, "Vertical Single-Axis Tracker");
sp.setTracker(SolarPanel.VERTICAL_SINGLE_AXIS_TRACKER);
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, sp, "Vertical Single-Axis Tracker for All Solar Panels on Selected Foundation");
foundation.setTrackerForSolarPanels(SolarPanel.VERTICAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(sp, "Vertical Single-Axis Tracker for All Solar Panels");
Scene.getInstance().setTrackerForAllSolarPanels(SolarPanel.VERTICAL_SINGLE_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JRadioButtonMenuItem miAltazimuthDualAxisTracker = new JRadioButtonMenuItem("Altazimuth Dual-Axis Tracker...");
trackerButtonGroup.add(miAltazimuthDualAxisTracker);
miAltazimuthDualAxisTracker.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>Set altitude-azimuth dual-axis tracker for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>The Alt/Az dual-axis solar tracker will rotate the solar panel to face the sun<br>all the time during the day.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, panel }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Altitude-Azimuth Dual-Axis Tracker");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = sp.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER;
if (rb1.isSelected()) {
if (changed) {
final SetSolarTrackerCommand c = new SetSolarTrackerCommand(sp, "Dual-Axis Tracker");
sp.setTracker(SolarPanel.ALTAZIMUTH_DUAL_AXIS_TRACKER);
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (x.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersOnFoundationCommand c = new SetSolarTrackersOnFoundationCommand(foundation, sp, "Dual-Axis Tracker for All Solar Panels on Selected Foundation");
foundation.setTrackerForSolarPanels(SolarPanel.ALTAZIMUTH_DUAL_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (x.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER) {
changed = true;
break;
}
}
}
if (changed) {
final SetSolarTrackersForAllCommand c = new SetSolarTrackersForAllCommand(sp, "Dual-Axis Tracker for All Solar Panels");
Scene.getInstance().setTrackerForAllSolarPanels(SolarPanel.ALTAZIMUTH_DUAL_AXIS_TRACKER);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
final JMenu orientationMenu = new JMenu("Orientation");
final ButtonGroup orientationGroup = new ButtonGroup();
final JRadioButtonMenuItem rbmiLandscape = new JRadioButtonMenuItem("Landscape");
rbmiLandscape.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (rbmiLandscape.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel s = (SolarPanel) selectedPart;
if (!s.isRotated()) {
final RotateSolarPanelCommand c = new RotateSolarPanelCommand(s);
s.setRotated(true);
SceneManager.getInstance().getUndoManager().addEdit(c);
s.draw();
SceneManager.getInstance().refresh();
updateAfterEdit();
}
}
}
});
orientationMenu.add(rbmiLandscape);
orientationGroup.add(rbmiLandscape);
final JRadioButtonMenuItem rbmiPortrait = new JRadioButtonMenuItem("Portrait", true);
rbmiPortrait.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (rbmiPortrait.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel s = (SolarPanel) selectedPart;
if (s.isRotated()) {
final RotateSolarPanelCommand c = new RotateSolarPanelCommand(s);
s.setRotated(false);
SceneManager.getInstance().getUndoManager().addEdit(c);
s.draw();
SceneManager.getInstance().refresh();
updateAfterEdit();
}
}
}
});
orientationMenu.add(rbmiPortrait);
orientationGroup.add(rbmiPortrait);
final JMenu labelMenu = new JMenu("Label");
final JCheckBoxMenuItem miLabelNone = new JCheckBoxMenuItem("None", true);
miLabelNone.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (miLabelNone.isSelected()) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.clearLabels();
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
}
});
labelMenu.add(miLabelNone);
final JCheckBoxMenuItem miLabelCustom = new JCheckBoxMenuItem("Custom");
miLabelCustom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelCustom(miLabelCustom.isSelected());
if (s.getLabelCustom()) {
s.setLabelCustomText(JOptionPane.showInputDialog(MainFrame.getInstance(), "Custom Text", s.getLabelCustomText()));
}
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCustom);
final JCheckBoxMenuItem miLabelId = new JCheckBoxMenuItem("ID");
miLabelId.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelId(miLabelId.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelId);
final JCheckBoxMenuItem miLabelModelName = new JCheckBoxMenuItem("Model");
miLabelModelName.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelModelName(miLabelModelName.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelModelName);
final JCheckBoxMenuItem miLabelCellEfficiency = new JCheckBoxMenuItem("Cell Efficiency");
miLabelCellEfficiency.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelCellEfficiency(miLabelCellEfficiency.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelCellEfficiency);
final JCheckBoxMenuItem miLabelTiltAngle = new JCheckBoxMenuItem("Tilt Angle");
miLabelTiltAngle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelTiltAngle(miLabelTiltAngle.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelTiltAngle);
final JCheckBoxMenuItem miLabelTracker = new JCheckBoxMenuItem("Tracker");
miLabelTracker.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelTracker(miLabelTracker.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelTracker);
final JCheckBoxMenuItem miLabelEnergyOutput = new JCheckBoxMenuItem("Energy Output");
miLabelEnergyOutput.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof SolarPanel) {
final SolarPanel s = (SolarPanel) selectedPart;
final SetSolarPanelLabelCommand c = new SetSolarPanelLabelCommand(s);
s.setLabelEnergyOutput(miLabelEnergyOutput.isSelected());
s.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
}
});
labelMenu.add(miLabelEnergyOutput);
final JMenuItem miTiltAngle = new JMenuItem("Tilt Angle...");
miTiltAngle.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final SolarPanel sp = (SolarPanel) selectedPart;
final String title = "<html>Tilt Angle of " + partInfo + " (°)</html>";
final String footnote = "<html><hr><font size=2>The tilt angle of a solar panel is the angle between its surface and the base surface.<br>The tilt angle must be between -90° and 90°.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("Only this Row", true);
final JRadioButton rb3 = new JRadioButton("All Solar Panels on This Foundation");
final JRadioButton rb4 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
panel.add(rb4);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
bg.add(rb4);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
case 3:
rb4.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(sp.getTiltAngle()));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Tilt Angle");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < -90 || val > 90) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "The tilt angle must be between -90 and 90 degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
if (Util.isZero(val - 90)) {
val = 89.999;
} else if (Util.isZero(val + 90)) {
val = -89.999;
}
boolean changed = Math.abs(val - sp.getTiltAngle()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeTiltAngleCommand c = new ChangeTiltAngleCommand(sp);
sp.setTiltAngle(val);
sp.draw();
if (sp.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This tilt angle cannot be set as the solar panel would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final List<SolarPanel> row = sp.getRow();
if (!changed) {
for (final SolarPanel x : row) {
if (Math.abs(val - x.getTiltAngle()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeTiltAngleForSolarPanelRowCommand c = new ChangeTiltAngleForSolarPanelRowCommand(row);
boolean intersected = false;
for (final SolarPanel x : row) {
x.setTiltAngle(val);
x.draw();
if (x.checkContainerIntersection()) {
intersected = true;
break;
}
}
SceneManager.getInstance().refresh();
if (intersected) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This tilt angle cannot be set as one or more solar panels would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final Foundation foundation = sp.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (Math.abs(val - x.getTiltAngle()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarPanelTiltAngleCommand c = new ChangeFoundationSolarPanelTiltAngleCommand(foundation);
foundation.setTiltAngleForSolarPanels(val);
if (foundation.checkContainerIntersectionForSolarPanels()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This tilt angle cannot be set as one or more solar panels would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
} else if (rb4.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (Math.abs(val - x.getTiltAngle()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeTiltAngleForAllSolarPanelsCommand c = new ChangeTiltAngleForAllSolarPanelsCommand();
Scene.getInstance().setTiltAngleForAllSolarPanels(val);
if (Scene.getInstance().checkContainerIntersectionForAllSolarPanels()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This tilt angle cannot be set as one or more solar panels would cut into the underlying surface.", "Illegal Tilt Angle", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 3;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miAzimuth = new JMenuItem("Azimuth...");
miAzimuth.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final SolarPanel sp = (SolarPanel) selectedPart;
final Foundation foundation = sp.getTopContainer();
final String title = "<html>Azimuth Angle of " + partInfo + " (°)</html>";
final String footnote = "<html><hr><font size=2>The azimuth angle is measured clockwise from the true north.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
double a = sp.getRelativeAzimuth() + foundation.getAzimuth();
if (a > 360) {
a -= 360;
}
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(a));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Azimuth");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
a = val - foundation.getAzimuth();
if (a < 0) {
a += 360;
}
boolean changed = Math.abs(a - sp.getRelativeAzimuth()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeAzimuthCommand c = new ChangeAzimuthCommand(sp);
sp.setRelativeAzimuth(a);
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (Math.abs(a - x.getRelativeAzimuth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarPanelAzimuthCommand c = new ChangeFoundationSolarPanelAzimuthCommand(foundation);
foundation.setAzimuthForSolarPanels(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (Math.abs(a - x.getRelativeAzimuth()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeAzimuthForAllSolarPanelsCommand c = new ChangeAzimuthForAllSolarPanelsCommand();
Scene.getInstance().setAzimuthForAllSolarPanels(a);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JMenuItem miSize = new JMenuItem("Size...");
miSize.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel s = (SolarPanel) selectedPart;
final String partInfo = s.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Choose Size for " + partInfo));
final JComboBox<String> sizeComboBox = new JComboBox<String>(solarPanelNominalSize.getStrings());
final int nItems = sizeComboBox.getItemCount();
for (int i = 0; i < nItems; i++) {
if (Util.isZero(s.getPanelHeight() - solarPanelNominalSize.getNominalHeights()[i]) && Util.isZero(s.getPanelWidth() - solarPanelNominalSize.getNominalWidths()[i])) {
sizeComboBox.setSelectedIndex(i);
}
}
gui.add(sizeComboBox, BorderLayout.NORTH);
if (JOptionPane.showConfirmDialog(MainFrame.getInstance(), gui, "Set Size", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.CANCEL_OPTION) {
return;
}
final int i = sizeComboBox.getSelectedIndex();
boolean changed = s.getNumberOfCellsInX() != solarPanelNominalSize.getCellNx()[i] || s.getNumberOfCellsInY() != solarPanelNominalSize.getCellNy()[i];
if (!changed) {
if (Math.abs(s.getPanelWidth() - solarPanelNominalSize.getNominalWidths()[i]) > 0.000001 || Math.abs(s.getPanelHeight() - solarPanelNominalSize.getNominalHeights()[i]) > 0.000001) {
changed = true;
}
}
if (changed) {
final ChooseSolarPanelSizeCommand c = new ChooseSolarPanelSizeCommand(s);
s.setPanelWidth(solarPanelNominalSize.getNominalWidths()[i]);
s.setPanelHeight(solarPanelNominalSize.getNominalHeights()[i]);
s.setNumberOfCellsInX(solarPanelNominalSize.getCellNx()[i]);
s.setNumberOfCellsInY(solarPanelNominalSize.getCellNy()[i]);
s.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
updateAfterEdit();
}
}
});
final JMenuItem miBaseHeight = new JMenuItem("Base Height...");
miBaseHeight.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final SolarPanel sp = (SolarPanel) selectedPart;
final Foundation foundation = sp.getTopContainer();
final String title = "<html>Base Height (m) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("Only this Row");
final JRadioButton rb3 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb4 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
panel.add(rb4);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
bg.add(rb4);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
case 3:
rb4.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(sp.getBaseHeight() * Scene.getInstance().getAnnotationScale()));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Base Height");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText()) / Scene.getInstance().getAnnotationScale();
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
boolean changed = Math.abs(val - sp.getBaseHeight()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeBaseHeightCommand c = new ChangeBaseHeightCommand(sp);
sp.setBaseHeight(val);
sp.draw();
if (sp.checkContainerIntersection()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This base height cannot be set as the solar panel would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final List<SolarPanel> row = sp.getRow();
for (final SolarPanel x : row) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
if (changed) {
final ChangeBaseHeightForSolarPanelRowCommand c = new ChangeBaseHeightForSolarPanelRowCommand(row);
boolean intersected = false;
for (final SolarPanel x : row) {
x.setBaseHeight(val);
x.draw();
if (x.checkContainerIntersection()) {
intersected = true;
break;
}
}
if (intersected) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This base height cannot be set as one or more solar panels in the row would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
if (changed) {
final ChangeFoundationSolarCollectorBaseHeightCommand c = new ChangeFoundationSolarCollectorBaseHeightCommand(foundation, sp.getClass());
foundation.setBaseHeightForSolarPanels(val);
if (foundation.checkContainerIntersectionForSolarPanels()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This base height cannot be set as one or more solar panels would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 2;
} else if (rb4.isSelected()) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (Math.abs(val - x.getBaseHeight()) > 0.000001) {
changed = true;
break;
}
}
if (changed) {
final ChangeBaseHeightForAllSolarCollectorsCommand c = new ChangeBaseHeightForAllSolarCollectorsCommand(sp.getClass());
Scene.getInstance().setBaseHeightForAllSolarPanels(val);
if (Scene.getInstance().checkContainerIntersectionForAllSolarPanels()) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "This base height cannot be set as one or more solar panels would cut into the underlying surface.", "Illegal Base Height", JOptionPane.ERROR_MESSAGE);
c.undo();
} else {
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
selectedScopeIndex = 3;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
});
final JCheckBoxMenuItem cbmiDisableEditPoint = new JCheckBoxMenuItem("Disable Edit Point");
cbmiDisableEditPoint.addItemListener(new ItemListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final boolean disabled = cbmiDisableEditPoint.isSelected();
final SolarPanel sp = (SolarPanel) selectedPart;
final String partInfo = sp.toString().substring(0, sp.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout(0, 20));
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final String title = "<html>" + (disabled ? "Disable" : "Enable") + " edit point for " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Disable the edit point of a solar panel prevents it<br>from being unintentionally moved.<hr></html>";
final Object[] options = new Object[] { "OK", "Cancel" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[0]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), (disabled ? "Disable" : "Enable") + " Edit Point");
dialog.setVisible(true);
if (optionPane.getValue() == options[0]) {
if (rb1.isSelected()) {
final LockEditPointsCommand c = new LockEditPointsCommand(sp);
sp.setLockEdit(disabled);
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = sp.getTopContainer();
final LockEditPointsOnFoundationCommand c = new LockEditPointsOnFoundationCommand(foundation, sp.getClass());
foundation.setLockEditForClass(disabled, sp.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final LockEditPointsForClassCommand c = new LockEditPointsForClassCommand(sp);
Scene.getInstance().setLockEditForClass(disabled, sp.getClass());
SceneManager.getInstance().getUndoManager().addEdit(c);
selectedScopeIndex = 2;
}
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
final JCheckBoxMenuItem cbmiDrawSunBeam = new JCheckBoxMenuItem("Draw Sun Beam");
cbmiDrawSunBeam.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
final ShowSunBeamCommand c = new ShowSunBeamCommand(sp);
sp.setSunBeamVisible(cbmiDrawSunBeam.isSelected());
sp.drawSunBeam();
sp.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
Scene.getInstance().setEdited(true);
}
});
final JMenuItem miCells = new JMenuItem("Solar Cells...");
miCells.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel solarPanel = (SolarPanel) selectedPart;
final String title = "<html>Solar Cell Properties of " + selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1) + "</html>";
String footnote = "<html><hr><font size=2><b>How efficiently can a solar cell convert light into electricity?</b><br>The Shockley-Queisser limit is 34%. The theoretical limit for multilayer cells<br>is 86%. As of 2017, the best solar panel in the market has an efficiency of 24%.<br>The highest efficiency you can choose is limited to " + SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "%.<hr>";
footnote += "<font size=2>Solar cells made of monocrystalline silicon are usually round or semi-round.<br>Hence, there is a small fraction of area on a solar panel not covered by cells.<br>In other words, a monocrystalline solar panel has a smaller packing density.";
footnote += "<br><font size=2>Solar cells made of polycrystalline silicon are usually square. Compared with a<br>monocrystalline solar panel, a polycrystalline one has a higher packing density.<br>Color has no relationship with efficiency.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final JPanel inputPanel = new JPanel(new SpringLayout());
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
JLabel label = new JLabel("Type: ", JLabel.LEFT);
inputPanel.add(label);
final JComboBox<String> typeComboBox = new JComboBox<String>(new String[] { "Polycrystalline", "Monocrystalline", "Thin Film" });
typeComboBox.setSelectedIndex(solarPanel.getCellType());
label.setLabelFor(typeComboBox);
inputPanel.add(typeComboBox);
label = new JLabel("Color: ", JLabel.LEFT);
inputPanel.add(label);
final JComboBox<String> colorComboBox = new JComboBox<String>(new String[] { "Blue", "Black", "Gray" });
colorComboBox.setSelectedIndex(solarPanel.getColorOption());
label.setLabelFor(colorComboBox);
inputPanel.add(colorComboBox);
label = new JLabel("Efficiency (%): ", JLabel.LEFT);
inputPanel.add(label);
final JTextField efficiencyField = new JTextField(EnergyPanel.TWO_DECIMALS.format(solarPanel.getCellEfficiency() * 100));
label.setLabelFor(efficiencyField);
inputPanel.add(efficiencyField);
SpringUtilities.makeCompactGrid(inputPanel, 3, 2, 6, 6, 6, 6);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Cell Properties");
while (true) {
efficiencyField.selectAll();
efficiencyField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(efficiencyField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), efficiencyField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE || val > SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Solar cell efficiency must be between " + SolarPanel.MIN_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "% and " + SolarPanel.MAX_SOLAR_CELL_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
final int cellType = typeComboBox.getSelectedIndex();
final int colorOption = colorComboBox.getSelectedIndex();
boolean changed = cellType != solarPanel.getCellType() || colorOption != solarPanel.getColorOption() || Math.abs(val * 0.01 - solarPanel.getCellEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarCellPropertiesCommand c = new ChangeSolarCellPropertiesCommand(solarPanel);
solarPanel.setCellEfficiency(val * 0.01);
solarPanel.setCellType(cellType);
solarPanel.setColorOption(colorOption);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = solarPanel.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (cellType != x.getCellType() || colorOption != x.getColorOption() || Math.abs(val * 0.01 - x.getCellEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarCellPropertiesCommand c = new ChangeFoundationSolarCellPropertiesCommand(foundation);
foundation.setSolarCellEfficiency(val * 0.01);
foundation.setCellTypeForSolarPanels(cellType);
foundation.setColorForSolarPanels(colorOption);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (cellType != x.getCellType() || colorOption != x.getColorOption() || Math.abs(val * 0.01 - x.getCellEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeSolarCellPropertiesForAllCommand c = new ChangeSolarCellPropertiesForAllCommand();
Scene.getInstance().setSolarCellEfficiencyForAll(val * 0.01);
Scene.getInstance().setCellTypeForAllSolarPanels(cellType);
Scene.getInstance().setColorForAllSolarPanels(colorOption);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miTemperatureEffects = new JMenuItem("Temperature Effects...");
miTemperatureEffects.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final SolarPanel solarPanel = (SolarPanel) selectedPart;
final String title = "<html>Temperature Effects of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Increased temperature reduces solar cell efficiency. To determine this temperature effect,<br>it is important to know the expected operating temperature: the Nominal Operating Cell<br>Temperature (NOCT). NOCT ranges from 33°C to 58°C.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.SOUTH);
final JPanel inputPanel = new JPanel(new SpringLayout());
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JLabel label = new JLabel("<html>Nominal Operating Cell Temperature (°C): ", JLabel.LEFT);
inputPanel.add(label);
final JTextField noctField = new JTextField(EnergyPanel.TWO_DECIMALS.format(solarPanel.getNominalOperatingCellTemperature()));
label.setLabelFor(noctField);
inputPanel.add(noctField);
label = new JLabel("<html>Temperature Coefficient of Pmax (%/°C): ", JLabel.LEFT);
inputPanel.add(label);
final JTextField pmaxField = new JTextField(EnergyPanel.TWO_DECIMALS.format(solarPanel.getTemperatureCoefficientPmax() * 100));
label.setLabelFor(pmaxField);
inputPanel.add(pmaxField);
SpringUtilities.makeCompactGrid(inputPanel, 2, 2, 6, 6, 6, 6);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Temperature Effects");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double noct = 0;
double pmax = 0;
boolean ok = true;
try {
noct = Double.parseDouble(noctField.getText());
pmax = Double.parseDouble(pmaxField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (noct < 33 || noct > 58) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Nominal Operating Cell Temperature must be between 33 and 58 Celsius degrees.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (pmax < -1 || pmax > 0) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Temperature coefficient of Pmax must be between -1% and 0% per Celsius degree.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(noct - solarPanel.getNominalOperatingCellTemperature()) > 0.000001 || Math.abs(pmax * 0.01 - solarPanel.getTemperatureCoefficientPmax()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetTemperatureEffectsCommand c = new SetTemperatureEffectsCommand(solarPanel);
solarPanel.setTemperatureCoefficientPmax(pmax * 0.01);
solarPanel.setNominalOperatingCellTemperature(noct);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = solarPanel.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (Math.abs(noct - x.getNominalOperatingCellTemperature()) > 0.000001 || Math.abs(pmax * 0.01 - x.getTemperatureCoefficientPmax()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetFoundationTemperatureEffectsCommand c = new SetFoundationTemperatureEffectsCommand(foundation);
foundation.setTemperatureCoefficientPmax(pmax * 0.01);
foundation.setNominalOperatingCellTemperature(noct);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (Math.abs(noct - x.getNominalOperatingCellTemperature()) > 0.000001 || Math.abs(pmax * 0.01 - x.getTemperatureCoefficientPmax()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetTemperatrureEffectsForAllCommand c = new SetTemperatrureEffectsForAllCommand();
Scene.getInstance().setTemperatureCoefficientPmaxForAll(pmax * 0.01);
Scene.getInstance().setNominalOperatingCellTemperatureForAll(noct);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miInverterEff = new JMenuItem("Inverter Efficiency...");
miInverterEff.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final SolarPanel solarPanel = (SolarPanel) selectedPart;
final String title = "<html>Inverter Efficiency (%) of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>The efficiency of a micro inverter for converting electricity from DC to AC is typically 95%.<hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
gui.add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(EnergyPanel.TWO_DECIMALS.format(solarPanel.getInverterEfficiency() * 100));
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Inverter Efficiency");
while (true) {
inputField.selectAll();
inputField.requestFocusInWindow();
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
double val = 0;
boolean ok = true;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE || val >= SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Inverter efficiency must be greater than " + SolarPanel.MIN_INVERTER_EFFICIENCY_PERCENTAGE + "% and less than " + SolarPanel.MAX_INVERTER_EFFICIENCY_PERCENTAGE + "%.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val * 0.01 - solarPanel.getInverterEfficiency()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeInverterEfficiencyCommand c = new ChangeInverterEfficiencyCommand(solarPanel);
solarPanel.setInverterEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
final Foundation foundation = solarPanel.getTopContainer();
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (Math.abs(val * 0.01 - x.getInverterEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationInverterEfficiencyCommand c = new ChangeFoundationInverterEfficiencyCommand(foundation);
foundation.setSolarPanelInverterEfficiency(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (Math.abs(val * 0.01 - x.getInverterEfficiency()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeInverterEfficiencyForAllCommand c = new ChangeInverterEfficiencyForAllCommand();
Scene.getInstance().setSolarPanelInverterEfficiencyForAll(val * 0.01);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
trackerMenu.add(miNoTracker);
trackerMenu.add(miHorizontalSingleAxisTracker);
trackerMenu.add(miVerticalSingleAxisTracker);
trackerMenu.add(miAltazimuthDualAxisTracker);
shadeToleranceMenu.add(miNoTolerance);
shadeToleranceMenu.add(miPartialTolerance);
shadeToleranceMenu.add(miHighTolerance);
final JMenuItem miModel = new JMenuItem("Model...");
miModel.addActionListener(new ActionListener() {
private String modelName;
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel s = (SolarPanel) selectedPart;
final Foundation foundation = s.getTopContainer();
final String partInfo = s.toString().substring(0, s.toString().indexOf(')') + 1);
final Map<String, PvModuleSpecs> modules = PvModulesData.getInstance().getModules();
final String[] models = new String[modules.size() + 1];
int i = 0;
models[i] = "Custom";
for (final String key : modules.keySet()) {
models[++i] = key;
}
final PvModuleSpecs specs = s.getPvModuleSpecs();
modelName = specs.getModel();
final JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(BorderFactory.createTitledBorder("Model for " + partInfo));
final JComboBox<String> typeComboBox = new JComboBox<String>(models);
typeComboBox.setSelectedItem(specs.getModel());
typeComboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
modelName = (String) typeComboBox.getSelectedItem();
}
}
});
gui.add(typeComboBox, BorderLayout.NORTH);
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Solar Panel", true);
final JRadioButton rb2 = new JRadioButton("All Solar Panels on this Foundation");
final JRadioButton rb3 = new JRadioButton("All Solar Panels");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.CENTER);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(gui, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Panel Model");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = !modelName.equals(s.getModelName());
if (rb1.isSelected()) {
if (changed) {
final ChangeSolarPanelModelCommand c = new ChangeSolarPanelModelCommand(s);
s.setPvModuleSpecs(PvModulesData.getInstance().getModuleSpecs(modelName));
s.draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
for (final SolarPanel x : foundation.getSolarPanels()) {
if (!modelName.equals(x.getModelName())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeFoundationSolarPanelModelCommand c = new ChangeFoundationSolarPanelModelCommand(foundation);
foundation.setModelForSolarPanels(PvModulesData.getInstance().getModuleSpecs(modelName));
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final SolarPanel x : Scene.getInstance().getAllSolarPanels()) {
if (!modelName.equals(x.getModelName())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeModelForAllSolarPanelsCommand c = new ChangeModelForAllSolarPanelsCommand();
Scene.getInstance().setModelForAllSolarPanels(PvModulesData.getInstance().getModuleSpecs(modelName));
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
});
popupMenuForSolarPanel = createPopupMenu(true, true, new Runnable() {
@Override
public void run() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
final SolarPanel sp = (SolarPanel) selectedPart;
switch(sp.getShadeTolerance()) {
case SolarPanel.HIGH_SHADE_TOLERANCE:
Util.selectSilently(miHighTolerance, true);
break;
case SolarPanel.PARTIAL_SHADE_TOLERANCE:
Util.selectSilently(miPartialTolerance, true);
break;
case SolarPanel.NO_SHADE_TOLERANCE:
Util.selectSilently(miNoTolerance, true);
break;
}
Util.selectSilently(cbmiDrawSunBeam, sp.isSunBeamVisible());
Util.selectSilently(cbmiDisableEditPoint, sp.getLockEdit());
Util.selectSilently(rbmiLandscape, sp.isRotated());
Util.selectSilently(rbmiPortrait, !sp.isRotated());
Util.selectSilently(miLabelNone, !sp.isLabelVisible());
Util.selectSilently(miLabelCustom, sp.getLabelCustom());
Util.selectSilently(miLabelId, sp.getLabelId());
Util.selectSilently(miLabelModelName, sp.getLabelModelName());
Util.selectSilently(miLabelCellEfficiency, sp.getLabelCellEfficiency());
Util.selectSilently(miLabelTiltAngle, sp.getLabelTiltAngle());
Util.selectSilently(miLabelTracker, sp.getLabelTracker());
Util.selectSilently(miLabelEnergyOutput, sp.getLabelEnergyOutput());
final PvModuleSpecs pms = sp.getPvModuleSpecs();
final boolean isCustom = "Custom".equals(pms.getModel());
miCells.setEnabled(isCustom);
miSize.setEnabled(isCustom);
miTemperatureEffects.setEnabled(isCustom);
shadeToleranceMenu.setEnabled(isCustom);
switch(sp.getTracker()) {
case Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER:
Util.selectSilently(miAltazimuthDualAxisTracker, true);
break;
case Trackable.HORIZONTAL_SINGLE_AXIS_TRACKER:
Util.selectSilently(miHorizontalSingleAxisTracker, true);
break;
case Trackable.VERTICAL_SINGLE_AXIS_TRACKER:
Util.selectSilently(miVerticalSingleAxisTracker, true);
break;
case Trackable.NO_TRACKER:
Util.selectSilently(miNoTracker, true);
break;
}
miAltazimuthDualAxisTracker.setEnabled(true);
miHorizontalSingleAxisTracker.setEnabled(true);
miVerticalSingleAxisTracker.setEnabled(true);
if (sp.getContainer() instanceof Roof) {
final Roof roof = (Roof) sp.getContainer();
final boolean flat = Util.isZero(roof.getHeight());
miAltazimuthDualAxisTracker.setEnabled(flat);
miHorizontalSingleAxisTracker.setEnabled(flat);
miVerticalSingleAxisTracker.setEnabled(flat);
} else if (sp.getContainer() instanceof Wall || sp.getContainer() instanceof Rack) {
miAltazimuthDualAxisTracker.setEnabled(false);
miHorizontalSingleAxisTracker.setEnabled(false);
miVerticalSingleAxisTracker.setEnabled(false);
}
if (sp.getTracker() != Trackable.NO_TRACKER) {
// vertical and tilted single-axis trackers can adjust the tilt angle
miTiltAngle.setEnabled(sp.getTracker() == Trackable.VERTICAL_SINGLE_AXIS_TRACKER || sp.getTracker() == Trackable.TILTED_SINGLE_AXIS_TRACKER);
// any tracker that will alter the azimuth angle should disable the menu item
miAzimuth.setEnabled(sp.getTracker() != Trackable.ALTAZIMUTH_DUAL_AXIS_TRACKER && sp.getTracker() != Trackable.VERTICAL_SINGLE_AXIS_TRACKER);
} else {
miTiltAngle.setEnabled(true);
miAzimuth.setEnabled(true);
miBaseHeight.setEnabled(true);
if (sp.getContainer() instanceof Roof) {
final Roof roof = (Roof) sp.getContainer();
if (roof.getHeight() > 0) {
miTiltAngle.setEnabled(false);
miAzimuth.setEnabled(false);
miBaseHeight.setEnabled(false);
}
} else if (sp.getContainer() instanceof Wall || sp.getContainer() instanceof Rack) {
miTiltAngle.setEnabled(false);
miAzimuth.setEnabled(false);
miBaseHeight.setEnabled(false);
}
}
}
});
final JMenuItem miDeleteRow = new JMenuItem("Delete Row");
miDeleteRow.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof SolarPanel)) {
return;
}
SceneManager.getTaskManager().update(new Callable<Object>() {
@Override
public Object call() {
Scene.getInstance().removeAllSolarPanels(((SolarPanel) selectedPart).getRow());
return null;
}
});
}
});
popupMenuForSolarPanel.add(miDeleteRow);
popupMenuForSolarPanel.addSeparator();
popupMenuForSolarPanel.add(miModel);
popupMenuForSolarPanel.add(miCells);
popupMenuForSolarPanel.add(miSize);
popupMenuForSolarPanel.add(miTemperatureEffects);
popupMenuForSolarPanel.add(shadeToleranceMenu);
popupMenuForSolarPanel.addSeparator();
popupMenuForSolarPanel.add(miTiltAngle);
popupMenuForSolarPanel.add(miAzimuth);
popupMenuForSolarPanel.add(miBaseHeight);
popupMenuForSolarPanel.add(miInverterEff);
popupMenuForSolarPanel.add(orientationMenu);
popupMenuForSolarPanel.add(trackerMenu);
popupMenuForSolarPanel.addSeparator();
popupMenuForSolarPanel.add(cbmiDisableEditPoint);
popupMenuForSolarPanel.add(cbmiDrawSunBeam);
popupMenuForSolarPanel.add(labelMenu);
popupMenuForSolarPanel.addSeparator();
JMenuItem mi = new JMenuItem("Daily Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof SolarPanel) {
new PvDailyAnalysis().show();
}
}
});
popupMenuForSolarPanel.add(mi);
mi = new JMenuItem("Annual Yield Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof SolarPanel) {
new PvAnnualAnalysis().show();
}
}
});
popupMenuForSolarPanel.add(mi);
}
return popupMenuForSolarPanel;
}
use of org.concord.energy3d.model.HousePart in project energy3d by concord-consortium.
the class PopupMenuForWindow method getPopupMenu.
static JPopupMenu getPopupMenu() {
if (popupMenuForWindow == null) {
final JMenu shutterMenu = new JMenu("Shutters");
popupMenuForWindow = createPopupMenu(true, true, new Runnable() {
@Override
public void run() {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
shutterMenu.setEnabled(selectedPart.getContainer() instanceof Wall);
}
}
});
final JMenu muntinMenu = new JMenu("Muntins");
final JCheckBoxMenuItem cbmiHorizontalBars = new JCheckBoxMenuItem("Horizontal Bars");
cbmiHorizontalBars.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
w.setHorizontalBars(cbmiHorizontalBars.isSelected());
w.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
muntinMenu.add(cbmiHorizontalBars);
final JCheckBoxMenuItem cbmiVerticalBars = new JCheckBoxMenuItem("Vertical Bars");
cbmiVerticalBars.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
w.setVerticalBars(cbmiVerticalBars.isSelected());
w.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
});
muntinMenu.add(cbmiVerticalBars);
muntinMenu.addSeparator();
final ButtonGroup muntinButtonGroup = new ButtonGroup();
final JRadioButtonMenuItem miMoreBars = new JRadioButtonMenuItem("More Bars");
miMoreBars.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
w.setStyle(Window.MORE_MUNTIN_BARS);
w.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
}
});
muntinButtonGroup.add(miMoreBars);
muntinMenu.add(miMoreBars);
final JRadioButtonMenuItem miMediumBars = new JRadioButtonMenuItem("Medium Bars");
miMediumBars.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
w.setStyle(Window.MEDIUM_MUNTIN_BARS);
w.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
}
});
muntinButtonGroup.add(miMediumBars);
muntinMenu.add(miMediumBars);
final JRadioButtonMenuItem miLessBars = new JRadioButtonMenuItem("Less Bars");
miLessBars.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
w.setStyle(Window.LESS_MUNTIN_BARS);
w.draw();
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
}
}
});
muntinButtonGroup.add(miLessBars);
muntinMenu.add(miLessBars);
muntinMenu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(final MenuEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window window = (Window) selectedPart;
switch(window.getStyle()) {
case Window.MORE_MUNTIN_BARS:
Util.selectSilently(miMoreBars, true);
break;
case Window.MEDIUM_MUNTIN_BARS:
Util.selectSilently(miMediumBars, true);
break;
case Window.LESS_MUNTIN_BARS:
Util.selectSilently(miLessBars, true);
break;
}
// NO_MUNTIN_BAR backward compatibility
Util.selectSilently(cbmiHorizontalBars, window.getStyle() != Window.NO_MUNTIN_BAR && window.getHorizontalBars());
Util.selectSilently(cbmiVerticalBars, window.getStyle() != Window.NO_MUNTIN_BAR && window.getVerticalBars());
}
}
@Override
public void menuDeselected(final MenuEvent e) {
muntinMenu.setEnabled(true);
}
@Override
public void menuCanceled(final MenuEvent e) {
muntinMenu.setEnabled(true);
}
});
final JCheckBoxMenuItem cbmiBothShutters = new JCheckBoxMenuItem("Both Shutters");
final JCheckBoxMenuItem cbmiLeftShutter = new JCheckBoxMenuItem("Left Shutter");
final JCheckBoxMenuItem cbmiRightShutter = new JCheckBoxMenuItem("Right Shutter");
cbmiLeftShutter.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
final ChangeWindowShuttersCommand c = new ChangeWindowShuttersCommand(w);
w.setLeftShutter(cbmiLeftShutter.isSelected());
w.draw();
Scene.getInstance().setEdited(true);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
});
shutterMenu.add(cbmiLeftShutter);
cbmiRightShutter.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
final ChangeWindowShuttersCommand c = new ChangeWindowShuttersCommand(w);
w.setRightShutter(cbmiRightShutter.isSelected());
w.draw();
Scene.getInstance().setEdited(true);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
});
shutterMenu.add(cbmiRightShutter);
cbmiBothShutters.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window w = (Window) selectedPart;
final ChangeWindowShuttersCommand c = new ChangeWindowShuttersCommand(w);
w.setLeftShutter(cbmiBothShutters.isSelected());
w.setRightShutter(cbmiBothShutters.isSelected());
w.draw();
Scene.getInstance().setEdited(true);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
}
}
});
shutterMenu.add(cbmiBothShutters);
shutterMenu.addSeparator();
final JMenuItem miShutterColor = new JMenuItem("Color...");
miShutterColor.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Window)) {
return;
}
final Window window = (Window) selectedPart;
final JColorChooser colorChooser = MainFrame.getInstance().getColorChooser();
final ReadOnlyColorRGBA color = window.getShutterColor();
if (color != null) {
colorChooser.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue()));
}
final ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final Color c = colorChooser.getColor();
final float[] newColor = c.getComponents(null);
final ColorRGBA color = new ColorRGBA(newColor[0], newColor[1], newColor[2], 1);
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Window", true);
final JRadioButton rb2 = new JRadioButton("All Windows on this " + (window.getContainer() instanceof Wall ? "Wall" : "Roof"));
final JRadioButton rb3 = new JRadioButton("All Windows of this Building");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Shutter Color");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = !color.equals(window.getShutterColor());
if (rb1.isSelected()) {
// apply to only this window
if (changed) {
final ChangeShutterColorCommand cmd = new ChangeShutterColorCommand(window);
window.setShutterColor(color);
window.draw();
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
if (window.getContainer() instanceof Wall) {
final Wall wall = (Wall) window.getContainer();
for (final Window x : wall.getWindows()) {
if (!color.equals(x.getShutterColor())) {
changed = true;
break;
}
}
} else if (window.getContainer() instanceof Roof) {
final Roof roof = (Roof) window.getContainer();
for (final Window x : roof.getWindows()) {
if (!color.equals(x.getShutterColor())) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeContainerShutterColorCommand cmd = new ChangeContainerShutterColorCommand(window.getContainer());
Scene.getInstance().setWindowColorInContainer(window.getContainer(), color, true);
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 1;
} else {
final Foundation foundation = window.getTopContainer();
if (!changed) {
for (final Window x : foundation.getWindows()) {
if (!color.equals(x.getShutterColor())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBuildingShutterColorCommand cmd = new ChangeBuildingShutterColorCommand(window);
Scene.getInstance().setShutterColorOfBuilding(window, color);
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 2;
}
if (changed) {
Scene.getInstance().setEdited(true);
SceneManager.getInstance().refresh();
}
if (choice == options[0]) {
break;
}
}
}
}
};
JColorChooser.createDialog(MainFrame.getInstance(), "Select Shutter Color", true, colorChooser, actionListener, null).setVisible(true);
}
});
shutterMenu.add(miShutterColor);
final JMenuItem miShutterLength = new JMenuItem("Relative Length...");
miShutterLength.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Window)) {
return;
}
final Window window = (Window) selectedPart;
final String partInfo = window.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final String title = "<html>Relative Length of Shutter for " + partInfo + "</html>";
final String footnote = "<html><hr width=400></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Window Shutter", true);
final JRadioButton rb2 = new JRadioButton("All Window Shutters on this Wall");
final JRadioButton rb3 = new JRadioButton("All Window Shutters of this Building");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(window.getShutterLength() + "");
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Shutter Length (Relative)");
while (true) {
dialog.setVisible(true);
inputField.selectAll();
inputField.requestFocusInWindow();
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
double val = 0;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val <= 0 || val > 1) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Relative shutter length must be within (0, 1).", "Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val - window.getShutterLength()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeShutterLengthCommand c = new ChangeShutterLengthCommand(window);
window.setShutterLength(val);
window.draw();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
if (window.getContainer() instanceof Wall) {
final Wall wall = (Wall) window.getContainer();
for (final Window x : wall.getWindows()) {
if (Math.abs(val - x.getShutterLength()) > 0.000001) {
changed = true;
break;
}
}
} else if (window.getContainer() instanceof Roof) {
final Roof roof = (Roof) window.getContainer();
for (final Window x : roof.getWindows()) {
if (Math.abs(val - x.getShutterLength()) > 0.000001) {
changed = true;
break;
}
}
}
}
if (changed) {
Scene.getInstance().setShutterLengthInContainer(window.getContainer(), val);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final Foundation foundation = window.getTopContainer();
if (!changed) {
for (final Window x : foundation.getWindows()) {
if (Math.abs(val - x.getShutterLength()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
Scene.getInstance().setShutterLengthOfBuilding(window, val);
}
selectedScopeIndex = 2;
}
if (changed) {
SceneManager.getInstance().refresh();
Scene.getInstance().setEdited(true);
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
shutterMenu.add(miShutterLength);
shutterMenu.addMenuListener(new MenuListener() {
@Override
public void menuSelected(final MenuEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (selectedPart instanceof Window) {
final Window window = (Window) selectedPart;
Util.selectSilently(cbmiLeftShutter, window.getLeftShutter());
Util.selectSilently(cbmiRightShutter, window.getRightShutter());
Util.selectSilently(cbmiBothShutters, window.getLeftShutter() && window.getRightShutter());
}
}
@Override
public void menuDeselected(final MenuEvent e) {
shutterMenu.setEnabled(true);
}
@Override
public void menuCanceled(final MenuEvent e) {
shutterMenu.setEnabled(true);
}
});
final JMenuItem miShgc = new JMenuItem("Solar Heat Gain Coefficient...");
miShgc.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Window)) {
return;
}
final String partInfo = selectedPart.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final Window window = (Window) selectedPart;
final String title = "<html>Solar Heat Gain Coefficient of " + partInfo + "</html>";
final String footnote = "<html><hr><font size=2>Examples:<br><table><tr><td><font size=2>Single glass (clear)</td><td><font size=2>0.66</td></tr><tr><td><font size=2>Single glass (green tint)</td><td><font size=2>0.55</td></tr><tr><td><font size=2>Triple glass (air spaces)</td><td><font size=2>0.39</td></tr></table><hr></html>";
final JPanel gui = new JPanel(new BorderLayout());
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Window", true);
final JRadioButton rb2 = new JRadioButton("All Windows on this " + (selectedPart.getContainer() instanceof Wall ? "Wall" : "Roof"));
final JRadioButton rb3 = new JRadioButton("All Windows of this Building");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(panel, BorderLayout.CENTER);
final JTextField inputField = new JTextField(window.getSolarHeatGainCoefficient() + "");
gui.add(inputField, BorderLayout.SOUTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { title, footnote, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Solar Heat Gain Coefficient (SHGC)");
while (true) {
dialog.setVisible(true);
inputField.selectAll();
inputField.requestFocusInWindow();
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
double val = 0;
try {
val = Double.parseDouble(inputField.getText());
} catch (final NumberFormatException exception) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), inputField.getText() + " is an invalid value!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
if (val < 0 || val > 1) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Solar heat gain coefficient must be between 0 and 1.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(val - window.getSolarHeatGainCoefficient()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final ChangeWindowShgcCommand c = new ChangeWindowShgcCommand(window);
window.setSolarHeatGainCoefficient(val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
if (window.getContainer() instanceof Wall) {
final Wall wall = (Wall) window.getContainer();
for (final Window x : wall.getWindows()) {
if (Math.abs(val - x.getSolarHeatGainCoefficient()) > 0.000001) {
changed = true;
break;
}
}
} else if (window.getContainer() instanceof Roof) {
final Roof roof = (Roof) window.getContainer();
for (final Window x : roof.getWindows()) {
if (Math.abs(val - x.getSolarHeatGainCoefficient()) > 0.000001) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeContainerWindowShgcCommand c = new ChangeContainerWindowShgcCommand(window.getContainer());
Scene.getInstance().setWindowShgcInContainer(window.getContainer(), val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final Foundation foundation = window.getTopContainer();
if (!changed) {
for (final Window x : foundation.getWindows()) {
if (Math.abs(val - x.getSolarHeatGainCoefficient()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBuildingWindowShgcCommand c = new ChangeBuildingWindowShgcCommand(foundation);
Scene.getInstance().setWindowShgcOfBuilding(foundation, val);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
final JMenuItem miTint = new JMenuItem("Tint...");
miTint.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Window)) {
return;
}
final Window window = (Window) selectedPart;
final JColorChooser colorChooser = MainFrame.getInstance().getColorChooser();
final ReadOnlyColorRGBA color = window.getColor();
if (color != null) {
colorChooser.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue()));
}
final ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
final Color c = colorChooser.getColor();
final float[] newColor = c.getComponents(null);
final ColorRGBA color = new ColorRGBA(newColor[0], newColor[1], newColor[2], (float) (1.0 - window.getSolarHeatGainCoefficient()));
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Window", true);
final JRadioButton rb2 = new JRadioButton("All Windows on this " + (window.getContainer() instanceof Wall ? "Wall" : "Roof"));
final JRadioButton rb3 = new JRadioButton("All Windows of this Building");
panel.add(rb1);
panel.add(rb2);
panel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(panel, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Window Tint");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean changed = !Util.isRGBEqual(color, window.getColor());
if (rb1.isSelected()) {
// apply to only this window
if (changed) {
final ChangePartColorCommand cmd = new ChangePartColorCommand(window);
window.setColor(color);
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
if (window.getContainer() instanceof Wall) {
final Wall wall = (Wall) window.getContainer();
for (final Window x : wall.getWindows()) {
if (!Util.isRGBEqual(color, x.getColor())) {
changed = true;
break;
}
}
} else if (window.getContainer() instanceof Roof) {
final Roof roof = (Roof) window.getContainer();
for (final Window x : roof.getWindows()) {
if (!Util.isRGBEqual(color, x.getColor())) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeContainerWindowColorCommand cmd = new ChangeContainerWindowColorCommand(window.getContainer());
Scene.getInstance().setWindowColorInContainer(window.getContainer(), color, false);
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
final Foundation foundation = window.getTopContainer();
if (!changed) {
for (final Window x : foundation.getWindows()) {
if (!Util.isRGBEqual(color, x.getColor())) {
changed = true;
break;
}
}
}
if (changed) {
final ChangeBuildingColorCommand cmd = new ChangeBuildingColorCommand(window);
Scene.getInstance().setPartColorOfBuilding(window, color);
SceneManager.getInstance().getUndoManager().addEdit(cmd);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
};
JColorChooser.createDialog(MainFrame.getInstance(), "Select Tint", true, colorChooser, actionListener, null).setVisible(true);
}
});
final JMenuItem miSize = new JMenuItem("Size...");
miSize.addActionListener(new ActionListener() {
// remember the scope selection as the next action will likely be applied to the same scope
private int selectedScopeIndex = 0;
@Override
public void actionPerformed(final ActionEvent e) {
final HousePart selectedPart = SceneManager.getInstance().getSelectedPart();
if (!(selectedPart instanceof Window)) {
return;
}
final Window window = (Window) selectedPart;
final HousePart container = window.getContainer();
final Foundation foundation = window.getTopContainer();
final String partInfo = window.toString().substring(0, selectedPart.toString().indexOf(')') + 1);
final JPanel gui = new JPanel(new BorderLayout());
final JPanel inputPanel = new JPanel(new GridLayout(2, 2, 5, 5));
gui.add(inputPanel, BorderLayout.CENTER);
inputPanel.add(new JLabel("Width (m): "));
final JTextField widthField = new JTextField(threeDecimalsFormat.format(window.getWindowWidth()));
inputPanel.add(widthField);
inputPanel.add(new JLabel("Height (m): "));
final JTextField heightField = new JTextField(threeDecimalsFormat.format(window.getWindowHeight()));
inputPanel.add(heightField);
inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JPanel scopePanel = new JPanel();
scopePanel.setLayout(new BoxLayout(scopePanel, BoxLayout.Y_AXIS));
scopePanel.setBorder(BorderFactory.createTitledBorder("Apply to:"));
final JRadioButton rb1 = new JRadioButton("Only this Window", true);
final JRadioButton rb2 = new JRadioButton("All Windows on this " + (window.getContainer() instanceof Wall ? "Wall" : "Roof"));
final JRadioButton rb3 = new JRadioButton("All Windows of this Building");
scopePanel.add(rb1);
scopePanel.add(rb2);
scopePanel.add(rb3);
final ButtonGroup bg = new ButtonGroup();
bg.add(rb1);
bg.add(rb2);
bg.add(rb3);
switch(selectedScopeIndex) {
case 0:
rb1.setSelected(true);
break;
case 1:
rb2.setSelected(true);
break;
case 2:
rb3.setSelected(true);
break;
}
gui.add(scopePanel, BorderLayout.NORTH);
final Object[] options = new Object[] { "OK", "Cancel", "Apply" };
final JOptionPane optionPane = new JOptionPane(new Object[] { "Set Size for " + partInfo, gui }, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION, null, options, options[2]);
final JDialog dialog = optionPane.createDialog(MainFrame.getInstance(), "Window Size");
while (true) {
dialog.setVisible(true);
final Object choice = optionPane.getValue();
if (choice == options[1] || choice == null) {
break;
} else {
boolean ok = true;
double w = 0, h = 0;
try {
w = Double.parseDouble(widthField.getText());
h = Double.parseDouble(heightField.getText());
} catch (final NumberFormatException x) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Invalid input!", "Error", JOptionPane.ERROR_MESSAGE);
ok = false;
}
if (ok) {
double wmax = 10;
if (container instanceof Wall) {
wmax = ((Wall) container).getWallWidth() * 0.99;
}
double hmax = 10;
if (container instanceof Wall) {
hmax = ((Wall) container).getWallHeight() * 0.99;
}
if (w < 0.1 || w > wmax) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Width must be between 0.1 and " + (int) wmax + " m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else if (h < 0.1 || h > hmax) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Height must be between 0.1 and " + (int) hmax + " m.", "Range Error", JOptionPane.ERROR_MESSAGE);
} else {
boolean changed = Math.abs(w - window.getWindowWidth()) > 0.000001 || Math.abs(h - window.getWindowHeight()) > 0.000001;
if (rb1.isSelected()) {
if (changed) {
final SetPartSizeCommand c = new SetPartSizeCommand(window);
window.setWindowWidth(w);
window.setWindowHeight(h);
window.draw();
window.getContainer().draw();
SceneManager.getInstance().refresh();
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 0;
} else if (rb2.isSelected()) {
if (!changed) {
if (window.getContainer() instanceof Wall) {
final Wall wall = (Wall) window.getContainer();
for (final Window x : wall.getWindows()) {
if (Math.abs(w - x.getWindowWidth()) > 0.000001 || Math.abs(h - x.getWindowHeight()) > 0.000001) {
changed = true;
break;
}
}
} else if (window.getContainer() instanceof Roof) {
final Roof roof = (Roof) window.getContainer();
for (final Window x : roof.getWindows()) {
if (Math.abs(w - x.getWindowWidth()) > 0.000001 || Math.abs(h - x.getWindowHeight()) > 0.000001) {
changed = true;
break;
}
}
}
}
if (changed) {
final ChangeContainerWindowSizeCommand c = new ChangeContainerWindowSizeCommand(window.getContainer());
Scene.getInstance().setWindowSizeInContainer(window.getContainer(), w, h);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 1;
} else if (rb3.isSelected()) {
if (!changed) {
for (final Window x : foundation.getWindows()) {
if (Math.abs(w - x.getWindowWidth()) > 0.000001 || Math.abs(h - x.getWindowHeight()) > 0.000001) {
changed = true;
break;
}
}
}
if (changed) {
final SetSizeForWindowsOnFoundationCommand c = new SetSizeForWindowsOnFoundationCommand(foundation);
foundation.setSizeForWindows(w, h);
SceneManager.getInstance().getUndoManager().addEdit(c);
}
selectedScopeIndex = 2;
}
if (changed) {
updateAfterEdit();
}
if (choice == options[0]) {
break;
}
}
}
}
}
}
});
popupMenuForWindow.addSeparator();
popupMenuForWindow.add(miSize);
popupMenuForWindow.add(miTint);
popupMenuForWindow.add(createInsulationMenuItem(true));
popupMenuForWindow.add(miShgc);
popupMenuForWindow.add(muntinMenu);
popupMenuForWindow.add(shutterMenu);
popupMenuForWindow.addSeparator();
JMenuItem mi = new JMenuItem("Daily Energy Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof Window) {
new EnergyDailyAnalysis().show("Daily Energy for Window");
}
}
});
popupMenuForWindow.add(mi);
mi = new JMenuItem("Annual Energy Analysis...");
mi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (EnergyPanel.getInstance().adjustCellSize()) {
return;
}
if (SceneManager.getInstance().getSelectedPart() instanceof Window) {
new EnergyAnnualAnalysis().show("Annual Energy for Window");
}
}
});
popupMenuForWindow.add(mi);
}
return popupMenuForWindow;
}
Aggregations