From 3da4655d011dfc2f04f9e4ac28b38aee42d01bc0 Mon Sep 17 00:00:00 2001
From: clemenso <clemenso@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>
Date: Tue, 5 Jan 2010 10:06:47 +0000
Subject: Features [#437] Handle pinpad [64:03] response apdu correctly [#445]
 pin entry feedback for VERIFY_PIN_START/FINISH [#471] Provide SecureViewer
 Link before Pinpad PinEntry timeout starts

Bugs
[#479] PIN Managment Applet allows unmatching new pin and pin confirmation
[#480] PIN Management displays blocked PINs as ACTIVE
[#486] Not possible to select 3 times in series the same item from signedReferencesList for display in secureViewer
[#506] change pin dialog (gui) issues
[#508] e-card G3 PIN activation (with TransportPIN) not supported
[#509] closing secure viewer window (WINDOW_CLOSING) leaves "signature data is displayed in viewer" dialog in applet


git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@565 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
---
 .../main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java |  28 +-
 .../main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java   | 765 +++++++++------------
 .../main/java/at/gv/egiz/bku/gui/PinDocument.java  | 125 +---
 .../at/gv/egiz/bku/gui/SecureViewerDialog.java     | 118 ++--
 .../at/gv/egiz/bku/gui/Messages.properties         |   9 +-
 .../at/gv/egiz/bku/gui/Messages_en.properties      |   9 +-
 .../test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java |  13 +-
 7 files changed, 454 insertions(+), 613 deletions(-)

(limited to 'BKUCommonGUI')

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 91c91dcb..1e23c64c 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
@@ -16,7 +16,7 @@
  */
 package at.gv.egiz.bku.gui;
 
-import at.gv.egiz.stal.HashDataInput;
+  import at.gv.egiz.stal.HashDataInput;
 import at.gv.egiz.smcc.PINSpec;
 import java.awt.Color;
 import java.awt.event.ActionListener;
@@ -53,14 +53,15 @@ public interface BKUGUIFacade {
   public static final String TITLE_WELCOME = "title.welcome";
   public static final String TITLE_INSERTCARD = "title.insertcard";
   public static final String TITLE_CARD_NOT_SUPPORTED = "title.cardnotsupported";
-  public static final String TITLE_CARDPIN = "title.cardpin";
+  public static final String TITLE_VERIFY_PIN = "title.verify.pin";
   public static final String TITLE_SIGN = "title.sign";
+  public static final String TITLE_VERIFY_PINPAD = "title.verify.pinpad";
   public static final String TITLE_ERROR = "title.error";
   public static final String TITLE_WARNING = "title.warning";
   public static final String TITLE_ENTRY_TIMEOUT = "title.entry.timeout";
   public static final String TITLE_RETRY = "title.retry";
   public static final String TITLE_WAIT = "title.wait";
-  public static final String TITLE_HASHDATA = "title.hashdata";
+  public static final String TITLE_SIGNATURE_DATA = "title.signature.data";
   public static final String WINDOWTITLE_SAVE = "windowtitle.save";
   public static final String WINDOWTITLE_ERROR = "windowtitle.error";
   public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir";
@@ -75,6 +76,7 @@ public interface BKUGUIFacade {
   public static final String MESSAGE_CARD_NOT_SUPPORTED = "cardnotsupported";
   public static final String MESSAGE_ENTERPIN = "enterpin";
   public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad";
+  public static final String MESSAGE_ENTERPIN_PINPAD_DIRECT = "enterpin.pinpad.direct";
   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";
@@ -96,8 +98,9 @@ public interface BKUGUIFacade {
   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_VERIFY_PIN = "help.cardpin";
   public static final String HELP_SIGNPIN = "help.signpin";
+  public static final String HELP_PINPAD = "help.pinpad";
   public static final String HELP_RETRY = "help.retry";
   public static final String HELP_HASHDATA = "help.hashdata";
   public static final String HELP_HASHDATALIST = "help.hashdatalist";
@@ -111,6 +114,18 @@ public interface BKUGUIFacade {
   public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix";
   public static final String ALT_HELP = "alt.help";
 
+  public void showEnterPINDirect(PINSpec spec, int retries);
+
+  public void showEnterPIN(PINSpec spec, int retries);
+
+  public void showSignatureDataDialog(PINSpec spec, ActionListener listener, String string, ActionListener aThis0, String string0, ActionListener aThis1, String string1);
+
+  public void correctionButtonPressed();
+
+  public void allKeysCleared();
+
+  public void validKeyPressed();
+
   public enum Style { tiny, simple, advanced };
     
   /**
@@ -119,7 +134,7 @@ public interface BKUGUIFacade {
    */
   public Locale getLocale();
 
-  public void showCardPINDialog(PINSpec pinSpec, int numRetries,
+  public void showVerifyPINDialog(PINSpec pinSpec, int numRetries,
           ActionListener okListener, String okCommand,
           ActionListener cancelListener, String cancelCommand);
 
@@ -128,9 +143,6 @@ public interface BKUGUIFacade {
           ActionListener cancelListener, String cancelCommand,
           ActionListener viewerListener, String viewerCommand);
 
-  public void showPinpadSignaturePINDialog(PINSpec pinSpec, int numRetries, 
-          ActionListener viewerListener, String viewerCommand);
-
   public char[] getPin();
 
   /**
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 baffb3fd..3fc631c3 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
@@ -93,6 +93,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
     protected JLabel switchFocusDummyLabel; 
     /** remember the pinfield to return to worker */
     protected JPasswordField pinField;
+    protected JPasswordField pinpadPINField;
 
     protected int buttonSize;
     
@@ -360,221 +361,27 @@ public class BKUGUIImpl implements BKUGUIFacade {
       return messages.containsKey(key);
     }
 
-//    @Override
-//    public void showWelcomeDialog() {
-//
-//      log.debug("scheduling welcome dialog");
-//
-//        SwingUtilities.invokeLater(new Runnable() {
-//
-//            @Override
-//            public void run() {
-//
-//              log.debug("show welcome dialog");
-//
-//                mainPanel.removeAll();
-//                buttonPanel.removeAll();
-//
-//                helpListener.setHelpTopic(HELP_WELCOME);
-//
-//                JLabel welcomeMsgLabel = new JLabel();
-//                welcomeMsgLabel.setFont(welcomeMsgLabel.getFont().deriveFont(welcomeMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
-//
-//                if (renderHeaderPanel) {
-//                  titleLabel.setText(getMessage(TITLE_WELCOME));
-//                  welcomeMsgLabel.setText(getMessage(MESSAGE_WAIT));
-//                } else {
-//                  welcomeMsgLabel.setText(getMessage(TITLE_WELCOME));
-//                }
-//
-//                GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
-//                mainPanel.setLayout(mainPanelLayout);
-//
-//                GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup()
-//                        .addComponent(welcomeMsgLabel);
-//                GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
-//                        .addComponent(welcomeMsgLabel);
-//                if (!renderHeaderPanel) {
-//                  messageHorizontal
-//                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
-//                          .addComponent(helpLabel);
-//                  messageVertical
-//                          .addComponent(helpLabel);
-//                }
-//
-//                mainPanelLayout.setHorizontalGroup(messageHorizontal);
-//                mainPanelLayout.setVerticalGroup(messageVertical);
-//
-//                contentPanel.validate();
-//
-//            }
-//        });
-//    }
-
-//    @Override
-//    public void showInsertCardDialog(
-//            final ActionListener cancelListener, final String cancelCommand) {
-//
-//      log.debug("scheduling insert card dialog");
-//
-//      SwingUtilities.invokeLater(new Runnable() {
-//
-//            @Override
-//            public void run() {
-//
-//              log.debug("show insert card dialog");
-//
-//                mainPanel.removeAll();
-//                buttonPanel.removeAll();
-//
-//                if (renderHeaderPanel) {
-//                  titleLabel.setText(getMessage(TITLE_INSERTCARD));
-//                }
-//
-//                helpListener.setHelpTopic(HELP_INSERTCARD);
-//
-//                JLabel insertCardMsgLabel = new JLabel();
-//                insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
-//                insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD));
-//
-//                GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
-//                mainPanel.setLayout(mainPanelLayout);
-//
-//                GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup()
-//                        .addComponent(insertCardMsgLabel);
-//                GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup()
-//                        .addComponent(insertCardMsgLabel);
-//
-//                if (!renderHeaderPanel) {
-//                  messageHorizontal
-//                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
-//                          .addComponent(helpLabel);
-//                  messageVertical
-//                          .addComponent(helpLabel);
-//                }
-//
-//                mainPanelLayout.setHorizontalGroup(messageHorizontal);
-//                mainPanelLayout.setVerticalGroup(messageVertical);
-//
-//                if (renderCancelButton) {
-//                  JButton cancelButton = new JButton();
-//                  cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
-//                  cancelButton.setText(getMessage(BUTTON_CANCEL));
-//                  cancelButton.addActionListener(cancelListener);
-//                  cancelButton.setActionCommand(cancelCommand);
-//
-//                  GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
-//                  buttonPanel.setLayout(buttonPanelLayout);
-//
-//                  buttonPanelLayout.setHorizontalGroup(
-//                    buttonPanelLayout.createSequentialGroup()
-//                          .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-//                          .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE));
-//                  buttonPanelLayout.setVerticalGroup(
-//                    buttonPanelLayout.createSequentialGroup()
-//                      .addComponent(cancelButton));
-//                }
-//
-//                contentPanel.validate();
-//            }
-//        });
-//    }
-
-    /**
-     * only difference to showInsertCard: title text: card not supported
-     * @param cancelListener
-     * @param cancelCommand
-     */
-//    @Override
-//    public void showCardNotSupportedDialog(final ActionListener cancelListener, final String cancelCommand) {
-//
-//      log.debug("scheduling card not supported dialog");
-//
-//      SwingUtilities.invokeLater(new Runnable() {
-//
-//            @Override
-//            public void run() {
-//
-//              log.debug("show card not supported dialog");
-//
-//              mainPanel.removeAll();
-//              buttonPanel.removeAll();
-//
-//              JLabel insertCardMsgLabel = new JLabel();
-//              insertCardMsgLabel.setFont(insertCardMsgLabel.getFont().deriveFont(insertCardMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
-//
-//              if (renderHeaderPanel) {
-//                titleLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED));
-//                insertCardMsgLabel.setText(getMessage(MESSAGE_INSERTCARD));
-//              } else {
-//                insertCardMsgLabel.setText(getMessage(TITLE_CARD_NOT_SUPPORTED));
-//              }
-//
-//              helpListener.setHelpTopic(HELP_CARDNOTSUPPORTED);
-//
-//              GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
-//              mainPanel.setLayout(mainPanelLayout);
-//
-//              GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup()
-//                      .addComponent(insertCardMsgLabel);
-//              GroupLayout.Group messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
-//                      .addComponent(insertCardMsgLabel);
-//              if (!renderHeaderPanel) {
-//                messageHorizontal
-//                        .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
-//                        .addComponent(helpLabel);
-//                messageVertical
-//                        .addComponent(helpLabel);
-//              }
-//
-//              mainPanelLayout.setHorizontalGroup(messageHorizontal);
-//              mainPanelLayout.setVerticalGroup(messageVertical);
-//
-//              if (renderCancelButton) {
-//                JButton cancelButton = new JButton();
-//                cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
-//                cancelButton.setText(getMessage(BUTTON_CANCEL));
-//                cancelButton.addActionListener(cancelListener);
-//                cancelButton.setActionCommand(cancelCommand);
-//
-//                GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
-//                buttonPanel.setLayout(buttonPanelLayout);
-//
-//                buttonPanelLayout.setHorizontalGroup(
-//                  buttonPanelLayout.createSequentialGroup()
-//                        .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-//                        .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE));
-//                buttonPanelLayout.setVerticalGroup(
-//                  buttonPanelLayout.createSequentialGroup()
-//                    .addComponent(cancelButton));
-//              }
-//
-//              contentPanel.validate();
-//            }
-//        });
-//    }
-
   @Override
-  public void showCardPINDialog(final PINSpec pinSpec, final int numRetries,
+  public void showVerifyPINDialog(final PINSpec pinSpec, final int numRetries,
           final ActionListener okListener, final String okCommand,
           final ActionListener cancelListener, final String cancelCommand) {
         
-      log.debug("scheduling card-pin dialog");
+      log.debug("scheduling verify pin dialog");
       
       SwingUtilities.invokeLater(new Runnable() {
 
             @Override
             public void run() {
 
-              log.debug("[" + Thread.currentThread().getName() + "] show card-pin dialog");
+              log.debug("[" + Thread.currentThread().getName() + "] show verify pin dialog");
       
                 mainPanel.removeAll();
                 buttonPanel.removeAll();
 
                 if (renderHeaderPanel) {
                   if (numRetries < 0) {
-                      String cardpinTitle = getMessage(TITLE_CARDPIN);
-                      titleLabel.setText(MessageFormat.format(cardpinTitle, new Object[]{pinSpec.getLocalizedName()}));
+                      String verifyTitle = getMessage(TITLE_VERIFY_PIN);
+                      titleLabel.setText(MessageFormat.format(verifyTitle, new Object[]{pinSpec.getLocalizedName()}));
                   } else {
                       titleLabel.setText(getMessage(TITLE_RETRY));
                   }
@@ -615,8 +422,8 @@ public class BKUGUIImpl implements BKUGUIFacade {
                   } else {
                     infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()}));
                   }
-                  helpMouseListener.setHelpTopic(HELP_CARDPIN);
-                  helpKeyListener.setHelpTopic(HELP_CARDPIN);
+                  helpMouseListener.setHelpTopic(HELP_VERIFY_PIN);
+                  helpKeyListener.setHelpTopic(HELP_VERIFY_PIN);
                 } else {
                   String retryPattern;
                   if (numRetries < 2) {
@@ -732,194 +539,346 @@ public class BKUGUIImpl implements BKUGUIFacade {
         });
     }
 
-//    @Override
-//    public void showCardPINDialog(PINSpec pinSpec, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) {
-//        showCardPINDialog(pinSpec, -1, okListener, okCommand, cancelListener, cancelCommand);
-//    }
-//
-//    @Override
-//    public void showCardPINRetryDialog(PINSpec pinSpec, int numRetries, ActionListener okListener, String okCommand, ActionListener cancelListener, String cancelCommand) {
-//        showCardPINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand);
-//    }
+  @Override
+  public void showEnterPINDirect(PINSpec pinSpec, int retries) {
+    if (retries < 0) {
+      showMessageDialog(TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD_DIRECT, new Object[] {
+                  pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() });
+    } else {
+      showMessageDialog(TITLE_RETRY, MESSAGE_RETRIES, new Object[]{String.valueOf(retries) });
+    }
+  }
 
-//    @Override
-//    public void showSignaturePINDialog(PINSpec pinSpec, ActionListener signListener, String signCommand, ActionListener cancelListener, String cancelCommand, ActionListener hashdataListener, String hashdataCommand) {
-//        showSignaturePINDialog(pinSpec, -1, signListener, signCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand);
-//    }
+  @Override
+  public void showEnterPIN(final PINSpec pinSpec, final int retries) {
+    showEnterPIN(pinSpec, retries, TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD, null);
+  }
 
-    @Override
-    public void showPinpadSignaturePINDialog(final PINSpec pinSpec, final int numRetries,
-//            final ActionListener cancelListener, final String cancelCommand,
-            final ActionListener hashdataListener, final String hashdataCommand) {
+  protected void showEnterPIN(final PINSpec pinSpec, final int retries, final String titleKey, final String messageKey, final Object[] messageParams) {
+    log.debug("scheduling pinpad dialog");
 
-        log.debug("scheduling pinpad signature-pin dialog");
+    SwingUtilities.invokeLater(new Runnable() {
 
-        SwingUtilities.invokeLater(new Runnable() {
+      @Override
+      public void run() {
 
-            @Override
-            public void run() {
+        log.debug("[" + Thread.currentThread().getName() + "] show pinpad dialog");
 
-              log.debug("[" + Thread.currentThread().getName() + "] show pinpad signature-pin dialog");
+        mainPanel.removeAll();
+        buttonPanel.removeAll();
 
-                mainPanel.removeAll();
-                buttonPanel.removeAll();
+        if (renderHeaderPanel) {
+          if (retries < 0) {
+              titleLabel.setText(getMessage(titleKey));
+          } else {
+              titleLabel.setText(getMessage(TITLE_RETRY));
+          }
+        }
 
-                if (renderHeaderPanel) {
-                  if (numRetries < 0) {
-                      titleLabel.setText(getMessage(TITLE_SIGN));
-                  } else {
-                      titleLabel.setText(getMessage(TITLE_RETRY));
-                  }
-                }
+        final JLabel infoLabel = new JLabel();
+        if (retries < 0) {
+          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+          infoLabel.setText(MessageFormat.format(getMessage(messageKey), messageParams));
+          helpMouseListener.setHelpTopic(HELP_PINPAD);
+          helpKeyListener.setHelpTopic(HELP_PINPAD);
+        } else {
+          String retryPattern;
+          if (retries == 1) {
+            retryPattern = getMessage(MESSAGE_LAST_RETRY);
+          } else {
+            retryPattern = getMessage(MESSAGE_RETRIES);
+          }
+          infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(retries)}));
+          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD));
+          infoLabel.setForeground(ERROR_COLOR);
+          helpMouseListener.setHelpTopic(HELP_RETRY);
+          helpKeyListener.setHelpTopic(HELP_RETRY);
+        }
+
+        JLabel pinLabel = new JLabel();
+        pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+        String pinName = getMessage(LABEL_PIN);
+        pinLabel.setText(MessageFormat.format(pinName, new Object[]{pinSpec.getLocalizedName()}));
+
+        pinpadPINField = new JPasswordField();
+        pinpadPINField.setText("");
+        pinpadPINField.setEnabled(false);
+
+        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()));
+
+        GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+        mainPanel.setLayout(mainPanelLayout);
+
+        GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+                .addComponent(infoLabel);
+        GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                .addComponent(infoLabel);
+
+        if (!renderHeaderPanel) {
+          infoHorizontal
+                  .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+                  .addComponent(switchFocusDummyLabel)
+                  .addComponent(helpLabel)
+                  ;
+          infoVertical
+                  .addComponent(switchFocusDummyLabel)
+                  .addComponent(helpLabel)
+                  ;
+        }
+
+        // align pinfield and pinsize to the right
+        GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING);
+        GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup();
+
+        if (pinLabelPos == PinLabelPosition.ABOVE) {
+          pinHorizontal
+                  .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                    .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+                    .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                  .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+          pinVertical
+                  .addComponent(pinLabel)
+                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                  .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                  .addComponent(pinsizeLabel);
+        } else { // PinLabelPosition.LEFT
+          pinHorizontal
+                  .addGroup(mainPanelLayout.createSequentialGroup()
+                    .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                    .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                  .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+          pinVertical
+                  .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+                    .addComponent(pinLabel)
+                    .addComponent(pinpadPINField))
+                  .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+                  .addComponent(pinsizeLabel);
+        }
+
+        mainPanelLayout.setHorizontalGroup(
+          mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+            .addGroup(infoHorizontal)
+            .addGroup(pinHorizontal));
+
+        mainPanelLayout.setVerticalGroup(
+          mainPanelLayout.createSequentialGroup()
+            .addGroup(infoVertical)
+            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+            .addGroup(pinVertical));
+
+        contentPanel.validate();
+      }
+    });
+  }
+
+  @Override
+  public void showSignatureDataDialog(PINSpec spec,
+          final ActionListener enterPINListener, final String enterPINCommand,
+          final ActionListener cancelListener, final String cancelCommand,
+          final ActionListener hashdataListener, final String hashdataCommand) {
+
+    log.debug("scheduling signature-data dialog");
+
+    SwingUtilities.invokeLater(new Runnable() {
+
+        @Override
+        public void run() {
+
+          log.debug("[" + Thread.currentThread().getName() + "] show signature-data dialog");
+
+          mainPanel.removeAll();
+          buttonPanel.removeAll();
+
+          if (renderHeaderPanel) {
+            titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA));
+          }
+
+          final JLabel infoLabel = new JLabel();
+          infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+          if (shortText) {
+            infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+          } else {
+            infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+          }
+          infoLabel.setFocusable(true);
+          infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+          infoLabel.setForeground(HYPERLINK_COLOR);
+          infoLabel.addMouseListener(new MouseAdapter() {
+
+              @Override
+              public void mouseClicked(MouseEvent me) {
+                  ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
+                  hashdataListener.actionPerformed(e);
+              }
+          });
+
+          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) {
 
-                final JLabel infoLabel = new JLabel();
-                if (numRetries < 0) {
-                  infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
                   if (shortText) {
-                    infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
-                  } else {
-                    infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
-                  }
-                  infoLabel.setFocusable(true);
-                  infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-                  infoLabel.setForeground(HYPERLINK_COLOR);
-                  infoLabel.addMouseListener(new MouseAdapter() {
+                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS));
+                    } else {
+                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS));
+                    }
+              }
 
-                      @Override
-                      public void mouseClicked(MouseEvent me) {
-                          ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
-                          hashdataListener.actionPerformed(e);
-                      }
-                  });
-                  
-                  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) {
-                    retryPattern = getMessage(MESSAGE_LAST_RETRY);
-                  } 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);
-                  helpMouseListener.setHelpTopic(HELP_RETRY);
-                  helpKeyListener.setHelpTopic(HELP_RETRY);
-                }
+              @Override
+              public void focusLost(FocusEvent e) {
 
-                String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD);
-                String msg = MessageFormat.format(msgPattern, new Object[] {
-                  pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() });
+                  if (shortText) {
+                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+                    } else {
+                      infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+                    }
 
-                JLabel msgLabel = new JLabel();
-                msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD));
-                msgLabel.setText(msg);
+              }
 
-                GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
-                mainPanel.setLayout(mainPanelLayout);
+          });
 
-                GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
-                        .addComponent(infoLabel);
-                GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
-                        .addComponent(infoLabel);
+          helpMouseListener.setHelpTopic(HELP_SIGNPIN);
+          helpKeyListener.setHelpTopic(HELP_SIGNPIN);
 
-                if (!renderHeaderPanel) {
-                  infoHorizontal
-                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
-                          .addComponent(switchFocusDummyLabel)
-                          .addComponent(helpLabel)
-                          ;
-                  infoVertical
-                          .addComponent(switchFocusDummyLabel)
-                          .addComponent(helpLabel)
-                          ;
-                }
+          //TODO message panel
 
-                mainPanelLayout.setHorizontalGroup(
-                  mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
-                    .addGroup(infoHorizontal)
-                    .addComponent(msgLabel));
+//              String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD);
+//              String msg = MessageFormat.format(msgPattern, new Object[] {
+//                pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() });
+//
+//              JLabel msgLabel = new JLabel();
+//              msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD));
+//              msgLabel.setText(msg);
 
-                mainPanelLayout.setVerticalGroup(
-                  mainPanelLayout.createSequentialGroup()
-                    .addGroup(infoVertical)
+          GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+          mainPanel.setLayout(mainPanelLayout);
+
+          GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+                  .addComponent(infoLabel);
+          GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+                  .addComponent(infoLabel);
+
+          if (!renderHeaderPanel) {
+            infoHorizontal
+                    .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+                    .addComponent(switchFocusDummyLabel)
+                    .addComponent(helpLabel)
+                    ;
+            infoVertical
+                    .addComponent(switchFocusDummyLabel)
+                    .addComponent(helpLabel)
+                    ;
+          }
+
+          mainPanelLayout.setHorizontalGroup(
+                  infoHorizontal);
+//              mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+//                .addGroup(infoHorizontal)
+//                .addComponent(msgLabel));
+
+          mainPanelLayout.setVerticalGroup(
+                  infoVertical);
+//              mainPanelLayout.createSequentialGroup()
+//                .addGroup(infoVertical)
+//                .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+//                .addComponent(msgLabel));
+
+
+          GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+          buttonPanel.setLayout(buttonPanelLayout);
+
+          GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup();
+          GroupLayout.Group buttonVertical;
+
+          JButton enterPINButton = new JButton();
+          enterPINButton.setFont(enterPINButton.getFont().deriveFont(enterPINButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+          enterPINButton.setText(getMessage(BUTTON_SIGN));
+          enterPINButton.setActionCommand(enterPINCommand);
+          enterPINButton.addActionListener(enterPINListener);
+
+          if (renderCancelButton) {
+            JButton cancelButton = new JButton();
+            cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+            cancelButton.setText(getMessage(BUTTON_CANCEL));
+            cancelButton.setActionCommand(cancelCommand);
+            cancelButton.addActionListener(cancelListener);
+
+            buttonHorizontal
+                    .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
                     .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
-                    .addComponent(msgLabel));
-
-                //no cancel button (cancel via pinpad)
-//                if (renderCancelButton) {
-//                    JButton cancelButton = new JButton();
-//                    cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
-//                    cancelButton.setText(getMessage(BUTTON_CANCEL));
-//                    cancelButton.setActionCommand(cancelCommand);
-//                    cancelButton.addActionListener(cancelListener);
-//
-//                    GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
-//                    buttonPanel.setLayout(buttonPanelLayout);
-//
-//                    GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup()
-//                            .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE);
-//                    GroupLayout.SequentialGroup buttonVertical = buttonPanelLayout.createSequentialGroup()
-//                            .addComponent(cancelButton);
-//
-//                    buttonPanelLayout.setHorizontalGroup(buttonHorizontal);
-//                    buttonPanelLayout.setVerticalGroup(buttonVertical);
-//                }
+                    .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+                    ;
+            buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+                    .addComponent(enterPINButton)
+                    .addComponent(cancelButton)
+                    ;
+          } else {
+            buttonHorizontal
+                    .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+                    ;
+            buttonVertical = buttonPanelLayout.createSequentialGroup()
+                    .addComponent(enterPINButton)
+                    ;
+          }
 
-                contentPanel.validate();
-            }
-        });
+          buttonPanelLayout.setHorizontalGroup(buttonHorizontal);
+          buttonPanelLayout.setVerticalGroup(buttonVertical);
+
+          contentPanel.validate();
+        }
+    });
+  }
+
+  @Override
+  public void correctionButtonPressed() {
+    log.debug("[" + Thread.currentThread().getName() + "] correction button pressed");
+
+    if (pinpadPINField != null) {
+      String maskedPIN = pinpadPINField.getText();
+      pinpadPINField.setText(maskedPIN.substring(0, maskedPIN.length() - 1));
+    }
+  }
+
+  @Override
+  public void allKeysCleared() {
+    log.debug("[" + Thread.currentThread().getName() + "] all keys cleared");
+
+    if (pinpadPINField != null) {
+      pinpadPINField.setText("");
+    }
+  }
+
+  @Override
+  public void validKeyPressed() {
+    log.debug("[" + Thread.currentThread().getName() + "] valid key pressed");
+
+    if (pinpadPINField != null) {
+      pinpadPINField.setText(pinpadPINField.getText() + '*');
     }
+  }
 
     @Override
     public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries,
             final ActionListener signListener, final String signCommand,
             final ActionListener cancelListener, final String cancelCommand,
             final ActionListener hashdataListener, final String hashdataCommand) {
-//        showSignaturePINDialog(pinSpec, numRetries, okListener, okCommand, cancelListener, cancelCommand, hashdataListener, hashdataCommand);
-//    }
-//
-//    private void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries, final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) {
 
       log.debug("scheduling signature-pin dialog");
       
@@ -1302,57 +1261,6 @@ public class BKUGUIImpl implements BKUGUIFacade {
         });
     }
 
-//    @Override
-//    public void showWaitDialog(final String waitMessage) {
-//
-//      log.debug("scheduling wait dialog");
-//
-//      SwingUtilities.invokeLater(new Runnable() {
-//
-//            @Override
-//            public void run() {
-//
-//              log.debug("show wait dialog");
-//
-//                mainPanel.removeAll();
-//                buttonPanel.removeAll();
-//
-//                if (renderHeaderPanel) {
-//                  titleLabel.setText(getMessage(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) {
-//                    waitMsgLabel.setText("<html>" + waitMessage + "</html>");
-//                } else {
-//                    waitMsgLabel.setText(getMessage(MESSAGE_WAIT));
-//                }
-//
-//                GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
-//                mainPanel.setLayout(mainPanelLayout);
-//
-//                GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup()
-//                        .addComponent(waitMsgLabel);
-//                GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
-//                        .addComponent(waitMsgLabel);
-//
-//                if (!renderHeaderPanel) {
-//                  messageHorizontal
-//                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
-//                          .addComponent(helpLabel);
-//                  messageVertical
-//                          .addComponent(helpLabel);
-//                }
-//                mainPanelLayout.setHorizontalGroup(messageHorizontal);
-//                mainPanelLayout.setVerticalGroup(messageVertical);
-//
-//                contentPanel.validate();
-//            }
-//        });
-//    }
 
     @Override
     public char[] getPin() {
@@ -1395,7 +1303,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
               @Override
               public void run() {
                 try {
-                  showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER);
+                  showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);
                   showSecureViewer(dataToBeSigned.get(0), backListener, backCommand);
                 } catch (FontProviderException ex) {
                   log.error("failed to display secure viewer", ex);
@@ -1411,7 +1319,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
           }
         } else {
           log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog");
-          showMessageDialog(TITLE_HASHDATA, MESSAGE_UNSUPPORTED_MIMETYPE);
+          showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_UNSUPPORTED_MIMETYPE);
           SecureViewerSaveDialog.showSaveDialog(dataToBeSigned.get(0), messages, backListener, backCommand); 
         }
       } else {
@@ -1421,28 +1329,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
     
     /**
      * has to be called from event dispatcher thread
-     * @param hashDataText
-     * @param saveListener
-     * @param saveCommand
      */
-//    private void showSecureViewer(HashDataInput dataToBeSigned) throws FontProviderException {
-//      
-//      log.debug("[" + Thread.currentThread().getName() + "] show secure viewer");
-//      if (secureViewer == null) {
-//        secureViewer = new SecureViewerDialog(null, messages,
-//                fontProvider, 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.
-//        Window window = SwingUtilities.getWindowAncestor(contentPane);
-//        if (window != null && window.isAlwaysOnTop()) {
-//          log.debug("make secureViewer alwaysOnTop");
-//          secureViewer.setAlwaysOnTop(true);
-//        }
-//      }
-//      secureViewer.setContent(dataToBeSigned);
-//      log.trace("show secure viewer returned");
-//    }
     private void showSecureViewer(HashDataInput dataToBeSigned, ActionListener closeListener, String closeCommand) throws FontProviderException {
       
       log.debug("[" + Thread.currentThread().getName() + "] show secure viewer");
@@ -1479,7 +1366,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
           buttonPanel.removeAll();
 
           if (renderHeaderPanel) {
-            titleLabel.setText(getMessage(TITLE_HASHDATA));
+            titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA));
           }
           
           helpMouseListener.setHelpTopic(HELP_HASHDATALIST);
@@ -1613,7 +1500,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
               @Override
               public void run() {
                 try {
-                  showMessageDialog(TITLE_HASHDATA, MESSAGE_HASHDATA_VIEWER);
+                  showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);
                   showSecureViewer(selection, backToListListener, null);
 //                  SecureViewerDialog.showSecureViewer(selection, messages, fontProvider, helpMouseListener.getActionListener(), false);
                 } catch (FontProviderException ex) {
@@ -1625,7 +1512,7 @@ public class BKUGUIImpl implements BKUGUIFacade {
             });
           } else {
             log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog");
-            showMessageDialog(BKUGUIFacade.TITLE_HASHDATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE);
+            showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE);
             SecureViewerSaveDialog.showSaveDialog(selection, messages, backToListListener, null);
           }
         }
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java
index 96032dc1..52a3d5fe 100644
--- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java
@@ -1,19 +1,19 @@
 /*
-* Copyright 2008 Federal Chancellery Austria and
-* Graz University of Technology
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package at.gv.egiz.bku.gui;
 
 import java.util.regex.Matcher;
@@ -21,7 +21,6 @@ import java.util.regex.Pattern;
 import javax.swing.JButton;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
 import javax.swing.text.PlainDocument;
 
 /**
@@ -31,16 +30,15 @@ import javax.swing.text.PlainDocument;
 class PINDocument extends PlainDocument {
 
   private static final long serialVersionUID = 1L;
-  
   protected Pattern pinPattern;
   protected int minLength;
   protected int maxLength;
-
   protected JButton enterButton;
-  protected Document compareTo;
-  protected Document oldPin;        
 
   public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton) {
+    if (enterButton == null) {
+      throw new NullPointerException("OK button null");
+    }
     if (pattern != null) {
       pinPattern = Pattern.compile(pattern);
     } else {
@@ -51,73 +49,26 @@ class PINDocument extends PlainDocument {
     this.enterButton = enterButton;
   }
 
-  /**
-   * @param pinSpec
-   * @param enterButton
-   * @param compareTo
-   *          enable enterButton if this pinDocument's pin equals to
-   *          compareTo's pin. may be null
-   */
-  public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton, Document compareTo) {
-    this(minLength, maxLength, pattern, enterButton);
-    this.compareTo = compareTo;
+  @Override
+  public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+    if (maxLength < 0 || maxLength >= (getLength() + str.length())) {
+      boolean matches = true;
+      for (int i = 0; i < str.length(); i++) {
+        Matcher m = pinPattern.matcher(str.substring(i, i + 1));
+        if (!m.matches()) {
+          matches = false;
+        }
+      }
+      if (matches) {
+        super.insertString(offs, str, a);
+        enterButton.setEnabled(getLength() >= minLength);
+      }
+    }
   }
 
-  /**
-   * @param pinSpec
-   * @param enterButton
-   *          may be null
-   * @param compareTo
-   *          enable enterButton if this pinDocument's pin equals to
-   *          compareTo's pin. may be null
-   * @param oldPin
-   *          enable enterButton if oldPin meets the pinSpec pin length
-   *          requirements, may be null
-   */
-  public PINDocument(int minLength, int maxLength, String pattern,
-      JButton enterButton, Document compareTo, Document oldPin) {
-    this(minLength, maxLength, pattern, enterButton);
-    this.compareTo = compareTo;
-    this.oldPin = oldPin;
+  @Override
+  public void remove(int offs, int len) throws BadLocationException {
+    super.remove(offs, len);
+    enterButton.setEnabled(getLength() >= minLength);
   }
-
-        @Override
-        public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
-            if (maxLength < 0 || maxLength >= (getLength() + str.length())) {
-                boolean matches = true;
-                for (int i = 0; i < str.length(); i++) {
-                    Matcher m = pinPattern.matcher(str.substring(i, i + 1));
-                    if (!m.matches()) {
-                        matches = false;
-                    }
-                }
-                if (matches) {
-                    super.insertString(offs, str, a);
-                }
-            }
-            if (enterButton != null) {
-              enterButton.setEnabled(
-                      (oldPin == null || oldPin.getLength() >= minLength) &&
-                      getLength() >= minLength &&
-                      compare());
-            }
-        }
-
-        @Override
-        public void remove(int offs, int len) throws BadLocationException {
-            super.remove(offs, len);
-            if (enterButton != null) {
-              enterButton.setEnabled(
-                      (oldPin == null || oldPin.getLength() >= minLength) &&
-                      getLength() >= minLength &&
-                      compare());
-            }
-        }
-
-        private boolean compare() throws BadLocationException {
-          if (compareTo == null) {
-            return true;
-          }
-          return compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()));
-        }
-    }
\ No newline at end of file
+}
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 7bae4673..7db70c46 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
@@ -17,7 +17,6 @@
 package at.gv.egiz.bku.gui;
 
 import at.gv.egiz.bku.gui.viewer.FontProvider;
-import at.gv.egiz.bku.gui.viewer.FontProviderException;
 import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog;
 import at.gv.egiz.stal.HashDataInput;
 import java.awt.Container;
@@ -25,7 +24,6 @@ import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.Frame;
-import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.FocusAdapter;
@@ -34,32 +32,26 @@ import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.io.BufferedOutputStream;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.nio.charset.Charset;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 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.JDialog;
 import javax.swing.JEditorPane;
-import javax.swing.JFileChooser;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.LayoutStyle;
-import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
 import javax.swing.text.Document;
 import javax.swing.text.EditorKit;
 import javax.swing.text.StyledEditorKit;
@@ -71,7 +63,7 @@ import org.apache.commons.logging.LogFactory;
  *
  * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
  */
-public class SecureViewerDialog extends JDialog implements ActionListener {
+public class SecureViewerDialog extends JDialog {
 
   /** don't import BKUFonts in order not to load BKUFonts.jar
    * BKUApplet includes BKUFonts as runtime dependency only, the jar is copied to the applet dir in BKUOnline with dependency-plugin
@@ -100,19 +92,6 @@ public class SecureViewerDialog extends JDialog implements ActionListener {
    * @param owner, dialog is positioned relative to its owner
    * (if null, at default location of native windowing system)
    */
-//  public static void showDataToBeSigned(HashDataInput dataToBeSigned,
-//          ResourceBundle messages,
-//          ActionListener saveListener, String saveCommand,
-//          ActionListener helpListener) {
-//
-////      Frame ownerFrame = (owner != null) ?
-////        JOptionPane.getFrameForComponent(owner) :
-////        null;
-//    dialog = new SecureViewerDialog(null, messages,
-//            saveListener, saveCommand, helpListener);
-//    dialog.setContent(dataToBeSigned);
-//    dialog.setVisible(true);
-//  }
   public SecureViewerDialog(Frame owner, ResourceBundle messages,
           ActionListener closeListener, String closeCommand,
           FontProvider fontProvider, ActionListener helpListener) {
@@ -125,6 +104,10 @@ public class SecureViewerDialog extends JDialog implements ActionListener {
             createViewerPanel(helpListener),
             createButtonPanel(closeListener, closeCommand));
 
+    // also leave defaultWindowClosing HIDE_ON_CLOSE
+    this.addWindowListener(new WindowCloseListener(closeListener, closeCommand));
+    this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
     pack();
     if (owner != null) {
       setLocationRelativeTo(owner);
@@ -305,19 +288,11 @@ public class SecureViewerDialog extends JDialog implements ActionListener {
     JButton closeButton = new JButton();
     closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE));
     closeButton.setActionCommand(closeCommand);
-    closeButton.addActionListener(closeListener);
-    closeButton.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent e) {
-        log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer");
-        setVisible(false);
-      }
-    });
+    closeButton.addActionListener(new CloseButtonListener(closeListener));
 
     JButton saveButton = new JButton();
     saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE));
-    saveButton.setActionCommand("save"); //TODO ensure unequal to closeCommand 
-    saveButton.addActionListener(this);
+    saveButton.addActionListener(new SaveButtonListener());
 
     int buttonSize = closeButton.getPreferredSize().width;
     if (saveButton.getPreferredSize().width > buttonSize) {
@@ -336,39 +311,50 @@ public class SecureViewerDialog extends JDialog implements ActionListener {
     return buttonPanel;
   }
 
-  @Override
-  public void actionPerformed(ActionEvent e) {
-    if ("save".equals(e.getActionCommand())) {
+  public class WindowCloseListener extends WindowAdapter {
+
+    ActionListener closeListener;
+    String closeCommand;
+
+    public WindowCloseListener(ActionListener closeListener, String closeCommand) {
+      this.closeListener = closeListener;
+      this.closeCommand = closeCommand;
+    }
+
+    @Override
+    public void windowClosing(WindowEvent e) {
+      log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer");
+      setVisible(false);
+      if (closeListener != null) {
+        closeListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), closeCommand));
+      }
+    }
+  }
+
+  public class CloseButtonListener implements ActionListener {
+
+    ActionListener closeListener;
+
+    public CloseButtonListener(ActionListener closeListener) {
+      this.closeListener = closeListener;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+      log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer");
+      setVisible(false);
+      if (closeListener != null) {
+        closeListener.actionPerformed(e);
+    }
+    }
+  }
+
+  public class SaveButtonListener implements ActionListener {
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
       log.trace("[" + Thread.currentThread().getName() + "] display secure viewer save dialog");
       SecureViewerSaveDialog.showSaveDialog(content, messages, null, null);
-      log.trace("done secure viewer save");
-    } else {
-      log.warn("unknown action command " + e.getActionCommand());
     }
   }
-  
-  
-//  //TEST
-//  private static SecureViewerDialog secureViewer;
-//  public static void showSecureViewerXXX(HashDataInput dataToBeSigned, ResourceBundle messages, FontProvider fontProvider, ActionListener helpListener, boolean alwaysOnTop) throws FontProviderException {
-//    
-////    ResourceBundle messages = ResourceBundle.getBundle(BKUGUIFacade.MESSAGES_BUNDLE, locale);
-//    
-//    log.debug("[" + Thread.currentThread().getName() + "] show secure viewer");
-//    if (secureViewer == null) {
-//      secureViewer = new SecureViewerDialog(null, messages,
-//              fontProvider, helpListener); 
-//
-//      // workaround for [#439]
-//      // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top.
-////      Window window = SwingUtilities.getWindowAncestor(contentPane);
-////      if (window != null && window.isAlwaysOnTop()) {
-////        log.debug("make secureViewer alwaysOnTop");
-//        secureViewer.setAlwaysOnTop(alwaysOnTop);
-////      }
-//    }
-//    secureViewer.setContent(dataToBeSigned);
-//    log.trace("show secure viewer returned");
-//  }
-
 }
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 3e483fc8..c09433de 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
@@ -16,15 +16,15 @@
 title.welcome=<html>Willkommen</html>
 title.insertcard=<html>Keine B\u00FCrgerkarte gefunden</html>
 title.cardnotsupported=<html>Die Karte wird nicht unterst\u00FCtzt</html>
-#title.cardpin=<html>{0} eingeben</html>
-title.cardpin=<html>Karte wird gelesen</html>
+title.verify.pin=<html>Karte wird gelesen</html>
 title.sign=<html>Signatur erstellen</html>
+title.verify.pinpad=<html>PIN eingeben
 title.error=<html>Fehler</html>
 title.warning=<html>Achtung
 title.entry.timeout=<html>Zeit\u00FCberschreitung</html>
 title.retry=<html>Falsche PIN</html>
 title.wait=<html>Bitte warten</html>
-title.hashdata=<html>Signaturdaten</html>
+title.signature.data=<html>Signaturdaten</html>
 windowtitle.save=Signaturdaten speichern
 windowtitle.error=Fehler
 windowtitle.savedir=Signaturdaten in Verzeichnis speichern
@@ -38,7 +38,8 @@ wait=<html>Bitte warten...</html>
 cardnotsupported=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html>
 insertcard=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html>
 enterpin=<html>{0} eingeben</html>
-enterpin.pinpad=<html>{0} ({1} stellig) am Kartenleser eingeben</html>
+enterpin.pinpad=<html>PIN am Kartenleser eingeben</html>
+enterpin.pinpad.direct=<html>{0} ({1} stellig) am Kartenleser eingeben</html>
 hashdatalink=<html><a href=\"anzeige\">Signaturdaten anzeigen</a></html>
 hashdatalink.tiny=<html><a href=\"anzeige\">Signaturdaten</a></html>
 hashdatalink.focus=<html><a href=\"anzeige\">[Signaturdaten anzeigen]</a></html>
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 c553bcb5..4d86d21b 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
@@ -16,15 +16,15 @@
 title.welcome=<html>Welcome</html>
 title.insertcard=<html>No citizen card found</html>
 title.cardnotsupported=<html>This card is not supported</html>
-#title.cardpin=<html>Enter {0}</html>
-title.cardpin=<html>Reading card</html>
+title.verify.pin=<html>Reading card</html>
 title.sign=<html>Create signature</html>
+title.verify.pinpad=<html>Enter PIN
 title.error=<html>Error</html>
 title.warning=<html>Warning
 title.entry.timeout=<html>Timeout</html>
 title.retry=<html>Wrong PIN</html>
 title.wait=<html>Please wait</html>
-title.hashdata=<html>Signature data</html>
+title.signature.data=<html>Signature data</html>
 windowtitle.save=Save signature data
 windowtitle.error=Error
 windowtitle.savedir=Save signature data to directory
@@ -38,7 +38,8 @@ wait=<html>Please wait...</html>
 insertcard=<html>Please insert your citizen card into the reader</html>
 cardnotsupported=<html>Please insert your citizen card into the reader</html>
 enterpin=<html>Enter {0}</html>
-enterpin.pinpad=<html>Enter {0} ({1} digits) on card reader pinpad</html>
+enterpin.pinpad=<html>Enter PIN on card reader pinpad</html>
+enterpin.pinpad.direct=<html>Enter {0} ({1} digits) on card reader pinpad</html>
 hashdatalink=<html><a href=\"anzeige\">Display signature data</a></html>
 hashdatalink.tiny=<html><a href=\"anzeige\">signature data</a></html>
 hashdatalink.focus=<html><a href=\"anzeige\">[Display signature data]</a></html>
diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java
index 6e345ee3..a2a84d6e 100644
--- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java
+++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java
@@ -45,7 +45,7 @@ public class BKUGUIWorker implements Runnable {
 
   @Override
   public void run() {
-//        try {
+        try {
 
     final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Test-PIN", (byte) 0x81, null);
     final PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Test-PIN", (byte) 0x01, null);
@@ -155,7 +155,10 @@ public class BKUGUIWorker implements Runnable {
 //
 //            gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata");
 
-    gui.showPinpadSignaturePINDialog(signPinSpec, -1, hashdataListener, "hashdata");
+    gui.showSignatureDataDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata");
+    Thread.sleep(2000);
+    
+    gui.showEnterPINDirect(signPinSpec, -1);
 //
 //            Thread.sleep(4000);
 //
@@ -189,8 +192,8 @@ public class BKUGUIWorker implements Runnable {
 //            gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save");
 //            Thread.sleep(2000);
 
-//        } catch (InterruptedException ex) {
-//            ex.printStackTrace();
-//        }
+        } catch (InterruptedException ex) {
+            ex.printStackTrace();
+        }
   }
 }
-- 
cgit v1.2.3