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.protocol.ldap.config.gui;
020:
021: import java.awt.BorderLayout;
022: import java.awt.Component;
023: import java.awt.FlowLayout;
024: import java.awt.event.ActionEvent;
025: import java.awt.event.ActionListener;
026: import java.util.Collection;
027: import java.util.Iterator;
028:
029: import javax.swing.BorderFactory;
030: import javax.swing.Box;
031: import javax.swing.JButton;
032: import javax.swing.JLabel;
033: import javax.swing.JPanel;
034: import javax.swing.JTable;
035: import javax.swing.ListSelectionModel;
036: import javax.swing.table.TableCellEditor;
037:
038: import org.apache.jmeter.config.gui.AbstractConfigGui;
039: import org.apache.jmeter.testelement.TestElement;
040: import org.apache.jmeter.testelement.property.PropertyIterator;
041: import org.apache.jmeter.util.JMeterUtils;
042: import org.apache.jorphan.gui.ObjectTableModel;
043: import org.apache.jorphan.reflect.Functor;
044:
045: /**
046: * A GUI panel allowing the user to enter name-value argument pairs. These
047: * arguments (or parameters) are usually used to provide configuration values
048: * for some other component.
049: *
050: * author Dolf Smits(Dolf.Smits@Siemens.com) created Aug 09 2003 11:00 AM
051: * company Siemens Netherlands N.V..
052: *
053: * Based on the work of:
054: *
055: * author Michael Stover
056: */
057:
058: public class LDAPArgumentsPanel extends AbstractConfigGui implements
059: ActionListener {
060: /** Logging. */
061: //private static final Logger log = LoggingManager.getLoggerForClass();
062: /** The title label for this component. */
063: private JLabel tableLabel;
064:
065: /** The table containing the list of arguments. */
066: private transient JTable table;
067:
068: /** The model for the arguments table. */
069: protected transient ObjectTableModel tableModel;
070:
071: /** A button for adding new arguments to the table. */
072: private JButton add;
073:
074: /** A button for removing arguments from the table. */
075: private JButton delete;
076:
077: /** Command for adding a row to the table. */
078: private static final String ADD = "add"; //$NON-NLS-1$
079:
080: /** Command for removing a row from the table. */
081: private static final String DELETE = "delete"; //$NON-NLS-1$
082:
083: private static final String[] COLUMN_NAMES = {
084: JMeterUtils.getResString("attribute"), //$NON-NLS-1$
085: JMeterUtils.getResString("value"), //$NON-NLS-1$
086: JMeterUtils.getResString("opcode"), //$NON-NLS-1$
087: JMeterUtils.getResString("metadata") }; //$NON-NLS-1$
088:
089: /**
090: * Create a new LDAPArgumentsPanel, using the default title.
091: */
092: public LDAPArgumentsPanel() {
093: this (JMeterUtils.getResString("paramtable")); //$NON-NLS-1$
094: }
095:
096: /**
097: * Create a new LDAPArgumentsPanel, using the specified title.
098: *
099: * @param label
100: * the title of the component
101: */
102: public LDAPArgumentsPanel(String label) {
103: tableLabel = new JLabel(label);
104: init();
105: }
106:
107: /**
108: * This is the list of menu categories this gui component will be available
109: * under. The LDAPArgumentsPanel is not intended to be used as a standalone
110: * component, so this inplementation returns null.
111: *
112: * @return a Collection of Strings, where each element is one of the
113: * constants defined in MenuFactory
114: */
115: public Collection getMenuCategories() {
116: return null;
117: }
118:
119: public String getStaticLabel() {
120: return ""; // This is not an independently displayable item
121: }
122:
123: public String getLabelResource() {
124: return "unused";// TODO use constant
125: }
126:
127: /* Implements JMeterGUIComponent.createTestElement() */
128: public TestElement createTestElement() {
129: LDAPArguments args = new LDAPArguments();
130: modifyTestElement(args);
131: // TODO: Why do we clone the return value? This is the only reference
132: // to it (right?) so we shouldn't need a separate copy.
133: return (TestElement) args.clone();
134: }
135:
136: /* Implements JMeterGUIComponent.modifyTestElement(TestElement) */
137: public void modifyTestElement(TestElement args) {
138: stopTableEditing();
139: Iterator modelData = tableModel.iterator();
140: LDAPArguments arguments = null;
141: if (args instanceof LDAPArguments) {
142: arguments = (LDAPArguments) args;
143: arguments.clear();
144: while (modelData.hasNext()) {
145: LDAPArgument arg = (LDAPArgument) modelData.next();
146: arg.setMetaData("=");
147: arguments.addArgument(arg);
148: }
149: }
150: this .configureTestElement(args);
151: }
152:
153: /**
154: * A newly created component can be initialized with the contents of a Test
155: * Element object by calling this method. The component is responsible for
156: * querying the Test Element object for the relevant information to display
157: * in its GUI.
158: *
159: * @param el
160: * the TestElement to configure
161: */
162: public void configure(TestElement el) {
163: super .configure(el);
164: if (el instanceof LDAPArguments) {
165: tableModel.clearData();
166: PropertyIterator iter = ((LDAPArguments) el).iterator();
167: while (iter.hasNext()) {
168: LDAPArgument arg = (LDAPArgument) iter.next()
169: .getObjectValue();
170: tableModel.addRow(arg);
171: }
172: }
173: checkDeleteStatus();
174: }
175:
176: /**
177: * Get the table used to enter arguments.
178: *
179: * @return the table used to enter arguments
180: */
181: protected JTable getTable() {
182: return table;
183: }
184:
185: /**
186: * Get the title label for this component.
187: *
188: * @return the title label displayed with the table
189: */
190: protected JLabel getTableLabel() {
191: return tableLabel;
192: }
193:
194: /**
195: * Get the button used to delete rows from the table.
196: *
197: * @return the button used to delete rows from the table
198: */
199: protected JButton getDeleteButton() {
200: return delete;
201: }
202:
203: /**
204: * Get the button used to add rows to the table.
205: *
206: * @return the button used to add rows to the table
207: */
208: protected JButton getAddButton() {
209: return add;
210: }
211:
212: /**
213: * Enable or disable the delete button depending on whether or not there is
214: * a row to be deleted.
215: */
216: protected void checkDeleteStatus() {
217: // Disable DELETE if there are no rows in the table to delete.
218: if (tableModel.getRowCount() == 0) {
219: delete.setEnabled(false);
220: } else {
221: delete.setEnabled(true);
222: }
223: }
224:
225: /**
226: * Clear all rows from the table. T.Elanjchezhiyan(chezhiyan@siptech.co.in)
227: */
228: public void clear() {
229: tableModel.clearData();
230: }
231:
232: /**
233: * Invoked when an action occurs. This implementation supports the add and
234: * delete buttons.
235: *
236: * @param e
237: * the event that has occurred
238: */
239: public void actionPerformed(ActionEvent e) {
240: String action = e.getActionCommand();
241: if (action.equals(DELETE)) {
242: deleteArgument();
243: } else if (action.equals(ADD)) {
244: addArgument();
245: }
246: }
247:
248: /**
249: * Remove the currently selected argument from the table.
250: */
251: protected void deleteArgument() {
252: // If a table cell is being edited, we must cancel the editing before
253: // deleting the row
254: if (table.isEditing()) {
255: TableCellEditor cellEditor = table.getCellEditor(table
256: .getEditingRow(), table.getEditingColumn());
257: cellEditor.cancelCellEditing();
258: }
259:
260: int rowSelected = table.getSelectedRow();
261: if (rowSelected >= 0) {
262: tableModel.removeRow(rowSelected);
263: tableModel.fireTableDataChanged();
264:
265: // Disable DELETE if there are no rows in the table to delete.
266: if (tableModel.getRowCount() == 0) {
267: delete.setEnabled(false);
268: }
269:
270: // Table still contains one or more rows, so highlight (select)
271: // the appropriate one.
272: else {
273: int rowToSelect = rowSelected;
274:
275: if (rowSelected >= tableModel.getRowCount()) {
276: rowToSelect = rowSelected - 1;
277: }
278:
279: table.setRowSelectionInterval(rowToSelect, rowToSelect);
280: }
281: }
282: }
283:
284: /**
285: * Add a new argument row to the table.
286: */
287: protected void addArgument() {
288: // If a table cell is being edited, we should accept the current value
289: // and stop the editing before adding a new row.
290: stopTableEditing();
291:
292: tableModel.addRow(makeNewLDAPArgument());
293:
294: // Enable DELETE (which may already be enabled, but it won't hurt)
295: delete.setEnabled(true);
296:
297: // Highlight (select) the appropriate row.
298: int rowToSelect = tableModel.getRowCount() - 1;
299: table.setRowSelectionInterval(rowToSelect, rowToSelect);
300: }
301:
302: /**
303: * Create a new LDAPArgument object.
304: *
305: * @return a new LDAPArgument object
306: */
307: protected Object makeNewLDAPArgument() {
308: return new LDAPArgument("", "", "");
309: }
310:
311: /**
312: * Stop any editing that is currently being done on the table. This will
313: * save any changes that have already been made.
314: */
315: private void stopTableEditing() {
316: if (table.isEditing()) {
317: TableCellEditor cellEditor = table.getCellEditor(table
318: .getEditingRow(), table.getEditingColumn());
319: cellEditor.stopCellEditing();
320: }
321: }
322:
323: /**
324: * Initialize the table model used for the arguments table.
325: */
326: protected void initializeTableModel() {
327: tableModel = new ObjectTableModel(new String[] {
328: COLUMN_NAMES[0], COLUMN_NAMES[1], COLUMN_NAMES[2] },
329: LDAPArgument.class, new Functor[] {
330: new Functor("getName"),
331: new Functor("getValue"),
332: new Functor("getOpcode") }, new Functor[] {
333: new Functor("setName"),
334: new Functor("setValue"),
335: new Functor("setOpcode") }, new Class[] {
336: String.class, String.class, String.class });
337: }
338:
339: public static boolean testFunctors() {
340: LDAPArgumentsPanel instance = new LDAPArgumentsPanel();
341: instance.initializeTableModel();
342: return instance.tableModel.checkFunctors(null, instance
343: .getClass());
344: }
345:
346: /*
347: * protected void initializeTableModel() { tableModel = new
348: * ObjectTableModel( new String[] { ArgumentsPanel.COLUMN_NAMES_0,
349: * ArgumentsPanel.COLUMN_NAMES_1, ENCODE_OR_NOT, INCLUDE_EQUALS }, new
350: * Functor[] { new Functor("getName"), new Functor("getValue"), new
351: * Functor("isAlwaysEncoded"), new Functor("isUseEquals") }, new Functor[] {
352: * new Functor("setName"), new Functor("setValue"), new
353: * Functor("setAlwaysEncoded"), new Functor("setUseEquals") }, new Class[] {
354: * String.class, String.class, Boolean.class, Boolean.class }); }
355: */
356: /**
357: * Resize the table columns to appropriate widths.
358: *
359: * @param _table
360: * the table to resize columns for
361: */
362: protected void sizeColumns(JTable _table) {
363: }
364:
365: /**
366: * Create the main GUI panel which contains the argument table.
367: *
368: * @return the main GUI panel
369: */
370: private Component makeMainPanel() {
371: initializeTableModel();
372: table = new JTable(tableModel);
373: table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
374: return makeScrollPane(table);
375: }
376:
377: /**
378: * Create a panel containing the title label for the table.
379: *
380: * @return a panel containing the title label
381: */
382: protected Component makeLabelPanel() {
383: JPanel labelPanel = new JPanel(
384: new FlowLayout(FlowLayout.CENTER));
385: labelPanel.add(tableLabel);
386: return labelPanel;
387: }
388:
389: /**
390: * Create a panel containing the add and delete buttons.
391: *
392: * @return a GUI panel containing the buttons
393: */
394: private JPanel makeButtonPanel() {
395: add = new JButton(JMeterUtils.getResString("add")); //$NON-NLS-1$
396: add.setActionCommand(ADD);
397: add.setEnabled(true);
398:
399: delete = new JButton(JMeterUtils.getResString("delete")); //$NON-NLS-1$
400: delete.setActionCommand(DELETE);
401:
402: checkDeleteStatus();
403:
404: JPanel buttonPanel = new JPanel();
405: buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0,
406: 10));
407: add.addActionListener(this );
408: delete.addActionListener(this );
409: buttonPanel.add(add);
410: buttonPanel.add(delete);
411: return buttonPanel;
412: }
413:
414: /**
415: * Initialize the components and layout of this component.
416: */
417: private void init() {
418: setLayout(new BorderLayout());
419:
420: add(makeLabelPanel(), BorderLayout.NORTH);
421: add(makeMainPanel(), BorderLayout.CENTER);
422: // Force a minimum table height of 70 pixels
423: add(Box.createVerticalStrut(70), BorderLayout.WEST);
424: add(makeButtonPanel(), BorderLayout.SOUTH);
425:
426: table.revalidate();
427: sizeColumns(table);
428: }
429: }
|