/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed 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 net.java.sip.communicator.plugin.desktoputil;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.jvnet.lafwidget.animation.*;
/**
* The <tt>SIPCommMenu</tt> is very similar to a JComboBox. The main
* component here is a JLabel only with an icon. When user clicks on the icon a
* popup menu is opened, containing a list of icon-text pairs from which the
* user could choose one item. When user selects the desired item, the icon of
* the selected item is set to the main component label.
*
* @author Yana Stamcheva
*/
public class SIPCommMenu
extends JMenu
{
private static final long serialVersionUID = 1L;
private Object selectedObject;
/**
* Creates an instance of <tt>SIPCommMenu</tt>.
*/
public SIPCommMenu()
{
super();
init();
}
/**
* Creates an instance of <tt>SIPCommMenu</tt> by specifying
* the text and the icon.
* @param text the text of the menu
* @param defaultIcon the menu icon
*/
public SIPCommMenu(String text, Icon defaultIcon)
{
super(text);
this.setIcon(defaultIcon);
init();
}
/**
* Creates an instance of <tt>SIPCommMenu</tt> by specifying the
* initialy selected item.
*
* @param text The item that is initialy selected.
*/
public SIPCommMenu(String text)
{
super(text);
init();
}
private void init()
{
MouseRolloverHandler mouseHandler = new MouseRolloverHandler();
this.addMouseListener(mouseHandler);
this.addMouseMotionListener(mouseHandler);
// Hides the popup menu when the parent window loses focus.
getPopupMenu().addComponentListener(new ComponentAdapter()
{
@Override
public void componentResized(ComponentEvent evt)
{
final Window parentWindow;
Component parent = SIPCommMenu.this.getParent();
// If this is a submenu get the invoker first.
if (parent instanceof JPopupMenu)
parentWindow = SwingUtilities.getWindowAncestor(
((JPopupMenu) parent).getInvoker());
else
parentWindow
= SwingUtilities.getWindowAncestor(SIPCommMenu.this);
if (!parentWindow.isActive())
{
getPopupMenu().setVisible(false);
}
parentWindow.addWindowListener(new WindowAdapter()
{
@Override
public void windowDeactivated(WindowEvent e)
{
JPopupMenu popupMenu = getPopupMenu();
if (popupMenu != null && popupMenu.isVisible())
popupMenu.setVisible(false);
}
/**
* Invoked when a window has been closed.
* Remove the listener as we do not need it any more.
*/
@Override
public void windowClosed(WindowEvent e)
{
parentWindow.removeWindowListener(this);
}
});
}
});
}
/**
* Adds an item to the "choice list" of this selector box.
*
* @param text The text of the item.
* @param icon The icon of the item.
* @param actionListener The <tt>ActionListener</tt>, which handles the
* case, when the item is selected.
*/
public void addItem(String text, Icon icon, ActionListener actionListener)
{
JMenuItem item = new JMenuItem(text, icon);
item.addActionListener(actionListener);
this.add(item);
}
/**
* Selects the given item.
*
* @param selectedObject The object to select.
*/
public void setSelected(SelectedObject selectedObject)
{
if (selectedObject.getIcon() != null)
this.setIcon(selectedObject.getIcon());
if (selectedObject.getText() != null)
this.setText(selectedObject.getText());
if (selectedObject.getObject() != null)
this.setSelectedObject(selectedObject.getObject());
}
/**
* Selects the given object.
*
* @param o The <tt>Object</tt> to select.
*/
public void setSelectedObject(Object o)
{
this.selectedObject = o;
}
/**
* Returns the selected object.
*
* @return the selected object.
*/
public Object getSelectedObject()
{
return this.selectedObject;
}
/**
* Sets the isMouseOver property value and repaints this component.
*
* @param isMouseOver <code>true</code> to indicate that the mouse is over
* this component, <code>false</code> - otherwise.
*/
public void setMouseOver(boolean isMouseOver)
{
this.repaint();
}
/**
* Paints this component.
* @param g the <tt>Graphics</tt> object used for painting
*/
@Override
public void paintComponent(Graphics g)
{
Graphics g2 = g.create();
try
{
internalPaintComponent(g2);
}
finally
{
g2.dispose();
}
super.paintComponent(g);
}
/**
* Paints a rollover effect when the mouse is over this menu.
* @param g the <tt>Graphics</tt> object used for painting
*/
private void internalPaintComponent(Graphics g)
{
AntialiasingManager.activateAntialiasing(g);
// Paint a roll over fade out.
FadeTracker fadeTracker = FadeTracker.getInstance();
float visibility = getModel().isRollover() ? 1.0f : 0.0f;
if (fadeTracker.isTracked(this, FadeKind.ROLLOVER))
{
visibility = fadeTracker.getFade(this, FadeKind.ROLLOVER);
}
visibility /= 2;
g.setColor(new Color(1.0f, 1.0f, 1.0f, visibility));
g.fillRoundRect(0, 0, this.getWidth(), this.getHeight(), 20, 20);
g.setColor(UIManager.getColor("Menu.foreground"));
}
/**
* The <tt>ButtonRepaintCallback</tt> is charged to repaint this button
* when the fade animation is performed.
*/
private class ButtonRepaintCallback implements FadeTrackerCallback
{
public void fadeEnded(FadeKind arg0)
{
repaintLater();
}
public void fadePerformed(FadeKind arg0, float arg1)
{
repaintLater();
}
private void repaintLater()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
SIPCommMenu.this.repaint();
}
});
}
public void fadeReversed(FadeKind arg0, boolean arg1, float arg2)
{
}
}
/**
* Perform a fade animation on mouse over.
*/
private class MouseRolloverHandler
implements MouseListener,
MouseMotionListener
{
public void mouseMoved(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
if (isEnabled())
{
getModel().setRollover(false);
FadeTracker fadeTracker = FadeTracker.getInstance();
fadeTracker.trackFadeOut(FadeKind.ROLLOVER,
SIPCommMenu.this,
true,
new ButtonRepaintCallback());
}
}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
if (isEnabled())
{
getModel().setRollover(true);
FadeTracker fadeTracker = FadeTracker.getInstance();
fadeTracker.trackFadeIn(FadeKind.ROLLOVER,
SIPCommMenu.this,
true,
new ButtonRepaintCallback());
}
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e)
{
}
}
}