mirror of https://github.com/sipwise/jitsi.git
Introduces new configuration from to setup global shortcut entry. Allows also to use special key detection for headset button _for MS Windows only_.
parent
da7a976995
commit
957b8633ae
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* 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.plugin.keybindingchooser.globalchooser;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.*;
|
||||
import java.util.List; // disambiguation
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import net.java.sip.communicator.plugin.keybindingchooser.*;
|
||||
import net.java.sip.communicator.service.globalshortcut.*;
|
||||
import net.java.sip.communicator.util.*;
|
||||
import net.java.sip.communicator.util.skin.*;
|
||||
import net.java.sip.communicator.util.swing.*;
|
||||
import net.java.sip.communicator.util.swing.plaf.*;
|
||||
|
||||
/**
|
||||
* Dialog to choose the shortcut.
|
||||
*
|
||||
* @author Sebastien Vincent
|
||||
*/
|
||||
public class GlobalShortcutDialog
|
||||
extends SIPCommDialog
|
||||
implements ActionListener,
|
||||
GlobalShortcutListener
|
||||
{
|
||||
/**
|
||||
* Serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
/**
|
||||
* Text displayed when no shortcut is configured.
|
||||
*/
|
||||
private static final String PRESS_TO_SETUP_SHORTCUT =
|
||||
Resources.getString("plugin.keybindings.globalchooser.PRESS_BTN");
|
||||
|
||||
/**
|
||||
* The global shortcut entry.
|
||||
*/
|
||||
private final GlobalShortcutEntry entry;
|
||||
|
||||
/**
|
||||
* OK button.
|
||||
*/
|
||||
private final JButton btnOK = new JButton(
|
||||
Resources.getString("service.gui.OK"));
|
||||
|
||||
/**
|
||||
* Cancel button.
|
||||
*/
|
||||
private final JButton btnCancel = new JButton(
|
||||
Resources.getString("service.gui.CANCEL"));
|
||||
|
||||
/**
|
||||
* Enable or not special key for shortcut.
|
||||
*/
|
||||
private final JCheckBox specialBox = new SIPCommCheckBox(
|
||||
Resources.getString("plugin.keybindings.globalchooser.ENABLE_SPECIAL"));
|
||||
|
||||
/**
|
||||
* First shortcut field.
|
||||
*/
|
||||
private final ShortcutField fldShortcut = new ShortcutField(
|
||||
PRESS_TO_SETUP_SHORTCUT);
|
||||
|
||||
/**
|
||||
* Secondary shortcut field.
|
||||
*/
|
||||
private final ShortcutField fldShortcut2 = new ShortcutField(
|
||||
PRESS_TO_SETUP_SHORTCUT);
|
||||
|
||||
/**
|
||||
* Return code.
|
||||
*/
|
||||
private int retCode = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param dialog root dialog
|
||||
* @param entry the global shortcut entry
|
||||
*/
|
||||
public GlobalShortcutDialog(Dialog dialog, GlobalShortcutEntry entry)
|
||||
{
|
||||
super(dialog);
|
||||
|
||||
setModal(true);
|
||||
setTitle("Global shortcut: " + entry.getAction());
|
||||
this.entry = entry;
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize components.
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
TransparentPanel mainPanel = new TransparentPanel(new BorderLayout());
|
||||
JPanel btnPanel = new TransparentPanel(
|
||||
new FlowLayout(FlowLayout.RIGHT));
|
||||
JPanel shortcutPanel = new TransparentPanel(
|
||||
new GridLayout(0, 2, 0, 10));
|
||||
|
||||
btnOK.addActionListener(this);
|
||||
btnCancel.addActionListener(this);
|
||||
|
||||
KeyAdapter keyAdapter = new KeyAdapter()
|
||||
{
|
||||
private KeyEvent buffer = null;
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event)
|
||||
{
|
||||
if(event.getKeyCode() == KeyEvent.VK_ESCAPE)
|
||||
{
|
||||
SIPCommTextField field =
|
||||
(SIPCommTextField)event.getSource();
|
||||
|
||||
AWTKeyStroke ks = null;
|
||||
|
||||
if(field == fldShortcut)
|
||||
{
|
||||
ks = entry.getShortcut();
|
||||
}
|
||||
else if(field == fldShortcut2)
|
||||
{
|
||||
ks = entry.getShortcut2();
|
||||
}
|
||||
|
||||
if(ks == null)
|
||||
field.setText(PRESS_TO_SETUP_SHORTCUT);
|
||||
else
|
||||
{
|
||||
|
||||
if(ks.getModifiers() ==
|
||||
GlobalShortcutService.SPECIAL_KEY_MODIFIERS)
|
||||
{
|
||||
field.setText("Special");
|
||||
}
|
||||
else
|
||||
{
|
||||
field.setText(GlobalShortcutEntry.getShortcutText(
|
||||
entry.getShortcut()));
|
||||
}
|
||||
}
|
||||
btnOK.requestFocusInWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.getKeyCode() == 0)
|
||||
return;
|
||||
|
||||
// Reports KEY_PRESSED events on release to support modifiers
|
||||
this.buffer = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent event)
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
SIPCommTextField field =
|
||||
(SIPCommTextField)event.getSource();
|
||||
AWTKeyStroke input = KeyStroke.getKeyStrokeForEvent(buffer);
|
||||
buffer = null;
|
||||
|
||||
GlobalShortcutEntry en = entry;
|
||||
List<AWTKeyStroke> kss = new ArrayList<AWTKeyStroke>();
|
||||
|
||||
kss.add(input);
|
||||
kss.add(en.getShortcut2());
|
||||
|
||||
en.setShortcuts(kss);
|
||||
en.setEditShortcut1(false);
|
||||
en.setEditShortcut2(false);
|
||||
field.setText(GlobalShortcutEntry.getShortcutText(
|
||||
input));
|
||||
btnOK.requestFocus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AWTKeyStroke ks = entry.getShortcut();
|
||||
AWTKeyStroke ks2 = entry.getShortcut2();
|
||||
|
||||
if(ks != null)
|
||||
{
|
||||
if(ks.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS)
|
||||
{
|
||||
fldShortcut.setText(GlobalShortcutEntry.getShortcutText(ks));
|
||||
}
|
||||
else
|
||||
{
|
||||
fldShortcut.setText("Special");
|
||||
}
|
||||
}
|
||||
|
||||
if(ks2 != null)
|
||||
{
|
||||
|
||||
if(ks2.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS)
|
||||
{
|
||||
fldShortcut2.setText(GlobalShortcutEntry.getShortcutText(ks2));
|
||||
}
|
||||
else
|
||||
{
|
||||
fldShortcut2.setText("Special");
|
||||
}
|
||||
}
|
||||
|
||||
fldShortcut.addKeyListener(keyAdapter);
|
||||
fldShortcut2.addKeyListener(keyAdapter);
|
||||
|
||||
specialBox.addItemListener(new ItemListener()
|
||||
{
|
||||
public void itemStateChanged(ItemEvent evt)
|
||||
{
|
||||
KeybindingChooserActivator.getGlobalShortcutService().
|
||||
setSpecialKeyDetection(
|
||||
(evt.getStateChange() == ItemEvent.SELECTED),
|
||||
GlobalShortcutDialog.this);
|
||||
}
|
||||
});
|
||||
|
||||
shortcutPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10,
|
||||
10));
|
||||
shortcutPanel.add(new JLabel("Primary shortcut"));
|
||||
shortcutPanel.add(fldShortcut);
|
||||
shortcutPanel.add(new JLabel("Secondary shortcut"));
|
||||
shortcutPanel.add(fldShortcut2);
|
||||
|
||||
if(OSUtils.IS_WINDOWS)
|
||||
{
|
||||
shortcutPanel.add(new TransparentPanel());
|
||||
shortcutPanel.add(specialBox);
|
||||
}
|
||||
|
||||
mainPanel.add(shortcutPanel, BorderLayout.CENTER);
|
||||
|
||||
btnPanel.add(btnOK);
|
||||
btnPanel.add(btnCancel);
|
||||
mainPanel.add(btnPanel, BorderLayout.SOUTH);
|
||||
|
||||
btnOK.requestFocus();
|
||||
|
||||
getContentPane().add(mainPanel);
|
||||
pack();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void close(boolean isEscaped)
|
||||
{
|
||||
super.close(isEscaped);
|
||||
KeybindingChooserActivator.getGlobalShortcutService().
|
||||
setSpecialKeyDetection(false, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the dialog and returns if the user has modified something (create
|
||||
* or modify entry).
|
||||
*
|
||||
* @return true if the user has modified something (create
|
||||
* or modify entry), false otherwise.
|
||||
*/
|
||||
public int showDialog()
|
||||
{
|
||||
setVisible(true);
|
||||
|
||||
// as the dialog is modal, wait for OK/Cancel button retCode
|
||||
setVisible(false);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
Object obj = evt.getSource();
|
||||
|
||||
if(obj == btnOK)
|
||||
{
|
||||
retCode = 1;
|
||||
dispose();
|
||||
}
|
||||
else if(obj == btnCancel)
|
||||
{
|
||||
retCode = 0;
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void shortcutReceived(GlobalShortcutEvent evt)
|
||||
{
|
||||
AWTKeyStroke ksr = evt.getKeyStroke();
|
||||
|
||||
if(ksr.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!fldShortcut.isFocusOwner() && !fldShortcut2.isFocusOwner())
|
||||
return;
|
||||
|
||||
List<AWTKeyStroke> kss = new ArrayList<AWTKeyStroke>();
|
||||
|
||||
if(fldShortcut.isFocusOwner())
|
||||
{
|
||||
kss.add(ksr);
|
||||
kss.add(entry.getShortcut2());
|
||||
fldShortcut.setText("Special");
|
||||
}
|
||||
else if(fldShortcut2.isFocusOwner())
|
||||
{
|
||||
kss.add(entry.getShortcut());
|
||||
kss.add(ksr);
|
||||
fldShortcut2.setText("Special");
|
||||
}
|
||||
entry.setShortcuts(kss);
|
||||
KeybindingChooserActivator.getGlobalShortcutService().
|
||||
setSpecialKeyDetection(false, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the text field.
|
||||
*
|
||||
* @param ui <tt>TextFieldUI</tt> to clear
|
||||
*/
|
||||
public void clearTextField(SIPCommTextFieldUI ui)
|
||||
{
|
||||
List<AWTKeyStroke> kss = new ArrayList<AWTKeyStroke>();
|
||||
|
||||
if(ui == fldShortcut.getUI())
|
||||
{
|
||||
kss.add(null);
|
||||
kss.add(entry.getShortcut2());
|
||||
entry.setShortcuts(kss);
|
||||
btnOK.requestFocusInWindow();
|
||||
}
|
||||
else if(ui == fldShortcut2.getUI())
|
||||
{
|
||||
kss.add(entry.getShortcut());
|
||||
kss.add(null);
|
||||
entry.setShortcuts(kss);
|
||||
btnOK.requestFocusInWindow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom call field.
|
||||
*/
|
||||
private class ShortcutField
|
||||
extends SIPCommTextField
|
||||
implements Skinnable
|
||||
{
|
||||
/**
|
||||
* Serial version UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 0L;
|
||||
|
||||
/**
|
||||
* The text field ui.
|
||||
*/
|
||||
private ShortcutFieldUI textFieldUI;
|
||||
|
||||
/**
|
||||
* Creates an instance of the <tt>CallField</tt>.
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
public ShortcutField(String text)
|
||||
{
|
||||
super(text);
|
||||
|
||||
textFieldUI = new ShortcutFieldUI();
|
||||
textFieldUI.setDeleteButtonEnabled(true);
|
||||
|
||||
this.setPreferredSize(new Dimension(200, 23));
|
||||
this.setUI(textFieldUI);
|
||||
this.setBorder(null);
|
||||
this.setOpaque(false);
|
||||
|
||||
this.setDragEnabled(true);
|
||||
|
||||
loadSkin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads text field UI defs.
|
||||
*/
|
||||
public void loadSkin()
|
||||
{
|
||||
textFieldUI.loadSkin();
|
||||
}
|
||||
}
|
||||
|
||||
public class ShortcutFieldUI
|
||||
extends SIPCommTextFieldUI
|
||||
implements Skinnable
|
||||
{
|
||||
/**
|
||||
* Creates a <tt>SIPCommTextFieldUI</tt>.
|
||||
*/
|
||||
public ShortcutFieldUI()
|
||||
{
|
||||
loadSkin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the custom mouse listeners defined in this class to the installed
|
||||
* listeners.
|
||||
*/
|
||||
protected void installListeners()
|
||||
{
|
||||
super.installListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void updateDeleteIcon(MouseEvent evt)
|
||||
{
|
||||
super.updateDeleteIcon(evt);
|
||||
|
||||
Rectangle deleteRect = getDeleteButtonRect();
|
||||
if(deleteRect.contains(evt.getX(), evt.getY()) &&
|
||||
evt.getID() == MouseEvent.MOUSE_CLICKED)
|
||||
{
|
||||
clearTextField(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements parent paintSafely method and enables antialiasing.
|
||||
* @param g the <tt>Graphics</tt> object that notified us
|
||||
*/
|
||||
protected void paintSafely(Graphics g)
|
||||
{
|
||||
customPaintBackground(g);
|
||||
super.paintSafely(g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paints the background of the associated component.
|
||||
* @param g the <tt>Graphics</tt> object used for painting
|
||||
*/
|
||||
protected void customPaintBackground(Graphics g)
|
||||
{
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
|
||||
try
|
||||
{
|
||||
AntialiasingManager.activateAntialiasing(g2);
|
||||
super.customPaintBackground(g2);
|
||||
}
|
||||
finally
|
||||
{
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue