use of java.awt.KeyEventDispatcher in project screenbird by adamhub.
the class RecorderPanel method addShortcutsListener.
/**
* Binds certain Recorder Panel Actions to key shortcuts. <BR/>
* Current bindings <BR/>
* - Start/Pause Recording <BR/>
* - Toggling of Full/Custom sized screen capture <BR/>
* - Bringing up the settings form <BR/>
* - Start Preview/Editing Mode <BR/>
* - Finalizing screen capture <BR/>
*/
private void addShortcutsListener() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (// We do not want to trigger any of this on upload screen
!jpUpload.isVisible() && // Recorder app is visible
(jpRecorderNonRec.isVisible() || jpRecorderRec.isVisible() || jpRecorderBackup.isVisible()) && // Only if applet is in recordable state
btnRecordNonRec.isEnabled() && // Locks all input while counting down recorder
(countdownTimer == null) && (e.getWhen() > (lastKeyWhen + 1000))) {
if (e.getKeyCode() == KeyEvent.VK_SPACE && !scrubManager.isPreviewing()) {
// Start Recording
e.consume();
lastKeyWhen = e.getWhen();
recordOrPause(true);
} else if (e.getKeyCode() == KeyEvent.VK_T && (e.isControlDown() || e.getModifiers() == Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) && recorder.getStatus() != RecorderStatus.RECORDING && !scrubManager.isPreviewing()) {
// Toggle Fullscreen/CustomScreen
e.consume();
lastKeyWhen = e.getWhen();
if (Settings.ENABLE_OOPS_FEATURE) {
toggleFullScreen.setSelected(!toggleFullScreen.isSelected());
} else {
toggleFullScreenBackup.setSelected(!toggleFullScreen.isSelected());
}
toggleCustomFullscreen();
} else if (e.getKeyCode() == KeyEvent.VK_ENTER && (e.isControlDown() || e.getModifiers() == Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) && !scrubManager.isPreviewing()) {
// End Recording
e.consume();
lastKeyWhen = e.getWhen();
processVideo();
} else if (e.getKeyCode() == KeyEvent.VK_M && (e.isControlDown() || e.getModifiers() == Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) && isRecorderConfigSate() && !scrubManager.isPreviewing()) {
// Open Settings Menu
e.consume();
lastKeyWhen = e.getWhen();
showSettingsForm();
}
}
return false;
}
});
}
use of java.awt.KeyEventDispatcher in project CCDD by nasa.
the class CcddKeyboardHandler method setKeyboardHandler.
/**
********************************************************************************************
* Adjust the handling of Enter and space key inputs in order to activate dialog controls, and
* keyboard focus changes in order to use the arrow keys like Tab keys
********************************************************************************************
*/
private void setKeyboardHandler() {
// Get the keyboard focus manager
focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
// Listen for key presses
focusManager.addKeyEventDispatcher(new KeyEventDispatcher() {
boolean isShowMacros = false;
Timer releaseTimer = null;
/**
************************************************************************************
* Alter the response to the Enter key to act like the Space key to activate button and
* check box controls, and the arrow keys so as to mimic the Tab and Shift+Tab keys,
* unless the key press originates within a table or combo box. For a tabbed pane the
* left/right arrows are left unchanged so that these are used for traversing the
* tabbed panes, but the down and up arrows act like Tab and Shift+Tab respectively
************************************************************************************
*/
@Override
public boolean dispatchKeyEvent(final KeyEvent ke) {
// Flag that indicates if the key event has been handled by this method (true) or
// that it still needs to be processed (false)
boolean handled = false;
// Get a reference to the component with the focus in order to shorten the
// subsequent calls
Component comp = ke.getComponent();
// pressed
if (ke.getID() == KeyEvent.KEY_PRESSED && !ke.isControlDown() && !ke.isShiftDown() && !ke.isAltDown()) {
// Check if the Enter key is pressed
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
// Check if this is a button
if (comp instanceof JButton) {
// Activate the control (same as if Space key is pressed)
((AbstractButton) comp).doClick();
handled = true;
} else // Check if this is a table
if (comp instanceof CcddJTableHandler || (comp.getParent() instanceof CcddJTableHandler && !(comp instanceof JComboBox))) {
// Handle the Enter key in the table
handled = tableEditCellHandler(comp);
}
} else // Check if the space key is pressed
if (ke.getKeyCode() == KeyEvent.VK_SPACE) {
// Check if this is a table
if (comp instanceof CcddJTableHandler) {
// Handle the space key in the table
handled = tableEditCellHandler(comp);
} else // Check this is a combo box in a table
if (comp.getParent() instanceof CcddJTableHandler && comp instanceof JComboBox) {
// Ignore the key press
handled = true;
}
} else // produce a character and is not a modifier; this covers the arrow keys)
if (ke.isActionKey()) {
// Assume that the default handling will be used with an arrow key
ArrowFocusOption arrowResponse = USE_DEFAULT_HANDLER;
// Check if the focus is on a tabbed pane's tab or on a slider
if (comp instanceof JTabbedPane || comp instanceof JSlider) {
// The left and right arrows traverse the tabs, and the up and down
// arrows behave like (Shift+)Tab
arrowResponse = HANDLE_UP_AND_DOWN_ARROWS;
} else // Check if the focus is in a text field within a table
if ((comp instanceof JTextField || comp instanceof JTextArea) && comp.getParent() instanceof CcddJTableHandler) {
// The up and down arrows are ignored. This prevents accidently exiting
// edit mode on a table cell and losing any changes
arrowResponse = IGNORE_UP_AND_DOWN_ARROWS;
} else // button, or check box
if (comp instanceof JButton || comp instanceof JRadioButton || comp instanceof JCheckBox) {
// The up and left arrow keys behave as Shift+Tab, and the down and
// right arrow keys behave as Tab
arrowResponse = HANDLE_ALL_ARROWS;
} else // Check if the focus is within a table
if (comp instanceof CcddJTableHandler) {
// Get the reference to the table with the focus
CcddJTableHandler table = (CcddJTableHandler) comp;
// Get the row containing the cell with the focus in order to shorten
// the subsequent calls
int row = table.getSelectedRow();
// Check if the table has no rows
if (row == -1) {
// Treat the table as if it wasn't there; i.e., the left and right
// arrows behave like the (Shift+)Tab key
arrowResponse = HANDLE_ALL_ARROWS;
} else // Check if the table has only a single row
if (table.getRowCount() == 1) {
// The up and down arrows behave like the (Shift+)Tab key
arrowResponse = HANDLE_UP_AND_DOWN_ARROWS;
} else // Check if the top row is selected
if (row == 0) {
// The up arrow behaves like the Shift+Tab key
arrowResponse = HANDLE_UP_ARROW;
} else // Check if the bottom row is selected
if (row == table.getRowCount() - 1) {
// The down arrow behaves like the Tab key
arrowResponse = HANDLE_DOWN_ARROW;
}
}
// Check if the key pressed is an arrow key and if so adjust its behavior
switch(ke.getKeyCode()) {
case KeyEvent.VK_LEFT:
case KeyEvent.VK_KP_LEFT:
// Check if the left arrow key should be handled
if (arrowResponse == HANDLE_ALL_ARROWS) {
// Treat the left arrow as a Shift+Tab key and indicate that
// the key has been handled
focusManager.focusPreviousComponent();
handled = true;
}
break;
case KeyEvent.VK_UP:
case KeyEvent.VK_KP_UP:
// Check if the up arrow key should be handled
if (arrowResponse == HANDLE_ALL_ARROWS || arrowResponse == HANDLE_UP_ARROW || arrowResponse == HANDLE_UP_AND_DOWN_ARROWS) {
// Treat the up arrow as a Shift+Tab key and indicate that the
// key has been handled
focusManager.focusPreviousComponent();
handled = true;
} else // Check if the up arrow should be ignored
if (arrowResponse == IGNORE_UP_AND_DOWN_ARROWS) {
// Indicate that the key has been handled
handled = true;
}
break;
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_KP_RIGHT:
// Check if the right arrow key should be handled
if (arrowResponse == HANDLE_ALL_ARROWS) {
// Treat the right arrow as a Tab key and indicate that the key
// has been handled
focusManager.focusNextComponent();
handled = true;
}
break;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_KP_DOWN:
// Check if the down arrow key should be handled
if (arrowResponse == HANDLE_ALL_ARROWS || arrowResponse == HANDLE_DOWN_ARROW || arrowResponse == HANDLE_UP_AND_DOWN_ARROWS) {
// Treat the down arrow as a Tab key and indicate that the key
// has been handled
focusManager.focusNextComponent();
handled = true;
} else // Check if the down arrow should be ignored
if (arrowResponse == IGNORE_UP_AND_DOWN_ARROWS) {
// Indicate that the key has been handled
handled = true;
}
break;
}
}
} else // Check if the Ctrl key is pressed
if (ke.getID() == KeyEvent.KEY_PRESSED && ke.isControlDown() && !ke.isAltDown()) {
// Check if the Ctrl-Z key is pressed
if (ke.getKeyCode() == KeyEvent.VK_Z) {
// Get the currently active undo manager
final CcddUndoManager undoManager = getActiveUndoManager();
// Check if an active undo manager was found
if (undoManager != null) {
// Create a runnable object to be executed
SwingUtilities.invokeLater(new Runnable() {
/**
****************************************************************
* Execute after all pending Swing events are finished so that the
* events occur in the desired order
****************************************************************
*/
@Override
public void run() {
// Undo the previous edit action
undoManager.undo();
// associated with the component
if (editPnlHandler != null) {
// Update the data field background colors
editPnlHandler.setFieldBackgound();
}
// Force the component to repaint so that the change is visible
ke.getComponent().repaint();
}
});
// Set the flag to indicate this key press was handled
handled = true;
}
} else // Check if the Ctrl-Y key is pressed
if (ke.getKeyCode() == KeyEvent.VK_Y) {
// Get the currently active undo manager
final CcddUndoManager undoManager = getActiveUndoManager();
// Check if an active undo manager was found
if (undoManager != null) {
// Create a runnable object to be executed
SwingUtilities.invokeLater(new Runnable() {
/**
****************************************************************
* Execute after all pending Swing events are finished so that the
* events occur in the desired order
****************************************************************
*/
@Override
public void run() {
// Redo the previous undo action
undoManager.redo();
// associated with the component
if (editPnlHandler != null) {
// Update the data field background colors
editPnlHandler.setFieldBackgound();
}
// Force the component to repaint so that the change is visible
ke.getComponent().repaint();
}
});
// Set the flag to indicate this key press was handled
handled = true;
}
} else // focus
if (ke.getKeyCode() == KeyEvent.VK_F && ccddMain.getMainFrame().isFocused()) {
// Open the event log search dialog
ccddMain.showSearchDialog(SearchDialogType.LOG, null, ccddMain.getSessionEventLog(), ccddMain.getMainFrame());
// Set the flag to indicate this key press was handled
handled = true;
} else // insertion
if (ke.getKeyCode() == KeyEvent.VK_S) {
// Get the table editor dialog with the focus
CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
// contain a combo box
if (editorDialog != null && !(comp instanceof JComboBox)) {
// Check if a cell in the table is being edited
if (editorDialog.getTableEditor().getTable().isEditing()) {
// Insert the structure name chosen by the user into the text field
// at the current text insertion point
dataTypeHandler.insertDataTypeName((JFrame) editorDialog, (JTextArea) comp, true, editorDialog.getTableEditor().getValidDataTypes().toArray(new String[0]));
}
} else // Check if the data type editor editing is active
if (SwingUtilities.getWindowAncestor(comp) instanceof CcddDataTypeEditorDialog && modalTable.isEditing()) {
// Get the row and column being edited in the table, and the contents
// of the edited row's base data type
int row = modalTable.getEditingRow();
int column = modalTable.convertColumnIndexToModel(modalTable.getEditingColumn());
String baseType = modalTable.getValueAt(row, DataTypeEditorColumnInfo.BASE_TYPE.ordinal()).toString();
// base data type is empty or a pointer
if ((column == DataTypeEditorColumnInfo.USER_NAME.ordinal() || column == DataTypeEditorColumnInfo.C_NAME.ordinal()) && (baseType.isEmpty() || baseType.equals(BaseDataTypeInfo.POINTER.getName()))) {
// Insert the structure name chosen by the user into the text field
// at the current text insertion point
dataTypeHandler.insertDataTypeName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextArea) comp, false, null);
}
} else // Check if the macro editor editing is active
if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog && modalTable.isEditing()) {
// Insert the structure name chosen by the user into the text field at
// the current text insertion point
dataTypeHandler.insertDataTypeName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextArea) comp, true, null);
}
// Set the flag to indicate this key press was handled
handled = true;
} else // and expansion
if (ke.getKeyCode() == KeyEvent.VK_M) {
// Check if the shift key is also pressed (Ctrl-Shift-M)
if (ke.isShiftDown()) {
// Check if the macros aren't already expanded
if (!isShowMacros) {
// Get the table editor dialog with the focus
CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
// Check if a table editor dialog has the focus
if (editorDialog != null) {
// Replace the macro names with their corresponding values in
// the currently selected table in this editor
editorDialog.getTableEditor().expandMacros(true, true);
isShowMacros = true;
} else // Check if this is the macro editor
if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog) {
// Expand the macros in the macro value column
((CcddMacroEditorDialog) SwingUtilities.getWindowAncestor(comp)).expandMacros(true);
isShowMacros = true;
}
}
} else // The shift key isn't pressed (Ctrl-M only). Check if this is a table cell
if (comp.getParent() instanceof CcddJTableHandler) {
// Get the table editor dialog with the focus
CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
// doesn't contain a combo box
if (editorDialog != null && !(comp instanceof JComboBox)) {
// Get references to shorten subsequent calls
CcddTableEditorHandler editor = editorDialog.getTableEditor();
CcddJTableHandler table = editor.getTable();
// Check if a cell in the table is being edited
if (table.isEditing()) {
// Get the index of the column being edited in model
// coordinates
int column = table.convertColumnIndexToModel(table.getEditingColumn());
// Get the input type for the column being edited
InputDataType inputType = editor.getTableTypeDefinition().getInputTypes()[column];
// Insert the macro name chosen by the user into the text
// component at the current text insertion point
macroHandler.insertMacroName(editorDialog, (JTextComponent) comp, inputType, editor.getValidDataTypes());
}
} else // column is being edited
if (SwingUtilities.getWindowAncestor(comp) instanceof CcddMacroEditorDialog && modalTable.isEditing() && modalTable.convertColumnIndexToModel(modalTable.getEditingColumn()) == MacroEditorColumnInfo.VALUE.ordinal()) {
// Insert the macro name chosen by the user into the text component
// at the current text insertion point
macroHandler.insertMacroName((JDialog) SwingUtilities.getWindowAncestor(comp), (JTextComponent) comp, InputDataType.TEXT, null);
}
}
// Set the flag to indicate this key press was handled
handled = true;
} else // Check if the Ctrl-E key is pressed while the focus is on a tree
if (ke.getKeyCode() == KeyEvent.VK_E && comp instanceof CcddCommonTreeHandler) {
// Expand/collapse the selected node(s)
((CcddCommonTreeHandler) comp).expandCollapseSelectedNodes();
}
} else // text
if (ke.getID() == KeyEvent.KEY_PRESSED && ke.isAltDown() && !ke.isControlDown() && ke.getKeyCode() == KeyEvent.VK_ENTER && comp.getParent() instanceof CcddJTableHandler && comp instanceof JTextArea) {
// Get the table editor dialog with the focus
CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
// Check if a table editor dialog has the focus
if (editorDialog != null) {
// Check if a cell in the table is being edited
if (editorDialog.getTableEditor().getTable().isEditing()) {
JTextComponent textComp = (JTextComponent) comp;
// Get the cell's current value
String cellValue = textComp.getText();
// Get the starting position of the selected text
int caretPosn = textComp.getSelectionStart();
// Replace the currently selected text with a line feed
textComp.setText(cellValue.substring(0, caretPosn) + "\n" + cellValue.substring(textComp.getSelectionEnd()));
// Position the cursor after the newly inserted line feed
textComp.setCaretPosition(caretPosn + 1);
}
}
}
// key sequence is no longer active
if (isShowMacros && ke.getID() == KeyEvent.KEY_RELEASED && ke.getKeyCode() == KeyEvent.VK_M) {
// Check if the key release action timer doesn't exist
if (releaseTimer == null) {
// Create the key release action timer. In Linux if a key is held it
// generates continuous key release events. This timer is used to ignore
// the key release events that are close together time-wise
releaseTimer = new Timer(75, new ActionListener() {
/**
********************************************************************
* Handle the key release action
********************************************************************
*/
@Override
public void actionPerformed(ActionEvent ae) {
// Get the table editor dialog with the focus
CcddTableEditorDialog editorDialog = getFocusedTableEditorDialog();
// Check if a table editor dialog has the focus
if (editorDialog != null) {
// Restore the macro names in the currently selected table in
// this editor
editorDialog.getTableEditor().expandMacros(false, true);
isShowMacros = false;
} else // Check if this is the macro editor
if (SwingUtilities.getWindowAncestor(modalTable) instanceof CcddMacroEditorDialog) {
// Expand the macros in the macro value column
((CcddMacroEditorDialog) SwingUtilities.getWindowAncestor(modalTable)).expandMacros(false);
isShowMacros = false;
}
}
});
// Allow the timer to send only a single expiration event
releaseTimer.setRepeats(false);
}
// (Re)start the key release action timer
releaseTimer.restart();
// Set the flag to indicate this key press was handled
handled = true;
}
return handled;
}
});
}
use of java.awt.KeyEventDispatcher in project freeplane by freeplane.
the class PresentationController method install.
public static void install(final ModeController modeController) {
final PresentationController presentationController = new PresentationController(modeController);
modeController.addExtension(PresentationController.class, presentationController);
presentationController.registerActions();
presentationController.addMapSelectionListener();
new PresentationBuilder().register(modeController.getMapController(), presentationController);
HighlightController highlightController = modeController.getController().getExtension(HighlightController.class);
final PresentationState presentationState = presentationController.presentationState;
new PresentationPngExporter.ActionInstaller().installActions(modeController, presentationState);
final JTabbedPane tabs = (JTabbedPane) modeController.getUserInputListenerFactory().getToolBar("/format").getComponent(1);
tabs.add("Presentations", presentationController.createPanel());
highlightController.addNodeHighlighter(new NodeHighlighter() {
@Override
public boolean isNodeHighlighted(NodeModel node, boolean isPrinting) {
return !isPrinting && presentationState.shouldHighlightNodeContainedOnSlide(node);
}
@Override
public void configure(Graphics2D g, boolean isPrinting) {
g.setColor(NODE_HIGHLIGHTING_COLOR);
}
});
highlightController.addNodeHighlighter(new NodeHighlighter() {
@Override
public boolean isNodeHighlighted(NodeModel node, boolean isPrinting) {
return !isPrinting && presentationState.shouldHighlightNodeFoldedOnSlide(node);
}
@Override
public void configure(Graphics2D g, boolean isPrinting) {
g.setColor(NODE_HIGHLIGHTING_COLOR);
g.setStroke(FOLDED_NODE_STROKE);
}
});
KeyEventDispatcher navigationKeyEventDispatcher = new NavigationKeyEventDispatcher(presentationState);
KeyEventDispatcher escapeKeyEventDispatcher = new EscapeKeyEventDispatcher(presentationState);
final PresentationAutomation presentationKeyHandler = new PresentationAutomation(presentationState, PresentationKeyEventDispatcher.of(navigationKeyEventDispatcher, PROCESS_NAVIGATION_KEYS_PROPERTY), PresentationKeyEventDispatcher.of(escapeKeyEventDispatcher, PROCESS_ESCAPE_KEY_PROPERTY));
presentationState.addPresentationStateListener(presentationKeyHandler);
}
use of java.awt.KeyEventDispatcher in project Universal-G-Code-Sender by winder.
the class MainWindow method initProgram.
private void initProgram() {
Localization.initialize(this.settings.getLanguage());
try {
backend.applySettings(settings);
} catch (Exception e) {
displayErrorDialog(e.getMessage());
}
this.setLocalLabels();
this.loadPortSelector();
this.checkScrollWindow();
this.loadFirmwareSelector();
this.setTitle(Localization.getString("title") + " (" + Localization.getString("version") + " " + Version.getVersionString() + ")");
// Command History
this.manualCommandHistory = new ArrayList<>();
// Add keyboard listener for manual controls.
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
// Check context.
if (((jogPanel.isKeyboardMovementEnabled()) && e.getID() == KeyEvent.KEY_PRESSED)) {
switch(e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_KP_RIGHT:
case KeyEvent.VK_NUMPAD6:
jogPanel.xPlusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_LEFT:
case KeyEvent.VK_KP_LEFT:
case KeyEvent.VK_NUMPAD4:
jogPanel.xMinusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_UP:
case KeyEvent.VK_KP_UP:
case KeyEvent.VK_NUMPAD8:
jogPanel.yPlusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_KP_DOWN:
case KeyEvent.VK_NUMPAD2:
jogPanel.yMinusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_PAGE_UP:
case KeyEvent.VK_NUMPAD9:
jogPanel.zPlusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_PAGE_DOWN:
case KeyEvent.VK_NUMPAD3:
jogPanel.zMinusButtonActionPerformed();
e.consume();
return true;
case KeyEvent.VK_ADD:
jogPanel.increaseStepActionPerformed();
e.consume();
return true;
case KeyEvent.VK_SUBTRACT:
jogPanel.decreaseStepActionPerformed();
e.consume();
return true;
case KeyEvent.VK_DIVIDE:
jogPanel.divideStepActionPerformed();
e.consume();
return true;
case KeyEvent.VK_MULTIPLY:
jogPanel.multiplyStepActionPerformed();
e.consume();
return true;
case KeyEvent.VK_INSERT:
case KeyEvent.VK_NUMPAD0:
// resetCoordinatesButtonActionPerformed(null);
e.consume();
return true;
default:
break;
}
}
return false;
}
});
}
use of java.awt.KeyEventDispatcher in project jadx by skylot.
the class JDebuggerPanel method regShortcuts.
private void regShortcuts() {
controllerShortCutDispatcher = new KeyEventDispatcher() {
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED && mainWindow.getTabbedPane().getFocusedComp() instanceof SmaliArea) {
if (e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK && e.getKeyCode() == KeyEvent.VK_F8) {
controller.stepOut();
return true;
}
switch(e.getKeyCode()) {
case KeyEvent.VK_F7:
controller.stepInto();
return true;
case KeyEvent.VK_F8:
controller.stepOver();
return true;
case KeyEvent.VK_F9:
controller.run();
return true;
}
}
return false;
}
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(controllerShortCutDispatcher);
}
Aggregations