/** * Copyright 2013 multibit.org * * Licensed under the MIT license (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://opensource.org/licenses/mit-license.php * * 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 org.multibit.viewsystem.swing.view.panels; import java.awt.BorderLayout; import java.awt.Color; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.multibit.controller.Controller; import org.multibit.controller.bitcoin.BitcoinController; import org.multibit.model.bitcoin.WalletBusyListener; import org.multibit.model.core.CoreModel; import org.multibit.utils.ImageLoader; import org.multibit.viewsystem.DisplayHint; import org.multibit.viewsystem.View; import org.multibit.viewsystem.Viewable; import org.multibit.viewsystem.swing.ColorAndFontConstants; import org.multibit.viewsystem.swing.MultiBitFrame; import org.multibit.viewsystem.swing.action.HelpContextAction; import org.multibit.viewsystem.swing.action.VerifyMessageSubmitAction; import org.multibit.viewsystem.swing.view.components.HelpButton; import org.multibit.viewsystem.swing.view.components.MultiBitButton; import org.multibit.viewsystem.swing.view.components.MultiBitLabel; import org.multibit.viewsystem.swing.view.components.MultiBitTextArea; import org.multibit.viewsystem.swing.view.components.MultiBitTitledPanel; /** * View for verifying messages. */ public class VerifyMessagePanel extends JPanel implements Viewable, WalletBusyListener { private static final long serialVersionUID = 444992294329957705L; private final Controller controller; private final BitcoinController bitcoinController; private MultiBitFrame mainFrame; private MultiBitLabel messageLabel1; private MultiBitLabel messageLabel2; private MultiBitTextArea addressTextArea; private MultiBitLabel addressLabel; private MultiBitTextArea messageTextArea; private MultiBitLabel messageLabel; private MultiBitTextArea signatureTextArea; private MultiBitLabel signatureLabel; private VerifyMessageSubmitAction verifyMessageSubmitAction; private MultiBitButton clearAllButton; private static final int FIELD_WIDTH = 360; private static final int FIELD_HEIGHT = 30; /** * Creates a new {@link VerifyMessagePanel}. */ public VerifyMessagePanel(BitcoinController bitcoinController, MultiBitFrame mainFrame) { this.bitcoinController = bitcoinController; this.controller = this.bitcoinController; this.mainFrame = mainFrame; setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR); applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); initUI(); walletBusyChange(this.bitcoinController.getModel().getActivePerWalletModelData().isBusy()); this.bitcoinController.registerWalletBusyListener(this); } private void initUI() { setLayout(new BorderLayout()); JPanel mainPanel = new JPanel(); mainPanel.setMinimumSize(new Dimension(800, 480)); mainPanel.setLayout(new GridBagLayout()); mainPanel.setOpaque(false); mainPanel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); String[] keys = new String[] { "sendBitcoinPanel.addressLabel", "verifyMessagePanel.message.text", "verifyMessagePanel.signature.text" }; int stentWidth = MultiBitTitledPanel.calculateStentWidthForKeys(controller.getLocaliser(), keys, this) + ExportPrivateKeysPanel.STENT_DELTA; GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 0; constraints.gridwidth = 2; constraints.weightx = 1; constraints.weighty = 1; constraints.anchor = GridBagConstraints.LINE_START; JPanel instructionsPanel = createInstructionsPanel(stentWidth); mainPanel.add(instructionsPanel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 0; constraints.gridy = 1; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 0.1; constraints.anchor = GridBagConstraints.CENTER; mainPanel.add(MultiBitTitledPanel.createStent(12, 12), constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 2; constraints.gridwidth = 1; constraints.weightx = 0.4; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; JPanel buttonPanel = createButtonPanel(); mainPanel.add(buttonPanel, constraints); messageLabel1 = new MultiBitLabel(" "); messageLabel1.setOpaque(false); messageLabel1.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); messageLabel1.setHorizontalAlignment(JLabel.LEADING); messageLabel1.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 3; constraints.gridwidth = 3; constraints.weightx = 1; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; mainPanel.add(messageLabel1, constraints); messageLabel2 = new MultiBitLabel(" "); messageLabel2.setOpaque(false); messageLabel2.setBorder(BorderFactory.createEmptyBorder(0, 30, 0, 0)); messageLabel2.setHorizontalAlignment(JLabel.LEADING); messageLabel2.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 0; constraints.gridy = 4; constraints.gridwidth = 3; constraints.weightx = 1; constraints.weighty = 0.06; constraints.anchor = GridBagConstraints.LINE_START; mainPanel.add(messageLabel2, constraints); Action helpAction; if (ComponentOrientation.LEFT_TO_RIGHT == ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())) { helpAction = new HelpContextAction(controller, ImageLoader.HELP_CONTENTS_BIG_ICON_FILE, "multiBitFrame.helpMenuText", "multiBitFrame.helpMenuTooltip", "multiBitFrame.helpMenuText", HelpContentsPanel.HELP_SIGN_AND_VERIFY_MESSAGE_URL); } else { helpAction = new HelpContextAction(controller, ImageLoader.HELP_CONTENTS_BIG_RTL_ICON_FILE, "multiBitFrame.helpMenuText", "multiBitFrame.helpMenuTooltip", "multiBitFrame.helpMenuText", HelpContentsPanel.HELP_SIGN_AND_VERIFY_MESSAGE_URL); } HelpButton helpButton = new HelpButton(helpAction, controller); helpButton.setText(""); String tooltipText = HelpContentsPanel.createMultilineTooltipText(new String[] { controller.getLocaliser().getString( "multiBitFrame.helpMenuTooltip") }); helpButton.setToolTipText(tooltipText); helpButton.setHorizontalAlignment(SwingConstants.LEADING); helpButton.setBorder(BorderFactory.createEmptyBorder(0, AbstractTradePanel.HELP_BUTTON_INDENT, AbstractTradePanel.HELP_BUTTON_INDENT, AbstractTradePanel.HELP_BUTTON_INDENT)); helpButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 0; constraints.gridy = 5; constraints.weightx = 1; constraints.weighty = 0.1; constraints.gridwidth = 1; constraints.gridheight = 1; constraints.anchor = GridBagConstraints.BASELINE_LEADING; mainPanel.add(helpButton, constraints); JLabel filler2 = new JLabel(); filler2.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 0; constraints.gridy = 6; constraints.gridwidth = 1; constraints.weightx = 1; constraints.weighty = 100; constraints.anchor = GridBagConstraints.CENTER; mainPanel.add(filler2, constraints); JScrollPane mainScrollPane = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); mainScrollPane.setBorder(BorderFactory.createEmptyBorder()); mainScrollPane.getViewport().setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR); mainScrollPane.getViewport().setOpaque(true); mainScrollPane.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); mainScrollPane.getHorizontalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); mainScrollPane.getVerticalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); add(mainScrollPane, BorderLayout.CENTER); } private JPanel createInstructionsPanel(int stentWidth) { MultiBitTitledPanel instructionsPanel = new MultiBitTitledPanel(controller.getLocaliser().getString( "verifyMessagePanel.instructions.title"), ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); GridBagConstraints constraints = new GridBagConstraints(); MultiBitTitledPanel.addLeftJustifiedTextAtIndent( controller.getLocaliser().getString("verifyMessagePanel.instructions.text1"), 3, instructionsPanel); MultiBitTitledPanel.addLeftJustifiedTextAtIndent( controller.getLocaliser().getString("verifyMessagePanel.instructions.text2"), 4, instructionsPanel); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 5; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(MultiBitTitledPanel.createStent(stentWidth, ExportPrivateKeysPanel.STENT_HEIGHT), constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 6; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; instructionsPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); JPanel filler3 = new JPanel(); filler3.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 8; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(filler3, constraints); addressLabel = new MultiBitLabel(controller.getLocaliser().getString("sendBitcoinPanel.addressLabel")); addressLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 9; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; instructionsPanel.add(addressLabel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 9; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; instructionsPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); //addressTextArea = new MultiBitTextField("", 30, controller); JTextField aTextField = new JTextField(); addressTextArea = new MultiBitTextArea("", 1, 30, controller); addressTextArea.setBorder(aTextField.getBorder()); addressTextArea.setMinimumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT)); addressTextArea.setPreferredSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT)); addressTextArea.setMaximumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT)); addressTextArea.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 3; constraints.gridy = 9; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(addressTextArea, constraints); JPanel filler4 = new JPanel(); filler4.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 10; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(filler4, constraints); JTextField secondTextField = new JTextField(); messageTextArea = new MultiBitTextArea("", AbstractTradePanel.PREFERRED_NUMBER_OF_LABEL_ROWS + 1, 20, controller); messageTextArea.setBorder(secondTextField.getBorder()); messageTextArea.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); final JScrollPane messageScrollPane = new JScrollPane(messageTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); messageScrollPane.setOpaque(true); messageScrollPane.setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR); messageScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); messageScrollPane.getViewport().addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (messageScrollPane.getVerticalScrollBar().isVisible()) { messageScrollPane.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.LIGHT_GRAY)); } else { messageScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); } } }); messageScrollPane.setMinimumSize(new Dimension(FIELD_WIDTH, (AbstractTradePanel.PREFERRED_NUMBER_OF_LABEL_ROWS + 1) * FIELD_HEIGHT + 6)); messageScrollPane.setPreferredSize(new Dimension(FIELD_WIDTH, (AbstractTradePanel.PREFERRED_NUMBER_OF_LABEL_ROWS + 1) * FIELD_HEIGHT + 6)); messageScrollPane.getHorizontalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); messageScrollPane.getVerticalScrollBar().setUnitIncrement(CoreModel.SCROLL_INCREMENT); if (messageScrollPane.getVerticalScrollBar().isVisible()) { messageScrollPane.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.LIGHT_GRAY)); } else { messageScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); } messageLabel = new MultiBitLabel(controller.getLocaliser().getString("verifyMessagePanel.message.text")); messageLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 11; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; instructionsPanel.add(messageLabel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 11; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; instructionsPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridx = 3; constraints.gridy = 11; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(messageScrollPane, constraints); JPanel filler5 = new JPanel(); filler5.setOpaque(false); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 1; constraints.gridy = 12; constraints.weightx = 0.3; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(filler5, constraints); signatureLabel = new MultiBitLabel(controller.getLocaliser().getString("verifyMessagePanel.signature.text")); signatureLabel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.NONE; constraints.gridx = 1; constraints.gridy = 13; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_END; instructionsPanel.add(signatureLabel, constraints); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 2; constraints.gridy = 13; constraints.weightx = 0.05; constraints.weighty = 0.3; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.CENTER; instructionsPanel.add(MultiBitTitledPanel.createStent(MultiBitTitledPanel.SEPARATION_BETWEEN_NAME_VALUE_PAIRS), constraints); JTextField anotherTextField = new JTextField(); signatureTextArea = new MultiBitTextArea("", 2, 30, controller); signatureTextArea.setBorder(anotherTextField.getBorder()); signatureTextArea.setMinimumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT * 2)); signatureTextArea.setPreferredSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT * 2)); signatureTextArea.setMaximumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT * 2)); signatureTextArea.setLineWrap(true); signatureTextArea.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); constraints.fill = GridBagConstraints.BOTH; constraints.gridx = 3; constraints.gridy = 13; constraints.weightx = 0.3; constraints.weighty = 0.4; constraints.gridwidth = 1; constraints.anchor = GridBagConstraints.LINE_START; instructionsPanel.add(signatureTextArea, constraints); return instructionsPanel; } private JPanel createButtonPanel() { JPanel buttonPanel = new JPanel(); buttonPanel.setOpaque(false); FlowLayout flowLayout = new FlowLayout(); flowLayout.setAlignment(FlowLayout.LEADING); buttonPanel.setLayout(flowLayout); buttonPanel.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); verifyMessageSubmitAction = new VerifyMessageSubmitAction(this.bitcoinController, mainFrame, this, ImageLoader.createImageIcon(ImageLoader.MESSAGE_VERIFY_ICON_FILE)); MultiBitButton submitButton = new MultiBitButton(verifyMessageSubmitAction, controller); submitButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); buttonPanel.add(submitButton); clearAllButton = new MultiBitButton(controller.getLocaliser().getString("signMessagePanel.clearAll.text")); clearAllButton.setToolTipText(controller.getLocaliser().getString("signMessagePanel.clearAll.tooltip")); clearAllButton.setIcon(ImageLoader.createImageIcon(ImageLoader.DELETE_ICON_FILE)); clearAllButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { addressTextArea.setText(""); messageTextArea.setText(""); signatureTextArea.setText(""); messageLabel1.setText(" "); messageLabel2.setText(" "); } }); clearAllButton.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale())); buttonPanel.add(clearAllButton); return buttonPanel; } @Override public void displayView(DisplayHint displayHint) { // If it is a wallet transaction change no need to update. if (DisplayHint.WALLET_TRANSACTIONS_HAVE_CHANGED == displayHint) { return; } walletBusyChange(this.bitcoinController.getModel().getActivePerWalletModelData().isBusy()); messageLabel1.setText(" "); messageLabel2.setText(" "); } @Override public void navigateAwayFromView() { } public void setMessageText1(String message1) { if (messageLabel1 != null) { messageLabel1.setText(message1); } } public String getMessageText1() { if (messageLabel1 != null) { return messageLabel1.getText(); } else { return ""; } } public void setMessageText2(String message2) { if (messageLabel2 != null) { messageLabel2.setText(message2); } } public String getMessageText2() { if (messageLabel2 != null) { return messageLabel2.getText(); } else { return ""; } } @Override public Icon getViewIcon() { return ImageLoader.createImageIcon(ImageLoader.MESSAGE_VERIFY_ICON_FILE); } @Override public String getViewTitle() { return controller.getLocaliser().getString("verifyMessageAction.text"); } @Override public String getViewTooltip() { return controller.getLocaliser().getString("verifyMessageAction.tooltip"); } @Override public View getViewId() { return View.VERIFY_MESSAGE_VIEW; } public VerifyMessageSubmitAction getVerifyMessageSubmitAction() { return verifyMessageSubmitAction; } @Override public void walletBusyChange(boolean newWalletIsBusy) { } public MultiBitTextArea getMessageTextArea() { return messageTextArea; } public MultiBitTextArea getAddressTextArea() { return addressTextArea; } public MultiBitTextArea getSignatureTextArea() { return signatureTextArea; } }