diff --git a/src/net/java/sip/communicator/impl/gui/customcontrols/SmartComboBox.java b/src/net/java/sip/communicator/impl/gui/customcontrols/SIPCommSmartComboBox.java similarity index 88% rename from src/net/java/sip/communicator/impl/gui/customcontrols/SmartComboBox.java rename to src/net/java/sip/communicator/impl/gui/customcontrols/SIPCommSmartComboBox.java index 7bd6ff37d..25be007e9 100644 --- a/src/net/java/sip/communicator/impl/gui/customcontrols/SmartComboBox.java +++ b/src/net/java/sip/communicator/impl/gui/customcontrols/SIPCommSmartComboBox.java @@ -14,20 +14,22 @@ import javax.swing.*; import javax.swing.event.*; +import net.java.sip.communicator.impl.gui.lookandfeel.*; + /** - * SmartComboBox is an editable combo box which selects an item + * SIPCommSmartComboBox is an editable combo box which selects an item * according to user input. * * @author Yana Stamcheva */ -public class SmartComboBox extends JComboBox +public class SIPCommSmartComboBox extends JComboBox { private ArrayList historyList = new ArrayList(); /** - * Creates an instance of SmartComboBox. + * Creates an instance of SIPCommSmartComboBox. */ - public SmartComboBox() + public SIPCommSmartComboBox() { setModel(new FilterableComboBoxModel(historyList)); setEditor(new CallComboEditor()); @@ -50,75 +52,75 @@ public class FilterableComboBoxModel private Object selectedItem; public FilterableComboBoxModel(List items) - { + { this.items = new ArrayList(items); filteredItems = new ArrayList(items.size()); - updateFilteredItems(); + updateFilteredItems(); } - + public boolean contains(Object obj) { return items.contains(obj); } - + public void addElement( Object obj ) { items.add(obj); updateFilteredItems(); } - + public void removeElement( Object obj ) { items.remove(obj); updateFilteredItems(); } - + public void removeElementAt(int index) { items.remove(index); updateFilteredItems(); } - + public void insertElementAt( Object obj, int index ) { items.add(index, obj); updateFilteredItems(); } - + public void setFilter(Filter filter) { this.filter = filter; updateFilteredItems(); } - + protected void updateFilteredItems() - { + { fireIntervalRemoved(this, 0, filteredItems.size()); filteredItems.clear(); - + if (filter == null) filteredItems.addAll(items); else { for (Iterator iterator = items.iterator(); iterator.hasNext();) { Object item = iterator.next(); - + if (filter.accept(item)) filteredItems.add(item); } } fireIntervalAdded(this, 0, filteredItems.size()); } - + public int getSize() { return filteredItems.size(); } - + public Object getElementAt(int index) { return filteredItems.get(index); } - + public Object getSelectedItem() { return selectedItem; @@ -166,34 +168,42 @@ public boolean accept(Object o) } public class CallComboEditor - implements ComboBoxEditor, DocumentListener - { + implements ComboBoxEditor, + DocumentListener + { private JTextField text; private volatile boolean filtering = false; private volatile boolean setting = false; public CallComboEditor() - { + { text = new JTextField(15); text.getDocument().addDocumentListener(this); + + // Enable delete button from the UI. + if (text.getUI() instanceof SIPCommTextFieldUI) + { + ((SIPCommTextFieldUI) text.getUI()) + .setDeleteButtonEnabled(true); + } } - + public Component getEditorComponent() { return text; } - + public void setItem(Object item) { if(filtering) return; - + setting = true; String newText = (item == null) ? "" : item.toString(); - + text.setText(newText); setting = false; } public Object getItem() - { + { return text.getText(); } @@ -222,7 +232,7 @@ protected void handleChange() Filter filter = null; if (text.getText().length() > 0) { - filter = new StartsWithFilter(text.getText()); + filter = new StartsWithFilter(text.getText()); } ((FilterableComboBoxModel) getModel()).setFilter(filter); diff --git a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommCallComboBoxUI.java b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommCallComboBoxUI.java index b2657587c..211a52418 100644 --- a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommCallComboBoxUI.java +++ b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommCallComboBoxUI.java @@ -14,19 +14,22 @@ public class SIPCommCallComboBoxUI extends SIPCommComboBoxUI { - public static ComponentUI createUI(JComponent c) { + public static ComponentUI createUI(JComponent c) + { return new SIPCommCallComboBoxUI(); } - + /** * Creates the popup portion of the combo box. * * @return an instance of ComboPopup * @see ComboPopup */ - protected ComboPopup createPopup() { + protected ComboPopup createPopup() + { SIPCommComboPopup popup = new SIPCommComboPopup( comboBox ); popup.getAccessibleContext().setAccessibleParent(comboBox); + return popup; } @@ -36,7 +39,7 @@ public SIPCommComboPopup(JComboBox combo) { super(combo); } - + /** * Makes the popup visible if it is hidden and makes it hidden if it is * visible. diff --git a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommComboBoxUI.java b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommComboBoxUI.java index 8bb85eb5d..f3df29fdd 100644 --- a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommComboBoxUI.java +++ b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommComboBoxUI.java @@ -1,8 +1,7 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.gui.lookandfeel; @@ -19,18 +18,22 @@ * * @author Yana Stamcheva */ -public class SIPCommComboBoxUI extends MetalComboBoxUI { - - public static ComponentUI createUI(JComponent c) { +public class SIPCommComboBoxUI + extends MetalComboBoxUI +{ + public static ComponentUI createUI(JComponent c) + { return new SIPCommComboBoxUI(); } - - public void paint(Graphics g, JComponent c) { + + public void paint(Graphics g, JComponent c) + { AntialiasingManager.activateAntialiasing(g); - super.paint(g, c); + super.paint(g, c); } - - protected ComboBoxEditor createEditor() { + + protected ComboBoxEditor createEditor() + { return new SIPCommComboBoxEditor.UIResource(); } } diff --git a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommTextFieldUI.java b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommTextFieldUI.java index 305a58173..c1070c7c0 100644 --- a/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommTextFieldUI.java +++ b/src/net/java/sip/communicator/impl/gui/lookandfeel/SIPCommTextFieldUI.java @@ -1,17 +1,19 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.gui.lookandfeel; 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.impl.gui.customcontrols.*; import net.java.sip.communicator.impl.gui.utils.*; /** @@ -19,20 +21,254 @@ * * @author Yana Stamcheva */ -public class SIPCommTextFieldUI extends MetalTextFieldUI { +public class SIPCommTextFieldUI + extends MetalTextFieldUI +{ + private boolean mouseOver = false; + + private boolean mousePressed = false; + + private int buttonState; + + private static int BUTTON_GAP = 5; + + private Image deleteButtonImg; + + private Image deleteButtonRolloverImg; + + private boolean isDeleteButtonEnabled = false; + + private SIPCommButton deleteButton; + + /** + * Creates a SIPCommTextFieldUI. + */ + public SIPCommTextFieldUI() + { + deleteButtonImg + = ImageLoader.getImage(ImageLoader.CLOSE_TAB_ICON); + + deleteButtonRolloverImg + = ImageLoader.getImage(ImageLoader.CLOSE_ICON); + + deleteButton = new SIPCommButton( deleteButtonImg, + deleteButtonRolloverImg); + + deleteButton.setSize ( deleteButtonImg.getWidth(null), + deleteButtonImg.getHeight(null)); + } - public static ComponentUI createUI(JComponent c) { + /** + * 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( + new TextFieldMouseListener()); + + getComponent().addMouseMotionListener( + new TextFieldMouseMotionListener()); + } + + /** + * Creates the UI. + * + * @param c the component associated with this UI implementation. + * @return an instance of this UI implementation + */ + public static ComponentUI createUI(JComponent c) + { return new SIPCommTextFieldUI(); } - - protected void paintSafely(Graphics g) { + + /** + * Implements parent paintSafely method and enables antialiasing. + */ + protected void paintSafely(Graphics g) + { AntialiasingManager.activateAntialiasing(g); super.paintSafely(g); } - - protected void paintBackground(Graphics g) { + + /** + * Paints the background of the associated component. + */ + protected void paintBackground(Graphics g) + { + AntialiasingManager.activateAntialiasing(g); JTextComponent c = this.getComponent(); g.setColor(c.getBackground()); - g.fillRoundRect(1, 1, c.getWidth()-2, c.getHeight()-2, 5, 5); + g.fillRoundRect(1, 1, c.getWidth() - 2, c.getHeight() - 2, 5, 5); + + int dx = c.getX() + c.getWidth() - deleteButton.getWidth() - BUTTON_GAP; + int dy = (c.getY() + c.getHeight()) / 2 - deleteButton.getHeight()/2; + + if (c.getText() != null + && c.getText().length() > 0 + && isDeleteButtonEnabled) + { + if (mouseOver) + g.drawImage(deleteButtonRolloverImg, dx, dy + 1, null); + else + g.drawImage(deleteButtonImg, dx, dy + 1, null); + } + } + + /** + * 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 x the x coordinate of the mouse event + * @param y the y coordinate of the mouse event + */ + protected void updateDeleteIcon(int x, int y) + { + if (!isDeleteButtonEnabled) + return; + + Rectangle deleteRect = getDeleteButtonRect(); + + if (deleteRect.contains(x, y)) + { + mouseOver = true; + getComponent().setCursor(Cursor.getDefaultCursor()); + + if (mousePressed) + getComponent().setText(""); + } + else + { + mouseOver = false; + getComponent().setCursor( + Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); + } + + getComponent().repaint(); + } + + /** + * Calculates the delete button rectangle. + * + * @return the delete button rectangle + */ + protected Rectangle getDeleteButtonRect() + { + Rectangle rect = getVisibleEditorRect(); + + int dx = rect.x + rect.width; + int dy = (rect.y + 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. + */ + protected Rectangle getVisibleEditorRect() + { + if (!isDeleteButtonEnabled) + { + return super.getVisibleEditorRect(); + } + + JTextComponent c = getComponent(); + + 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 + + deleteButton.getWidth(); + alloc.height -= insets.top + insets.bottom; + return alloc; + } + + return null; + } + + /** + * The MouseListener that listens for mouse events in order to + * update the delete icon. + */ + protected class TextFieldMouseListener implements MouseListener + { + public void mouseClicked(MouseEvent e) + {} + + public void mouseEntered(MouseEvent e) + { + updateDeleteIcon(e.getX(), e.getY()); + } + + public void mouseExited(MouseEvent e) + { + updateDeleteIcon(e.getX(), e.getY()); + } + + public void mousePressed(MouseEvent e) + { + mousePressed = true; + + updateDeleteIcon(e.getX(), e.getY()); + } + + public void mouseReleased(MouseEvent e) + { + mousePressed = false; + + updateDeleteIcon(e.getX(), e.getY()); + } + } + + /** + * The MouseMotionListener that listens for mouse events in order + * to update the delete icon. + */ + protected class TextFieldMouseMotionListener implements MouseMotionListener + { + public void mouseDragged(MouseEvent e) + { + updateDeleteIcon(e.getX(), e.getY()); + } + + public void mouseMoved(MouseEvent e) + { + updateDeleteIcon(e.getX(), e.getY()); + } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallComboBox.java b/src/net/java/sip/communicator/impl/gui/main/call/CallComboBox.java index 7642a753c..5669dd09d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallComboBox.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallComboBox.java @@ -1,8 +1,7 @@ /* * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. - * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * + * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.gui.main.call; @@ -15,42 +14,41 @@ import net.java.sip.communicator.impl.gui.lookandfeel.*; import net.java.sip.communicator.impl.gui.main.contactlist.*; import net.java.sip.communicator.service.contactlist.*; - + /** - * The CallComboBox is a history editable combo box that is positioned - * above call and hangup buttons and is used when writing a number or a contact - * name in order to be called. + * The CallComboBox is a history editable combo box that is + * positioned above call and hangup buttons and is used when writing a number or + * a contact name in order to be called. * * @author Yana Stamcheva */ public class CallComboBox - extends SmartComboBox - implements ActionListener, - DocumentListener -{ - + extends SIPCommSmartComboBox + implements ActionListener, DocumentListener +{ private CallManager callManager; - + public final static int MAX_COMBO_SIZE = 10; - - public CallComboBox(CallManager callManager) { - + + public CallComboBox(CallManager callManager) + { this.callManager = callManager; - + this.setUI(new SIPCommCallComboBoxUI()); this.addActionListener(this); - - JTextField textField = (JTextField)this.getEditor().getEditorComponent(); - + + JTextField textField = + (JTextField) this.getEditor().getEditorComponent(); + textField.getDocument().addDocumentListener(this); - + textField.getActionMap().put("createCall", new CreateCallAction()); textField.getInputMap().put( - KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "createCall"); + KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "createCall"); } - + /** - * Checks if this combo box editor field is empty. This will be the case if + * Checks if this combobox editor field is empty. This will be the case if * the user hasn't selected an item from the combobox and hasn't written * anything the field. * @@ -58,69 +56,86 @@ public CallComboBox(CallManager callManager) { */ public boolean isComboFieldEmpty() { - String item = ((CallComboEditor)this.getEditor()).getItem().toString(); - - if(item.length() > 0) + String item = ((CallComboEditor) this.getEditor()).getItem().toString(); + + if (item.length() > 0) return false; else return true; } - + /** - * Handles events triggered by user selection. Enables the call button - * when user selects something in the combo box. + * Handles events triggered by user selection. Enables the call button when + * user selects something in the combo box. */ public void actionPerformed(ActionEvent e) - { + { callManager.setCallMetaContact(false); callManager.getCallButton().setEnabled(true); } - public void insertUpdate(DocumentEvent e) { handleChange(); } - public void removeUpdate(DocumentEvent e) { handleChange(); } - public void changedUpdate(DocumentEvent e) {} - + public void insertUpdate(DocumentEvent e) + { + handleChange(); + } + + public void removeUpdate(DocumentEvent e) + { + handleChange(); + } + + public void changedUpdate(DocumentEvent e) + { + } + /** - * Enables or disabled the call button according to the content in the - * combo box editor field. + * Enables or disabled the call button according to the content in the combo + * box editor field. */ - protected void handleChange() { - String item = ((CallComboEditor)this.getEditor()).getItem().toString(); - - if (item.length() > 0) { + protected void handleChange() + { + String item = ((CallComboEditor) this.getEditor()).getItem().toString(); + + if (item.length() > 0) + { callManager.setCallMetaContact(false); - ContactList clist = this.callManager.getMainFrame() - .getContactListPanel().getContactList(); - - clist.removeSelectionInterval( - clist.getSelectedIndex(), clist.getSelectedIndex()); - + ContactList clist = + this.callManager.getMainFrame().getContactListPanel() + .getContactList(); + + clist.removeSelectionInterval(clist.getSelectedIndex(), clist + .getSelectedIndex()); + callManager.getCallButton().setEnabled(true); } - else { - Object o = callManager.getMainFrame().getContactListPanel() - .getContactList().getSelectedValue(); - - if(o == null || !(o instanceof MetaContact)) + else + { + Object o = + callManager.getMainFrame().getContactListPanel() + .getContactList().getSelectedValue(); + + if (o == null || !(o instanceof MetaContact)) callManager.getCallButton().setEnabled(false); } } - + /** - * Creates a call to the contact given by the string in the combo box - * editor field. + * Creates a call to the contact given by the string in the combo box editor + * field. */ - private class CreateCallAction extends AbstractAction + private class CreateCallAction + extends AbstractAction { public void actionPerformed(ActionEvent e) { - String item = ((CallComboEditor)getEditor()).getItem().toString(); - - if(item.length() > 0) + String item = ((CallComboEditor) getEditor()).getItem().toString(); + + if (item.length() > 0) callManager.createCall(item); - else { - if(!isPopupVisible()) + else + { + if (!isPopupVisible()) setPopupVisible(true); } } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallListPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallListPanel.java index bc2251574..c6f369923 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallListPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallListPanel.java @@ -14,7 +14,7 @@ import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.customcontrols.*; -import net.java.sip.communicator.impl.gui.customcontrols.SmartComboBox.*; +import net.java.sip.communicator.impl.gui.customcontrols.SIPCommSmartComboBox.*; import net.java.sip.communicator.impl.gui.i18n.*; import net.java.sip.communicator.impl.gui.main.*; import net.java.sip.communicator.impl.gui.utils.*; @@ -37,7 +37,7 @@ public class CallListPanel private JLabel searchLabel = new JLabel( Messages.getI18NString("search").getText() + ": "); - private SmartComboBox searchComboBox = new SmartComboBox(); + private SIPCommSmartComboBox searchComboBox = new SIPCommSmartComboBox(); private CallList callList = new CallList();