/*
* Copyright (c) 2004-2007 by Michael Connor. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of FormLayoutBuilder or Michael Connor nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.mlc.swing.layout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.AbstractListModel;
import javax.swing.AbstractSpinnerModel;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.factories.DefaultComponentFactory;
import com.jgoodies.forms.layout.CellConstraints;
/**
* This is the main panel that is used in LayoutFrame serving as the user
* interface for the builder. This is a pretty juicy file because there is a lot
* going on here. Better docs to come...
*
* @author Michael Connor mlconnor@yahoo.com
@version $Id$
@since Ptolemy II 7.1
*/
@SuppressWarnings("serial")
public class FormEditor extends JPanel {
String[] verticalAlignmentList = { LayoutConstraintsManager.DEFAULT,
LayoutConstraintsManager.FILL, LayoutConstraintsManager.CENTER,
LayoutConstraintsManager.TOP, LayoutConstraintsManager.BOTTOM };
String[] horizontalAlignmentList = { LayoutConstraintsManager.DEFAULT,
LayoutConstraintsManager.FILL, LayoutConstraintsManager.CENTER,
LayoutConstraintsManager.LEFT, LayoutConstraintsManager.RIGHT };
ColSpanSpinnerModel colSpinnerModel = new ColSpanSpinnerModel();
RowSpanSpinnerModel rowSpinnerModel = new RowSpanSpinnerModel();
Action newComponentAction = new NewComponentAction();
Action removeComponentAction = new RemoveComponentAction();
Action insertRowBeforeAction = new InsertRowBeforeAction();
Action insertRowAfterAction = new InsertRowAfterAction();
Action deleteRowAction = new DeleteRowAction();
Action insertColumnBeforeAction = new InsertColumnBeforeAction();
Action insertColumnAfterAction = new InsertColumnAfterAction();
Action deleteColumnAction = new DeleteColumnAction();
JComboBox verticalAlignmentCombo = new JComboBox(verticalAlignmentList);
JComboBox horizontalAlignmentCombo = new JComboBox(horizontalAlignmentList);
JSpinner rowSpanSpinner = new JSpinner(rowSpinnerModel);
JSpinner columnSpanSpinner = new JSpinner(colSpinnerModel);
JLabel columnSpanLabel = new JLabel("Column Span");
JLabel horizontalAlignmentLabel = new JLabel("Horizontal Alignment");
JLabel rowSpanLabel = new JLabel("Row Span");
JLabel verticalAlignmentLabel = new JLabel("Vertical Alignment");
JPanel contentPanel = new JPanel();
JPanel insetsPanel = new JPanel();
SpinnerNumberModel rightInsetSpinnerModel = new SpinnerNumberModel(0, 0,
Integer.MAX_VALUE, 1);
SpinnerNumberModel topInsetSpinnerModel = new SpinnerNumberModel(0, 0,
Integer.MAX_VALUE, 1);
SpinnerNumberModel bottomInsetSpinnerModel = new SpinnerNumberModel(0, 0,
Integer.MAX_VALUE, 1);
SpinnerNumberModel leftInsetSpinnerModel = new SpinnerNumberModel(0, 0,
Integer.MAX_VALUE, 1);
JSpinner rightInsetSpinner = new JSpinner(rightInsetSpinnerModel);
JSpinner bottomInsetSpinner = new JSpinner(bottomInsetSpinnerModel);
JSpinner leftInsetSpinner = new JSpinner(leftInsetSpinnerModel);
JSpinner topInsetSpinner = new JSpinner(topInsetSpinnerModel);
GridTableModel tableModel = new GridTableModel();
JLabel insetsLabel = new JLabel("Insets");
JLabel componentsLabel = new JLabel("Components (Drag n Drop)");
JLabel componentPaletteLabel = new JLabel("Palette (Drag n Drop)");
ComponentPaletteListModel componentPaletteListModel = new ComponentPaletteListModel();
// KBR JList componentPalette = new JList(componentPaletteListModel);
DndList componentPalette = new DndList(this, componentPaletteListModel);
JScrollPane componentPaletteScrollPane = new JScrollPane(componentPalette);
ComponentSelectionListModel componentSelectionListModel = new ComponentSelectionListModel();
DndList componentList = new DndList(this, componentSelectionListModel);
JScrollPane componentListScrollPane = new JScrollPane(componentList);
ComponentListCellRenderer componentListCellRenderer = new ComponentListCellRenderer();
Component constraintsSeparator = DefaultComponentFactory.getInstance()
.createSeparator("Component Constraints");
Component positionsSeparator = DefaultComponentFactory.getInstance()
.createSeparator("Component Positions (Drag n Drop)");
JPanel componentsPanel = new JPanel();
JPanel propertiesPanel = new JPanel();
JSplitPane componentsSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
componentsPanel, propertiesPanel);
JTextField colSpecField = new JTextField();
JTextField rowSpecField = new JTextField();
Set<Component> newComponents = new HashSet<Component>();
LayoutConstraintsManager layoutConstraintsManager;
JToolBar toolbar = new JToolBar();
JButton newComponentButton = new JButton(newComponentAction);
JButton removeComponentButton = new JButton(removeComponentAction);
JButton columnDeleteButton = new JButton(deleteColumnAction);
JButton columnInsertAfterButton = new JButton(insertColumnAfterAction);
JButton columnInsertBeforeButton = new JButton(insertColumnBeforeAction);
JButton rowDeleteButton = new JButton(deleteRowAction);
JButton rowInsertBeforeButton = new JButton(insertRowBeforeAction);
JButton rowInsertAfterButton = new JButton(insertRowAfterAction);
Container container;
ContainerLayout containerLayout;
MultiContainerFrame layoutFrame;
DnDTable table = null;
JScrollPane tableScrollPane = null;
JSplitPane constraintsSplitPane = null;
Component topComponent = null;
boolean suspendConstraintControlUpdates = false;
void setContainer(Container container) {
java.awt.LayoutManager layoutManager = container.getLayout();
if (!(layoutManager instanceof ContainerLayout)) {
throw new RuntimeException(
"Container layout must be of type ContainerLayout");
}
this.container = container;
}
public FormEditor(MultiContainerFrame layoutFrame, ContainerLayout layout,
Container container) {
super();
this.layoutFrame = layoutFrame;
table = new DnDTable(layoutFrame, this);
tableScrollPane = new JScrollPane(table);
constraintsSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
tableScrollPane, componentsSplitPane);
setContainer(container);
containerLayout = layout;
table.setBackground(java.awt.Color.white);
table.setSelectionBackground(new Color(220, 220, 255));
table.setSelectionForeground(Color.black);
table.setDefaultRenderer(Object.class,
new ConstraintTableCellRenderer());
table.setRowHeight(20);
table.setModel(tableModel);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// let's put the cursor in the table so the create component
// icon is enabled. at least then the user knows what to do...
if (tableModel.getRowCount() > 1 && tableModel.getColumnCount() > 1) {
// KBR do NOT force visible so constraints row can still be seen
setSelectedCell(1, 1, false);
}
componentList.setCellRenderer(componentListCellRenderer);
// let's setup all of the usability stuff...
componentsLabel.setLabelFor(componentListScrollPane);
// componentsLabel.setDisplayedMnemonic(KeyEvent.VK_S);
verticalAlignmentLabel.setLabelFor(verticalAlignmentCombo);
verticalAlignmentLabel.setDisplayedMnemonic(KeyEvent.VK_V);
horizontalAlignmentLabel.setLabelFor(horizontalAlignmentCombo);
horizontalAlignmentLabel.setDisplayedMnemonic(KeyEvent.VK_H);
columnSpanLabel.setLabelFor(columnSpanSpinner);
columnSpanLabel.setDisplayedMnemonic(KeyEvent.VK_C);
rowSpanLabel.setLabelFor(rowSpanSpinner);
rowSpanLabel.setDisplayedMnemonic(KeyEvent.VK_R);
columnInsertAfterButton
.setToolTipText("Insert a column after this column");
columnInsertBeforeButton
.setToolTipText("Insert a column before this column");
columnDeleteButton.setToolTipText("Delete this column");
rowInsertBeforeButton.setToolTipText("Insert a row before this row");
rowInsertAfterButton.setToolTipText("Insert a row after this row");
// let's setup the table toolbar
toolbar.add(newComponentButton);
toolbar.add(removeComponentButton);
toolbar.addSeparator();
toolbar.add(columnDeleteButton);
toolbar.add(columnInsertBeforeButton);
toolbar.add(columnInsertAfterButton);
toolbar.addSeparator();
toolbar.add(rowDeleteButton);
toolbar.add(rowInsertBeforeButton);
toolbar.add(rowInsertAfterButton);
setFormComponent(null);
layoutConstraintsManager = LayoutConstraintsManager
.getLayoutConstraintsManager(this.getClass()
.getResourceAsStream("editableLayoutConstraints.xml"));
layoutConstraintsManager.setLayout("mainLayout", contentPanel);
layoutConstraintsManager.setLayout("insetsLayout", insetsPanel);
layoutConstraintsManager.setLayout("componentsLayout", componentsPanel);
layoutConstraintsManager.setLayout("propertiesLayout", propertiesPanel);
insetsPanel.add(rightInsetSpinner, "rightInsetSpinner");
insetsPanel.add(leftInsetSpinner, "leftInsetSpinner");
insetsPanel.add(topInsetSpinner, "topInsetSpinner");
insetsPanel.add(bottomInsetSpinner, "bottomInsetSpinner");
componentsPanel.add(componentListScrollPane, "componentListScrollPane");
componentsPanel.add(componentsLabel, "componentsLabel");
propertiesPanel.add(componentPaletteScrollPane,
"componentPaletteScrollPane");
componentPalette.setCellRenderer(new ComponentPaletteListRenderer());
propertiesPanel.add(componentPaletteLabel, "componentPaletteLabel");
contentPanel.add(rowSpanLabel, "rowSpanLabel");
contentPanel.add(horizontalAlignmentCombo, "horizontalAlignmentCombo");
contentPanel.add(horizontalAlignmentLabel, "horizontalAlignmentLabel");
contentPanel.add(rowSpanSpinner, "rowSpanSpinner");
contentPanel.add(verticalAlignmentCombo, "verticalAlignmentCombo");
contentPanel.add(columnSpanLabel, "columnSpanLabel");
contentPanel.add(verticalAlignmentLabel, "verticalAlignmentLabel");
contentPanel.add(columnSpanSpinner, "columnSpanSpinner");
contentPanel.add(insetsPanel, "insetsPanel");
contentPanel.add(insetsLabel, "insetsLabel");
contentPanel.add(constraintsSeparator, "constraintsSeparator");
contentPanel.add(positionsSeparator, "positionsSeparator");
contentPanel.add(toolbar, "toolbar");
contentPanel.add(constraintsSplitPane, "constraintsSplitPane");
constraintsSplitPane.setDividerLocation(605);
contentPanel.setBorder(Borders.DIALOG_BORDER);
setLayout(new BorderLayout());
add(contentPanel, BorderLayout.CENTER);
setupListeners();
}
private void setupListeners() {
verticalAlignmentCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component component = table.getSelectedControl();
if (component != null) {
CellConstraints cellConstraints = getComponentConstraints(component);
cellConstraints.vAlign = LayoutConstraintsManager
.getAlignment((String) verticalAlignmentCombo
.getSelectedItem());
updateLayout(component);
}
}
});
horizontalAlignmentCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Component component = table.getSelectedControl();
if (component != null) {
CellConstraints cellConstraints = getComponentConstraints(component);
cellConstraints.hAlign = LayoutConstraintsManager
.getAlignment((String) horizontalAlignmentCombo
.getSelectedItem());
updateLayout(component);
}
}
});
topInsetSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (!suspendConstraintControlUpdates) {
Component component = table.getSelectedControl();
CellConstraints constraints = getComponentConstraints(component);
Insets insets = new Insets(topInsetSpinnerModel.getNumber()
.intValue(), constraints.insets.left,
constraints.insets.bottom, constraints.insets.right);
constraints.insets = insets;
updateLayout(component);
}
}
});
leftInsetSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (!suspendConstraintControlUpdates) {
Component component = table.getSelectedControl();
CellConstraints constraints = getComponentConstraints(component);
Insets insets = new Insets(constraints.insets.top,
leftInsetSpinnerModel.getNumber().intValue(),
constraints.insets.bottom, constraints.insets.right);
constraints.insets = insets;
updateLayout(component);
}
}
});
rightInsetSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (!suspendConstraintControlUpdates) {
Component component = table.getSelectedControl();
CellConstraints constraints = getComponentConstraints(component);
Insets insets = new Insets(constraints.insets.top,
constraints.insets.left, constraints.insets.bottom,
rightInsetSpinnerModel.getNumber().intValue());
constraints.insets = insets;
updateLayout(component);
}
}
});
bottomInsetSpinnerModel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (!suspendConstraintControlUpdates) {
Component component = table.getSelectedControl();
CellConstraints constraints = getComponentConstraints(component);
Insets insets = new Insets(constraints.insets.top,
constraints.insets.left, bottomInsetSpinnerModel
.getNumber().intValue(),
constraints.insets.right);
constraints.insets = insets;
updateLayout(component);
}
}
});
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
Point p = e.getPoint();
int row = table.rowAtPoint(p);
int col = table.columnAtPoint(p);
// support double-click:
Component component = table.getSelectedControl();
if (component == null) {
return;
}
/* invoke componentDef editor on double-clicked control */
String name = getComponentName(component);
ComponentDef componentDef = containerLayout
.getComponentDef(name);
if (componentDef != null) {
editComponent(componentDef, component,
new CellConstraints(col, row));
}
}
}
});
componentList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
/* set selected component as selected, which causes a
* scroll-to-visible in the table */
Component thisComponent = (Component) componentList
.getSelectedValue();
CellConstraints constraints = getComponentConstraints(thisComponent);
if (constraints == null) {
throw new RuntimeException(
"Unable to find constraints for component "
+ thisComponent + " in layout "
+ containerLayout.getName());
}
int col = constraints.gridX;
int row = constraints.gridY;
table.changeSelection(row, col, false, false);
topComponent = thisComponent;
}
}
});
componentList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int index = componentList.locationToIndex(e.getPoint());
if (index == -1) {
return;
}
// Get item
ListModel lm = ((DndList) e.getSource()).getModel();
Component thisComponent = (Component) lm
.getElementAt(index);
String name = getComponentName(thisComponent);
ComponentDef compDef = containerLayout
.getComponentDef(name);
CellConstraints constraints = getComponentConstraints(thisComponent);
if (constraints == null) {
throw new RuntimeException(
"Unable to find constraints for component "
+ thisComponent + " in layout "
+ containerLayout.getName());
}
editComponent(compDef, thisComponent, constraints);
}
}
});
}
String getComponentName(Component control) {
return containerLayout.getComponentName(control);
}
CellConstraints getComponentConstraints(Component component) {
return containerLayout.getComponentConstraints(component);
}
private void specsChanged() {
updateLayouts();
// lets go down the tree
Component[] children = container.getComponents();
for (int index = 0; index < children.length; index++) {
Component component = children[index];
if (component instanceof Container) {
((Container) component).doLayout();
}
}
}
void updateLayouts() {
container.validate();
container.doLayout();
Container parent = container;
while (parent != null) {
parent.validate();
parent = parent.getParent();
}
}
private void setSelectedCell(int columnIndex, int rowIndex,
boolean forceVisible) {
// we don't want to update the selection interval if nothing changed...
table.getSelectionModel().setSelectionInterval(rowIndex, rowIndex);
table.getColumnModel().getSelectionModel().setSelectionInterval(
columnIndex, columnIndex);
if (forceVisible) {
// let's make sure the cell is in the visible range...
JViewport viewport = (JViewport) table.getParent();
Rectangle rect = table.getCellRect(rowIndex, columnIndex, true);
Point pt = viewport.getViewPosition();
rect.setLocation(rect.x - pt.x, rect.y - pt.y);
viewport.scrollRectToVisible(rect);
}
}
@SuppressWarnings("serial")
private class ComponentSelectionListModel extends
javax.swing.AbstractListModel {
// private String selectedName = null;
List<Component> sortedComponents = new ArrayList<Component>();
public ComponentSelectionListModel() {
super();
}
// Bug: when the user does the following:
// 1) drags a new control into place
// 2) drags a 2nd new control into place
// 3) deletes the 2nd control
// 4) drags a new 2nd control into place
// we get an array out of bounds exception in getElementAt. The
// delete probably failed to update our list.
public Object getElementAt(int index) {
Component component = sortedComponents.get(index);
return component;
}
public int getSize() {
sortedComponents = new ArrayList<Component>();
if (container != null) {
Component[] containerComponents = container.getComponents();
for (int index = 0; index < containerComponents.length; index++) {
Component insertComponent = containerComponents[index];
String insertComponentName = getComponentName(insertComponent);
int insertIndex = 0;
while (insertIndex < sortedComponents.size()
&& insertComponentName != null) {
Component testComponent = sortedComponents
.get(insertIndex);
String testName = getComponentName(testComponent);
if (testName != null) {
testName = testName.toUpperCase();
}
if (insertComponentName.toUpperCase().compareTo(
testName) <= 0) {
break;
} else {
insertIndex++;
}
}
sortedComponents.add(insertIndex, insertComponent);
}
}
return container != null ? container.getComponentCount() : 0;
}
public void fireDelete() {
super.fireContentsChanged(this, 0, Math.max(0, container
.getComponents().length - 1));
}
public void fireInsert() {
super.fireContentsChanged(this, 0, Math.max(0, container
.getComponents().length - 1));
}
}
class ComponentListCellRenderer extends JLabel implements ListCellRenderer {
private static final long serialVersionUID = 1L;
Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public ComponentListCellRenderer() {
super();
setOpaque(true);
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component component = (Component) value;
String name = getComponentName(component);
setComponentOrientation(list.getComponentOrientation());
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setText(name != null ? name : "(Untitled)");
setEnabled(list.isEnabled());
Font font = list.getFont();
setFont(font.deriveFont(component.isVisible() ? Font.PLAIN
: Font.BOLD));
setBorder((cellHasFocus) ? UIManager
.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
return this;
}
}
private void insertColumn(int column) {
for (int index = 0; index < container.getComponentCount(); index++) {
Component component = container.getComponent(index);
CellConstraints constraints = getComponentConstraints(component);
if (constraints.gridX > column) {
constraints.gridX++;
}
}
try {
containerLayout.addColumnSpec(column, "pref");
tableModel.fireTableStructureChanged();
setSelectedCell(column + 1, 0, true);
specsChanged();
} catch (IllegalArgumentException iae) {
JOptionPane.showMessageDialog(FormEditor.this, iae.getMessage(),
"Invalid Layout", JOptionPane.ERROR_MESSAGE);
}
}
private void insertRow(int rowIndex) {
for (int index = 0; index < container.getComponentCount(); index++) {
Component component = container.getComponent(index);
CellConstraints constraints = getComponentConstraints(component);
if (constraints.gridY > rowIndex) {
constraints.gridY++;
}
}
try {
containerLayout.addRowSpec(rowIndex, "pref");
tableModel.fireTableStructureChanged();
setSelectedCell(0, rowIndex + 1, true);
specsChanged();
} catch (IllegalArgumentException iae) {
JOptionPane.showMessageDialog(FormEditor.this, iae.getMessage(),
"Invalid Layout", JOptionPane.ERROR_MESSAGE);
}
}
Component formComponent = null;
// this method will act as the controller for the buttons
// and the cell constraints form
public void setFormComponent(Component component) {
// KBR with this, selecting header row then table body row, doesn't enable
// 'add'
// if ( component == formComponent )
// return;
formComponent = component;
CellConstraints constraints = formComponent != null ? getComponentConstraints(formComponent)
: null;
suspendConstraintControlUpdates = true;
if (formComponent != null) {
rowSpinnerModel.setComponent(formComponent);
colSpinnerModel.setComponent(formComponent);
verticalAlignmentCombo.setSelectedItem(LayoutConstraintsManager
.getAlignment(constraints.vAlign));
horizontalAlignmentCombo.setSelectedItem(LayoutConstraintsManager
.getAlignment(constraints.hAlign));
topInsetSpinnerModel.setValue(Integer
.valueOf(constraints.insets.top));
bottomInsetSpinnerModel.setValue(Integer
.valueOf(constraints.insets.bottom));
rightInsetSpinnerModel.setValue(Integer
.valueOf(constraints.insets.right));
leftInsetSpinnerModel.setValue(Integer
.valueOf(constraints.insets.left));
}
verticalAlignmentCombo.setEnabled(constraints != null);
horizontalAlignmentCombo.setEnabled(constraints != null);
rightInsetSpinner.setEnabled(constraints != null);
leftInsetSpinner.setEnabled(constraints != null);
topInsetSpinner.setEnabled(constraints != null);
bottomInsetSpinner.setEnabled(constraints != null);
rowSpanSpinner.setEnabled(constraints != null);
columnSpanSpinner.setEnabled(constraints != null);
int col = table.getSelectedColumn();
int row = table.getSelectedRow();
// Don't allow 'add' on top of existing component
newComponentAction.setEnabled(col > 0 && row > 0
&& formComponent == null);
removeComponentAction.setEnabled(constraints != null);
columnDeleteButton.setEnabled(row == 0 && col > 0
&& containerLayout.getColumnCount() > 1);
columnInsertAfterButton.setEnabled(col > -1);
columnInsertBeforeButton.setEnabled(col > 0);
rowDeleteButton.setEnabled(col == 0 && row > 0
&& containerLayout.getRowCount() > 1);
rowInsertBeforeButton.setEnabled(row > 0);
rowInsertAfterButton.setEnabled(row > -1);
suspendConstraintControlUpdates = false;
}
public void updateLayout(Component component) {
if (suspendConstraintControlUpdates) {
return;
}
CellConstraints constraints = getComponentConstraints(component);
// we have to update the containerLayout which is the keeper of all
// constraints. if we didn't do this then we wouldn't notice any changes
// when we went to print everything out.
String name = getComponentName(component);
// i don't like this direct access thing. this should be changed...
containerLayout.setCellConstraints(name, constraints);
// updateForm();
// be careful when modifying the next few lines of code. this
// is tricky to get right. this seems to work.
container.invalidate();
container.doLayout();
// KBR list (for example) doesn't seem to re-layout properly on drag&drop
// without these
container.validate();
container.repaint();
if (component instanceof Container) {
Container cContainer = (Container) component;
cContainer.invalidate();
cContainer.doLayout();
}
}
private class ColSpanSpinnerModel extends AbstractSpinnerModel {
CellConstraints constraints;
Component component;
public ColSpanSpinnerModel() {
}
public void setComponent(Component component) {
this.component = component;
if (component != null) {
constraints = getComponentConstraints(component);
fireStateChanged();
} else {
constraints = null;
}
}
public Object getNextValue() {
if (constraints == null) {
return null;
}
Integer next = constraints.gridX + constraints.gridWidth - 1 < containerLayout
.getColumnCount() ? Integer
.valueOf(constraints.gridWidth + 1) : null;
return next;
}
public Object getPreviousValue() {
if (constraints == null) {
return null;
} else {
Integer previous = constraints.gridWidth > 1 ? Integer
.valueOf(constraints.gridWidth - 1) : null;
return previous;
}
}
public Object getValue() {
if (constraints == null) {
return "";
} else {
return Integer.valueOf(constraints.gridWidth);
}
}
public void setValue(Object value) {
if (constraints == null || value == null) {
return;
}
// Number val = (Number) value;
constraints.gridWidth = ((Number) value).intValue();
super.fireStateChanged();
updateLayout(component);
// firing table data changed messes up the
// selection so we'll get it and then restore it...
int col = table.getSelectedColumn();
int row = table.getSelectedRow();
tableModel.fireTableDataChanged();
setSelectedCell(col, row, true);
}
}
private class RowSpanSpinnerModel extends AbstractSpinnerModel {
CellConstraints constraints;
Component component;
public RowSpanSpinnerModel() {
}
public void setComponent(Component component) {
this.component = component;
if (component != null) {
constraints = getComponentConstraints(component);
fireStateChanged();
} else {
constraints = null;
}
}
public Object getNextValue() {
if (constraints == null) {
return null;
} else {
Integer next = constraints.gridY + constraints.gridHeight - 1 < containerLayout
.getRowCount() ? Integer
.valueOf(constraints.gridHeight + 1) : null;
return next;
}
}
public Object getPreviousValue() {
if (constraints == null) {
return null;
} else {
Integer previous = constraints.gridHeight > 1 ? Integer
.valueOf(constraints.gridHeight - 1) : null;
return previous;
}
}
public Object getValue() {
if (constraints == null) {
return "";
} else {
return Integer.valueOf(constraints.gridHeight);
}
}
public void setValue(Object value) {
if (constraints == null || value == null) {
return;
}
// Number val = (Number) value;
constraints.gridHeight = ((Number) value).intValue();
super.fireStateChanged();
updateLayout(component);
// firing table data changed messes up the
// selection so we'll get it and then restore it...
int col = table.getSelectedColumn();
int row = table.getSelectedRow();
tableModel.fireTableDataChanged();
setSelectedCell(col, row, true);
}
}
/**
* Returns true if the named component was created by hand in this session
*/
public boolean isNewComponent(Component component) {
return newComponents.contains(component);
}
@SuppressWarnings("serial")
private class NewComponentDialog0 extends JDialog {
JTextField nameField = new JTextField();
JLabel nameLabel = new JLabel("Name");
JLabel typeLabel = new JLabel("Type");
JButton okButton = new JButton("OK");
JButton cancelButton = new JButton("Cancel");
JComboBox typeCombo = new JComboBox();
PropertyTableModel propertyTableModel = new PropertyTableModel();
JTable propertyTable = new JTable();
JScrollPane propertyScrollPane = new JScrollPane(propertyTable);
boolean wasSuccessful = false;
Component component = null;
Map<String, Object> controlProperties = new HashMap<String, Object>();
public NewComponentDialog0(Frame owner) throws Exception {
super(owner, "Add Component", true);
okButton.setMnemonic(KeyEvent.VK_O);
cancelButton.setMnemonic(KeyEvent.VK_C);
nameLabel.setDisplayedMnemonic(KeyEvent.VK_N);
typeLabel.setDisplayedMnemonic(KeyEvent.VK_T);
nameLabel.setLabelFor(nameField);
typeLabel.setLabelFor(typeCombo);
// FormLayout layout = new FormLayout("right:max(40dlu;pref), 3dlu, 130dlu",
// "");
JPanel content = new JPanel();
content.setBorder(Borders.DIALOG_BORDER);
layoutConstraintsManager.setLayout("newComponentContent", content);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(content, BorderLayout.CENTER);
content.add(typeCombo, "typeCombo");
content.add(nameField, "nameField");
content.add(typeLabel, "typeLabel");
content.add(nameLabel, "nameLabel");
content.add(propertyScrollPane, "propertyScrollPane");
content.add(com.jgoodies.forms.factories.ButtonBarFactory
.buildRightAlignedBar(new JButton[] { okButton,
cancelButton }), "buttonPanel");
propertyTable.putClientProperty("terminateEditOnFocusLost",
Boolean.TRUE);
propertyTable.setModel(propertyTableModel);
pack();
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JButton.class, new String[] { "text" }));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JCheckBox.class, new String[] { "text" }));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JComboBox.class));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JLabel.class, new String[] { "text" }));
typeCombo.addItem(new JListComponentBuilder());
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JPanel.class));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JPasswordField.class));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JRadioButton.class, new String[] { "text" }));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JScrollPane.class));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JSpinner.class));
typeCombo.addItem(new JTableComponentBuilder());
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JTextArea.class));
typeCombo.addItem(new DefaultComponentBuilder(
javax.swing.JTextField.class));
typeCombo.addItem(new JToolBarComponentBuilder());
typeCombo.addItem(new JTreeComponentBuilder());
typeCombo.addItem(new SeparatorComponentBuilder());
typeCombo.addItem(new ButtonBarComponentBuilder());
typeCombo.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
controlProperties = new HashMap<String, Object>();
propertyTableModel.fireTableDataChanged();
}
});
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
if (nameField.getText().trim().length() == 0) {
throw new Exception("The name field is required");
}
// int currentCol = propertyTable.getSelectedColumn();
// int currentRow = propertyTable.getSelectedRow();
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
component = builder.getInstance(controlProperties);
wasSuccessful = true;
dispose();
} catch (Exception exception) {
exception.printStackTrace();
wasSuccessful = false;
JOptionPane.showMessageDialog(null, exception
.getMessage(), "Error Creating Component",
JOptionPane.ERROR_MESSAGE);
}
}
});
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
wasSuccessful = false;
dispose();
}
});
}
public boolean wasSuccessful() {
return wasSuccessful;
}
public String getComponentName() {
return nameField.getText();
}
// public String getComponentDeclaration() {
// ComponentBuilder builder = (ComponentBuilder) typeCombo
// .getSelectedItem();
// return builder
// .getDeclaration(getComponentName(), controlProperties);
// }
public boolean isUsingLayoutComponent() {
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
return builder.isComponentALayoutContainer();
}
public Component getComponent() {
return component;
}
public ComponentDef getComponentDef() {
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
return builder.getComponentDef(getComponentName(),
controlProperties);
}
private class PropertyTableModel extends
javax.swing.table.AbstractTableModel {
public int getColumnCount() {
return 2;
}
public int getRowCount() {
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
return builder != null ? builder.getProperties().size() : 0;
}
public boolean isCellEditable(int row, int col) {
return col == 1;
}
public String getColumnName(int col) {
return col == 0 ? "Property" : "Value";
}
public void setValueAt(Object aValue, int row, int col) {
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
List<BeanProperty> properties = builder.getProperties();
BeanProperty property = properties.get(row);
controlProperties.put(property.getName(), aValue);
}
public Object getValueAt(int rowIndex, int columnIndex) {
ComponentBuilder builder = (ComponentBuilder) typeCombo
.getSelectedItem();
List<BeanProperty> properties = builder.getProperties();
BeanProperty property = properties.get(rowIndex);
return columnIndex == 0 ? property.getName()
: controlProperties.get(property.getName());
}
// public Component getComponent() throws Exception {
// ComponentBuilder builder = (ComponentBuilder) typeCombo
// .getSelectedItem();
// Component instance = builder.getInstance(controlProperties);
// return instance;
// }
}
}
@SuppressWarnings("serial")
private class ConstraintTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
String stringValue = null;
if (value != null) {
if (value instanceof Component) {
String name = getComponentName((Component) value);
stringValue = name == null ? "(Untitled)" : name;
} else {
// in this case it's a row or col header
stringValue = (String) value;
}
}
return super.getTableCellRendererComponent(table, stringValue,
isSelected, hasFocus, row, column);
}
}
@SuppressWarnings("serial")
private class GridTableModel extends javax.swing.table.AbstractTableModel {
public int getColumnCount() {
return containerLayout != null ? containerLayout.getColumnCount() + 1
: 1;
}
public int getRowCount() {
return containerLayout != null ? containerLayout.getRowCount() + 1
: 1;
}
public boolean isCellEditable(int row, int col) {
return (row == 0 || col == 0) && !(row == 0 && col == 0);
}
public String getColumnName(int col) {
return col == 0 ? "*" : "" + col;
}
public void setValueAt(Object aValue, int row, int col) {
String value = (String) aValue;
if (row == 0) // a column was changed
{
try {
containerLayout.setColumnSpec(col - 1, value);
specsChanged();
} catch (IllegalArgumentException iae) {
JOptionPane.showMessageDialog(FormEditor.this, iae
.getMessage(), "Invalid Layout",
JOptionPane.ERROR_MESSAGE);
}
} else if (col == 0) {
try {
containerLayout.setRowSpec(row - 1, value);
specsChanged();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(),
"Invalid row specification",
JOptionPane.ERROR_MESSAGE);
}
}
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == 0 && columnIndex == 0) {
return null;
}
if (rowIndex == 0) {
return containerLayout.getColumnSpec(columnIndex - 1);
}
if (columnIndex == 0) {
return containerLayout.getRowSpec(rowIndex - 1);
}
Component component = null;
for (int index = 0; index < container.getComponentCount(); index++) {
Component thisComponent = container.getComponent(index);
// we don't want to show invisible components. we
// have decided to make components that are added without
// constraints invisible until they are dropped onto the form.
// this is our way of hiding them.
if (thisComponent.isVisible()) {
CellConstraints constraints = getComponentConstraints(thisComponent);
if (constraints == null) {
throw new RuntimeException(
"Unable to find constraints for component "
+ thisComponent + " in layout "
+ containerLayout.getName());
}
if (columnIndex >= constraints.gridX
&& columnIndex < constraints.gridX
+ constraints.gridWidth
&& rowIndex >= constraints.gridY
&& rowIndex < constraints.gridY
+ constraints.gridHeight) {
component = thisComponent;
if (component == topComponent) {
break;
}
}
}
}
return component;
}
}
@SuppressWarnings("serial")
private class RemoveComponentAction extends AbstractAction {
public RemoveComponentAction() {
super();
putValue(Action.SHORT_DESCRIPTION, "Remove the component (Alt+D)");
putValue(Action.LONG_DESCRIPTION, "Remove the component (Alt+D)");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("Remove24.gif")));
putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(
KeyEvent.VK_D, KeyEvent.CTRL_MASK));
}
public void actionPerformed(ActionEvent e) {
Component selectedControl = table.getSelectedControl();
String controlName = getComponentName(selectedControl);
container.remove(selectedControl);
tableModel.fireTableDataChanged();
if (selectedControl instanceof Container
&& layoutFrame.hasContainer(controlName)) {
layoutFrame.removeContainer(controlName);
}
container.doLayout();
container.repaint();
componentSelectionListModel.fireDelete();
setFormComponent(null);
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class NewComponentAction extends AbstractAction {
public NewComponentAction() {
super();
putValue(Action.SHORT_DESCRIPTION, "Create a new component (Alt+N)");
putValue(Action.LONG_DESCRIPTION, "Create a new component (Alt+N)");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("New24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_N));
}
public void actionPerformed(ActionEvent e) {
Frame frame = (Frame) SwingUtilities.getAncestorOfClass(
Frame.class, FormEditor.this);
NewComponentDialog0 newComponentDialog = null;
int columnIndex = table.getSelectedColumn();
int rowIndex = table.getSelectedRow();
try {
newComponentDialog = new NewComponentDialog0(frame);
newComponentDialog.setVisible(true);
} catch (Exception ex) {
ex.printStackTrace();
}
if (newComponentDialog.wasSuccessful()) {
String controlName = newComponentDialog.getComponentName();
Component newControl = newComponentDialog.getComponent();
ComponentDef newCD = newComponentDialog.getComponentDef();
if (containerLayout.getCellConstraints(controlName) != null) {
JOptionPane.showMessageDialog(FormEditor.this,
"A component named '" + controlName
+ "' already exists", "Error",
JOptionPane.ERROR_MESSAGE);
} else {
// the best way to add this control is to setup the constraints
// in the map of name->constraints and then add it to the container.
// this layout manager will intercept it, find the constraints and
// then
// set it up properly in the table and assign the maps.
CellConstraints newConstraints = new CellConstraints(
columnIndex, rowIndex);
if (newCD != null) {
containerLayout.addComponent(controlName, newCD,
newConstraints);
}
containerLayout.getCellConstraints().put(controlName,
newConstraints);
container.add(newControl, controlName);
// we need to keep track of the new components added so we can present
// some code to the user to add back into their module.
// newComponents.put(controlName,
// newComponentDialog.getComponentDeclaration());
// if it's a panel, let's add it to the LayoutFrame so it can be
// manipulated too...
if (newComponentDialog.isUsingLayoutComponent()) {
Container newContainer = (Container) newControl;
layoutFrame.addContainer(controlName, newContainer);
}
componentSelectionListModel.fireInsert();
table.changeSelection(newConstraints.gridY,
newConstraints.gridX, false, false);
updateLayout(newControl); // relayout preview
updateLayouts(); // relayout all panels
newComponents.add(newControl); // we're not generating code unless this happens
}
}
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class InsertRowBeforeAction extends AbstractAction {
public InsertRowBeforeAction() {
super();
putValue(Action.SHORT_DESCRIPTION,
"Inserts a row before the selected row");
putValue(Action.LONG_DESCRIPTION,
"Inserts a row before the selected row");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("RowInsertBefore24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_I));
}
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
insertRow(row - 1);
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class InsertRowAfterAction extends AbstractAction {
public InsertRowAfterAction() {
super();
putValue(Action.SHORT_DESCRIPTION,
"Inserts a row after the selected row");
putValue(Action.LONG_DESCRIPTION,
"Inserts a row after the selected row");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("RowInsertAfter24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_O));
}
public void actionPerformed(ActionEvent e) {
int row = table.getSelectedRow();
insertRow(row);
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class InsertColumnBeforeAction extends AbstractAction {
public InsertColumnBeforeAction() {
super();
putValue(Action.SHORT_DESCRIPTION,
"Inserts a column before the selected column");
putValue(Action.LONG_DESCRIPTION,
"Inserts a column before the selected column");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("ColumnInsertBefore24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_K));
}
public void actionPerformed(ActionEvent e) {
int column = table.getSelectedColumn();
insertColumn(column - 1);
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class InsertColumnAfterAction extends AbstractAction {
public InsertColumnAfterAction() {
super();
putValue(Action.SHORT_DESCRIPTION,
"Inserts a column after the selected column");
putValue(Action.LONG_DESCRIPTION,
"Inserts a column after the selected column");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("ColumnInsertAfter24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_L));
}
public void actionPerformed(ActionEvent e) {
int column = table.getSelectedColumn();
insertColumn(column);
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class DeleteRowAction extends AbstractAction {
public DeleteRowAction() {
super();
putValue(Action.SHORT_DESCRIPTION, "Deletes the selected row");
putValue(Action.LONG_DESCRIPTION, "Deletes the selected row");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("RowDelete24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_D));
}
public void actionPerformed(ActionEvent e) {
int rowIndex = table.getSelectedRow();
// move any components that are on the deleted row or
// above it down one
for (int index = 0; index < container.getComponentCount(); index++) {
Component component = container.getComponent(index);
CellConstraints constraints = getComponentConstraints(component);
if (constraints.gridY >= rowIndex && constraints.gridY > 1) {
constraints.gridY--;
} else {
// if the row deleted was within the span of the component and the
// component
// is bigger than one cell...
if (constraints.gridY + constraints.gridHeight - 1 >= rowIndex
&& constraints.gridHeight > 1) {
constraints.gridHeight--;
}
}
}
containerLayout.removeRowSpec(rowIndex - 1);
tableModel.fireTableRowsDeleted(rowIndex, rowIndex);
table.changeSelection(Math.min(rowIndex, containerLayout
.getRowCount()), 0, false, false);
specsChanged();
table.requestFocus();
}
}
@SuppressWarnings("serial")
private class DeleteColumnAction extends AbstractAction {
public DeleteColumnAction() {
super();
putValue(Action.SHORT_DESCRIPTION, "Deletes the selected column");
putValue(Action.LONG_DESCRIPTION, "Deletes the selected column");
putValue(Action.SMALL_ICON, new ImageIcon(FormEditor.class
.getResource("ColumnDelete24.gif")));
putValue(Action.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_C));
}
public void actionPerformed(ActionEvent e) {
int columnIndex = table.getSelectedColumn();
for (int index = 0; index < container.getComponentCount(); index++) {
Component component = container.getComponent(index);
CellConstraints constraints = getComponentConstraints(component);
if (constraints.gridX >= columnIndex && constraints.gridX > 1) {
constraints.gridX--;
} else {
// if the col deleted was within the span of the component and the
// component
// is bigger than one cell...
if (constraints.gridX + constraints.gridWidth - 1 >= columnIndex
&& constraints.gridWidth > 1) {
constraints.gridWidth--;
}
}
}
containerLayout.removeColumnSpec(columnIndex - 1);
tableModel.fireTableStructureChanged();
table.changeSelection(0, Math.min(columnIndex, containerLayout
.getColumnCount()), false, false);
specsChanged();
table.requestFocus();
}
}
@SuppressWarnings("serial")
class ComponentPaletteListModel extends AbstractListModel {
List<ComponentDef> componentDefs = ComponentDef.createComponentDefs();
public int getSize() {
return componentDefs.size();
}
public Object getElementAt(int index) {
return componentDefs.get(index);
}
}
@SuppressWarnings("serial")
class ComponentPaletteListRenderer extends JLabel implements
ListCellRenderer {
public ComponentPaletteListRenderer() {
setOpaque(true);
}
/*
* This method finds the image and text corresponding to the selected value
* and returns the label, set up to display the text and image.
*/
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
ComponentDef componentDef = (ComponentDef) value;
setIcon(componentDef.icon != null ? componentDef.icon : null);
setText(componentDef.name);
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
return this;
}
}
public void updateList() {
componentSelectionListModel.fireInsert();
}
public String uniqueName(String name, Component comp) {
// insure the component name doesn't collide
String newname = name;
int suffix = 1;
for (;;) {
Component temp = containerLayout.getComponentByName(newname);
// no such component, or found component was ourself, stop the search
if (temp == null || temp == comp) {
break; // exitloop
}
newname = name + "_" + suffix;
suffix++;
}
return newname;
}
public boolean editComponent(ComponentDef componentDef,
Component component, CellConstraints cellConstraints) {
if (componentDef.isContainer) {
return false; //punt!
}
// get original name for remove
String name = getComponentName(component);
NewComponentDialog dlg = NewComponentDialog.editDialog(
(JFrame) layoutFrame, componentDef);
if (!dlg.succeeded()) {
return false;
}
componentDef.name = uniqueName(dlg.getComponentName(), component);
String newname = componentDef.name;
Component newcomponent = dlg.getInstance();
containerLayout.removeLayoutComponent(component);
containerLayout.addComponent(newname, componentDef, cellConstraints);
container.remove(component);
container.add(newcomponent, newname);
newComponents.remove(component);
newComponents.add(newcomponent);
if (componentDef.isContainer) {
/** @todo losing components INSIDE the container!! */
// layoutFrame.replaceContainer(name, newName, (Container) newcomponent);
layoutFrame.removeContainer(name);
layoutFrame.addContainer(newname, (Container) newcomponent);
}
updateLayout(newcomponent);
updateList();
updateLayouts();
repaint();
return true;
}
}