/* * 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<>(); 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(); } } }