private int addButton(SIPCommButton button, int gridX, int xBounds, boolean isLast) {
    lastAddedButton = button;

    constraints.insets = new Insets(0, 0, V_GAP, 0);
    constraints.anchor = GridBagConstraints.WEST;
    constraints.fill = GridBagConstraints.NONE;
    constraints.gridx = gridX;
    constraints.gridy = 2;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 0f;
    constraints.weighty = 0f;
    this.add(button, constraints);

    int yBounds =
        TOP_BORDER
            + BOTTOM_BORDER
            + 2 * V_GAP
            + ComponentUtils.getStringSize(nameLabel, nameLabel.getText()).height
            + ComponentUtils.getStringSize(displayDetailsLabel, displayDetailsLabel.getText())
                .height;

    button.setBounds(xBounds, yBounds, BUTTON_WIDTH, BUTTON_HEIGHT);

    button.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));

    setButtonBg(button, gridX, isLast);

    return button.getWidth();
  }
  /**
   * Resets the rollover state of all rollover components in the current cell except the component
   * given as a parameter.
   *
   * @param excludeComponent the component to exclude from the reset
   */
  public void resetRolloverState(Component excludeComponent) {
    if (!chatButton.equals(excludeComponent)) chatButton.getModel().setRollover(false);

    if (!callButton.equals(excludeComponent)) callButton.getModel().setRollover(false);

    if (!callVideoButton.equals(excludeComponent)) callVideoButton.getModel().setRollover(false);

    if (!desktopSharingButton.equals(excludeComponent))
      desktopSharingButton.getModel().setRollover(false);

    if (!addContactButton.equals(excludeComponent)) addContactButton.getModel().setRollover(false);

    if (customActionButtons != null) {
      Iterator<JButton> buttonsIter = customActionButtons.iterator();
      while (buttonsIter.hasNext()) {
        JButton button = buttonsIter.next();

        if (!button.equals(excludeComponent)) button.getModel().setRollover(false);
      }
    }

    if (customActionButtonsUIGroup != null) {
      Iterator<JButton> buttonsIter = customActionButtonsUIGroup.iterator();
      while (buttonsIter.hasNext()) {
        JButton button = buttonsIter.next();

        if (!button.equals(excludeComponent)) button.getModel().setRollover(false);
      }
    }
  }
 /**
  * Sets the background of the button depending on its position in the button bar.
  *
  * @param button the button which background to set
  * @param gridX the position of the button in the grid
  * @param isLast indicates if this is the last button in the button bar
  */
 private void setButtonBg(SIPCommButton button, int gridX, boolean isLast) {
   if (!isLast) {
     if (gridX == 1)
       button.setBackgroundImage(ImageLoader.getImage(ImageLoader.CONTACT_LIST_BUTTON_BG_LEFT));
     else if (gridX > 1)
       button.setBackgroundImage(ImageLoader.getImage(ImageLoader.CONTACT_LIST_BUTTON_BG_MIDDLE));
   } else {
     if (gridX == 1) // We have only one button shown.
     button.setBackgroundImage(ImageLoader.getImage(ImageLoader.CONTACT_LIST_ONE_BUTTON_BG));
     else // We set the background of the last button in the toolbar
     button.setBackgroundImage(ImageLoader.getImage(ImageLoader.CONTACT_LIST_BUTTON_BG_RIGHT));
   }
 }
  /**
   * Shows the appropriate user interface that would allow the user to add the given
   * <tt>SourceUIContact</tt> to their contact list.
   *
   * @param contact the contact to add
   */
  private void addContact(SourceUIContact contact) {
    SourceContact sourceContact = (SourceContact) contact.getDescriptor();

    List<ContactDetail> details =
        sourceContact.getContactDetails(OperationSetPersistentPresence.class);
    int detailsCount = details.size();

    if (detailsCount > 1) {
      JMenuItem addContactMenu =
          TreeContactList.createAddContactMenu((SourceContact) contact.getDescriptor());

      JPopupMenu popupMenu = ((JMenu) addContactMenu).getPopupMenu();

      // Add a title label.
      JLabel infoLabel = new JLabel();
      infoLabel.setText(
          "<html><b>"
              + GuiActivator.getResources().getI18NString("service.gui.ADD_CONTACT")
              + "</b></html>");

      popupMenu.insert(infoLabel, 0);
      popupMenu.insert(new Separator(), 1);

      popupMenu.setFocusable(true);
      popupMenu.setInvoker(treeContactList);

      Point location =
          new Point(
              addContactButton.getX(), addContactButton.getY() + addContactButton.getHeight());

      SwingUtilities.convertPointToScreen(location, treeContactList);

      location.y = location.y + treeContactList.getPathBounds(treeContactList.getSelectionPath()).y;

      popupMenu.setLocation(location.x + 8, location.y - 8);
      popupMenu.setVisible(true);
    } else if (details.size() == 1) {
      TreeContactList.showAddContactDialog(details.get(0), sourceContact.getDisplayName());
    }
  }
  /** Inializes button tool tips. */
  private void initButtonToolTips() {
    callButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT"));
    callVideoButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.VIDEO_CALL"));
    desktopSharingButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.SHARE_DESKTOP"));
    chatButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.SEND_MESSAGE"));
    addContactButton.setToolTipText(
        GuiActivator.getResources().getI18NString("service.gui.ADD_CONTACT"));

    // We need to explicitly remove the buttons from the tooltip manager,
    // because we're going to manager the tooltip ourselves in the
    // DefaultTreeContactList class. We need to do this in order to have
    // a different tooltip for every button and for non button area.
    ToolTipManager ttManager = ToolTipManager.sharedInstance();
    ttManager.unregisterComponent(callButton);
    ttManager.unregisterComponent(callVideoButton);
    ttManager.unregisterComponent(desktopSharingButton);
    ttManager.unregisterComponent(chatButton);
    ttManager.unregisterComponent(addContactButton);
  }
  /** Resets the rollover state of all rollover components in the current cell. */
  public void resetRolloverState() {
    chatButton.getModel().setRollover(false);
    callButton.getModel().setRollover(false);
    callVideoButton.getModel().setRollover(false);
    desktopSharingButton.getModel().setRollover(false);
    addContactButton.getModel().setRollover(false);

    if (customActionButtons != null) {
      Iterator<JButton> buttonsIter = customActionButtons.iterator();
      while (buttonsIter.hasNext()) {
        JButton button = buttonsIter.next();
        button.getModel().setRollover(false);
      }
    }

    if (customActionButtonsUIGroup != null) {
      Iterator<JButton> buttonsIter = customActionButtonsUIGroup.iterator();
      while (buttonsIter.hasNext()) {
        JButton button = buttonsIter.next();
        button.getModel().setRollover(false);
      }
    }
  }
  /** Initializes the panel containing the node. */
  public ContactListTreeCellRenderer() {
    super(new GridBagLayout());

    loadSkin();

    this.setOpaque(true);
    this.nameLabel.setOpaque(false);

    this.displayDetailsLabel.setFont(getFont().deriveFont(9f));
    this.displayDetailsLabel.setForeground(Color.GRAY);

    this.rightLabel.setHorizontalAlignment(JLabel.RIGHT);

    // !! IMPORTANT: General insets used for all components if not
    // overwritten!
    constraints.insets = new Insets(0, 0, 0, H_GAP);

    constraints.anchor = GridBagConstraints.WEST;
    constraints.fill = GridBagConstraints.NONE;
    constraints.gridx = 0;
    constraints.gridy = 0;
    constraints.gridheight = 1;
    constraints.weightx = 0f;
    constraints.weighty = 1f;
    this.add(statusLabel, constraints);

    addLabels(1);

    callButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (treeNode != null && treeNode instanceof ContactNode) {
              call(treeNode, callButton, false, false);
            }
          }
        });

    callVideoButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (treeNode != null && treeNode instanceof ContactNode) {
              call(treeNode, callVideoButton, true, false);
            }
          }
        });

    desktopSharingButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (treeNode != null && treeNode instanceof ContactNode) {
              call(treeNode, desktopSharingButton, true, true);
            }
          }
        });

    chatButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (treeNode != null && treeNode instanceof ContactNode) {
              UIContact contactDescriptor = ((ContactNode) treeNode).getContactDescriptor();

              if (contactDescriptor.getDescriptor() instanceof MetaContact) {
                GuiActivator.getUIService()
                    .getChatWindowManager()
                    .startChat((MetaContact) contactDescriptor.getDescriptor());
              }
            }
          }
        });

    addContactButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            if (treeNode != null && treeNode instanceof ContactNode) {
              UIContact contactDescriptor = ((ContactNode) treeNode).getContactDescriptor();

              // The add contact function has only sense for external
              // source contacts.
              if (contactDescriptor instanceof SourceUIContact) {
                addContact((SourceUIContact) contactDescriptor);
              }
            }
          }
        });

    initButtonToolTips();
    this.setToolTipText("");
  }
  /** Loads all images and colors. */
  public void loadSkin() {
    openedGroupIcon = new ImageIcon(ImageLoader.getImage(ImageLoader.OPENED_GROUP_ICON));

    closedGroupIcon = new ImageIcon(ImageLoader.getImage(ImageLoader.CLOSED_GROUP_ICON));

    callButton.setIconImage(ImageLoader.getImage(ImageLoader.CALL_BUTTON_SMALL));
    callButton.setRolloverIcon(ImageLoader.getImage(ImageLoader.CALL_BUTTON_SMALL_ROLLOVER));
    callButton.setPressedIcon(ImageLoader.getImage(ImageLoader.CALL_BUTTON_SMALL_PRESSED));

    chatButton.setIconImage(ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL));
    chatButton.setRolloverIcon(ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_ROLLOVER));
    chatButton.setPressedIcon(ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_PRESSED));

    msgReceivedImage = ImageLoader.getImage(ImageLoader.MESSAGE_RECEIVED_ICON);

    int groupForegroundProperty =
        GuiActivator.getResources().getColor("service.gui.CONTACT_LIST_GROUP_FOREGROUND");

    if (groupForegroundProperty > -1) groupForegroundColor = new Color(groupForegroundProperty);

    int contactForegroundProperty =
        GuiActivator.getResources().getColor("service.gui.CONTACT_LIST_CONTACT_FOREGROUND");

    if (contactForegroundProperty > -1)
      contactForegroundColor = new Color(contactForegroundProperty);

    callVideoButton.setIconImage(ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL));
    callVideoButton.setRolloverIcon(
        ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL_ROLLOVER));
    callVideoButton.setPressedIcon(
        ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED));

    desktopSharingButton.setIconImage(ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL));
    desktopSharingButton.setRolloverIcon(
        ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL_ROLLOVER));
    desktopSharingButton.setPressedIcon(
        ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED));

    addContactButton.setIconImage(ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL));
    addContactButton.setRolloverIcon(
        ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_ROLLOVER));
    addContactButton.setPressedIcon(
        ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED));
  }