/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.gui.main;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.plugin.desktoputil.*;
import net.java.sip.communicator.plugin.desktoputil.plaf.*;
import net.java.sip.communicator.util.skin.*;
import org.jitsi.util.*;
import com.explodingpixels.macwidgets.*;
/**
* The <tt>DialpadDialog</tt> is a popup dialog containing a dialpad.
*
* @author Yana Stamcheva
*/
public class GeneralDialPadDialog
{
/**
* The call field, where the dialed number is typed.
*/
private final JTextField callField;
/**
* The actual dial pad dialog.
*/
private final JDialog dialPadDialog;
/**
* The call button.
*/
private JButton callButton;
/**
* A keyboard manager, where we register our own key dispatcher.
*/
private KeyboardFocusManager keyManager;
/**
* A key dispatcher that redirects all key events to call field.
*/
private KeyEventDispatcher keyDispatcher;
/**
* Creates an instance of <tt>GeneralDialPadDialog</tt>.
*/
public GeneralDialPadDialog()
{
dialPadDialog
= OSUtils.IS_MAC
? new HudWindow().getJDialog()
: new SIPCommDialog(false);
dialPadDialog.setTitle(
GuiActivator.getResources().getI18NString(
"service.gui.DIALPAD"));
callField
= new CallField(
GuiActivator.getResources().getI18NString(
"service.gui.ENTER_NAME_OR_NUMBER"));
initInputMap();
JPanel mainPanel = new TransparentPanel(new BorderLayout());
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
mainPanel.add(callField, BorderLayout.NORTH);
final DTMFHandler dtmfHandler = new DTMFHandler();
mainPanel.add(new GeneralDialPanel(this, dtmfHandler));
mainPanel.add(createCallPanel(), BorderLayout.SOUTH);
dialPadDialog.add(mainPanel);
dialPadDialog.pack();
dialPadDialog.addWindowListener(new WindowAdapter()
{
@Override
public void windowOpened(WindowEvent e)
{
if (keyManager == null)
{
keyManager
= KeyboardFocusManager.getCurrentKeyboardFocusManager();
}
if (keyDispatcher == null)
keyDispatcher = new MainKeyDispatcher(keyManager);
keyManager.addKeyEventDispatcher(keyDispatcher);
dtmfHandler.addParent(dialPadDialog);
}
@Override
public void windowClosed(WindowEvent e)
{
try
{
if (keyManager != null)
{
keyManager.removeKeyEventDispatcher(keyDispatcher);
keyManager = null;
}
keyDispatcher = null;
}
finally
{
dtmfHandler.removeParent(dialPadDialog);
}
}
});
}
/**
* Initializes the input map.
*/
private void initInputMap()
{
InputMap imap = dialPadDialog.getRootPane().getInputMap(
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
ActionMap amap = dialPadDialog.getRootPane().getActionMap();
amap.put("escape", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
String text = callField.getText();
// If the text area is empty we close the dialpad.
if (text == null || text.length() <= 0)
dialPadDialog.setVisible(false);
else
callField.setText("");
}
});
// put the defaults for macosx
if(OSUtils.IS_MAC)
{
imap.put(
KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK),
"close");
imap.put(
KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK),
"close");
amap.put("close", new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
dialPadDialog.setVisible(false);
}
});
}
}
/**
* Creates the call panel.
*
* @return the created call panel.
*/
private JComponent createCallPanel()
{
JPanel buttonsPanel
= new TransparentPanel(new FlowLayout(FlowLayout.CENTER));
Image callButtonImage
= ImageLoader.getImage(ImageLoader.DIAL_PAD_CALL_BUTTON_BG);
callButton = new SIPCommTextButton(
GuiActivator.getResources().getI18NString("service.gui.CALL"),
callButtonImage);
callButton.setPreferredSize(new Dimension(
callButtonImage.getWidth(null),
callButtonImage.getHeight(null)));
callButton.setForeground(Color.WHITE);
callButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String callNumber = callField.getText();
if (callNumber != null && callNumber.length() > 0)
CallManager.createCall(callField.getText(), callButton,
new CallInterfaceListener()
{
public void callInterfaceStarted()
{
dialPadDialog.setVisible(false);
}
});
}
});
buttonsPanel.add(callButton);
dialPadDialog.getRootPane().setDefaultButton(callButton);
return buttonsPanel;
}
/**
* Indicates that a dial button was pressed.
*
* @param s the string corresponding to a number to add to the call field
*/
public void dialButtonPressed(String s)
{
String currentText = callField.getText();
if (currentText == null)
currentText = "";
callField.setText(currentText + s);
}
/**
* Shows/hides the dial pad dialog.
*
* @param visible indicates if the dial pad should be shown or hidden.
*/
public void setVisible(boolean visible)
{
dialPadDialog.setLocationRelativeTo(
GuiActivator.getUIService().getMainFrame());
dialPadDialog.setVisible(visible);
callField.requestFocus();
}
/**
* Clears the call field.
*/
public void clear()
{
callField.setText("");
}
/**
* The <tt>MainKeyDispatcher</tt> is added to pre-listen KeyEvents before
* they're delivered to the current focus owner in order to introduce a
* specific behavior for the <tt>CallField</tt> on top of the dial pad.
*/
private class MainKeyDispatcher implements KeyEventDispatcher
{
private final KeyboardFocusManager keyManager;
/**
* Creates an instance of <tt>MainKeyDispatcher</tt>.
* @param keyManager the parent <tt>KeyboardFocusManager</tt>
*/
public MainKeyDispatcher(KeyboardFocusManager keyManager)
{
this.keyManager = keyManager;
}
/**
* Dispatches the given <tt>KeyEvent</tt>.
* @param e the <tt>KeyEvent</tt> to dispatch
* @return <tt>true</tt> if the KeyboardFocusManager should take no
* further action with regard to the KeyEvent; <tt>false</tt>
* otherwise
*/
public boolean dispatchKeyEvent(KeyEvent e)
{
// If this window is not the focus window or if the event is not
// of type PRESSED we have nothing more to do here.
if (!dialPadDialog.isFocused() || (e.getID() != KeyEvent.KEY_TYPED))
return false;
switch (e.getKeyChar())
{
case KeyEvent.CHAR_UNDEFINED:
case KeyEvent.VK_ENTER:
case KeyEvent.VK_DELETE:
case KeyEvent.VK_BACK_SPACE:
case KeyEvent.VK_TAB:
case KeyEvent.VK_SPACE:
return false;
}
if (!callField.isFocusOwner()
&& (keyManager.getFocusOwner() != null))
{
// Request the focus in the call field if a letter is typed.
callField.requestFocusInWindow();
// We re-dispatch the event to call field.
keyManager.redispatchEvent(callField, e);
// We don't want to dispatch further this event.
return true;
}
return false;
}
}
/**
* A custom call field.
*/
private static class CallField
extends SIPCommTextField
implements Skinnable
{
/**
* Class id key used in UIDefaults.
*/
private static final String uiClassID =
CallField.class.getName() + "FieldUI";
/**
* Adds the ui class to UIDefaults.
*/
static
{
UIManager.getDefaults().put(uiClassID,
DialPadFieldUI.class.getName());
}
/**
* The text field ui.
*/
private SIPCommTextFieldUI textFieldUI;
/**
* Creates an instance of the <tt>CallField</tt>.
*
* @param text
*/
public CallField(String text)
{
super(text);
if(getUI() instanceof DialPadFieldUI)
{
((DialPadFieldUI)getUI()).setDeleteButtonEnabled(true);
}
this.setPreferredSize(new Dimension(200, 23));
this.setBorder(null);
this.setOpaque(false);
this.setDragEnabled(true);
loadSkin();
}
/**
* Reloads text field UI defs.
*/
public void loadSkin()
{
if(getUI() instanceof SIPCommTextFieldUI)
textFieldUI = (SIPCommTextFieldUI)getUI();
else
return;
textFieldUI.loadSkin();
if (OSUtils.IS_MAC)
{
textFieldUI.setBgStartColor(Color.BLACK);
textFieldUI.setBgEndColor(Color.BLACK);
textFieldUI.setBgBorderStartColor(Color.DARK_GRAY);
textFieldUI.setBgBorderEndColor(Color.GRAY);
setForegroundColor(Color.WHITE);
setDefaultTextColor(Color.GRAY);
setCaretColor(Color.WHITE);
}
}
/**
* Returns the name of the L&F class that renders this component.
*
* @return the string "TreeUI"
* @see JComponent#getUIClassID
* @see UIDefaults#getUI
*/
@Override
public String getUIClassID()
{
return uiClassID;
}
}
}