/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.Border;
import javax.swing.tree.TreeNode;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.testelement.property.NullProperty;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.visualizers.Printable;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
/**
* This abstract class takes care of the most basic functions necessary to
* create a viable JMeter GUI component. It extends JPanel and implements
* JMeterGUIComponent. This abstract class is, in turn, extended by several
* other abstract classes that create different classes of GUI components for
* JMeter (Visualizers, Timers, Samplers, Modifiers, Controllers, etc).
*
* @see org.apache.jmeter.gui.JMeterGUIComponent
* @see org.apache.jmeter.config.gui.AbstractConfigGui
* @see org.apache.jmeter.assertions.gui.AbstractAssertionGui
* @see org.apache.jmeter.control.gui.AbstractControllerGui
* @see org.apache.jmeter.timers.gui.AbstractTimerGui
* @see org.apache.jmeter.visualizers.gui.AbstractVisualizer
* @see org.apache.jmeter.samplers.gui.AbstractSamplerGui
*
*/
public abstract class AbstractJMeterGuiComponent extends JPanel implements JMeterGUIComponent, Printable {
/** Logging */
private static final Logger log = LoggingManager.getLoggerForClass();
/** Flag indicating whether or not this component is enabled. */
private boolean enabled = true;
/** The tree node which this component is associated with. */
private TreeNode node;
/** A GUI panel containing the name of this component. */
protected NamePanel namePanel;
// used by AbstractReportGui
private CommentPanel commentPanel;
/**
* When constructing a new component, this takes care of basic tasks like
* setting up the Name Panel and assigning the class's static label as the
* name to start.
*/
public AbstractJMeterGuiComponent() {
namePanel = new NamePanel();
commentPanel=new CommentPanel();
initGui();
}
/**
* Provides a default implementation for setting the name property. It's unlikely
* developers will need to override.
*/
public void setName(String name) {
namePanel.setName(name);
}
/**
* Provides a default implementation for setting the comment property. It's unlikely
* developers will need to override.
*/
public void setComment(String comment) {
commentPanel.setText(comment);
}
/**
* Provides a default implementation for the enabled property. It's unlikely
* developers will need to override.
*/
public boolean isEnabled() {
return enabled;
}
/**
* Provides a default implementation for the enabled property. It's unlikely
* developers will need to override.
*/
public void setEnabled(boolean e) {
log.debug("Setting enabled: " + e);
enabled = e;
}
/**
* Provides a default implementation for the name property. It's unlikely
* developers will need to override.
*/
public String getName() {
if (getNamePanel() != null) {
return getNamePanel().getName();
}
return ""; // $NON-NLS-1$
}
/**
* Provides a default implementation for the comment property. It's unlikely
* developers will need to override.
*/
public String getComment() {
if (getCommentPanel() != null) {
return getCommentPanel().getText();
}
return ""; // $NON-NLS-1$
}
/**
* Provides the Name Panel for extending classes. Extending classes are free
* to place it as desired within the component, or not at all. Most
* components place the NamePanel automatically by calling
* {@link #makeTitlePanel()} instead of directly calling this method.
*
* @return a NamePanel containing the name of this component
*/
protected NamePanel getNamePanel() {
return namePanel;
}
private CommentPanel getCommentPanel(){
return commentPanel;
}
/**
* Provides a label containing the title for the component. Subclasses
* typically place this label at the top of their GUI. The title is set to
* the name returned from the component's
* {@link JMeterGUIComponent#getStaticLabel() getStaticLabel()} method. Most
* components place this label automatically by calling
* {@link #makeTitlePanel()} instead of directly calling this method.
*
* @return a JLabel which subclasses can add to their GUI
*/
protected Component createTitleLabel() {
JLabel titleLabel = new JLabel(getStaticLabel());
Font curFont = titleLabel.getFont();
titleLabel.setFont(curFont.deriveFont((float) curFont.getSize() + 4));
return titleLabel;
}
/**
* A newly created gui component can be initialized with the contents of a
* Test Element object by calling this method. The component is responsible
* for querying the Test Element object for the relevant information to
* display in its GUI.
* <p>
* AbstractJMeterGuiComponent provides a partial implementation of this
* method, setting the name of the component and its enabled status.
* Subclasses should override this method, performing their own
* configuration as needed, but also calling this super-implementation.
*
* @param element
* the TestElement to configure
*/
public void configure(TestElement element) {
setName(element.getName());
if (element.getProperty(TestElement.ENABLED) instanceof NullProperty) {
enabled = true;
} else {
enabled = element.getPropertyAsBoolean(TestElement.ENABLED);
}
getCommentPanel().setText(element.getComment());
}
/**
* Provides a default implementation that resets the name field to the value of
* getStaticLabel(), reset comment and sets enabled to true. Your GUI may need more things
* cleared, in which case you should override, clear the extra fields, and
* still call super.clearGui().
*/
public void clearGui() {
initGui();
enabled = true;
}
// helper method - also used by constructor
private void initGui() {
setName(getStaticLabel());
commentPanel.clearGui();
}
/**
* This provides a convenience for extenders when they implement the
* {@link JMeterGUIComponent#modifyTestElement(TestElement)} method. This
* method will set the name, gui class, and test class for the created Test
* Element. It should be called by every extending class when
* creating/modifying Test Elements, as that will best assure consistent
* behavior.
*
* @param mc
* the TestElement being created.
*/
protected void configureTestElement(TestElement mc) {
mc.setName(getName());
mc.setProperty(new StringProperty(TestElement.GUI_CLASS, this.getClass().getName()));
mc.setProperty(new StringProperty(TestElement.TEST_CLASS, mc.getClass().getName()));
// This stores the state of the TestElement
log.debug("setting element to enabled: " + enabled);
mc.setProperty(new BooleanProperty(TestElement.ENABLED, enabled));
mc.setComment(getComment());
}
/**
* Provides a default implementation for the node property. It is unlikely
* developers would need to override this method.
*/
public void setNode(TreeNode node) {
this.node = node;
getNamePanel().setNode(node);
}
/**
* Provides a default implementation for the node property. It is unlikely
* developers would need to override this method.
*/
protected TreeNode getNode() {
return node;
}
/**
* Create a standard title section for JMeter components. This includes the
* title for the component and the Name Panel allowing the user to change
* the name for the component. This method is typically added to the top of
* the component at the beginning of the component's init method.
*
* @return a panel containing the component title and name panel
*/
protected Container makeTitlePanel() {
VerticalPanel titlePanel = new VerticalPanel();
titlePanel.add(createTitleLabel());
VerticalPanel contentPanel = new VerticalPanel();
contentPanel.setBorder(BorderFactory.createEtchedBorder());
contentPanel.add(getNamePanel());
contentPanel.add(getCommentPanel());
titlePanel.add(contentPanel);
return titlePanel;
}
/**
* Create a top-level Border which can be added to JMeter components.
* Components typically set this as their border in their init method. It
* simply provides a nice spacing between the GUI components used and the
* edges of the window in which they appear.
*
* @return a Border for JMeter components
*/
protected Border makeBorder() {
return BorderFactory.createEmptyBorder(10, 10, 5, 10);
}
/**
* Create a scroll panel that sets it's preferred size to it's minimum size.
* Explicitly for scroll panes that live inside other scroll panes, or
* within containers that stretch components to fill the area they exist in.
* Use this for any component you would put in a scroll pane (such as
* TextAreas, tables, JLists, etc). It is here for convenience and to avoid
* duplicate code. JMeter displays best if you follow this custom.
*
* @param comp
* the component which should be placed inside the scroll pane
* @return a JScrollPane containing the specified component
*/
protected JScrollPane makeScrollPane(Component comp) {
JScrollPane pane = new JScrollPane(comp);
pane.setPreferredSize(pane.getMinimumSize());
return pane;
}
/**
* Create a scroll panel that sets it's preferred size to it's minimum size.
* Explicitly for scroll panes that live inside other scroll panes, or
* within containers that stretch components to fill the area they exist in.
* Use this for any component you would put in a scroll pane (such as
* TextAreas, tables, JLists, etc). It is here for convenience and to avoid
* duplicate code. JMeter displays best if you follow this custom.
*
* @see javax.swing.ScrollPaneConstants
*
* @param comp
* the component which should be placed inside the scroll pane
* @param verticalPolicy
* the vertical scroll policy
* @param horizontalPolicy
* the horizontal scroll policy
* @return a JScrollPane containing the specified component
*/
protected JScrollPane makeScrollPane(Component comp, int verticalPolicy, int horizontalPolicy) {
JScrollPane pane = new JScrollPane(comp, verticalPolicy, horizontalPolicy);
pane.setPreferredSize(pane.getMinimumSize());
return pane;
}
public String getStaticLabel() {
return JMeterUtils.getResString(getLabelResource());
}
public String getDocAnchor() {
return getStaticLabel().replace(' ', '_');
}
/**
* Subclasses need to over-ride this method, if they wish to return
* something other than the Visualizer itself.
*
* @return this object
*/
public JComponent getPrintableComponent() {
return this;
}
}