/* * SoapUI, Copyright (C) 2004-2016 SmartBear Software * * Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent * versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl * * Unless required by applicable law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the Licence for the specific language governing permissions and limitations * under the Licence. */ package com.eviware.soapui.impl.rest.panels.component; import com.eviware.soapui.SoapUI; import com.eviware.soapui.impl.rest.RestResource; import com.eviware.soapui.impl.rest.support.RestUtils; import com.eviware.soapui.support.DocumentListenerAdapter; import com.eviware.soapui.support.StringUtils; import com.eviware.soapui.support.UISupport; import com.jgoodies.forms.factories.ButtonBarFactory; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.text.Document; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; /** * Popup window displayed by the RestResourceEditor class */ class RestResourceEditorPopupWindow extends JDialog { private static final ImageIcon CONNECTOR_ICON = UISupport.createImageIcon("/connector.png"); // package protected fields to facilitate unit testing JTextField basePathTextField; List<RestSubResourceTextField> restSubResourceTextFields; private RestResource targetResource; private RestResource focusedResource; RestResourceEditorPopupWindow(RestResource resource, RestResource focusedResource) { super(SoapUI.getFrame()); this.targetResource = resource; this.focusedResource = focusedResource; setModal(true); setResizable(false); setMinimumSize(new Dimension(230, 0)); JPanel contentPane = new JPanel(new BorderLayout()); setContentPane(contentPane); JButton okButton = new JButton(new AbstractAction("OK") { @Override public void actionPerformed(ActionEvent e) { if (basePathTextField != null) { targetResource.getInterface().setBasePath(basePathTextField.getText().trim()); } for (RestSubResourceTextField restSubResourceTextField : restSubResourceTextFields) { restSubResourceTextField.getRestResource().setPath(restSubResourceTextField.getTextField().getText().trim()); } RestResourceEditor.scanForTemplateParameters(targetResource); dispose(); } }); AbstractAction cancelAction = new AbstractAction("Cancel") { @Override public void actionPerformed(ActionEvent e) { dispose(); } }; JButton cancelButton = new JButton(cancelAction); cancelButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); cancelButton.getActionMap().put("cancel", cancelAction); JPanel buttonBar = ButtonBarFactory.buildRightAlignedBar(okButton, cancelButton); buttonBar.setLayout(new FlowLayout(FlowLayout.RIGHT)); contentPane.add(createResourceEditorPanel(focusedResource), BorderLayout.CENTER); contentPane.add(buttonBar, BorderLayout.SOUTH); getRootPane().setDefaultButton(okButton); pack(); } private JPanel createResourceEditorPanel(RestResource focusedResource) { final JPanel panel = new JPanel(new BorderLayout()); Box contentBox = Box.createVerticalBox(); final JLabel changeWarningLabel = new JLabel(" "); changeWarningLabel.setBorder(BorderFactory.createCompoundBorder( contentBox.getBorder(), BorderFactory.createEmptyBorder(10, 0, 0, 0))); addBasePathFieldIfApplicable(contentBox, changeWarningLabel); addResourceFields(focusedResource, contentBox, changeWarningLabel); panel.add(contentBox, BorderLayout.NORTH); panel.add(changeWarningLabel, BorderLayout.CENTER); panel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK), BorderFactory.createEmptyBorder(10, 10, 10, 10))); return panel; } private void addResourceFields(RestResource focusedResource, Box contentBox, JLabel changeWarningLabel) { restSubResourceTextFields = new ArrayList<RestSubResourceTextField>(); int rowIndex = contentBox.getComponents().length; for (RestResource restResource : RestUtils.extractAncestorsParentFirst(targetResource)) { Box row = Box.createHorizontalBox(); row.setAlignmentX(0); addConnectorIfApplicable(rowIndex, row); final RestSubResourceTextField restSubResourceTextField = new RestSubResourceTextField(restResource); final JTextField innerTextField = restSubResourceTextField.getTextField(); innerTextField.getDocument().addDocumentListener(new PathChangeListener(changeWarningLabel, restResource)); restSubResourceTextFields.add(restSubResourceTextField); Box textFieldBox = createBoxWith(innerTextField); row.add(textFieldBox); contentBox.add(row); if (restResource == focusedResource) { moveFocusToField(innerTextField); } rowIndex++; } } private void addConnectorIfApplicable(int rowIndex, Box row) { if (rowIndex > 1) { row.add(Box.createHorizontalStrut((rowIndex - 1) * CONNECTOR_ICON.getIconWidth())); } if (rowIndex >= 1) { row.add(new JLabel(CONNECTOR_ICON)); } } private void moveFocusToField(final JTextField innerTextField) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { innerTextField.requestFocusInWindow(); innerTextField.selectAll(); } }); } private Box createBoxWith(JTextField innerTextField) { Box textFieldBox = Box.createVerticalBox(); textFieldBox.add(Box.createVerticalGlue()); textFieldBox.add(innerTextField); return textFieldBox; } class RestSubResourceTextField { private RestResource restResource; private JTextField textField; private RestSubResourceTextField(RestResource restResource) { this.restResource = restResource; textField = new JTextField(restResource.getPath()); textField.setMaximumSize(new Dimension(340, (int) textField.getPreferredSize().getHeight())); textField.setPreferredSize(new Dimension(340, (int) textField.getPreferredSize().getHeight())); } public JTextField getTextField() { return textField; } public RestResource getRestResource() { return restResource; } } private void addBasePathFieldIfApplicable(Box contentBox, JLabel changeWarningLabel) { if (!StringUtils.isNullOrEmpty(targetResource.getInterface().getBasePath())) { basePathTextField = new JTextField(targetResource.getInterface().getBasePath()); basePathTextField.getDocument().addDocumentListener(new PathChangeListener(changeWarningLabel, targetResource.getTopLevelResource())); basePathTextField.setMaximumSize(new Dimension(340, (int) basePathTextField.getPreferredSize().getHeight())); Box row = Box.createHorizontalBox(); row.setAlignmentX(0); row.add(createBoxWith(basePathTextField)); contentBox.add(row); if (focusedResource == null) { moveFocusToField(basePathTextField); } } } private class PathChangeListener extends DocumentListenerAdapter { private final JLabel changeWarningLabel; private RestResource affectedRestResource; public PathChangeListener(JLabel changeWarningLabel, RestResource affectedRestResource) { this.changeWarningLabel = changeWarningLabel; this.affectedRestResource = affectedRestResource; } @Override public void update(Document document) { int affectedRequestCount = getRequestCountForResource(affectedRestResource); if (affectedRequestCount > 0) { changeWarningLabel.setText(String.format("<html>Changes will affect <b>%d</b> request%s</html>", affectedRequestCount, affectedRequestCount > 1 ? "s" : "")); changeWarningLabel.setVisible(true); } else { changeWarningLabel.setVisible(false); } } private int getRequestCountForResource(RestResource affectedRestResource) { int affectedRequestCount = affectedRestResource.getRequestCount(); for (RestResource childResource : affectedRestResource.getAllChildResources()) { affectedRequestCount += childResource.getRequestCount(); } return affectedRequestCount; } } }