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$ | * @version $Revision$ | ||||
* @author Simeon Fitch | * @author Simeon Fitch | ||||
*/ | */ | ||||
public class ACSTargetElement extends ACSNamedElement { | |||||
public class ACSTargetElement extends ACSNamedElement implements Cloneable{ | |||||
/** Dependency property name. */ | /** Dependency property name. */ | ||||
public static final String DEPENDS = "depends"; | public static final String DEPENDS = "depends"; | ||||
@@ -152,4 +152,31 @@ public class ACSTargetElement extends ACSNamedElement { | |||||
setAttribute(UNLESS, val); | setAttribute(UNLESS, val); | ||||
firePropertyChange(UNLESS, old, 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, | new PropertyDescriptor(ACSTargetElement.DESCRIPTION, | ||||
ACSTargetElement.class), | ACSTargetElement.class), | ||||
new PropertyDescriptor(ACSTargetElement.DEPENDS, | new PropertyDescriptor(ACSTargetElement.DEPENDS, | ||||
ACSTargetElement.class), | |||||
ACSTargetElement.class, | |||||
"getClone", "copyDependsFromTarget"), | |||||
new PropertyDescriptor(ACSTargetElement.IF, | new PropertyDescriptor(ACSTargetElement.IF, | ||||
ACSTargetElement.class), | ACSTargetElement.class), | ||||
new PropertyDescriptor(ACSTargetElement.UNLESS, | new PropertyDescriptor(ACSTargetElement.UNLESS, | ||||
@@ -140,6 +141,11 @@ public class ACSTargetElementBeanInfo extends BaseBeanInfo { | |||||
/** Customizer for this bean info. */ | /** Customizer for this bean info. */ | ||||
public static class Customizer extends DynamicCustomizer { | 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() { | public Customizer() { | ||||
super(ACSTargetElement.class); | 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; | |||||
} | |||||
} |