From 036dd1a8054c5dc818d01e238eb9480d67da478d Mon Sep 17 00:00:00 2001 From: clemenso Date: Thu, 30 Oct 2008 17:43:40 +0000 Subject: Help Icon git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@130 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/java/at/gv/egiz/bku/gui/BKUGUI.java | 140 ++++++++++----- .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java | 14 +- .../java/at/gv/egiz/bku/gui/HelpMouseListener.java | 33 ++++ .../main/java/at/gv/egiz/bku/gui/SimpleGUI.java | 200 +++++++++++++++------ .../at/gv/egiz/bku/gui/Messages.properties | 10 +- BKUCommonGUI/src/main/resources/images/help.png | Bin 0 -> 746 bytes 6 files changed, 287 insertions(+), 110 deletions(-) create mode 100644 BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java create mode 100644 BKUCommonGUI/src/main/resources/images/help.png (limited to 'BKUCommonGUI/src/main') diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java index 7e0f0447..27841d1c 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUI.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import javax.swing.GroupLayout; +import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; @@ -66,6 +67,8 @@ public class BKUGUI implements BKUGUIFacade { private static final Log log = LogFactory.getLog(BKUGUI.class); + protected HelpMouseListener helpListener; + protected Container contentPane; protected ResourceBundle messages; /** left and right side main panels */ @@ -89,7 +92,7 @@ public class BKUGUI implements BKUGUIFacade { * @param localeString may be null */ @Override - public void init(final Container contentPane, String localeString, final URL background) { + public void init(final Container contentPane, String localeString, final URL background, ActionListener helpListener) { if (localeString != null) { messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, new Locale(localeString)); @@ -98,6 +101,7 @@ public class BKUGUI implements BKUGUIFacade { } this.contentPane = contentPane; + registerHelpListener(helpListener); try { @@ -175,6 +179,11 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2)); + JLabel helpLabel = new JLabel(); + helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); + helpLabel.addMouseListener(helpListener); + helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + JButton b = new JButton(); b.setText(messages.getString(BUTTON_CANCEL)); if (b.getPreferredSize().width > buttonSize) @@ -204,15 +213,17 @@ public class BKUGUI implements BKUGUIFacade { GroupLayout headerPanelLayout = new GroupLayout(headerPanel); headerPanel.setLayout(headerPanelLayout); -// + headerPanelLayout.setHorizontalGroup( headerPanelLayout.createSequentialGroup() - .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) - .addContainerGap()); + .addComponent(titleLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)); headerPanelLayout.setVerticalGroup( - headerPanelLayout.createSequentialGroup() - .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); - + headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) //SequentialGroup() + .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) + .addComponent(helpLabel)); + GroupLayout contentPanelLayout = new GroupLayout(contentPanel); contentPanel.setLayout(contentPanelLayout); @@ -234,7 +245,7 @@ public class BKUGUI implements BKUGUIFacade { .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) //, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); //); + .addContainerGap()); } @Override @@ -291,6 +302,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_WELCOME)); + helpListener.setHelpTopic(HELP_WELCOME); + JLabel welcomeMsgLabel = new JLabel(); welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); welcomeMsgLabel.setText(messages.getString(MESSAGE_WAIT)); @@ -300,10 +313,10 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel)); + .addComponent(welcomeMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel)); + .addComponent(welcomeMsgLabel)); contentPanel.validate(); @@ -328,6 +341,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_INSERTCARD)); + helpListener.setHelpTopic(HELP_INSERTCARD); + JLabel insertCardMsgLabel = new JLabel(); insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); insertCardMsgLabel.setText(messages.getString(MESSAGE_INSERTCARD)); @@ -385,6 +400,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); + JLabel insertCardMsgLabel = new JLabel(); insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); insertCardMsgLabel.setText(messages.getString(MESSAGE_INSERTCARD)); @@ -476,10 +493,12 @@ public class BKUGUI implements BKUGUIFacade { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); String infoPattern = messages.getString(MESSAGE_ENTERPIN); infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()})); + helpListener.setHelpTopic(HELP_CARDPIN); } else { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setText(MessageFormat.format(messages.getString(MESSAGE_RETRIES), new Object[]{String.valueOf(numRetries)})); infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); } JLabel pinsizeLabel = new JLabel(); @@ -496,7 +515,7 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(cardPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) @@ -506,13 +525,13 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(infoLabel) - .addGap(infoLabel.getFont().getSize()) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cardPinLabel) - .addComponent(pinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addComponent(infoLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(cardPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); @@ -628,10 +647,12 @@ public class BKUGUI implements BKUGUIFacade { hashdataListener.actionPerformed(e); } }); + helpListener.setHelpTopic(HELP_SIGNPIN); } else { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setText(MessageFormat.format(messages.getString(MESSAGE_RETRIES), new Object[]{String.valueOf(numRetries)})); infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); } GroupLayout mainPanelLayout = new GroupLayout(mainPanel); @@ -640,22 +661,22 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pinsizeLabel)))); + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pinsizeLabel)))); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() .addComponent(infoLabel) - .addGap(infoLabel.getFont().getSize()) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(signPinLabel) - .addComponent(pinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(signPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); @@ -695,6 +716,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_ERROR)); + helpListener.setHelpTopic(errorMsgKey); + String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -708,10 +731,10 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + .addComponent(errorMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + .addComponent(errorMsgLabel)); JButton okButton = new JButton(); okButton.setText(messages.getString(BUTTON_OK)); @@ -751,6 +774,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_ERROR)); + helpListener.setHelpTopic(errorMsgKey); + String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -764,10 +789,10 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + .addComponent(errorMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + .addComponent(errorMsgLabel)); contentPanel.validate(); } @@ -791,6 +816,8 @@ public class BKUGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_WAIT)); + helpListener.setHelpTopic(HELP_WAIT); + JLabel waitMsgLabel = new JLabel(); waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); if (waitMessage != null) { @@ -804,10 +831,10 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel)); + .addComponent(waitMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel)); + .addComponent(waitMsgLabel)); contentPanel.validate(); } @@ -883,6 +910,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_HASHDATA)); + helpListener.setHelpTopic(HELP_HASHDATA); + JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); refIdLabel.setText(messages.getString(MESSAGE_HASHDATA)); //MessageFormat.format(refIdLabelPattern, new Object[]{refId})); @@ -904,14 +933,14 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addComponent(refIdLabel) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); JButton backButton = new JButton(); backButton.setText(messages.getString(BUTTON_BACK)); @@ -958,6 +987,8 @@ public class BKUGUI implements BKUGUIFacade { titleLabel.setText(messages.getString(TITLE_HASHDATA)); + helpListener.setHelpTopic(HELP_HASHDATALIST); + JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); String refIdLabelPattern = messages.getString(MESSAGE_HASHDATALIST); @@ -982,15 +1013,15 @@ public class BKUGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addComponent(refIdLabel) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, 0, hashDataTable.getPreferredSize().height+3)); - + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, 0, hashDataTable.getPreferredSize().height+3)); + JButton backButton = new JButton(); backButton.setText(messages.getString(BUTTON_BACK)); backButton.setActionCommand(cancelCommand); @@ -1133,4 +1164,19 @@ public class BKUGUI implements BKUGUIFacade { } } } + + private void registerHelpListener(ActionListener helpListener) { + if (helpListener != null) { + this.helpListener = new HelpMouseListener(helpListener); + } else { + log.error("no help listener provided, will not be able to display help"); + this.helpListener = new HelpMouseListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")"); + } + }); + } + } } 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 ced74834..6c157e76 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 @@ -37,6 +37,7 @@ public interface BKUGUIFacade { public static final String MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/Messages"; public static final String DEFAULT_BACKGROUND = "/images/BackgroundChipperling.png"; + public static final String HELP_IMG = "/images/help.png"; public static final String HASHDATA_FONT = "Monospaced"; public static final Color ERROR_COLOR = Color.RED; public static final Color HYPERLINK_COLOR = Color.BLUE; @@ -63,6 +64,15 @@ public interface BKUGUIFacade { public static final String LABEL_PIN = "label.pin"; public static final String LABEL_PINSIZE = "label.pinsize"; // public static final String ERROR_NO_HASHDATA = "error.no.hashdata"; + public static final String HELP_WELCOME = "help.welcome"; + public static final String HELP_WAIT = "help.wait"; + public static final String HELP_CARDNOTSUPPORTED = "help.cardnotsupported"; + public static final String HELP_INSERTCARD = "help.insertcard"; + public static final String HELP_CARDPIN = "help.cardpin"; + public static final String HELP_SIGNPIN = "help.signpin"; + public static final String HELP_RETRY = "help.retry"; + public static final String HELP_HASHDATA = "help.hashdata"; + public static final String HELP_HASHDATALIST = "help.hashdatalist"; public static final String BUTTON_OK = "button.ok"; public static final String BUTTON_CANCEL = "button.cancel"; @@ -72,9 +82,9 @@ public interface BKUGUIFacade { public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix"; - public void init(Container contentPane, String localeString, URL background); + public void init(Container contentPane, String localeString, URL background, ActionListener helpListener); - public void showWelcomeDialog(); + public void showWelcomeDialog(); /** * MOA-ID only diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java new file mode 100644 index 00000000..6d814f01 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java @@ -0,0 +1,33 @@ +package at.gv.egiz.bku.gui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class HelpMouseListener extends MouseAdapter { + + protected static final Log log = LogFactory.getLog(HelpMouseListener.class); + + protected ActionListener externalHelpListener; + protected String locale; + protected String topic; + + public HelpMouseListener(ActionListener externalHelpListener) { + super(); + this.externalHelpListener = externalHelpListener; + } + + public void setHelpTopic(String topic) { + log.trace("setting help topic: " + topic); + this.topic = topic; + } + + @Override + public void mouseClicked(MouseEvent arg0) { + ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, topic); + externalHelpListener.actionPerformed(e); + } +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java index c37704e2..29913d2a 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SimpleGUI.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import javax.swing.GroupLayout; +import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; @@ -65,6 +66,8 @@ import org.apache.commons.logging.LogFactory; public class SimpleGUI implements BKUGUIFacade { private static final Log log = LogFactory.getLog(SimpleGUI.class); + + protected HelpMouseListener helpListener; protected Container contentPane; protected ResourceBundle messages; @@ -77,6 +80,7 @@ public class SimpleGUI implements BKUGUIFacade { protected JPanel buttonPanel; /** right side fixed labels */ // protected JLabel titleLabel; + protected JLabel helpLabel; /** remember the pinfield to return to worker */ protected JPasswordField pinField; @@ -89,7 +93,7 @@ public class SimpleGUI implements BKUGUIFacade { * @param localeString may be null */ @Override - public void init(final Container contentPane, String localeString, final URL background) { + public void init(final Container contentPane, String localeString, final URL background, ActionListener helpListener) { if (localeString != null) { messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, new Locale(localeString)); @@ -98,7 +102,8 @@ public class SimpleGUI implements BKUGUIFacade { } this.contentPane = contentPane; - + registerHelpListener(helpListener); + try { log.debug("scheduling gui initialization"); @@ -131,7 +136,7 @@ public class SimpleGUI implements BKUGUIFacade { throw new RuntimeException("Failed to init GUI: " + ex.getMessage()); } } - + // protected void initIconPanel() { // iconPanel = new JPanel(); // JLabel iconLabel = new JLabel(); @@ -151,7 +156,7 @@ public class SimpleGUI implements BKUGUIFacade { // .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)); //); // } - protected void initContentPanel(URL background) { + protected void initContentPanel(URL background) { if (background == null) { background = this.getClass().getResource(DEFAULT_BACKGROUND); @@ -175,6 +180,11 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | // java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2)); + helpLabel = new JLabel(); + helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG))); + helpLabel.addMouseListener(helpListener); + helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + JButton b = new JButton(); // b.setText(messages.getString(BUTTON_CANCEL)); // if (b.getPreferredSize().width > buttonSize) @@ -207,8 +217,7 @@ public class SimpleGUI implements BKUGUIFacade { // // headerPanelLayout.setHorizontalGroup( // headerPanelLayout.createSequentialGroup() -// .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE) -// .addContainerGap()); +// .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); // headerPanelLayout.setVerticalGroup( // headerPanelLayout.createSequentialGroup() // .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)); @@ -234,7 +243,7 @@ public class SimpleGUI implements BKUGUIFacade { .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) //, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addContainerGap()); //); + .addContainerGap()); } @Override @@ -291,6 +300,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_WELCOME)); + helpListener.setHelpTopic(HELP_WELCOME); + JLabel welcomeMsgLabel = new JLabel(); welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); welcomeMsgLabel.setText(messages.getString(TITLE_WELCOME)); @@ -299,12 +310,16 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel)); + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(welcomeMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(welcomeMsgLabel)); - + .addComponent(helpLabel) + .addComponent(welcomeMsgLabel)); + contentPanel.validate(); } @@ -328,6 +343,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_INSERTCARD)); + helpListener.setHelpTopic(HELP_INSERTCARD); + JLabel insertCardMsgLabel = new JLabel(); insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); insertCardMsgLabel.setText(messages.getString(MESSAGE_INSERTCARD)); @@ -336,10 +353,14 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) .addComponent(insertCardMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() + .addComponent(helpLabel) .addComponent(insertCardMsgLabel)); // JButton cancelButton = new JButton(); @@ -385,6 +406,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); + helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED); + JLabel insertCardMsgLabel = new JLabel(); insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); insertCardMsgLabel.setText(messages.getString(TITLE_CARD_NOT_SUPPORTED)); @@ -393,12 +416,16 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) .addComponent(insertCardMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() + .addComponent(helpLabel) .addComponent(insertCardMsgLabel)); - + // JButton cancelButton = new JButton(); // cancelButton.setText(messages.getString(BUTTON_CANCEL)); // cancelButton.addActionListener(cancelListener); @@ -477,10 +504,12 @@ public class SimpleGUI implements BKUGUIFacade { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); String infoPattern = messages.getString(MESSAGE_ENTERPIN); infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()})); + helpListener.setHelpTopic(HELP_CARDPIN); } else { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setText(MessageFormat.format(messages.getString(MESSAGE_RETRIES), new Object[]{String.valueOf(numRetries)})); infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); } JLabel pinsizeLabel = new JLabel(); @@ -497,7 +526,10 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(cardPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) @@ -507,13 +539,15 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(infoLabel) - .addGap(infoLabel.getFont().getSize()) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(cardPinLabel) - .addComponent(pinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(infoLabel) + .addComponent(helpLabel)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(cardPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); @@ -580,7 +614,7 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.removeAll(); buttonPanel.removeAll(); - + // if (numRetries < 0) { // titleLabel.setText(messages.getString(TITLE_SIGN)); // } else { @@ -626,7 +660,7 @@ public class SimpleGUI implements BKUGUIFacade { pinSize += "-" + pinSpec.getMaxLength(); } pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); - + JLabel infoLabel = new JLabel(); if (numRetries < 0) { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -641,10 +675,12 @@ public class SimpleGUI implements BKUGUIFacade { hashdataListener.actionPerformed(e); } }); + helpListener.setHelpTopic(HELP_SIGNPIN); } else { infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD)); infoLabel.setText(MessageFormat.format(messages.getString(MESSAGE_RETRIES), new Object[]{String.valueOf(numRetries)})); infoLabel.setForeground(ERROR_COLOR); + helpListener.setHelpTopic(HELP_RETRY); } GroupLayout mainPanelLayout = new GroupLayout(mainPanel); @@ -652,23 +688,28 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(infoLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addGroup(mainPanelLayout.createSequentialGroup() - .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) - .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pinsizeLabel)))); + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING) + .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pinsizeLabel)))); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) .addComponent(infoLabel) - .addGap(infoLabel.getFont().getSize()) - .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) - .addComponent(signPinLabel) - .addComponent(pinField)) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pinsizeLabel)); + .addComponent(helpLabel)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(signPinLabel) + .addComponent(pinField)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(pinsizeLabel)); GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); buttonPanel.setLayout(buttonPanelLayout); @@ -719,6 +760,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_ERROR)); + helpListener.setHelpTopic(errorMsgKey); + String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -731,12 +774,16 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(errorMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); - + .addComponent(helpLabel) + .addComponent(errorMsgLabel)); + JButton okButton = new JButton(); okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); okButton.setText(messages.getString(BUTTON_OK)); @@ -776,6 +823,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_ERROR)); + helpListener.setHelpTopic(errorMsgKey); + String errorMsgPattern = messages.getString(errorMsgKey); String errorMsg = MessageFormat.format(errorMsgPattern, errorMsgParams); @@ -788,11 +837,15 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(errorMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(errorMsgLabel)); + .addComponent(helpLabel) + .addComponent(errorMsgLabel)); contentPanel.validate(); } @@ -816,6 +869,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_WAIT)); + helpListener.setHelpTopic(HELP_WAIT); + JLabel waitMsgLabel = new JLabel(); waitMsgLabel.setFont(waitMsgLabel.getFont().deriveFont(waitMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); if (waitMessage != null) { @@ -828,11 +883,15 @@ public class SimpleGUI implements BKUGUIFacade { mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( - mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel)); + mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(mainPanelLayout.createSequentialGroup() + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(waitMsgLabel)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(waitMsgLabel)); + .addComponent(helpLabel) + .addComponent(waitMsgLabel)); contentPanel.validate(); } @@ -907,6 +966,8 @@ public class SimpleGUI implements BKUGUIFacade { buttonPanel.removeAll(); // titleLabel.setText(messages.getString(TITLE_HASHDATA)); + + helpListener.setHelpTopic(HELP_HASHDATA); JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -929,14 +990,19 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(refIdLabel) + .addComponent(helpLabel)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); JButton backButton = new JButton(); backButton.setFont(backButton.getFont().deriveFont(backButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -995,6 +1061,8 @@ public class SimpleGUI implements BKUGUIFacade { // titleLabel.setText(messages.getString(TITLE_HASHDATA)); + helpListener.setHelpTopic(HELP_HASHDATALIST); + JLabel refIdLabel = new JLabel(); refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); String refIdLabelPattern = messages.getString(MESSAGE_HASHDATALIST); @@ -1019,14 +1087,19 @@ public class SimpleGUI implements BKUGUIFacade { mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) - .addComponent(refIdLabel) - .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); + .addGroup(mainPanelLayout.createSequentialGroup() + .addComponent(refIdLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) + .addComponent(helpLabel)) + .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE)); mainPanelLayout.setVerticalGroup( mainPanelLayout.createSequentialGroup() - .addComponent(refIdLabel) - .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) - .addComponent(hashDataScrollPane, 0, 0, hashDataTable.getPreferredSize().height+3)); + .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(refIdLabel) + .addComponent(helpLabel)) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addComponent(hashDataScrollPane, 0, 0, hashDataTable.getPreferredSize().height+3)); JButton backButton = new JButton(); backButton.setFont(backButton.getFont().deriveFont(backButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -1183,4 +1256,19 @@ public class SimpleGUI implements BKUGUIFacade { } } } + + private void registerHelpListener(ActionListener helpListener) { + if (helpListener != null) { + this.helpListener = new HelpMouseListener(helpListener); + } else { + log.error("no help listener provided, will not be able to display help"); + this.helpListener = new HelpMouseListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")"); + } + }); + } + } } 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 a38e2cf8..5a427360 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 @@ -26,12 +26,12 @@ windowtitle.save=Signaturdaten speichern windowtitle.savedir=Signaturdaten in Verzeichnis speichern windowtitle.overwrite=Datei \u00FCberschreiben? message.wait=Bitte warten... -message.insertcard=Bitte B\u00FCrgerkarte in den Kartenleser stecken -message.enterpin=Bitte {0} eingeben -message.hashdatalink=Signaturdaten anzeigen... -message.hashdata=Ein Signaturdatenobjekt: +message.insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken +message.enterpin={0} eingeben +message.hashdatalink=Signaturdaten anzeigen +message.hashdata=Signaturdaten: #message.hashdata=Referenz Id: {0} -message.hashdatalist={0} Signaturdatenobjekte: +message.hashdatalist={0} Signaturdaten: message.retries=Noch {0} Versuch(e) message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? label.pin={0}: diff --git a/BKUCommonGUI/src/main/resources/images/help.png b/BKUCommonGUI/src/main/resources/images/help.png new file mode 100644 index 00000000..4ed65a97 Binary files /dev/null and b/BKUCommonGUI/src/main/resources/images/help.png differ -- cgit v1.2.3