package net.sourceforge.fidocadj.dialogs;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import net.sourceforge.fidocadj.dialogs.*;
import net.sourceforge.fidocadj.dialogs.OSKeybPanel.KEYBMODES;
import net.sourceforge.fidocadj.globals.*;
import net.sourceforge.fidocadj.layers.*;
import net.sourceforge.fidocadj.graphic.*;
import net.sourceforge.fidocadj.dialogs.mindimdialog.MinimumSizeDialog;
/**
Allows to create a generic dialog, capable of displaying and let the user
modify the parameters of a graphic primitive. The idea is that the dialog
uses a ParameterDescripion vector which contains all the elements, their
description as well as the type. Depending on the contents of the array, the
window will be created automagically.
<pre>
This file is part of FidoCadJ.
FidoCadJ is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FidoCadJ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FidoCadJ. If not,
@see <a href=http://www.gnu.org/licenses/>http://www.gnu.org/licenses/</a>.
Copyright 2007-2015 by Davide Bucci
</pre>
*/
public class DialogParameters extends JDialog
{
private int minWidth = 450;
private int minHeight = 350;
private static final int MAX = 20;
// Maximum number of user interface elements of the same type present
// in the dialog window.
private static final int MAX_ELEMENTS = 20;
public boolean active; // true if the user selected Ok
// Text box array and counter
private final JTextField jtf[];
private int tc; // NOPMD this field can NOT be final! It is a counter.
// Check box array and counter
private final JCheckBox jcb[];
private int cc; // NOPMD this field can NOT be final! It is a counter.
private final JComboBox jco[];
private int co; // NOPMD this field can NOT be final! It is a counter.
private final Vector<ParameterDescription> v;
OSKeybPanel keyb1,keyb2;
JTabbedPane keyb = new JTabbedPane();
/**
Programmatically build a dialog frame containing the appropriate
elements, in order to let the user modify the characteristics of a
graphic primitive.
@param parent the parent frame useful for creating the dialog.
@param vec a ParameterDescription array containing the value and the
description of each parameter that should be edited by the
user.
@param strict true if a strict compatibility with FidoCAD is required
@param layers a vector containing the layers
*/
// Here some legacy code makes use of generics. They are tested, so
// there is no risk of an actual error, but Java issues a warning.
@SuppressWarnings("unchecked")
public DialogParameters(final JFrame parent,
Vector<ParameterDescription> vec,
boolean strict, Vector<LayerDesc> layers)
{
super(parent, Globals.messages.getString("Param_opt"), true);
keyb1 = new OSKeybPanel(KEYBMODES.GREEK);
keyb2 = new OSKeybPanel(KEYBMODES.MISC);
keyb1.setField(this);
keyb2.setField(this);
keyb.addTab("Greek", keyb1);
keyb.addTab("Misc", keyb2);
keyb.setVisible(false);
v = vec;
// We create dynamically all the needed elements.
// For this reason, we work on arrays of the potentially useful Swing
// objects.
jtf = new JTextField[MAX_ELEMENTS];
jcb = new JCheckBox[MAX_ELEMENTS];
jco = new JComboBox[MAX_ELEMENTS];
active = false;
GridBagLayout bgl = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
Container contentPane = getContentPane();
contentPane.setLayout(bgl);
boolean extStrict = strict;
int top = 0;
JLabel lab;
tc = 0;
cc = 0;
co = 0;
// We process all parameter passed. Depending on its type, a
// corresponding interface element will be created.
// A symmetrical operation is done when validating parameters.
int ycount = 0;
for (ParameterDescription pd : v) {
// We do not need to store label objects, since we do not need
// to retrieve data from them.
lab = new JLabel(pd.description);
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 1;
constraints.gridy = ycount;
constraints.gridwidth = 1;
constraints.gridheight = 1;
// The first element needs a little bit more space at the top.
if (ycount == 0)
top = 10;
else
top = 0;
// Here, we configure the grid layout.
constraints.insets = new Insets(top, 20, 0, 6);
constraints.fill = GridBagConstraints.VERTICAL;
constraints.anchor = GridBagConstraints.EAST;
lab.setEnabled(!(pd.isExtension && extStrict));
if (!(pd.parameter instanceof Boolean))
contentPane.add(lab, constraints);
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(top, 0, 0, 0);
constraints.fill = GridBagConstraints.HORIZONTAL;
// Now, depending on the type of parameter we create interface
// elements and we populate the dialog.
if (pd.parameter instanceof PointG) {
jtf[tc] = new JTextField(10);
jtf[tc].setText("" + ((PointG) (pd.parameter)).x);
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 1;
constraints.gridheight = 1;
// Disable FidoCadJ extensions in the strict compatibility mode
jtf[tc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jtf[tc++], constraints);
jtf[tc] = new JTextField(10);
jtf[tc].setText("" + ((PointG) (pd.parameter)).y);
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 3;
constraints.gridy = ycount;
constraints.gridwidth = 1;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 6, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jtf[tc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jtf[tc++], constraints);
} else if (pd.parameter instanceof String) {
jtf[tc] = new JTextField(24);
jtf[tc].setText((String) (pd.parameter));
// If we have a String text field in the first position, its
// contents should be evidenced, since it is supposed to be
// the most important field (e.g. for the AdvText primitive)
if (ycount == 0) {
jtf[tc].selectAll();
}
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jtf[tc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jtf[tc++], constraints);
} else if (pd.parameter instanceof Boolean) {
jcb[cc] = new JCheckBox(pd.description);
jcb[cc].setSelected(((Boolean) (pd.parameter)).booleanValue());
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jcb[cc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jcb[cc++], constraints);
} else if (pd.parameter instanceof Integer) {
jtf[tc] = new JTextField(24);
jtf[tc].setText(((Integer) pd.parameter).toString());
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jtf[tc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jtf[tc++], constraints);
} else if (pd.parameter instanceof Float) {
jtf[tc] = new JTextField(24);
jtf[tc].setText(""+pd.parameter);
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jtf[tc].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jtf[tc++], constraints);
} else if (pd.parameter instanceof FontG) {
GraphicsEnvironment gE;
gE = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] s = gE.getAvailableFontFamilyNames();
jco[co] = new JComboBox();
for (int i = 0; i < s.length; ++i) {
jco[co].addItem(s[i]);
if (s[i].equals(((FontG) pd.parameter).getFamily()))
jco[co].setSelectedIndex(i);
}
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jco[co].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jco[co++], constraints);
} else if (pd.parameter instanceof LayerInfo) {
jco[co] = new JComboBox(new Vector<LayerDesc>(layers));
jco[co].setSelectedIndex(((LayerInfo) pd.parameter).layer);
jco[co].setRenderer(new LayerCellRenderer());
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jco[co].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jco[co++], constraints);
} else if (pd.parameter instanceof ArrowInfo) {
jco[co] = new JComboBox<ArrowInfo>();
jco[co].addItem(new ArrowInfo(0));
jco[co].addItem(new ArrowInfo(1));
jco[co].addItem(new ArrowInfo(2));
jco[co].addItem(new ArrowInfo(3));
jco[co].setSelectedIndex(((ArrowInfo) pd.parameter).style);
jco[co].setRenderer(new ArrowCellRenderer());
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jco[co].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jco[co++], constraints);
} else if (pd.parameter instanceof DashInfo) {
jco[co] = new JComboBox<DashInfo>();
for (int k = 0; k < Globals.dashNumber; ++k) {
jco[co].addItem(new DashInfo(k));
}
jco[co].setSelectedIndex(((DashInfo) pd.parameter).style);
jco[co].setRenderer(new DashCellRenderer());
constraints.weightx = 100;
constraints.weighty = 100;
constraints.gridx = 2;
constraints.gridy = ycount;
constraints.gridwidth = 2;
constraints.gridheight = 1;
constraints.insets = new Insets(top, 0, 0, 20);
constraints.fill = GridBagConstraints.HORIZONTAL;
jco[co].setEnabled(!(pd.isExtension && extStrict));
contentPane.add(jco[co++], constraints);
}
if (ycount++ > MAX)
break;
}
// Put the OK and Cancel buttons and make them active.
JButton ok = new JButton(Globals.messages.getString("Ok_btn"));
JButton cancel = new JButton(Globals.messages.getString("Cancel_btn"));
JButton keybd = new JButton("\u00B6\u2211\u221A");// phylum
keybd.setFocusable(false);
keybd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
// If at this point, the keyboard is not visible, this means
// that it will become visible in a while. It is better to
// resize first and then show up the keyboard.
if (keyb.isVisible()) {
minWidth = 400;
minHeight = 350;
} else {
minWidth = 400;
minHeight = 500;
}
keyb.setVisible(!keyb.isVisible());
pack();
}
});
++ycount;
constraints.gridx = 0;
constraints.gridy = ycount++;
constraints.gridwidth = 4;
constraints.gridheight = 1;
constraints.anchor = GridBagConstraints.EAST;
constraints.insets = new Insets(6, 20, 20, 20);
// Put the OK and Cancel buttons and make them active.
Box b = Box.createHorizontalBox();
b.add(keybd); // phylum
b.add(Box.createHorizontalGlue());
ok.setPreferredSize(cancel.getPreferredSize());
if (Globals.okCancelWinOrder) {
b.add(ok);
b.add(Box.createHorizontalStrut(12));
b.add(cancel);
} else {
b.add(cancel);
b.add(Box.createHorizontalStrut(12));
b.add(ok);
}
contentPane.add(b, constraints);
constraints.gridx = 0;
constraints.gridy = ycount;
constraints.gridwidth = 4;
constraints.gridheight = 1;
constraints.anchor = GridBagConstraints.EAST;
constraints.insets = new Insets(6, 20, 20, 20);
contentPane.add(keyb, constraints);
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
try {
int ycount=0;
//ParameterDescription pd;
tc = 0;
cc = 0;
co = 0;
// Here we read all the contents of the interface and we
// update the contents of the parameter description array.
for (ParameterDescription pd: v) {
if (ycount++ > MAX)
break;
if (pd.parameter instanceof PointG) {
((PointG) (pd.parameter)).x = Integer
.parseInt(jtf[tc++].getText());
((PointG) (pd.parameter)).y = Integer
.parseInt(jtf[tc++].getText());
} else if (pd.parameter instanceof String) {
pd.parameter = jtf[tc++].getText();
} else if (pd.parameter instanceof Boolean) {
pd.parameter = Boolean.valueOf(
jcb[cc++].isSelected());
} else if (pd.parameter instanceof Integer) {
pd.parameter = Integer.valueOf(Integer
.parseInt(jtf[tc++].getText()));
} else if (pd.parameter instanceof Float) {
pd.parameter = Float.valueOf(Float
.parseFloat(jtf[tc++].getText()));
} else if (pd.parameter instanceof FontG) {
pd.parameter = new FontG((String) jco[co++]
.getSelectedItem());
} else if (pd.parameter instanceof LayerInfo) {
pd.parameter = new LayerInfo(jco[co++]
.getSelectedIndex());
} else if (pd.parameter instanceof ArrowInfo) {
pd.parameter = new ArrowInfo(jco[co++]
.getSelectedIndex());
} else if (pd.parameter instanceof DashInfo) {
pd.parameter = new DashInfo(jco[co++]
.getSelectedIndex());
}
}
} catch (NumberFormatException E) {
// Error detected. Probably, the user has entered an
// invalid string when FidoCadJ was expecting a numerical
// input.
JOptionPane.showMessageDialog(parent,
Globals.messages.getString("Format_invalid"), "",
JOptionPane.INFORMATION_MESSAGE);
return;
}
active = true;
setVisible(false);
keyb.setVisible(false);
}
});
// Here is an action in which the dialog is closed
AbstractAction cancelAction = new AbstractAction() {
public void actionPerformed(ActionEvent e)
{
setVisible(false);
keyb.setVisible(false);
}
};
cancel.addActionListener(cancelAction);
DialogUtil.addCancelEscape(this, cancelAction);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
keyb.setVisible(false);
}
});
pack();
DialogUtil.center(this);
getRootPane().setDefaultButton(ok);
}
/**
Get a ParameterDescription vector describing the characteristics
modified by the user.
@return a ParameterDescription vector describing each parameter.
*/
public Vector<ParameterDescription> getCharacteristics()
{
return v;
}
}