/* elementWrapper.java This class will be used as a wrapper for each of the elements in an edit-in-place vector. It contains plus and minus buttons that will allow a component to be deleted or a component to be added to the vector being displayed. Created: 16 October 1997 Module By: Michael Mulvaney ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996-2014 The University of Texas at Austin Ganymede is a registered trademark of The University of Texas at Austin Contact information Author Email: ganymede_author@arlut.utexas.edu Email mailing list: ganymede@arlut.utexas.edu US Mail: Computer Science Division Applied Research Laboratories The University of Texas at Austin PO Box 8029, Austin TX 78713-8029 Telephone: (512) 835-3200 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package arlut.csd.ganymede.client; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.rmi.RemoteException; import javax.swing.JComponent; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import arlut.csd.JDataComponent.JIPField; import arlut.csd.JDataComponent.JSetValueObject; import arlut.csd.JDataComponent.JValueObject; import arlut.csd.Util.TranslationService; import arlut.csd.ganymede.common.Invid; /*------------------------------------------------------------------------------ class elementWrapper ------------------------------------------------------------------------------*/ /** * This GUI class is used in the Ganymede client to wrap embedded * objects in an expandable panel for inclusion in a presentation in a * {@link arlut.csd.ganymede.client.vectorPanel vectorPanel}. * * Typically, elementWrapper objects contain {@link * arlut.csd.ganymede.client.containerPanel containerPanels}, which * themselves contain GUI elements from embedded objects. */ class elementWrapper extends JPanel implements ActionListener, MouseListener, FocusListener { /** * TranslationService object for handling string localization in the * Ganymede client. */ static final TranslationService ts = TranslationService.getTranslationService("arlut.csd.ganymede.client.elementWrapper"); boolean debug = false; // class variables private Component my_component = null; JPanel buttonPanel; JLabel title; String titleText; JButton expand, remove; final vectorPanel vp; boolean editable, expanded = false, loaded = false; int index; long lastClick = 0; // Used to determine double clicks /* -- */ // class methods public elementWrapper(String titleText, Component comp, vectorPanel parent, boolean editable) { if (comp == null) { throw new IllegalArgumentException("Error: Component parameter is null"); } this.titleText = titleText; this.vp = parent; this.editable = editable; this.my_component = comp; debug = vp.gc.debug; if (debug) { System.err.println("Adding new elementWrapper"); } setLayout(new BorderLayout()); buttonPanel = new JPanel(); buttonPanel.setOpaque(true); /* // set the border/button panel color based on the // object's validity checkValidation(); */ buttonPanel.setBackground(ClientColor.vectorTitles); setBorder(vp.wp.eWrapperBorder); buttonPanel.setForeground(ClientColor.vectorFore); buttonPanel.setLayout(new BorderLayout()); if (editable) { remove = new JButton(vp.wp.removeImageIcon); remove.setOpaque(false); remove.setMargin(new Insets(0,0,0,0)); remove.setBorder(vp.wp.eWrapperButtonBorder); remove.setBorderPainted(false); // "Delete this element" remove.setToolTipText(ts.l("init.remove_tooltip")); remove.setContentAreaFilled(false); remove.addActionListener(this); remove.addFocusListener(this); } if (comp instanceof containerPanel) { if (titleText != null) { title = new JLabel(titleText); } else { // "Component" title = new JLabel(ts.l("init.default_label")); } title.setForeground(Color.white); title.addMouseListener(this); expand = new JButton(vp.wp.closeIcon); expand.setPressedIcon(vp.wp.closePressedIcon); expand.setMargin(new Insets(0,0,0,0)); expand.setBorder(vp.wp.eWrapperButtonBorder); expand.setBorderPainted(false); // "Expand this element" expand.setToolTipText(ts.l("global.expand_tooltip")); expand.setOpaque(false); expand.addActionListener(this); expand.addFocusListener(this); expand.setContentAreaFilled(false); buttonPanel.add("West", expand); buttonPanel.add("Center", title); if (editable) { buttonPanel.add("East",remove); } } else { if (titleText != null) { buttonPanel.add("West", new JLabel(titleText)); } buttonPanel.add("Center", comp); if (editable) { buttonPanel.add("East", remove); } } add("North",buttonPanel); } public void setIndex(int index) { this.index = index; // "{0,number,#}. {1}" title.setText(ts.l("setIndex.element_pattern", Integer.valueOf(index+1), titleText)); } public Component getComponent() { return my_component; } public Invid getObjectInvid() { if (!(my_component instanceof containerPanel)) { return null; } return ((containerPanel)my_component).getObjectInvid(); } public Object getValue() { if (my_component instanceof containerPanel) { return getObjectInvid(); } if (my_component instanceof JIPField) { return ((JIPField) my_component).getValue(); } throw new RuntimeException("Unrecognized value wrapped in elementWrapper"); } public void clearElement() { this.my_component = null; } /** * Checks to see if the object on the server wrapped by this elementWrapper * is complete and correct, and sets the color of the elementWrapper based * on this. * * THIS IS CURRENTLY NOT BEING USED.. NOT SURE IF THIS IS A DESIRABLE UI * FEATURE IN ANY CASE. */ public void checkValidation() { if (my_component instanceof containerPanel) { try { setValidated(((containerPanel)my_component).getObject().isValid()); } catch (Exception ex) { gclient.client.processExceptionRethrow(ex); } } } private void setValidated(boolean valid) { if (valid) { buttonPanel.setBackground(ClientColor.vectorTitles); setBorder(vp.wp.eWrapperBorder); } else { buttonPanel.setBackground(ClientColor.vectorTitlesInvalid); setBorder(vp.wp.eWrapperBorderInvalid); } } public void refreshTitle() { if (my_component instanceof containerPanel) { try { containerPanel cp = (containerPanel) my_component; titleText = cp.getObject().getEmbeddedObjectDisplayLabel(); title.setText((index + 1) + ". " + titleText); } catch (Exception rx) { gclient.client.processExceptionRethrow(rx); } } } /** * Expand this element wrapper. */ public void open() { if (my_component instanceof containerPanel) { containerPanel myContainerPanel = (containerPanel) my_component; if (!loaded) { if (!myContainerPanel.isLoaded()) { myContainerPanel.load(); } add("Center", my_component); loaded = true; } } my_component.setVisible(true); expand.setIcon(vp.wp.openIcon); expand.setPressedIcon(vp.wp.openPressedIcon); // "Close this element" expand.setToolTipText(ts.l("global.shrink_tooltip")); expanded = true; } /** * Close this element wrapper. */ public void close() { my_component.setVisible(false); expand.setIcon(vp.wp.closeIcon); expand.setPressedIcon(vp.wp.closePressedIcon); // "Expand this element" expand.setToolTipText(ts.l("global.expand_tooltip")); expanded = false; } /** * Toggle the elementWrapper open/closed. * * If the elementWrapper is open, this will close it. If it is closed, this will open it. */ public void toggle() { vp.wp.getgclient().setWaitCursor(); if (debug) { System.err.println("toggle()."); } if (expanded) { if (debug) { System.err.println("remove"); } close(); } else { open(); } if (debug) { System.err.println("Done with toggle()."); } vp.wp.getgclient().setNormalCursor(); } // ActionListener methods ------------------------------------------------------ public void actionPerformed(ActionEvent evt) { if (debug) { System.err.println("Action performed: " + evt.getActionCommand()); } if (evt.getSource() == remove) { JValueObject v = new JSetValueObject(this,"remove"); vp.setValuePerformed(v); } else if (evt.getSource() == expand) { toggle(); invalidate(); vp.container.frame.validate(); } else { throw new RuntimeException("actionPerformed invoked by ActionEvent from invalid source"); } } // MouseListener methods ------------------------------------------------------ public void mouseClicked(MouseEvent e) { if (e.getWhen() - lastClick < 500) { toggle(); invalidate(); vp.container.frame.validate(); } lastClick = e.getWhen(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } // FocusListener methods ------------------------------------------------------ public void focusLost(FocusEvent e) { JButton trigger = null; try { trigger = (JButton) e.getSource(); } catch (ClassCastException ex) { return; } trigger.setBorderPainted(false); trigger.invalidate(); repaint(); } public void focusGained(FocusEvent e) { JButton trigger = null; try { trigger = (JButton) e.getSource(); } catch (ClassCastException ex) { return; } if (expanded) { vp.scrollRectToVisible(trigger.getBounds()); } else { vp.scrollRectToVisible(this.getBounds()); } trigger.setBorderPainted(true); trigger.invalidate(); repaint(); } }