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; | |||||
| } | |||||
| } | |||||