/*
*
* Copyright 2014 http://Bither.net
*
* 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 net.bither.viewsystem.froms;
import com.google.common.base.Optional;
import net.bither.BitherUI;
import net.bither.bitherj.core.Address;
import net.bither.bitherj.crypto.SecureCharSequence;
import net.bither.fonts.AwesomeIcon;
import net.bither.languages.MessageKey;
import net.bither.viewsystem.TextBoxes;
import net.bither.viewsystem.action.TextTransfer;
import net.bither.viewsystem.base.AccessibilityDecorator;
import net.bither.viewsystem.base.Buttons;
import net.bither.viewsystem.base.Labels;
import net.bither.viewsystem.base.Panels;
import net.bither.viewsystem.components.ScrollBarUIDecorator;
import net.bither.viewsystem.components.borders.TextBubbleBorder;
import net.bither.viewsystem.themes.Themes;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.event.ActionEvent;
public class SignMessagePanel extends WizardPanel {
private Address address;
private JLabel signingAddressLabel;
private JLabel messageLabel;
private JLabel signatureLabel;
private JTextField signingAddress;
private JTextArea signature;
private JTextArea messageTextArea;
private JPasswordField currentPassword;
private JLabel spinner;
JLabel reportLabel;
public SignMessagePanel(Address address) {
super(MessageKey.SIGN_MESSAGE_TITLE, AwesomeIcon.PENCIL);
this.address = address;
}
@Override
public void initialiseContent(JPanel panel) {
panel.setLayout(new MigLayout(
Panels.migXYLayout(),
"[][][][]", // Column constraints
"[][80][][30][30][20]" // Row constraints
));
// Labels (also used in clipboard)
signingAddressLabel = Labels.newBitcoinAddress();
messageLabel = Labels.newMessage();
signatureLabel = Labels.newSignature();
signingAddress = TextBoxes.newTextField(43);
signingAddress.setText(address.getAddress());
messageTextArea = TextBoxes.newEnterMessage();
// The message is a wall of text so needs scroll bars in many cases
messageTextArea.setBorder(null);
// Message requires its own scroll pane
JScrollPane messageScrollPane = new JScrollPane();
messageScrollPane.setOpaque(true);
messageScrollPane.setBackground(Themes.currentTheme.dataEntryBackground());
messageScrollPane.setBorder(null);
messageScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
messageScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
// View port requires special handling
messageScrollPane.setViewportView(messageTextArea);
messageScrollPane.getViewport().setBackground(Themes.currentTheme.dataEntryBackground());
messageScrollPane.setViewportBorder(new TextBubbleBorder(Themes.currentTheme.dataEntryBorder()));
// Ensure we maintain the overall theme
ScrollBarUIDecorator.apply(messageScrollPane, true);
signature = TextBoxes.newReadOnlyLengthLimitedTextArea(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
}
@Override
public void removeUpdate(DocumentEvent e) {
}
@Override
public void changedUpdate(DocumentEvent e) {
}
}, 5, 40);
AccessibilityDecorator.apply(signature, MessageKey.SIGNATURE);
// Add them to the panel
panel.add(signingAddressLabel);
panel.add(signingAddress, "growx,span 3,push,wrap");
panel.add(messageLabel);
panel.add(messageScrollPane, "grow,span 3,push,wrap");
panel.add(Labels.newEnterPassword());
panel.add(getenterPasswordMaV(), "growx,span 3,wrap");
panel.add(Buttons.newSignMessageButton(getSignMessageAction()), "cell 1 3,align right");
// panel.add(Buttons.newCopyAllButton(getCopyClipboardAction()), "cell 2 3");
panel.add(Buttons.newClearAllButton(getClearAllAction()), "cell 3 3,wrap");
panel.add(signatureLabel);
panel.add(signature, "grow,span 3,push,wrap");
reportLabel = Labels.newStatusLabel(Optional.<MessageKey>absent(), null, Optional.<Boolean>absent());
AccessibilityDecorator.apply(reportLabel, MessageKey.NOTES);
panel.add(reportLabel, "growx,span 4");
}
/**
* @return A new action for signing the message
*/
private Action getSignMessageAction() {
// Sign the message
return new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
signMessage();
}
};
}
/**
* @return A new action for clearing the signing address, message text and signature
*/
private Action getClearAllAction() {
// Clear the fields and set focus
return new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
signingAddress.setText("");
messageTextArea.setText("");
currentPassword.setText("");
signature.setText("");
reportLabel.setText("");
reportLabel.setIcon(null);
// Reset focus
signingAddress.requestFocusInWindow();
}
};
}
private JPanel getenterPasswordMaV() {
JPanel panel = Panels.newPanel(
new MigLayout(
Panels.migXLayout(), // Layout
"[][][][]", // Columns
"[]" // Rows
));
// Keep track of the credentials fields
currentPassword = TextBoxes.newPassword();
// Provide an invisible tar pit spinner
spinner = Labels.newSpinner(Themes.currentTheme.fadedText(), BitherUI.NORMAL_PLUS_ICON_SIZE);
spinner.setVisible(false);
// Bind a document listener to allow instant update of UI to matched passwords
currentPassword.getDocument().addDocumentListener(
new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
@Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
/**
* Trigger any UI updates
*/
private void updateModel() {
// Reset the credentials background
currentPassword.setBackground(Themes.currentTheme.dataEntryBackground());
}
});
panel.add(currentPassword, "growx,h 32,push");
//panel.add(showButton, "shrink");
// Ensure the icon label is a size suitable for rotation
panel.add(spinner, BitherUI.NORMAL_PLUS_ICON_SIZE_MIG + ",wrap");
return panel;
}
/**
* Sign the message text with the address specified and update UI
*/
private void signMessage() {
String messageText = messageTextArea.getText();
SecureCharSequence secureCharSequence = new SecureCharSequence(currentPassword.getPassword());
String signMessage = this.address.signMessage(messageText, secureCharSequence);
signature.setText(signMessage);
}
/**
* @return A new action for copying the view contents to the clipboard
*/
private Action getCopyClipboardAction() {
return new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
TextTransfer textTransfer = new TextTransfer();
//getReceiveAddress
textTransfer.setClipboardContents(signature.getText());
}
};
}
}