/**
* Copyright 2011 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.action;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import org.multibit.controller.Controller;
import org.multibit.controller.bitcoin.BitcoinController;
import org.multibit.file.BackupManager;
import org.multibit.file.FileHandler;
import org.multibit.file.WalletLoadException;
import org.multibit.file.WalletSaveException;
import org.multibit.message.Message;
import org.multibit.message.MessageManager;
import org.multibit.model.bitcoin.BitcoinModel;
import org.multibit.model.bitcoin.WalletData;
import org.multibit.model.bitcoin.WalletInfoData;
import org.multibit.store.MultiBitWalletVersion;
import org.multibit.store.WalletVersionException;
import org.multibit.viewsystem.swing.MultiBitFrame;
import org.multibit.viewsystem.swing.view.WalletFileFilter;
import org.multibit.viewsystem.swing.view.components.FontSizer;
import org.multibit.viewsystem.swing.view.panels.HelpContentsPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Wallet;
/**
* This {@link Action} creates a new wallet.
*/
public class CreateWalletSubmitAction extends AbstractAction {
private static final Logger log = LoggerFactory.getLogger(CreateWalletSubmitAction.class);
private static final long serialVersionUID = 1923492460523457765L;
private final Controller controller;
private final BitcoinController bitcoinController;
private MultiBitFrame mainFrame;
private Font adjustedFont;
/**
* Creates a new {@link CreateWalletSubmitAction}.
*/
public CreateWalletSubmitAction(BitcoinController bitcoinController, ImageIcon icon, MultiBitFrame mainFrame) {
super(bitcoinController.getLocaliser().getString("createNewWalletAction.text"), icon);
this.bitcoinController = bitcoinController;
this.controller = this.bitcoinController;
this.mainFrame = mainFrame;
MnemonicUtil mnemonicUtil = new MnemonicUtil(controller.getLocaliser());
putValue(SHORT_DESCRIPTION, HelpContentsPanel.createTooltipTextForMenuItem(controller.getLocaliser().getString("createNewWalletAction.tooltip")));
putValue(MNEMONIC_KEY, mnemonicUtil.getMnemonic("createNewWalletAction.text"));
}
/**
* Create new wallet.
*/
@Override
public void actionPerformed(ActionEvent e) {
if (mainFrame != null) {
mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
setEnabled(false);
try {
// Create a file save dialog.
JFileChooser.setDefaultLocale(controller.getLocaliser().getLocale());
JFileChooser fileChooser = new JFileChooser();
fileChooser.setLocale(controller.getLocaliser().getLocale());
fileChooser.setDialogTitle(controller.getLocaliser().getString("createNewWalletAction.tooltip"));
adjustedFont = FontSizer.INSTANCE.getAdjustedDefaultFont();
if (adjustedFont != null) {
setFileChooserFont(new Container[] {fileChooser});
}
fileChooser.applyComponentOrientation(ComponentOrientation.getOrientation(controller.getLocaliser().getLocale()));
if (this.bitcoinController.getModel().getActiveWalletFilename() != null) {
fileChooser.setCurrentDirectory(new File(this.bitcoinController.getModel().getActiveWalletFilename()));
}
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setFileFilter(new WalletFileFilter(controller));
String defaultFileName = fileChooser.getCurrentDirectory().getAbsoluteFile() + File.separator
+ controller.getLocaliser().getString("saveWalletAsView.untitled") + "." + BitcoinModel.WALLET_FILE_EXTENSION;
fileChooser.setSelectedFile(new File(defaultFileName));
fileChooser.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
int returnVal = fileChooser.showSaveDialog(mainFrame);
String newWalletFilename = null;
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
if (file != null) {
newWalletFilename = file.getAbsolutePath();
createNewWallet(newWalletFilename);
}
}
} finally {
setEnabled(true);
if (mainFrame != null) {
mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
public void createNewWallet(String newWalletFilename) {
String message;
if (new File(newWalletFilename).isDirectory()) {
message = controller.getLocaliser().getString("createNewWalletAction.walletFileIsADirectory",
new Object[] { newWalletFilename });
log.debug(message);
MessageManager.INSTANCE.addMessage(new Message(message));
return;
}
// If the filename has no extension, put on the wallet extension.
if (!newWalletFilename.contains(".")) {
newWalletFilename = newWalletFilename + "." + BitcoinModel.WALLET_FILE_EXTENSION;
}
File newWalletFile = new File(newWalletFilename);
boolean theWalletWasNotOpenedSuccessfully = false;
try {
// If file exists, load the existing wallet.
if (newWalletFile.exists()) {
WalletData perWalletModelData = this.bitcoinController.getFileHandler().loadFromFile(newWalletFile);
if (perWalletModelData != null) {
// Use the existing wallet.
this.bitcoinController.addWalletFromFilename(newWalletFile.getAbsolutePath());
this.bitcoinController.getModel().setActiveWalletByFilename(newWalletFilename);
controller.getModel().setUserPreference(BitcoinModel.GRAB_FOCUS_FOR_ACTIVE_WALLET, "true");
controller.fireRecreateAllViews(true);
controller.fireDataChangedUpdateNow();
}
} else {
// Create a new wallet - protobuf.2 initially for backwards compatibility.
Wallet newWallet = new Wallet(this.bitcoinController.getModel().getNetworkParameters());
ECKey newKey = new ECKey();
newWallet.addKey(newKey);
WalletData perWalletModelData = new WalletData();
perWalletModelData.setWalletInfo(new WalletInfoData(newWalletFilename, newWallet, MultiBitWalletVersion.PROTOBUF));
perWalletModelData.setWallet(newWallet);
perWalletModelData.setWalletFilename(newWalletFilename);
perWalletModelData.setWalletDescription(controller.getLocaliser().getString(
"createNewWalletSubmitAction.defaultDescription"));
this.bitcoinController.getFileHandler().savePerWalletModelData(perWalletModelData, true);
// Start using the new file as the wallet.
this.bitcoinController.addWalletFromFilename(newWalletFile.getAbsolutePath());
this.bitcoinController.getModel().setActiveWalletByFilename(newWalletFilename);
controller.getModel().setUserPreference(BitcoinModel.GRAB_FOCUS_FOR_ACTIVE_WALLET, "true");
// Save the user properties to disk.
FileHandler.writeUserPreferences(this.bitcoinController);
log.debug("User preferences with new wallet written successfully");
// Backup the wallet and wallet info.
BackupManager.INSTANCE.backupPerWalletModelData(bitcoinController.getFileHandler(), perWalletModelData);
controller.fireRecreateAllViews(true);
controller.fireDataChangedUpdateNow();
}
} catch (WalletLoadException e) {
message = controller.getLocaliser().getString("createNewWalletAction.walletCouldNotBeCreated",
new Object[] { newWalletFilename, e.getMessage() });
log.error(message);
MessageManager.INSTANCE.addMessage(new Message(message));
theWalletWasNotOpenedSuccessfully = true;
} catch (WalletSaveException e) {
message = controller.getLocaliser().getString("createNewWalletAction.walletCouldNotBeCreated",
new Object[] { newWalletFilename, e.getMessage() });
log.error(message);
MessageManager.INSTANCE.addMessage(new Message(message));
theWalletWasNotOpenedSuccessfully = true;
} catch (WalletVersionException e) {
message = controller.getLocaliser().getString("createNewWalletAction.walletCouldNotBeCreated",
new Object[] { newWalletFilename, e.getMessage() });
log.error(message);
MessageManager.INSTANCE.addMessage(new Message(message));
theWalletWasNotOpenedSuccessfully = true;
} catch (IOException e) {
message = controller.getLocaliser().getString("createNewWalletAction.walletCouldNotBeCreated",
new Object[] { newWalletFilename, e.getMessage() });
log.error(message);
MessageManager.INSTANCE.addMessage(new Message(message));
theWalletWasNotOpenedSuccessfully = true;
}
if (theWalletWasNotOpenedSuccessfully) {
WalletData loopData = this.bitcoinController.getModel().getPerWalletModelDataByWalletFilename(newWalletFilename);
if (loopData != null) {
// Clear the backup wallet filename - this prevents it being automatically overwritten.
if (loopData.getWalletInfo() != null) {
loopData.getWalletInfo().put(BitcoinModel.WALLET_BACKUP_FILE, "");
}
}
}
}
private void setFileChooserFont(Component[] comp) {
for (int x = 0; x < comp.length; x++) {
if (comp[x] instanceof Container)
setFileChooserFont(((Container) comp[x]).getComponents());
try {
comp[x].setFont(adjustedFont);
} catch (Exception e) {
}// do nothing
}
}
}