Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions src/main/java/com/googlecode/lanterna/gui2/AbstractBasePane.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,12 @@ public boolean handleInput(KeyStroke key) {

// Now try to deliver the event to the focused component
boolean handled = doHandleInput(key);

if (!handled)
{
// Now try to deliver the event as an accelerator to unfocused components
handled = doHandleAccelerator(key);
}

// If it wasn't handled, fire the listeners and decide what to report to the TextGUI
if(!handled) {
AtomicBoolean hasBeenHandled = new AtomicBoolean(false);
Expand All @@ -111,9 +116,42 @@ public boolean handleInput(KeyStroke key) {
}
return handled;
}

abstract T self();

private boolean doHandleAccelerator(KeyStroke key)
{
if (key.getKeyType() == KeyType.MOUSE_EVENT) return false;

MenuBar menuBar = getMenuBar();

// Check menu accelerators
if (menuBar != null && menuBar.handleInput(key)) return true;

// Check on base component
return handleAccelerator(contentHolder, key);
}

private boolean handleAccelerator(Container container, KeyStroke key)
{
// Check unfocused buttons
for (Component child : container.getChildren())
{
if (child instanceof Button)
{
Button btn = (Button) child;
if (btn.handleInput(key) == Result.HANDLED) return true;
}

if (child instanceof Container && ((Container)child).getChildCount() > 0)
{
if (handleAccelerator((Container)child, key)) return true;
}
}

return false;
}

private boolean doHandleInput(KeyStroke key) {
boolean result = false;
if(key.getKeyType() == KeyType.MOUSE_EVENT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public abstract class AbstractInteractableComponent<T extends AbstractInteractab
private InputFilter inputFilter;
private boolean inFocus;
private boolean enabled;
private KeyStroke accelerator;

/**
* Default constructor
Expand Down Expand Up @@ -81,6 +82,14 @@ protected void afterEnterFocus(FocusChangeDirection direction, Interactable prev
//By default no action
}

protected synchronized T setAccelerator(KeyStroke keyStroke)
{
this.accelerator = keyStroke;
return self();
}

protected synchronized KeyStroke getAccelerator() { return this.accelerator; };

/**
* {@inheritDoc}
* <p>
Expand Down Expand Up @@ -190,7 +199,7 @@ protected Result handleKeyStroke(KeyStroke keyStroke) {
public TerminalPosition getCursorLocation() {
return getRenderer().getCursorLocation(self());
}

@Override
public InputFilter getInputFilter() {
return inputFilter;
Expand All @@ -208,6 +217,13 @@ public boolean isKeyboardActivationStroke(KeyStroke keyStroke) {
return isFocused() && isKeyboardActivation;
}

public boolean isKeyboardAcceleratorStroke(KeyStroke keyStroke)
{
if (accelerator == null) return false;

return isEnabled() && accelerator.equals(keyStroke);
}

public boolean isMouseActivationStroke(KeyStroke keyStroke) {
boolean isMouseActivation = false;
if (keyStroke instanceof MouseAction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ public synchronized Result handleKeyStroke(KeyStroke keyStroke) {
return Result.HANDLED;

case CHARACTER:
if(selectByCharacter(keyStroke.getCharacter())) {
// Only check is Alt and Ctrl keys are not pressed signaling a possible accelerator key
if(!keyStroke.isAltDown() && !keyStroke.isCtrlDown() && selectByCharacter(keyStroke.getCharacter())) {
return Result.HANDLED;
}
return Result.UNHANDLED;
Expand Down
14 changes: 11 additions & 3 deletions src/main/java/com/googlecode/lanterna/gui2/Button.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import com.googlecode.lanterna.TerminalTextUtils;
import com.googlecode.lanterna.graphics.ThemeDefinition;
import com.googlecode.lanterna.input.KeyStroke;
import com.googlecode.lanterna.input.KeyType;

/**
* Simple labeled button that the user can trigger by pressing the Enter or the Spacebar key on the keyboard when the
Expand Down Expand Up @@ -81,12 +80,21 @@ public synchronized TerminalPosition getCursorLocation() {
return getRenderer().getCursorLocation(this);
}

public Button setAccelerator(KeyStroke keyStroke)
{
return super.setAccelerator(keyStroke);
}

public KeyStroke getAccelerator() { return super.getAccelerator(); };

@Override
public synchronized Result handleKeyStroke(KeyStroke keyStroke) {
if (isActivationStroke(keyStroke)) {
if (isActivationStroke(keyStroke) || isKeyboardAcceleratorStroke(keyStroke))
{
getBasePane().setFocusedInteractable(this);
triggerActions();
return Result.HANDLED;
}
}
return super.handleKeyStroke(keyStroke);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

package com.googlecode.lanterna.gui2.dialogs;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;

import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.ActionListBox;
import com.googlecode.lanterna.gui2.BorderLayout;
Expand All @@ -32,10 +36,7 @@
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.TextBox;
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import com.googlecode.lanterna.input.KeyStroke;

/**
* Dialog that allows the user to iterate the file system and pick directory.
Expand Down Expand Up @@ -101,8 +102,8 @@ public DirectoryDialog(

Panel panelButtons = new Panel(new GridLayout(2));
panelButtons.setLayoutData(GridLayout.createLayoutData(GridLayout.Alignment.END, GridLayout.Alignment.CENTER, false, false, 2, 1));
panelButtons.addComponent(new Button(actionLabel, new OkHandler()));
panelButtons.addComponent(new Button(LocalizedString.Cancel.toString(), new CancelHandler()));
panelButtons.addComponent(new Button(actionLabel, new OkHandler()).setAccelerator(new KeyStroke('s', false, true)));
panelButtons.addComponent(new Button(LocalizedString.Cancel.toString(), new CancelHandler()).setAccelerator(new KeyStroke('c', false, true)));
contentPane.addComponent(panelButtons, Location.BOTTOM);

if (selectedObject.isFile()) {
Expand Down
24 changes: 18 additions & 6 deletions src/main/java/com/googlecode/lanterna/gui2/dialogs/FileDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,26 @@
*/
package com.googlecode.lanterna.gui2.dialogs;

import com.googlecode.lanterna.TerminalTextUtils;
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.*;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;

import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.TerminalTextUtils;
import com.googlecode.lanterna.gui2.ActionListBox;
import com.googlecode.lanterna.gui2.Borders;
import com.googlecode.lanterna.gui2.Button;
import com.googlecode.lanterna.gui2.Direction;
import com.googlecode.lanterna.gui2.GridLayout;
import com.googlecode.lanterna.gui2.Label;
import com.googlecode.lanterna.gui2.LocalizedString;
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.Panels;
import com.googlecode.lanterna.gui2.Separator;
import com.googlecode.lanterna.gui2.TextBox;
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
import com.googlecode.lanterna.input.KeyStroke;

/**
* Dialog that allows the user to iterate the file system and pick file to open/save
*
Expand Down Expand Up @@ -129,10 +141,10 @@ public FileDialog(
1))
.addTo(contentPane);

okButton = new Button(actionLabel, new OkHandler());
okButton = new Button(actionLabel, new OkHandler()).setAccelerator(new KeyStroke('o', false, true));
Panels.grid(2,
okButton,
new Button(LocalizedString.Cancel.toString(), new CancelHandler()))
new Button(LocalizedString.Cancel.toString(), new CancelHandler()).setAccelerator(new KeyStroke('c', false, true)))
.setLayoutData(GridLayout.createLayoutData(GridLayout.Alignment.END, GridLayout.Alignment.CENTER, false, false, 2, 1))
.addTo(contentPane);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@
package com.googlecode.lanterna.gui2.dialogs;

import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.*;
import com.googlecode.lanterna.gui2.Button;
import com.googlecode.lanterna.gui2.EmptySpace;
import com.googlecode.lanterna.gui2.GridLayout;
import com.googlecode.lanterna.gui2.Label;
import com.googlecode.lanterna.gui2.Panel;
import com.googlecode.lanterna.gui2.WindowBasedTextGUI;
import com.googlecode.lanterna.input.KeyStroke;

/**
* Simple message dialog that displays a message and has optional selection/confirmation buttons
Expand Down Expand Up @@ -47,7 +53,7 @@ public class MessageDialog extends DialogWindow {
buttonPanel.addComponent(new Button(button.toString(), () -> {
result = button;
close();
}));
}).setAccelerator(new KeyStroke(button.getAcceleratorCharacter(), false, true)));
}

Panel mainPanel = new Panel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,47 +30,50 @@ public enum MessageDialogButton {
/**
* "OK"
*/
OK(LocalizedString.OK),
OK(LocalizedString.OK, 'o'),
/**
* "Cancel"
*/
CANCEL(LocalizedString.Cancel),
CANCEL(LocalizedString.Cancel, 'c'),
/**
* "Yes"
*/
YES(LocalizedString.Yes),
YES(LocalizedString.Yes, 'y'),
/**
* "No"
*/
NO(LocalizedString.No),
NO(LocalizedString.No, 'n'),
/**
* "Close"
*/
CLOSE(LocalizedString.Close),
CLOSE(LocalizedString.Close, 'x'),
/**
* "Abort"
*/
ABORT(LocalizedString.Abort),
ABORT(LocalizedString.Abort, 'a'),
/**
* "Ignore"
*/
IGNORE(LocalizedString.Ignore),
IGNORE(LocalizedString.Ignore, 'i'),
/**
* "Retry"
*/
RETRY(LocalizedString.Retry),
RETRY(LocalizedString.Retry, 'r'),

/**
* "Continue"
*/
CONTINUE(LocalizedString.Continue);
CONTINUE(LocalizedString.Continue, 'c');

private final LocalizedString label;
private final char acceleratorChar;

MessageDialogButton(final LocalizedString label) {
MessageDialogButton(final LocalizedString label, char acceleratorChar) {
this.label = label;
this.acceleratorChar = acceleratorChar;
}

public char getAcceleratorCharacter() { return acceleratorChar; }
@Override
public String toString() {
return label.toString();
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/googlecode/lanterna/gui2/menu/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ public Menu add(MenuItem menuItem) {
return this;
}

public List<MenuItem> getSubMenus()
{
return new ArrayList<>(subItems);
}

public Menu setAccelerator(KeyStroke keyStroke)
{
super.setAccelerator(keyStroke);
return this;
}

@Override
protected boolean onActivated() {
boolean result = true;
Expand Down Expand Up @@ -91,6 +102,16 @@ public void onUnhandledInput(Window basePane, KeyStroke keyStroke, AtomicBoolean
nextSelectedMenu.onActivated();
}
}

// Check if accelerator for c
for (MenuItem menuItem : subItems)
{
if (menuItem.isEnabled() && menuItem.isKeyboardAcceleratorStroke(keyStroke))
{
Result result = menuItem.handleKeyStroke(keyStroke);
if (result == Result.HANDLED) break;
}
}
}
});
}
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/googlecode/lanterna/gui2/menu/MenuBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,18 @@ else if (!menus.contains(fromThis) || menus.indexOf(fromThis) == 0) {
}

@Override
public boolean handleInput(KeyStroke key) {
public boolean handleInput(KeyStroke key)
{
// Process top level menus
for (Menu mnu : menus)
{
// Check to see if handled by accelerator
if (mnu.isKeyboardAcceleratorStroke(key))
{
mnu.handleKeyStroke(key);
return true;
}
}
return false;
}

Expand Down
Loading