diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
index cb28d5f52..d99b23511 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java
@@ -603,17 +603,10 @@ && isMobile((MetaContact)contact.getDescriptor()))
+ V_GAP
+ ComponentUtils.getStringHeight(displayDetailsLabel);
- // load button height, before button is even shown
- // will be the same as the image
- int buttonHeight = 27;
- Image img = ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL);
- if(img != null)
- buttonHeight = img.getHeight(chatButton);
-
preferredSelectedContactNodeHeight =
preferredNotSelectedContactNodeHeight
+ V_GAP
- + buttonHeight;
+ + BUTTON_HEIGHT;
}
}
else if (value instanceof GroupNode)
@@ -873,10 +866,11 @@ else if (treeNode instanceof GroupNode)
&& !customActionButtonsUIGroup.isEmpty())
{
if(preferredGroupNodeHeight != null)
+ {
preferredSize.height = preferredGroupNodeHeight
- + customActionButtonsUIGroup.size()
- * customActionButtonsUIGroup.get(0).getHeight()
- + V_GAP;
+ + V_GAP
+ + BUTTON_HEIGHT;
+ }
else
preferredSize.height = 70;
}
@@ -941,19 +935,6 @@ private void addLabels(int nameLabelGridWidth)
constraints.gridwidth = nameLabelGridWidth;
constraints.gridheight = 1;
- add(displayDetailsLabel, constraints);
- }
- else if (treeNode != null && treeNode instanceof GroupNode)
- {
- constraints.anchor = GridBagConstraints.WEST;
- constraints.fill = GridBagConstraints.NONE;
- constraints.gridx = 1;
- constraints.gridy = 1;
- constraints.weightx = 1f;
- constraints.weighty = 0f;
- constraints.gridwidth = nameLabelGridWidth;
- constraints.gridheight = 1;
-
add(displayDetailsLabel, constraints);
}
}
@@ -1029,7 +1010,7 @@ private void initButtonsPanel(UIContact uiContact)
if (imContact != null)
{
- x += addButton(chatButton, ++gridX, x, false);
+ x += addButton(chatButton, ++gridX, x, false, true);
}
UIContactDetail telephonyContact
@@ -1067,7 +1048,7 @@ private void initButtonsPanel(UIContact uiContact)
&& contactPhoneUtil.isCallEnabled(detailsListener)
&& providers.size() > 0))
{
- x += addButton(callButton, ++gridX, x, false);
+ x += addButton(callButton, ++gridX, x, false, true);
}
UIContactDetail videoContact
@@ -1078,7 +1059,7 @@ private void initButtonsPanel(UIContact uiContact)
|| (contactPhoneUtil != null
&& contactPhoneUtil.isVideoCallEnabled(detailsListener)))
{
- x += addButton(callVideoButton, ++gridX, x, false);
+ x += addButton(callVideoButton, ++gridX, x, false, true);
}
UIContactDetail desktopContact
@@ -1089,7 +1070,7 @@ private void initButtonsPanel(UIContact uiContact)
|| (contactPhoneUtil != null
&& contactPhoneUtil.isDesktopSharingEnabled(detailsListener)))
{
- x += addButton(desktopSharingButton, ++gridX, x, false);
+ x += addButton(desktopSharingButton, ++gridX, x, false, true);
}
// enable add contact button if contact source has indicated
@@ -1103,7 +1084,7 @@ private void initButtonsPanel(UIContact uiContact)
null).size() > 0
&& !ConfigurationUtils.isAddContactDisabled())
{
- x += addButton(addContactButton, ++gridX, x, false);
+ x += addButton(addContactButton, ++gridX, x, false, true);
}
//webButton
@@ -1117,7 +1098,7 @@ private void initButtonsPanel(UIContact uiContact)
getURLDetails(uiContact, webDetailsListener, true);
if(dets != null && dets.size() > 0)
{
- x += addButton(webButton, ++gridX, x, false);
+ x += addButton(webButton, ++gridX, x, false, true);
webButton.setLinksFromURLDetail(dets);
}
@@ -1135,7 +1116,7 @@ else if (uiContact.getDescriptor() instanceof SourceContact)
ContactDetail.Category.Web);
if(dets != null && dets.size() > 0)
{
- x += addButton(webButton, ++gridX, x, false);
+ x += addButton(webButton, ++gridX, x, false, true);
webButton.setLinksFromContactDetail(dets);
}
@@ -1265,7 +1246,7 @@ private int initGroupActionButtons(
customActionButtonsUIGroup.add(actionButton);
xBounds
- += addButton(actionButton, ++gridX, xBounds, false);
+ += addButton(actionButton, ++gridX, xBounds, false, false);
}
return gridX;
@@ -1305,7 +1286,7 @@ private int initContactActionButtons(
customActionButtons.add(actionButton);
xBounds
- += addButton(actionButton, ++gridX, xBounds, false);
+ += addButton(actionButton, ++gridX, xBounds, false, true);
}
return gridX;
@@ -2029,10 +2010,21 @@ public void run()
}
}
+ /**
+ * Adds button.
+ * @param button the button to add
+ * @param gridX the current x
+ * @param xBounds bounds
+ * @param isLast is it the last button
+ * @param isContact is contact or false if it is group node, that
+ * we are painting.
+ * @return the button width.
+ */
private int addButton( SIPCommButton button,
int gridX,
int xBounds,
- boolean isLast)
+ boolean isLast,
+ boolean isContact)
{
lastAddedButton = button;
@@ -2047,9 +2039,11 @@ private int addButton( SIPCommButton button,
constraints.weighty = 0f;
add(button, constraints);
- int yBounds = TOP_BORDER + BOTTOM_BORDER + 2*V_GAP
- + ComponentUtils.getStringSize(
- nameLabel, nameLabel.getText()).height
+ int yBounds = ComponentUtils.getStringSize(
+ nameLabel, nameLabel.getText()).height;
+
+ if(isContact)
+ yBounds += TOP_BORDER + BOTTOM_BORDER + 2*V_GAP
+ ComponentUtils.getStringSize(
displayDetailsLabel, displayDetailsLabel.getText()).height;
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
index 8dfb86606..bde4b0069 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
@@ -42,6 +42,7 @@ public class TreeContactList
MetaContactQueryListener,
MouseListener,
MouseMotionListener,
+ TreeWillExpandListener,
TreeExpansionListener,
TreeSelectionListener
{
@@ -173,6 +174,12 @@ public class TreeContactList
*/
private Boolean setAutoSelectionAllowed = false;
+ /**
+ * The previously selected node component. First nothing is selected so
+ * it is null.
+ */
+ private Object previouslySelectedNode = null;
+
/**
* Creates the TreeContactList.
*
@@ -192,6 +199,7 @@ public TreeContactList(ContactListContainer clContainer)
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.addTreeExpansionListener(this);
+ this.addTreeWillExpandListener(this);
this.addTreeSelectionListener(this);
GuiActivator.getContactListService()
@@ -1644,6 +1652,66 @@ public void mouseMoved(MouseEvent e)
public void mouseDragged(MouseEvent e) {}
+ /**
+ * Invoked whenever a node in the tree is about to be expanded.
+ */
+ @Override
+ public void treeWillExpand(TreeExpansionEvent event)
+ throws ExpandVetoException
+ {
+ TreePath path = event.getPath();
+
+ if (path == null)
+ return;
+
+ // remember it as previously selected, or moving from other group
+ // to the collapsed group with custom action buttons, we will need an
+ // extra click to collapse it again
+ // keep it null, till something is selected (valueChanged method called)
+ if(previouslySelectedNode != null)
+ previouslySelectedNode = path.getLastPathComponent();
+ }
+
+ /**
+ * Invoked whenever a node in the tree is about to be collapsed.
+ */
+ @Override
+ public void treeWillCollapse(TreeExpansionEvent event)
+ throws ExpandVetoException
+ {
+ TreePath path = event.getPath();
+
+ // If we didn't find any path for the given mouse location, we have
+ // nothing to do here.
+ if (path == null)
+ return;
+
+ Object lastComponent = path.getLastPathComponent();
+
+ if(lastComponent instanceof GroupNode)
+ {
+ GroupNode gn = (GroupNode)lastComponent;
+
+ UIGroupImpl uiGroup = gn.getGroupDescriptor();
+
+ // if the previous selection is not the group, do not collapse
+ // this way groups with custom buttons will only collapse
+ // when selected and clicked again (give a chance to the buttons
+ // to show)
+ if( (previouslySelectedNode != null
+ && !previouslySelectedNode.equals(lastComponent)
+ || previouslySelectedNode == null)
+ && uiGroup.getCustomActionButtons() != null
+ && uiGroup.getCustomActionButtons().size() > 0)
+ {
+ // the veto will not call valueChanged of TreeSelectionListener
+ previouslySelectedNode = lastComponent;
+
+ throw new ExpandVetoException(event);
+ }
+ }
+ }
+
/**
* Stores the state of the collapsed group.
* @param event the TreeExpansionEvent that notified us for about
@@ -1756,6 +1824,15 @@ private void dispatchEventToButtons(MouseEvent event)
((SIPCommButton) mouseComponent).getModel()
.setRollover(event.getID() == MouseEvent.MOUSE_MOVED);
+ // when clicking on buttons, make sure we do not
+ // collapse group if it is a button in group
+ if(event.getID() == MouseEvent.MOUSE_RELEASED
+ && event.getClickCount() < 2
+ && previouslySelectedNode instanceof GroupNode)
+ {
+ previouslySelectedNode = null;
+ }
+
renderer.resetRolloverState(mouseComponent);
mouseComponent.dispatchEvent(evt);
@@ -2549,6 +2626,12 @@ public void removeSelection()
*/
public void valueChanged(TreeSelectionEvent e)
{
+ TreePath oldSelectionPath = e.getOldLeadSelectionPath();
+ if(oldSelectionPath != null)
+ {
+ previouslySelectedNode = oldSelectionPath.getLastPathComponent();
+ }
+
UIGroup selectedGroup = getSelectedGroup();
if (selectedGroup != null)