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