git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268700 13f79535-47bb-0310-9956-ffa450edef68master
@@ -62,7 +62,7 @@ import java.util.StringTokenizer; | |||
* @version $Revision$ | |||
* @author Simeon Fitch | |||
*/ | |||
public class ACSTargetElement extends ACSNamedElement { | |||
public class ACSTargetElement extends ACSNamedElement implements Cloneable{ | |||
/** Dependency property name. */ | |||
public static final String DEPENDS = "depends"; | |||
@@ -152,4 +152,31 @@ public class ACSTargetElement extends ACSNamedElement { | |||
setAttribute(UNLESS, val); | |||
firePropertyChange(UNLESS, old, val); | |||
} | |||
/** | |||
* Copys the depends of a given target to the current. | |||
* | |||
* @param Source target for the copy operation. | |||
*/ | |||
public void copyDependsFromTarget(ACSTargetElement newTarget) { | |||
setDepends(newTarget.getDepends()); | |||
} | |||
/** | |||
* Copys the depends of a given target to the current. | |||
* I can't override clone, because I need an ACSTargetElement | |||
* to be returned! | |||
* | |||
* @return A clones target element | |||
*/ | |||
public ACSTargetElement getClone() { | |||
ACSTargetElement retVal = null; | |||
try { | |||
retVal = (ACSTargetElement)clone(); | |||
retVal.setDepends(getDepends()); | |||
} catch (java.lang.CloneNotSupportedException ex) { | |||
// Cannot occur, for ACSTarget implements Clonable! | |||
} | |||
return retVal; | |||
} | |||
} |
@@ -103,7 +103,8 @@ public class ACSTargetElementBeanInfo extends BaseBeanInfo { | |||
new PropertyDescriptor(ACSTargetElement.DESCRIPTION, | |||
ACSTargetElement.class), | |||
new PropertyDescriptor(ACSTargetElement.DEPENDS, | |||
ACSTargetElement.class), | |||
ACSTargetElement.class, | |||
"getClone", "copyDependsFromTarget"), | |||
new PropertyDescriptor(ACSTargetElement.IF, | |||
ACSTargetElement.class), | |||
new PropertyDescriptor(ACSTargetElement.UNLESS, | |||
@@ -140,6 +141,11 @@ public class ACSTargetElementBeanInfo extends BaseBeanInfo { | |||
/** Customizer for this bean info. */ | |||
public static class Customizer extends DynamicCustomizer { | |||
static { | |||
PropertyEditorManager.registerEditor( | |||
org.apache.tools.ant.gui.acs.ACSTargetElement.class, org.apache.tools.ant.gui.modules.edit.DependentTargetPropertyEditor.class); | |||
} | |||
public Customizer() { | |||
super(ACSTargetElement.class); | |||
} | |||
@@ -0,0 +1,423 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 1999, 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. 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. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR | |||
* ITS ConstrIBUTORS 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. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.tools.ant.gui.modules.edit; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
import org.w3c.dom.Node; | |||
import org.w3c.dom.NodeList; | |||
import java.awt.BorderLayout; | |||
import java.awt.FlowLayout; | |||
import java.awt.GridBagLayout; | |||
import java.awt.GridBagConstraints; | |||
import java.awt.Insets; | |||
import java.awt.Frame; | |||
import java.awt.Dimension; | |||
import java.awt.event.ActionListener; | |||
import java.awt.event.ActionEvent; | |||
import javax.swing.JDialog; | |||
import javax.swing.JPanel; | |||
import javax.swing.JButton; | |||
import javax.swing.JScrollPane; | |||
import javax.swing.ListSelectionModel; | |||
import javax.swing.ImageIcon; | |||
import javax.swing.JTable; | |||
import javax.swing.table.TableColumn; | |||
import org.apache.tools.ant.gui.util.WindowUtils; | |||
import org.apache.tools.ant.gui.acs.ACSProjectElement; | |||
import org.apache.tools.ant.gui.acs.ACSTargetElement; | |||
/** | |||
* Dialog for choosing dependent targes comfortable. | |||
* | |||
* @version $Revision$ | |||
* @author Christoph Wilhelms | |||
*/ | |||
public class DependentTargetChooser extends JDialog { | |||
// "Business"-Object | |||
private ACSTargetElement _target = null; | |||
// Tables | |||
private JTable _srcTable = null; | |||
private JTable _dstTable = null; | |||
private JButton _append = null; | |||
private JButton _remove = null; | |||
private JButton _moveUp = null; | |||
private JButton _moveDown = null; | |||
// Major Elements; | |||
private JPanel _commandButtonPanel = null; | |||
private JPanel _selectionPanel = null; | |||
// CommandButtons | |||
private JButton _ok = null; | |||
private JButton _cancel = null; | |||
private static ActionHandler _handler = null; | |||
/** | |||
* Constructor needs a parent Frame | |||
*/ | |||
public DependentTargetChooser (Frame parentFrame) { | |||
this (parentFrame, null); | |||
} | |||
/** | |||
* Constructor needs a parent Frame, target can be set later | |||
*/ | |||
public DependentTargetChooser (Frame parentFrame, ACSTargetElement target) { | |||
super(parentFrame, true); | |||
_handler = new ActionHandler(); // get the ActionHandler ready | |||
// Dialog settings | |||
setTitle("Select dependent targets"); | |||
setDefaultCloseOperation(HIDE_ON_CLOSE); | |||
// Container | |||
JPanel container = new JPanel(); | |||
this.setContentPane(container); | |||
container.setLayout(new BorderLayout()); | |||
// Populate container | |||
container.add(getCommandButtonPanel(), BorderLayout.SOUTH); | |||
container.add(getSelectionPanel(), BorderLayout.CENTER); | |||
// Apply model - must be done this late, because it relies | |||
// on an instntiated GUI | |||
setTarget(target); | |||
// Set an initial size and pack it | |||
container.setPreferredSize(new Dimension(500,200)); | |||
pack(); | |||
} | |||
/** | |||
* Lazily get the selectionPanel with 2 tables and 4 buttons | |||
* @return the created JPanel | |||
*/ | |||
private JPanel getSelectionPanel() { | |||
if (_selectionPanel == null) { | |||
_selectionPanel = new JPanel(); | |||
_selectionPanel.setLayout(new GridBagLayout()); | |||
// LEFT Table | |||
JScrollPane srcSP = new JScrollPane(); | |||
srcSP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); | |||
srcSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); | |||
_srcTable = createTargetsTable(); | |||
srcSP.setViewportView(_srcTable); | |||
GridBagConstraints srcSPConstr = new GridBagConstraints(); | |||
srcSPConstr.fill = GridBagConstraints.BOTH; | |||
srcSPConstr.anchor = GridBagConstraints.CENTER; | |||
srcSPConstr.gridx = 0; srcSPConstr.gridy = 0; | |||
srcSPConstr.weightx = 1.0; srcSPConstr.weighty = 2.0; | |||
srcSPConstr.gridwidth = 1; srcSPConstr.gridheight = 2; | |||
srcSPConstr.insets = new Insets(5,5,0,5); | |||
_selectionPanel.add(srcSP, srcSPConstr); | |||
// Append Button | |||
_append = new JButton(); | |||
_append.setIcon(new ImageIcon(getClass().getResource("/org/apache/tools/ant/gui/resources/enter.gif"))); | |||
_append.setPreferredSize(new Dimension(28, 28)); | |||
_append.setMaximumSize(new Dimension(28, 28)); | |||
_append.setMinimumSize(new Dimension(28, 28)); | |||
_append.addActionListener(_handler); | |||
GridBagConstraints appendConstr = new GridBagConstraints(); | |||
appendConstr.fill = GridBagConstraints.NONE; | |||
appendConstr.anchor = GridBagConstraints.SOUTH; | |||
appendConstr.gridx = 1; appendConstr.gridy = 0; | |||
appendConstr.weightx = 0.0; appendConstr.weighty = 1.0; | |||
appendConstr.gridwidth = 1; appendConstr.gridheight = 1; | |||
appendConstr.insets = new Insets(0,0,2,0); | |||
_selectionPanel.add(_append, appendConstr); | |||
// Remove Button | |||
_remove = new JButton(); | |||
_remove.setIcon(new ImageIcon(getClass().getResource("/org/apache/tools/ant/gui/resources/exit.gif"))); | |||
_remove.setPreferredSize(new Dimension(28, 28)); | |||
_remove.setMaximumSize(new Dimension(28, 28)); | |||
_remove.setMinimumSize(new Dimension(28, 28)); | |||
_remove.addActionListener(_handler); | |||
GridBagConstraints removeConstr = new GridBagConstraints(); | |||
removeConstr.fill = GridBagConstraints.NONE; | |||
removeConstr.anchor = GridBagConstraints.NORTH; | |||
removeConstr.gridx = 1; removeConstr.gridy = 1; | |||
removeConstr.weightx = 0.0; removeConstr.weighty = 1.0; | |||
removeConstr.gridwidth = 1; removeConstr.gridheight = 1; | |||
removeConstr.insets = new Insets(3,0,0,0); | |||
_selectionPanel.add(_remove, removeConstr); | |||
// RIGHT Table | |||
JScrollPane dstSP = new JScrollPane(); | |||
dstSP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); | |||
dstSP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); | |||
_dstTable = createTargetsTable(); | |||
dstSP.setViewportView(_dstTable); | |||
GridBagConstraints dstSPConstr = new GridBagConstraints(); | |||
dstSPConstr.fill = GridBagConstraints.BOTH; | |||
dstSPConstr.anchor = GridBagConstraints.CENTER; | |||
dstSPConstr.gridx = 2; dstSPConstr.gridy = 0; | |||
dstSPConstr.weightx = 1.0; dstSPConstr.weighty = 2.0; | |||
dstSPConstr.gridwidth = 1; dstSPConstr.gridheight = 2; | |||
dstSPConstr.insets = new Insets(5,5,0,5); | |||
_selectionPanel.add(dstSP, dstSPConstr); | |||
// Move Up Button | |||
_moveUp = new JButton(); | |||
_moveUp.setIcon(new ImageIcon(getClass().getResource("/org/apache/tools/ant/gui/resources/up.gif"))); | |||
_moveUp.setPreferredSize(new Dimension(28, 28)); | |||
_moveUp.setMaximumSize(new Dimension(28, 28)); | |||
_moveUp.setMinimumSize(new Dimension(28, 28)); | |||
_moveUp.addActionListener(_handler); | |||
GridBagConstraints moveUpConstr = new GridBagConstraints(); | |||
moveUpConstr.fill = GridBagConstraints.NONE; | |||
moveUpConstr.anchor = GridBagConstraints.CENTER; | |||
moveUpConstr.gridx = 3; moveUpConstr.gridy = 0; | |||
moveUpConstr.weightx = 0.0; moveUpConstr.weighty = 1.0; | |||
moveUpConstr.gridwidth = 1; moveUpConstr.gridheight = 1; | |||
moveUpConstr.insets = new Insets(0,0,0,5); | |||
_selectionPanel.add(_moveUp, moveUpConstr); | |||
// Move Up Button | |||
_moveDown = new JButton(); | |||
_moveDown.setIcon(new ImageIcon(getClass().getResource("/org/apache/tools/ant/gui/resources/down.gif"))); | |||
_moveDown.setPreferredSize(new Dimension(28, 28)); | |||
_moveDown.setMaximumSize(new Dimension(28, 28)); | |||
_moveDown.setMinimumSize(new Dimension(28, 28)); | |||
_moveDown.addActionListener(_handler); | |||
GridBagConstraints moveDownConstr = new GridBagConstraints(); | |||
moveDownConstr.fill = GridBagConstraints.NONE; | |||
moveDownConstr.anchor = GridBagConstraints.CENTER; | |||
moveDownConstr.gridx = 3; moveDownConstr.gridy = 1; | |||
moveDownConstr.weightx = 0.0; moveDownConstr.weighty = 1.0; | |||
moveDownConstr.gridwidth = 1; moveDownConstr.gridheight = 1; | |||
moveDownConstr.insets = new Insets(0,0,0,5); | |||
_selectionPanel.add(_moveDown, moveDownConstr); | |||
} | |||
return _selectionPanel; | |||
} | |||
/** | |||
* Lazily get the commandButtonPanel | |||
* @return the created JPanel | |||
*/ | |||
private JPanel getCommandButtonPanel() { | |||
if (_commandButtonPanel == null) { | |||
_commandButtonPanel = new JPanel(); | |||
FlowLayout btnLayout = new FlowLayout(); | |||
btnLayout.setAlignment(FlowLayout.RIGHT); | |||
_commandButtonPanel.setLayout(btnLayout); | |||
_ok = new JButton("OK"); | |||
_ok.addActionListener(_handler); | |||
getRootPane().setDefaultButton(_ok); | |||
_cancel = new JButton("Cancel"); | |||
_cancel.addActionListener(_handler); | |||
_commandButtonPanel.add(_ok); | |||
_commandButtonPanel.add(_cancel); | |||
} | |||
return _commandButtonPanel; | |||
} | |||
/** | |||
* Writer method for the model-element | |||
* @param ACSTargetElement the new Target model element. | |||
*/ | |||
public void setTarget(ACSTargetElement newTarget) { | |||
_target = newTarget; | |||
// fill source-TableModel with "sister-targets" | |||
TargetsTableModel srcModel = (TargetsTableModel)_srcTable.getModel(); | |||
srcModel.setTargets(getCoTargets(newTarget)); | |||
srcModel.fireTableDataChanged(); | |||
// fill dest-TableModel with selected depends-targets | |||
TargetsTableModel dstModel = (TargetsTableModel)_dstTable.getModel(); | |||
dstModel.setTargets(fillDependsList(newTarget)); | |||
dstModel.fireTableDataChanged(); | |||
} | |||
/** | |||
* Fills a List with all sister- or depending-targets of a single target | |||
* @return filled or empty List | |||
*/ | |||
private List fillDependsList(ACSTargetElement aTarget) { | |||
List retVal = new ArrayList(); | |||
String[] dependNames = aTarget.getDepends(); | |||
int length = dependNames.length; | |||
ArrayList allTargets = getCoTargets (aTarget); | |||
int allLen = allTargets.size(); | |||
for (int i = 0; i < length; i++) | |||
{ | |||
for (int j = 0; j < allLen; j++) { | |||
ACSTargetElement currentElement = (ACSTargetElement)allTargets.get(j); | |||
if (currentElement.getName().equalsIgnoreCase(dependNames[i].trim())) retVal.add(currentElement); | |||
} | |||
} | |||
return retVal; | |||
} | |||
private ArrayList getCoTargets (ACSTargetElement aTarget) { | |||
ACSProjectElement parentProject = null; | |||
// Caution is the mother of wisdom ;-) | |||
if (aTarget.getParentNode() instanceof ACSProjectElement) | |||
parentProject = (ACSProjectElement) aTarget.getParentNode(); | |||
else throw new IllegalArgumentException("Target not part of Project"); | |||
NodeList allNodes = parentProject.getChildNodes(); | |||
ArrayList retVal = new ArrayList(); | |||
int length = allNodes.getLength(); | |||
for (int i = 0; i < length; i++) | |||
{ | |||
Node node = allNodes.item(i); | |||
if (node instanceof ACSTargetElement) { | |||
ACSTargetElement currentElement = ((ACSTargetElement)node); | |||
// ... leave out the current target TODO: avoid cyclic relations! | |||
if (currentElement != aTarget) retVal.add(currentElement); | |||
} | |||
} | |||
return retVal; | |||
} | |||
/** | |||
* Checks if a String is part of an existing dependent task list | |||
* @return true, if it is a dependent target | |||
*/ | |||
private boolean checkDepends(String name, ACSTargetElement aTarget) { | |||
String[] depend = aTarget.getDepends(); | |||
for( int i= 0; i < depend.length; i++) { | |||
if (name.equalsIgnoreCase(depend[i])) return true; | |||
} | |||
return false; | |||
} | |||
/** | |||
* Creates a target-table with two columns - we need two of them! | |||
* @return created JTable | |||
*/ | |||
private JTable createTargetsTable() { | |||
JTable table = new JTable(); | |||
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); | |||
table.setAutoCreateColumnsFromModel(false); | |||
table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | |||
// Coulumn showing the Target | |||
TableColumn targetCol = new TableColumn(); | |||
targetCol.setHeaderValue("Target"); | |||
targetCol.setModelIndex(0); | |||
targetCol.setPreferredWidth(150); | |||
targetCol.setMaxWidth(150); | |||
targetCol.setResizable(true); | |||
// Coulumn showing the description of targets | |||
TableColumn descrCol = new TableColumn(); | |||
descrCol.setHeaderValue("Description"); | |||
descrCol.setModelIndex(1); | |||
descrCol.setPreferredWidth(250); | |||
descrCol.setResizable(false); | |||
table.addColumn(targetCol); | |||
table.addColumn(descrCol); | |||
table.setModel(new TargetsTableModel()); | |||
return table; | |||
} | |||
/** | |||
* Ihis handler is the ActionListener for each button. | |||
*/ | |||
private class ActionHandler implements ActionListener { | |||
/** | |||
* ActionListener Interface ethod | |||
* @param ActionEvent | |||
*/ | |||
public void actionPerformed(ActionEvent e) { | |||
// Get some initial values needed later | |||
TargetsTableModel srcModel = (TargetsTableModel)_srcTable.getModel(); | |||
TargetsTableModel dstModel = (TargetsTableModel)_dstTable.getModel(); | |||
int srcRow = _srcTable.getSelectedRow(); | |||
int dstRow = _dstTable.getSelectedRow(); | |||
// Evaluate EventSource | |||
if (e.getSource()==_ok) { | |||
// OK: take the selected targets and leave | |||
_target.setDepends( dstModel.getTargetsAsStringArray() ); | |||
dispose(); | |||
} else if (e.getSource()==_cancel) { | |||
// just close dialog | |||
dispose(); | |||
} else if (e.getSource()==_moveUp) { | |||
// Move dependent target up (one row) | |||
dstModel.moveTarget(dstRow, -1); | |||
_dstTable.getSelectionModel().setSelectionInterval(dstRow - 1, dstRow - 1); | |||
} else if (e.getSource()==_moveDown) { | |||
// Move dependent target down (one row) | |||
dstModel.moveTarget(dstRow, 1); | |||
_dstTable.getSelectionModel().setSelectionInterval(dstRow + 1, dstRow + 1); | |||
} else if (e.getSource()==_append) { | |||
// Append selected target to depends | |||
if (srcRow >= 0) dstModel.addTarget(srcModel.getTarget(srcRow)); | |||
} else if (e.getSource()==_remove) { | |||
// Remove dependent target | |||
if (dstRow >= 0) dstModel.removeTarget(dstRow); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,327 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 1999, 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. 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. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR | |||
* ITS 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. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.tools.ant.gui.modules.edit; | |||
import java.util.StringTokenizer; | |||
import java.awt.Component; | |||
import java.awt.BorderLayout; | |||
import java.awt.event.ActionListener; | |||
import java.awt.event.ActionEvent; | |||
import java.awt.event.FocusListener; | |||
import java.awt.event.FocusEvent; | |||
import java.awt.event.KeyListener; | |||
import java.awt.event.KeyEvent; | |||
import java.awt.Point; | |||
import java.awt.Dimension; | |||
import java.awt.Toolkit; | |||
import javax.swing.JPanel; | |||
import javax.swing.JButton; | |||
import javax.swing.JTextField; | |||
import javax.swing.JOptionPane; | |||
import javax.swing.BorderFactory; | |||
import javax.swing.border.BevelBorder; | |||
import org.apache.tools.ant.gui.customizer.AbstractPropertyEditor; | |||
import org.apache.tools.ant.gui.acs.ACSTargetElement; | |||
/** | |||
* PropertyEditor for DependentTargets | |||
* | |||
* @version $Revision$ | |||
* @author Christoph Wilhelms | |||
*/ | |||
public class DependentTargetPropertyEditor extends AbstractPropertyEditor { | |||
private JTextField _textField = null; | |||
private JButton _button = null; | |||
private JPanel _widget = null; | |||
private ACSTargetElement _value = null; | |||
private EventHandler _handler = new EventHandler(); | |||
private static DependentTargetChooser _dialog = null; | |||
/** | |||
* Gets the editor component: A panel containing a textfield an a button. | |||
* @return the property editor component | |||
*/ | |||
public Component getChild() { | |||
if (_widget == null) // Lazy get | |||
{ | |||
_widget = new JPanel(); | |||
_widget.setLayout(new BorderLayout()); | |||
_widget.add(getTextField(), BorderLayout.CENTER); | |||
_widget.add(getButton(), BorderLayout.EAST); | |||
} | |||
return _widget; | |||
} | |||
/** | |||
* Lazily create the textfield, to make sure its only instantiated once. | |||
* @return the button | |||
*/ | |||
private JTextField getTextField() { | |||
if (_textField == null) { | |||
_textField = new JTextField(); | |||
_textField.setText(getAsText()); | |||
_textField.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); | |||
_textField.addFocusListener(_handler); | |||
_textField.addKeyListener(_handler); | |||
// We dont really need the next line in Antidote context, just for testpurpose! | |||
_textField.setPreferredSize(new Dimension(150, _textField.getPreferredSize().height)); | |||
} | |||
// Transfer Tooltip from Panel to TextField - this hat to be done at every get! | |||
_textField.setToolTipText( _widget.getToolTipText()); | |||
return _textField; | |||
} | |||
/** | |||
* Lazily create the button, to make sure its only instantiated once. | |||
* @return the button | |||
*/ | |||
private JButton getButton() { | |||
if (_button == null) { | |||
_button = new JButton(); | |||
_button.setText("..."); // Probably an Image is more nice, but ... is standart, I think. | |||
_button.setPreferredSize(new Dimension(getTextField().getPreferredSize().height, getTextField().getPreferredSize().height)); | |||
_button.addActionListener(_handler); | |||
} | |||
return _button; | |||
} | |||
/** | |||
* Sets the model for the component. Used to comunicate externally. | |||
* @param The target element the editior works with. | |||
*/ | |||
public void setValue(Object newValue) { | |||
if(!(newValue instanceof ACSTargetElement)) { | |||
throw new IllegalArgumentException( | |||
"Value must be of type ACSTargetElement."); | |||
} | |||
_value = (ACSTargetElement)newValue; | |||
// Directly show the targets. | |||
getTextField().setText(getAsText()); | |||
} | |||
/** | |||
* Sets the model for the component. Used to comunicate externally. | |||
* @return The target element the editior works with. | |||
*/ | |||
public Object getValue() { | |||
return _value; | |||
} | |||
/** | |||
* Sets the depends for the target as text. | |||
* @param A String containing all targetnames, separated by "," | |||
*/ | |||
public void setAsText(String newValue) { | |||
String vals = getTextField().getText(); | |||
StringTokenizer tok = new StringTokenizer(vals,","); | |||
String[] depends = new String[tok.countTokens()]; | |||
for(int i = 0; i < depends.length; i++) { | |||
depends[i] = tok.nextToken().trim(); | |||
} | |||
// Directly supply the target with the new depends. | |||
((ACSTargetElement)getValue()).setDepends(depends);; | |||
} | |||
/** | |||
* Gets the depends for the target as text. | |||
* @return A String containing all targetnames, separated by "," | |||
*/ | |||
public String getAsText() { | |||
if (_value == null) return ""; | |||
String[] dep = _value.getDepends(); | |||
String retVal = ""; | |||
for (int i = 0; i < dep.length; i++) { | |||
retVal += dep[i]; | |||
if (i < dep.length - 1) retVal += ", "; | |||
} | |||
return retVal; | |||
} | |||
/** | |||
* Creates and shows the dialog for selecting dependent targets. | |||
*/ | |||
private void showSelectionDialog() { | |||
// Create the dialog lazyly - it is static, for we want only ONE instance! | |||
if (_dialog == null) { | |||
_dialog = new DependentTargetChooser(JOptionPane.getFrameForComponent(getChild()), (ACSTargetElement)getValue()); | |||
} | |||
else { | |||
// Supply dialog with target - it needs nothing else ;-) - but the | |||
// target will be modified by the dialog. | |||
_dialog.setTarget((ACSTargetElement)getValue()); | |||
} | |||
String oldValue = getTextField().getText(); | |||
// Set the position of the dialog right under the Editor, if possible | |||
DependentTargetPropertyEditor.setWindowRelativeToComponent (_dialog, getChild()); | |||
_dialog.show(); | |||
// after the modal dialog is disposed make shure that the propertyChangeEvent | |||
// will be thrown and the textfield becomes updated! | |||
Object newValue = (Object)getAsText(); | |||
getTextField().setText(getAsText()); | |||
firePropertyChange(newValue, oldValue); | |||
} | |||
/** | |||
* Handler for ButtonAction, Focus- and KeyListening. I can't use the FocusHandler | |||
* in superclass, for I have a different Object in Property Change! | |||
*/ | |||
private class EventHandler implements ActionListener, FocusListener, KeyListener { | |||
/* ActionListener methods */ | |||
public void actionPerformed(ActionEvent e) { | |||
if (e.getSource() == _button) showSelectionDialog(); | |||
} | |||
/* FocusListener methods */ | |||
public void focusLost(FocusEvent e) { | |||
Object oldValue = (Object)getAsText(); | |||
String newValue = getTextField().getText(); | |||
setAsText(newValue); | |||
firePropertyChange(newValue, oldValue); | |||
} | |||
public void focusGained(FocusEvent e) { | |||
} | |||
/* KeyListener methods */ | |||
public void keyPressed(KeyEvent e) { | |||
} | |||
public void keyTyped(KeyEvent e) { | |||
} | |||
public void keyReleased(KeyEvent e) { | |||
if (e.getKeyCode() == KeyEvent.VK_F4) { | |||
showSelectionDialog(); | |||
} | |||
} | |||
} | |||
/** | |||
* Places a window, depending of it's size, relative to a component and it's size | |||
* TODO: move to WindowUtilities | |||
*/ | |||
public static void setWindowRelativeToComponent (java.awt.Window window, Component theComp) { | |||
int compX = theComp.getLocationOnScreen().x; | |||
int compY = theComp.getLocationOnScreen().y; | |||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); | |||
Dimension dialogSize = window.getSize(); | |||
int x = 0, y = 0; | |||
// Window should be aligned LEFT with component | |||
x = compX; | |||
// If there is not enough space to align LEFT, align RIGTH | |||
if (x + dialogSize.width > screenSize.getWidth()) { | |||
x = compX - (dialogSize.width - theComp.getWidth()); | |||
} | |||
// If there is not enough space to align LEFT, make sure that it | |||
// will be display completely. | |||
if (x < 0) x = 0; | |||
// Window should be located BELOW component | |||
y = compY + theComp.getHeight(); | |||
// If there is not enough space Window BELOW component, place ABOVE component | |||
if (y + dialogSize.height > screenSize.getHeight() ) { | |||
y = compY - dialogSize.height; | |||
} | |||
// If there is not enough space Window ABOVE component make sure that it | |||
// will be display completely. | |||
if (y < 0) y = 0; | |||
window.setLocation(x, y); | |||
} | |||
/** main just for Test reasons */ | |||
public static void main(String[] args) { | |||
javax.swing.JFrame f = new javax.swing.JFrame(); | |||
f.setDefaultCloseOperation(3 /*JFrame.EXIT_ON_CLOSE*/); | |||
org.apache.tools.ant.gui.core.AppContext context = new org.apache.tools.ant.gui.core.AppContext(f); | |||
try { | |||
context.getProjectManager().open(new java.io.File("G:\\build.xml")); | |||
} catch (Exception e) { | |||
System.out.println("No buildfile found"); | |||
} | |||
JPanel c = new JPanel(); | |||
c.setLayout(new java.awt.FlowLayout()); | |||
f.setContentPane(c); | |||
org.w3c.dom.NodeList all2ndLevelNodes = context.getProjectManager().getOpen()[0].getChildNodes(); | |||
int i= 0; | |||
while (i < all2ndLevelNodes.getLength()) { | |||
org.w3c.dom.Node node = all2ndLevelNodes.item(i); | |||
if (node instanceof ACSTargetElement) { | |||
ACSTargetElement newTarget = ((ACSTargetElement)node); | |||
DependentTargetPropertyEditor a = new DependentTargetPropertyEditor(); | |||
c.add(a.getChild()); | |||
a.setValue(newTarget); | |||
} | |||
i++; | |||
} | |||
f.pack(); | |||
f.addWindowListener(new java.awt.event.WindowListener() { | |||
public void windowOpened(java.awt.event.WindowEvent e) {} | |||
public void windowIconified(java.awt.event.WindowEvent e) {} | |||
public void windowDeiconified(java.awt.event.WindowEvent e) {} | |||
public void windowActivated(java.awt.event.WindowEvent e) {} | |||
public void windowDeactivated(java.awt.event.WindowEvent e) {} | |||
public void windowClosing(java.awt.event.WindowEvent e) {} | |||
public void windowClosed(java.awt.event.WindowEvent e) {System.exit(0);} | |||
}); | |||
f.show(); | |||
} | |||
} |
@@ -0,0 +1,189 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 1999, 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. 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. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||
* Foundation" must not be used to endorse or promote products derived | |||
* from this software without prior written permission. For written | |||
* permission, please contact apache@apache.org. | |||
* | |||
* 5. Products derived from this software may not be called "Apache" | |||
* nor may "Apache" appear in their names without prior written | |||
* permission of the Apache Group. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR | |||
* ITS 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. | |||
* ==================================================================== | |||
* | |||
* This software consists of voluntary contributions made by many | |||
* individuals on behalf of the Apache Software Foundation. For more | |||
* information on the Apache Software Foundation, please see | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.tools.ant.gui.modules.edit; | |||
import org.w3c.dom.Node; | |||
import org.w3c.dom.NodeList; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
import javax.swing.table.AbstractTableModel; | |||
import org.apache.tools.ant.gui.acs.ACSProjectElement; | |||
import org.apache.tools.ant.gui.acs.ACSTargetElement; | |||
/** | |||
* This is a TableModel containing the co-targets of a distinct target. | |||
* | |||
* @version $Revision$ | |||
* @author Christoph Wilhelms | |||
*/ | |||
public class TargetsTableModel extends AbstractTableModel { | |||
// model data | |||
private List _delegate = new ArrayList(); | |||
private ACSTargetElement _mainTarget = null; | |||
/** | |||
* Default constructor | |||
*/ | |||
public TargetsTableModel() { | |||
super(); | |||
} | |||
/** | |||
* @param int columnIndex | |||
* @return String.class | |||
*/ | |||
public Class getColumnClass(int columnIndex) { | |||
return String.class; | |||
} | |||
/** | |||
* @return 2 | |||
*/ | |||
public int getColumnCount() { | |||
return 2; | |||
} | |||
/** | |||
* @return number of containing element | |||
*/ | |||
public int getRowCount() { | |||
return _delegate.size(); | |||
} | |||
/** | |||
* @param row and column in table | |||
* @return the requested object to be shown. | |||
*/ | |||
public Object getValueAt(int row, int col) { | |||
ACSTargetElement rowObj = (ACSTargetElement)_delegate.get(row); | |||
switch (col) { | |||
case 0: return rowObj.getName(); | |||
case 1: return rowObj.getDescription(); | |||
default: return ""; | |||
} | |||
} | |||
/** | |||
* @return false for no cell is editable. | |||
*/ | |||
public boolean isCellEditable(int row, int col) { | |||
return false; | |||
} | |||
/** | |||
* Change the entire model. | |||
* @param List of ACSTargetElements | |||
*/ | |||
public void setTargets(List newTargets) { | |||
_delegate = newTargets; | |||
fireTableDataChanged(); | |||
} | |||
/** | |||
* Access a single element. | |||
* @param rowIndex | |||
* @return ACSTargetElement | |||
*/ | |||
public ACSTargetElement getTarget(int index) { | |||
return (ACSTargetElement)_delegate.get(index); | |||
} | |||
/** | |||
* Remove a single element. | |||
* @param int rowIndex | |||
*/ | |||
public void removeTarget(int index) { | |||
_delegate.remove(index); | |||
fireTableRowsDeleted(index -1, index); | |||
} | |||
/** | |||
* Add a new element to list. | |||
* @param ACSTargetElement newTarget to be added to the list. | |||
*/ | |||
public void addTarget(ACSTargetElement newTarget) { | |||
_delegate.add(newTarget); | |||
fireTableRowsInserted(_delegate.size()-1, _delegate.size()); | |||
} | |||
/** | |||
* Moves a Target | |||
* @param int rowindex in List | |||
* @param int delta to move (negative to move up) | |||
*/ | |||
public void moveTarget(int index, int delta) { | |||
if (index + delta < 0) return; | |||
else if (index + delta > _delegate.size()) return; | |||
Object backObj = _delegate.get(index + delta); | |||
_delegate.set(index + delta, _delegate.get(index) ); | |||
_delegate.set(index, backObj); | |||
fireTableRowsUpdated(index + delta, index); | |||
} | |||
/** | |||
* @return a StringArray (String[]) containing the names of all targets. | |||
*/ | |||
public String[] getTargetsAsStringArray() { | |||
int length = _delegate.size(); | |||
String[] retVal = new String[length]; | |||
for (int i = 0; i < length; i++) { | |||
retVal[i] = ((ACSTargetElement)_delegate.get(i)).getName(); | |||
} | |||
return retVal; | |||
} | |||
} |