/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license. See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.desktoputil.plaf;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.metal.*;
import javax.swing.text.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.util.skin.*;
/**
* SIPCommTextFieldUI implementation.
*
* @author Yana Stamcheva
* @author Adam Netocny
*/
public class SIPCommTextFieldUI
extends MetalTextFieldUI
implements Skinnable,
MouseMotionListener,
MouseListener
{
/**
* Indicates if the mouse is currently over the delete button.
*/
protected boolean isDeleteMouseOver = false;
/**
* Indicates if the mouse is currently pressed on the delete button.
*/
protected boolean isDeleteMousePressed = false;
/**
* The gap between the delete button and the text in the field.
*/
protected static int BUTTON_GAP = 5;
/**
* The image of the delete text button.
*/
private Image deleteButtonImg;
/**
* The rollover image of the delete text button.
*/
private Image deleteButtonRolloverImg;
/**
* The image for the pressed state of the delete text button.
*/
private Image deleteButtonPressedImg;
/**
* Indicates if the text field contains a
* delete button allowing to delete all the content at once.
*/
private boolean isDeleteButtonEnabled = false;
/**
* The delete text button shown on the right of the field.
*/
protected SIPCommButton deleteButton;
/**
* Indicates if the delete icon is visible.
*/
private boolean isDeleteIconVisible = false;
/**
* The start background gradient color.
*/
private Color bgStartColor
= new Color(DesktopUtilActivator.getResources().getColor(
"service.gui.SEARCH_BACKGROUND"));
/**
* The end background gradient color.
*/
private Color bgEndColor
= new Color(DesktopUtilActivator.getResources().getColor(
"service.gui.SEARCH_GRADIENT"));
/**
* The start background gradient color.
*/
private Color bgBorderStartColor
= new Color(DesktopUtilActivator.getResources().getColor(
"service.gui.SEARCH_BORDER"));
/**
* The end background gradient color.
*/
private Color bgBorderEndColor
= new Color(DesktopUtilActivator.getResources().getColor(
"service.gui.SEARCH_BORDER_GRADIENT"));
/**
* Creates a SIPCommTextFieldUI.
*/
public SIPCommTextFieldUI()
{
loadSkin();
}
/**
* Returns true
if the delete buttons is enabled and false -
* otherwise.
* @return true
if the delete buttons is enabled and false -
* otherwise
*/
public boolean isDeleteButtonEnabled()
{
return isDeleteButtonEnabled;
}
/**
* Updates the isDeleteButtonEnabled field.
*
* @param isDeleteButtonEnabled indicates if the delete buttons is enabled
* or not
*/
public void setDeleteButtonEnabled(boolean isDeleteButtonEnabled)
{
this.isDeleteButtonEnabled = isDeleteButtonEnabled;
}
/**
* Adds the custom mouse listeners defined in this class to the installed
* listeners.
*/
protected void installListeners()
{
super.installListeners();
getComponent().addMouseListener(this);
getComponent().addMouseMotionListener(this);
}
/**
* Uninstalls listeners for the UI.
*/
protected void uninstallListeners()
{
super.uninstallListeners();
getComponent().removeMouseListener(this);
getComponent().removeMouseMotionListener(this);
}
/**
* Paints the background of the associated component.
* @param g the Graphics object used for painting
*/
protected void customPaintBackground(Graphics g)
{
Graphics2D g2 = (Graphics2D) g.create();
try
{
String roundedSet = DesktopUtilActivator.getResources().
getSettingsString(
"impl.gui.IS_SIP_COMM_TEXT_FIELD_ROUNDED");
boolean isRounded = true;
if(roundedSet != null)
{
isRounded = new Boolean(roundedSet)
.booleanValue();
}
AntialiasingManager.activateAntialiasing(g2);
JTextComponent c = this.getComponent();
GradientPaint bgGradientColor =
new GradientPaint( c.getWidth() / 2, 0,
bgStartColor,
c.getWidth() / 2, c.getHeight(),
bgEndColor);
g2.setPaint(bgGradientColor);
if(isRounded)
{
g2.fillRoundRect(1, 1, c.getWidth() - 1, c.getHeight() - 1,
8, 8);
}
else
{
g2.fillRect(1, 1, c.getWidth() - 1, c.getHeight() - 1);
}
Rectangle deleteButtonRect = getDeleteButtonRect();
if(deleteButtonRect != null)
{
int dx = deleteButtonRect.x;
int dy = deleteButtonRect.y;
if (c.getText() != null
&& c.getText().length() > 0
&& isDeleteButtonEnabled)
{
if (isDeleteMousePressed)
g2.drawImage(deleteButtonPressedImg, dx, dy, null);
if (isDeleteMouseOver)
g2.drawImage(deleteButtonRolloverImg, dx, dy, null);
else
g2.drawImage(deleteButtonImg, dx, dy, null);
isDeleteIconVisible = true;
}
else
isDeleteIconVisible = false;
}
else
isDeleteIconVisible = false;
g2.setStroke(new BasicStroke(1f));
GradientPaint bgBorderGradientColor
= new GradientPaint( c.getWidth() / 2, 0,
bgBorderStartColor,
c.getWidth() / 2, c.getHeight(),
bgBorderEndColor);
g2.setPaint(bgBorderGradientColor);
if(isRounded)
{
g2.drawRoundRect(
0, 0, c.getWidth() - 1, c.getHeight() - 1, 8, 8);
}
else
{
g2.drawRect(0, 0, c.getWidth() - 1, c.getHeight() - 1);
}
}
finally
{
g2.dispose();
}
}
/**
* Updates the delete icon, changes the cursor and deletes the content of
* the associated text component when the mouse is pressed over the delete
* icon.
*
* @param evt the mouse event that has prompted us to update the delete
* icon.
*/
protected void updateDeleteIcon(MouseEvent evt)
{
// If the component is null we have nothing more to do here. Fixes a
// NullPointerException in getDeleteButtonRectangle().
if (getComponent() == null)
return;
int x = evt.getX();
int y = evt.getY();
if (!isDeleteButtonEnabled)
return;
Rectangle deleteRect = getDeleteButtonRect();
if (isDeleteIconVisible && deleteRect.contains(x, y))
{
if (evt.getID() == MouseEvent.MOUSE_PRESSED)
{
isDeleteMouseOver = false;
isDeleteMousePressed = true;
}
else
{
isDeleteMouseOver = true;
isDeleteMousePressed = false;
}
getComponent().setCursor(Cursor.getDefaultCursor());
if (evt.getID() == MouseEvent.MOUSE_CLICKED)
getComponent().setText("");
}
else
{
isDeleteMouseOver = false;
isDeleteMousePressed = false;
}
getComponent().repaint();
}
/**
* Calculates the delete button rectangle.
*
* @return the delete button rectangle
*/
protected Rectangle getDeleteButtonRect()
{
JTextComponent c = getComponent();
if(c == null)
return null;
Rectangle rect = c.getBounds();
int dx = rect.width - deleteButton.getWidth() - BUTTON_GAP;
int dy = rect.height / 2 - deleteButton.getHeight()/2;
return new Rectangle( dx,
dy,
deleteButton.getWidth(),
deleteButton.getHeight());
}
/**
* If we are in the case of disabled delete button, we simply call the
* parent implementation of this method, otherwise we recalculate the editor
* rectangle in order to leave place for the delete button.
* @return the visible editor rectangle
*/
protected Rectangle getVisibleEditorRect()
{
if (!isDeleteIconVisible)
{
return super.getVisibleEditorRect();
}
JTextComponent c = getComponent();
if(c == null)
return null;
Rectangle alloc = c.getBounds();
if ((alloc.width > 0) && (alloc.height > 0))
{
alloc.x = alloc.y = 0;
Insets insets = c.getInsets();
alloc.x += insets.left;
alloc.y += insets.top;
alloc.width -= insets.left + insets.right
+ getDeleteButtonRect().getWidth();
alloc.height -= insets.top + insets.bottom;
return alloc;
}
return null;
}
/**
* @param bgStartColor the bgStartColor to set
*/
public void setBgStartColor(Color bgStartColor)
{
this.bgStartColor = bgStartColor;
}
/**
* @param bgEndColor the bgEndColor to set
*/
public void setBgEndColor(Color bgEndColor)
{
this.bgEndColor = bgEndColor;
}
/**
* @param bgBorderStartColor the bgBorderStartColor to set
*/
public void setBgBorderStartColor(Color bgBorderStartColor)
{
this.bgBorderStartColor = bgBorderStartColor;
}
/**
* @param bgBorderEndColor the bgBorderEndColor to set
*/
public void setBgBorderEndColor(Color bgBorderEndColor)
{
this.bgBorderEndColor = bgBorderEndColor;
}
/**
* Reloads skin information.
*/
public void loadSkin()
{
deleteButtonImg = DesktopUtilActivator.getResources()
.getImage("service.gui.lookandfeel.DELETE_TEXT_ICON").getImage();
deleteButtonRolloverImg = DesktopUtilActivator.getResources()
.getImage("service.gui.lookandfeel.DELETE_TEXT_ROLLOVER_ICON")
.getImage();
deleteButtonPressedImg = DesktopUtilActivator.getResources()
.getImage("service.gui.lookandfeel.DELETE_TEXT_PRESSED_ICON")
.getImage();
if(deleteButton != null)
{
deleteButton.setBackgroundImage(deleteButtonImg);
deleteButton.setRolloverImage(deleteButtonRolloverImg);
deleteButton.setPressedImage(deleteButtonPressedImg);
}
else
{
deleteButton = new SIPCommButton(
deleteButtonImg,
deleteButtonRolloverImg,
deleteButtonPressedImg,
null, null, null);
}
deleteButton.setSize ( deleteButtonImg.getWidth(null),
deleteButtonImg.getHeight(null));
}
/**
* Updates the delete icon when the mouse was clicked.
* @param e the MouseEvent that notified us of the click
*/
public void mouseClicked(MouseEvent e)
{
updateDeleteIcon(e);
updateCursor(e);
}
/**
* Updates the delete icon when the mouse is enters the component area.
* @param e the MouseEvent that notified us
*/
public void mouseEntered(MouseEvent e)
{
updateDeleteIcon(e);
updateCursor(e);
}
/**
* Updates the delete icon when the mouse exits the component area.
* @param e the MouseEvent that notified us
*/
public void mouseExited(MouseEvent e)
{
updateDeleteIcon(e);
updateCursor(e);
}
public void mousePressed(MouseEvent e)
{
updateDeleteIcon(e);
}
public void mouseReleased(MouseEvent e)
{
updateDeleteIcon(e);
}
/**
* Updates the delete icon when the mouse is dragged over.
* @param e the MouseEvent that notified us
*/
public void mouseDragged(MouseEvent e)
{
updateDeleteIcon(e);
updateCursor(e);
}
/**
* Updates the delete icon when the mouse is moved over.
* @param e the MouseEvent that notified us
*/
public void mouseMoved(MouseEvent e)
{
updateDeleteIcon(e);
updateCursor(e);
}
/**
* Updates the cursor type depending on a given MouseEvent.
*
* @param mouseEvent the MouseEvent on which the cursor depends
*/
private void updateCursor(MouseEvent mouseEvent)
{
Rectangle rect = getVisibleEditorRect();
if (rect != null && rect.contains(mouseEvent.getPoint()))
{
getComponent().setCursor(
Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
}
}
/**
* Creates a UI for a SIPCommTextFieldUI.
*
* @param c the text field
* @return the UI
*/
public static ComponentUI createUI(JComponent c)
{
return new SIPCommTextFieldUI();
}
}