package chatty.util.hotkeys;
import chatty.*;
import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;
import com.melloware.jintellitype.JIntellitypeException;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
/**
* Actually initialize JIntellitype and register the hotkeys.
*
* @author tduva
*/
public class GlobalHotkeySetter implements HotkeyListener {
private static final Logger LOGGER = Logger.getLogger(GlobalHotkeySetter.class.getName());
private boolean initialized = false;
/**
* Error that occured when initializing (usually the correct dll not found).
*/
private String error;
private final GlobalHotkeyListener listener;
/**
* Save an association between id (Integer) that JIntelliType uses and the
* id that can be referred to by the caller (any Object).
*/
private final Map<Integer, Object> hotkeys = new HashMap<>();
/**
* Increasing number to get ids off of for JIntelliType to use.
*/
private int idCount;
public GlobalHotkeySetter(GlobalHotkeyListener listener) {
this.listener = listener;
initialize();
}
/**
* Adds a hotkey listener.
*/
public final void initialize() {
try {
JIntellitype.getInstance().addHotKeyListener(this);
initialized = true;
} catch (JIntellitypeException ex) {
error = "Failed adding global hotkeys listener: "+ex.getLocalizedMessage();
LOGGER.warning(error);
}
}
/**
* Whether the listener has been added without an error. If false, then an
* error occured which can be retrieved with the
* {@link #getError() getError} method.
*
* @return true if global hotkeys can be added, false if an error occured
*/
public boolean isInitalized() {
return initialized;
}
/**
* Returns an error message if an error occured while initializing.
*
* @return The error message, or null if no error occured
*/
public String getError() {
return error;
}
/**
* Called when global hotkey is pressed. This is run in the EDT.
*
* @param i
*/
@Override
public void onHotKey(int i) {
Object hotkeyId = hotkeys.get(i);
if (hotkeyId != null) {
listener.onHotkey(hotkeyId);
}
}
/**
* Sets a hotkey with the given id. The hotkey consists of modifiers
* (c == ctrl, s == shift, ..) and the keyCode.
*
* @param hotkeyId
* @param modifiers
* @param keyCode
*/
public void registerHotkey(Object hotkeyId, int modifiers, int keyCode) {
if (!initialized) {
return;
}
try {
int id = getId(hotkeyId);
int mod = getModFromModifiers(modifiers);
// Remove previously under this id registered hotkey (if there is
// any)
JIntellitype.getInstance().unregisterHotKey(id);
LOGGER.info("[Global Hotkeys] Trying to register hotkey: " + id + "/" + mod + "/" + keyCode);
JIntellitype.getInstance().registerHotKey(id, mod, keyCode);
hotkeys.put(id, hotkeyId);
} catch (JIntellitypeException ex) {
LOGGER.info("[Global Hotkeys] Couldn't register hotkey: " + ex);
}
}
/**
* Removes all registered hotkeys.
*/
public void unregisterAllHotkeys() {
if (!initialized) {
return;
}
if (!hotkeys.isEmpty()) {
LOGGER.info("[Global Hotkeys] Unregistering "+hotkeys.size()+" global hotkeys.");
}
for (Integer id : hotkeys.keySet()) {
try {
JIntellitype.getInstance().unregisterHotKey(id);
} catch (JIntellitypeException ex) {
LOGGER.info("[Global Hotkeys] Couldn't unregister hotkey: " + ex);
}
}
hotkeys.clear();
idCount = 0;
}
private int getModFromModifiers(int modifiers) {
int mod = 0;
if (checkModifier(modifiers, KeyEvent.CTRL_DOWN_MASK)) {
mod += JIntellitype.MOD_CONTROL;
}
if (checkModifier(modifiers, KeyEvent.ALT_DOWN_MASK)) {
mod += JIntellitype.MOD_ALT;
}
if (checkModifier(modifiers, KeyEvent.SHIFT_DOWN_MASK)) {
mod += JIntellitype.MOD_SHIFT;
}
return mod;
}
private static boolean checkModifier(int modifiers, int modifier) {
return (modifiers & modifier) == modifier;
}
public void cleanUp() {
if (initialized) {
JIntellitype.getInstance().cleanUp();
}
}
/**
* Find if this hotkey has an id and if not, assign a new one.
*
* @param hotkeyId
* @return
*/
private int getId(Object hotkeyId) {
for (Integer id : hotkeys.keySet()) {
if (hotkeys.get(id) == hotkeyId) {
return id;
}
}
return idCount++;
}
public interface GlobalHotkeyListener {
public void onHotkey(Object hotkeyId);
}
}