Flight configuration dialogs
This commit is contained in:
parent
525869c3e7
commit
5b93c923f5
@ -1856,6 +1856,6 @@ SeparationSelectionDialog.opt.title = Which flight configurations are affected:
|
|||||||
SeparationSelectionDialog.opt.default = Change all configuration using the default separation event
|
SeparationSelectionDialog.opt.default = Change all configuration using the default separation event
|
||||||
SeparationSelectionDialog.opt.override = Override for the {0} flight configuration only
|
SeparationSelectionDialog.opt.override = Override for the {0} flight configuration only
|
||||||
|
|
||||||
MotorConfigurationPanel.description = <b>Select the motors and motor ignition events of your rocket.</b><br> <em>Motor mounts:</em> Select which components function as motor mounts.<br> <em>Motor configurations:</em> Select the motor and ignition event for each motor mount.
|
MotorConfigurationPanel.description = <b>Select the motors and motor ignition events of the selected flight configuration.</b><br> <em>Motor mounts:</em> Select which components function as motor mounts.<br> <em>Motor configurations:</em> Select the motor and ignition event for each motor mount.
|
||||||
|
|
||||||
MotorDescriptionSubstitutor.description = Motors in the configuration
|
MotorDescriptionSubstitutor.description = Motors in the configuration
|
||||||
|
@ -21,6 +21,10 @@ import net.sf.openrocket.rocketcomponent.Rocket;
|
|||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ComboBoxModel that contains a list of flight configurations. The list can
|
||||||
|
* optionally contain a last element that opens up the configuration edit dialog.
|
||||||
|
*/
|
||||||
public class FlightConfigurationModel implements ComboBoxModel, StateChangeListener {
|
public class FlightConfigurationModel implements ComboBoxModel, StateChangeListener {
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
@ -33,22 +37,32 @@ public class FlightConfigurationModel implements ComboBoxModel, StateChangeListe
|
|||||||
|
|
||||||
private final Configuration config;
|
private final Configuration config;
|
||||||
private final Rocket rocket;
|
private final Rocket rocket;
|
||||||
|
private final boolean showEditElement;
|
||||||
|
|
||||||
private Map<String, ID> map = new HashMap<String, ID>();
|
private Map<String, ID> map = new HashMap<String, ID>();
|
||||||
|
|
||||||
|
|
||||||
public FlightConfigurationModel(Configuration config) {
|
public FlightConfigurationModel(Configuration config) {
|
||||||
this.config = config;
|
this(config, true);
|
||||||
this.rocket = config.getRocket();
|
|
||||||
config.addChangeListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public FlightConfigurationModel(Configuration config, boolean showEditElement) {
|
||||||
|
this.config = config;
|
||||||
|
this.rocket = config.getRocket();
|
||||||
|
this.showEditElement = showEditElement;
|
||||||
|
config.addChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getElementAt(int index) {
|
public Object getElementAt(int index) {
|
||||||
String[] ids = rocket.getFlightConfigurationIDs();
|
String[] ids = rocket.getFlightConfigurationIDs();
|
||||||
if (index < 0 || index > ids.length)
|
|
||||||
|
if (index < 0)
|
||||||
|
return null;
|
||||||
|
if ((showEditElement && index > ids.length) ||
|
||||||
|
(!showEditElement && index >= ids.length))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (index == ids.length)
|
if (index == ids.length)
|
||||||
@ -59,7 +73,11 @@ public class FlightConfigurationModel implements ComboBoxModel, StateChangeListe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return rocket.getFlightConfigurationIDs().length + 1;
|
if (showEditElement) {
|
||||||
|
return rocket.getFlightConfigurationIDs().length + 1;
|
||||||
|
} else {
|
||||||
|
return rocket.getFlightConfigurationIDs().length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,7 +60,7 @@ public class FlightConfigurationDialog extends JDialog {
|
|||||||
JLabel label = new JLabel("Selected flight configuration:");
|
JLabel label = new JLabel("Selected flight configuration:");
|
||||||
panel.add(label, "span, split");
|
panel.add(label, "span, split");
|
||||||
|
|
||||||
flightConfigurationModel = new FlightConfigurationModel(rocket.getDefaultConfiguration());
|
flightConfigurationModel = new FlightConfigurationModel(rocket.getDefaultConfiguration(), false);
|
||||||
JComboBox configSelector = new JComboBox(flightConfigurationModel);
|
JComboBox configSelector = new JComboBox(flightConfigurationModel);
|
||||||
configSelector.addActionListener(new ActionListener() {
|
configSelector.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,7 +36,7 @@ public class IgnitionSelectionDialog extends JDialog {
|
|||||||
|
|
||||||
private IgnitionConfiguration newConfiguration;
|
private IgnitionConfiguration newConfiguration;
|
||||||
|
|
||||||
IgnitionSelectionDialog(JDialog parent, final Rocket rocket, final MotorMount component) {
|
public IgnitionSelectionDialog(JDialog parent, final Rocket rocket, final MotorMount component) {
|
||||||
super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
|
super(parent, trans.get("edtmotorconfdlg.title.Selectignitionconf"), Dialog.ModalityType.APPLICATION_MODAL);
|
||||||
final String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
|
final String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
|
||||||
|
|
||||||
@ -44,6 +44,7 @@ public class IgnitionSelectionDialog extends JDialog {
|
|||||||
|
|
||||||
JPanel panel = new JPanel(new MigLayout("fill"));
|
JPanel panel = new JPanel(new MigLayout("fill"));
|
||||||
|
|
||||||
|
// Edit default or override option
|
||||||
boolean isDefault = component.getIgnitionConfiguration().isDefault(id);
|
boolean isDefault = component.getIgnitionConfiguration().isDefault(id);
|
||||||
panel.add(new JLabel(trans.get("IgnitionSelectionDialog.opt.title")), "span, wrap rel");
|
panel.add(new JLabel(trans.get("IgnitionSelectionDialog.opt.title")), "span, wrap rel");
|
||||||
final JRadioButton defaultButton = new JRadioButton(trans.get("IgnitionSelectionDialog.opt.default"), isDefault);
|
final JRadioButton defaultButton = new JRadioButton(trans.get("IgnitionSelectionDialog.opt.default"), isDefault);
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
@ -8,13 +11,16 @@ import java.util.Iterator;
|
|||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
||||||
@ -26,8 +32,6 @@ import net.sf.openrocket.unit.UnitGroup;
|
|||||||
|
|
||||||
public class RecoveryConfigurationPanel extends JPanel {
|
public class RecoveryConfigurationPanel extends JPanel {
|
||||||
|
|
||||||
// FIXME: Gray italics for default selection
|
|
||||||
|
|
||||||
private Translator trans = Application.getTranslator();
|
private Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +57,6 @@ public class RecoveryConfigurationPanel extends JPanel {
|
|||||||
recoveryTable.addMouseListener(new MouseAdapter() {
|
recoveryTable.addMouseListener(new MouseAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
JTable table = (JTable) e.getComponent();
|
|
||||||
updateButtonState();
|
updateButtonState();
|
||||||
|
|
||||||
if (e.getClickCount() == 2) {
|
if (e.getClickCount() == 2) {
|
||||||
@ -62,6 +65,7 @@ public class RecoveryConfigurationPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
recoveryTable.setDefaultRenderer(Object.class, new RecoveryTableCellRenderer());
|
||||||
|
|
||||||
JScrollPane scroll = new JScrollPane(recoveryTable);
|
JScrollPane scroll = new JScrollPane(recoveryTable);
|
||||||
this.add(scroll, "span, grow, wrap");
|
this.add(scroll, "span, grow, wrap");
|
||||||
@ -90,7 +94,12 @@ public class RecoveryConfigurationPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fireTableDataChanged() {
|
public void fireTableDataChanged() {
|
||||||
|
int selected = recoveryTable.getSelectedRow();
|
||||||
recoveryTableModel.fireTableDataChanged();
|
recoveryTableModel.fireTableDataChanged();
|
||||||
|
if (selected >= 0) {
|
||||||
|
selected = Math.min(selected, recoveryTable.getRowCount() - 1);
|
||||||
|
recoveryTable.getSelectionModel().setSelectionInterval(selected, selected);
|
||||||
|
}
|
||||||
updateButtonState();
|
updateButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,4 +218,47 @@ public class RecoveryConfigurationPanel extends JPanel {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class RecoveryTableCellRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
|
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||||
|
if (!(c instanceof JLabel)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
JLabel label = (JLabel) c;
|
||||||
|
|
||||||
|
RecoveryDevice recoveryDevice = findRecoveryDevice(row);
|
||||||
|
String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
|
||||||
|
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
regular(label);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (recoveryDevice.getDeploymentConfiguration().isDefault(id)) {
|
||||||
|
shaded(label);
|
||||||
|
} else {
|
||||||
|
regular(label);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shaded(JLabel label) {
|
||||||
|
GUIUtil.changeFontStyle(label, Font.ITALIC);
|
||||||
|
label.setForeground(Color.GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void regular(JLabel label) {
|
||||||
|
GUIUtil.changeFontStyle(label, Font.PLAIN);
|
||||||
|
label.setForeground(Color.BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
package net.sf.openrocket.gui.dialogs.flightconfiguration;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Font;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
@ -8,13 +11,16 @@ import java.util.Iterator;
|
|||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTable;
|
import javax.swing.JTable;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.table.AbstractTableModel;
|
import javax.swing.table.AbstractTableModel;
|
||||||
|
import javax.swing.table.DefaultTableCellRenderer;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.gui.util.GUIUtil;
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
@ -25,9 +31,6 @@ import net.sf.openrocket.unit.UnitGroup;
|
|||||||
|
|
||||||
public class SeparationConfigurationPanel extends JPanel {
|
public class SeparationConfigurationPanel extends JPanel {
|
||||||
|
|
||||||
// FIXME: Gray italics for default selection
|
|
||||||
|
|
||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
private final FlightConfigurationDialog flightConfigurationDialog;
|
private final FlightConfigurationDialog flightConfigurationDialog;
|
||||||
@ -80,6 +83,7 @@ public class SeparationConfigurationPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
separationTable.setDefaultRenderer(Object.class, new SeparationTableCellRenderer());
|
||||||
|
|
||||||
JScrollPane scroll = new JScrollPane(separationTable);
|
JScrollPane scroll = new JScrollPane(separationTable);
|
||||||
this.add(scroll, "span, grow, wrap");
|
this.add(scroll, "span, grow, wrap");
|
||||||
@ -109,12 +113,21 @@ public class SeparationConfigurationPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fireTableDataChanged() {
|
public void fireTableDataChanged() {
|
||||||
|
int selected = separationTable.getSelectedRow();
|
||||||
separationTableModel.fireTableDataChanged();
|
separationTableModel.fireTableDataChanged();
|
||||||
|
if (selected >= 0) {
|
||||||
|
selected = Math.min(selected, separationTable.getRowCount() - 1);
|
||||||
|
separationTable.getSelectionModel().setSelectionInterval(selected, selected);
|
||||||
|
}
|
||||||
updateButtonState();
|
updateButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stage getSelectedStage() {
|
private Stage getSelectedStage() {
|
||||||
int row = separationTable.getSelectedRow();
|
int row = separationTable.getSelectedRow();
|
||||||
|
return getStage(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stage getStage(int row) {
|
||||||
if (row >= 0 && row < stages.length) {
|
if (row >= 0 && row < stages.length) {
|
||||||
return stages[row];
|
return stages[row];
|
||||||
}
|
}
|
||||||
@ -200,7 +213,50 @@ public class SeparationConfigurationPanel extends JPanel {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class SeparationTableCellRenderer extends DefaultTableCellRenderer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||||
|
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||||
|
if (!(c instanceof JLabel)) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
JLabel label = (JLabel) c;
|
||||||
|
|
||||||
|
Stage stage = getStage(row);
|
||||||
|
String id = rocket.getDefaultConfiguration().getFlightConfigurationID();
|
||||||
|
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
regular(label);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
if (stage.getStageSeparationConfiguration().isDefault(id)) {
|
||||||
|
shaded(label);
|
||||||
|
} else {
|
||||||
|
regular(label);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void shaded(JLabel label) {
|
||||||
|
GUIUtil.changeFontStyle(label, Font.ITALIC);
|
||||||
|
label.setForeground(Color.GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void regular(JLabel label) {
|
||||||
|
GUIUtil.changeFontStyle(label, Font.PLAIN);
|
||||||
|
label.setForeground(Color.BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,17 @@ import java.awt.Dialog;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JRadioButton;
|
||||||
import javax.swing.JSpinner;
|
import javax.swing.JSpinner;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import net.sf.openrocket.formatting.RocketDescriptor;
|
||||||
import net.sf.openrocket.gui.SpinnerEditor;
|
import net.sf.openrocket.gui.SpinnerEditor;
|
||||||
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||||
import net.sf.openrocket.gui.adaptors.EnumModel;
|
import net.sf.openrocket.gui.adaptors.EnumModel;
|
||||||
@ -28,6 +31,8 @@ public class SeparationSelectionDialog extends JDialog {
|
|||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
|
|
||||||
|
private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class);
|
||||||
|
|
||||||
private StageSeparationConfiguration newConfiguration;
|
private StageSeparationConfiguration newConfiguration;
|
||||||
|
|
||||||
SeparationSelectionDialog(JDialog parent, final Rocket rocket, final Stage component) {
|
SeparationSelectionDialog(JDialog parent, final Rocket rocket, final Stage component) {
|
||||||
@ -41,6 +46,23 @@ public class SeparationSelectionDialog extends JDialog {
|
|||||||
|
|
||||||
// FIXME: Edit Default or override option
|
// FIXME: Edit Default or override option
|
||||||
|
|
||||||
|
|
||||||
|
// Edit default or override option
|
||||||
|
boolean isDefault = component.getStageSeparationConfiguration().isDefault(id);
|
||||||
|
panel.add(new JLabel(trans.get("SeparationSelectionDialog.opt.title")), "span, wrap rel");
|
||||||
|
final JRadioButton defaultButton = new JRadioButton(trans.get("SeparationSelectionDialog.opt.default"), isDefault);
|
||||||
|
panel.add(defaultButton, "span, gapleft para, wrap rel");
|
||||||
|
String str = trans.get("SeparationSelectionDialog.opt.override");
|
||||||
|
str = str.replace("{0}", descriptor.format(rocket, id));
|
||||||
|
final JRadioButton overrideButton = new JRadioButton(str, !isDefault);
|
||||||
|
panel.add(overrideButton, "span, gapleft para, wrap para");
|
||||||
|
|
||||||
|
ButtonGroup buttonGroup = new ButtonGroup();
|
||||||
|
buttonGroup.add(defaultButton);
|
||||||
|
buttonGroup.add(overrideButton);
|
||||||
|
// FIXME: Make buttons work
|
||||||
|
|
||||||
|
|
||||||
// Select separation event
|
// Select separation event
|
||||||
panel.add(new JLabel(trans.get("SeparationSelectionDialog.lbl.separation")), "");
|
panel.add(new JLabel(trans.get("SeparationSelectionDialog.lbl.separation")), "");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user