/* * 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.codehaus.groovy.runtime; import groovy.lang.GString; import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling; import javax.swing.*; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import java.awt.*; import java.util.Enumeration; import java.util.Iterator; /** * This class defines all the new Swing-related groovy methods which enhance * the normal JDK Swing classes when inside the Groovy environment. * Static methods are used with the first parameter the destination class. * * @author Andres Almiray */ public class SwingGroovyMethods { /** * Provide the standard Groovy <code>size()</code> method for <code>Container</code>. * * @param self a Container * @return the component count of the container * @since 1.6.4 */ public static int size(Container self) { return self.getComponentCount(); } /** * Support the subscript operator for Container. * * @param self a Container * @param index the index of the Component to get * @return the component at the given index * @since 1.6.4 */ public static Component getAt(Container self, int index) { return self.getComponent(index); } /** * Overloads the left shift operator to provide an easy way to add * components to a Container. * * @param self a Container * @param c a Component to be added to the container. * @return same container, after the value was added to it. * @since 1.6.4 */ public static Container leftShift(Container self, Component c) { self.add(c); return self; } /** * Returns an {@link java.util.Iterator} which traverses the Container one Component at a time. * * @param self a Container * @return an Iterator for a Container * @since 1.6.4 */ public static Iterator<Component> iterator(Container self) { return DefaultGroovyMethods.iterator(self.getComponents()); } /** * Removes all components from the Container. * * @param self a Container * @since 1.6.4 */ public static void clear(Container self) { self.removeAll(); } /** * Provide the standard Groovy <code>size()</code> method for <code>ButtonGroup</code>. * * @param self a ButtonGroup * @return the button count of the buttonGroup * @since 1.6.4 */ public static int size(ButtonGroup self) { return self.getButtonCount(); } /** * Support the subscript operator for ButtonGroup. * * @param self a ButtonGroup * @param index the index of the AbstractButton to get * @return the button at the given index * @since 1.6.4 */ public static AbstractButton getAt(ButtonGroup self, int index) { int size = self.getButtonCount(); if (index < 0 || index >= size) return null; Enumeration buttons = self.getElements(); for (int i = 0; i <= index; i++) { AbstractButton b = (AbstractButton) buttons.nextElement(); if (i == index) return b; } return null; } /** * Overloads the left shift operator to provide an easy way to add * buttons to a ButtonGroup. * * @param self a ButtonGroup * @param b an AbstractButton to be added to the buttonGroup. * @return same buttonGroup, after the value was added to it. * @since 1.6.4 */ public static ButtonGroup leftShift(ButtonGroup self, AbstractButton b) { self.add(b); return self; } /** * Returns an {@link java.util.Iterator} which traverses the ButtonGroup one AbstractButton at a time. * * @param self a ButtonGroup * @return an Iterator for a ButtonGroup * @since 1.6.4 */ public static Iterator<AbstractButton> iterator(ButtonGroup self) { return DefaultGroovyMethods.iterator(self.getElements()); } /** * Provide the standard Groovy <code>size()</code> method for <code>ListModel</code>. * * @param self a ListModel * @return the size of the ListModel * @since 1.6.4 */ public static int size(ListModel self) { return self.getSize(); } /** * Support the subscript operator for ListModel. * * @param self a ListModel * @param index the index of the element to get * @return the element at the given index * @since 1.6.4 */ public static Object getAt(ListModel self, int index) { return self.getElementAt(index); } /** * Returns an {@link java.util.Iterator} which traverses the ListModel one element at a time. * * @param self a ListModel * @return an Iterator for a ListModel * @since 1.6.4 */ public static Iterator iterator(final ListModel self) { return new Iterator() { private int index = 0; public boolean hasNext() { return index < self.getSize(); } public Object next() { return self.getElementAt(index++); } public void remove() { throw new UnsupportedOperationException("LisModel is immutable."); } }; } /** * Overloads the left shift operator to provide an easy way to add * elements to a DefaultListModel. * * @param self a DefaultListModel * @param e an element to be added to the listModel. * @return same listModel, after the value was added to it. * @since 1.6.4 */ public static DefaultListModel leftShift(DefaultListModel self, Object e) { self.addElement(e); return self; } /** * Allow DefaultListModel to work with subscript operators.<p> * <b>WARNING:</b> this operation does not replace the element at the * specified index, rather it inserts the element at that index, thus * increasing the size of of the model by 1. * * @param self a DefaultListModel * @param index an index * @param e the element to insert at the given index * @since 1.6.4 */ public static void putAt(DefaultListModel self, int index, Object e) { self.set(index, e); } /** * Removes all elements from the DefaultListModel. * * @param self a DefaultListModel * @since 1.6.4 */ public static void clear(DefaultListModel self) { self.removeAllElements(); } /** * Returns an {@link java.util.Iterator} which traverses the DefaultListModel one element at a time. * * @param self a DefaultListModel * @return an Iterator for a DefaultListModel * @since 1.6.4 */ public static Iterator iterator(final DefaultListModel self) { return new Iterator() { private int index = 0; public boolean hasNext() { return index > -1 && index < self.getSize(); } public Object next() { return self.getElementAt(index++); } public void remove() { if (hasNext()) self.removeElementAt(index--); } }; } /** * Provide the standard Groovy <code>size()</code> method for <code>JComboBox</code>. * * @param self a JComboBox * @return the item count of the comboBox * @since 1.6.4 */ public static int size(JComboBox self) { return self.getItemCount(); } /** * Support the subscript operator for JComboBox. * * @param self a JComboBox * @param index the index of the item to get * @return the tem at the given index * @since 1.6.4 */ public static Object getAt(JComboBox self, int index) { return self.getItemAt(index); } /** * Overloads the left shift operator to provide an easy way to add * items to a JComboBox. * * @param self a JComboBox * @param i an item to be added to the comboBox. * @return same comboBox, after the value was added to it. * @since 1.6.4 */ public static JComboBox leftShift(JComboBox self, Object i) { self.addItem(i); return self; } /** * Removes all items from the JComboBox. * * @param self a JComboBox * @since 1.6.4 */ public static void clear(JComboBox self) { self.removeAllItems(); } /** * Returns an {@link java.util.Iterator} which traverses the ComboBox one item at a time. * * @param self a ComboBox * @return an Iterator for a ComboBox * @since 1.6.4 */ public static Iterator iterator(JComboBox self) { return iterator(self.getModel()); } /** * Overloads the left shift operator to provide an easy way to add * items to a MutableComboBoxModel. * * @param self a MutableComboBoxModel * @param i an item to be added to the model. * @return same model, after the value was added to it. * @since 1.6.4 */ public static MutableComboBoxModel leftShift(MutableComboBoxModel self, Object i) { self.addElement(i); return self; } /** * Allow MutableComboBoxModel to work with subscript operators.<p> * <b>WARNING:</b> this operation does not replace the item at the * specified index, rather it inserts the item at that index, thus * increasing the size of the model by 1. * * @param self a MutableComboBoxModel * @param index an index * @param i the item to insert at the given index * @since 1.6.4 */ public static void putAt(MutableComboBoxModel self, int index, Object i) { self.insertElementAt(i, index); } /** * Returns an {@link java.util.Iterator} which traverses the MutableComboBoxModel one item at a time. * * @param self a MutableComboBoxModel * @return an Iterator for a MutableComboBoxModel * @since 1.6.4 */ public static Iterator iterator(final MutableComboBoxModel self) { return new Iterator() { private int index = 0; public boolean hasNext() { return index > -1 && index < self.getSize(); } public Object next() { return self.getElementAt(index++); } public void remove() { if (hasNext()) self.removeElementAt(index--); } }; } /** * Removes all items from the model. * * @param self a DefaultComboBoxModel * @since 1.7.3 */ public static void clear(DefaultComboBoxModel self) { self.removeAllElements(); } /** * Provide the standard Groovy <code>size()</code> method for <code>TableModel</code>. * * @param self a TableModel * @return the row count of the TableModel * @since 1.6.4 */ public static int size(TableModel self) { return self.getRowCount(); } /** * Support the subscript operator for TableModel. * * @param self a TableModel * @param index the index of the row to get * @return the row at the given index * @since 1.6.4 */ public static Object[] getAt(TableModel self, int index) { int cols = self.getColumnCount(); Object[] rowData = new Object[cols]; for (int col = 0; col < cols; col++) { rowData[col] = self.getValueAt(index, col); } return rowData; } /** * Returns an {@link java.util.Iterator} which traverses the TableModel one row at a time. * * @param self a TableModel * @return an Iterator for a TableModel * @since 1.6.4 */ public static Iterator iterator(final TableModel self) { return new Iterator() { private int row = 0; public boolean hasNext() { return row < self.getRowCount(); } public Object next() { int cols = self.getColumnCount(); Object[] rowData = new Object[cols]; for (int col = 0; col < cols; col++) { rowData[col] = self.getValueAt(row, col); } row++; return rowData; } public void remove() { throw new UnsupportedOperationException("TableModel is immutable."); } }; } /** * Overloads the left shift operator to provide an easy way to add * rows to a DefaultTableModel. * <p> * if row.size < model.size -> row will be padded with nulls<br> * if row.size > model.size -> additional columns will be discarded<br> * * @param self a DefaultTableModel * @param row a row to be added to the model. * @return same model, after the value was added to it. * @since 1.6.4 */ public static DefaultTableModel leftShift(DefaultTableModel self, Object row) { if (row == null) { // adds an empty row self.addRow((Object[]) null); return self; } self.addRow(buildRowData(self, row)); return self; } /** * Allow DefaultTableModel to work with subscript operators.<p> * <b>WARNING:</b> this operation does not replace the item at the * specified index, rather it inserts the item at that index, thus * increasing the size of the model by 1.<p> * <p> * if row.size < model.size -> row will be padded with nulls<br> * if row.size > model.size -> additional columns will be discarded * * @param self a DefaultTableModel * @param index an index * @param row the row to insert at the given index * @since 1.6.4 */ public static void putAt(DefaultTableModel self, int index, Object row) { if (row == null) { // adds an empty row self.insertRow(index, (Object[]) null); return; } self.insertRow(index, buildRowData(self, row)); } private static Object[] buildRowData(DefaultTableModel delegate, Object row) { int cols = delegate.getColumnCount(); Object[] rowData = new Object[cols]; int i = 0; for (Iterator it = DefaultGroovyMethods.iterator(row); it.hasNext() && i < cols;) { rowData[i++] = it.next(); } return rowData; } /** * Returns an {@link java.util.Iterator} which traverses the DefaultTableModel one item at a time. * * @param self a DefaultTableModel * @return an Iterator for a DefaultTableModel * @since 1.6.4 */ public static Iterator iterator(final DefaultTableModel self) { return new Iterator() { private int row = 0; public boolean hasNext() { return row > -1 && row < self.getRowCount(); } public Object next() { int cols = self.getColumnCount(); Object[] rowData = new Object[cols]; for (int col = 0; col < cols; col++) { rowData[col] = self.getValueAt(row, col); } row++; return rowData; } public void remove() { if (hasNext()) self.removeRow(row--); } }; } /** * Provide the standard Groovy <code>size()</code> method for <code>TableColumnModel</code>. * * @param self a TableColumnModel * @return the column count of the TableColumnModel * @since 1.6.4 */ public static int size(TableColumnModel self) { return self.getColumnCount(); } /** * Support the subscript operator for TableColumnModel. * * @param self a TableColumnModel * @param index the index of the column to get * @return the column at the given index * @since 1.6.4 */ public static TableColumn getAt(TableColumnModel self, int index) { return self.getColumn(index); } /** * Returns an {@link java.util.Iterator} which traverses the TableColumnModel one TableColumn at a time. * * @param self a TableColumnModel * @return an Iterator for a TableColumnModel * @since 1.6.4 */ public static Iterator<TableColumn> iterator(final TableColumnModel self) { return new Iterator<TableColumn>() { private int index = 0; public boolean hasNext() { return index > -1 && index < self.getColumnCount(); } public TableColumn next() { return self.getColumn(index++); } public void remove() { if (hasNext()) self.removeColumn(self.getColumn(index--)); } }; } /** * Overloads the left shift operator to provide an easy way to add * columns to a TableColumnModel. * * @param self a TableColumnModel * @param column a TableColumn to be added to the model. * @return same model, after the value was added to it. * @since 1.6.4 */ public static TableColumnModel leftShift(TableColumnModel self, TableColumn column) { self.addColumn(column); return self; } /** * Provide the standard Groovy <code>size()</code> method for <code>TreePath</code>. * * @param self a TreePath * @return the path count of the treePath * @since 1.6.4 */ public static int size(TreePath self) { return self.getPathCount(); } /** * Support the subscript operator for TreePath. * * @param self a TreePath * @param index the index of the path to get * @return the path at the given index * @since 1.6.4 */ public static Object getAt(TreePath self, int index) { return self.getPath()[index]; } /** * Overloads the left shift operator to provide an easy way to add * paths to a treePath.<p> * <b>WARNING:</b> this operation returns a new TreePath, not the original one.<p> * * @param self a TreePath * @param p an object to be added to the treePath. * @return same treePath, after the value was added to it. * @since 1.6.4 */ public static TreePath leftShift(TreePath self, Object p) { return self.pathByAddingChild(p); } /** * Returns an {@link java.util.Iterator} which traverses the TreePath one path at a time. * * @param self a TreePath * @return an Iterator for a TreePath * @since 1.6.4 */ public static Iterator iterator(TreePath self) { return DefaultGroovyMethods.iterator(self.getPath()); } /** * Provide the standard Groovy <code>size()</code> method for <code>TreeNode</code>. * * @param self a TreeNode * @return the child count of the treeNode * @since 1.6.4 */ public static int size(TreeNode self) { return self.getChildCount(); } /** * Support the subscript operator for TreeNode. * * @param self a TreeNode * @param index the index of the child node to get * @return the child node at the given index * @since 1.6.4 */ public static TreeNode getAt(TreeNode self, int index) { return self.getChildAt(index); } /** * Returns an {@link java.util.Iterator} which traverses the TreeNode one node at a time. * * @param self a TreeNode * @return an Iterator for a TreeNode * @since 1.6.4 */ @SuppressWarnings("unchecked") public static Iterator<TreeNode> iterator(TreeNode self) { return (Iterator<TreeNode>) DefaultGroovyMethods.iterator(self.children()); } /** * Overloads the left shift operator to provide an easy way to add * nodes to a MutableTreeNode.<p> * * @param self a MutableTreeNode * @param node a node to be added to the treeNode. * @return same treeNode, after the value was added to it. * @since 1.6.4 */ public static MutableTreeNode leftShift(MutableTreeNode self, MutableTreeNode node) { self.insert(node, self.getChildCount()); return self; } /** * Allow MutableTreeNode to work with subscript operators.<p> * <b>WARNING:</b> this operation does not replace the node at the * specified index, rather it inserts the node at that index, thus * increasing the size of the treeNode by 1.<p> * * @param self a MutableTreeNode * @param index an index * @param node the node to insert at the given index * @since 1.6.4 */ public static void putAt(MutableTreeNode self, int index, MutableTreeNode node) { self.insert(node, index); } /** * Overloads the left shift operator to provide an easy way to add * nodes to a DefaultMutableTreeNode.<p> * * @param self a DefaultMutableTreeNode * @param node a node to be added to the treeNode. * @return same treeNode, after the value was added to it. * @since 1.6.4 */ public static DefaultMutableTreeNode leftShift(DefaultMutableTreeNode self, DefaultMutableTreeNode node) { self.add(node); return self; } /** * Removes all children nodes from the DefaultMutableTreeNode. * * @param self a DefaultMutableTreeNode * @since 1.6.4 */ public static void clear(DefaultMutableTreeNode self) { self.removeAllChildren(); } /** * Provide the standard Groovy <code>size()</code> method for <code>JMenu</code>. * * @param self a JMenu * @return the menu component count of the menu * @since 1.6.4 */ public static int size(JMenu self) { return self.getMenuComponentCount(); } /** * Support the subscript operator for JMenu. * * @param self a JMenu * @param index the index of the menu component to get * @return the menu component at the given index * @since 1.6.4 */ public static Component getAt(JMenu self, int index) { return self.getMenuComponent(index); } /** * Overloads the left shift operator to provide an easy way to add * components to a menu.<p> * * @param self a JMenu * @param action an action to be added to the menu. * @return same menu, after the value was added to it. * @since 1.6.4 */ public static JMenu leftShift(JMenu self, Action action) { self.add(action); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a menu.<p> * * @param self a JMenu * @param component a component to be added to the menu. * @return same menu, after the value was added to it. * @since 1.6.4 */ public static JMenu leftShift(JMenu self, Component component) { self.add(component); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a menu.<p> * * @param self a JMenu * @param item an item to be added to the menu. * @return same menu, after the value was added to it. * @since 1.6.4 */ public static JMenu leftShift(JMenu self, JMenuItem item) { self.add(item); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a menu.<p> * * @param self a JMenu * @param str a String to be added to the menu. * @return same menu, after the value was added to it. * @since 1.6.4 */ public static JMenu leftShift(JMenu self, String str) { self.add(str); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a menu.<p> * * @param self a JMenu * @param gstr a GString to be added to the menu. * @return same menu, after the value was added to it. * @since 1.6.4 */ public static JMenu leftShift(JMenu self, GString gstr) { self.add(gstr.toString()); return self; } /** * Returns an {@link java.util.Iterator} which traverses the JMenu one component at a time. * * @param self a JMenu * @return an Iterator for a JMenu * @since 1.6.4 */ public static Iterator/*<MenuElement>*/ iterator(JMenu self) { return DefaultGroovyMethods.iterator(self.getMenuComponents()); } /** * Provide the standard Groovy <code>size()</code> method for <code>JMenuBar</code>. * * @param self a JMenuBar * @return the menu count of the menuBar * @since 1.6.4 */ public static int size(JMenuBar self) { return self.getMenuCount(); } /** * Support the subscript operator for JMenuBar. * * @param self a JMenuBar * @param index the index of the menu to get * @return the menu at the given index * @since 1.6.4 */ public static JMenu getAt(JMenuBar self, int index) { return self.getMenu(index); } /** * Overloads the left shift operator to provide an easy way to add * menus to a menuBar.<p> * * @param self a JMenuBar * @param menu a menu to be added to the menuBar. * @return same menuBar, after the value was added to it. * @since 1.6.4 */ public static JMenuBar leftShift(JMenuBar self, JMenu menu) { self.add(menu); return self; } /** * Returns an {@link java.util.Iterator} which traverses the JMenuBar one menu at a time. * * @param self a JMenuBar * @return an Iterator for a JMenuBar * @since 1.6.4 */ public static Iterator/*<JMenu>*/ iterator(JMenuBar self) { return DefaultGroovyMethods.iterator(self.getSubElements()); } /** * Overloads the left shift operator to provide an easy way to add * components to a popupMenu.<p> * * @param self a JPopupMenu * @param action an action to be added to the popupMenu. * @return same popupMenu, after the value was added to it. * @since 1.6.4 */ public static JPopupMenu leftShift(JPopupMenu self, Action action) { self.add(action); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a popupMenu.<p> * * @param self a JPopupMenu * @param component a component to be added to the popupMenu. * @return same popupMenu, after the value was added to it. * @since 1.6.4 */ public static JPopupMenu leftShift(JPopupMenu self, Component component) { self.add(component); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a popupMenu.<p> * * @param self a JPopupMenu * @param item an item to be added to the popupMenu. * @return same popupMenu, after the value was added to it. * @since 1.6.4 */ public static JPopupMenu leftShift(JPopupMenu self, JMenuItem item) { self.add(item); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a popupMenu.<p> * * @param self a JPopupMenu * @param str a String to be added to the popupMenu. * @return same popupMenu, after the value was added to it. * @since 1.6.4 */ public static JPopupMenu leftShift(JPopupMenu self, String str) { self.add(str); return self; } /** * Overloads the left shift operator to provide an easy way to add * components to a popupMenu.<p> * * @param self a JPopupMenu * @param gstr a GString to be added to the popupMenu. * @return same popupMenu, after the value was added to it. * @since 1.6.4 */ public static JPopupMenu leftShift(JPopupMenu self, GString gstr) { self.add(gstr.toString()); return self; } /** * Returns an {@link java.util.Iterator} which traverses the JPopupMenu one MenuElement at a time. * * @param self a JPopupMenu * @return an Iterator for a JPopupMenu * @since 1.6.4 */ public static Iterator<MenuElement> iterator(JPopupMenu self) { return DefaultGroovyMethods.iterator(self.getSubElements()); } /** * Provide the standard Groovy <code>size()</code> method for <code>JTabbedPane</code>. * * @param self a JTabbedPane * @return the tab count of the tabbedPane * @since 1.6.4 */ public static int size(JTabbedPane self) { return self.getTabCount(); } /** * Removes all elements from the JTabbedPane. * * @param self a JTabbedPane * @since 1.6.4 */ public static void clear(JTabbedPane self) { self.removeAll(); } /** * Support the subscript operator for JTabbedPane. * * @param self a JTabbedPane * @param index the index of the tab component to get * @return the component at the given index * @since 1.6.4 */ public static Component getAt(JTabbedPane self, int index) { return self.getComponentAt(index); } /** * Returns an {@link java.util.Iterator} which traverses the JTabbedPane one Component tab at a time. * * @param self a JTabbedPane * @return an Iterator for a JTabbedPane * @since 1.6.4 */ public static Iterator<Component> iterator(final JTabbedPane self) { return new Iterator<Component>() { private int index = 0; public boolean hasNext() { return index > -1 && index < self.getTabCount(); } public Component next() { return self.getComponentAt(index++); } public void remove() { if (hasNext()) self.removeTabAt(index--); } }; } /** * Overloads the left shift operator to provide an easy way to add * components to a toolBar.<p> * * @param self a JToolBar * @param action an Action to be added to the toolBar. * @return same toolBar, after the value was added to it. * @since 1.6.4 */ public static JToolBar leftShift(JToolBar self, Action action) { self.add(action); return self; } /** * Support the subscript operator for JToolBar. * * @param self a JToolBar * @param index the index of the tab component to get * @return the tab component at the given index * @since 1.6.4 */ public static Component getAt(JToolBar self, int index) { return self.getComponentAtIndex(index); } /** * Allows the usage of a one-element string for a mnemonic * @param button a AbstractButton * @param mnemonic the String * @since 2.3.7 */ public static void setMnemonic(AbstractButton button, String mnemonic) { char c = ShortTypeHandling.castToChar(mnemonic); button.setMnemonic(c); } }