public class KeyBindingManager
extends java.lang.Object
This class handles key bindings.
Modifier and Type | Field and Description |
---|---|
private javax.swing.ActionMap |
actionMap |
private static java.util.TreeMap<java.lang.Integer,java.util.TreeSet<KeyBinding>> |
bindingsToCbxChannel |
private java.util.HashMap<java.lang.String,java.util.HashSet<java.lang.String>> |
bindingToIds |
private javax.swing.JComboBox<?> |
comboboxToSetChannel |
private javax.swing.JComponent |
component |
private java.util.TreeSet<KeyBinding> |
conflicts |
private boolean |
hasNestedTabs |
private java.util.TreeMap<java.lang.Integer,javax.swing.JTabbedPane> |
indexToLvl2Pane |
private java.util.TreeMap<java.lang.Integer,java.util.HashSet<java.lang.String>> |
indexToLvl2Tabs |
private javax.swing.InputMap |
inputMap |
private boolean |
isEnterUsed |
private boolean |
isSpaceGlobal |
private boolean |
isSpaceUsed |
private java.util.TreeMap<java.lang.String,javax.swing.JComponent> |
lvl3Components |
private javax.swing.JTabbedPane |
tabbedPaneLvl1 |
private java.util.HashMap<java.lang.String,int[]> |
tabToIndices |
private java.util.HashMap<java.lang.String,java.lang.Integer> |
tabToLevel |
private java.util.TreeSet<KeyBinding> |
usedBindings |
private java.awt.Window |
window |
Constructor and Description |
---|
KeyBindingManager(java.awt.Window w,
javax.swing.JComponent c)
Creates a new key binding manager used for one main container and window.
|
Modifier and Type | Method and Description |
---|---|
void |
addBindingsForButton(MidicaButton btn,
java.lang.String id)
Adds a key binding for a button to be clicked.
|
void |
addBindingsForButtonOfVisibleElement(java.util.ArrayList<MidicaButton> buttons,
java.lang.String id)
Adds a key binding for a list of buttons to be pressed when possible.
|
void |
addBindingsForCheckbox(javax.swing.JCheckBox cbx,
java.lang.String id)
Adds a key binding for a checkbox to be toggled.
|
void |
addBindingsForCheckboxOfVisibleElement(java.util.ArrayList<javax.swing.JCheckBox> checkboxes,
java.lang.String id)
Adds a key binding for a list of checkboxes to be toggled when possible.
|
void |
addBindingsForClose(java.lang.String id)
Adds a key binding for closing the window.
|
void |
addBindingsForComboboxOfVisibleElement(java.util.ArrayList<javax.swing.JComboBox<?>> comboboxes,
java.lang.String id)
Adds a key binding for a list of comboboxes to be opened when possible.
|
void |
addBindingsForComboboxOpen(javax.swing.JComboBox<?> cbx,
java.lang.String id)
Adds a key binding for a combobox to be opened.
|
void |
addBindingsForComboboxSelect(javax.swing.JComboBox<?> cbx,
java.lang.String id,
int index)
Adds a key binding for a combobox element to be selected.
|
void |
addBindingsForFocus(javax.swing.JComponent comp,
java.lang.String id)
Adds a key binding for a component to be focused.
|
void |
addBindingsForFocusOfVisibleElement(java.util.ArrayList<?> components,
java.lang.String id)
Adds a key binding for list of components to be focused when possible.
|
void |
addBindingsForIconLabel(javax.swing.JComponent icon,
java.lang.String id)
Adds a key binding for an icon label that’s used to open a window or layer.
|
void |
addBindingsForIconLabelOfVisibleTab(java.util.ArrayList<javax.swing.JComponent> icons,
java.lang.String id)
Adds a key binding for a list of icon labels to be pressed when possible.
|
void |
addBindingsForSliderSet(javax.swing.JSlider slider,
java.lang.String id,
int value)
Adds a key binding for a slider to be set.
|
void |
addBindingsForTabLevel1(javax.swing.JTabbedPane tabbedPane,
java.lang.String id,
int index)
Adds a key binding for selecting a tab in the first level of a nested {link
JTabbedPane }. |
void |
addBindingsForTabLevel2(javax.swing.JTabbedPane lvl2Pane,
java.lang.String id,
int indexLvl1,
int indexLvl2)
Adds a key binding for selecting a tab in the second level of a nested {link
JTabbedPane }. |
void |
addBindingsForTabLevel3(javax.swing.JComponent c,
java.lang.String id)
Adds a key binding for an element inside of a nested tab.
|
private void |
addInputs(java.lang.String id)
Fills the input maps for the key bindings of the given ID.
|
private void |
addInputsForNestedTabs(java.lang.String id)
Fills the input maps for the key bindings of the given ID.
|
static void |
addTooltip(javax.swing.JComponent c,
java.lang.String id,
java.lang.String ttType)
Adds a key binding related part to the tooltip of the component or sets a new tooltip, if no tooltip is set.
|
private static java.lang.String |
getBindingSpecificToolTip(java.lang.String id,
java.lang.String ttType)
Create and return the key binding specific part of a tooltip text.
|
private javax.swing.Action |
getSliderAction(javax.swing.JSlider slider,
java.lang.String actionName)
Creates and returns an action for a slider-specific key-binding that can be put into the slider’s action map.
|
void |
globalizeSpace()
Enables the SPACE key to be a window-wide global key binding.
|
private void |
handleSlidersInChildren(java.awt.Container c,
java.util.TreeSet<KeyBinding> sliderBindings)
Adds some slider-specific bindings recursively to sliders in the decendents of the given container.
|
private void |
ignoreKeysInChildren(java.awt.Container c,
java.util.TreeSet<KeyBinding> keyBindings)
Ignores special bindings in the children of the given container, recursively.
|
private void |
ignoreKeysInComponent(javax.swing.JComponent c,
java.util.TreeSet<KeyBinding> keyBindings)
Ignores special bindings in the component.
|
private void |
init(javax.swing.JComponent c)
Initializes and resets all fields.
|
private boolean |
mustIgnore(java.awt.event.ActionEvent e)
Checks if a key binding action must be ignored.
|
void |
postprocess()
This method must be called after all bindings have been added.
|
private void |
postprocessNestedTabs()
Fills the action maps for key bindings in windows with (nested) tabs.
|
private void |
rememberTabBindings(java.lang.String id)
Fills the input map and stores the association between key bindings and components of the given ID to be used later.
|
private void |
setSliderAndInformListeners(javax.swing.JSlider slider,
int value)
Sets a slider after a key has been pressed.
|
private void |
warnAboutConflicts()
Checks if conflicting key bindings exist in the same instance and warns if conflicts are found.
|
private java.awt.Window window
private javax.swing.JComponent component
private javax.swing.InputMap inputMap
private javax.swing.ActionMap actionMap
private java.util.TreeSet<KeyBinding> usedBindings
private java.util.TreeSet<KeyBinding> conflicts
private boolean isSpaceUsed
private boolean isEnterUsed
private boolean isSpaceGlobal
private boolean hasNestedTabs
private java.util.HashMap<java.lang.String,java.lang.Integer> tabToLevel
private java.util.HashMap<java.lang.String,int[]> tabToIndices
private java.util.HashMap<java.lang.String,java.util.HashSet<java.lang.String>> bindingToIds
private javax.swing.JTabbedPane tabbedPaneLvl1
private java.util.TreeMap<java.lang.Integer,java.util.HashSet<java.lang.String>> indexToLvl2Tabs
private java.util.TreeMap<java.lang.Integer,javax.swing.JTabbedPane> indexToLvl2Pane
private java.util.TreeMap<java.lang.String,javax.swing.JComponent> lvl3Components
private javax.swing.JComboBox<?> comboboxToSetChannel
private static java.util.TreeMap<java.lang.Integer,java.util.TreeSet<KeyBinding>> bindingsToCbxChannel
public KeyBindingManager(java.awt.Window w, javax.swing.JComponent c)
Creates a new key binding manager used for one main container and window. The container will be used to host the input map and action map of the key bindings. It will react to the key bindings if one of it’s decendents has the focus.
w
- the window hosting the container and the key bindingsc
- the container hosting input map and action mapprivate void init(javax.swing.JComponent c)
Initializes and resets all fields.
c
- the container hosting input map and action mappublic void globalizeSpace()
Enables the SPACE key to be a window-wide global key binding. Used for the player and soundcheck view.
public void addBindingsForButton(MidicaButton btn, java.lang.String id)
Adds a key binding for a button to be clicked.
btn
- the buttonid
- the key binding IDpublic void addBindingsForFocus(javax.swing.JComponent comp, java.lang.String id)
Adds a key binding for a component to be focused.
comp
- the componentid
- the key binding IDpublic void addBindingsForFocusOfVisibleElement(java.util.ArrayList<?> components, java.lang.String id)
Adds a key binding for list of components to be focused when possible. All elements use the same key binding ID but at most one of them is visible. This is used for channel-based widgets in the player window that are only visible if the according channel has been opened. The indices of the given components must match the channel number.
components
- the list of componentsid
- the key binding IDpublic void addBindingsForButtonOfVisibleElement(java.util.ArrayList<MidicaButton> buttons, java.lang.String id)
Adds a key binding for a list of buttons to be pressed when possible. All buttons use the same key binding ID but at most one of them is visible. This is used for channel-based ‘apply-to-all’ buttons in the player window that are only visible if the according channel has been opened. The indices of the given buttons must match the channel number.
buttons
- the list of buttonsid
- the key binding IDpublic void addBindingsForComboboxOfVisibleElement(java.util.ArrayList<javax.swing.JComboBox<?>> comboboxes, java.lang.String id)
Adds a key binding for a list of comboboxes to be opened when possible. All comboboxes use the same key binding ID but at most one of them is visible. This is used for charset comboboxes in file choosers with multiple tabs.
comboboxes
- the list of comboboxesid
- the key binding IDpublic void addBindingsForCheckboxOfVisibleElement(java.util.ArrayList<javax.swing.JCheckBox> checkboxes, java.lang.String id)
Adds a key binding for a list of checkboxes to be toggled when possible. All checkboxes use the same key binding ID but at most one of them is visible.
checkboxes
- the list of checkboxesid
- the key binding IDpublic void addBindingsForIconLabelOfVisibleTab(java.util.ArrayList<javax.swing.JComponent> icons, java.lang.String id)
Adds a key binding for a list of icon labels to be pressed when possible. All buttons use the same key binding ID but at most one of them is visible.
This is used for decompile config icons in the export file chooser. Each target format has its own tab with its own icon. The icon is only visible if the according tab is chosen.
icons
- the list of iconsid
- the key binding IDpublic void addBindingsForComboboxOpen(javax.swing.JComboBox<?> cbx, java.lang.String id)
Adds a key binding for a combobox to be opened. This is used for opening the config comboboxes in the main window.
cbx
- the comboboxid
- the key binding IDpublic void addBindingsForComboboxSelect(javax.swing.JComboBox<?> cbx, java.lang.String id, int index)
Adds a key binding for a combobox element to be selected. This is used for channel selection in the soundcheck window.
cbx
- the comboboxid
- the key binding IDindex
- the index to be selectedpublic void addBindingsForCheckbox(javax.swing.JCheckBox cbx, java.lang.String id)
Adds a key binding for a checkbox to be toggled.
cbx
- the checkboxid
- the key binding IDpublic void addBindingsForIconLabel(javax.swing.JComponent icon, java.lang.String id)
Adds a key binding for an icon label that’s used to open a window or layer.
The given icon can be an element of one of the following classes:
Currently only used for FilterIconWithLabel, from the soundcheck window.
icon
- the icon belongingid
- the key binding IDpublic void addBindingsForSliderSet(javax.swing.JSlider slider, java.lang.String id, int value)
Adds a key binding for a slider to be set.
slider
- the sliderid
- the key binding IDvalue
- the value to be setpublic void addBindingsForClose(java.lang.String id)
Adds a key binding for closing the window.
id
- the key binding IDpublic void addBindingsForTabLevel1(javax.swing.JTabbedPane tabbedPane, java.lang.String id, int index)
Adds a key binding for selecting a tab in the first level of a nested {link JTabbedPane
}. The same key binding can also be used for a different element. If the other element is visible, it has always priority over level-1 tabs. This is used for the Info View.
tabbedPane
- the level-1 tabbed paneid
- the key binding IDindex
- the index of the tab in the level-1 tabbed panepublic void addBindingsForTabLevel2(javax.swing.JTabbedPane lvl2Pane, java.lang.String id, int indexLvl1, int indexLvl2)
Adds a key binding for selecting a tab in the second level of a nested {link JTabbedPane
}. The same key binding can also be used for a different element. If the other element is visible and inside of the currently selected level-2 tab, it has priority over the level-2 tab to be selected. If the other element is a level-1 tab, the level-2 tab has priority. This is used for the Info View.
lvl2Pane
- the level-2 tabbed paneid
- the key binding IDindexLvl1
- the index of the tab in the level-1 tabbed paneindexLvl2
- the index of the tab in the level-2 tabbed panepublic void addBindingsForTabLevel3(javax.swing.JComponent c, java.lang.String id)
Adds a key binding for an element inside of a nested tab.
The same key binding can also be used for selecting a level-1 or level-2 tab. In this case, the level-3 element has always priority if it’s currently visible.
This is used for the Info View and other tab-based windows.
c
- the component to be controlled by the key bindingid
- the key binding IDprivate void rememberTabBindings(java.lang.String id)
Fills the input map and stores the association between key bindings and components of the given ID to be used later. Only used for nested tabs. Needed for the info window.
id
- the key binding IDprivate boolean mustIgnore(java.awt.event.ActionEvent e)
Checks if a key binding action must be ignored. This method is called if a bound key has been pressed.
A key must be ignored, if:
The SPACE bar exception is needed to enable the space bar to be bound to the PLAY/PAUSE button even if another button has the focus.
e
- the action event that was caused by a key pressprivate void addInputs(java.lang.String id)
Fills the input maps for the key bindings of the given ID.
id
- the key binding IDprivate void addInputsForNestedTabs(java.lang.String id)
Fills the input maps for the key bindings of the given ID. Used instead of addInputs(String)
, when nested tabs are used. Used for the info window.
Other than addInputs(), the key of the added input maps also contains the key binding.
id
- the key binding IDpublic void postprocess()
This method must be called after all bindings have been added.
If some special bindings (SPACE or ENTER) are in use, it prevents the focused element to react to these bindings directly.
It also checks if the root component contains sliders. If this is the case, it adds some slider-specific bindings to them.
This is needed for some special cases, if a slider-specific binding is used for something else. In this case we still want to use the binding for the slider, if the slider is focused.
If nested tabs are used, the action map is filled here as well.
Also sets the tooltip of the channel selection combobox in the soundcheck window.
private void warnAboutConflicts()
Checks if conflicting key bindings exist in the same instance and warns if conflicts are found.
public static void addTooltip(javax.swing.JComponent c, java.lang.String id, java.lang.String ttType)
Adds a key binding related part to the tooltip of the component or sets a new tooltip, if no tooltip is set.
c
- the componentid
- the key binding ID (or null in case of the channel combobox in the soundcheck window)ttType
- the translation ID of the tooltip typeprivate static java.lang.String getBindingSpecificToolTip(java.lang.String id, java.lang.String ttType)
Create and return the key binding specific part of a tooltip text.
id
- the key binding ID (or null in case of the channel combobox in the soundcheck window)ttType
- the translation ID of the tooltip typeprivate void ignoreKeysInChildren(java.awt.Container c, java.util.TreeSet<KeyBinding> keyBindings)
Ignores special bindings in the children of the given container, recursively. This is needed if ENTER or SPACE is used for something else. Then we want to prevent the child elements to consume the binding first.
Needed e.g. for the player to enable SPACE for PLAY/PAUSE even if a button is focused.
c
- the containerkeyBindings
- the key binding to be ignored by the children of the containerprivate void ignoreKeysInComponent(javax.swing.JComponent c, java.util.TreeSet<KeyBinding> keyBindings)
Ignores special bindings in the component. This is needed if ENTER or SPACE is used for something else.
c
- the componentkeyBindings
- the bindings to be ignored by that componentprivate void handleSlidersInChildren(java.awt.Container c, java.util.TreeSet<KeyBinding> sliderBindings)
Adds some slider-specific bindings recursively to sliders in the decendents of the given container.
This is needed for some special cases, if a slider-specific binding is used for something else. In this case we still want to use the binding for the slider, if the slider is focused.
c
- the container to be checked for sliders recursivelysliderBindings
- the slider-specific bindings (arrow keys, HOME and END)private javax.swing.Action getSliderAction(javax.swing.JSlider slider, java.lang.String actionName)
Creates and returns an action for a slider-specific key-binding that can be put into the slider’s action map.
slider
- the slideractionName
- an identifier that describes how the slider value must be changedprivate void setSliderAndInformListeners(javax.swing.JSlider slider, int value)
Sets a slider after a key has been pressed. Invokes the change listener and sets valueIsAdjusting accordingly. In this project this is necessary because slider changes are only handled if getValueIsAdjusting() returns true.
slider
- the slider to be adjusted.value
- the value to be set.private void postprocessNestedTabs()
Fills the action maps for key bindings in windows with (nested) tabs. This method is used for the info window. It’s called after all bindings have been added and the input maps are filled.
The same key binding could possibly exist for different actions inside of the same container. In this case we need to check which (nested) tabs are open. Then we need to process the binding according to it’s priority:
The action event doesn’t hold the information which key binding has been pressed or for which component it has been added. So here we add one action for each binding and binding ID. So we are still able to get that information.