- Moves the "full screen" and "transfer call" buttons from the status bar to the call window button bar.

- Prints DTMF chars, when dtmf key is typed or dial pad button is clicked
- Fixes DTMF tones, when typed with modifiers (SHIFT-# for example)
cusax-fix
Yana Stamcheva 16 years ago
parent 51e5668dbd
commit 2667743cbd

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 B

After

Width:  |  Height:  |  Size: 483 B

@ -34,36 +34,96 @@ public class CallDialog
CallChangeListener,
CallPeerConferenceListener
{
/**
* The dial button name.
*/
private static final String DIAL_BUTTON = "DIAL_BUTTON";
/**
* The conference button name.
*/
private static final String CONFERENCE_BUTTON = "CONFERENCE_BUTTON";
/**
* The hang up button name.
*/
private static final String HANGUP_BUTTON = "HANGUP_BUTTON";
/**
* The dial pad dialog opened when the dial button is clicked.
*/
private DialpadDialog dialpadDialog;
/**
* The handler for DTMF tones.
*/
private DTMFHandler dtmfHandler;
/**
* The content pane of this dialog.
*/
private final Container contentPane = getContentPane();
/**
* The panel containing call settings.
*/
private final TransparentPanel settingsPanel = new TransparentPanel();
/**
* The panel representing the call. For conference calls this would be an
* instance of <tt>ConferenceCallPanel</tt> and for one-to-one calls this
* would be an instance of <tt>OneToOneCallPanel</tt>.
*/
private JComponent callPanel = null;
/**
* The hold button.
*/
private HoldButton holdButton;
/**
* The mute button.
*/
private MuteButton muteButton;
/**
* The video button.
*/
private LocalVideoButton videoButton;
/**
* The transfer call button.
*/
private TransferCallButton transferCallButton;
/**
* The full screen button.
*/
private FullScreenButton fullScreenButton;
/**
* The call represented in this dialog.
*/
private final Call call;
/**
* Indicates if the last call was a conference call.
*/
private boolean isLastConference = false;
/**
* The start date time of the call.
*/
private Date callStartDate;
/**
* Indicates if the call timer has been started.
*/
private boolean isCallTimerStarted = false;
/**
* A timer to count call duration.
*/
private Timer callDurationTimer;
/**
@ -141,6 +201,8 @@ private void init()
holdButton = new HoldButton(call);
muteButton = new MuteButton(call);
videoButton = new LocalVideoButton(call);
transferCallButton = new TransferCallButton(call);
fullScreenButton = new FullScreenButton(this);
dialButton.setName(DIAL_BUTTON);
dialButton.setToolTipText(
@ -167,7 +229,11 @@ private void init()
settingsPanel.add(muteButton);
if (!isLastConference)
{
settingsPanel.add(videoButton);
settingsPanel.add(transferCallButton);
settingsPanel.add(fullScreenButton);
}
buttonsPanel.add(settingsPanel, BorderLayout.WEST);
buttonsPanel.add(hangupButton, BorderLayout.EAST);
@ -175,8 +241,7 @@ private void init()
buttonsPanel.setBorder(
new ExtendedEtchedBorder(EtchedBorder.LOWERED, 1, 0, 0, 0));
dtmfHandler = new DTMFHandler(this.call);
dtmfHandler.addParent(this);
dtmfHandler = new DTMFHandler(this);
}
/**
@ -391,8 +456,8 @@ public void run()
if (isLastConference)
{
contentPane.remove(callPanel);
callPanel
= new ConferenceCallPanel(CallDialog.this, call);
updateCurrentCallPanel(
new ConferenceCallPanel(CallDialog.this, call));
contentPane.add(callPanel, BorderLayout.CENTER);
}
// We're still in one-to-one call and we receive the
@ -463,8 +528,8 @@ public void run()
{
settingsPanel.remove(videoButton);
contentPane.remove(callPanel);
callPanel
= new ConferenceCallPanel(CallDialog.this, call);
updateCurrentCallPanel(
new ConferenceCallPanel(CallDialog.this, call));
contentPane.add(callPanel, BorderLayout.CENTER);
}
}
@ -595,8 +660,8 @@ public void run()
// his members
if (singlePeer != null
&& !singlePeer.isConferenceFocus())
callPanel = new OneToOneCallPanel(
CallDialog.this, call, singlePeer);
updateCurrentCallPanel(new OneToOneCallPanel(
CallDialog.this, call, singlePeer));
else if(singlePeer.isConferenceFocus())
{
((ConferenceCallPanel) callPanel)
@ -664,4 +729,36 @@ public void refreshWindow()
else
contentPane.repaint();
}
/**
* Returns the currently used <tt>CallRenderer</tt>.
* @return the currently used <tt>CallRenderer</tt>
*/
public CallRenderer getCurrentCallRenderer()
{
return (CallRenderer) callPanel;
}
/**
* Replaces the current call panel with the given one.
* @param callPanel the <tt>JComponent</tt> to replace the current
* call panel
*/
private void updateCurrentCallPanel(JComponent callPanel)
{
this.callPanel = callPanel;
if (callPanel instanceof OneToOneCallPanel)
{
settingsPanel.add(videoButton);
settingsPanel.add(transferCallButton);
settingsPanel.add(fullScreenButton);
}
else
{
settingsPanel.remove(videoButton);
settingsPanel.remove(transferCallButton);
settingsPanel.remove(fullScreenButton);
}
}
}

@ -6,8 +6,6 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import javax.swing.*;
/**
@ -68,19 +66,6 @@ public void securityOn( String securityString,
*/
public void securityOff();
/**
* Enters in full screen view mode.
*/
public void enterFullScreen();
/**
* Exits from the full screen view mode by specifying the full screen window
* previously created.
*
* @param fullScreenWindow the window previously shown in full screen mode
*/
public void exitFullScreen(Window fullScreenWindow);
/**
* Sets the audio security on or off.
*
@ -117,6 +102,12 @@ public void securityOn( String securityString,
*/
public CallPeerAdapter getCallPeerAdapter();
/**
* Prints the given DTMG character through this <tt>CallPeerRenderer</tt>.
* @param dtmfChar the DTMF char to print
*/
public void printDTMFTone(char dtmfChar);
/**
* Returns the parent <tt>CallDialog</tt> containing this renderer.
* @return the parent <tt>CallDialog</tt> containing this renderer

@ -13,7 +13,6 @@
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.swing.*;
/**
@ -25,56 +24,6 @@
*/
public class CallPeerRendererUtils
{
/**
* Creates a new <code>Component</code> representing a UI means to transfer
* the <code>Call</code> of the associated <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported.
*
* @param callPeer the <tt>CallPeer</tt>, for which we create the button
* @return a new <code>Component</code> representing the UI means to
* transfer the <code>Call</code> of <code>callPeer</code> or
* <tt>null</tt> if call-transfer is unsupported
*/
public static Component createTransferCallButton(CallPeer callPeer)
{
if (callPeer != null)
{
OperationSetAdvancedTelephony telephony =
callPeer.getProtocolProvider()
.getOperationSet(OperationSetAdvancedTelephony.class);
if (telephony != null)
return new TransferCallButton(callPeer);
}
return null;
}
/**
* Creates a new <tt>Component</tt> through which the user would be able to
* enter in full screen mode.
*
* @param renderer the renderer through which we enter in full screen mode
* @return the newly created component
*/
public static Component createEnterFullScreenButton(
final CallPeerRenderer renderer)
{
SIPCommButton button =
new SIPCommButton(ImageLoader
.getImage(ImageLoader.ENTER_FULL_SCREEN_BUTTON));
button.setToolTipText(GuiActivator.getResources().getI18NString(
"service.gui.ENTER_FULL_SCREEN_TOOL_TIP"));
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
renderer.enterFullScreen();
}
});
return button;
}
/**
* Creates a new <tt>Component</tt> through which the user would be able to
* exit the full screen mode.
@ -83,7 +32,7 @@ public void actionPerformed(ActionEvent event)
* @return the newly created component
*/
public static Component createExitFullScreenButton(
final CallPeerRenderer renderer)
final CallRenderer renderer)
{
JButton button =
new SIPCommButton(
@ -96,12 +45,7 @@ public static Component createExitFullScreenButton(
{
public void actionPerformed(ActionEvent event)
{
Object source = event.getSource();
Frame fullScreenFrame =
(source instanceof Component) ? TransferCallButton
.getFrame((Component) source) : null;
renderer.exitFullScreen(fullScreenFrame);
renderer.exitFullScreen();
}
});
return button;
@ -164,4 +108,32 @@ public static Component createButtonBar(boolean heavyweight,
}
return buttonBar;
}
/**
* Gets the first <tt>Frame</tt> in the ancestor <tt>Component</tt>
* hierarchy of a specific <tt>Component</tt>.
* <p>
* The located <tt>Frame</tt> (if any) is often used as the owner of
* <tt>Dialog</tt>s opened by the specified <tt>Component</tt> in
* order to provide natural <tt>Frame</tt> ownership.
*
* @param component the <tt>Component</tt> which is to have its
* <tt>Component</tt> hierarchy examined for <tt>Frame</tt>
* @return the first <tt>Frame</tt> in the ancestor
* <tt>Component</tt> hierarchy of the specified <tt>Component</tt>;
* <tt>null</tt>, if no such <tt>Frame</tt> was located
*/
public static Frame getFrame(Component component)
{
while (component != null)
{
Container container = component.getParent();
if (container instanceof Frame)
return (Frame) container;
component = container;
}
return null;
}
}

@ -0,0 +1,55 @@
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>CallRenderer</tt> represents a renderer for a call. All user
* interfaces representing a call should implement this interface.
*
* @author Yana Stamcheva
*/
public interface CallRenderer
{
/**
* Returns the call represented by this call renderer.
* @return the call represented by this call renderer
*/
public Call getCall();
/**
* Enters in full screen mode.
*/
public void enterFullScreen();
/**
* Exits the full screen mode.
*/
public void exitFullScreen();
/**
* Ensures the size of the window.
* @param component the component, which size should be considered
* @param width the desired width
* @param height the desired height
*/
public void ensureSize(Component component, int width, int height);
/**
* Returns the parent call dialog, where this renderer is contained.
* @return the parent call dialog, where this renderer is contained
*/
public CallDialog getCallDialog();
/**
* Returns the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>.
* @param callPeer the <tt>CallPeer</tt>, for which we're looking for a
* renderer
* @return the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>
*/
public CallPeerRenderer getCallPeerRenderer(CallPeer callPeer);
}

@ -32,9 +32,9 @@ public class DTMFHandler
private final Logger logger = Logger.getLogger(DTMFHandler.class);
/**
* Current call.
* The call dialog, where this handler is registered.
*/
private Call call;
private CallDialog callDialog;
/**
* Parent windows we listen key entering on them.
@ -56,92 +56,111 @@ public class DTMFHandler
new DTMFToneInfo(
DTMFTone.DTMF_1,
KeyEvent.VK_1,
'1',
ImageLoader.ONE_DIAL_BUTTON,
SoundProperties.DIAL_ONE),
new DTMFToneInfo(
DTMFTone.DTMF_2,
KeyEvent.VK_2,
'2',
ImageLoader.TWO_DIAL_BUTTON,
SoundProperties.DIAL_TWO),
new DTMFToneInfo(
DTMFTone.DTMF_3,
KeyEvent.VK_3,
'3',
ImageLoader.THREE_DIAL_BUTTON,
SoundProperties.DIAL_THREE),
new DTMFToneInfo(
DTMFTone.DTMF_4,
KeyEvent.VK_4,
'4',
ImageLoader.FOUR_DIAL_BUTTON,
SoundProperties.DIAL_FOUR),
new DTMFToneInfo(
DTMFTone.DTMF_5,
KeyEvent.VK_5,
'5',
ImageLoader.FIVE_DIAL_BUTTON,
SoundProperties.DIAL_FIVE),
new DTMFToneInfo(
DTMFTone.DTMF_6,
KeyEvent.VK_6,
'6',
ImageLoader.SIX_DIAL_BUTTON,
SoundProperties.DIAL_SIX),
new DTMFToneInfo(
DTMFTone.DTMF_7,
KeyEvent.VK_7,
'7',
ImageLoader.SEVEN_DIAL_BUTTON,
SoundProperties.DIAL_SEVEN),
new DTMFToneInfo(
DTMFTone.DTMF_8,
KeyEvent.VK_8,
'8',
ImageLoader.EIGHT_DIAL_BUTTON,
SoundProperties.DIAL_EIGHT),
new DTMFToneInfo(
DTMFTone.DTMF_9,
KeyEvent.VK_9,
'9',
ImageLoader.NINE_DIAL_BUTTON,
SoundProperties.DIAL_NINE),
new DTMFToneInfo(
DTMFTone.DTMF_A,
KeyEvent.VK_A,
'a',
null,
null),
new DTMFToneInfo(
DTMFTone.DTMF_B,
KeyEvent.VK_B,
'b',
null,
null),
new DTMFToneInfo(
DTMFTone.DTMF_C,
KeyEvent.VK_C,
'c',
null,
null),
new DTMFToneInfo(
DTMFTone.DTMF_D,
KeyEvent.VK_D,
'd',
null,
null),
new DTMFToneInfo(
DTMFTone.DTMF_STAR,
KeyEvent.VK_ASTERISK,
'*',
ImageLoader.STAR_DIAL_BUTTON,
SoundProperties.DIAL_STAR),
new DTMFToneInfo(
DTMFTone.DTMF_0,
KeyEvent.VK_0,
'0',
ImageLoader.ZERO_DIAL_BUTTON,
SoundProperties.DIAL_ZERO),
new DTMFToneInfo(
DTMFTone.DTMF_SHARP,
KeyEvent.VK_NUMBER_SIGN,
'#',
ImageLoader.DIEZ_DIAL_BUTTON,
SoundProperties.DIAL_DIEZ)
};
/**
* Creates DTMF handler for a call.
* @param call
* @param callDialog the <tt>CallDialog</tt>, where this handler is
* registered
*/
public DTMFHandler(Call call)
public DTMFHandler(CallDialog callDialog)
{
this.call = call;
this.callDialog = callDialog;
this.addParent(callDialog);
KeyboardFocusManager keyManager
= KeyboardFocusManager.getCurrentKeyboardFocusManager();
@ -186,7 +205,8 @@ public boolean dispatchKeyEvent(KeyEvent e)
for (int i = 0; i < availableTones.length; i++)
{
DTMFToneInfo info = availableTones[i];
if(info.keyCode == e.getKeyCode())
if(info.keyChar == e.getKeyChar())
{
if(e.getID() == KeyEvent.KEY_PRESSED)
{
@ -228,7 +248,6 @@ void startSendingDtmfTone(String toneValue)
*/
private synchronized void startSendingDtmfTone(DTMFToneInfo info)
{
AudioNotifierService audioNotifier = GuiActivator.getAudioNotifier();
if(info.sound != null)
@ -243,7 +262,8 @@ private synchronized void startSendingDtmfTone(DTMFToneInfo info)
currentlyPlayingAudio.playInLoop(10);
}
Iterator<? extends CallPeer> callPeers = this.call.getCallPeers();
Iterator<? extends CallPeer> callPeers
= this.callDialog.getCurrentCallRenderer().getCall().getCallPeers();
try
{
@ -251,12 +271,19 @@ private synchronized void startSendingDtmfTone(DTMFToneInfo info)
{
CallPeer peer = callPeers.next();
OperationSetDTMF dtmfOpSet
= peer
.getProtocolProvider()
.getOperationSet(OperationSetDTMF.class);
= peer.getProtocolProvider()
.getOperationSet(OperationSetDTMF.class);
if (dtmfOpSet != null)
{
dtmfOpSet.startSendingDTMF(peer, info.tone);
CallPeerRenderer peerRenderer
= callDialog.getCurrentCallRenderer()
.getCallPeerRenderer(peer);
if (peerRenderer != null)
peerRenderer.printDTMFTone(info.keyChar);
}
}
}
catch (Throwable e1)
@ -275,7 +302,8 @@ synchronized void stopSendingDtmfTone()
currentlyPlayingAudio = null;
Iterator<? extends CallPeer> callPeers = this.call.getCallPeers();
Iterator<? extends CallPeer> callPeers
= this.callDialog.getCurrentCallRenderer().getCall().getCallPeers();
try
{
@ -312,6 +340,11 @@ static class DTMFToneInfo
*/
int keyCode;
/**
* The char associated with this DTMF tone.
*/
char keyChar;
/**
* The image to display in buttons sending DTMFs.
*/
@ -326,14 +359,17 @@ static class DTMFToneInfo
* Creates DTMF extended info.
* @param tone the tone.
* @param keyCode its key code.
* @param keyChar the char associated with the DTMF
* @param imageID the image if any.
* @param sound the sound if any.
*/
public DTMFToneInfo(
DTMFTone tone, int keyCode, ImageID imageID, String sound)
DTMFTone tone, int keyCode, char keyChar,
ImageID imageID, String sound)
{
this.tone = tone;
this.keyCode = keyCode;
this.keyChar = keyChar;
this.imageID = imageID;
this.sound = sound;
}

@ -0,0 +1,53 @@
/*
* SIP Communicator, 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.*;
import net.java.sip.communicator.util.swing.*;
/**
* Represents the button, which is used to expand the video in full screen mode.
*
* @author Yana Stamcheva
*/
public class FullScreenButton
extends SIPCommButton
{
/**
* Initializes a new <tt>FullScreenButton</tt> instance which is to
* enter the full screen mode.
*
* @param callDialog the parent <tt>CallDialog</tt>, where this button is
* contained
*/
public FullScreenButton(final CallDialog callDialog)
{
super( ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
ImageLoader.getImage(ImageLoader.ENTER_FULL_SCREEN_BUTTON));
setToolTipText(GuiActivator.getResources().getI18NString(
"service.gui.ENTER_FULL_SCREEN_TOOL_TIP"));
addActionListener(new ActionListener()
{
/**
* Invoked when an action occurs.
*
* @param evt the <tt>ActionEvent</tt> instance containing the
* data associated with the action and the act of its
* performing
*/
public void actionPerformed(ActionEvent evt)
{
callDialog.getCurrentCallRenderer().enterFullScreen();
}
});
}
}

@ -6,6 +6,8 @@
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
@ -22,11 +24,36 @@
*/
public class OneToOneCallPanel
extends TransparentPanel
implements CallRenderer
{
/**
* The panel representing the underlying <tt>CallPeer</tt>.
*/
private OneToOneCallPeerPanel peerPanel;
/**
* The parent call dialog.
*/
private final CallDialog callDialog;
/**
* The underlying <tt>Call</tt>, this panel is representing.
*/
private final Call call;
/**
* The underlying <tt>CallPeer</tt>.
*/
private final CallPeer callPeer;
/**
* The current <code>Window</code> being displayed in full-screen. Because
* the AWT API with respect to the full-screen support doesn't seem
* sophisticated enough, the field is used sparingly i.e. when there are no
* other means (such as a local variable) of acquiring the instance.
*/
private Window fullScreenWindow;
/**
* Creates a call panel for the corresponding call, by specifying the
* call type (incoming or outgoing) and the parent dialog.
@ -42,6 +69,8 @@ public OneToOneCallPanel( CallDialog callDialog,
super(new BorderLayout());
this.callDialog = callDialog;
this.call = call;
this.callPeer = callPeer;
this.setBorder(BorderFactory
.createEmptyBorder(5, 0, 5, 0));
@ -62,7 +91,7 @@ public void addCallPeerPanel(CallPeer peer)
{
if (peerPanel == null)
{
peerPanel = new OneToOneCallPeerPanel(callDialog, peer);
peerPanel = new OneToOneCallPeerPanel(this, peer);
this.add(peerPanel);
@ -85,4 +114,275 @@ public void addCallPeerPanel(CallPeer peer)
}
}
}
/**
* Enters full screen mode. Initializes all components for the full screen
* user interface.
*/
public void enterFullScreen()
{
// Create the main Components of the UI.
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setTitle(peerPanel.getPeerName());
frame.setUndecorated(true);
Component center = peerPanel.createCenter();
final Component buttonBar = createFullScreenButtonBar();
// Lay out the main Components of the UI.
final Container contentPane = frame.getContentPane();
contentPane.setLayout(new FullScreenLayout(false));
if (buttonBar != null)
contentPane.add(buttonBar, FullScreenLayout.SOUTH);
if (center != null)
contentPane.add(center, FullScreenLayout.CENTER);
// Full-screen windows usually have black backgrounds.
Color background = Color.black;
contentPane.setBackground(background);
CallPeerRendererUtils.setBackground(center, background);
class FullScreenListener
implements ContainerListener, KeyListener, WindowStateListener
{
public void componentAdded(ContainerEvent event)
{
Component child = event.getChild();
child.addKeyListener(this);
}
public void componentRemoved(ContainerEvent event)
{
Component child = event.getChild();
child.removeKeyListener(this);
}
public void keyPressed(KeyEvent event)
{
if (!event.isConsumed()
&& (event.getKeyCode() == KeyEvent.VK_ESCAPE))
{
event.consume();
exitFullScreen();
}
}
public void keyReleased(KeyEvent event)
{
}
public void keyTyped(KeyEvent event)
{
}
public void windowStateChanged(WindowEvent event)
{
switch (event.getID())
{
case WindowEvent.WINDOW_CLOSED:
case WindowEvent.WINDOW_DEACTIVATED:
case WindowEvent.WINDOW_ICONIFIED:
case WindowEvent.WINDOW_LOST_FOCUS:
exitFullScreen();
break;
}
}
}
FullScreenListener listener = new FullScreenListener();
// Exit on Escape.
CallPeerRendererUtils.addKeyListener(frame, listener);
// Activate the above features for the local and remote videos.
if (center instanceof Container)
((Container) center).addContainerListener(listener);
// Exit when the "full screen" looses its focus.
frame.addWindowStateListener(listener);
getGraphicsConfiguration().getDevice().setFullScreenWindow(frame);
this.fullScreenWindow = frame;
}
/**
* Exits the full screen mode.
*/
public void exitFullScreen()
{
GraphicsConfiguration graphicsConfig = getGraphicsConfiguration();
if (graphicsConfig != null)
graphicsConfig.getDevice().setFullScreenWindow(null);
if (fullScreenWindow != null)
{
if (fullScreenWindow.isVisible())
fullScreenWindow.setVisible(false);
fullScreenWindow.dispose();
fullScreenWindow = null;
}
}
private Component createFullScreenButtonBar()
{
Component[] buttons
= new Component[]
{
new HoldButton(call,
true,
CallPeerState.isOnHold(callPeer.getState())),
new MuteButton(call,
true,
callPeer.isMute()),
CallPeerRendererUtils.createExitFullScreenButton(this)
};
return CallPeerRendererUtils.createButtonBar(true, buttons);
}
/**
* Attempts to give a specific <tt>Component</tt> a visible rectangle with a
* specific width and a specific height if possible and sane.
*
* @param component the <tt>Component</tt> to be given a visible rectangle
* with the specified width and height
* @param width the width of the visible rectangle to be given to the
* specified <tt>Component</tt>
* @param height the height of the visible rectangle to be given to the
* specified <tt>Component</tt>
*/
public void ensureSize(Component component, int width, int height)
{
Frame frame = CallPeerRendererUtils.getFrame(component);
if (frame == null)
return;
else if ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH)
== Frame.MAXIMIZED_BOTH)
{
/*
* Forcing the size of a Component which is displayed in a maximized
* window does not sound like anything we want to do.
*/
return;
}
else if (frame.equals(frame.getGraphicsConfiguration()
.getDevice().getFullScreenWindow()))
{
/*
* Forcing the size of a Component which is displayed in a
* full-screen window does not sound like anything we want to do.
*/
return;
}
else
{
Insets frameInsets = frame.getInsets();
/*
* XXX This is a very wild guess and it is very easy to break
* because it wants to have the component with the specified width
* yet it forces the Frame to have nearly the same width without
* knowing anything about the layouts of the containers between the
* Frame and the component.
*/
int newFrameWidth = width + frameInsets.left + frameInsets.right;
Dimension frameSize = frame.getSize();
Dimension componentSize = component.getSize();
int newFrameHeight
= frameSize.height + height - componentSize.height;
// Don't get bigger than the screen.
Rectangle screenBounds
= frame.getGraphicsConfiguration().getBounds();
if (newFrameWidth > screenBounds.width)
newFrameWidth = screenBounds.width;
if (newFrameHeight > screenBounds.height)
newFrameHeight = screenBounds.height;
// Don't go out of the screen.
Point frameLocation = frame.getLocation();
int newFrameX = frameLocation.x;
int newFrameY = frameLocation.y;
int xDelta
= (newFrameX + newFrameWidth)
- (screenBounds.x + screenBounds.width);
int yDelta
= (newFrameY + newFrameHeight)
- (screenBounds.y + screenBounds.height);
if (xDelta > 0)
{
newFrameX -= xDelta;
if (newFrameX < screenBounds.x)
newFrameX = screenBounds.x;
}
if (yDelta > 0)
{
newFrameY -= yDelta;
if (newFrameY < screenBounds.y)
newFrameY = screenBounds.y;
}
/*
* XXX Unreliable because VideoRenderer Components such as the
* Component of the AWTRenderer on Linux overrides its
* #getPreferredSize().
*/
component.setPreferredSize(new Dimension(width, height));
/*
* If we're going to make too small a change, don't even bother.
* Besides, we don't want some weird recursive resizing.
*/
int frameWidthDelta = newFrameWidth - frameSize.width;
int frameHeightDelta = newFrameHeight - frameSize.height;
if ((frameWidthDelta < -1)
|| (frameWidthDelta > 1)
|| (frameHeightDelta < -1)
|| (frameHeightDelta > 1))
{
frame.setBounds(
newFrameX, newFrameY,
newFrameWidth, newFrameHeight);
}
}
}
/**
* Returns the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>.
* @param callPeer the <tt>CallPeer</tt>, for which we're looking for a
* renderer
* @return the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>
*/
public CallPeerRenderer getCallPeerRenderer(CallPeer callPeer)
{
if (callPeer.equals(this.callPeer))
return peerPanel;
return null;
}
/**
* Returns the call represented by this call renderer.
* @return the call represented by this call renderer
*/
public Call getCall()
{
return call;
}
/**
* Returns the parent call dialog, where this renderer is contained.
* @return the parent call dialog, where this renderer is contained
*/
public CallDialog getCallDialog()
{
return callDialog;
}
}

@ -68,6 +68,11 @@ public class OneToOneCallPeerPanel
*/
private final JLabel holdStatusLabel = new JLabel();
/**
* The DTMF label.
*/
private final JLabel dtmfLabel = new JLabel();
/**
* The <tt>Component</tt>s showing the avatar of the underlying call peer.
* <p>
@ -109,9 +114,9 @@ public class OneToOneCallPeerPanel
private OperationSetVideoTelephony videoTelephony;
/**
* The parent dialog, where this panel is contained.
* The renderer of the call.
*/
private final CallDialog callDialog;
private final CallRenderer callRenderer;
/**
* The component showing the local video.
@ -119,25 +124,20 @@ public class OneToOneCallPeerPanel
private Component localVideo;
/**
* The current <code>Window</code> being displayed in full-screen. Because
* the AWT API with respect to the full-screen support doesn't seem
* sophisticated enough, the field is used sparingly i.e. when there are no
* other means (such as a local variable) of acquiring the instance.
* The <tt>CallPeer</tt>, which is rendered in this panel.
*/
private Window fullScreenWindow;
private CallPeer callPeer;
/**
* Creates a <tt>CallPeerPanel</tt> for the given call peer.
*
* @param callDialog the parent dialog containing this call peer panel
* @param callRenderer the renderer of the call
* @param callPeer the <tt>CallPeer</tt> represented in this panel
*/
public OneToOneCallPeerPanel( CallDialog callDialog,
public OneToOneCallPeerPanel( CallRenderer callRenderer,
CallPeer callPeer)
{
this.callDialog = callDialog;
this.callRenderer = callRenderer;
this.callPeer = callPeer;
this.peerName = callPeer.getDisplayName();
@ -205,7 +205,7 @@ public OneToOneCallPeerPanel( CallDialog callDialog,
* area of this <code>CallPeerPanel</code> which displays the
* photo of the <code>CallPeer</code> or the video if any
*/
private Component createCenter()
Component createCenter()
{
final JLabel photoLabel = new JLabel(getPhotoLabelIcon());
@ -281,33 +281,17 @@ private Component createStatusBar()
{
// stateLabel
callStatusLabel.setForeground(Color.WHITE);
dtmfLabel.setForeground(Color.WHITE);
callStatusLabel.setText(callPeer.getState().getStateString());
PeerStatusPanel statusPanel = new PeerStatusPanel(
new FlowLayout(FlowLayout.CENTER, 10, 0));
TransparentPanel statusIconsPanel
= new TransparentPanel(
new FlowLayout(FlowLayout.CENTER, 5, 0));
statusIconsPanel.add(securityStatusLabel);
statusIconsPanel.add(holdStatusLabel);
statusIconsPanel.add(muteStatusLabel);
statusIconsPanel.add(callStatusLabel);
statusPanel.add(statusIconsPanel);
Component[] buttons =
new Component[]
{
CallPeerRendererUtils.createTransferCallButton(callPeer),
CallPeerRendererUtils.createEnterFullScreenButton(this)
};
Component buttonBar
= CallPeerRendererUtils.createButtonBar(false, buttons);
statusPanel.add(buttonBar);
statusPanel.add(securityStatusLabel);
statusPanel.add(holdStatusLabel);
statusPanel.add(muteStatusLabel);
statusPanel.add(callStatusLabel);
statusPanel.add(dtmfLabel);
return statusPanel;
}
@ -545,7 +529,7 @@ private void removeVideoListener()
videoTelephony = null;
}
exitFullScreen(fullScreenWindow);
callRenderer.exitFullScreen();
}
};
call.addCallChangeListener(callListener);
@ -653,7 +637,7 @@ private void handleVideoEvent(
}
else if (isAncestor(videoContainer, visualComponent))
{
ensureSize(visualComponent, width, height);
callRenderer.ensureSize(visualComponent, width, height);
/*
* Even if ensureSize hasn't changed the Frame size,
@ -709,8 +693,8 @@ else if (isAncestor(videoContainer, visualComponent))
* If the local video is turned on, we ensure that the button is
* selected.
*/
if (!callDialog.isVideoButtonSelected())
callDialog.setVideoButtonSelected(true);
if (!callRenderer.getCallDialog().isVideoButtonSelected())
callRenderer.getCallDialog().setVideoButtonSelected(true);
}
videoContainer.validate();
@ -765,252 +749,6 @@ public String getPeerName()
return peerName;
}
private Component createFullScreenButtonBar()
{
Call call = callPeer.getCall();
Component[] buttons
= new Component[]
{
new HoldButton(call,
true,
CallPeerState.isOnHold(callPeer.getState())),
new MuteButton(call,
true,
callPeer.isMute()),
CallPeerRendererUtils.createExitFullScreenButton(this)
};
return CallPeerRendererUtils.createButtonBar(true, buttons);
}
/**
* Attempts to give a specific <tt>Component</tt> a visible rectangle with a
* specific width and a specific height if possible and sane.
*
* @param component the <tt>Component</tt> to be given a visible rectangle
* with the specified width and height
* @param width the width of the visible rectangle to be given to the
* specified <tt>Component</tt>
* @param height the height of the visible rectangle to be given to the
* specified <tt>Component</tt>
* @return <tt>true</tt> if an actual attempt has been made because it
* seemed possible and sounded sane; otherwise, <tt>false</tt>
*/
private boolean ensureSize(Component component, int width, int height)
{
Frame frame = TransferCallButton.getFrame(component);
if (frame == null)
return false;
else if ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH)
== Frame.MAXIMIZED_BOTH)
{
/*
* Forcing the size of a Component which is displayed in a maximized
* window does not sound like anything we want to do.
*/
return false;
}
else if (frame.equals(frame.getGraphicsConfiguration()
.getDevice().getFullScreenWindow()))
{
/*
* Forcing the size of a Component which is displayed in a
* full-screen window does not sound like anything we want to do.
*/
return false;
}
else
{
Insets frameInsets = frame.getInsets();
/*
* XXX This is a very wild guess and it is very easy to break
* because it wants to have the component with the specified width
* yet it forces the Frame to have nearly the same width without
* knowing anything about the layouts of the containers between the
* Frame and the component.
*/
int newFrameWidth = width + frameInsets.left + frameInsets.right;
Dimension frameSize = frame.getSize();
Dimension componentSize = component.getSize();
int newFrameHeight
= frameSize.height + height - componentSize.height;
// Don't get bigger than the screen.
Rectangle screenBounds
= frame.getGraphicsConfiguration().getBounds();
if (newFrameWidth > screenBounds.width)
newFrameWidth = screenBounds.width;
if (newFrameHeight > screenBounds.height)
newFrameHeight = screenBounds.height;
// Don't go out of the screen.
Point frameLocation = frame.getLocation();
int newFrameX = frameLocation.x;
int newFrameY = frameLocation.y;
int xDelta
= (newFrameX + newFrameWidth)
- (screenBounds.x + screenBounds.width);
int yDelta
= (newFrameY + newFrameHeight)
- (screenBounds.y + screenBounds.height);
if (xDelta > 0)
{
newFrameX -= xDelta;
if (newFrameX < screenBounds.x)
newFrameX = screenBounds.x;
}
if (yDelta > 0)
{
newFrameY -= yDelta;
if (newFrameY < screenBounds.y)
newFrameY = screenBounds.y;
}
/*
* XXX Unreliable because VideoRenderer Components such as the
* Component of the AWTRenderer on Linux overrides its
* #getPreferredSize().
*/
component.setPreferredSize(new Dimension(width, height));
/*
* If we're going to make too small a change, don't even bother.
* Besides, we don't want some weird recursive resizing.
*/
int frameWidthDelta = newFrameWidth - frameSize.width;
int frameHeightDelta = newFrameHeight - frameSize.height;
if ((frameWidthDelta < -1)
|| (frameWidthDelta > 1)
|| (frameHeightDelta < -1)
|| (frameHeightDelta > 1))
{
frame.setBounds(
newFrameX, newFrameY,
newFrameWidth, newFrameHeight);
}
return true;
}
}
/**
* Enters full screen mode. Initializes all components for the full screen
* user interface.
*/
public void enterFullScreen()
{
// Create the main Components of the UI.
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setTitle(getPeerName());
frame.setUndecorated(true);
Component center = createCenter();
final Component buttonBar = createFullScreenButtonBar();
// Lay out the main Components of the UI.
final Container contentPane = frame.getContentPane();
contentPane.setLayout(new FullScreenLayout(false));
if (buttonBar != null)
contentPane.add(buttonBar, FullScreenLayout.SOUTH);
if (center != null)
contentPane.add(center, FullScreenLayout.CENTER);
// Full-screen windows usually have black backgrounds.
Color background = Color.black;
contentPane.setBackground(background);
CallPeerRendererUtils.setBackground(center, background);
class FullScreenListener
implements ContainerListener, KeyListener, WindowStateListener
{
public void componentAdded(ContainerEvent event)
{
Component child = event.getChild();
child.addKeyListener(this);
}
public void componentRemoved(ContainerEvent event)
{
Component child = event.getChild();
child.removeKeyListener(this);
}
public void keyPressed(KeyEvent event)
{
if (!event.isConsumed()
&& (event.getKeyCode() == KeyEvent.VK_ESCAPE))
{
event.consume();
exitFullScreen(frame);
}
}
public void keyReleased(KeyEvent event)
{
}
public void keyTyped(KeyEvent event)
{
}
public void windowStateChanged(WindowEvent event)
{
switch (event.getID())
{
case WindowEvent.WINDOW_CLOSED:
case WindowEvent.WINDOW_DEACTIVATED:
case WindowEvent.WINDOW_ICONIFIED:
case WindowEvent.WINDOW_LOST_FOCUS:
exitFullScreen(frame);
break;
}
}
}
FullScreenListener listener = new FullScreenListener();
// Exit on Escape.
CallPeerRendererUtils.addKeyListener(frame, listener);
// Activate the above features for the local and remote videos.
if (center instanceof Container)
((Container) center).addContainerListener(listener);
// Exit when the "full screen" looses its focus.
frame.addWindowStateListener(listener);
getGraphicsConfiguration().getDevice().setFullScreenWindow(frame);
this.fullScreenWindow = frame;
}
/**
* Exits the full screen mode.
* @param fullScreenWindow the window shown in the full screen mode
*/
public void exitFullScreen(Window fullScreenWindow)
{
GraphicsConfiguration graphicsConfig = getGraphicsConfiguration();
if (graphicsConfig != null)
graphicsConfig.getDevice().setFullScreenWindow(null);
if (fullScreenWindow != null)
{
if (fullScreenWindow.isVisible())
fullScreenWindow.setVisible(false);
fullScreenWindow.dispose();
if (this.fullScreenWindow == fullScreenWindow)
this.fullScreenWindow = null;
}
}
private static class PeerStatusPanel
extends TransparentPanel
{
@ -1024,7 +762,7 @@ private static class PeerStatusPanel
public PeerStatusPanel(LayoutManager layout)
{
super(layout);
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
this.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
}
@Override
@ -1257,6 +995,15 @@ public CallPeerAdapter getCallPeerAdapter()
*/
public CallDialog getCallDialog()
{
return callDialog;
return callRenderer.getCallDialog();
}
/**
* Prints the given DTMG character through this <tt>CallPeerRenderer</tt>.
* @param dtmfChar the DTMF char to print
*/
public void printDTMFTone(char dtmfChar)
{
dtmfLabel.setText(dtmfLabel.getText() + dtmfChar);
}
}

@ -6,8 +6,8 @@
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
@ -19,35 +19,43 @@
* <tt>CallPariticant</tt>.
*
* @author Lubomir Marinov
* @author Yana Stamcheva
*/
public class TransferCallButton
extends SIPCommButton
{
/**
* The <tt>CallPeer</tt> (whose <tt>Call</tt> is) to be
* transfered.
* The <tt>Call</tt> to be transfered.
*/
private final CallPeer callPeer;
private final Call call;
/**
* Initializes a new <tt>TransferCallButton</tt> instance which is to
* transfer (the <tt>Call</tt> of) a specific
* <tt>CallPeer</tt>.
*
* @param peer the <tt>CallPeer</tt> to be associated
* with the new instance and to be transfered
* @param c the <tt>Call</tt> to be associated with the new instance and
* to be transfered
*/
public TransferCallButton(CallPeer peer)
public TransferCallButton(Call c)
{
super(ImageLoader.getImage(ImageLoader.TRANSFER_CALL_BUTTON));
super( ImageLoader.getImage(ImageLoader.CALL_SETTING_BUTTON_BG),
ImageLoader.getImage(ImageLoader.TRANSFER_CALL_BUTTON));
this.callPeer = peer;
this.call = c;
setToolTipText(GuiActivator.getResources().getI18NString(
"service.gui.TRANSFER_BUTTON_TOOL_TIP"));
OperationSetAdvancedTelephony telephony =
call.getProtocolProvider()
.getOperationSet(OperationSetAdvancedTelephony.class);
if (telephony == null)
this.setEnabled(false);
addActionListener(new ActionListener()
{
/**
* Invoked when an action occurs.
*
@ -57,36 +65,12 @@ public TransferCallButton(CallPeer peer)
*/
public void actionPerformed(ActionEvent evt)
{
CallManager.transferCall(callPeer);
Iterator<? extends CallPeer> callPeers = call.getCallPeers();
while (callPeers.hasNext())
{
CallManager.transferCall(callPeers.next());
}
}
});
}
/**
* Gets the first <tt>Frame</tt> in the ancestor <tt>Component</tt>
* hierarchy of a specific <tt>Component</tt>.
* <p>
* The located <tt>Frame</tt> (if any) is often used as the owner of
* <tt>Dialog</tt>s opened by the specified <tt>Component</tt> in
* order to provide natural <tt>Frame</tt> ownership.
*
* @param component the <tt>Component</tt> which is to have its
* <tt>Component</tt> hierarchy examined for <tt>Frame</tt>
* @return the first <tt>Frame</tt> in the ancestor
* <tt>Component</tt> hierarchy of the specified <tt>Component</tt>;
* <tt>null</tt>, if no such <tt>Frame</tt> was located
*/
public static Frame getFrame(Component component)
{
while (component != null)
{
Container container = component.getParent();
if (container instanceof Frame)
return (Frame) container;
component = container;
}
return null;
}
}

@ -26,6 +26,7 @@
*/
public class ConferenceCallPanel
extends JScrollPane
implements CallRenderer
{
/**
* The conference call.
@ -373,4 +374,59 @@ else if (vpSize.height < viewSize.height)
vp.setViewSize(viewSize);
}
}
/**
* Ensures the size of the window.
* @param component the component, which size should be considered
* @param width the desired width
* @param height the desired height
*/
public void ensureSize(Component component, int width, int height) {}
/**
* Enters in full screen view mode.
*/
public void enterFullScreen()
{
// TODO: Implement full screen mode for this renderer.
}
/**
* Exits from the full screen view mode.
*/
public void exitFullScreen()
{
// TODO: Implement full screen mode for this renderer.
}
/**
* Returns the parent call dialog, where this renderer is contained.
* @return the parent call dialog, where this renderer is contained
*/
public CallDialog getCallDialog()
{
return callDialog;
}
/**
* Returns the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>.
* @param callPeer the <tt>CallPeer</tt>, for which we're looking for a
* renderer
* @return the <tt>CallPeerRenderer</tt> corresponding to the given
* <tt>callPeer</tt>
*/
public CallPeerRenderer getCallPeerRenderer(CallPeer callPeer)
{
return callPeerPanels.get(callPeer);
}
/**
* Returns the call represented by this call renderer.
* @return the call represented by this call renderer
*/
public Call getCall()
{
return call;
}
}

@ -61,6 +61,11 @@ public class ConferencePeerPanel
*/
private SecurityStatusLabel securityStatusLabel = new SecurityStatusLabel();
/**
* The DTMF label.
*/
private final JLabel dtmfLabel = new JLabel();
/**
* The component showing the security details.
*/
@ -308,22 +313,12 @@ public CallDialog getCallDialog()
}
/**
* Enters in full screen view mode.
*/
public void enterFullScreen()
{
// TODO: Implement full screen mode for this renderer.
}
/**
* Exits from the full screen view mode by specifying the full screen window
* previously created.
*
* @param fullScreenWindow the window previously shown in full screen mode
* Prints the given DTMG character through this <tt>CallPeerRenderer</tt>.
* @param dtmfChar the DTMF char to print
*/
public void exitFullScreen(Window fullScreenWindow)
public void printDTMFTone(char dtmfChar)
{
// TODO: Implement full screen mode for this renderer.
dtmfLabel.setText(dtmfLabel.getText() + dtmfChar);
}
/**
@ -338,6 +333,7 @@ private void initStatusBar(CallPeer callPeer)
this.addToStatusBar(securityStatusLabel);
this.addToStatusBar(holdStatusLabel);
this.addToStatusBar(muteStatusLabel);
this.addToStatusBar(dtmfLabel);
}
/**

Loading…
Cancel
Save