blob: 903c236c8fc263bf612ae56a0492a81fb0b1670e [file] [log] [blame]
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.uiDesigner.radComponents;
import com.intellij.ui.MappingListCellRenderer;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.util.containers.ContainerUtil;
import com.jgoodies.forms.layout.*;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author yole
*/
public class FormLayoutColumnProperties implements CustomPropertiesPanel {
private static final Map<Object, String> UNITS_MAP;
static {
UNITS_MAP = new HashMap<Object, String>();
UNITS_MAP.put("px", UIDesignerBundle.message("unit.pixels"));
UNITS_MAP.put("dlu", UIDesignerBundle.message("unit.dialog.units"));
UNITS_MAP.put("pt", UIDesignerBundle.message("unit.points"));
UNITS_MAP.put("in", UIDesignerBundle.message("unit.inches"));
UNITS_MAP.put("cm", UIDesignerBundle.message("unit.centimeters"));
UNITS_MAP.put("mm", UIDesignerBundle.message("unit.millimeters"));
}
private JPanel myRootPanel;
private JRadioButton myDefaultRadioButton;
private JRadioButton myPreferredRadioButton;
private JRadioButton myMinimumRadioButton;
private JRadioButton myConstantRadioButton;
private JComboBox myConstantSizeUnitsCombo;
private JCheckBox myMinimumCheckBox;
private JCheckBox myMaximumCheckBox;
private JSpinner myMaxSizeSpinner;
private JComboBox myMinSizeUnitsCombo;
private JComboBox myMaxSizeUnitsCombo;
private JSpinner myConstantSizeSpinner;
private JSpinner myMinSizeSpinner;
private JCheckBox myGrowCheckBox;
private JSpinner myGrowSpinner;
private JRadioButton myLeftRadioButton;
private JRadioButton myCenterRadioButton;
private JRadioButton myRightRadioButton;
private JRadioButton myFillRadioButton;
private JLabel myTitleLabel;
private JPanel myAlignmentPanel;
private JPanel mySizePanel;
private FormLayout myLayout;
private int myIndex;
private boolean myIsRow;
private final List<ChangeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private boolean myShowing = false;
private boolean mySaving = false;
public FormLayoutColumnProperties() {
@NonNls String[] unitNames = new String[]{"px", "dlu", "pt", "in", "cm", "mm"};
myConstantSizeUnitsCombo.setModel(new DefaultComboBoxModel(unitNames));
myMinSizeUnitsCombo.setModel(new DefaultComboBoxModel(unitNames));
myMaxSizeUnitsCombo.setModel(new DefaultComboBoxModel(unitNames));
myConstantSizeUnitsCombo.setRenderer(new MappingListCellRenderer(myConstantSizeUnitsCombo.getRenderer(), UNITS_MAP));
myMinSizeUnitsCombo.setRenderer(new MappingListCellRenderer(myMinSizeUnitsCombo.getRenderer(), UNITS_MAP));
myMaxSizeUnitsCombo.setRenderer(new MappingListCellRenderer(myMaxSizeUnitsCombo.getRenderer(), UNITS_MAP));
final MyRadioListener listener = new MyRadioListener();
myDefaultRadioButton.addActionListener(listener);
myPreferredRadioButton.addActionListener(listener);
myMinimumRadioButton.addActionListener(listener);
myConstantRadioButton.addActionListener(listener);
myMinimumCheckBox.addChangeListener(new MyCheckboxListener(myMinimumCheckBox, myMinSizeUnitsCombo, myMinSizeSpinner));
myMaximumCheckBox.addChangeListener(new MyCheckboxListener(myMaximumCheckBox, myMaxSizeUnitsCombo, myMaxSizeSpinner));
myConstantRadioButton.addChangeListener(new MyCheckboxListener(myConstantRadioButton, myConstantSizeUnitsCombo, myConstantSizeSpinner));
updateOnRadioChange();
myGrowCheckBox.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
myGrowSpinner.setEnabled(myGrowCheckBox.isSelected());
updateSpec();
}
});
final MyChangeListener changeListener = new MyChangeListener();
myGrowSpinner.setModel(new SpinnerNumberModel(1.0, 0.0, 10.0, 0.1));
myGrowSpinner.addChangeListener(changeListener);
myMinSizeSpinner.addChangeListener(changeListener);
myMaxSizeSpinner.addChangeListener(changeListener);
myConstantSizeSpinner.addChangeListener(changeListener);
myLeftRadioButton.addChangeListener(changeListener);
myCenterRadioButton.addChangeListener(changeListener);
myRightRadioButton.addChangeListener(changeListener);
myFillRadioButton.addChangeListener(changeListener);
final MyItemListener itemListener = new MyItemListener();
myMinSizeUnitsCombo.addItemListener(itemListener);
myMaxSizeUnitsCombo.addItemListener(itemListener);
myConstantSizeUnitsCombo.addItemListener(itemListener);
}
public JPanel getComponent() {
return myRootPanel;
}
public void addChangeListener(ChangeListener listener) {
myListeners.add(listener);
}
public void removeChangeListener(ChangeListener listener) {
myListeners.remove(listener);
}
public void showProperties(final RadContainer container, final boolean row, final int[] selectedIndices) {
if (mySaving) return;
if (selectedIndices.length == 1) {
showControls(true);
myShowing = true;
try {
myLayout = (FormLayout)container.getLayout();
myIndex = selectedIndices[0] + 1;
myIsRow = row;
myTitleLabel.setText(myIsRow
? UIDesignerBundle.message("title.row.properties", myIndex)
: UIDesignerBundle.message("title.column.properties", myIndex));
myLeftRadioButton.setText(row ? UIDesignerBundle.message("alignment.top") : UIDesignerBundle.message("alignment.left"));
myRightRadioButton.setText(row ? UIDesignerBundle.message("alignment.bottom") : UIDesignerBundle.message("alignment.right"));
mySizePanel.setBorder(IdeBorderFactory.createTitledBorder(myIsRow
? UIDesignerBundle.message("title.height")
: UIDesignerBundle.message("title.width"), true));
FormSpec formSpec = row ? myLayout.getRowSpec(myIndex) : myLayout.getColumnSpec(myIndex);
showAlignment(formSpec.getDefaultAlignment());
showSize(formSpec.getSize());
if (formSpec.getResizeWeight() < 0.01) {
myGrowCheckBox.setSelected(false);
myGrowSpinner.setValue(1.0);
}
else {
myGrowCheckBox.setSelected(true);
myGrowSpinner.setValue(formSpec.getResizeWeight());
}
}
finally {
myShowing = false;
}
}
else {
showControls(false);
if (selectedIndices.length > 1) {
myTitleLabel.setText(myIsRow
? UIDesignerBundle.message("title.multiple.rows.selected")
: UIDesignerBundle.message("title.multiple.columns.selected"));
}
else {
myTitleLabel.setText(myIsRow
? UIDesignerBundle.message("title.no.rows.selected")
: UIDesignerBundle.message("title.no.columns.selected"));
}
}
}
private void showControls(final boolean visible) {
mySizePanel.setVisible(visible);
myAlignmentPanel.setVisible(visible);
myGrowCheckBox.setVisible(visible);
myGrowSpinner.setVisible(visible);
}
private void showAlignment(final FormSpec.DefaultAlignment defaultAlignment) {
if (defaultAlignment.equals(RowSpec.TOP) || defaultAlignment.equals(ColumnSpec.LEFT)) {
myLeftRadioButton.setSelected(true);
}
else if (defaultAlignment.equals(RowSpec.CENTER)) {
myCenterRadioButton.setSelected(true);
}
else if (defaultAlignment.equals(RowSpec.BOTTOM) || defaultAlignment.equals(ColumnSpec.RIGHT)) {
myRightRadioButton.setSelected(true);
}
else {
myFillRadioButton.setSelected(true);
}
}
private void showSize(Size size) {
Size minimumSize = null;
Size maximumSize = null;
if (size instanceof BoundedSize) {
BoundedSize boundedSize = (BoundedSize)size;
minimumSize = boundedSize.getLowerBound();
maximumSize = boundedSize.getUpperBound();
size = boundedSize.getBasis();
}
if (size instanceof ConstantSize) {
myConstantRadioButton.setSelected(true);
myMinimumCheckBox.setEnabled(false);
myMinimumCheckBox.setSelected(false);
myMaximumCheckBox.setEnabled(false);
myMaximumCheckBox.setSelected(false);
showConstantSize((ConstantSize)size, myConstantSizeUnitsCombo, myConstantSizeSpinner);
}
else {
@NonNls String s = size.toString();
if (s.startsWith("m")) {
myMinimumRadioButton.setSelected(true);
}
else if (s.startsWith("p")) {
myPreferredRadioButton.setSelected(true);
}
else {
myDefaultRadioButton.setSelected(true);
}
myMinimumCheckBox.setEnabled(true);
myMaximumCheckBox.setEnabled(true);
if (minimumSize instanceof ConstantSize) {
myMinimumCheckBox.setSelected(true);
myMaximumCheckBox.setEnabled(false); // TODO: remove this code when IDEADEV-9678 is implemented
showConstantSize((ConstantSize)minimumSize, myMinSizeUnitsCombo, myMinSizeSpinner);
}
else {
myMinimumCheckBox.setSelected(false);
}
if (maximumSize instanceof ConstantSize) {
myMaximumCheckBox.setSelected(true);
myMinimumCheckBox.setEnabled(false); // TODO: remove this code when IDEADEV-9678 is implemented
showConstantSize((ConstantSize)maximumSize, myMaxSizeUnitsCombo, myMaxSizeSpinner);
}
else {
myMaximumCheckBox.setSelected(false);
}
}
}
private static void showConstantSize(final ConstantSize size, final JComboBox unitsCombo, final JSpinner spinner) {
double value = size.getValue();
ConstantSize.Unit unit = size.getUnit();
if (unit.equals(ConstantSize.DIALOG_UNITS_X) || unit.equals(ConstantSize.DIALOG_UNITS_Y)) {
unitsCombo.setSelectedItem("dlu");
}
else {
unitsCombo.setSelectedItem(unit.abbreviation());
}
spinner.setModel(new SpinnerNumberModel(0.0, 0.0, Double.MAX_VALUE, 1.0));
spinner.setValue(value);
}
private void updateOnRadioChange() {
final boolean canSetBounds = !myConstantRadioButton.isSelected();
myMinimumCheckBox.setEnabled(canSetBounds);
myMaximumCheckBox.setEnabled(canSetBounds);
// TODO: remove this code when IDEADEV-9678 is implemented
if (myMinimumCheckBox.isSelected()) {
myMaximumCheckBox.setEnabled(false);
myMaximumCheckBox.setSelected(false);
}
else if (myMaximumCheckBox.isSelected()) {
myMinimumCheckBox.setEnabled(false);
}
if (!canSetBounds) {
myMinimumCheckBox.setSelected(false);
myMaximumCheckBox.setSelected(false);
}
updateSpec();
}
private void updateSpec() {
if (myLayout == null || myShowing) return;
mySaving = true;
try {
Size size = getSelectedSize();
final SpinnerNumberModel model = (SpinnerNumberModel)myGrowSpinner.getModel();
double resizeWeight = myGrowCheckBox.isSelected() ? model.getNumber().doubleValue() : 0.0;
FormSpec.DefaultAlignment alignment = getSelectedAlignment();
if (myIsRow) {
myLayout.setRowSpec(myIndex, new RowSpec(alignment, size, resizeWeight));
}
else {
myLayout.setColumnSpec(myIndex, new ColumnSpec(alignment, size, resizeWeight));
}
for (ChangeListener listener : myListeners) {
listener.stateChanged(new ChangeEvent(this));
}
}
finally {
mySaving = false;
}
}
private Size getSelectedSize() {
Size size;
if (myDefaultRadioButton.isSelected()) {
size = Sizes.DEFAULT;
}
else if (myPreferredRadioButton.isSelected()) {
size = Sizes.PREFERRED;
}
else if (myMinimumRadioButton.isSelected()) {
size = Sizes.MINIMUM;
}
else {
size = getConstantSize(myConstantSizeUnitsCombo, myConstantSizeSpinner);
}
if (myMinimumCheckBox.isSelected() || myMaximumCheckBox.isSelected()) {
Size minSize = null;
Size maxSize = null;
if (myMinimumCheckBox.isSelected()) {
minSize = getConstantSize(myMinSizeUnitsCombo, myMinSizeSpinner);
}
if (myMaximumCheckBox.isSelected()) {
maxSize = getConstantSize(myMaxSizeUnitsCombo, myMaxSizeSpinner);
}
size = Sizes.bounded(size, minSize, maxSize);
}
return size;
}
private FormSpec.DefaultAlignment getSelectedAlignment() {
if (myLeftRadioButton.isSelected()) {
return myIsRow ? RowSpec.TOP : ColumnSpec.LEFT;
}
if (myCenterRadioButton.isSelected()) {
return RowSpec.CENTER;
}
if (myRightRadioButton.isSelected()) {
return myIsRow ? RowSpec.BOTTOM : ColumnSpec.RIGHT;
}
return RowSpec.FILL;
}
private ConstantSize getConstantSize(final JComboBox unitsCombo, final JSpinner spinner) {
return Sizes.constant(spinner.getValue().toString() + unitsCombo.getSelectedItem().toString(), myIsRow);
}
private class MyRadioListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
updateOnRadioChange();
}
}
private class MyCheckboxListener implements ChangeListener {
private boolean myWasSelected;
private final AbstractButton myButton;
private final JComboBox myUnitsCombo;
private final JSpinner mySpinner;
public MyCheckboxListener(final AbstractButton button, final JComboBox unitsCombo, final JSpinner spinner) {
myButton = button;
myUnitsCombo = unitsCombo;
mySpinner = spinner;
myWasSelected = myButton.isSelected();
}
public void stateChanged(ChangeEvent e) {
if (myWasSelected != myButton.isSelected()) {
myWasSelected = myButton.isSelected();
myUnitsCombo.setEnabled(myButton.isSelected());
mySpinner.setEnabled(myButton.isSelected());
if (myButton.isSelected() && mySpinner.getValue().equals(new Integer(0))) {
mySpinner.setValue(100);
}
updateOnRadioChange();
}
}
}
private class MyChangeListener implements ChangeListener {
public void stateChanged(ChangeEvent e) {
updateSpec();
}
}
private class MyItemListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
updateSpec();
}
}
}