From 4b8b858ddcab0bfbde80304a0f631233388a13d1 Mon Sep 17 00:00:00 2001 From: tzefferer Date: Fri, 16 Oct 2009 09:54:37 +0000 Subject: Keyboard accessibility for Online-BKU git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@528 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 5 + .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java | 280 ++++++++++++++++++--- .../java/at/gv/egiz/bku/gui/HelpKeyListener.java | 46 ++++ .../at/gv/egiz/bku/gui/HelpLinkFocusManager.java | 138 ++++++++++ .../main/java/at/gv/egiz/bku/gui/HelpViewer.java | 4 + .../at/gv/egiz/bku/gui/SecureViewerDialog.java | 35 ++- .../gv/egiz/bku/gui/SwitchFocusFocusListener.java | 38 +++ .../at/gv/egiz/bku/gui/SwitchFocusListener.java | 44 ++++ .../at/gv/egiz/bku/gui/Messages.properties | 2 + .../at/gv/egiz/bku/gui/Messages_en.properties | 2 + .../resources/at/gv/egiz/bku/gui/help_focus.png | Bin 0 -> 343 bytes .../test/java/at/gv/egiz/bku/gui/BKUGUITest.java | 2 +- 12 files changed, 557 insertions(+), 39 deletions(-) create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java create mode 100644 BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java index 6c27910a..e4af6443 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -46,6 +46,7 @@ public interface BKUGUIFacade { public static final String DEFAULT_BACKGROUND = "/at/gv/egiz/bku/gui/chip32.png"; public static final String DEFAULT_ICON = "/at/gv/egiz/bku/gui/chiperling105.png"; public static final String HELP_IMG = "/at/gv/egiz/bku/gui/help.png"; + public static final String HELP_IMG_FOCUS = "/at/gv/egiz/bku/gui/help_focus.png"; public static final String HASHDATA_FONT = "Monospaced"; public static final Color ERROR_COLOR = Color.RED; public static final Color HYPERLINK_COLOR = Color.BLUE; @@ -75,6 +76,8 @@ public interface BKUGUIFacade { public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad"; public static final String MESSAGE_HASHDATALINK = "hashdatalink"; public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny"; + public static final String MESSAGE_HASHDATALINK_FOCUS = "hashdatalink.focus"; + public static final String MESSAGE_HASHDATALINK_TINY_FOCUS = "hashdatalink.tiny.focus"; public static final String MESSAGE_HASHDATALIST = "hashdatalist"; public static final String MESSAGE_RETRIES = "retries"; public static final String MESSAGE_LAST_RETRY = "retries.last"; @@ -153,4 +156,6 @@ public interface BKUGUIFacade { public void showMessageDialog(String titleKey, String msgKey); + + public void getFocusFromBrowser(); } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index b84a2164..e83502a8 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -26,6 +26,10 @@ import java.awt.Font; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; @@ -45,11 +49,14 @@ import javax.swing.JTable; import javax.swing.LayoutStyle; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + + /** * * @author clemens @@ -62,7 +69,9 @@ public class BKUGUIImpl implements BKUGUIFacade { LEFT, ABOVE } - protected HelpMouseListener helpListener; + protected HelpMouseListener helpMouseListener; + protected HelpKeyListener helpKeyListener; + protected SwitchFocusFocusListener switchFocusKeyListener; protected SecureViewerDialog secureViewer; protected Container contentPane; @@ -77,6 +86,7 @@ public class BKUGUIImpl implements BKUGUIFacade { /** right side fixed labels */ protected JLabel titleLabel; protected JLabel helpLabel; + protected JLabel switchFocusDummyLabel; /** remember the pinfield to return to worker */ protected JPasswordField pinField; @@ -107,7 +117,8 @@ public class BKUGUIImpl implements BKUGUIFacade { Locale locale, Style guiStyle, URL background, - ActionListener helpListener) { + ActionListener helpListener, + SwitchFocusListener switchFocusListener) { this.contentPane = contentPane; loadMessageBundle(locale); @@ -122,8 +133,13 @@ public class BKUGUIImpl implements BKUGUIFacade { pinLabelPos = PinLabelPosition.ABOVE; } + // ensure that buttons can be fired with enter key too + UIManager.put("Button.defaultButtonFollowsFocus", Boolean.TRUE); + registerHelpListener(helpListener); + registerSwitchFocusListener(switchFocusListener); + createGUI(background); } @@ -224,12 +240,35 @@ public class BKUGUIImpl implements BKUGUIFacade { mainPanel.setOpaque(false); buttonPanel = new JPanel(); buttonPanel.setOpaque(false); - + helpLabel = new JLabel(); helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); helpLabel.getAccessibleContext().setAccessibleName(getMessage(ALT_HELP)); - helpLabel.addMouseListener(helpListener); + helpLabel.setFocusable(true); + helpLabel.addMouseListener(helpMouseListener); + helpLabel.addKeyListener(helpKeyListener); + helpLabel.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { + + helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG_FOCUS))); + } + + @Override + public void focusLost(FocusEvent e) { + + helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); + } + + + }); helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + switchFocusDummyLabel = new JLabel(); + switchFocusDummyLabel.setText(""); + switchFocusDummyLabel.setFocusable(true); + switchFocusDummyLabel.addFocusListener(switchFocusKeyListener); buttonSize = initButtonSize(); @@ -248,11 +287,15 @@ public class BKUGUIImpl implements BKUGUIFacade { headerPanelLayout.createSequentialGroup() .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ); headerPanelLayout.setVerticalGroup( headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) - .addComponent(helpLabel)); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ); } GroupLayout contentPanelLayout = new GroupLayout(contentPanel); @@ -566,7 +609,8 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()})); } - helpListener.setHelpTopic(HELP_CARDPIN); + helpMouseListener.setHelpTopic(HELP_CARDPIN); + helpKeyListener.setHelpTopic(HELP_CARDPIN); } else { String retryPattern; if (numRetries < 2) { @@ -577,7 +621,8 @@ public class BKUGUIImpl implements BKUGUIFacade { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); infoLabel.setForeground(ERROR_COLOR); - helpListener.setHelpTopic(HELP_RETRY); + helpMouseListener.setHelpTopic(HELP_RETRY); + helpKeyListener.setHelpTopic(HELP_RETRY); } JLabel pinsizeLabel = new JLabel(); @@ -595,9 +640,13 @@ public class BKUGUIImpl implements BKUGUIFacade { if (!renderHeaderPanel) { infoHorizontal .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; infoVertical - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; } // align pinfield and pinsize to the right @@ -668,7 +717,9 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanelLayout.setHorizontalGroup(buttonHorizontal); buttonPanelLayout.setVerticalGroup(buttonVertical); - pinField.requestFocusInWindow(); +// pinField.requestFocusInWindow(); +// helpLabel.requestFocus(); + pinField.requestFocus(); contentPanel.validate(); } @@ -715,7 +766,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } } - JLabel infoLabel = new JLabel(); + final JLabel infoLabel = new JLabel(); if (numRetries < 0) { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); if (shortText) { @@ -723,6 +774,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); } + infoLabel.setFocusable(true); infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); infoLabel.setForeground(HYPERLINK_COLOR); infoLabel.addMouseListener(new MouseAdapter() { @@ -733,7 +785,47 @@ public class BKUGUIImpl implements BKUGUIFacade { hashdataListener.actionPerformed(e); } }); - helpListener.setHelpTopic(HELP_SIGNPIN); + + infoLabel.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + + if(e.getKeyCode() == KeyEvent.VK_ENTER) { + ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e1); + } + } + + }); + + infoLabel.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { + + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); + } + } + + @Override + public void focusLost(FocusEvent e) { + + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + + } + + }); + + helpMouseListener.setHelpTopic(HELP_SIGNPIN); + helpKeyListener.setHelpTopic(HELP_SIGNPIN); } else { String retryPattern; if (numRetries < 2) { @@ -741,10 +833,12 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { retryPattern = getMessage(MESSAGE_RETRIES); } + infoLabel.setFocusable(true); infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setForeground(ERROR_COLOR); - helpListener.setHelpTopic(HELP_RETRY); + helpMouseListener.setHelpTopic(HELP_RETRY); + helpKeyListener.setHelpTopic(HELP_RETRY); } String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD); @@ -766,9 +860,13 @@ public class BKUGUIImpl implements BKUGUIFacade { if (!renderHeaderPanel) { infoHorizontal .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; infoVertical - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; } mainPanelLayout.setHorizontalGroup( @@ -837,7 +935,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } } - JLabel infoLabel = new JLabel(); + final JLabel infoLabel = new JLabel(); if (numRetries < 0) { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); if (shortText) { @@ -845,6 +943,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); } + infoLabel.setFocusable(true); infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); infoLabel.setForeground(HYPERLINK_COLOR); infoLabel.addMouseListener(new MouseAdapter() { @@ -855,7 +954,49 @@ public class BKUGUIImpl implements BKUGUIFacade { hashdataListener.actionPerformed(e); } }); - helpListener.setHelpTopic(HELP_SIGNPIN); + + infoLabel.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + + if(e.getKeyCode() == KeyEvent.VK_ENTER) { + ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand); + hashdataListener.actionPerformed(e1); + } + } + + }); + + infoLabel.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { + + + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS)); + } + } + + @Override + public void focusLost(FocusEvent e) { + + + if (shortText) { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY)); + } else { + infoLabel.setText(getMessage(MESSAGE_HASHDATALINK)); + } + + } + + }); + + helpMouseListener.setHelpTopic(HELP_SIGNPIN); + helpKeyListener.setHelpTopic(HELP_SIGNPIN); } else { String retryPattern; if (numRetries < 2) { @@ -863,10 +1004,12 @@ public class BKUGUIImpl implements BKUGUIFacade { } else { retryPattern = getMessage(MESSAGE_RETRIES); } + infoLabel.setFocusable(true); infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)})); infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setForeground(ERROR_COLOR); - helpListener.setHelpTopic(HELP_RETRY); + helpMouseListener.setHelpTopic(HELP_RETRY); + helpKeyListener.setHelpTopic(HELP_RETRY); } JButton signButton = new JButton(); @@ -895,6 +1038,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } }); + JLabel pinsizeLabel = new JLabel(); pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength())); @@ -910,9 +1054,13 @@ public class BKUGUIImpl implements BKUGUIFacade { if (!renderHeaderPanel) { infoHorizontal .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; infoVertical - .addComponent(helpLabel); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; } // align pinfield and pinsize to the right @@ -973,21 +1121,27 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonHorizontal .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + ; buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(signButton) - .addComponent(cancelButton); + .addComponent(cancelButton) + ; } else { buttonHorizontal - .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); + .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + ; buttonVertical = buttonPanelLayout.createSequentialGroup() - .addComponent(signButton); + .addComponent(signButton) + ; } buttonPanelLayout.setHorizontalGroup(buttonHorizontal); buttonPanelLayout.setVerticalGroup(buttonVertical); - pinField.requestFocusInWindow(); +// pinField.requestFocusInWindow(); +// helpLabel.requestFocus(); + pinField.requestFocus(); contentPanel.validate(); } @@ -1065,7 +1219,8 @@ public class BKUGUIImpl implements BKUGUIFacade { titleLabel.setText(getMessage(titleKey)); } - helpListener.setHelpTopic(msgKey); + helpMouseListener.setHelpTopic(msgKey); + helpKeyListener.setHelpTopic(msgKey); String msgPattern = getMessage(msgKey); String msg = MessageFormat.format(msgPattern, msgParams); @@ -1080,6 +1235,9 @@ public class BKUGUIImpl implements BKUGUIFacade { GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); + log.debug("focus to contentPanel"); + contentPanel.requestFocus(); + if (!renderHeaderPanel) { JLabel titleLabel = new JLabel(); titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | Font.BOLD)); @@ -1092,11 +1250,18 @@ public class BKUGUIImpl implements BKUGUIFacade { .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(titleLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel)); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ); mainVertical .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(titleLabel) - .addComponent(helpLabel)); + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ); + + log.debug("focus to helpLabel"); + helpLabel.requestFocus(); } mainPanelLayout.setHorizontalGroup(mainHorizontal @@ -1105,6 +1270,7 @@ public class BKUGUIImpl implements BKUGUIFacade { .addComponent(msgLabel)); if (okListener != null) { + JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); okButton.setText(getMessage((buttonKey != null) ? buttonKey : BUTTON_OK)); @@ -1120,6 +1286,9 @@ public class BKUGUIImpl implements BKUGUIFacade { buttonPanelLayout.setVerticalGroup( buttonPanelLayout.createSequentialGroup() .addComponent(okButton)); + + log.debug("focus to ok-button"); + okButton.requestFocus(); } contentPanel.validate(); @@ -1243,7 +1412,7 @@ public class BKUGUIImpl implements BKUGUIFacade { log.debug("show secure viewer [" + Thread.currentThread().getName() + "]"); if (secureViewer == null) { secureViewer = new SecureViewerDialog(null, messages, - helpListener.getActionListener()); + helpMouseListener.getActionListener()); // workaround for [#439] // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top. @@ -1276,7 +1445,8 @@ public class BKUGUIImpl implements BKUGUIFacade { titleLabel.setText(getMessage(TITLE_HASHDATA)); } - helpListener.setHelpTopic(HELP_HASHDATALIST); + helpMouseListener.setHelpTopic(HELP_HASHDATALIST); + helpKeyListener.setHelpTopic(HELP_HASHDATALIST); JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -1335,10 +1505,14 @@ public class BKUGUIImpl implements BKUGUIFacade { if (!renderHeaderPanel) { messageHorizontal - .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) - .addComponent(helpLabel); - messageVertical - .addComponent(helpLabel); + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; + messageVertical + .addComponent(switchFocusDummyLabel) + .addComponent(helpLabel) + ; } mainPanelLayout.setHorizontalGroup( @@ -1469,19 +1643,42 @@ public class BKUGUIImpl implements BKUGUIFacade { private void registerHelpListener(ActionListener helpListener) { if (helpListener != null) { - this.helpListener = new HelpMouseListener(helpListener); + this.helpMouseListener = new HelpMouseListener(helpListener); + this.helpKeyListener = new HelpKeyListener(helpListener); } else { log.error("no help listener provided, will not be able to display help"); - this.helpListener = new HelpMouseListener(new ActionListener() { + this.helpMouseListener = new HelpMouseListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")"); } }); + this.helpKeyListener = new HelpKeyListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")"); + } + }); } } + private void registerSwitchFocusListener(ActionListener switchFocusListener) { + if (switchFocusListener != null) { + this.switchFocusKeyListener = new SwitchFocusFocusListener(switchFocusListener); + + } else { + + this.switchFocusKeyListener = new SwitchFocusFocusListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + log.warn("no switch focus listener registered"); + } + }); + } + } //////////////////////////////////////////////////////////////////////////// // INITIALIZERS (MAY BE OVERRIDDEN BY SUBCLASSES) @@ -1539,4 +1736,13 @@ public class BKUGUIImpl implements BKUGUIFacade { } return bs; } + + @Override + public void getFocusFromBrowser() { + + // This method puts the focus to the helpLabel as this + // element is supposed to appear in each dialogue. + helpLabel.requestFocus(); + + } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java new file mode 100644 index 00000000..4ca20f7e --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java @@ -0,0 +1,46 @@ +package at.gv.egiz.bku.gui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Thomas Zefferer + */ +public class HelpKeyListener extends KeyAdapter { + + protected static final Log log = LogFactory.getLog(HelpKeyListener.class); + + protected ActionListener helpListener; + protected String locale; + protected String topic; + + public HelpKeyListener(ActionListener externalHelpListener) { + super(); + this.helpListener = externalHelpListener; + } + + public void setHelpTopic(String topic) { + log.trace("setting help topic: " + topic); + this.topic = topic; + } + + public ActionListener getActionListener() { + return helpListener; + } + + @Override + public void keyPressed(KeyEvent arg0) { + + if(arg0.getKeyCode() == KeyEvent.VK_ENTER) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, topic); + helpListener.actionPerformed(e); + } + } + +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java new file mode 100644 index 00000000..f5882b3d --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java @@ -0,0 +1,138 @@ +package at.gv.egiz.bku.gui; + +import java.awt.Color; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.net.URL; + +import javax.accessibility.AccessibleHyperlink; +import javax.accessibility.AccessibleHypertext; +import javax.swing.JEditorPane; +import javax.swing.event.HyperlinkEvent; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.Element; +import javax.swing.text.MutableAttributeSet; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; + +/** + * + * @author Thomas Zefferer + */ +public final class HelpLinkFocusManager extends KeyAdapter { + + private static final int FOCUS_UNDEFINED = -1; + + private int focusedHyperlinkIndex = FOCUS_UNDEFINED; + private JEditorPane displayPane; + + public HelpLinkFocusManager(JEditorPane displayPane) { + + super(); + this.displayPane = displayPane; + } + + public void keyPressed(KeyEvent e) { + + AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane + .getAccessibleContext().getAccessibleText(); + + if (accessibleHypertext.getLinkCount() > 0) { + switch (e.getKeyCode()) { + + case KeyEvent.VK_RIGHT: + if (this.focusedHyperlinkIndex != FOCUS_UNDEFINED) { + removeHyperlinkFocus(); + } + + this.focusedHyperlinkIndex++; + + if (this.focusedHyperlinkIndex >= accessibleHypertext + .getLinkCount()) { + + this.focusedHyperlinkIndex = 0; + } + + setHyperlinkFocus(); + break; + + case KeyEvent.VK_LEFT: + if (this.focusedHyperlinkIndex != FOCUS_UNDEFINED) { + removeHyperlinkFocus(); + } + + this.focusedHyperlinkIndex--; + + if (this.focusedHyperlinkIndex < 0) { + this.focusedHyperlinkIndex = accessibleHypertext + .getLinkCount() - 1; + } + + setHyperlinkFocus(); + break; + + case KeyEvent.VK_SPACE: + case KeyEvent.VK_ENTER: + + + AccessibleHyperlink link = accessibleHypertext + .getLink(this.focusedHyperlinkIndex); + if (link != null) { + URL url = (URL) link.getAccessibleActionObject(0); + Element element = ((DefaultStyledDocument) this.displayPane + .getDocument()).getCharacterElement(link + .getStartIndex()); + HyperlinkEvent linkEvent = new HyperlinkEvent( + this.displayPane, + HyperlinkEvent.EventType.ACTIVATED, url, null, + element); + this.displayPane.fireHyperlinkUpdate(linkEvent); + } + + removeHyperlinkFocus(); + this.focusedHyperlinkIndex = FOCUS_UNDEFINED; + break; + default: + // nothig to do + break; + } + } + } + + private void setHyperlinkFocus() { + + AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane + .getAccessibleContext().getAccessibleText(); + AccessibleHyperlink link = accessibleHypertext + .getLink(this.focusedHyperlinkIndex); + + if (link != null) { + + MutableAttributeSet style = new SimpleAttributeSet(); + StyleConstants.setForeground(style, Color.RED); + ((DefaultStyledDocument) this.displayPane.getDocument()) + .setCharacterAttributes(link.getStartIndex(), link + .getEndIndex() + - link.getStartIndex(), style, false); + } + } + + private void removeHyperlinkFocus() { + Color textColor = Color.BLUE; + AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane + .getAccessibleContext().getAccessibleText(); + AccessibleHyperlink link = accessibleHypertext + .getLink(this.focusedHyperlinkIndex); + + if (link != null) { + + MutableAttributeSet style = new SimpleAttributeSet(); + StyleConstants.setForeground(style, textColor); + ((DefaultStyledDocument) this.displayPane.getDocument()) + .setCharacterAttributes(link.getStartIndex(), link + .getEndIndex() + - link.getStartIndex(), style, false); + } + } + +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java index 48393101..0f887f78 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java @@ -135,6 +135,10 @@ public class HelpViewer extends JDialog try { viewer.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); viewer.setPage(helpURL); + + HelpLinkFocusManager editorFocusManager = new HelpLinkFocusManager (viewer); + viewer.addKeyListener(editorFocusManager ); + viewer.addHyperlinkListener(new HyperlinkListener() { @Override diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java index 84c2a5ff..ef70f94b 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java @@ -24,6 +24,10 @@ import java.awt.Font; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.BufferedOutputStream; @@ -149,7 +153,8 @@ public class SecureViewerDialog extends JDialog implements ActionListener { infoVertical.addComponent(viewerLabel); if (helpListener != null) { - JLabel helpLabel = new JLabel(); + final JLabel helpLabel = new JLabel(); + helpLabel.setFocusable(true); helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP)); helpLabel.addMouseListener(new MouseAdapter() { @@ -159,6 +164,34 @@ public class SecureViewerDialog extends JDialog implements ActionListener { ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); helpListener.actionPerformed(e); } + }); + helpLabel.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent arg0) { + + if(arg0.getKeyCode() == KeyEvent.VK_ENTER) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER); + helpListener.actionPerformed(e); + } + } + }); + + helpLabel.addFocusListener(new FocusAdapter() { + + @Override + public void focusGained(FocusEvent e) { + + helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG_FOCUS))); + } + + @Override + public void focusLost(FocusEvent e) { + + helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG))); + } + + }); helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java new file mode 100644 index 00000000..06e37a89 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java @@ -0,0 +1,38 @@ +package at.gv.egiz.bku.gui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Thomas Zefferer + */ +public class SwitchFocusFocusListener extends FocusAdapter { + + protected static final Log log = LogFactory.getLog(SwitchFocusFocusListener.class); + + protected ActionListener swichFocusListener; + + public SwitchFocusFocusListener(ActionListener externalSwitchFocusListener) { + super(); + this.swichFocusListener = externalSwitchFocusListener; + } + + public ActionListener getActionListener() { + return swichFocusListener; + } + + @Override + public void focusGained(FocusEvent arg0) { + + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null); + swichFocusListener.actionPerformed(e); + } + + +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java new file mode 100644 index 00000000..1e3fabbd --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java @@ -0,0 +1,44 @@ +package at.gv.egiz.bku.gui; + +import java.applet.AppletContext; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Thomas Zefferer + */ +public class SwitchFocusListener implements ActionListener { + + protected final static Log log = LogFactory.getLog(SwitchFocusListener.class); + + protected AppletContext ctx; + protected String javascriptFunction; + + public SwitchFocusListener(AppletContext ctx, String javascriptFunction) { + + this.ctx = ctx; + this.javascriptFunction = javascriptFunction; + } + + @Override + public void actionPerformed(ActionEvent e) { + + try { + ctx.showDocument + (new URL("javascript:" + javascriptFunction)); + } + catch (MalformedURLException me) { + + log.warn("Unable to call external javascript function.", me); + } + + + } + +} diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 146d9353..a96b835f 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -40,6 +40,8 @@ enterpin={0} eingeben enterpin.pinpad={0} ({1} stellig) am Kartenleser eingeben hashdatalink=Signaturdaten anzeigen hashdatalink.tiny=Signaturdaten +hashdatalink.focus=[Signaturdaten anzeigen] +hashdatalink.tiny.focus=[Signaturdaten] #message.hashdata=Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i). #message.hashdata=Dies ist eine Voransicht des zu signierenden Inhaltes. F\u00FCr Details siehe Hilfe (i). #verwenden sie bitte die von ihrem System zur Verf\u00FCgung gestellte {0} Anwendung. diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties index 1a40aeea..c795b3fa 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -40,6 +40,8 @@ enterpin=Enter {0} enterpin.pinpad=Enter {0} ({1} digits) on card reader pinpad hashdatalink=Display signature data hashdatalink.tiny=signature data +hashdatalink.focus=[Display signature data] +hashdatalink.tiny.focus=[signature data] #message.hashdata=Remark: This is a preview of the data to-be signed. For standards compliant display see help. hashdatalist={0} signature data objects: retries.last=Last try! diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png new file mode 100644 index 00000000..d650bea2 Binary files /dev/null and b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png differ diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java index b3eaf8c7..9f1cb612 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java @@ -41,7 +41,7 @@ public class BKUGUITest { Container contentPane = testFrame.getContentPane(); // contentPane.setPreferredSize(new Dimension(170, 150)); contentPane.setPreferredSize(new Dimension(290, 190)); - BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.advanced, null, null); + BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.advanced, null, null, null); BKUGUIWorker worker = new BKUGUIWorker(); worker.init(gui); testFrame.pack(); -- cgit v1.2.3