aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip
diff options
context:
space:
mode:
authorYana Stamcheva <yana@jitsi.org>2012-09-23 17:23:33 +0000
committerYana Stamcheva <yana@jitsi.org>2012-09-23 17:23:33 +0000
commit86a0325947316d5e4b229a7f178f87a4f12be52c (patch)
treec83d09fad6da0566b0f4f310ce651da5660c9674 /src/net/java/sip
parent9dfae463286f44520f3ce9dda3e4ea01ff35f852 (diff)
downloadjitsi-86a0325947316d5e4b229a7f178f87a4f12be52c.zip
jitsi-86a0325947316d5e4b229a7f178f87a4f12be52c.tar.gz
jitsi-86a0325947316d5e4b229a7f178f87a4f12be52c.tar.bz2
New enhanced interface.
Diffstat (limited to 'src/net/java/sip')
-rw-r--r--src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java169
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/MainFrame.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java62
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java39
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java163
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallPeerRendererUtils.java130
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/CallToolBarButton.java72
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/FullScreenButton.java36
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java22
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/HangupButton.java42
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/InputVolumeControlButton.java12
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java9
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java9
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/OutputVolumeControlButton.java208
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/TransferCallButton.java25
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/call/VolumeControlSlider.java29
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationComponent.java2
-rwxr-xr-xsrc/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java726
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/ChatHtmlUtils.java412
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java33
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java2
-rwxr-xr-xsrc/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java5
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/IncomingMessageStyle.java203
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/OutgoingMessageStyle.java206
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/history/HistoryWindow.java28
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/menus/ChatRightButtonMenu.java40
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/menus/FileMenu.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java100
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListCellRenderer.java6
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java338
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java81
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java34
-rw-r--r--src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java123
-rw-r--r--src/net/java/sip/communicator/util/AvatarCacheUtils.java344
-rw-r--r--src/net/java/sip/communicator/util/GuiUtils.java37
-rw-r--r--src/net/java/sip/communicator/util/ImageUtils.java2
-rw-r--r--src/net/java/sip/communicator/util/UtilActivator.java20
-rw-r--r--src/net/java/sip/communicator/util/swing/OrderedTransparentPanel.java4
-rwxr-xr-xsrc/net/java/sip/communicator/util/swing/SIPCommButton.java14
-rw-r--r--src/net/java/sip/communicator/util/swing/SIPCommTextButton.java10
-rw-r--r--src/net/java/sip/communicator/util/swing/SIPCommToggleButton.java13
-rw-r--r--src/net/java/sip/communicator/util/swing/SoundLevelIndicator.java135
-rw-r--r--src/net/java/sip/communicator/util/swing/plaf/SIPCommTabbedPaneUI.java12
-rw-r--r--src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java6
-rw-r--r--src/net/java/sip/communicator/util/util.manifest.mf1
45 files changed, 2801 insertions, 1167 deletions
diff --git a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
index 8b1573d..81528e4 100644
--- a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
+++ b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
@@ -6,7 +6,6 @@
*/
package net.java.sip.communicator.impl.contactlist;
-import java.io.*;
import java.util.*;
import net.java.sip.communicator.service.contactlist.*;
@@ -14,8 +13,6 @@ import net.java.sip.communicator.service.contactlist.event.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
-import org.jitsi.service.fileaccess.*;
-
/**
* A default implementation of the <code>MetaContact</code> interface.
*
@@ -94,34 +91,11 @@ public class MetaContactImpl
private Map<String, List<String>> details;
/**
- * The name (i.e. not the whole path) of the directory in which the avatar
- * files are to be cached for later reuse.
- */
- private final static String AVATAR_DIR = "avatarcache";
-
- /**
* Whether user has renamed this meta contact.
*/
private boolean isDisplayNameUserDefined = false;
/**
- * Characters and their replacement in created folder names
- */
- private final static String[][] ESCAPE_SEQUENCES = new String[][]
- {
- {"&", "&_amp"},
- {"/", "&_sl"},
- {"\\\\", "&_bs"}, // the char \
- {":", "&_co"},
- {"\\*", "&_as"}, // the char *
- {"\\?", "&_qm"}, // the char ?
- {"\"", "&_pa"}, // the char "
- {"<", "&_lt"},
- {">", "&_gt"},
- {"\\|", "&_pp"} // the char |
- };
-
- /**
* Creates new meta contact with a newly generated meta contact UID.
*/
MetaContactImpl()
@@ -636,16 +610,8 @@ public class MetaContactImpl
while (iter.hasNext())
{
Contact protoContact = iter.next();
- String avatarPath = AVATAR_DIR
- + File.separator
- + escapeSpecialCharacters(
- protoContact
- .getProtocolProvider()
- .getAccountID().getAccountUniqueID())
- + File.separator
- + escapeSpecialCharacters(protoContact.getAddress());
-
- cachedAvatar = getLocallyStoredAvatar(avatarPath);
+
+ cachedAvatar = AvatarCacheUtils.getCachedAvatar(protoContact);
/*
* Caching a zero-length avatar happens but such an avatar isn't
* very useful.
@@ -1103,136 +1069,7 @@ public class MetaContactImpl
this.cachedAvatar = avatarBytes;
this.avatarFileCacheAlreadyQueried = true;
- String avatarDirPath
- = AVATAR_DIR
- + File.separator
- + escapeSpecialCharacters(
- protoContact
- .getProtocolProvider()
- .getAccountID().getAccountUniqueID());
- String avatarFileName
- = escapeSpecialCharacters(protoContact.getAddress());
-
- File avatarDir = null;
- File avatarFile = null;
- try
- {
- FileAccessService fileAccessService
- = ContactlistActivator.getFileAccessService();
-
- avatarDir
- = fileAccessService.getPrivatePersistentDirectory(
- avatarDirPath);
- avatarFile
- = fileAccessService.getPrivatePersistentFile(
- avatarDirPath + File.separator + avatarFileName);
-
- if(!avatarFile.exists())
- {
- if (!avatarDir.exists() && !avatarDir.mkdirs())
- {
- throw
- new IOException(
- "Failed to create directory: "
- + avatarDir.getAbsolutePath());
- }
-
- if (!avatarFile.createNewFile())
- {
- throw
- new IOException(
- "Failed to create file"
- + avatarFile.getAbsolutePath());
- }
- }
-
- FileOutputStream fileOutStream = new FileOutputStream(avatarFile);
-
- try
- {
- fileOutStream.write(avatarBytes);
- fileOutStream.flush();
- }
- finally
- {
- fileOutStream.close();
- }
- }
- catch (Exception ex)
- {
- logger.error(
- "Failed to store avatar. dir =" + avatarDir
- + " file=" + avatarFile,
- ex);
- }
- }
-
- /**
- * Returns the avatar image corresponding to the given avatar path.
- *
- * @param avatarPath The path to the lovally stored avatar.
- * @return the avatar image corresponding to the given avatar path.
- */
- private byte[] getLocallyStoredAvatar(String avatarPath)
- {
- try
- {
- File avatarFile
- = ContactlistActivator
- .getFileAccessService()
- .getPrivatePersistentFile(avatarPath);
-
- if(avatarFile.exists())
- {
- FileInputStream avatarInputStream
- = new FileInputStream(avatarFile);
- byte[] bs = null;
-
- try
- {
- int available = avatarInputStream.available();
-
- if (available > 0)
- {
- bs = new byte[available];
- avatarInputStream.read(bs);
- }
- }
- finally
- {
- avatarInputStream.close();
- }
- if (bs != null)
- return bs;
- }
- }
- catch (Exception ex)
- {
- logger.error(
- "Could not read avatar image from file " + avatarPath,
- ex);
- }
- return null;
- }
-
- /**
- * Replaces the characters that we must escape used for the created
- * filename.
- *
- * @param id the <tt>String</tt> which is to have its characters escaped
- * @return a <tt>String</tt> derived from the specified <tt>id</tt> by
- * escaping characters
- */
- private String escapeSpecialCharacters(String id)
- {
- String resultId = id;
-
- for (int j = 0; j < ESCAPE_SEQUENCES.length; j++)
- {
- resultId = resultId.
- replaceAll(ESCAPE_SEQUENCES[j][0], ESCAPE_SEQUENCES[j][1]);
- }
- return resultId;
+ AvatarCacheUtils.cacheAvatar(protoContact, avatarBytes);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
index a0f2eb9..7bc1ea7 100644
--- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
+++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java
@@ -276,7 +276,7 @@ public class MainFrame
this.setJMenuBar(menu);
TransparentPanel searchPanel
- = new TransparentPanel(new BorderLayout(2, 0));
+ = new TransparentPanel(new BorderLayout(5, 0));
searchPanel.add(searchField);
searchPanel.add(new DialPadButton(), BorderLayout.WEST);
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java b/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
index 7958d68..0c67e0b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/AbstractCallToggleButton.java
@@ -37,17 +37,17 @@ public abstract class AbstractCallToggleButton
/**
* The background image.
*/
- protected ImageID bgImage;
+ protected ImageID bgImageID;
/**
* The rollover image
*/
- protected ImageID bgRolloverImage;
+ protected ImageID bgRolloverImageID;
/**
* The pressed image.
*/
- protected ImageID pressedImage;
+ protected ImageID pressedImageID;
/**
* The icon image.
@@ -136,27 +136,17 @@ public abstract class AbstractCallToggleButton
this.fullScreen = fullScreen;
this.settingsPanel = settingsPanel;
- if (fullScreen)
+ if(settingsPanel)
{
- bgImage = ImageLoader.FULL_SCREEN_BUTTON_BG;
- bgRolloverImage = ImageLoader.FULL_SCREEN_BUTTON_BG;
- pressedImage = ImageLoader.FULL_SCREEN_BUTTON_BG_PRESSED;
+ bgRolloverImageID = ImageLoader.CALL_SETTING_BUTTON_BG;
+ pressedImageID = ImageLoader.CALL_SETTING_BUTTON_PRESSED_BG;
}
else
{
- if(settingsPanel)
- {
- bgImage = ImageLoader.CALL_SETTING_BUTTON_BG;
- bgRolloverImage = ImageLoader.CALL_SETTING_BUTTON_BG;
- pressedImage = ImageLoader.CALL_SETTING_BUTTON_PRESSED_BG;
- }
- else
- {
- bgImage = ImageLoader.SOUND_SETTING_BUTTON_BG;
- bgRolloverImage = ImageLoader.SOUND_SETTING_BUTTON_BG;
- pressedImage = ImageLoader.SOUND_SETTING_BUTTON_PRESSED;
+ bgImageID = ImageLoader.SOUND_SETTING_BUTTON_BG;
+ bgRolloverImageID = ImageLoader.SOUND_SETTING_BUTTON_BG;
+ pressedImageID = ImageLoader.SOUND_SETTING_BUTTON_PRESSED;
- }
}
if (toolTipTextKey != null)
@@ -171,13 +161,6 @@ public abstract class AbstractCallToggleButton
// All items are now instantiated and could safely load the skin.
loadSkin();
-
- int width = getBgImage().getWidth(null);
- int height = getBgImage().getHeight(null);
-
- this.setPreferredSize(new Dimension(width, height));
- this.setMaximumSize(new Dimension(width, height));
- this.setMinimumSize(new Dimension(width, height));
}
/**
@@ -256,15 +239,30 @@ public abstract class AbstractCallToggleButton
*/
public void loadSkin()
{
- setBgImage(ImageLoader.getImage(bgImage));
- setBgRolloverImage(ImageLoader.getImage(bgRolloverImage));
- setPressedImage(ImageLoader.getImage(pressedImage));
+ int width = CallToolBarButton.DEFAULT_WIDTH;
+ int height = CallToolBarButton.DEFAULT_HEIGHT;
+
+ if (bgImageID != null)
+ {
+ Image bgImage = ImageLoader.getImage(bgImageID);
+ setBgImage(bgImage);
+
+ width = bgImage.getWidth(this);
+ height = bgImage.getHeight(this);
+ }
+
+ setPreferredSize(new Dimension(width, height));
+ setMaximumSize(new Dimension(width, height));
+ setMinimumSize(new Dimension(width, height));
+
+ setBgRolloverImage(ImageLoader.getImage(bgRolloverImageID));
+ setPressedImage(ImageLoader.getImage(pressedImageID));
if (iconImageID != null)
{
if (!fullScreen && !settingsPanel)
setIconImage(ImageUtils.scaleImageWithinBounds(
- ImageLoader.getImage(iconImageID), 12, 12));
+ ImageLoader.getImage(iconImageID), 18, 18));
else
setIconImage(ImageLoader.getImage(iconImageID));
}
@@ -273,7 +271,7 @@ public abstract class AbstractCallToggleButton
{
if (!fullScreen && !settingsPanel)
setPressedIconImage(ImageUtils.scaleImageWithinBounds(
- ImageLoader.getImage(pressedIconImageID), 12, 12));
+ ImageLoader.getImage(pressedIconImageID), 18, 18));
else
setPressedIconImage(ImageLoader.getImage(pressedIconImageID));
}
@@ -290,7 +288,7 @@ public abstract class AbstractCallToggleButton
if (!fullScreen && !settingsPanel)
setIconImage(ImageUtils.scaleImageWithinBounds(
- ImageLoader.getImage(iconImageID), 12, 12));
+ ImageLoader.getImage(iconImageID), 18, 18));
else
setIconImage(ImageLoader.getImage(iconImageID));
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java b/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java
index 476ad52..d00d60d 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java
@@ -42,6 +42,11 @@ public class CallHistoryButton
private Image pressedImage;
/**
+ * The notification image.
+ */
+ private Image notificationImage;
+
+ /**
* Indicates if the history is visible.
*/
private boolean isHistoryVisible = false;
@@ -142,7 +147,10 @@ public class CallHistoryButton
*/
private void setHistoryView()
{
- isNotificationsView = false;
+ if (isNotificationsView)
+ isNotificationsView = false;
+ else
+ setIcon(null);
if (isHistoryVisible)
{
@@ -167,7 +175,6 @@ public class CallHistoryButton
{
int notificationCount = 0;
isNotificationsView = true;
- this.setBgImage(null);
Iterator<UINotificationGroup> groupsIter
= notificationGroups.iterator();
@@ -204,7 +211,29 @@ public class CallHistoryButton
this.setToolTipText(tooltipText + "</html>");
this.setBackground(new Color(200, 0, 0));
- this.setText(new Integer(notificationCount).toString());
+ this.setVerticalTextPosition(SwingConstants.TOP);
+
+ Image iconImage = ImageLoader.getImage(notificationImage,
+ new Integer(notificationCount).toString(), this);
+
+ if (isHistoryVisible)
+ {
+ setBgImage(ImageLoader.getImage(
+ pressedImage,
+ iconImage,
+ pressedImage.getWidth(null)/2
+ - notificationImage.getWidth(null)/2,
+ 0));
+ }
+ else
+ {
+ setBgImage(ImageLoader.getImage(
+ historyImage,
+ iconImage,
+ pressedImage.getWidth(null)/2
+ - notificationImage.getWidth(null)/2,
+ 0));
+ }
}
/**
@@ -218,6 +247,10 @@ public class CallHistoryButton
pressedImage
= ImageLoader.getImage(ImageLoader.CALL_HISTORY_BUTTON_PRESSED);
+ notificationImage
+ = ImageLoader.getImage(
+ ImageLoader.CALL_HISTORY_BUTTON_NOTIFICATION);
+
this.setPreferredSize(new Dimension(historyImage.getWidth(this),
historyImage.getHeight(this)));
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index 966a7a2..e8a5c2a 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -14,7 +14,6 @@ import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
-import javax.swing.border.*;
import javax.swing.event.*;
import net.java.sip.communicator.impl.gui.*;
@@ -29,7 +28,6 @@ import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.Logger;
import net.java.sip.communicator.util.skin.*;
import net.java.sip.communicator.util.swing.*;
-import net.java.sip.communicator.util.swing.border.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.device.*;
@@ -108,11 +106,6 @@ public class CallPanel
/**
* The hang up button name.
*/
- private static final String HANGUP_BUTTON = "HANGUP_BUTTON";
-
- /**
- * The hang up button name.
- */
private static final String MERGE_BUTTON = "MERGE_BUTTON";
/**
@@ -128,7 +121,7 @@ public class CallPanel
/**
* The panel containing call settings.
*/
- private final TransparentPanel settingsPanel = new OrderedTransparentPanel();
+ private JComponent settingsPanel;
/**
* The panel representing the call. For conference calls this would be an
@@ -181,17 +174,20 @@ public class CallPanel
/**
* The dial button, which opens a keypad dialog.
*/
- private SIPCommButton dialButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.DIAL_BUTTON));
+ private CallToolBarButton dialButton = new CallToolBarButton(
+ ImageLoader.getImage(ImageLoader.DIAL_BUTTON),
+ DIAL_BUTTON,
+ GuiActivator.getResources().getI18NString("service.gui.DIALPAD"));
/**
* The conference button.
*/
- private SIPCommButton conferenceButton
- = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.ADD_TO_CALL_BUTTON));
+ private CallToolBarButton conferenceButton
+ = new CallToolBarButton(
+ ImageLoader.getImage(ImageLoader.ADD_TO_CALL_BUTTON),
+ CONFERENCE_BUTTON,
+ GuiActivator.getResources().getI18NString(
+ "service.gui.CREATE_CONFERENCE_CALL"));
/**
* Chat button.
@@ -216,10 +212,12 @@ public class CallPanel
/**
* Merge button.
*/
- private SIPCommButton mergeButton =
- new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.MERGE_CALL_BUTTON));
+ private CallToolBarButton mergeButton =
+ new CallToolBarButton(
+ ImageLoader.getImage(ImageLoader.MERGE_CALL_BUTTON),
+ MERGE_BUTTON,
+ GuiActivator.getResources().getI18NString(
+ "service.gui.MERGE_TO_CALL"));
/**
* The call represented in this dialog.
@@ -264,7 +262,7 @@ public class CallPanel
/**
* Sound remote level label.
*/
- private OutputVolumeControlButton remoteLevel;
+ private Component remoteLevel;
/**
* A collection of listeners, registered for call title change events.
@@ -290,23 +288,28 @@ public class CallPanel
this.call = call;
this.callWindow = callWindow;
+ settingsPanel
+ = CallPeerRendererUtils.createButtonBar(false, null);
+
holdButton = new HoldButton(call);
recordButton = new RecordButton(call);
videoButton = new LocalVideoButton(call);
showHideVideoButton = new ShowHideVideoButton(call);
desktopSharingButton = new DesktopSharingButton(call);
transferCallButton = new TransferCallButton(call);
- fullScreenButton = new FullScreenButton(this);
- chatButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_WHITE));
+ fullScreenButton = new FullScreenButton(this, false);
+ chatButton = new CallToolBarButton(
+ ImageLoader.getImage(ImageLoader.CHAT_BUTTON_SMALL_WHITE),
+ CHAT_BUTTON,
+ GuiActivator.getResources().getI18NString("service.gui.CHAT"));
+
localLevel = new InputVolumeControlButton(
call,
ImageLoader.MICROPHONE,
ImageLoader.MUTE_BUTTON,
false, true, false);
remoteLevel = new OutputVolumeControlButton(
- ImageLoader.VOLUME_CONTROL_BUTTON, false, true);
+ ImageLoader.VOLUME_CONTROL_BUTTON, false, true).getComponent();
this.callDurationTimer = new Timer(1000, new CallTimerListener());
this.callDurationTimer.setRepeats(true);
@@ -345,7 +348,7 @@ public class CallPanel
callPeers.next().addCallPeerConferenceListener(this);
// Initializes all buttons and common panels.
- init();
+ initToolBar();
initPluginComponents();
}
@@ -353,15 +356,12 @@ public class CallPanel
/**
* Initializes all buttons and common panels
*/
- private void init()
+ private void initToolBar()
{
- hangupButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.HANGUP_BUTTON_BG));
+ hangupButton = new HangupButton(this);
- holdButton.setIndex(2);
- recordButton.setIndex(3);
- videoButton.setIndex(11);
- showHideVideoButton.setIndex(12);
+ // Initializes the order of buttons in the call tool bar.
+ initButtonIndexes();
showHideVideoButton.setPeerRenderer(((CallRenderer) callPanel)
.getCallPeerRenderer(call.getCallPeers().next()));
@@ -388,42 +388,9 @@ public class CallPanel
}
});
- desktopSharingButton.setIndex(8);
- transferCallButton.setIndex(5);
- fullScreenButton.setIndex(10);
-
- chatButton.setName(CHAT_BUTTON);
- chatButton.setToolTipText(
- GuiActivator.getResources().getI18NString("service.gui.CHAT"));
chatButton.addActionListener(this);
- chatButton.setIndex(19);
-
- localLevel.setIndex(6);
- remoteLevel.setIndex(7);
-
- dialButton.setIndex(0);
- dialButton.setName(DIAL_BUTTON);
- dialButton.setToolTipText(
- GuiActivator.getResources().getI18NString("service.gui.DIALPAD"));
dialButton.addActionListener(this);
-
- conferenceButton.setIndex(1);
- conferenceButton.setName(CONFERENCE_BUTTON);
- conferenceButton.setToolTipText(
- GuiActivator.getResources().getI18NString(
- "service.gui.CREATE_CONFERENCE_CALL"));
conferenceButton.addActionListener(this);
-
- hangupButton.setName(HANGUP_BUTTON);
- hangupButton.setToolTipText(
- GuiActivator.getResources().getI18NString("service.gui.HANG_UP"));
- hangupButton.addActionListener(this);
-
- mergeButton.setIndex(4);
- mergeButton.setName(MERGE_BUTTON);
- mergeButton.setToolTipText(
- GuiActivator.getResources().getI18NString(
- "service.gui.MERGE_TO_CALL"));
mergeButton.addActionListener(this);
/*
@@ -474,24 +441,50 @@ public class CallPanel
if(GuiActivator.getConfigurationService()
.getBoolean(SHOW_CALL_INFO_BUTON_PROP, true))
{
- infoButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.CALL_INFO));
- infoButton.setName(INFO_BUTTON);
- infoButton.setToolTipText(
- GuiActivator.getResources().getI18NString(
- "service.gui.PRESS_FOR_CALL_INFO"));
+ infoButton = new CallToolBarButton(
+ ImageLoader.getImage(ImageLoader.CALL_INFO),
+ INFO_BUTTON,
+ GuiActivator.getResources().getI18NString(
+ "service.gui.PRESS_FOR_CALL_INFO"));
+
infoButton.addActionListener(this);
- infoButton.setIndex(20);
settingsPanel.add(infoButton);
}
- dtmfHandler = new DTMFHandler(this);
+ settingsPanel.add(hangupButton);
- JComponent bottomBar = createBottomBar();
+ dtmfHandler = new DTMFHandler(this);
add(callPanel, BorderLayout.CENTER);
- add(bottomBar, BorderLayout.SOUTH);
+ add(createBottomBar(), BorderLayout.SOUTH);
+ }
+
+ /**
+ * Initializes buttons order in the call tool bar.
+ */
+ private void initButtonIndexes()
+ {
+ dialButton.setIndex(0);
+ conferenceButton.setIndex(1);
+ holdButton.setIndex(2);
+ recordButton.setIndex(3);
+ mergeButton.setIndex(4);
+ transferCallButton.setIndex(5);
+ localLevel.setIndex(6);
+
+ if (remoteLevel instanceof OrderedComponent)
+ ((OrderedComponent) remoteLevel).setIndex(7);
+
+ desktopSharingButton.setIndex(8);
+ fullScreenButton.setIndex(10);
+ videoButton.setIndex(11);
+ showHideVideoButton.setIndex(12);
+ chatButton.setIndex(19);
+
+ if (infoButton != null)
+ infoButton.setIndex(20);
+
+ hangupButton.setIndex(100);
}
/**
@@ -503,11 +496,7 @@ public class CallPanel
JButton button = (JButton) evt.getSource();
String buttonName = button.getName();
- if (buttonName.equals(HANGUP_BUTTON))
- {
- actionPerformedOnHangupButton(false);
- }
- else if (buttonName.equals(MERGE_BUTTON))
+ if (buttonName.equals(MERGE_BUTTON))
{
Collection<Call> calls = CallManager.getActiveCalls();
@@ -1612,10 +1601,10 @@ public class CallPanel
*/
private JComponent createBottomBar()
{
- JComponent bottomBar = new TransparentPanel();
+ JComponent bottomBar
+ = new TransparentPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
- bottomBar.setBorder(
- new ExtendedEtchedBorder(EtchedBorder.LOWERED, 1, 0, 0, 0));
+ bottomBar.setBorder(BorderFactory.createEmptyBorder(0, 30, 2, 30));
if (OSUtils.IS_MAC)
{
@@ -1625,9 +1614,7 @@ public class CallPanel
.getColor("service.gui.MAC_PANEL_BACKGROUND")));
}
- bottomBar.setLayout(new BorderLayout());
- bottomBar.add(settingsPanel, BorderLayout.WEST);
- bottomBar.add(hangupButton, BorderLayout.EAST);
+ bottomBar.add(settingsPanel);
return bottomBar;
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRendererUtils.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRendererUtils.java
index f6a4656..543af5d 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRendererUtils.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPeerRendererUtils.java
@@ -13,7 +13,6 @@ import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
-import net.java.sip.communicator.util.skin.*;
import net.java.sip.communicator.util.swing.*;
/**
@@ -27,30 +26,6 @@ import net.java.sip.communicator.util.swing.*;
public class CallPeerRendererUtils
{
/**
- * Creates a new <tt>Component</tt> through which the user would be able to
- * exit the full screen mode.
- *
- * @param renderer the renderer through which we exit the full screen mode
- * @return the newly created component
- */
- public static Component createExitFullScreenButton(
- final CallRenderer renderer)
- {
- JButton button = new ExitFullScreenButton();
-
- button.setToolTipText(GuiActivator.getResources().getI18NString(
- "service.gui.EXIT_FULL_SCREEN_TOOL_TIP"));
- button.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent event)
- {
- renderer.exitFullScreen();
- }
- });
- return button;
- }
-
- /**
* Sets the given <tt>background</tt> color to the given <tt>component</tt>.
*
* @param component the component to which we set the background
@@ -87,24 +62,27 @@ public class CallPeerRendererUtils
/**
* Creates a buttons bar from the given list of button components.
*
- * @param heavyweight indicates if the created button bar should be heavy
- * weight component (useful in full screen mode)
+ * @param fullScreen indicates if the created button bar would be shown in
+ * full screen mode
* @param buttons the list of buttons to add in the created button bar
* @return the created button bar
*/
- public static Component createButtonBar(boolean heavyweight,
+ public static JComponent createButtonBar(boolean fullScreen,
Component[] buttons)
{
- Container buttonBar
- = heavyweight ? new Container() : new TransparentPanel();
+ JComponent buttonBar = fullScreen
+ ? new CallToolBarPanel(true)
+ : new CallToolBarPanel(false);
- buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 3, 3));
-
- for (Component button : buttons)
+ if (buttons != null)
{
- if (button != null)
- buttonBar.add(button);
+ for (Component button : buttons)
+ {
+ if (button != null)
+ ((Container) buttonBar).add(button);
+ }
}
+
return buttonBar;
}
@@ -137,32 +115,74 @@ public class CallPeerRendererUtils
}
/**
- * Full screen exit button. Implements <tt>Skinnable</tt>.
+ * The tool bar container shown in the call window.
*/
- public static class ExitFullScreenButton
- extends SIPCommButton
- implements Skinnable
+ private static class CallToolBarPanel
+ extends OrderedTransparentPanel
{
- /**
- * Creates an instance of SIPCommButton.
- */
- public ExitFullScreenButton()
+ final Color settingsColor
+ = new Color(GuiActivator.getResources().getColor(
+ "service.gui.CALL_TOOL_BAR"));
+
+ final Color settingsFullScreenColor
+ = new Color(GuiActivator.getResources().getColor(
+ "service.gui.CALL_TOOL_BAR_FULL_SCREEN"));
+
+ final Image buttonSeparatorImage
+ = ImageLoader.getImage(ImageLoader.CALL_TOOLBAR_SEPARATOR);
+
+ private final boolean isFullScreen;
+
+ private final int TOOL_BAR_BORDER = 2;
+
+ private final int TOOL_BAR_X_GAP = 3;
+
+ public CallToolBarPanel(boolean isFullScreen)
{
- super(
- ImageLoader.getImage(ImageLoader.FULL_SCREEN_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.EXIT_FULL_SCREEN_BUTTON));
+ this.isFullScreen = isFullScreen;
+
+ setLayout(new FlowLayout(FlowLayout.CENTER, 3, 0));
+ setBorder(BorderFactory.createEmptyBorder(
+ TOOL_BAR_BORDER,
+ TOOL_BAR_BORDER,
+ TOOL_BAR_BORDER,
+ TOOL_BAR_BORDER));
}
- /**
- * Reloads icons.
- */
- public void loadSkin()
+ public void paintComponent(Graphics g)
{
- setBackgroundImage(
- ImageLoader.getImage(ImageLoader.FULL_SCREEN_BUTTON_BG));
- setIconImage(
- ImageLoader.getImage(ImageLoader.EXIT_FULL_SCREEN_BUTTON));
- }
+ super.paintComponent(g);
+
+ g = g.create();
+
+ AntialiasingManager.activateAntialiasing(g);
+
+ try
+ {
+ if (isFullScreen)
+ g.setColor(settingsFullScreenColor);
+ else
+ g.setColor(settingsColor);
+
+ g.fillRoundRect(0, 0, getWidth(), getHeight(), 8, 8);
+
+ // We add the border.
+ int x = CallToolBarButton.DEFAULT_WIDTH
+ + TOOL_BAR_BORDER + TOOL_BAR_X_GAP;
+
+ while (x < getWidth() - TOOL_BAR_BORDER - TOOL_BAR_X_GAP)
+ {
+ g.drawImage(buttonSeparatorImage, x + 1,
+ (getHeight() - buttonSeparatorImage.getHeight(this))/2,
+ this);
+ x += CallToolBarButton.DEFAULT_WIDTH + TOOL_BAR_X_GAP;
+ }
+ }
+ finally
+ {
+ g.dispose();
+ }
+ }
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallToolBarButton.java b/src/net/java/sip/communicator/impl/gui/main/call/CallToolBarButton.java
new file mode 100644
index 0000000..c63e631
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallToolBarButton.java
@@ -0,0 +1,72 @@
+/*
+ * 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.impl.gui.main.call;
+
+import java.awt.*;
+
+import net.java.sip.communicator.util.swing.*;
+
+/**
+ * The <tt>CallBarButton</tt> is a button shown in the call window tool bar.
+ *
+ * @author Yana Stamcheva
+ */
+public class CallToolBarButton
+ extends SIPCommButton
+{
+ /**
+ * The default width of a button in the call tool bar.
+ */
+ public static final int DEFAULT_WIDTH = 44;
+
+ /**
+ * The default height of a button in the call tool bar.
+ */
+ public static final int DEFAULT_HEIGHT = 38;
+
+ /**
+ * Creates an instance of <tt>CallToolBarButton</tt>.
+ */
+ public CallToolBarButton()
+ {
+ this(null, null);
+ }
+
+ /**
+ * Creates an instance of <tt>CallToolBarButton</tt> by specifying the icon
+ * image and the tool tip text.
+ *
+ * @param iconImage the icon of this button
+ * @param tooltipText the text to show in the button tooltip
+ */
+ public CallToolBarButton( Image iconImage,
+ String tooltipText)
+ {
+ this(iconImage, null, tooltipText);
+ }
+
+ /**
+ * Creates an instance of <tt>CallToolBarButton</tt> by specifying the icon
+ * image, the name of the button and the tool tip text.
+ *
+ * @param iconImage the icon of this button
+ * @param buttonName the name of this button
+ * @param tooltipText the text to show in the button tooltip
+ */
+ public CallToolBarButton( Image iconImage,
+ String buttonName,
+ String tooltipText)
+ {
+ super(null, iconImage);
+
+ setIconImage(iconImage);
+
+ setPreferredSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
+ setName(buttonName);
+ setToolTipText(tooltipText);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenButton.java b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenButton.java
index 216bde8..714b0fc 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenButton.java
@@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
+import java.awt.*;
import java.awt.event.*;
import net.java.sip.communicator.impl.gui.*;
@@ -24,19 +25,30 @@ public class FullScreenButton
implements Skinnable
{
/**
+ * Indicates if this buttons is shown in full screen view or normal window.
+ */
+ private boolean isFullScreen = false;
+
+ /**
* Initializes a new <tt>FullScreenButton</tt> instance which is to
* enter the full screen mode.
*
* @param callContainer the parent <tt>CallContainer</tt>, where this button
* is contained
*/
- public FullScreenButton(final CallPanel callContainer)
+ public FullScreenButton(final CallPanel callContainer,
+ final boolean isFullScreen)
{
- super( ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.ENTER_FULL_SCREEN_BUTTON));
+ this.isFullScreen = isFullScreen;
+
+ if (isFullScreen)
+ setToolTipText(GuiActivator.getResources().getI18NString(
+ "service.gui.EXIT_FULL_SCREEN_TOOL_TIP"));
+ else
+ setToolTipText(GuiActivator.getResources().getI18NString(
+ "service.gui.ENTER_FULL_SCREEN_TOOL_TIP"));
- setToolTipText(GuiActivator.getResources().getI18NString(
- "service.gui.ENTER_FULL_SCREEN_TOOL_TIP"));
+ loadSkin();
addActionListener(new ActionListener()
{
@@ -49,7 +61,10 @@ public class FullScreenButton
*/
public void actionPerformed(ActionEvent evt)
{
- callContainer.getCurrentCallRenderer().enterFullScreen();
+ if (isFullScreen)
+ callContainer.getCurrentCallRenderer().exitFullScreen();
+ else
+ callContainer.getCurrentCallRenderer().enterFullScreen();
}
});
}
@@ -59,10 +74,13 @@ public class FullScreenButton
*/
public void loadSkin()
{
- setBackgroundImage(ImageLoader.getImage(
- ImageLoader.CALL_SETTING_BUTTON_BG));
+ setPreferredSize(new Dimension(44, 38));
- setIconImage(ImageLoader.getImage(
+ if (isFullScreen)
+ setIconImage(ImageLoader.getImage(
+ ImageLoader.EXIT_FULL_SCREEN_BUTTON));
+ else
+ setIconImage(ImageLoader.getImage(
ImageLoader.ENTER_FULL_SCREEN_BUTTON));
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java
index 34032b3..6d1e861 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java
@@ -34,17 +34,30 @@ public class FullScreenLayout
private Component south;
/**
+ * The vertical gap between the center and the south components.
+ */
+ private int yGap = 0;
+
+ /**
* Initializes a new <tt>FullScreenLayout</tt> instance.
*
* @param overlay <tt>true</tt> to lay out the <tt>Component</tt> at
* {@link #SOUTH} on top of the <tt>Component</tt> at {@link #CENTER} i.e as
* an overlay; otherwise, <tt>false</tt>
+ * @oaram yGap the gap betwen the center and the south component
*/
- public FullScreenLayout(boolean overlay)
+ public FullScreenLayout(boolean overlay, int yGap)
{
this.overlay = overlay;
+ this.yGap = yGap;
}
+ /**
+ * Adds the given component to this layout.
+ *
+ * @param name the name of the constraint (CENTER or SOUTH)
+ * @param comp the component to add to this layout
+ */
public void addLayoutComponent(String name, Component comp)
{
if (CENTER.equals(name))
@@ -72,6 +85,11 @@ public class FullScreenLayout
return layoutComponents;
}
+ /**
+ * Lays out the components added in the given parent container
+ *
+ * @param parent the parent container to lay out
+ */
public void layoutContainer(Container parent)
{
int southWidth;
@@ -97,7 +115,7 @@ public class FullScreenLayout
* If the Component at the SOUTH is not to be shown as an overlay,
* make room for it bellow the Component at the CENTER.
*/
- int yOffset = overlay ? 0 : southHeight;
+ int yOffset = overlay ? 0 : southHeight + yGap;
center.setBounds(
0,
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/HangupButton.java b/src/net/java/sip/communicator/impl/gui/main/call/HangupButton.java
new file mode 100644
index 0000000..645df75
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/call/HangupButton.java
@@ -0,0 +1,42 @@
+/*
+ * 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.impl.gui.main.call;
+
+import java.awt.event.*;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.impl.gui.utils.*;
+
+/**
+ * The hangup button shown in the call window.
+ *
+ * @author Yana Stamcheva
+ */
+public class HangupButton
+ extends CallToolBarButton
+{
+ /**
+ * Creates an instance of <tt>HangupButton</tt>, by specifying the parent
+ * call panel.
+ *
+ * @param callPanel the parent call panel
+ */
+ public HangupButton(final CallPanel callPanel)
+ {
+ super( ImageLoader.getImage(ImageLoader.HANGUP_BUTTON_BG),
+ GuiActivator.getResources()
+ .getI18NString("service.gui.HANG_UP"));
+
+ addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ callPanel.actionPerformedOnHangupButton(false);
+ }
+ });
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/InputVolumeControlButton.java b/src/net/java/sip/communicator/impl/gui/main/call/InputVolumeControlButton.java
index f318667..d161548 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/InputVolumeControlButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/InputVolumeControlButton.java
@@ -51,8 +51,14 @@ public class InputVolumeControlButton
*/
private final VolumeControl volumeControl;
- private final VolumeControlSlider sliderMenu;
+ /**
+ * The slider popup menu.
+ */
+ private final JPopupMenu sliderMenu;
+ /**
+ * Indicates if this component is shown in full screen mode.
+ */
private final boolean fullScreen;
/**
@@ -135,7 +141,9 @@ public class InputVolumeControlButton
volumeControl = getVolumeControl();
// Creates the menu that would contain the volume control component.
- sliderMenu = new VolumeControlSlider(volumeControl);
+ sliderMenu
+ = new VolumeControlSlider(volumeControl, JSlider.VERTICAL)
+ .getPopupMenu();
sliderMenu.setInvoker(this);
addMouseListener(new MouseAdapter()
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
index 476d089..f3558bb 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPanel.java
@@ -209,7 +209,7 @@ public class OneToOneCallPanel
// Lay out the main Components of the UI.
final Container contentPane = frame.getContentPane();
- contentPane.setLayout(new FullScreenLayout(false));
+ contentPane.setLayout(new FullScreenLayout(false, 10));
if (buttonBar != null)
contentPane.add(buttonBar, FullScreenLayout.SOUTH);
if (center != null)
@@ -331,7 +331,7 @@ public class OneToOneCallPanel
*
* @return the buttons bar <tt>Component</tt>
*/
- private Component createFullScreenButtonBar()
+ private JComponent createFullScreenButtonBar()
{
ShowHideVideoButton showHideButton = new ShowHideVideoButton(
call, true, callContainer.isShowHideVideoButtonSelected());
@@ -341,16 +341,17 @@ public class OneToOneCallPanel
Component[] buttons
= new Component[]
{
+ new OutputVolumeControlButton(true).getComponent(),
new InputVolumeControlButton(call, true, callPeer.isMute()),
- new OutputVolumeControlButton(true),
new HoldButton(call,
true,
CallPeerState.isOnHold(callPeer.getState())),
new RecordButton(call, true, callContainer.isRecordingStarted()),
+ new FullScreenButton(callContainer, true),
new LocalVideoButton(
call, true, callContainer.isVideoButtonSelected()),
showHideButton,
- CallPeerRendererUtils.createExitFullScreenButton(this)
+ new HangupButton(callContainer)
};
return CallPeerRendererUtils.createButtonBar(true, buttons);
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
index 7242a22..f60cafd 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OneToOneCallPeerPanel.java
@@ -142,7 +142,7 @@ public class OneToOneCallPeerPanel
/**
* Sound remote level label.
*/
- private OutputVolumeControlButton remoteLevel;
+ private Component remoteLevel;
/**
* The center component.
@@ -356,7 +356,7 @@ public class OneToOneCallPeerPanel
ImageLoader.MUTE_BUTTON,
false, false, false);
remoteLevel = new OutputVolumeControlButton(
- ImageLoader.HEADPHONE, false, false);
+ ImageLoader.HEADPHONE, false, false).getComponent();
final SoundLevelIndicator localLevelIndicator
= new SoundLevelIndicator(
@@ -831,9 +831,8 @@ public class OneToOneCallPeerPanel
localLevel.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.MICROPHONE)));
- if(remoteLevel != null)
- remoteLevel.setIcon(new ImageIcon(
- ImageLoader.getImage(ImageLoader.HEADPHONE)));
+ if(remoteLevel != null && remoteLevel instanceof Skinnable)
+ ((Skinnable) remoteLevel).loadSkin();
if(muteStatusLabel.getIcon() != null)
muteStatusLabel.setIcon(new ImageIcon(
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/OutputVolumeControlButton.java b/src/net/java/sip/communicator/impl/gui/main/call/OutputVolumeControlButton.java
index 78a157d..13b6771 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/OutputVolumeControlButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/OutputVolumeControlButton.java
@@ -14,6 +14,7 @@ import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.resources.*;
+import net.java.sip.communicator.util.*;
import net.java.sip.communicator.util.swing.*;
import org.jitsi.service.neomedia.*;
@@ -26,7 +27,6 @@ import org.jitsi.service.neomedia.*;
* @author Damian Minkov
*/
public class OutputVolumeControlButton
- extends SIPCommButton
{
/**
* The background image.
@@ -44,6 +44,16 @@ public class OutputVolumeControlButton
private ImageID iconImageID;
/**
+ * Indicates if we're in full screen mode.
+ */
+ private final boolean fullScreen;
+
+ /**
+ *
+ */
+ private final boolean inButtonToolBar;
+
+ /**
* Creates not full screen button.
*/
public OutputVolumeControlButton()
@@ -53,68 +63,122 @@ public class OutputVolumeControlButton
/**
* Creates volume control button.
+ *
* @param fullScreen is full screen.
*/
public OutputVolumeControlButton(boolean fullScreen)
{
- this(ImageLoader.VOLUME_CONTROL_BUTTON, fullScreen, false);
+ this(ImageLoader.VOLUME_CONTROL_BUTTON, fullScreen, true);
}
/**
* Creates volume control button.
+ *
* @param iconImageID the image.
* @param fullScreen is full screen.
+ * @param inButtonToolBar indicates if this button is shown in the button
+ * tool bar
*/
public OutputVolumeControlButton(ImageID iconImageID,
boolean fullScreen,
- boolean inSettingsPanel)
+ boolean inButtonToolBar)
{
- super( ImageLoader.getImage(ImageLoader.SOUND_SETTING_BUTTON_PRESSED),
- ImageLoader.getImage(iconImageID));
+ this.fullScreen = fullScreen;
+ this.inButtonToolBar = inButtonToolBar;
- initVolumeControlButton(fullScreen, inSettingsPanel, iconImageID,
- "service.gui.VOLUME_CONTROL_TOOL_TIP");
+ this.iconImageID = iconImageID;
}
/**
- *
- * @param fullScreen
- * @param inSettingsPanel
- * @param iconImageID
- * @param toolTipTextKey
+ * Returns the component associated with this output volume control button.
+ *
+ * @return the component associated with this output volume control button
*/
- public void initVolumeControlButton(final boolean fullScreen,
- boolean inSettingsPanel,
- ImageID iconImageID,
- String toolTipTextKey)
+ public Component getComponent()
{
- this.iconImageID = iconImageID;
-
- if (fullScreen)
- {
- bgImage = ImageLoader.FULL_SCREEN_BUTTON_BG;
- pressedImage = ImageLoader.FULL_SCREEN_BUTTON_BG_PRESSED;
- }
+ if (!fullScreen)
+ return createVolumeControlButton(
+ inButtonToolBar,
+ iconImageID,
+ "service.gui.VOLUME_CONTROL_TOOL_TIP");
else
+ return createSliderComponent();
+ }
+
+ /**
+ * Creates the slider component for the full screen interface.
+ *
+ * @return the created component
+ */
+ public Component createSliderComponent()
+ {
+ final Color bgColor
+ = new Color(GuiActivator.getResources().getColor(
+ "service.gui.CALL_TOOL_BAR_SOUND_BG"));
+
+ @SuppressWarnings("serial")
+ TransparentPanel soundPanel = new TransparentPanel(
+ new FlowLayout(FlowLayout.LEFT, 0, 0))
{
- if(inSettingsPanel)
+ public void paintComponent(Graphics g)
{
- bgImage = ImageLoader.CALL_SETTING_BUTTON_BG;
- pressedImage = ImageLoader.CALL_SETTING_BUTTON_PRESSED_BG;
- }
- else
- {
- bgImage = ImageLoader.SOUND_SETTING_BUTTON_BG;
- pressedImage = ImageLoader.SOUND_SETTING_BUTTON_PRESSED;
+ super.paintComponent(g);
+
+ g = g.create();
+
+ AntialiasingManager.activateAntialiasing(g);
+
+ try
+ {
+ g.setColor(bgColor);
+
+ g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 8, 8);
+ }
+ finally
+ {
+ g.dispose();
+ }
}
- }
+ };
+
+ soundPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
+ final VolumeControl volumeControl
+ = GuiActivator.getMediaService().getOutputVolumeControl();
+
+ // Creates the menu that would contain the volume control component.
+ VolumeControlSlider slider
+ = new VolumeControlSlider(volumeControl, JSlider.HORIZONTAL);
+
+ soundPanel.add(new JLabel(GuiActivator.getResources()
+ .getImage("service.gui.icons.NO_SOUND_ICON")));
+ soundPanel.add(slider);
+ soundPanel.add(new JLabel(GuiActivator.getResources()
+ .getImage("service.gui.icons.SOUND_MENU_ICON")));
+
+ return soundPanel;
+ }
+
+ /**
+ * Initializes the volume control button.
+ *
+ * @param fullScreen indicates if we're in fullscreen mode
+ * @param isButtonBar indicates if this button is shown in the button
+ * toolbar
+ * @param iconImageID the identifier of the button icon
+ * @param toolTipTextKey the key of the tool tip text
+ */
+ public Component createVolumeControlButton( boolean isButtonBar,
+ ImageID iconImageID,
+ String toolTipTextKey)
+ {
+ this.iconImageID = iconImageID;
- // Loads the skin of this button.
- loadSkin();
+ final SIPCommButton volumeControlButton
+ = new VolumeControlButton(isButtonBar);
if (toolTipTextKey != null)
{
- setToolTipText(
+ volumeControlButton.setToolTipText(
GuiActivator.getResources().getI18NString(toolTipTextKey));
}
@@ -122,40 +186,78 @@ public class OutputVolumeControlButton
= GuiActivator.getMediaService().getOutputVolumeControl();
// Creates the menu that would contain the volume control component.
- final VolumeControlSlider sliderMenu
- = new VolumeControlSlider(volumeControl);
+ final JPopupMenu sliderMenu
+ = new VolumeControlSlider(volumeControl, JSlider.VERTICAL)
+ .getPopupMenu();
- sliderMenu.setInvoker(this);
+ sliderMenu.setInvoker(volumeControlButton);
- this.addActionListener(new ActionListener()
+ volumeControlButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
- Point location = new Point(getX(), getY() + getHeight());
+ Point location = new Point(
+ volumeControlButton.getX(),
+ volumeControlButton.getY()
+ + volumeControlButton.getHeight());
- SwingUtilities.convertPointToScreen(location,
- OutputVolumeControlButton.this.getParent());
-
- if(fullScreen)
- location.setLocation(location.getX(),
- location.getY()
- - sliderMenu.getPreferredSize().getHeight()
- - getHeight());
+ SwingUtilities.convertPointToScreen(
+ location,
+ volumeControlButton.getParent());
sliderMenu.setLocation(location);
sliderMenu.setVisible(!sliderMenu.isVisible());
}
});
+
+ return volumeControlButton;
}
/**
- * Loads images.
+ * The <tt>VolumeControlButton</tt>
*/
- public void loadSkin()
+ @SuppressWarnings("serial")
+ private class VolumeControlButton
+ extends SIPCommButton
{
- setBackgroundImage(ImageLoader.getImage(bgImage));
- setPressedImage(ImageLoader.getImage(pressedImage));
- setIconImage(ImageLoader.getImage(iconImageID));
+ public VolumeControlButton(boolean inSettingsPanel)
+ {
+ super(
+ ImageLoader.getImage(ImageLoader.SOUND_SETTING_BUTTON_PRESSED),
+ ImageLoader.getImage(iconImageID));
+
+ if(inSettingsPanel)
+ {
+ bgImage = ImageLoader.CALL_SETTING_BUTTON_BG;
+ pressedImage = ImageLoader.CALL_SETTING_BUTTON_PRESSED_BG;
+ }
+ else
+ {
+ bgImage = ImageLoader.SOUND_SETTING_BUTTON_BG;
+ pressedImage = ImageLoader.SOUND_SETTING_BUTTON_PRESSED;
+ }
+
+ // Loads the skin of this button.
+ loadSkin();
+ }
+
+ /**
+ * Loads images.
+ */
+ public void loadSkin()
+ {
+ setBackgroundImage(ImageLoader.getImage(bgImage));
+ setPressedImage(ImageLoader.getImage(pressedImage));
+
+ if (iconImageID != null)
+ {
+ if (!fullScreen && !inButtonToolBar)
+ setIconImage(ImageUtils.scaleImageWithinBounds(
+ ImageLoader.getImage(iconImageID), 18, 18));
+ else
+ setIconImage(ImageLoader.getImage(iconImageID));
+ }
+ }
}
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/TransferCallButton.java b/src/net/java/sip/communicator/impl/gui/main/call/TransferCallButton.java
index 127a193..6f31bec 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/TransferCallButton.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/TransferCallButton.java
@@ -12,8 +12,6 @@ import java.util.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
-import net.java.sip.communicator.util.skin.*;
-import net.java.sip.communicator.util.swing.*;
/**
* Represents an UI means to transfer (the <tt>Call</tt> of) an associated
@@ -24,8 +22,7 @@ import net.java.sip.communicator.util.swing.*;
* @author Adam Netocny
*/
public class TransferCallButton
- extends SIPCommButton
- implements Skinnable
+ extends CallToolBarButton
{
/**
* The <tt>Call</tt> to be transfered.
@@ -42,14 +39,12 @@ public class TransferCallButton
*/
public TransferCallButton(Call c)
{
- super( ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
- ImageLoader.getImage(ImageLoader.TRANSFER_CALL_BUTTON));
+ super( ImageLoader.getImage(ImageLoader.TRANSFER_CALL_BUTTON),
+ GuiActivator.getResources().getI18NString(
+ "service.gui.TRANSFER_BUTTON_TOOL_TIP"));
this.call = c;
- setToolTipText(GuiActivator.getResources().getI18NString(
- "service.gui.TRANSFER_BUTTON_TOOL_TIP"));
-
OperationSetAdvancedTelephony<?> telephony =
call.getProtocolProvider()
.getOperationSet(OperationSetAdvancedTelephony.class);
@@ -131,16 +126,4 @@ public class TransferCallButton
}
return transferCalls;
}
-
- /**
- * Reloads icons.
- */
- public void loadSkin()
- {
- this.setBackgroundImage(ImageLoader.getImage(
- ImageLoader.CALL_SETTING_BUTTON_BG));
-
- this.setIconImage(ImageLoader.getImage(
- ImageLoader.TRANSFER_CALL_BUTTON));
- }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlSlider.java b/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlSlider.java
index 9f8d2f2..e6e19d0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlSlider.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/VolumeControlSlider.java
@@ -22,7 +22,7 @@ import org.jitsi.service.neomedia.event.*;
* @author Yana Stamcheva
*/
public class VolumeControlSlider
- extends SIPCommPopupMenu
+ extends TransparentPanel
implements VolumeChangeListener
{
private final JSlider volumeSlider;
@@ -41,12 +41,19 @@ public class VolumeControlSlider
* @param volumeControl the <tt>VolumeControl</tt> that do the actual volume
* adjusting.
*/
- public VolumeControlSlider(final VolumeControl volumeControl)
+ public VolumeControlSlider( final VolumeControl volumeControl,
+ int orientation)
{
+ super(new BorderLayout());
+
volumeControl.addVolumeChangeListener(this);
- volumeSlider = new JSlider(JSlider.VERTICAL, 0, 100, 50);
- volumeSlider.setPreferredSize(new Dimension(20, 100));
+ volumeSlider = new JSlider(orientation, 0, 100, 50);
+
+ if (orientation == JSlider.VERTICAL)
+ volumeSlider.setPreferredSize(new Dimension(20, 100));
+ else
+ volumeSlider.setPreferredSize(new Dimension(100, 20));
// Sets the minimum, maximum and default volume values for the volume
// slider.
@@ -83,4 +90,18 @@ public class VolumeControlSlider
if (volumeSlider.getValue() != newValue)
volumeSlider.setValue(newValue);
}
+
+ /**
+ * Returns this slider in a popup menu.
+ *
+ * @return this slider in a popup menu
+ */
+ public JPopupMenu getPopupMenu()
+ {
+ SIPCommPopupMenu popupMenu = new SIPCommPopupMenu();
+
+ popupMenu.add(this);
+
+ return popupMenu;
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationComponent.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationComponent.java
index e25a9af..2191697 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationComponent.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationComponent.java
@@ -296,7 +296,7 @@ public abstract class ChatConversationComponent
*/
public String getDateString(Date date)
{
- return ChatConversationPanel.getDateString(date.getTime())
+ return ChatHtmlUtils.getDateString(date.getTime())
+ GuiUtils.formatTime(date)
+ " ";
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java
index fba0eee..3ec57fa 100755
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java
@@ -23,11 +23,11 @@ import javax.swing.text.html.*;
import javax.swing.text.html.HTML.*;
import net.java.sip.communicator.impl.gui.*;
-import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.main.chat.history.*;
import net.java.sip.communicator.impl.gui.main.chat.menus.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.replacement.*;
import net.java.sip.communicator.service.replacement.smilies.*;
import net.java.sip.communicator.util.*;
@@ -61,16 +61,6 @@ public class ChatConversationPanel
= Logger.getLogger(ChatConversationPanel.class);
/**
- * The closing tag of the <code>PLAINTEXT</code> HTML element.
- */
- private static final String END_PLAINTEXT_TAG = "</PLAINTEXT>";
-
- /**
- * The opening tag of the <code>PLAINTEXT</code> HTML element.
- */
- private static final String START_PLAINTEXT_TAG = "<PLAINTEXT>";
-
- /**
* The regular expression (in the form of compiled <tt>Pattern</tt>) which
* matches URLs for the purposed of turning them into links.
*/
@@ -141,19 +131,14 @@ public class ChatConversationPanel
private long lastIncomingMsgTimestamp;
/**
- * Indicates if this component is rendering a history conversation.
+ * The timestamp of the last message.
*/
- private final boolean isHistory;
+ private long lastMessageTimestamp;
/**
- * The html text content type.
- */
- public static final String HTML_CONTENT_TYPE = "text/html";
-
- /**
- * The plain text content type.
+ * Indicates if this component is rendering a history conversation.
*/
- public static final String TEXT_CONTENT_TYPE = "text/plain";
+ private final boolean isHistory;
/**
* The indicator which determines whether an automatic scroll to the bottom
@@ -161,6 +146,8 @@ public class ChatConversationPanel
*/
private boolean scrollToBottomIsPending = false;
+ private String lastMessageUID = null;
+
/**
* The implementation of the routine which scrolls {@link #chatTextPane} to its
* bottom.
@@ -339,32 +326,6 @@ public class ChatConversationPanel
}
/**
- * Initializes the editor by adding a header containing the date.
- * TODO: remove if not used anymore
- */
-// private void initEditor()
-// {
-// Element root = this.document.getDefaultRootElement();
-//
-// Date date = new Date(System.currentTimeMillis());
-//
-// String chatHeader = "<h1>" + GuiUtils.formatDate(date) + " " + "</h1>";
-//
-// try
-// {
-// this.document.insertAfterStart(root, chatHeader);
-// }
-// catch (BadLocationException e)
-// {
-// logger.error("Insert in the HTMLDocument failed.", e);
-// }
-// catch (IOException e)
-// {
-// logger.error("Insert in the HTMLDocument failed.", e);
-// }
-// }
-
- /**
* Retrieves the contents of the sent message with the given ID.
*
* @param messageUID The ID of the message to retrieve.
@@ -373,7 +334,11 @@ public class ChatConversationPanel
public String getMessageContents(String messageUID)
{
Element root = document.getDefaultRootElement();
- Element e = document.getElement(root, Attribute.ID, messageUID);
+ Element e = document.getElement(
+ root,
+ Attribute.ID,
+ ChatHtmlUtils.MESSAGE_TEXT_ID + messageUID);
+
if (e == null)
{
logger.warn("Could not find message with ID" + messageUID);
@@ -395,38 +360,6 @@ public class ChatConversationPanel
}
/**
- * Creates a tag that shows the last edit time of a message, in the format
- * (Edited at ...).
- * If <tt>date < 0</tt>, returns an empty tag that serves as a placeholder
- * for future corrections of this message.
- *
- * @param messageUID The ID of the edited message.
- * @param date The date when the message was last edited, or -1 to generate
- * an empty tag.
- * @return The string representation of the tag.
- */
- private String generateEditedAtTag(String messageUID, long date)
- {
- StringBuilder res = new StringBuilder();
- // Use a <cite /> tag here as most of the other inline tags (e.g. h1-7,
- // b, i) cause different problems when used in setOuterHTML.
- res.append("<cite id='");
- res.append(messageUID);
- res.append("-editedAt'> ");
- if (date > 0)
- {
- res.append("&nbsp;");
- String contents = GuiActivator.getResources().getI18NString(
- "service.gui.EDITED_AT",
- new String[] { GuiUtils.formatTime(date) }
- );
- res.append(contents);
- }
- res.append("</cite>");
- return res.toString();
- }
-
- /**
* Processes the message given by the parameters.
*
* @param chatMessage the message
@@ -434,8 +367,20 @@ public class ChatConversationPanel
* display of <tt>chatMessage</tt> in the UI
* @return the processed message
*/
- public String processMessage(ChatMessage chatMessage, String keyword)
+ public String processMessage( ChatMessage chatMessage,
+ String keyword,
+ ProtocolProviderService protocolProvider,
+ String contactAddress)
{
+ String contentType = chatMessage.getContentType();
+
+ // If this is a consecutive message don't go through the initiation
+ // and just append it.
+ if (appendConsecutiveMessage(chatMessage, keyword, contentType))
+ return null;
+
+ lastMessageTimestamp = chatMessage.getDate();
+
String contactName = chatMessage.getContactName();
String contactDisplayName = chatMessage.getContactDisplayName();
if (contactDisplayName == null
@@ -445,99 +390,88 @@ public class ChatConversationPanel
{
// for some reason &apos; is not rendered correctly from our ui,
// lets use its equivalent. Other similar chars(< > & ") seem ok.
- contactDisplayName = contactDisplayName.replaceAll("&apos;", "&#39;");
+ contactDisplayName
+ = contactDisplayName.replaceAll("&apos;", "&#39;");
}
- String contentType = chatMessage.getContentType();
long date = chatMessage.getDate();
String messageType = chatMessage.getMessageType();
String messageTitle = chatMessage.getMessageTitle();
- String message = chatMessage.getMessage();
String messageUID = chatMessage.getMessageUID();
-
- String msgID = "message";
- String msgHeaderID = "messageHeader";
+ String message = chatMessage.getMessage();
+ String msgID = ChatHtmlUtils.MESSAGE_TEXT_ID + messageUID;
String chatString = "";
String endHeaderTag = "";
- String dateString = getDateString(date);
- String idAttr = messageUID == null ? "" : " id='" + messageUID + "'";
- String dateAttr = " date='" + date + "'";
- String editedAtTag = generateEditedAtTag(messageUID, -1);
-
- String startDivTag = "<DIV identifier=\"" + msgID + "\"" + idAttr + ">";
- String startHistoryDivTag
- = "<DIV identifier=\"" + msgID + "\" style=\"color:#707070;\">";
+
String startSystemDivTag
= "<DIV identifier=\"systemMessage\" style=\"color:#627EB7;\">";
String endDivTag = "</DIV>";
- String startPlainTextTag;
- String endPlainTextTag;
+ lastMessageUID = messageUID;
- if (HTML_CONTENT_TYPE.equals(contentType))
+ String startPlainTextTag
+ = ChatHtmlUtils.createStartPlainTextTag(contentType);
+ String endPlainTextTag
+ = ChatHtmlUtils.createEndPlainTextTag(contentType);
+
+ if (messageType.equals(Chat.INCOMING_MESSAGE))
{
- startPlainTextTag = "";
- endPlainTextTag = "";
+ this.lastIncomingMsgTimestamp = System.currentTimeMillis();
+
+ chatString = ChatHtmlUtils.createIncomingMessageTag(
+ msgID,
+ contactName,
+ contactDisplayName,
+ getContactAvatar(protocolProvider, contactAddress),
+ date,
+ formatMessage(message, contentType, keyword),
+ contentType);
}
- else
+ else if (messageType.equals(Chat.OUTGOING_MESSAGE))
{
- startPlainTextTag = START_PLAINTEXT_TAG;
- endPlainTextTag = END_PLAINTEXT_TAG;
+ chatString = ChatHtmlUtils.createOutgoingMessageTag(
+ msgID,
+ contactName,
+ contactDisplayName,
+ getContactAvatar(protocolProvider),
+ date,
+ formatMessage(message, contentType, keyword),
+ contentType);
}
-
- if (messageType.equals(Chat.INCOMING_MESSAGE))
+ else if (messageType.equals(Chat.HISTORY_INCOMING_MESSAGE))
{
this.lastIncomingMsgTimestamp = System.currentTimeMillis();
- chatString = "<h2 identifier=\"" + msgHeaderID + "\""
- + dateAttr + ">"
- + "<a style=\"color:#ef7b1e;"
- + "font-weight:bold;"
- + "text-decoration:none;\" "
- + "href=\"" + contactName + "\">";
-
- endHeaderTag = "</a></h2>";
-
- chatString
- += dateString + contactDisplayName + " at "
- + GuiUtils.formatTime(date) + editedAtTag + endHeaderTag
- + startDivTag + startPlainTextTag
- + formatMessage(message, contentType, keyword)
- + endPlainTextTag + endDivTag;
+ chatString = ChatHtmlUtils.createIncomingMessageTag(
+ msgID,
+ contactName,
+ contactDisplayName,
+ getContactAvatar(protocolProvider, contactAddress),
+ date,
+ formatMessage(message, contentType, keyword),
+ contentType);
}
- else if (messageType.equals(Chat.SMS_MESSAGE))
+ else if (messageType.equals(Chat.HISTORY_OUTGOING_MESSAGE))
{
- chatString = "<h2 identifier=\""
- + msgHeaderID
- + "\" date=\""
- + date + "\">";
-
- endHeaderTag = "</h2>";
-
- chatString
- += "SMS: " + dateString + contactName + " at "
- + GuiUtils.formatTime(date) + endHeaderTag + startDivTag
- + startPlainTextTag
- + formatMessage(message, contentType, keyword)
- + endPlainTextTag + endDivTag;
+ chatString = ChatHtmlUtils.createOutgoingMessageTag(
+ msgID,
+ contactName,
+ contactDisplayName,
+ getContactAvatar(protocolProvider),
+ date,
+ formatMessage(message, contentType, keyword),
+ contentType);
}
- else if (messageType.equals(Chat.OUTGOING_MESSAGE))
+ else if (messageType.equals(Chat.SMS_MESSAGE))
{
- chatString = "<h3 identifier=\"" + msgHeaderID + "\""
- + dateAttr + ">"
- + "<a style=\"color:#2e538b;"
- + "font-weight:bold;"
- + "text-decoration:none;\" "
- + "href=\"" + contactName + "\">";
-
- endHeaderTag = "</a></h3>";
-
- chatString
- += dateString + contactDisplayName + " at "
- + GuiUtils.formatTime(date) + editedAtTag + endHeaderTag
- + startDivTag + startPlainTextTag
- + formatMessage(message, contentType, keyword)
- + endPlainTextTag + endDivTag;
+ chatString = ChatHtmlUtils.createIncomingMessageTag(
+ msgID,
+ contactName,
+ contactDisplayName,
+ getContactAvatar(protocolProvider, contactAddress),
+ date,
+ formatMessage("SMS: " + message, contentType, keyword),
+ contentType);
}
else if (messageType.equals(Chat.STATUS_MESSAGE))
{
@@ -570,7 +504,7 @@ public class ChatConversationPanel
else if (messageType.equals(Chat.ERROR_MESSAGE))
{
chatString = "<h6 identifier=\""
- + msgHeaderID
+ + ChatHtmlUtils.MESSAGE_HEADER_ID
+ "\" date=\""
+ date + "\">";
@@ -584,43 +518,6 @@ public class ChatConversationPanel
+ messageTitle
+ endHeaderTag + "<h5>" + message + "</h5>";
}
- else if (messageType.equals(Chat.HISTORY_INCOMING_MESSAGE))
- {
- chatString = "<h2 identifier=\"" + msgHeaderID + "\""
- + dateAttr + ">"
- + "<a style=\"color:#ef7b1e;"
- + "font-weight:bold;"
- + "text-decoration:none;\" "
- + "href=\"" + contactName + "\">";
-
- endHeaderTag = "</a></h2>";
-
- chatString
- += dateString + contactDisplayName
- + " at " + GuiUtils.formatTime(date) + endHeaderTag
- + editedAtTag + startHistoryDivTag + startPlainTextTag
- + formatMessage(message, contentType, keyword)
- + endPlainTextTag + endDivTag;
- }
- else if (messageType.equals(Chat.HISTORY_OUTGOING_MESSAGE))
- {
- chatString = "<h3 identifier=\"" + msgHeaderID + "\""
- + dateAttr + ">"
- + "<a style=\"color:#2e538b;"
- + "font-weight:bold;"
- + "text-decoration:none;\" "
- + "href=\"" + contactName + "\">";
-
- endHeaderTag = "</h3>";
-
- chatString
- += dateString
- + contactDisplayName + " at " + GuiUtils.formatTime(date)
- + editedAtTag + endHeaderTag
- + startHistoryDivTag + startPlainTextTag
- + formatMessage(message, contentType, keyword)
- + endPlainTextTag + endDivTag;
- }
return chatString;
}
@@ -631,9 +528,91 @@ public class ChatConversationPanel
* @param chatMessage the message.
* @return the formatted message
*/
- public String processMessage(ChatMessage chatMessage)
+ public String processMessage( ChatMessage chatMessage,
+ ProtocolProviderService protocolProvider,
+ String contactAddress)
+ {
+ return processMessage( chatMessage,
+ null,
+ protocolProvider,
+ contactAddress);
+ }
+
+ /**
+ * Appends a consecutive message to the document.
+ *
+ * @param chatMessage the message to append
+ * @return <tt>true</tt> if the append succeeded, <tt>false</tt> - otherwise
+ */
+ public boolean appendConsecutiveMessage(ChatMessage chatMessage,
+ String keyword,
+ String contentType)
{
- return processMessage(chatMessage, null);
+ if (lastMessageUID == null)
+ return false;
+
+ Element root = document.getDefaultRootElement();
+ Element lastMsgElement = document.getElement(root, Attribute.ID,
+ ChatHtmlUtils.MESSAGE_TEXT_ID + lastMessageUID);
+
+ if (lastMsgElement == null)
+ {
+ logger.warn("Could not find message with ID " + lastMessageUID);
+ return false;
+ }
+
+ String contactAddress
+ = (String) lastMsgElement.getAttributes()
+ .getAttribute(Attribute.NAME);
+
+ if (contactAddress != null
+ && contactAddress.equals(chatMessage.getContactName())
+ // And if the new message is within a minute from the last one.
+ && (chatMessage.getDate() - lastMessageTimestamp
+ < 60000))
+ {
+ String newMessage = ChatHtmlUtils.createMessageTag(
+ ChatHtmlUtils.MESSAGE_TEXT_ID
+ + chatMessage.getMessageUID(),
+ contactAddress,
+ formatMessage(chatMessage.getMessage(),
+ contentType,
+ keyword),
+ contentType,
+ chatMessage.getDate(),
+ false);
+
+ synchronized (scrollToBottomRunnable)
+ {
+ try
+ {
+ Element parentElement = lastMsgElement.getParentElement();
+
+ document.insertBeforeEnd(parentElement, newMessage);
+
+ lastMessageUID = chatMessage.getMessageUID();
+
+ // Need to call explicitly scrollToBottom, because for some
+ // reason the componentResized event isn't fired every time
+ // we add text.
+ SwingUtilities.invokeLater(scrollToBottomRunnable);
+ }
+ catch (BadLocationException ex)
+ {
+ logger.error("Could not replace chat message", ex);
+ }
+ catch (IOException ex)
+ {
+ logger.error("Could not replace chat message", ex);
+ }
+ }
+
+ finishMessageAdd(newMessage, contentType);
+
+ return true;
+ }
+
+ return false;
}
/**
@@ -647,82 +626,78 @@ public class ChatConversationPanel
{
String correctedUID = chatMessage.getCorrectedMessageUID();
Element root = document.getDefaultRootElement();
- Element e = document.getElement(root, Attribute.ID, correctedUID);
- if (e == null)
+ Element correctedMsgElement
+ = document.getElement(root,
+ Attribute.ID,
+ ChatHtmlUtils.MESSAGE_TEXT_ID + correctedUID);
+
+ if (correctedMsgElement == null)
{
logger.warn("Could not find message with ID " + correctedUID);
return;
}
- int len = e.getEndOffset() - e.getStartOffset();
-
- StringBuilder newContents = new StringBuilder();
- String bgColor = GuiActivator.getResources().getColorString(
- "service.gui.CHAT_EDIT_MESSAGE_BACKGROUND");
- newContents.append("<div identifier='message' id='");
- newContents.append(chatMessage.getMessageUID());
- newContents.append("' bgcolor='");
- newContents.append(bgColor);
- newContents.append("'>");
- if (chatMessage.getContentType().equals(TEXT_CONTENT_TYPE))
- {
- newContents.append(START_PLAINTEXT_TAG);
- newContents.append(chatMessage.getMessage());
- newContents.append(END_PLAINTEXT_TAG);
- }
- else
- {
- newContents.append(chatMessage.getMessage());
- }
- newContents.append("</div>");
-
- Element header = document.getElement(root, Attribute.ID,
- correctedUID + "-editedAt");
-
- try
+
+ String contactAddress
+ = (String) correctedMsgElement.getAttributes()
+ .getAttribute(Attribute.NAME);
+
+ String newMessage = ChatHtmlUtils.createMessageTag(
+ ChatHtmlUtils.MESSAGE_TEXT_ID
+ + chatMessage.getMessageUID(),
+ contactAddress,
+ formatMessage( chatMessage.getMessage(),
+ chatMessage.getContentType(),
+ ""),
+ chatMessage.getContentType(),
+ chatMessage.getDate(),
+ true);
+
+ synchronized (scrollToBottomRunnable)
{
- if (header != null)
+ try
{
- String newHeaderContents = generateEditedAtTag(
- chatMessage.getMessageUID(), chatMessage.getDate());
- document.setOuterHTML(header, newHeaderContents);
+ document.setOuterHTML(correctedMsgElement, newMessage);
+
+ lastMessageUID = chatMessage.getMessageUID();
+
+ // Need to call explicitly scrollToBottom, because for some
+ // reason the componentResized event isn't fired every time
+ // we add text.
+ SwingUtilities.invokeLater(scrollToBottomRunnable);
+ }
+ catch (BadLocationException ex)
+ {
+ logger.error("Could not replace chat message", ex);
+ }
+ catch (IOException ex)
+ {
+ logger.error("Could not replace chat message", ex);
}
- document.setOuterHTML(e, newContents.toString());
- }
- catch (BadLocationException ex)
- {
- logger.error("Could not replace chat message", ex);
- }
- catch (IOException ex)
- {
- logger.error("Could not replace chat message", ex);
}
+
+ finishMessageAdd(newMessage, chatMessage.getContentType());
}
/**
* Appends the given string at the end of the contained in this panel
* document.
*
- * @param chatString the string to append
+ * @param message the message string to append
*/
- public void appendMessageToEnd(String chatString, String contentType)
+ public void appendMessageToEnd(String message, String contentType)
{
+ if (message == null)
+ return;
+
synchronized (scrollToBottomRunnable)
{
Element root = document.getDefaultRootElement();
-// Need to call explicitly scrollToBottom, because for some
-// reason the componentResized event isn't fired every time we
-// add text.
-// Replaced by the code on line: 573.
-//
-// scrollToBottomIsPending = true;
-
try
{
- document
- .insertAfterEnd(
- root.getElement(root.getElementCount() - 1),
- chatString);
+ document.insertAfterEnd(
+ root.getElement(root.getElementCount() - 1),
+ message);
// Need to call explicitly scrollToBottom, because for some
// reason the componentResized event isn't fired every time we
@@ -737,33 +712,44 @@ public class ChatConversationPanel
{
logger.error("Insert in the HTMLDocument failed.", e);
}
- if (!isHistory)
- ensureDocumentSize();
+ }
- // Process replacements.
- final Element elem;
- /*
- * Check to make sure element isn't the first element in the HTML
- * document.
- */
- if (!(root.getElementCount() < 2))
- {
- elem = root.getElement(root.getElementCount() - 2);
- }
- else
- elem = root.getElement(1);
+ finishMessageAdd(message, contentType);
+ }
- /*
- * Replacements will be processed only if it is enabled in the
- * property
- */
- if (GuiActivator.getConfigurationService().getBoolean(
- ReplacementProperty.REPLACEMENT_ENABLE, true)
- || GuiActivator.getConfigurationService().getBoolean(
- ReplacementProperty.getPropertyName("SMILEY"), true))
- {
- processReplacement(elem, chatString, contentType);
- }
+ /**
+ * Performs all operations needed in order to finish the adding of the
+ * message to the document.
+ *
+ * @param message the message string
+ * @param contentType
+ */
+ private void finishMessageAdd(String message, String contentType)
+ {
+ Element root = document.getDefaultRootElement();
+
+ // If we're not in chat history case we need to be sure the document
+ // has not exceeded the required size (number of messages).
+ if (!isHistory)
+ ensureDocumentSize();
+
+ /*
+ * Check to make sure element isn't the first element in the HTML
+ * document.
+ */
+ Element elem = document.getElement(root, Attribute.ID,
+ ChatHtmlUtils.MESSAGE_TEXT_ID + lastMessageUID);
+
+ /*
+ * Replacements will be processed only if it is enabled in the
+ * property.
+ */
+ if (GuiActivator.getConfigurationService().getBoolean(
+ ReplacementProperty.REPLACEMENT_ENABLE, true)
+ || GuiActivator.getConfigurationService().getBoolean(
+ ReplacementProperty.getPropertyName("SMILEY"), true))
+ {
+ processReplacement(elem, message, contentType);
}
}
@@ -818,15 +804,6 @@ public class ChatConversationPanel
Matcher m = p.matcher(msgStore);
- String startPlainTextTag = "";
- String endPlainTextTag = "";
-
- if (!HTML_CONTENT_TYPE.equals(contentType))
- {
- startPlainTextTag = START_PLAINTEXT_TAG;
- endPlainTextTag = END_PLAINTEXT_TAG;
- }
-
int count = 0, startPos = 0;
StringBuffer msgBuff = new StringBuffer();
@@ -843,7 +820,9 @@ public class ChatConversationPanel
{
if(isSmiley)
{
- msgBuff.append(endPlainTextTag);
+ msgBuff.append(
+ ChatHtmlUtils.createEndPlainTextTag(
+ contentType));
msgBuff.append("<IMG SRC=\"");
}
else
@@ -858,7 +837,9 @@ public class ChatConversationPanel
msgBuff.append("\"></IMG>");
if(isSmiley)
- msgBuff.append(startPlainTextTag);
+ msgBuff.append(
+ ChatHtmlUtils.createStartPlainTextTag(
+ contentType));
}
else
{
@@ -884,8 +865,12 @@ public class ChatConversationPanel
synchronized (scrollToBottomRunnable)
{
scrollToBottomIsPending = true;
+
+ int msgStartIndex = msgStore.indexOf("<div id");
document.setOuterHTML(elem, msgStore.toString()
- .substring(msgStore.indexOf("<DIV")));
+ .substring(
+ msgStartIndex,
+ msgStore.indexOf("</div>", msgStartIndex)));
}
}
return "";
@@ -916,7 +901,7 @@ public class ChatConversationPanel
.getAttributes().getAttribute("identifier");
if(idAttr != null
- && (idAttr.equals("message")
+ && (idAttr.startsWith(ChatHtmlUtils.MESSAGE_TEXT_ID)
|| idAttr.equals("statusMessage")
|| idAttr.equals("systemMessage")))
{
@@ -940,7 +925,8 @@ public class ChatConversationPanel
// Remove the header of the message if such exists.
if(firstMsgIndex > 0)
{
- Element headerElement = rootElement.getElement(firstMsgIndex - 1);
+ Element headerElement
+ = rootElement.getElement(firstMsgIndex - 1);
String idAttr = (String) headerElement
.getAttributes().getAttribute("identifier");
@@ -977,20 +963,6 @@ public class ChatConversationPanel
String contentType,
String keyword)
{
- String startPlainTextTag;
- String endPlainTextTag;
-
- if (HTML_CONTENT_TYPE.equals(contentType))
- {
- startPlainTextTag = "";
- endPlainTextTag = "";
- }
- else
- {
- startPlainTextTag = START_PLAINTEXT_TAG;
- endPlainTextTag = END_PLAINTEXT_TAG;
- }
-
Matcher m
= Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE)
.matcher(message);
@@ -1004,11 +976,11 @@ public class ChatConversationPanel
String keywordMatch = m.group().trim();
- msgBuffer.append(endPlainTextTag);
+ msgBuffer.append(ChatHtmlUtils.createEndPlainTextTag(contentType));
msgBuffer.append("<b>");
msgBuffer.append(keywordMatch);
msgBuffer.append("</b>");
- msgBuffer.append(startPlainTextTag);
+ msgBuffer.append(ChatHtmlUtils.createStartPlainTextTag(contentType));
}
/*
@@ -1037,7 +1009,7 @@ public class ChatConversationPanel
{
// If the message content type is HTML we won't process links and
// new lines, but only the smileys.
- if (!HTML_CONTENT_TYPE.equals(contentType))
+ if (!ChatHtmlUtils.HTML_CONTENT_TYPE.equals(contentType))
{
/*
@@ -1065,7 +1037,8 @@ public class ChatConversationPanel
message
= processNewLines(
- processLinksAndHTMLChars(message, processHTMLChars));
+ processLinksAndHTMLChars(
+ message, processHTMLChars, contentType), contentType);
}
// If the message content is HTML, we process br and img tags.
else
@@ -1090,10 +1063,12 @@ public class ChatConversationPanel
* @param message The source message string.
* @param processHTMLChars <tt>true</tt> to escape the special HTML chars;
* otherwise, <tt>false</tt>
+ * @param contentType the message content type (html or plain text)
* @return The message string with properly formatted links.
*/
private String processLinksAndHTMLChars(String message,
- boolean processHTMLChars)
+ boolean processHTMLChars,
+ String contentType)
{
Matcher m = URL_PATTERN.matcher(message);
StringBuffer msgBuffer = new StringBuffer();
@@ -1110,7 +1085,7 @@ public class ChatConversationPanel
String url = m.group().trim();
- msgBuffer.append(END_PLAINTEXT_TAG);
+ msgBuffer.append(ChatHtmlUtils.createEndPlainTextTag(contentType));
msgBuffer.append("<A href=\"");
if (url.startsWith("www"))
msgBuffer.append("http://");
@@ -1118,7 +1093,7 @@ public class ChatConversationPanel
msgBuffer.append("\">");
msgBuffer.append(url);
msgBuffer.append("</A>");
- msgBuffer.append(START_PLAINTEXT_TAG);
+ msgBuffer.append(ChatHtmlUtils.createStartPlainTextTag(contentType));
}
String fromPrevEndToEnd = message.substring(prevEnd);
@@ -1151,9 +1126,10 @@ public class ChatConversationPanel
* Formats message new lines.
*
* @param message The source message string.
+ * @param contentType message contentType (html or plain text)
* @return The message string with properly formatted new lines.
*/
- private String processNewLines(String message)
+ private String processNewLines(String message, String contentType)
{
/*
@@ -1171,7 +1147,9 @@ public class ChatConversationPanel
message
.replaceAll(
"\n",
- END_PLAINTEXT_TAG + "<BR/>&#10;" + START_PLAINTEXT_TAG);
+ ChatHtmlUtils.createEndPlainTextTag(contentType)
+ + "<BR/>&#10;"
+ + ChatHtmlUtils.createStartPlainTextTag(contentType));
}
/**
@@ -1508,7 +1486,8 @@ public class ChatConversationPanel
int start = 0;
// while we find some <img /> self-closing tags with a slash inside.
- while(m.find()){
+ while(m.find())
+ {
// First, we have to copy all the message preceding the <img> tag.
processedMessage.append(message.substring(start, m.start()));
// Then, we find the position of the slash inside the tag.
@@ -1577,13 +1556,16 @@ public class ChatConversationPanel
wrapPanel.add(component, BorderLayout.NORTH);
- style
- .addAttribute(StyleConstants.ComponentAttribute, wrapPanel);
+ style.addAttribute(StyleConstants.ComponentAttribute, wrapPanel);
style.addAttribute("identifier", "messageHeader");
style.addAttribute("date", component.getDate().getTime());
scrollToBottomIsPending = true;
+ // We need to reinitialize the last message ID, because we don't
+ // want components to be taken into account.
+ lastMessageUID = null;
+
// Insert the component style at the end of the text
try
{
@@ -1620,26 +1602,6 @@ public class ChatConversationPanel
}
/**
- * Returns the date string to show for the given date.
- *
- * @param date the date to format
- * @return the date string to show for the given date
- */
- public static String getDateString(long date)
- {
- if (GuiUtils.compareDatesOnly(date, System.currentTimeMillis()) < 0)
- {
- StringBuffer dateStrBuf = new StringBuffer();
-
- GuiUtils.formatDate(date, dateStrBuf);
- dateStrBuf.append(" ");
- return dateStrBuf.toString();
- }
-
- return "";
- }
-
- /**
* Reloads images.
*/
public void loadSkin()
@@ -1665,33 +1627,26 @@ public class ChatConversationPanel
{
return processKeyword(message, contentType, keyWord);
}
-
+
+ /**
+ * Processes /me command in group chats.
+ *
+ * @param chatMessage the chat message
+ * @return the newly processed message string
+ */
public String processMeCommand(ChatMessage chatMessage)
{
String contentType = chatMessage.getContentType();
String message = chatMessage.getMessage();
- String msgID = "message";
+ String msgID
+ = ChatHtmlUtils.MESSAGE_TEXT_ID + chatMessage.getMessageUID();
String chatString = "";
String endHeaderTag = "";
- String startDivTag = "<DIV identifier=\"" + msgID + "\">";
+ String startDivTag = "<DIV id=\"" + msgID + "\">";
String endDivTag = "</DIV>";
- String startPlainTextTag;
- String endPlainTextTag;
-
- if (HTML_CONTENT_TYPE.equals(contentType))
- {
- startPlainTextTag = "";
- endPlainTextTag = "";
- }
- else
- {
- startPlainTextTag = START_PLAINTEXT_TAG;
- endPlainTextTag = END_PLAINTEXT_TAG;
- }
-
if (message.length() > 4 && message.substring(0, 4).equals("/me "))
{
chatString = startDivTag + "<B><I>";
@@ -1699,7 +1654,6 @@ public class ChatConversationPanel
endHeaderTag = "</I></B>" + endDivTag;
chatString +=
-
processHTMLChars("*** " + chatMessage.getContactName() + " "
+ message.substring(4))
+ endHeaderTag;
@@ -1731,9 +1685,13 @@ public class ChatConversationPanel
while (m.find())
{
- msgTemp.insert(m.start(), startPlainTextTag);
- msgTemp.insert(m.end() + startPlainTextTag.length(),
- endPlainTextTag);
+ msgTemp.insert(m.start(),
+ ChatHtmlUtils.createStartPlainTextTag(contentType));
+ msgTemp.insert(
+ m.end()
+ + ChatHtmlUtils
+ .createStartPlainTextTag(contentType).length(),
+ ChatHtmlUtils.createEndPlainTextTag(contentType));
}
if (msgTemp.length() != msgStore.length())
@@ -1746,4 +1704,72 @@ public class ChatConversationPanel
else
return "";
}
-}
+
+ /**
+ * Returns the avatar corresponding to the account of the given
+ * <tt>protocolProvider</tt>.
+ *
+ * @param protocolProvider the protocol provider service, which account
+ * avatar we're looking for
+ * @return the avatar corresponding to the account of the given
+ * <tt>protocolProvider</tt>
+ */
+ private static String getContactAvatar(
+ ProtocolProviderService protocolProvider,
+ String contactAddress)
+ {
+ String avatarPath
+ = AvatarCacheUtils.getCachedAvatarPath( protocolProvider,
+ contactAddress);
+
+ File avatarFile;
+ try
+ {
+ avatarFile = GuiActivator.getFileAccessService()
+ .getPrivatePersistentFile(avatarPath);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ if(avatarFile.exists() && avatarFile.length() > 0)
+ return "file:" + avatarFile.getAbsolutePath();
+ else
+ return GuiActivator.getResources().getImageURL(
+ "service.gui.DEFAULT_USER_PHOTO_SMALL").toString();
+ }
+
+ /**
+ * Returns the avatar corresponding to the account of the given
+ * <tt>protocolProvider</tt>.
+ *
+ * @param protocolProvider the protocol provider service, which account
+ * avatar we're looking for
+ * @return the avatar corresponding to the account of the given
+ * <tt>protocolProvider</tt>
+ */
+ private static String getContactAvatar(
+ ProtocolProviderService protocolProvider)
+ {
+ String avatarPath
+ = AvatarCacheUtils.getCachedAvatarPath(protocolProvider);
+
+ File avatarFile;
+ try
+ {
+ avatarFile = GuiActivator.getFileAccessService()
+ .getPrivatePersistentFile(avatarPath);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ if(avatarFile.exists() && avatarFile.length() > 0)
+ return "file:" + avatarFile.getAbsolutePath();
+ else
+ return GuiActivator.getResources().getImageURL(
+ "service.gui.DEFAULT_USER_PHOTO_SMALL").toString();
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatHtmlUtils.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatHtmlUtils.java
new file mode 100644
index 0000000..98293f3
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatHtmlUtils.java
@@ -0,0 +1,412 @@
+/*
+ * 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.impl.gui.main.chat;
+
+import net.java.sip.communicator.impl.gui.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ *
+ * @author Yana Stamcheva
+ */
+public class ChatHtmlUtils
+{
+ /**
+ * The name attribute.
+ */
+ public final static String NAME_ATTRIBUTE = "name";
+
+ /**
+ * The date attribute.
+ */
+ public final static String DATE_ATTRIBUTE = "date";
+
+ /**
+ * The message header identifier attribute.
+ */
+ public final static String MESSAGE_HEADER_ID = "messageHeader";
+
+ /**
+ * The message identifier attribute.
+ */
+ public final static String MESSAGE_TEXT_ID = "message";
+
+ /**
+ * The closing tag of the <code>PLAINTEXT</code> HTML element.
+ */
+ private static final String END_PLAINTEXT_TAG = "</PLAINTEXT>";
+
+ /**
+ * The opening tag of the <code>PLAINTEXT</code> HTML element.
+ */
+ private static final String START_PLAINTEXT_TAG = "<PLAINTEXT>";
+
+ /**
+ * The html text content type.
+ */
+ public static final String HTML_CONTENT_TYPE = "text/html";
+
+ /**
+ * The plain text content type.
+ */
+ public static final String TEXT_CONTENT_TYPE = "text/plain";
+
+ /**
+ * Creates an incoming message tag.
+ *
+ * @param messageID the identifier
+ * @param contactName the name of the contact sending the message
+ * @param contactDisplayName the display name of the contact sending the
+ * message
+ * @param avatarPath the path to the avatar file
+ * @param date the date, when the message was sent
+ * @param message the message content
+ * @param contentType the content type HTML or PLAIN_TEXT
+ * @return the created incoming message tag
+ */
+ public static String createIncomingMessageTag(
+ String messageID,
+ String contactName,
+ String contactDisplayName,
+ String avatarPath,
+ long date,
+ String message,
+ String contentType)
+ {
+ StringBuffer headerBuffer = new StringBuffer();
+
+ headerBuffer.append("<h2 identifier=\"" + MESSAGE_HEADER_ID + "\" ");
+ headerBuffer.append(DATE_ATTRIBUTE + "='" + date + "'" + ">");
+ headerBuffer.append("<a style=\"color:#488fe7;");
+ headerBuffer.append("font-weight:bold;");
+ headerBuffer.append("text-decoration:none;\" ");
+ headerBuffer.append("href=\"" + contactName + "\">");
+ headerBuffer.append(
+ contactDisplayName + createEditedAtTag(messageID, -1));
+ headerBuffer.append("</a></h2>");
+
+ StringBuffer messageBuff = new StringBuffer();
+
+ messageBuff.append("<div "
+ + IncomingMessageStyle.createMessageStyle() + ">");
+ messageBuff.append("<table width=\"100%\">");
+ messageBuff.append("<tr>");
+ messageBuff.append("<td valign=\"top\">");
+ messageBuff.append(
+ "<table " + IncomingMessageStyle.createTableBubbleStyle()
+ + " cellspacing=\"0px\" cellpadding=\"0px\">");
+ messageBuff.append("<tr>");
+ messageBuff.append("<td style=\"width:26px;\"></td>");
+ messageBuff.append("<td style=\"width:9px;\"></td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleTlStyle() + ">");
+ messageBuff.append(
+ createMessageTableTag(headerBuffer.toString(), date));
+ messageBuff.append("</td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleTrStyle() + "></td>");
+ messageBuff.append("</tr>");
+
+ // Third row.
+ messageBuff.append("<tr>");
+ messageBuff.append("<td><img src=\"" + avatarPath
+ + "\" width=\"26px\" height=\"26px\"/> </td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createIndicatorStyle() +"></td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleMessageStyle() + ">");
+
+ messageBuff.append(
+ createMessageTag( messageID,
+ contactName,
+ message,
+ contentType,
+ date,
+ false));
+
+ messageBuff.append("</td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleMessageRightStyle()
+ + "></td>");
+ messageBuff.append("</tr>");
+
+ //Forth row.
+ messageBuff.append("<tr>");
+ messageBuff.append("<td style=\"width:26px;\"></td>");
+ messageBuff.append("<td style=\"width:9px;\"></td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleBlStyle() + "></td>");
+ messageBuff.append("<td "
+ + IncomingMessageStyle.createTableBubbleBrStyle() + "></td>");
+ messageBuff.append("</tr>");
+
+ messageBuff.append("</table>");
+ messageBuff.append("</td>");
+ messageBuff.append("</tr>");
+ messageBuff.append("</table>");
+ messageBuff.append("</div>");
+
+ return messageBuff.toString();
+ }
+
+ /**
+ * Create an outgoing message tag.
+ *
+ * @param messageID the identifier of the message
+ * @param contactName the name of the account sending the message
+ * @param contactDisplayName the display name of the account sending the
+ * message
+ * @param avatarPath the path to the avatar image
+ * @param date the date, when the message was sent
+ * @param message the content of the message
+ * @param contentType the content type HTML or PLAIN_TEXT
+ * @return the created outgoing message tag
+ */
+ public static String createOutgoingMessageTag( String messageID,
+ String contactName,
+ String contactDisplayName,
+ String avatarPath,
+ long date,
+ String message,
+ String contentType)
+ {
+ StringBuffer headerBuffer = new StringBuffer();
+
+ headerBuffer.append("<h3 identifier=\"" + MESSAGE_HEADER_ID + "\"");
+ headerBuffer.append(DATE_ATTRIBUTE + "='" + date + "'" + ">");
+ headerBuffer.append("<a style=\"color:#6a6868;");
+ headerBuffer.append("font-weight:bold;");
+ headerBuffer.append("float:left;");
+ headerBuffer.append("text-decoration:none;\" ");
+ headerBuffer.append("href=\"" + contactName + "\">");
+ headerBuffer.append(contactDisplayName
+ + createEditedAtTag(messageID, -1));
+ headerBuffer.append("</a></h3>");
+
+ StringBuffer messageBuff = new StringBuffer();
+
+ messageBuff.append("<div "
+ + OutgoingMessageStyle.createMessageStyle() + ">");
+ messageBuff.append("<table width=\"100%\">");
+ messageBuff.append("<tr>");
+ messageBuff.append("<td valign=\"top\">");
+ messageBuff.append(
+ "<table " + OutgoingMessageStyle.createTableBubbleStyle()
+ + " cellspacing=\"0px\" cellpadding=\"0px\">");
+
+ // First row.
+ messageBuff.append("<tr>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleTlStyle() + ">");
+ messageBuff.append(
+ createMessageTableTag(headerBuffer.toString(), date));
+ messageBuff.append("</td>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleTrStyle() + "></td>");
+ messageBuff.append("<td style=\"width:9px;\"></td>");
+ messageBuff.append("<td style=\"width:26px;\"></td>");
+ messageBuff.append("</tr>");
+
+ // Third row.
+ messageBuff.append("<tr>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleMessageStyle() + ">");
+
+ messageBuff.append(
+ createMessageTag( messageID,
+ contactName,
+ message,
+ contentType,
+ date,
+ false));
+
+ messageBuff.append("</td>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleMessageRightStyle()
+ + "></td>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createIndicatorStyle() +"></td>");
+ messageBuff.append("<td><div width=\"26px\" height=\"26px\"><img src=\""
+ + avatarPath
+ + "\" width=\"26px\" height=\"26px\"/></div></td>");
+ messageBuff.append("</tr>");
+
+ // Forth row.
+ messageBuff.append("<tr>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleBlStyle() + "></td>");
+ messageBuff.append("<td "
+ + OutgoingMessageStyle.createTableBubbleBrStyle() + "></td>");
+ messageBuff.append("<td style=\"width:9px;\"></td>");
+ messageBuff.append("<td style=\"width:26px;\"></td>");
+ messageBuff.append("</tr>");
+ messageBuff.append("</table>");
+ messageBuff.append("</td>");
+ messageBuff.append("</tr>");
+ messageBuff.append("</table>");
+ messageBuff.append("</div>");
+
+ return messageBuff.toString();
+ }
+
+ /**
+ * Creates a message table tag, representing the message header.
+ *
+ * @param nameHeader the name of the header.
+ * @param date the date, when the message was sent or received
+ * @return the message header tag
+ */
+ public static String createMessageTableTag( String nameHeader,
+ long date)
+ {
+ StringBuffer messageHeader = new StringBuffer();
+
+ messageHeader.append("<table width=\"100%\">");
+ messageHeader.append("<tr>");
+ messageHeader.append("<td nowrap=\"nowrap\">");
+ messageHeader.append(nameHeader);
+ messageHeader.append("</td>");
+ messageHeader.append("<td nowrap=\"nowrap\" "
+ + OutgoingMessageStyle.createDateStyle() + ">");
+ messageHeader.append(getDateString(date));
+ messageHeader.append(GuiUtils.formatTime(date));
+ messageHeader.append("</td>");
+ messageHeader.append("</tr>");
+ messageHeader.append("</table>");
+
+ return messageHeader.toString();
+ }
+
+ /**
+ * Creates the start tag, which indicates that the next text would be plain
+ * text.
+ *
+ * @param contentType the current content type
+ * @return the start plaintext tag
+ */
+ public static String createStartPlainTextTag(String contentType)
+ {
+ if (HTML_CONTENT_TYPE.equals(contentType))
+ {
+ return "";
+ }
+ else
+ {
+ return START_PLAINTEXT_TAG;
+ }
+ }
+
+ /**
+ * Creates the end tag, which indicates that the next text would be plain
+ * text.
+ *
+ * @param contentType the current content type
+ * @return the end plaintext tag
+ */
+ public static String createEndPlainTextTag(String contentType)
+ {
+ if (HTML_CONTENT_TYPE.equals(contentType))
+ {
+ return "";
+ }
+ else
+ {
+ return END_PLAINTEXT_TAG;
+ }
+ }
+
+ /**
+ * Creates a tag that shows the last edit time of a message, in the format
+ * (Edited at ...).
+ * If <tt>date < 0</tt>, returns an empty tag that serves as a placeholder
+ * for future corrections of this message.
+ *
+ * @param messageUID The ID of the edited message.
+ * @param date The date when the message was last edited, or -1 to generate
+ * an empty tag.
+ * @return The string representation of the tag.
+ */
+ public static String createEditedAtTag(String messageUID, long date)
+ {
+ StringBuilder res = new StringBuilder();
+ // Use a <cite /> tag here as most of the other inline tags (e.g. h1-7,
+ // b, i) cause different problems when used in setOuterHTML.
+ res.append("<cite id='");
+ res.append(messageUID);
+ res.append("-editedAt'> ");
+ if (date > 0)
+ {
+ res.append("&nbsp;");
+ String contents = GuiActivator.getResources().getI18NString(
+ "service.gui.EDITED_AT",
+ new String[] { GuiUtils.formatTime(date) }
+ );
+ res.append(contents);
+ }
+ res.append("</cite>");
+ return res.toString();
+ }
+
+ /**
+ * Creates the message tag.
+ *
+ * @param messageID the identifier of the message
+ * @param contactName the name of the sender
+ * @param message the message content
+ * @param contentType the content type (html or plain text)
+ * @param date the date on which the message was sent
+ * @param isEdited indicates if the given message has been edited
+ * @return the newly constructed message tag
+ */
+ public static String createMessageTag( String messageID,
+ String contactName,
+ String message,
+ String contentType,
+ long date,
+ boolean isEdited)
+ {
+ StringBuffer messageTag = new StringBuffer();
+
+ messageTag.append("<div id=\"");
+ messageTag.append(messageID);
+ messageTag.append("\" ");
+ messageTag.append(NAME_ATTRIBUTE + "=\"" + contactName);
+ messageTag.append("\" style=\"padding-left:10px;");
+ if (isEdited)
+ messageTag.append("font-style:italic;\">");
+ else
+ messageTag.append("\">");
+ messageTag.append(createStartPlainTextTag(contentType));
+ messageTag.append(message);
+ if (isEdited)
+ messageTag.append(" (edited at "
+ + GuiUtils.formatTime(date) + ")");
+ messageTag.append(createEndPlainTextTag(contentType));
+ messageTag.append("</div>");
+
+ return messageTag.toString();
+ }
+
+ /**
+ * Returns the date string to show for the given date.
+ *
+ * @param date the date to format
+ * @return the date string to show for the given date
+ */
+ public static String getDateString(long date)
+ {
+ if (GuiUtils.compareDatesOnly(date, System.currentTimeMillis()) <= 0)
+ {
+ StringBuffer dateStrBuf = new StringBuffer();
+
+ GuiUtils.formatDate(date, dateStrBuf);
+ dateStrBuf.append(" ");
+ return dateStrBuf.toString();
+ }
+
+ return "";
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java
index 9cf6f62..d39b7a0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java
@@ -130,8 +130,6 @@ public class ChatPanel
private boolean isHistoryLoaded;
- private int autoDividerLocation = 0;
-
/**
* Stores all active file transfer requests and effective transfers with
* the identifier of the transfer.
@@ -482,7 +480,7 @@ public class ChatPanel
new String[]{evt.getSourceMember().getName(),
getRoleDescription(evt.getNewRole())})
+"</DIV>",
- ChatConversationPanel.HTML_CONTENT_TYPE);
+ ChatHtmlUtils.HTML_CONTENT_TYPE);
}
/**
@@ -497,7 +495,7 @@ public class ChatPanel
+GuiActivator.getResources().getI18NString("service.gui.ARE_NOW",
new String[]{
getRoleDescription(evt.getNewRole())}) +"</DIV>",
- ChatConversationPanel.HTML_CONTENT_TYPE);
+ ChatHtmlUtils.HTML_CONTENT_TYPE);
}
/**
@@ -687,7 +685,7 @@ public class ChatPanel
if (historyString != null)
conversationPanel.appendMessageToEnd(
- historyString, ChatConversationPanel.TEXT_CONTENT_TYPE);
+ historyString, ChatHtmlUtils.TEXT_CONTENT_TYPE);
}
fireChatHistoryChange();
@@ -839,6 +837,11 @@ public class ChatPanel
message, "text");
}
+ /**
+ * Displays the given chat message.
+ *
+ * @param chatMessage the chat message to display
+ */
private void displayChatMessage(ChatMessage chatMessage)
{
if (chatMessage.getCorrectedMessageUID() != null
@@ -863,7 +866,9 @@ public class ChatPanel
private void appendChatMessage(ChatMessage chatMessage)
{
String processedMessage
- = this.conversationPanel.processMessage(chatMessage);
+ = this.conversationPanel.processMessage(chatMessage,
+ chatSession.getCurrentChatTransport().getProtocolProvider(),
+ chatSession.getCurrentChatTransport().getName());
if (chatSession instanceof ConferenceChatSession)
{
@@ -963,7 +968,10 @@ public class ChatPanel
messageType, null, message, contentType, messageId, null);
String processedMessage =
- this.conversationPanel.processMessage(chatMessage);
+ this.conversationPanel.processMessage(chatMessage,
+ chatSession.getCurrentChatTransport().getProtocolProvider(),
+ chatSession.getCurrentChatTransport().getName());
+
if (chatSession instanceof ConferenceChatSession)
{
String tempMessage =
@@ -1004,7 +1012,7 @@ public class ChatPanel
public String getTextFromWriteArea(String mimeType)
{
if (mimeType.equals(
- OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE))
+ OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE))
{
return writeMessagePanel.getText();
}
@@ -2062,7 +2070,7 @@ public class ChatPanel
System.currentTimeMillis(),
Chat.STATUS_MESSAGE,
statusMessage,
- ChatConversationPanel.TEXT_CONTENT_TYPE);
+ ChatHtmlUtils.TEXT_CONTENT_TYPE);
}
/**
@@ -2094,7 +2102,7 @@ public class ChatPanel
"service.gui.CHAT_ROOM_SUBJECT_CHANGED",
new String []{ chatSession.getChatName(),
subject}),
- ChatConversationPanel.TEXT_CONTENT_TYPE);
+ ChatHtmlUtils.TEXT_CONTENT_TYPE);
}
}
@@ -2461,8 +2469,6 @@ public class ChatPanel
{
int dividerLocation = messagePane.getHeight() - location;
- autoDividerLocation = dividerLocation;
-
messagePane.setDividerLocation(dividerLocation);
messagePane.revalidate();
messagePane.repaint();
@@ -2760,8 +2766,7 @@ public class ChatPanel
+ event.getOldValue()
+ " is now known as "
+ event.getNewValue() + "</DIV>",
- ChatConversationPanel.HTML_CONTENT_TYPE);
-
+ ChatHtmlUtils.HTML_CONTENT_TYPE);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java
index 12aeedd..fc6561b 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java
@@ -35,7 +35,7 @@ public interface ChatTransport
* messaging, otherwise returns <code>false</code>
*/
public boolean allowsInstantMessage();
-
+
/**
* Returns <tt>true</tt> if this chat transport supports message
* corrections and false otherwise.
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
index 7cdb61f..160515b 100755
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java
@@ -18,7 +18,6 @@ import javax.swing.text.html.*;
import javax.swing.undo.*;
import net.java.sip.communicator.impl.gui.*;
-import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.main.chat.conference.*;
import net.java.sip.communicator.impl.gui.main.chat.menus.*;
import net.java.sip.communicator.impl.gui.utils.*;
@@ -654,7 +653,7 @@ public class ChatWritePanel
chatPanel.getChatConversationPanel()
.appendMessageToEnd(contactList,
- ChatConversationPanel.HTML_CONTENT_TYPE);
+ ChatHtmlUtils.HTML_CONTENT_TYPE);
}
else if(contacts.size() == 1)
{
@@ -963,7 +962,7 @@ public class ChatWritePanel
GuiActivator.getResources().
getI18NString("service.gui.MSG_NOT_POSSIBLE") +
"</h5>",
- ChatConversationPanel.HTML_CONTENT_TYPE);
+ ChatHtmlUtils.HTML_CONTENT_TYPE);
}
else
{
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/IncomingMessageStyle.java b/src/net/java/sip/communicator/impl/gui/main/chat/IncomingMessageStyle.java
new file mode 100644
index 0000000..e6e5b4e
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/IncomingMessageStyle.java
@@ -0,0 +1,203 @@
+/*
+ * 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.impl.gui.main.chat;
+
+import net.java.sip.communicator.impl.gui.*;
+
+/**
+ * Defines the CSS style of an incoming chat message elements.
+ *
+ * @author Yana Stamcheva
+ */
+public class IncomingMessageStyle
+{
+ /**
+ * The incoming message background image path.
+ */
+ private final static String INCOMING_MESSAGE_IMAGE_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.INCOMING_MESSAGE_BACKGROUND").toString();
+
+ /**
+ * The incoming message right image path.
+ */
+ private final static String INCOMING_MESSAGE_IMAGE_RIGHT_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.INCOMING_MESSAGE_BACKGROUND_RIGHT")
+ .toString();
+
+ /**
+ * The incoming message indicator image path.
+ */
+ private final static String INCOMING_MESSAGE_INDICATOR_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.INCOMING_MESSAGE_INDICATOR").toString();
+
+ /**
+ * The incoming message round border image path.
+ */
+ private final static String INCOMING_MESSAGE_CURVES_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.INCOMING_MESSAGE_CURVES").toString();
+
+ /**
+ * The incoming message top image path.
+ */
+ private final static String INCOMING_MESSAGE_CURVES_TOP_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.INCOMING_MESSAGE_CURVES_TOP").toString();
+
+ /**
+ * Creates the global message style.
+ *
+ * @return the style attribute defining the global message style.
+ */
+ public static String createMessageStyle()
+ {
+ return "style=\""
+ + "width:100%;"
+ + "opacity:0.96;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table bubble right element.
+ *
+ * @return the style of the table bubble right element
+ */
+ public static String createTableBubbleMessageRightStyle()
+ {
+ return "style=\""
+ + "width:8px;"
+ + " background-image: url('"
+ +INCOMING_MESSAGE_IMAGE_RIGHT_PATH+"');"
+ + " background-repeat: repeat-y;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table bubble (wrapping the message table).
+ *
+ * @return the style of the table bubble
+ */
+ public static String createTableBubbleStyle()
+ {
+ return "style=\""
+ + "width:100%;"
+ + " position:relative;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the message table bubble.
+ *
+ * @return the style of the message table bubble
+ */
+ public static String createTableBubbleMessageStyle()
+ {
+ return "style=\""
+ + "font-size:10px;"
+ + " background-image: url('"+INCOMING_MESSAGE_IMAGE_PATH+"');"
+ + " background-repeat: repeat-y;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble bottom left corner.
+ *
+ * @return the style of the table buuble bottom left corner
+ */
+ public static String createTableBubbleBlStyle()
+ {
+ return "style=\""
+ + "height:10px;"
+ + " background-image: url('"+INCOMING_MESSAGE_CURVES_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: 0px -20px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble bottom right corner.
+ *
+ * @return the style of the table buuble bottom right corner
+ */
+ public static String createTableBubbleBrStyle()
+ {
+ return "style=\""
+ + "width:8px;"
+ + " height:10px;"
+ + " background-image: url('"+INCOMING_MESSAGE_CURVES_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: -2999px -20px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble top left corner.
+ *
+ * @return the style of the table buuble top left corner
+ */
+ public static String createTableBubbleTlStyle()
+ {
+ return "style=\""
+ + "height:23px;"
+ + " background-image: url('"
+ +INCOMING_MESSAGE_CURVES_TOP_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble top right corner.
+ *
+ * @return the style of the table buuble top right corner
+ */
+ public static String createTableBubbleTrStyle()
+ {
+ return "style=\""
+ + "width:6px;"
+ + " height:23px;"
+ + " background-image: url('"
+ +INCOMING_MESSAGE_CURVES_TOP_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: -2999px 0px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the indicator pointing to the avatar image.
+ *
+ * @return the style of the indicator pointing to the avatar image
+ */
+ public static String createIndicatorStyle()
+ {
+ return "style =\""
+ + "width:9px;"
+ + " height:19px;"
+ + " background-image: url('"
+ + INCOMING_MESSAGE_INDICATOR_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: top right;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the avatar image.
+ *
+ * @return the style of the avatar image
+ */
+ public static String createAvatarStyle()
+ {
+ return "style=\"width:26px;"
+ + " height:26px;"
+ + " float:left;\"";
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/OutgoingMessageStyle.java b/src/net/java/sip/communicator/impl/gui/main/chat/OutgoingMessageStyle.java
new file mode 100644
index 0000000..b64f287
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/OutgoingMessageStyle.java
@@ -0,0 +1,206 @@
+/*
+ * 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.impl.gui.main.chat;
+
+import net.java.sip.communicator.impl.gui.*;
+
+/**
+ * Defines the CSS style of an outgoing chat message elements.
+ *
+ * @author Yana Stamcheva
+ */
+public class OutgoingMessageStyle
+ extends IncomingMessageStyle
+{
+ /**
+ * The outgoing message background image path.
+ */
+ private final static String OUTGOING_MESSAGE_IMAGE_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.OUTGOING_MESSAGE_BACKGROUND").toString();
+
+ /**
+ * The outgoing message right image path.
+ */
+ private final static String OUTGOING_MESSAGE_IMAGE_RIGHT_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.OUTGOING_MESSAGE_BACKGROUND_RIGHT")
+ .toString();
+
+ /**
+ * The outgoing message indicator image path.
+ */
+ private final static String OUTGOING_MESSAGE_INDICATOR_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.OUTGOING_MESSAGE_INDICATOR").toString();
+
+ /**
+ * The outgoing message round border image path.
+ */
+ private final static String OUTGOING_MESSAGE_CURVES_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.OUTGOING_MESSAGE_CURVES").toString();
+
+ /**
+ * The outgoing message top image path.
+ */
+ private final static String OUTGOING_MESSAGE_CURVES_TOP_PATH
+ = GuiActivator.getResources().getImageURL(
+ "service.gui.lookandfeel.OUTGOING_MESSAGE_CURVES_TOP").toString();
+
+ /**
+ * Creates the style of the table bubble (wrapping the message table).
+ *
+ * @return the style of the table bubble
+ */
+ public static String createTableBubbleStyle()
+ {
+ return "style=\""
+ + "width:100%;"
+ + " position:relative;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table bubble right element.
+ *
+ * @return the style of the table bubble right element
+ */
+ public static String createTableBubbleMessageRightStyle()
+ {
+ return "style=\""
+ + "width:6px;"
+ + " background-image: url('"
+ + OUTGOING_MESSAGE_IMAGE_RIGHT_PATH+"');"
+ + " background-repeat: repeat-y;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the message table bubble.
+ *
+ * @return the style of the message table bubble
+ */
+ public static String createTableBubbleMessageStyle()
+ {
+ return "style=\""
+ + "font-size:10px;"
+ + " background-image: url('"+OUTGOING_MESSAGE_IMAGE_PATH+"');"
+ + " background-repeat: repeat-y;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble bottom left corner.
+ *
+ * @return the style of the table buuble bottom left corner
+ */
+ public static String createTableBubbleBlStyle()
+ {
+ return "style=\""
+ + "height:10px;"
+ + " background-image: url('"+OUTGOING_MESSAGE_CURVES_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: 0px -20px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble bottom right corner.
+ *
+ * @return the style of the table buuble bottom right corner
+ */
+ public static String createTableBubbleBrStyle()
+ {
+ return "style=\""
+ + "width:6px;"
+ + " height:10px;"
+ + " background-image: url('"+OUTGOING_MESSAGE_CURVES_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: -2999px -20px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble top left corner.
+ *
+ * @return the style of the table buuble top left corner
+ */
+ public static String createTableBubbleTlStyle()
+ {
+ return "style=\""
+ + "height:23px;"
+ + " background-image: url('"
+ +OUTGOING_MESSAGE_CURVES_TOP_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the table buuble top right corner.
+ *
+ * @return the style of the table buuble top right corner
+ */
+ public static String createTableBubbleTrStyle()
+ {
+ return "style=\""
+ + "width:6px;"
+ + " height:23px;"
+ + " background-image: url('"
+ +OUTGOING_MESSAGE_CURVES_TOP_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: -2999px 0px;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the indicator pointing to the avatar image.
+ *
+ * @return the style of the indicator pointing to the avatar image
+ */
+ public static String createIndicatorStyle()
+ {
+ return "style =\""
+ + "width:9px;"
+ + " height:19px;"
+ + " background-image: url('"
+ +OUTGOING_MESSAGE_INDICATOR_PATH+"');"
+ + " background-repeat: no-repeat;"
+ + " background-position: top left;"
+ + "\"";
+ }
+
+ /**
+ * Creates the style of the avatar image.
+ *
+ * @return the style of the avatar image
+ */
+ public static String createAvatarStyle()
+ {
+ return "style=\"width:26px;"
+ + " height:26px;"
+ + " float:right;\"";
+ }
+
+ /**
+ * Creates the style of the date.
+ *
+ * @return the style of the date
+ */
+ public static String createDateStyle()
+ {
+ return "style =\""
+ + "color:#6a6868;"
+ + " font-size:10px;"
+ + " padding-top:4px;"
+ + " text-align:right;"
+ + "\"";
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/history/HistoryWindow.java b/src/net/java/sip/communicator/impl/gui/main/chat/history/HistoryWindow.java
index 2c2b216..78dd4f7 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/history/HistoryWindow.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/history/HistoryWindow.java
@@ -263,13 +263,14 @@ public class HistoryWindow
Object o = i.next();
ChatMessage chatMessage = null;
+ ProtocolProviderService protocolProvider = null;
if(o instanceof MessageDeliveredEvent)
{
MessageDeliveredEvent evt = (MessageDeliveredEvent) o;
- ProtocolProviderService protocolProvider = evt
- .getDestinationContact().getProtocolProvider();
+ protocolProvider
+ = evt.getDestinationContact().getProtocolProvider();
chatMessage = new ChatMessage(
GuiActivator.getUIService().getMainFrame()
@@ -288,6 +289,9 @@ public class HistoryWindow
{
MessageReceivedEvent evt = (MessageReceivedEvent) o;
+ protocolProvider
+ = evt.getSourceContact().getProtocolProvider();
+
chatMessage = new ChatMessage(
evt.getSourceContact().getAddress(),
evt.getSourceContact().getDisplayName(),
@@ -304,6 +308,9 @@ public class HistoryWindow
ChatRoomMessageReceivedEvent evt
= (ChatRoomMessageReceivedEvent) o;
+ protocolProvider
+ = evt.getSourceChatRoom().getParentProvider();
+
chatMessage = new ChatMessage(
evt.getSourceChatRoomMember().getName(),
evt.getTimestamp(), Chat.INCOMING_MESSAGE,
@@ -315,6 +322,9 @@ public class HistoryWindow
ChatRoomMessageDeliveredEvent evt
= (ChatRoomMessageDeliveredEvent) o;
+ protocolProvider
+ = evt.getSourceChatRoom().getParentProvider();
+
chatMessage = new ChatMessage(
evt.getSourceChatRoom().getParentProvider()
.getAccountID().getUserID(),
@@ -326,6 +336,9 @@ public class HistoryWindow
{
FileRecord fileRecord = (FileRecord) o;
+ protocolProvider
+ = fileRecord.getContact().getProtocolProvider();
+
FileHistoryConversationComponent component
= new FileHistoryConversationComponent(
this, fileRecord);
@@ -336,10 +349,13 @@ public class HistoryWindow
if (chatMessage != null)
{
processedMessage = chatConvPanel.processMessage(
- chatMessage, searchKeyword);
+ chatMessage,
+ searchKeyword,
+ protocolProvider,
+ chatMessage.getContactName());
chatConvPanel.appendMessageToEnd(processedMessage,
- ChatConversationPanel.TEXT_CONTENT_TYPE);
+ ChatHtmlUtils.TEXT_CONTENT_TYPE);
}
}
}
@@ -875,7 +891,9 @@ public class HistoryWindow
messageContentType);
String processedMessage = chatConvPanel.processMessage(
- chatMessage, searchKeyword);
+ chatMessage, searchKeyword,
+ contact.getProtocolProvider(),
+ contact.getAddress());
this.appendMessageToDocument(document, processedMessage);
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/menus/ChatRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/chat/menus/ChatRightButtonMenu.java
index c619a34..9393909 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/menus/ChatRightButtonMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/menus/ChatRightButtonMenu.java
@@ -36,14 +36,6 @@ public class ChatRightButtonMenu
GuiActivator.getResources().getI18NString("service.gui.COPY"),
new ImageIcon(ImageLoader.getImage(ImageLoader.COPY_ICON)));
- private JMenuItem saveMenuItem = new JMenuItem(
- GuiActivator.getResources().getI18NString("service.gui.SAVE"),
- new ImageIcon(ImageLoader.getImage(ImageLoader.SAVE_ICON)));
-
- private JMenuItem printMenuItem = new JMenuItem(
- GuiActivator.getResources().getI18NString("service.gui.PRINT"),
- new ImageIcon(ImageLoader.getImage(ImageLoader.PRINT_ICON)));
-
private JMenuItem closeMenuItem = new JMenuItem(
GuiActivator.getResources().getI18NString("service.gui.CLOSE"),
new ImageIcon(ImageLoader.getImage(ImageLoader.CLOSE_ICON)));
@@ -71,47 +63,23 @@ public class ChatRightButtonMenu
this.addSeparator();
- this.add(saveMenuItem);
- this.add(printMenuItem);
-
- this.addSeparator();
-
this.add(closeMenuItem);
this.copyMenuItem.setName("copy");
- this.saveMenuItem.setName("save");
- this.printMenuItem.setName("print");
this.closeMenuItem.setName("service.gui.CLOSE");
this.copyMenuItem.addActionListener(this);
- this.saveMenuItem.addActionListener(this);
- this.printMenuItem.addActionListener(this);
this.closeMenuItem.addActionListener(this);
this.copyMenuItem.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.COPY"));
- this.saveMenuItem.setMnemonic(
- GuiActivator.getResources().getI18nMnemonic("service.gui.SAVE"));
- this.printMenuItem.setMnemonic(
- GuiActivator.getResources().getI18nMnemonic("service.gui.PRINT"));
+
this.closeMenuItem.setMnemonic(
GuiActivator.getResources().getI18nMnemonic("service.gui.CLOSE"));
this.copyMenuItem.setAccelerator(
KeyStroke.getKeyStroke(KeyEvent.VK_C,
KeyEvent.CTRL_MASK));
-
- this.saveMenuItem.setAccelerator(
- KeyStroke.getKeyStroke(KeyEvent.VK_S,
- KeyEvent.CTRL_MASK));
-
- this.printMenuItem.setAccelerator(
- KeyStroke.getKeyStroke(KeyEvent.VK_R,
- KeyEvent.CTRL_MASK));
-
- // Disable all menu items that do nothing.
- this.saveMenuItem.setEnabled(false);
- this.printMenuItem.setEnabled(false);
}
/**
@@ -168,12 +136,6 @@ public class ChatRightButtonMenu
copyMenuItem.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.COPY_ICON)));
- saveMenuItem.setIcon(new ImageIcon(
- ImageLoader.getImage(ImageLoader.SAVE_ICON)));
-
- printMenuItem.setIcon(new ImageIcon(
- ImageLoader.getImage(ImageLoader.PRINT_ICON)));
-
closeMenuItem.setIcon(new ImageIcon(
ImageLoader.getImage(ImageLoader.CLOSE_ICON)));
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/menus/FileMenu.java b/src/net/java/sip/communicator/impl/gui/main/chat/menus/FileMenu.java
index df0a7f5..f188fc0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/menus/FileMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/menus/FileMenu.java
@@ -20,7 +20,7 @@ import net.java.sip.communicator.util.swing.*;
/**
* The <tt>FileMenu</tt> is the menu in the chat window menu bar that contains
- * save, print and close.
+ * my chat rooms, history and close.
*
* @author Yana Stamcheva
* @author Adam Netocny
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java
index 14faa61..1c63daf 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java
@@ -21,7 +21,6 @@ import net.java.sip.communicator.impl.gui.main.chat.*;
import net.java.sip.communicator.impl.gui.main.chat.conference.*;
import net.java.sip.communicator.impl.gui.main.chat.history.*;
import net.java.sip.communicator.impl.gui.main.configforms.*;
-import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.gui.*;
@@ -29,10 +28,8 @@ import net.java.sip.communicator.service.gui.Container;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.FaxDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail;
-import net.java.sip.communicator.service.protocol.ServerStoredDetails.MobilePhoneDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.PagerDetail;
import net.java.sip.communicator.service.protocol.ServerStoredDetails.PhoneNumberDetail;
-import net.java.sip.communicator.service.protocol.ServerStoredDetails.WorkPhoneDetail;
import net.java.sip.communicator.util.skin.*;
import net.java.sip.communicator.util.swing.*;
@@ -109,6 +106,13 @@ public class MainToolBar
ImageLoader.getImage(ImageLoader.CHAT_CALL));
/**
+ * The call button.
+ */
+ private final ChatToolbarButton callVideoButton
+ = new ChatToolbarButton(
+ ImageLoader.getImage(ImageLoader.CHAT_VIDEO_CALL));
+
+ /**
* The options button.
*/
private final ChatToolbarButton optionsButton
@@ -181,6 +185,7 @@ public class MainToolBar
this.add(leaveChatRoomButton);
this.add(callButton);
+// this.add(callVideoButton);
this.add(desktopSharingButton);
this.add(sendFileButton);
@@ -235,6 +240,11 @@ public class MainToolBar
GuiActivator.getResources().getI18NString(
"service.gui.CALL_CONTACT"));
+ this.callVideoButton.setName("callVideo");
+ this.callVideoButton.setToolTipText(
+ GuiActivator.getResources().getI18NString(
+ "service.gui.CALL_CONTACT"));
+
this.desktopSharingButton.setName("desktop");
this.desktopSharingButton.setToolTipText(
GuiActivator.getResources().getI18NString(
@@ -264,6 +274,7 @@ public class MainToolBar
inviteButton.addActionListener(this);
leaveChatRoomButton.addActionListener(this);
callButton.addActionListener(this);
+ callVideoButton.addActionListener(this);
desktopSharingButton.addActionListener(this);
historyButton.addActionListener(this);
optionsButton.addActionListener(this);
@@ -377,7 +388,7 @@ public class MainToolBar
}
}
}
-
+
callButton.setEnabled(hasTelephony || hasPhone);
desktopSharingButton.setEnabled(!getOperationSetForCapabilities(
chatPanel.chatSession.getTransportsForOperationSet(
@@ -550,84 +561,13 @@ public class MainToolBar
List<ChatTransport> contactOpSetSupported =
getOperationSetForCapabilities(telTransports,
OperationSetBasicTelephony.class);
-
+
MetaContact metaContact
= GuiActivator.getUIService().getChatContact(chatPanel);
- Iterator<Contact> contacts = metaContact.getContacts();
- List<UIContactDetail> phones = new ArrayList<UIContactDetail>();
-
- while(contacts.hasNext())
- {
- Contact contact = contacts.next();
-
- OperationSetServerStoredContactInfo infoOpSet =
- contact.getProtocolProvider().getOperationSet(
- OperationSetServerStoredContactInfo.class);
- Iterator<GenericDetail> details = null;
-
- if(infoOpSet != null)
- {
- details = infoOpSet.getAllDetailsForContact(contact);
+
+ List<UIContactDetail> phones
+ = CallManager.getAdditionalNumbers(metaContact);
- while(details.hasNext())
- {
- GenericDetail d = details.next();
- if(d instanceof PhoneNumberDetail &&
- !(d instanceof PagerDetail) &&
- !(d instanceof FaxDetail))
- {
- PhoneNumberDetail pnd = (PhoneNumberDetail)d;
- if(pnd.getNumber() != null &&
- pnd.getNumber().length() > 0)
- {
- String localizedType = null;
-
- if(d instanceof WorkPhoneDetail)
- {
- localizedType =
- GuiActivator.getResources().
- getI18NString(
- "service.gui.WORK_PHONE");
- }
- else if(d instanceof MobilePhoneDetail)
- {
- localizedType =
- GuiActivator.getResources().
- getI18NString(
- "service.gui.MOBILE_PHONE");
- }
- else
- {
- localizedType =
- GuiActivator.getResources().
- getI18NString(
- "service.gui.PHONE");
- }
-
- UIContactDetail cd =
- new UIContactDetailImpl(
- pnd.getNumber(),
- pnd.getNumber() +
- " (" + localizedType + ")",
- null,
- new ArrayList<String>(),
- null,
- null,
- null,
- pnd)
- {
- public PresenceStatus getPresenceStatus()
- {
- return null;
- }
- };
- phones.add(cd);
- }
- }
- }
- }
- }
-
if (telTransports != null || phones.size() > 0)
{
if (contactOpSetSupported.size() == 1 && phones.size() == 0)
@@ -638,7 +578,7 @@ public class MainToolBar
transport.getName());
}
else if (contactOpSetSupported.size() == 0
- && phones.size() == 1)
+ && phones.size() == 1)
{
UIContactDetail detail = phones.get(0);
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListCellRenderer.java
index 09ad46f..d856041 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListCellRenderer.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListCellRenderer.java
@@ -61,13 +61,13 @@ public class ContactListCellRenderer
* The icon indicating an open group.
*/
private ImageIcon openedGroupIcon =
- new ImageIcon(ImageLoader.getImage(ImageLoader.DOWN_ARROW_ICON));
+ new ImageIcon(ImageLoader.getImage(ImageLoader.OPENED_GROUP_ICON));
/**
* The icon indicating a closed group.
*/
private ImageIcon closedGroupIcon =
- new ImageIcon(ImageLoader.getImage(ImageLoader.RIGHT_ARROW_ICON));
+ new ImageIcon(ImageLoader.getImage(ImageLoader.CLOSED_GROUP_ICON));
/**
* The foreground color for groups.
@@ -494,7 +494,7 @@ public class ContactListCellRenderer
= new ImageIcon(ImageLoader.getImage(ImageLoader.DOWN_ARROW_ICON));
closedGroupIcon
- = new ImageIcon(ImageLoader.getImage(ImageLoader.RIGHT_ARROW_ICON));
+ = new ImageIcon(ImageLoader.getImage(ImageLoader.CLOSED_GROUP_ICON));
int groupForegroundProperty = GuiActivator.getResources()
.getColor("service.gui.CONTACT_LIST_GROUP_FOREGROUND");
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 b6a5f75..ad6b3da 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
@@ -16,6 +16,8 @@ import javax.swing.*;
import javax.swing.JPopupMenu.Separator;
import javax.swing.tree.*;
+import org.jitsi.util.*;
+
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*;
@@ -74,6 +76,16 @@ public class ContactListTreeCellRenderer
private static final int EXTENDED_AVATAR_WIDTH = 45;
/**
+ * The default width of the button.
+ */
+ private static final int BUTTON_WIDTH = 26;
+
+ /**
+ * The default height of the button.
+ */
+ private static final int BUTTON_HEIGHT = 27;
+
+ /**
* Left border value.
*/
private static final int LEFT_BORDER = 5;
@@ -84,14 +96,30 @@ public class ContactListTreeCellRenderer
private static final int TOP_BORDER = 2;
/**
- * Status label right border.
+ * Bottom border value.
+ */
+ private static final int BOTTOM_BORDER = 2;
+
+ /**
+ * Right border value.
*/
- private static final int STATUS_RIGHT_BORDER = 2;
+ private static final int RIGHT_BORDER = 2;
/**
- * Status label top border.
+ * The horizontal gap between columns in pixels;
*/
- private static final int STATUS_TOP_BORDER = 2;
+ private static final int H_GAP = 2;
+
+ /**
+ * The vertical gap between rows in pixels;
+ */
+ private static final int V_GAP = 3;
+
+ /**
+ * The separator image for the button toolbar.
+ */
+ private static final Image BUTTON_SEPARATOR_IMG
+ = ImageLoader.getImage(ImageLoader.CONTACT_LIST_BUTTON_SEPARATOR);
/**
* The icon used for opened groups.
@@ -131,18 +159,12 @@ public class ContactListTreeCellRenderer
/**
* The call video button.
*/
- private final SIPCommButton callVideoButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL),
- ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED),
- null);
+ private final SIPCommButton callVideoButton = new SIPCommButton();
/**
* The desktop sharing button.
*/
- private final SIPCommButton desktopSharingButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL),
- ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED),
- null);
+ private final SIPCommButton desktopSharingButton = new SIPCommButton();
/**
* The chat button.
@@ -152,10 +174,7 @@ public class ContactListTreeCellRenderer
/**
* The add contact button.
*/
- private final SIPCommButton addContactButton = new SIPCommButton(
- ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL),
- ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED),
- null);
+ private final SIPCommButton addContactButton = new SIPCommButton();
/**
* The constraints used to align components in the <tt>centerPanel</tt>.
@@ -209,6 +228,11 @@ public class ContactListTreeCellRenderer
private List<JButton> customActionButtons;
/**
+ * The last added button.
+ */
+ private SIPCommButton lastAddedButton;
+
+ /**
* Initializes the panel containing the node.
*/
public ContactListTreeCellRenderer()
@@ -222,11 +246,11 @@ public class ContactListTreeCellRenderer
* correctly calculated problems may occur when clicking buttons!
*/
this.setBorder(BorderFactory
- .createEmptyBorder(TOP_BORDER, LEFT_BORDER, 2, 2));
+ .createEmptyBorder( TOP_BORDER,
+ LEFT_BORDER,
+ BOTTOM_BORDER,
+ RIGHT_BORDER));
- statusLabel.setBorder(
- BorderFactory.createEmptyBorder(STATUS_TOP_BORDER,
- 0, 0, STATUS_RIGHT_BORDER));
loadSkin();
this.setOpaque(true);
@@ -237,6 +261,10 @@ public class ContactListTreeCellRenderer
this.rightLabel.setHorizontalAlignment(JLabel.RIGHT);
+ // !! IMPORTANT: General insets used for all components if not
+ // overwritten!
+ constraints.insets = new Insets(0, 0, V_GAP, H_GAP);
+
constraints.anchor = GridBagConstraints.WEST;
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
@@ -595,11 +623,11 @@ public class ContactListTreeCellRenderer
if (preferredHeight > 0)
preferredSize.height = preferredHeight;
else if (contact instanceof ShowMoreContact)
- preferredSize.height = 18;
+ preferredSize.height = 20;
else if (isSelected && treeContactList.isContactButtonsVisible())
preferredSize.height = 70;
else
- preferredSize.height = 30;
+ preferredSize.height = 35;
}
else if (treeNode instanceof GroupNode)
{
@@ -611,7 +639,7 @@ public class ContactListTreeCellRenderer
if (preferredHeight > 0)
preferredSize.height = preferredHeight;
else
- preferredSize.height = 18;
+ preferredSize.height = 20;
}
return preferredSize;
@@ -639,8 +667,6 @@ public class ContactListTreeCellRenderer
constraints.gridwidth = nameLabelGridWidth;
this.add(nameLabel, constraints);
- rightLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
-
constraints.anchor = GridBagConstraints.NORTHEAST;
constraints.fill = GridBagConstraints.VERTICAL;
constraints.gridx = nameLabelGridWidth + 1;
@@ -719,15 +745,6 @@ public class ContactListTreeCellRenderer
if (!isSelected)
return;
- int statusMessageLabelHeight = 0;
- if (displayDetailsLabel.getText().length() > 0)
- statusMessageLabelHeight = 20;
- else
- statusMessageLabelHeight = 15;
-
- int y = TOP_BORDER + STATUS_TOP_BORDER
- + nameLabel.getHeight() + statusMessageLabelHeight;
-
UIContactDetail imContact = null;
// For now we support instance messaging only for contacts in our
// contact list until it's implemented for external source contacts.
@@ -736,9 +753,8 @@ public class ContactListTreeCellRenderer
OperationSetBasicInstantMessaging.class);
int x = (statusIcon == null ? 0 : statusIcon.getIconWidth())
- + (statusLabel == null ? 0 : statusLabel.getIconTextGap())
+ LEFT_BORDER
- + STATUS_RIGHT_BORDER;
+ + H_GAP;
// Re-initialize the x grid.
constraints.gridx = 0;
@@ -746,20 +762,7 @@ public class ContactListTreeCellRenderer
if (imContact != null)
{
- 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.chatButton.setBorder(null);
- this.add(chatButton, constraints);
-
- chatButton.setBounds(x, y, 28, 28);
-
- x += chatButton.getWidth();
+ x += addButton(chatButton, ++gridX, x, false);
}
UIContactDetail telephonyContact
@@ -833,22 +836,7 @@ public class ContactListTreeCellRenderer
|| uiContact.getDescriptor() instanceof SourceContact ||
(hasPhone && providers.size() > 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.callButton.setBorder(null);
- this.add(callButton, constraints);
-
- callButton.setBounds(x, y, 28, 28);
-
- callButton.setEnabled(telephonyContact != null || hasPhone);
-
- x += callButton.getWidth();
+ x += addButton(callButton, ++gridX, x, false);
}
UIContactDetail videoContact
@@ -864,20 +852,7 @@ public class ContactListTreeCellRenderer
null,
null).size() > 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.callVideoButton.setBorder(null);
- this.add(callVideoButton, constraints);
-
- callVideoButton.setBounds(x, y, 28, 28);
-
- x += callVideoButton.getWidth();
+ x += addButton(callVideoButton, ++gridX, x, false);
}
UIContactDetail desktopContact
@@ -893,39 +868,13 @@ public class ContactListTreeCellRenderer
null,
null).size() > 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.desktopSharingButton.setBorder(null);
- this.add(desktopSharingButton, constraints);
-
- desktopSharingButton.setBounds(x, y, 28, 28);
-
- x += desktopSharingButton.getWidth();
+ x += addButton(desktopSharingButton, ++gridX, x, false);
}
if (uiContact.getDescriptor() instanceof SourceContact
&& !ConfigurationManager.isAddContactDisabled())
{
- 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.addContactButton.setBorder(null);
- this.add(addContactButton, constraints);
-
- addContactButton.setBounds(x, y, 28, 28);
-
- x += addContactButton.getWidth();
+ x += addButton(addContactButton, ++gridX, x, false);
}
// The list of the contact actions
@@ -933,16 +882,20 @@ public class ContactListTreeCellRenderer
Collection<SIPCommButton> contactActions
= uiContact.getContactCustomActionButtons();
- if (contactActions != null)
+ if (contactActions != null && contactActions.size() > 0)
{
- initContactActionButtons(contactActions, gridX, x);
+ initContactActionButtons(contactActions, ++gridX, x);
}
else
{
addLabels(gridX);
}
- this.setBounds(0, 0, treeContactList.getWidth(), getPreferredSize().height);
+ if (lastAddedButton != null)
+ setButtonBg(lastAddedButton, gridX, true);
+
+ this.setBounds(0, 0, treeContactList.getWidth(),
+ getPreferredSize().height);
}
/**
@@ -970,28 +923,8 @@ public class ContactListTreeCellRenderer
customActionButtons.add(actionButton);
- 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;
- actionButton.setBorder(null);
- this.add(actionButton, constraints);
-
- int statusMessageLabelHeight = 0;
- if (displayDetailsLabel.getText().length() > 0)
- statusMessageLabelHeight = 20;
- else
- statusMessageLabelHeight = 15;
-
- actionButton.setBounds(xBounds,
- nameLabel.getHeight() + statusMessageLabelHeight
- + TOP_BORDER + STATUS_TOP_BORDER, 28, 28);
-
- xBounds += actionButton.getWidth();
+ xBounds
+ += addButton(actionButton, ++gridX, xBounds, false);
}
}
@@ -1039,6 +972,15 @@ public class ContactListTreeCellRenderer
* Returns the call button contained in the current cell.
* @return the call button contained in the current cell
*/
+ public JButton getChatButton()
+ {
+ return chatButton;
+ }
+
+ /**
+ * Returns the call button contained in the current cell.
+ * @return the call button contained in the current cell
+ */
public JButton getCallButton()
{
return callButton;
@@ -1365,7 +1307,9 @@ public class ContactListTreeCellRenderer
else if (desktopContacts.size() > 1)
{
chooseAccountDialog
- = new ChooseCallAccountPopupMenu(treeContactList, desktopContacts,
+ = new ChooseCallAccountPopupMenu(
+ treeContactList,
+ desktopContacts,
OperationSetDesktopSharingServer.class);
}
@@ -1378,7 +1322,8 @@ public class ContactListTreeCellRenderer
SwingUtilities.convertPointToScreen(location, treeContactList);
location.y = location.y
- + treeContactList.getPathBounds(treeContactList.getSelectionPath()).y;
+ + treeContactList.getPathBounds(
+ treeContactList.getSelectionPath()).y;
chooseAccountDialog.showPopupMenu(location.x + 8, location.y - 8);
}
@@ -1487,14 +1432,14 @@ public class ContactListTreeCellRenderer
tree.getWidth() - imageWidth, 0, imageWidth, imageHeight);
}
- statusLabel.setBounds( 0, 0,
+ dragC.statusLabel.setBounds( 0, 0,
statusLabel.getWidth(),
statusLabel.getHeight());
- nameLabel.setBounds(statusLabel.getWidth(), 0,
+ dragC.nameLabel.setBounds(statusLabel.getWidth(), 0,
tree.getWidth() - imageWidth - 5, nameLabel.getHeight());
- displayDetailsLabel.setBounds(
+ dragC.displayDetailsLabel.setBounds(
displayDetailsLabel.getX(),
nameLabel.getHeight(),
displayDetailsLabel.getWidth(),
@@ -1509,20 +1454,24 @@ public class ContactListTreeCellRenderer
public void loadSkin()
{
openedGroupIcon
- = new ImageIcon(ImageLoader.getImage(ImageLoader.DOWN_ARROW_ICON));
+ = new ImageIcon(ImageLoader.getImage(ImageLoader.OPENED_GROUP_ICON));
closedGroupIcon
- = new ImageIcon(ImageLoader.getImage(ImageLoader.RIGHT_ARROW_ICON));
+ = new ImageIcon(ImageLoader.getImage(ImageLoader.CLOSED_GROUP_ICON));
- callButton.setBackgroundImage(ImageLoader.getImage(
+ callButton.setIconImage(ImageLoader.getImage(
ImageLoader.CALL_BUTTON_SMALL));
+ callButton.setRolloverImage(ImageLoader.getImage(
+ ImageLoader.CALL_BUTTON_SMALL_PRESSED));
callButton.setPressedImage(ImageLoader.getImage(
ImageLoader.CALL_BUTTON_SMALL_PRESSED));
- chatButton.setBackgroundImage(ImageLoader.getImage(
+ chatButton.setIconImage(ImageLoader.getImage(
ImageLoader.CHAT_BUTTON_SMALL));
chatButton.setPressedImage(ImageLoader.getImage(
ImageLoader.CHAT_BUTTON_SMALL_PRESSED));
+ chatButton.setRolloverImage(ImageLoader.getImage(
+ ImageLoader.CHAT_BUTTON_SMALL_PRESSED));
msgReceivedImage
= ImageLoader.getImage(ImageLoader.MESSAGE_RECEIVED_ICON);
@@ -1539,17 +1488,40 @@ public class ContactListTreeCellRenderer
if (contactForegroundProperty > -1)
contactForegroundColor = new Color(contactForegroundProperty);
- callVideoButton.setBackgroundImage(ImageLoader.getImage(
+ callVideoButton.setIconImage(ImageLoader.getImage(
ImageLoader.CALL_VIDEO_BUTTON_SMALL));
-
+ callVideoButton.setRolloverImage(ImageLoader.getImage(
+ ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED));
callVideoButton.setPressedImage(ImageLoader.getImage(
ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED));
- desktopSharingButton.setBackgroundImage(ImageLoader.getImage(
+ desktopSharingButton.setIconImage(ImageLoader.getImage(
ImageLoader.DESKTOP_BUTTON_SMALL));
-
+ desktopSharingButton.setRolloverImage(ImageLoader.getImage(
+ ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED));
desktopSharingButton.setPressedImage(ImageLoader.getImage(
ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED));
+
+ callVideoButton.setIconImage(
+ ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL));
+ callVideoButton.setRolloverImage(
+ ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED));
+ callVideoButton.setPressedImage(
+ ImageLoader.getImage(ImageLoader.CALL_VIDEO_BUTTON_SMALL_PRESSED));
+
+ desktopSharingButton.setIconImage(
+ ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL));
+ desktopSharingButton.setRolloverImage(
+ ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED));
+ desktopSharingButton.setPressedImage(
+ ImageLoader.getImage(ImageLoader.DESKTOP_BUTTON_SMALL_PRESSED));
+
+ addContactButton.setIconImage(
+ ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL));
+ addContactButton.setRolloverImage(
+ ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED));
+ addContactButton.setPressedImage(
+ ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED));
}
/**
@@ -1628,4 +1600,78 @@ public class ContactListTreeCellRenderer
}
}
}
+
+ 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);
+
+// addButtonSeparator(gridX);
+
+ int yBounds = TOP_BORDER + BOTTOM_BORDER + 2*V_GAP
+ + GuiUtils.getStringSize(
+ nameLabel, nameLabel.getText()).height
+ + GuiUtils.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();// + BUTTON_SEPARATOR_IMG.getWidth(this);
+ }
+
+ 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));
+ }
+ }
+
+ private void addButtonSeparator(int buttonGridX)
+ {
+ JLabel separatorLabel = new JLabel(new ImageIcon(BUTTON_SEPARATOR_IMG));
+
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.fill = GridBagConstraints.NONE;
+ constraints.gridx = ++buttonGridX;
+ constraints.gridy = 2;
+ constraints.gridwidth = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 0f;
+ constraints.weighty = 0f;
+ this.add(separatorLabel, constraints);
+ }
}
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 f703aaa..37d8c9a 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
@@ -1224,25 +1224,25 @@ public class TreeContactList
/**
* Forwards the given mouse <tt>event</tt> to the list of original
* <tt>MouseListener</tt>-s.
- * @param event the <tt>MouseEvent</tt> that notified us
+ * @param e the <tt>MouseEvent</tt> that notified us
*/
- public void mouseEntered(MouseEvent event)
+ public void mouseEntered(MouseEvent e)
{
// forward the event to the original listeners
for (MouseListener listener : originalMouseListeners)
- listener.mouseEntered(event);
+ listener.mouseEntered(e);
}
/**
* Forwards the given mouse <tt>event</tt> to the list of original
* <tt>MouseListener</tt>-s.
- * @param event the <tt>MouseEvent</tt> that notified us
+ * @param e the <tt>MouseEvent</tt> that notified us
*/
- public void mouseExited(MouseEvent event)
+ public void mouseExited(MouseEvent e)
{
// forward the event to the original listeners
for (MouseListener listener : originalMouseListeners)
- listener.mouseExited(event);
+ listener.mouseExited(e);
}
/**
@@ -1278,7 +1278,14 @@ public class TreeContactList
rightButtonMenu.setVisible(true);
}
- public void mouseMoved(MouseEvent e) {}
+ public void mouseMoved(MouseEvent e)
+ {
+ dispatchEventToButtons(e);
+
+ // forward the event to the original listeners
+ for (MouseListener listener : originalMouseListeners)
+ listener.mouseReleased(e);
+ }
public void mouseDragged(MouseEvent e) {}
@@ -1335,18 +1342,29 @@ public class TreeContactList
TreePath mousePath
= this.getPathForLocation(event.getX(), event.getY());
+ ContactListTreeCellRenderer renderer
+ = (ContactListTreeCellRenderer) getCellRenderer()
+ .getTreeCellRendererComponent( this,
+ mousePath.getLastPathComponent(),
+ true,
+ true,
+ true,
+ this.getRowForPath(mousePath),
+ true);
+
// If this is not the selection path we have nothing to do here.
if (mousePath == null || !mousePath.equals(this.getSelectionPath()))
- return;
+ {
+ renderer.getChatButton().getModel().setRollover(false);
+ renderer.getCallButton().getModel().setRollover(false);
+ renderer.getCallVideoButton().getModel().setRollover(false);
+ renderer.getDesktopSharingButton().getModel().setRollover(false);
+ renderer.getAddContactButton().getModel().setRollover(false);
- JPanel renderer = (JPanel) getCellRenderer()
- .getTreeCellRendererComponent( this,
- mousePath.getLastPathComponent(),
- true,
- true,
- true,
- this.getRowForPath(mousePath),
- true);
+ this.repaint();
+
+ return;
+ }
// We need to translate coordinates here.
Rectangle r = this.getPathBounds(mousePath);
@@ -1373,10 +1391,37 @@ public class TreeContactList
5, // we're in the button for sure
event.getClickCount(),
event.isPopupTrigger());
- mouseComponent.dispatchEvent(evt);
- this.repaint();
+ ((SIPCommButton) mouseComponent).getModel()
+ .setRollover(event.getID() == MouseEvent.MOUSE_MOVED);
+
+ if (!mouseComponent.equals(renderer.getChatButton()))
+ renderer.getChatButton().getModel().setRollover(false);
+
+ if (!mouseComponent.equals(renderer.getCallButton()))
+ renderer.getCallButton().getModel().setRollover(false);
+
+ if (!mouseComponent.equals(renderer.getCallVideoButton()))
+ renderer.getCallVideoButton().getModel().setRollover(false);
+
+ if (!mouseComponent.equals(renderer.getDesktopSharingButton()))
+ renderer.getDesktopSharingButton().getModel().setRollover(false);
+
+ if (!mouseComponent.equals(renderer.getAddContactButton()))
+ renderer.getAddContactButton().getModel().setRollover(false);
+
+ mouseComponent.dispatchEvent(evt);
}
+ else
+ {
+ renderer.getChatButton().getModel().setRollover(false);
+ renderer.getCallButton().getModel().setRollover(false);
+ renderer.getCallVideoButton().getModel().setRollover(false);
+ renderer.getDesktopSharingButton().getModel().setRollover(false);
+ renderer.getAddContactButton().getModel().setRollover(false);
+ }
+
+ this.repaint();
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java b/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
index a49d02a..4aa50c8 100644
--- a/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/presence/AccountStatusPanel.java
@@ -345,7 +345,7 @@ public class AccountStatusPanel
*/
public void registrationStateChanged(RegistrationStateChangeEvent evt)
{
- ProtocolProviderService protocolProvider = evt.getProvider();
+ final ProtocolProviderService protocolProvider = evt.getProvider();
this.updateStatus(protocolProvider);
@@ -379,16 +379,30 @@ public class AccountStatusPanel
{
if (currentImage == null)
{
- byte[] accountImage
- = AccountInfoUtils.getImage(accountInfoOpSet);
+ currentImage
+ = AvatarCacheUtils
+ .getCachedAvatar(protocolProvider);
- // do not set empty images
- if ((accountImage != null)
- && (accountImage.length > 0))
+ if (currentImage == null)
{
- currentImage = accountImage;
- accountImageLabel.setImageIcon(currentImage);
+ byte[] accountImage
+ = AccountInfoUtils
+ .getImage(accountInfoOpSet);
+
+ // do not set empty images
+ if ((accountImage != null)
+ && (accountImage.length > 0))
+ {
+ currentImage = accountImage;
+
+ AvatarCacheUtils.cacheAvatar(
+ protocolProvider, accountImage);
+
+ accountImageLabel.setImageIcon(currentImage);
+ }
}
+ else
+ accountImageLabel.setImageIcon(currentImage);
}
if(!StringUtils.isNullOrEmpty(globalDisplayName))
@@ -570,6 +584,10 @@ public class AccountStatusPanel
currentImage = ImageUtils.toByteArray(
ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO));
}
+
+ AvatarCacheUtils.cacheAvatar(
+ event.getSourceProvider(), currentImage);
+
accountImageLabel.setImageIcon(currentImage);
}
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index e589bd4..63c21f7 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -196,12 +196,6 @@ public class ImageLoader
= new ImageID("service.gui.buttons.MORE_BUTTON");
/**
- * Closed group icon.
- */
- public static final ImageID RIGHT_ARROW_ICON
- = new ImageID("service.gui.icons.RIGHT_ARROW_ICON");
-
- /**
* The background of the main window and chat window.
*/
public static final ImageID DOWN_ARROW_ICON
@@ -276,6 +270,40 @@ public class ImageLoader
= new ImageID("service.gui.buttons.CALL_VIDEO_BUTTON_BG");
/**
+ * The background image for a button in contact list that is shown on the
+ * left of the button toolbar.
+ */
+ public static final ImageID CONTACT_LIST_BUTTON_BG_LEFT
+ = new ImageID("service.gui.buttons.CONTACT_LIST_BUTTON_BG_LEFT");
+
+ /**
+ * The background image for a button in contact list that is shown on the
+ * right of the button toolbar.
+ */
+ public static final ImageID CONTACT_LIST_BUTTON_BG_RIGHT
+ = new ImageID("service.gui.buttons.CONTACT_LIST_BUTTON_BG_RIGHT");
+
+ /**
+ * The background image for a button in contact list that is shown in the
+ * middle of other buttons.
+ */
+ public static final ImageID CONTACT_LIST_BUTTON_BG_MIDDLE
+ = new ImageID("service.gui.buttons.CONTACT_LIST_BUTTON_BG_MIDDLE");
+
+ /**
+ * The background image for a button in contact list if there's only one
+ * button shown.
+ */
+ public static final ImageID CONTACT_LIST_ONE_BUTTON_BG
+ = new ImageID("service.gui.buttons.CONTACT_LIST_ONE_BUTTON_BG");
+
+ /**
+ * The separator image for the button toolbar in the contact list.
+ */
+ public static final ImageID CONTACT_LIST_BUTTON_SEPARATOR
+ = new ImageID("service.gui.buttons.CONTACT_LIST_BUTTON_SEPARATOR");
+
+ /**
* The call button small image.
*/
public static final ImageID CALL_BUTTON_SMALL
@@ -344,12 +372,24 @@ public class ImageLoader
= new ImageID("service.gui.buttons.CHAT_BUTTON_SMALL_WHITE");
/**
+ * The icon used to separate buttons in the call toolbar.
+ */
+ public static final ImageID CALL_TOOLBAR_SEPARATOR
+ = new ImageID("service.gui.icons.CALL_TOOLBAR_SEPARATOR");
+
+ /**
* The chat call button image.
*/
public static final ImageID CHAT_CALL
= new ImageID("service.gui.buttons.CHAT_CALL");
/**
+ * The chat video call button image.
+ */
+ public static final ImageID CHAT_VIDEO_CALL
+ = new ImageID("service.gui.buttons.CHAT_VIDEO_CALL");
+
+ /**
* The chat call button image.
*/
public static final ImageID CHAT_DESKTOP_SHARING
@@ -368,6 +408,12 @@ public class ImageLoader
= new ImageID("service.gui.buttons.CALL_HISTORY_BUTTON_PRESSED");
/**
+ * The call history button missed call notification image.
+ */
+ public static final ImageID CALL_HISTORY_BUTTON_NOTIFICATION
+ = new ImageID("service.gui.icons.CALL_HISTORY_BUTTON_NOTIFICATION");
+
+ /**
* The chat button small pressed image.
*/
public static final ImageID CHAT_BUTTON_SMALL_PRESSED
@@ -987,13 +1033,13 @@ public class ImageLoader
/**
* The image used for opened groups.
*/
- public static final ImageID OPENED_GROUP
+ public static final ImageID OPENED_GROUP_ICON
= new ImageID("service.gui.icons.OPENED_GROUP");
/**
* The image used for closed groups.
*/
- public static final ImageID CLOSED_GROUP
+ public static final ImageID CLOSED_GROUP_ICON
= new ImageID("service.gui.icons.CLOSED_GROUP");
/**
@@ -1763,6 +1809,67 @@ public class ImageLoader
badged = image;
return badged;
}
+
+ /**
+ * Returns the given protocol image with an index allowing to distinguish
+ * different accounts from the same protocol.
+ *
+ * @param bgImage the background image
+ * @param topImage the image that should be painted on the top of the
+ * background image
+ * @param x the x coordinate of the top image
+ * @param y the y coordinate of the top image
+ * @return the result merged image
+ */
+ public static Image getImage(Image bgImage, Image topImage, int x, int y)
+ {
+ BufferedImage buffImage
+ = new BufferedImage(bgImage.getWidth(null),
+ bgImage.getHeight(null),
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = (Graphics2D) buffImage.getGraphics();
+
+ AntialiasingManager.activateAntialiasing(g);
+ g.drawImage(bgImage, 0, 0, null);
+ g.drawImage(topImage, x, y, null);
+
+ return buffImage;
+ }
+
+ /**
+ * Returns the given protocol image with an index allowing to distinguish
+ * different accounts from the same protocol.
+ *
+ * @param bgImage the background image
+ * @param text the text that should be painted on the top of the
+ * background image
+ * @return the result merged image
+ */
+ public static Image getImage(Image bgImage, String text, Component c)
+ {
+ BufferedImage buffImage
+ = new BufferedImage(bgImage.getWidth(c),
+ bgImage.getHeight(c),
+ BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g = (Graphics2D) buffImage.getGraphics();
+
+ AntialiasingManager.activateAntialiasing(g);
+ g.setColor(Color.WHITE);
+ g.setFont(c.getFont().deriveFont(Font.BOLD, 9));
+ g.drawImage(bgImage, 0, 0, null);
+
+ FontMetrics fontMetrics = g.getFontMetrics();
+ int fontHeight = fontMetrics.getHeight();
+ int textWidth = fontMetrics.stringWidth(text);
+
+ g.drawString(
+ text,
+ (bgImage.getWidth(null) - textWidth)/2 + 1,
+ (bgImage.getHeight(null) - fontHeight)/2 + fontHeight - 3);
+
+ return buffImage;
+ }
+
/**
* Loads an image icon from a given image path.
* @param imagePath The identifier of the image.
diff --git a/src/net/java/sip/communicator/util/AvatarCacheUtils.java b/src/net/java/sip/communicator/util/AvatarCacheUtils.java
new file mode 100644
index 0000000..37dcac1
--- /dev/null
+++ b/src/net/java/sip/communicator/util/AvatarCacheUtils.java
@@ -0,0 +1,344 @@
+/*
+ * 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.util;
+
+import java.io.*;
+
+import org.jitsi.service.fileaccess.*;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * The <tt>AvatarCacheUtils</tt> allows to cache an avatar or to obtain the
+ * image of a cached avatar by specifying a contact or an account address.
+ *
+ * @author Yana Stamcheva
+ */
+public class AvatarCacheUtils
+{
+ /**
+ * The logger for this class.
+ */
+ private final static Logger logger
+ = Logger.getLogger(AvatarCacheUtils.class);
+
+ /**
+ * The name (i.e. not the whole path) of the directory in which the avatar
+ * files are to be cached for later reuse.
+ */
+ private final static String AVATAR_DIR = "avatarcache";
+
+ /**
+ * Characters and their replacement in created folder names
+ */
+ private final static String[][] ESCAPE_SEQUENCES = new String[][]
+ {
+ {"&", "&_amp"},
+ {"/", "&_sl"},
+ {"\\\\", "&_bs"}, // the char \
+ {":", "&_co"},
+ {"\\*", "&_as"}, // the char *
+ {"\\?", "&_qm"}, // the char ?
+ {"\"", "&_pa"}, // the char "
+ {"<", "&_lt"},
+ {">", "&_gt"},
+ {"\\|", "&_pp"} // the char |
+ };
+
+ /**
+ * Returns the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, which
+ * account avatar image we're looking for
+ * @return the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider
+ */
+ public static byte[] getCachedAvatar(
+ ProtocolProviderService protocolProvider)
+ {
+ String avatarPath = getCachedAvatarPath(protocolProvider);
+
+ byte[] cachedAvatar = getLocallyStoredAvatar(avatarPath);
+
+ /*
+ * Caching a zero-length avatar happens but such an avatar isn't
+ * very useful.
+ */
+ if ((cachedAvatar != null) && (cachedAvatar.length > 0))
+ return cachedAvatar;
+
+ return null;
+ }
+
+ /**
+ * Returns the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, which
+ * account avatar image we're looking for
+ * @return the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider
+ */
+ public static byte[] getCachedAvatar(Contact protocolContact)
+ {
+ String avatarPath = getCachedAvatarPath(protocolContact);
+
+ byte[] cachedAvatar = getLocallyStoredAvatar(avatarPath);
+
+ /*
+ * Caching a zero-length avatar happens but such an avatar isn't
+ * very useful.
+ */
+ if ((cachedAvatar != null) && (cachedAvatar.length > 0))
+ return cachedAvatar;
+
+ return null;
+ }
+
+ /**
+ * Returns the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, which
+ * account avatar image we're looking for
+ * @return the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider
+ */
+ public static String getCachedAvatarPath(
+ ProtocolProviderService protocolProvider)
+ {
+ return AVATAR_DIR
+ + File.separator
+ + escapeSpecialCharacters(
+ protocolProvider.getAccountID().getAccountUniqueID())
+ + File.separator
+ + escapeSpecialCharacters(
+ protocolProvider.getAccountID().getAccountUniqueID());
+ }
+
+ /**
+ * Returns the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, which
+ * account avatar image we're looking for
+ * @return the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider
+ */
+ public static String getCachedAvatarPath(Contact protocolContact)
+ {
+ return AVATAR_DIR
+ + File.separator
+ + escapeSpecialCharacters(
+ protocolContact
+ .getProtocolProvider()
+ .getAccountID().getAccountUniqueID())
+ + File.separator
+ + escapeSpecialCharacters(protocolContact.getAddress());
+ }
+
+ /**
+ * Returns the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider.
+ *
+ * @param protocolProvider the <tt>ProtocolProviderService</tt>, which
+ * account avatar image we're looking for
+ * @return the bytes of the avatar image stored for the account
+ * corresponding to the given protocol provider
+ */
+ public static String getCachedAvatarPath(
+ ProtocolProviderService protocolProvider,
+ String contactAddress)
+ {
+ return AVATAR_DIR
+ + File.separator
+ + escapeSpecialCharacters(
+ protocolProvider.getAccountID().getAccountUniqueID())
+ + File.separator
+ + escapeSpecialCharacters(contactAddress);
+ }
+
+ /**
+ * Returns the avatar image corresponding to the given avatar path.
+ *
+ * @param avatarPath The path to the lovally stored avatar.
+ * @return the avatar image corresponding to the given avatar path.
+ */
+ private static byte[] getLocallyStoredAvatar(String avatarPath)
+ {
+ try
+ {
+ File avatarFile
+ = UtilActivator
+ .getFileAccessService()
+ .getPrivatePersistentFile(avatarPath);
+
+ if(avatarFile.exists())
+ {
+ FileInputStream avatarInputStream
+ = new FileInputStream(avatarFile);
+ byte[] bs = null;
+
+ try
+ {
+ int available = avatarInputStream.available();
+
+ if (available > 0)
+ {
+ bs = new byte[available];
+ avatarInputStream.read(bs);
+ }
+ }
+ finally
+ {
+ avatarInputStream.close();
+ }
+ if (bs != null)
+ return bs;
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.error(
+ "Could not read avatar image from file " + avatarPath,
+ ex);
+ }
+ return null;
+ }
+
+ /**
+ * Replaces the characters that we must escape used for the created
+ * filename.
+ *
+ * @param id the <tt>String</tt> which is to have its characters escaped
+ * @return a <tt>String</tt> derived from the specified <tt>id</tt> by
+ * escaping characters
+ */
+ private static String escapeSpecialCharacters(String id)
+ {
+ String resultId = id;
+
+ for (int j = 0; j < ESCAPE_SEQUENCES.length; j++)
+ {
+ resultId = resultId.
+ replaceAll(ESCAPE_SEQUENCES[j][0], ESCAPE_SEQUENCES[j][1]);
+ }
+ return resultId;
+ }
+
+ /**
+ * Stores avatar bytes in the given <tt>Contact</tt>.
+ *
+ * @param protoContact The contact in which we store the avatar.
+ * @param avatarBytes The avatar image bytes.
+ */
+ public static void cacheAvatar( Contact protoContact,
+ byte[] avatarBytes)
+ {
+ String avatarDirPath
+ = AVATAR_DIR
+ + File.separator
+ + escapeSpecialCharacters(
+ protoContact
+ .getProtocolProvider()
+ .getAccountID().getAccountUniqueID());
+ String avatarFileName
+ = escapeSpecialCharacters(protoContact.getAddress());
+
+ cacheAvatar(avatarDirPath, avatarFileName, avatarBytes);
+ }
+ /**
+ * Stores avatar bytes for the account corresponding to the given
+ * <tt>protocolProvider</tt>.
+ *
+ * @param protocolProvider the protocol provider corresponding to the
+ * account, which avatar we're storing
+ * @param avatarBytes the avatar image bytes
+ */
+ public static void cacheAvatar( ProtocolProviderService protocolProvider,
+ byte[] avatarBytes)
+ {
+ String accountUID
+ = protocolProvider.getAccountID().getAccountUniqueID();
+
+ String avatarDirPath
+ = AVATAR_DIR
+ + File.separator
+ + escapeSpecialCharacters(accountUID);
+
+ String avatarFileName = escapeSpecialCharacters(accountUID);
+
+ cacheAvatar(avatarDirPath, avatarFileName, avatarBytes);
+ }
+
+ /**
+ * Stores avatar bytes for the account corresponding to the given
+ * <tt>protocolProvider</tt>.
+ *
+ * @param avatarDirPath the directory in which the file will be stored
+ * @param avatarFileName the name of the avatar file
+ * @param avatarBytes the avatar image bytes
+ */
+ private static void cacheAvatar(String avatarDirPath,
+ String avatarFileName,
+ byte[] avatarBytes)
+ {
+ File avatarDir = null;
+ File avatarFile = null;
+ try
+ {
+ FileAccessService fileAccessService
+ = UtilActivator.getFileAccessService();
+
+ avatarDir
+ = fileAccessService.getPrivatePersistentDirectory(
+ avatarDirPath);
+ avatarFile
+ = fileAccessService.getPrivatePersistentFile(
+ avatarDirPath + File.separator + avatarFileName);
+
+ if(!avatarFile.exists())
+ {
+ if (!avatarDir.exists() && !avatarDir.mkdirs())
+ {
+ throw
+ new IOException(
+ "Failed to create directory: "
+ + avatarDir.getAbsolutePath());
+ }
+
+ if (!avatarFile.createNewFile())
+ {
+ throw
+ new IOException(
+ "Failed to create file"
+ + avatarFile.getAbsolutePath());
+ }
+ }
+
+ FileOutputStream fileOutStream = new FileOutputStream(avatarFile);
+
+ try
+ {
+ fileOutStream.write(avatarBytes);
+ fileOutStream.flush();
+ }
+ finally
+ {
+ fileOutStream.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.error(
+ "Failed to store avatar. dir =" + avatarDir
+ + " file=" + avatarFile,
+ ex);
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/util/GuiUtils.java b/src/net/java/sip/communicator/util/GuiUtils.java
index a106bde..aad1825 100644
--- a/src/net/java/sip/communicator/util/GuiUtils.java
+++ b/src/net/java/sip/communicator/util/GuiUtils.java
@@ -59,6 +59,23 @@ public class GuiUtils
// European equivalent.
private static final Map<Character, Character> DIGIT_MAPPINGS;
+ /**
+ * Characters and their replacement in created folder names
+ */
+ private final static String[][] ESCAPE_SEQUENCES = new String[][]
+ {
+ {"&", "&_amp"},
+ {"/", "&_sl"},
+ {"\\\\", "&_bs"}, // the char \
+ {":", "&_co"},
+ {"\\*", "&_as"}, // the char *
+ {"\\?", "&_qm"}, // the char ?
+ {"\"", "&_pa"}, // the char "
+ {"<", "&_lt"},
+ {">", "&_gt"},
+ {"\\|", "&_pp"} // the char |
+ };
+
static
{
HashMap<Character, Character> digitMap
@@ -644,4 +661,24 @@ public class GuiUtils
updateComponentTreeUI0(children[i]);
}
}
+
+ /**
+ * Replaces the characters that we must escape used for the created
+ * filename.
+ *
+ * @param string the <tt>String</tt> which is to have its characters escaped
+ * @return a <tt>String</tt> derived from the specified <tt>id</tt> by
+ * escaping characters
+ */
+ public static String escapeFileNameSpecialCharacters(String string)
+ {
+ String resultId = string;
+
+ for (int j = 0; j < ESCAPE_SEQUENCES.length; j++)
+ {
+ resultId = resultId.
+ replaceAll(ESCAPE_SEQUENCES[j][0], ESCAPE_SEQUENCES[j][1]);
+ }
+ return resultId;
+ }
}
diff --git a/src/net/java/sip/communicator/util/ImageUtils.java b/src/net/java/sip/communicator/util/ImageUtils.java
index 002dcde..dd5933d 100644
--- a/src/net/java/sip/communicator/util/ImageUtils.java
+++ b/src/net/java/sip/communicator/util/ImageUtils.java
@@ -168,7 +168,7 @@ public class ImageUtils
g.setComposite(AlphaComposite.Src);
AntialiasingManager.activateAntialiasing(g);
g.setColor(Color.WHITE);
- g.fillRoundRect(0, 0, scaledImageWidth, scaledImageHeight, 15, 15);
+ g.fillRoundRect(0, 0, scaledImageWidth, scaledImageHeight, 5, 5);
// We use SrcAtop, which effectively uses the
// alpha value as a coverage value for each pixel stored in the
diff --git a/src/net/java/sip/communicator/util/UtilActivator.java b/src/net/java/sip/communicator/util/UtilActivator.java
index e4f523b..78d6c5e 100644
--- a/src/net/java/sip/communicator/util/UtilActivator.java
+++ b/src/net/java/sip/communicator/util/UtilActivator.java
@@ -18,6 +18,7 @@ import net.java.sip.communicator.service.netaddr.*;
import net.java.sip.communicator.service.resources.*;
import org.jitsi.service.configuration.*;
+import org.jitsi.service.fileaccess.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.resources.*;
import org.osgi.framework.*;
@@ -51,6 +52,8 @@ public class UtilActivator
private static UIService uiService;
+ private static FileAccessService fileAccessService;
+
private static BundleContext bundleContext;
/**
@@ -239,6 +242,23 @@ public class UtilActivator
}
/**
+ * Returns the <tt>FileAccessService</tt> obtained from the bundle context.
+ *
+ * @return the <tt>FileAccessService</tt> obtained from the bundle context
+ */
+ public static FileAccessService getFileAccessService()
+ {
+ if (fileAccessService == null)
+ {
+ fileAccessService
+ = ServiceUtils.getService(
+ bundleContext,
+ FileAccessService.class);
+ }
+ return fileAccessService;
+ }
+
+ /**
* Returns the {@link MediaConfigurationService} instance registered in the
* <tt>BundleContext</tt> of the <tt>UtilActivator</tt>.
*
diff --git a/src/net/java/sip/communicator/util/swing/OrderedTransparentPanel.java b/src/net/java/sip/communicator/util/swing/OrderedTransparentPanel.java
index 9cc9367..ebc358e 100644
--- a/src/net/java/sip/communicator/util/swing/OrderedTransparentPanel.java
+++ b/src/net/java/sip/communicator/util/swing/OrderedTransparentPanel.java
@@ -18,7 +18,7 @@ public class OrderedTransparentPanel
extends TransparentPanel
{
private static final long serialVersionUID = 0L;
-
+
public Component add(Component comp)
{
if(comp instanceof OrderedComponent)
@@ -54,7 +54,7 @@ public class OrderedTransparentPanel
int cIx;
if(c instanceof OrderedComponent)
{
- cIx = ((OrderedComponent)c).getIndex();
+ cIx = ((OrderedComponent) c).getIndex();
if(orederIndex < cIx)
{
diff --git a/src/net/java/sip/communicator/util/swing/SIPCommButton.java b/src/net/java/sip/communicator/util/swing/SIPCommButton.java
index cbdea52..db40d4d 100755
--- a/src/net/java/sip/communicator/util/swing/SIPCommButton.java
+++ b/src/net/java/sip/communicator/util/swing/SIPCommButton.java
@@ -221,19 +221,11 @@ public class SIPCommButton
g.setColor(new Color(1.0f, 1.0f, 1.0f, visibility));
- if (this.bgImage != null)
+ if (this.bgImage == null
+ && (isContentAreaFilled() || (visibility != 0.0f)))
{
g.fillRoundRect(
- this.getWidth() / 2 - this.bgImage.getWidth(null) / 2,
- this.getHeight() / 2 - this.bgImage.getHeight(null) / 2,
- bgImage.getWidth(null),
- bgImage.getHeight(null),
- 10, 10);
- }
- else if (isContentAreaFilled() || (visibility != 0.0f))
- {
- g.fillRoundRect(
- 0, 0, this.getWidth(), this.getHeight(), 10, 10);
+ 0, 0, this.getWidth(), this.getHeight(), 8, 8);
}
}
diff --git a/src/net/java/sip/communicator/util/swing/SIPCommTextButton.java b/src/net/java/sip/communicator/util/swing/SIPCommTextButton.java
index 14b130e..eb6fe7c 100644
--- a/src/net/java/sip/communicator/util/swing/SIPCommTextButton.java
+++ b/src/net/java/sip/communicator/util/swing/SIPCommTextButton.java
@@ -92,6 +92,16 @@ public class SIPCommTextButton extends JButton
}
/**
+ * Return the background image.
+ *
+ * @return the background image of this button
+ */
+ public Image getBgImage()
+ {
+ return bgImage;
+ }
+
+ /**
* Overrides the <code>paintComponent</code> method of <tt>JButton</tt> to
* paint the button background and icon, and all additional effects of this
* configurable button.
diff --git a/src/net/java/sip/communicator/util/swing/SIPCommToggleButton.java b/src/net/java/sip/communicator/util/swing/SIPCommToggleButton.java
index 6a1ca46..a18e207 100644
--- a/src/net/java/sip/communicator/util/swing/SIPCommToggleButton.java
+++ b/src/net/java/sip/communicator/util/swing/SIPCommToggleButton.java
@@ -234,12 +234,17 @@ public class SIPCommToggleButton
}
}
+ int bgWidth = (bgImage != null)
+ ? bgImage.getWidth(null)
+ : getWidth();
+ int bgHeight = (bgImage != null)
+ ? bgImage.getHeight(null)
+ : getHeight();
+
if (iconImageFinal != null)
g.drawImage(iconImageFinal,
- (this.bgImage.getWidth(null) - iconImageFinal
- .getWidth(null)) / 2, (this.bgImage
- .getHeight(null) - iconImageFinal
- .getHeight(null)) / 2, this);
+ (bgWidth - iconImageFinal.getWidth(null)) / 2,
+ (bgHeight - iconImageFinal.getHeight(null)) / 2, this);
}
/**
diff --git a/src/net/java/sip/communicator/util/swing/SoundLevelIndicator.java b/src/net/java/sip/communicator/util/swing/SoundLevelIndicator.java
index 92b65dd..4e81bc9 100644
--- a/src/net/java/sip/communicator/util/swing/SoundLevelIndicator.java
+++ b/src/net/java/sip/communicator/util/swing/SoundLevelIndicator.java
@@ -32,11 +32,29 @@ public class SoundLevelIndicator
*/
private static final long serialVersionUID = 0L;
- private static final String SOUND_LEVEL_ACTIVE
- = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE";
+ private static final String SOUND_LEVEL_ACTIVE_LEFT
+ = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE_LEFT";
- private static final String SOUND_LEVEL_INACTIVE
- = "service.gui.soundlevel.SOUND_LEVEL_INACTIVE";
+ private static final String SOUND_LEVEL_ACTIVE_LEFT_GRADIENT
+ = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE_LEFT_GRADIENT";
+
+ private static final String SOUND_LEVEL_ACTIVE_MIDDLE
+ = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE_MIDDLE";
+
+ private static final String SOUND_LEVEL_ACTIVE_RIGHT
+ = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE_RIGHT";
+
+ private static final String SOUND_LEVEL_ACTIVE_RIGHT_GRADIENT
+ = "service.gui.soundlevel.SOUND_LEVEL_ACTIVE_RIGHT_GRADIENT";
+
+ private static final String SOUND_LEVEL_INACTIVE_LEFT
+ = "service.gui.soundlevel.SOUND_LEVEL_INACTIVE_LEFT";
+
+ private static final String SOUND_LEVEL_INACTIVE_MIDDLE
+ = "service.gui.soundlevel.SOUND_LEVEL_INACTIVE_MIDDLE";
+
+ private static final String SOUND_LEVEL_INACTIVE_RIGHT
+ = "service.gui.soundlevel.SOUND_LEVEL_INACTIVE_RIGHT";
/**
* The maximum possible sound level.
@@ -62,12 +80,42 @@ public class SoundLevelIndicator
/**
* Image when a sound level block is active
*/
- private ImageIcon soundLevelActiveImage;
+ private ImageIcon soundLevelActiveImageLeft;
+
+ /**
+ * Image when a sound level block is active
+ */
+ private ImageIcon soundLevelActiveImageLeftGradient;
+
+ /**
+ * Image when a sound level block is active
+ */
+ private ImageIcon soundLevelActiveImageMiddle;
+
+ /**
+ * Image when a sound level block is active
+ */
+ private ImageIcon soundLevelActiveImageRight;
+
+ /**
+ * Image when a sound level block is active
+ */
+ private ImageIcon soundLevelActiveImageRightGradient;
+
+ /**
+ * Image when a sound level block is not active
+ */
+ private ImageIcon soundLevelInactiveImageLeft;
/**
* Image when a sound level block is not active
*/
- private ImageIcon soundLevelInactiveImage;
+ private ImageIcon soundLevelInactiveImageMiddle;
+
+ /**
+ * Image when a sound level block is not active
+ */
+ private ImageIcon soundLevelInactiveImageRight;
/**
* Initializes a new <tt>SoundLevelIndicator</tt> instance.
@@ -143,12 +191,42 @@ public class SoundLevelIndicator
if (c instanceof JLabel)
{
+ Icon activeIcon = null;
+ Icon inactiveIcon = null;
+ if (i == 0)
+ {
+ if (activeSoundBarCount == 1)
+ activeIcon = soundLevelActiveImageLeftGradient;
+ else
+ {
+ activeIcon = soundLevelActiveImageLeft;
+ inactiveIcon = soundLevelInactiveImageLeft;
+ }
+ }
+ else if (i == activeSoundBarCount - 1)
+ {
+ if (i == components.length - 1)
+ activeIcon = soundLevelActiveImageRight;
+ else
+ activeIcon = soundLevelActiveImageRightGradient;
+ }
+ else if (i == components.length - 1)
+ {
+ inactiveIcon = soundLevelInactiveImageRight;
+ }
+ else
+ {
+ activeIcon = soundLevelActiveImageMiddle;
+ inactiveIcon = soundLevelInactiveImageMiddle;
+ }
+
((JLabel) c).setIcon(
(i < activeSoundBarCount)
- ? soundLevelActiveImage
- : soundLevelInactiveImage);
+ ? activeIcon
+ : inactiveIcon);
}
}
+
repaint();
}
@@ -183,7 +261,13 @@ public class SoundLevelIndicator
}
while (soundBarCount < newSoundBarCount)
{
- JLabel soundBar = new JLabel(soundLevelInactiveImage);
+ JLabel soundBar;
+ if (soundBarCount == 0)
+ soundBar = new JLabel(soundLevelInactiveImageLeft);
+ else if (soundBarCount == newSoundBarCount - 1)
+ soundBar = new JLabel(soundLevelInactiveImageRight);
+ else
+ soundBar = new JLabel(soundLevelInactiveImageMiddle);
soundBar.setVerticalAlignment(JLabel.CENTER);
add(soundBar);
@@ -206,7 +290,7 @@ public class SoundLevelIndicator
*/
private int getSoundBarCount(int width)
{
- int soundBarWidth = soundLevelActiveImage.getIconWidth();
+ int soundBarWidth = soundLevelActiveImageLeft.getIconWidth();
return width / soundBarWidth;
}
@@ -218,28 +302,43 @@ public class SoundLevelIndicator
{
ResourceManagementService resources = UtilActivator.getResources();
- soundLevelActiveImage = resources.getImage(SOUND_LEVEL_ACTIVE);
- soundLevelInactiveImage = resources.getImage(SOUND_LEVEL_INACTIVE);
+ soundLevelActiveImageLeft
+ = resources.getImage(SOUND_LEVEL_ACTIVE_LEFT);
+ soundLevelActiveImageLeftGradient
+ = resources.getImage(SOUND_LEVEL_ACTIVE_LEFT_GRADIENT);
+ soundLevelActiveImageMiddle
+ = resources.getImage(SOUND_LEVEL_ACTIVE_MIDDLE);
+ soundLevelActiveImageRight
+ = resources.getImage(SOUND_LEVEL_ACTIVE_RIGHT);
+ soundLevelActiveImageRightGradient
+ = resources.getImage(SOUND_LEVEL_ACTIVE_RIGHT_GRADIENT);
+
+ soundLevelInactiveImageLeft
+ = resources.getImage(SOUND_LEVEL_INACTIVE_LEFT);
+ soundLevelInactiveImageMiddle
+ = resources.getImage(SOUND_LEVEL_INACTIVE_MIDDLE);
+ soundLevelInactiveImageRight
+ = resources.getImage(SOUND_LEVEL_INACTIVE_RIGHT);
if (!isPreferredSizeSet())
{
int preferredHeight = 0;
int preferredWidth = 0;
- if (soundLevelActiveImage != null)
+ if (soundLevelActiveImageLeft != null)
{
- int height = soundLevelActiveImage.getIconHeight();
- int width = soundLevelActiveImage.getIconWidth();
+ int height = soundLevelActiveImageLeft.getIconHeight();
+ int width = soundLevelActiveImageLeft.getIconWidth();
if (preferredHeight < height)
preferredHeight = height;
if (preferredWidth < width)
preferredWidth = width;
}
- if (soundLevelInactiveImage != null)
+ if (soundLevelInactiveImageLeft != null)
{
- int height = soundLevelInactiveImage.getIconHeight();
- int width = soundLevelInactiveImage.getIconWidth();
+ int height = soundLevelInactiveImageLeft.getIconHeight();
+ int width = soundLevelInactiveImageLeft.getIconWidth();
if (preferredHeight < height)
preferredHeight = height;
diff --git a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTabbedPaneUI.java b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTabbedPaneUI.java
index 554119b..93f7c6c 100644
--- a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTabbedPaneUI.java
+++ b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTabbedPaneUI.java
@@ -78,7 +78,7 @@ public class SIPCommTabbedPaneUI
public static final int BUTTONSIZE = 15;
- public static final int WIDTHDELTA = 10;
+ public static final int WIDTHDELTA = 1;
private static final Border PRESSEDBORDER = new SoftBevelBorder(
SoftBevelBorder.LOWERED);
@@ -237,9 +237,10 @@ public class SIPCommTabbedPaneUI
tabPane.putClientProperty("html", null);
- iconRect.x = tabRect.x + 5;
+ iconRect.y = iconRect.y + 2;
+ iconRect.x = tabRect.x + 7;
+ textRect.y = textRect.y + 2;
textRect.x = iconRect.x + iconRect.width + 5;
-
}
protected MouseListener createMouseListener()
@@ -649,8 +650,7 @@ public class SIPCommTabbedPaneUI
if (cropShape)
{
save = g2.getClip();
- g2
- .clipRect(tabRect.x, tabRect.y, tabRect.width,
+ g2.clipRect(tabRect.x, tabRect.y, tabRect.width,
tabRect.height);
}
@@ -687,7 +687,7 @@ public class SIPCommTabbedPaneUI
else if (isOver || isSelected)
{
int dx = tabRect.x + tabRect.width - BUTTONSIZE - WIDTHDELTA;
- int dy = (tabRect.y + tabRect.height) / 2 - 7;
+ int dy = (tabRect.y + tabRect.height) / 2 - 3;
if (isCloseButtonEnabled)
paintCloseIcon(g2, dx, dy, isOver);
diff --git a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
index 5b68197..1b1a643 100644
--- a/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
+++ b/src/net/java/sip/communicator/util/swing/plaf/SIPCommTextFieldUI.java
@@ -183,7 +183,7 @@ public class SIPCommTextFieldUI
if(isRounded)
{
g2.fillRoundRect(1, 1, c.getWidth() - 1, c.getHeight() - 1,
- 20, 20);
+ 8, 8);
}
else
{
@@ -225,8 +225,8 @@ public class SIPCommTextFieldUI
if(isRounded)
{
- g2.drawRoundRect(0, 0, c.getWidth() - 1, c.getHeight() - 1,
- 20, 20);
+ g2.drawRoundRect(
+ 0, 0, c.getWidth() - 1, c.getHeight() - 1, 8, 8);
}
else
{
diff --git a/src/net/java/sip/communicator/util/util.manifest.mf b/src/net/java/sip/communicator/util/util.manifest.mf
index 64557f4..7e08cd4 100644
--- a/src/net/java/sip/communicator/util/util.manifest.mf
+++ b/src/net/java/sip/communicator/util/util.manifest.mf
@@ -41,6 +41,7 @@ Import-Package: com.sun.awt,
org.jitsi.service.neomedia,
org.jitsi.service.neomedia.codec,
org.jitsi.service.resources,
+ org.jitsi.service.fileaccess,
org.jitsi.util,
org.jitsi.util.event,
org.jitsi.util.swing,