001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.gui;
020:
021: import java.awt.Component;
022: import java.awt.Container;
023: import java.awt.Font;
024:
025: import javax.swing.BorderFactory;
026: import javax.swing.JComponent;
027: import javax.swing.JLabel;
028: import javax.swing.JPanel;
029: import javax.swing.JScrollPane;
030: import javax.swing.border.Border;
031: import javax.swing.tree.TreeNode;
032:
033: import org.apache.jmeter.gui.util.VerticalPanel;
034: import org.apache.jmeter.testelement.TestElement;
035: import org.apache.jmeter.testelement.property.BooleanProperty;
036: import org.apache.jmeter.testelement.property.NullProperty;
037: import org.apache.jmeter.testelement.property.StringProperty;
038: import org.apache.jmeter.util.JMeterUtils;
039: import org.apache.jmeter.visualizers.Printable;
040: import org.apache.jorphan.logging.LoggingManager;
041: import org.apache.log.Logger;
042:
043: /**
044: * This abstract class takes care of the most basic functions necessary to
045: * create a viable JMeter GUI component. It extends JPanel and implements
046: * JMeterGUIComponent. This abstract class is, in turn, extended by several
047: * other abstract classes that create different classes of GUI components for
048: * JMeter (Visualizers, Timers, Samplers, Modifiers, Controllers, etc).
049: *
050: * @see org.apache.jmeter.gui.JMeterGUIComponent
051: * @see org.apache.jmeter.config.gui.AbstractConfigGui
052: * @see org.apache.jmeter.assertions.gui.AbstractAssertionGui
053: * @see org.apache.jmeter.control.gui.AbstractControllerGui
054: * @see org.apache.jmeter.timers.gui.AbstractTimerGui
055: * @see org.apache.jmeter.visualizers.gui.AbstractVisualizer
056: * @see org.apache.jmeter.samplers.gui.AbstractSamplerGui
057: *
058: */
059: public abstract class AbstractJMeterGuiComponent extends JPanel
060: implements JMeterGUIComponent, Printable {
061: /** Logging */
062: private static Logger log = LoggingManager.getLoggerForClass();
063:
064: /** Flag indicating whether or not this component is enabled. */
065: private boolean enabled = true;
066:
067: /** The tree node which this component is associated with. */
068: private TreeNode node;
069:
070: /** A GUI panel containing the name of this component. */
071: protected NamePanel namePanel;
072: // used by AbstractReportGui
073:
074: private CommentPanel commentPanel;
075:
076: /**
077: * When constructing a new component, this takes care of basic tasks like
078: * setting up the Name Panel and assigning the class's static label as the
079: * name to start.
080: */
081: public AbstractJMeterGuiComponent() {
082: namePanel = new NamePanel();
083: commentPanel = new CommentPanel();
084: initGui();
085: }
086:
087: /**
088: * Provides a default implementation for setting the name property. It's unlikely
089: * developers will need to override.
090: */
091: public void setName(String name) {
092: namePanel.setName(name);
093: }
094:
095: /**
096: * Provides a default implementation for setting the comment property. It's unlikely
097: * developers will need to override.
098: */
099: public void setComment(String comment) {
100: commentPanel.setText(comment);
101: }
102:
103: /**
104: * Provides a default implementation for the enabled property. It's unlikely
105: * developers will need to override.
106: */
107: public boolean isEnabled() {
108: return enabled;
109: }
110:
111: /**
112: * Provides a default implementation for the enabled property. It's unlikely
113: * developers will need to override.
114: */
115: public void setEnabled(boolean e) {
116: log.debug("Setting enabled: " + e);
117: enabled = e;
118: }
119:
120: /**
121: * Provides a default implementation for the name property. It's unlikely
122: * developers will need to override.
123: */
124: public String getName() {
125: if (getNamePanel() != null) {
126: return getNamePanel().getName();
127: } else
128: return ""; // $NON-NLS-1$
129: }
130:
131: /**
132: * Provides a default implementation for the comment property. It's unlikely
133: * developers will need to override.
134: */
135: public String getComment() {
136: if (getCommentPanel() != null) {
137: return getCommentPanel().getText();
138: } else {
139: return ""; // $NON-NLS-1$
140: }
141: }
142:
143: /**
144: * Provides the Name Panel for extending classes. Extending classes are free
145: * to place it as desired within the component, or not at all. Most
146: * components place the NamePanel automatically by calling
147: * {@link #makeTitlePanel()} instead of directly calling this method.
148: *
149: * @return a NamePanel containing the name of this component
150: */
151: protected NamePanel getNamePanel() {
152: return namePanel;
153: }
154:
155: private CommentPanel getCommentPanel() {
156: return commentPanel;
157: }
158:
159: /**
160: * Provides a label containing the title for the component. Subclasses
161: * typically place this label at the top of their GUI. The title is set to
162: * the name returned from the component's
163: * {@link JMeterGUIComponent#getStaticLabel() getStaticLabel()} method. Most
164: * components place this label automatically by calling
165: * {@link #makeTitlePanel()} instead of directly calling this method.
166: *
167: * @return a JLabel which subclasses can add to their GUI
168: */
169: protected Component createTitleLabel() {
170: JLabel titleLabel = new JLabel(getStaticLabel());
171: Font curFont = titleLabel.getFont();
172: titleLabel.setFont(curFont
173: .deriveFont((float) curFont.getSize() + 4));
174: return titleLabel;
175: }
176:
177: /**
178: * A newly created gui component can be initialized with the contents of a
179: * Test Element object by calling this method. The component is responsible
180: * for querying the Test Element object for the relevant information to
181: * display in its GUI.
182: * <p>
183: * AbstractJMeterGuiComponent provides a partial implementation of this
184: * method, setting the name of the component and its enabled status.
185: * Subclasses should override this method, performing their own
186: * configuration as needed, but also calling this super-implementation.
187: *
188: * @param element
189: * the TestElement to configure
190: */
191: public void configure(TestElement element) {
192: setName(element.getPropertyAsString(TestElement.NAME));
193: if (element.getProperty(TestElement.ENABLED) instanceof NullProperty) {
194: enabled = true;
195: } else {
196: enabled = element.getPropertyAsBoolean(TestElement.ENABLED);
197: }
198: getCommentPanel().setText(element.getComment());
199: }
200:
201: /**
202: * Provides a default implementation that resets the name field to the value of
203: * getStaticLabel(), reset comment and sets enabled to true. Your GUI may need more things
204: * cleared, in which case you should override, clear the extra fields, and
205: * still call super.clearGui().
206: */
207: public void clearGui() {
208: initGui();
209: enabled = true;
210: }
211:
212: // helper method - also used by constructor
213: private void initGui() {
214: setName(getStaticLabel());
215: commentPanel.clearGui();
216: }
217:
218: /**
219: * This provides a convenience for extenders when they implement the
220: * {@link JMeterGUIComponent#modifyTestElement(TestElement)} method. This
221: * method will set the name, gui class, and test class for the created Test
222: * Element. It should be called by every extending class when
223: * creating/modifying Test Elements, as that will best assure consistent
224: * behavior.
225: *
226: * @param mc
227: * the TestElement being created.
228: */
229: protected void configureTestElement(TestElement mc) {
230: mc.setProperty(new StringProperty(TestElement.NAME, getName()));
231:
232: mc.setProperty(new StringProperty(TestElement.GUI_CLASS, this
233: .getClass().getName()));
234:
235: mc.setProperty(new StringProperty(TestElement.TEST_CLASS, mc
236: .getClass().getName()));
237:
238: // This stores the state of the TestElement
239: log.debug("setting element to enabled: " + enabled);
240: mc
241: .setProperty(new BooleanProperty(TestElement.ENABLED,
242: enabled));
243: mc.setComment(getComment());
244: }
245:
246: /**
247: * Provides a default implementation for the node property. It is unlikely
248: * developers would need to override this method.
249: */
250: public void setNode(TreeNode node) {
251: this .node = node;
252: getNamePanel().setNode(node);
253: }
254:
255: /**
256: * Provides a default implementation for the node property. It is unlikely
257: * developers would need to override this method.
258: */
259: protected TreeNode getNode() {
260: return node;
261: }
262:
263: /**
264: * Create a standard title section for JMeter components. This includes the
265: * title for the component and the Name Panel allowing the user to change
266: * the name for the component. This method is typically added to the top of
267: * the component at the beginning of the component's init method.
268: *
269: * @return a panel containing the component title and name panel
270: */
271: protected Container makeTitlePanel() {
272: VerticalPanel titlePanel = new VerticalPanel();
273: titlePanel.add(createTitleLabel());
274: VerticalPanel contentPanel = new VerticalPanel();
275: contentPanel.setBorder(BorderFactory.createEtchedBorder());
276: contentPanel.add(getNamePanel());
277: contentPanel.add(getCommentPanel());
278: titlePanel.add(contentPanel);
279: return titlePanel;
280: }
281:
282: /**
283: * Create a top-level Border which can be added to JMeter components.
284: * Components typically set this as their border in their init method. It
285: * simply provides a nice spacing between the GUI components used and the
286: * edges of the window in which they appear.
287: *
288: * @return a Border for JMeter components
289: */
290: protected Border makeBorder() {
291: return BorderFactory.createEmptyBorder(10, 10, 5, 10);
292: }
293:
294: /**
295: * Create a scroll panel that sets it's preferred size to it's minimum size.
296: * Explicitly for scroll panes that live inside other scroll panes, or
297: * within containers that stretch components to fill the area they exist in.
298: * Use this for any component you would put in a scroll pane (such as
299: * TextAreas, tables, JLists, etc). It is here for convenience and to avoid
300: * duplicate code. JMeter displays best if you follow this custom.
301: *
302: * @param comp
303: * the component which should be placed inside the scroll pane
304: * @return a JScrollPane containing the specified component
305: */
306: protected JScrollPane makeScrollPane(Component comp) {
307: JScrollPane pane = new JScrollPane(comp);
308: pane.setPreferredSize(pane.getMinimumSize());
309: return pane;
310: }
311:
312: /**
313: * Create a scroll panel that sets it's preferred size to it's minimum size.
314: * Explicitly for scroll panes that live inside other scroll panes, or
315: * within containers that stretch components to fill the area they exist in.
316: * Use this for any component you would put in a scroll pane (such as
317: * TextAreas, tables, JLists, etc). It is here for convenience and to avoid
318: * duplicate code. JMeter displays best if you follow this custom.
319: *
320: * @see javax.swing.ScrollPaneConstants
321: *
322: * @param comp
323: * the component which should be placed inside the scroll pane
324: * @param verticalPolicy
325: * the vertical scroll policy
326: * @param horizontalPolicy
327: * the horizontal scroll policy
328: * @return a JScrollPane containing the specified component
329: */
330: protected JScrollPane makeScrollPane(Component comp,
331: int verticalPolicy, int horizontalPolicy) {
332: JScrollPane pane = new JScrollPane(comp, verticalPolicy,
333: horizontalPolicy);
334: pane.setPreferredSize(pane.getMinimumSize());
335: return pane;
336: }
337:
338: public String getStaticLabel() {
339: return JMeterUtils.getResString(getLabelResource());
340: }
341:
342: public String getDocAnchor() {
343: return getStaticLabel().replace(' ', '_');
344: }
345:
346: /**
347: * Subclasses need to over-ride this method, if they wish to return
348: * something other than the Visualizer itself.
349: *
350: * @return this object
351: */
352: public JComponent getPrintableComponent() {
353: return this;
354: }
355: }
|