/**
* Copyright 2012 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 net.bither.viewsystem;
import com.google.common.base.Preconditions;
import net.bither.Bither;
import net.bither.BitherSetting;
import net.bither.bitherj.core.Address;
import net.bither.platform.listener.GenericQuitEventListener;
import net.bither.utils.LocaliserUtils;
import net.bither.viewsystem.base.DisplayHint;
import net.bither.viewsystem.base.ViewEnum;
import net.bither.viewsystem.base.ViewSystem;
import net.bither.viewsystem.base.Viewable;
import net.bither.viewsystem.dialogs.PanelDialog;
import org.simplericity.macify.eawt.ApplicationEvent;
import org.simplericity.macify.eawt.ApplicationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MainFrame extends JFrame implements ViewSystem, ApplicationListener {
private static final Logger log = LoggerFactory.getLogger(MainFrame.class);
private final CoreController coreController;
private String helpContext;
final private GenericQuitEventListener quitEventListener;
private MainFrameUI mainFrameUi;
@SuppressWarnings("deprecation")
public MainFrame(CoreController coreController, ViewEnum initialView) {
Preconditions.checkState(SwingUtilities.isEventDispatchThread(), "MainFrame isEventDispatchThread");
this.coreController = coreController;
this.quitEventListener = this.coreController;
this.mainFrameUi = new MainFrameUI(MainFrame.this, this.quitEventListener);
remapCommandOnMac();
setCursor(Cursor.WAIT_CURSOR);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
String titleText = LocaliserUtils.getString("bitherframe_title");
setTitle(titleText);
ToolTipManager.sharedInstance().setDismissDelay(BitherSetting.TOOLTIP_DISMISSAL_DELAY);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent arg0) {
quitEventListener.onQuitEvent(null, MainFrameUI.bitherFrameQuitResponse);
}
});
applyComponentOrientation(ComponentOrientation.getOrientation(LocaliserUtils.getLocale()));
sizeAndCenter();
this.mainFrameUi.initUI(initialView);
this.mainFrameUi.focusableUI();
displayView(null != initialView ? initialView : ViewEnum.DEFAULT_VIEW());
pack();
setVisible(true);
}
private void remapCommandOnMac() {
// Remap to command v and C on a Mac
if (Bither.getGenericApplication() != null && Bither.getGenericApplication().isMac()) {
InputMap im = (InputMap) UIManager.get("TextField.focusInputMap");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.META_DOWN_MASK), DefaultEditorKit.copyAction);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), DefaultEditorKit.pasteAction);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.META_DOWN_MASK), DefaultEditorKit.cutAction);
}
}
public MainFrameUI getMainFrameUi() {
return mainFrameUi;
}
private void sizeAndCenter() {
// Get the screen size as a java dimension.
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int height = (int) (screenSize.height * BitherSetting.PROPORTION_OF_VERTICAL_SCREEN_TO_FILL);
int width = (int) (screenSize.width * BitherSetting.PROPORTION_OF_HORIZONTAL_SCREEN_TO_FILL);
// Set the jframe height and width.
setPreferredSize(new Dimension(width, height));
double startVerticalPositionRatio = (1 - BitherSetting.PROPORTION_OF_VERTICAL_SCREEN_TO_FILL) / 2;
double startHorizontalPositionRatio = (1 - BitherSetting.PROPORTION_OF_HORIZONTAL_SCREEN_TO_FILL) / 2;
setLocation((int) (width * startHorizontalPositionRatio), (int) (height * startVerticalPositionRatio));
}
@Override
public void setHelpContext(String helpContext) {
this.helpContext = helpContext;
}
/**
* Recreate all views.
*/
@Override
public void recreateAllViews(final boolean initUI, final ViewEnum initialView) {
// if initUI set, do an invokeLater or else it can sometimes leave the menu items in the Mac header row.
if (EventQueue.isDispatchThread() && !initUI) {
mainFrameUi.recreateAllViewsOnSwingThread(initUI, initialView);
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrameUi.recreateAllViewsOnSwingThread(initUI, initialView);
}
});
}
}
/**
* Display next view.
*/
@Override
public void displayView(ViewEnum viewToDisplay) {
log.debug("Displaying view '" + viewToDisplay + "'");
// Open wallet view obselete - show transactions
if (ViewEnum.OPEN_WALLET_VIEW == viewToDisplay) {
viewToDisplay = ViewEnum.TRANSACTIONS_VIEW;
}
// Create Bulk addreses obselete - show transactions
if (ViewEnum.CREATE_BULK_ADDRESSES_VIEW == viewToDisplay) {
viewToDisplay = ViewEnum.TRANSACTIONS_VIEW;
}
// Show wallets view always on display.
if (ViewEnum.YOUR_WALLETS_VIEW == viewToDisplay) {
mainFrameUi.getWalletsView().displayView(DisplayHint.COMPLETE_REDRAW);
return;
}
coreController.setCurrentView(viewToDisplay);
final Viewable nextViewFinal = mainFrameUi.getViewFactory().getView(viewToDisplay);
if (nextViewFinal == null) {
log.debug("Cannot display view " + viewToDisplay);
return;
}
if (EventQueue.isDispatchThread()) {
displayViewOnSwingThread(nextViewFinal);
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
displayViewOnSwingThread(nextViewFinal);
}
});
}
}
private void displayViewOnSwingThread(final Viewable nextViewFinal) {
if (nextViewFinal.getViewId() != ViewEnum.TRANSACTIONS_VIEW && nextViewFinal.getViewId() != ViewEnum.COLD_WALLET_VIEW) {
PanelDialog panelDialog = new PanelDialog(nextViewFinal.getPanel());
panelDialog.pack();
panelDialog.setVisible(true);
return;
}
nextViewFinal.displayView(DisplayHint.COMPLETE_REDRAW);
//log.debug("viewTabbedPane " + System.identityHashCode(viewTabbedPane) + " finally has " + viewTabbedPane.getTabCount() + " tabs.");
this.setCursor(Cursor.getDefaultCursor());
}
@Override
public void setVisible(boolean b) {
super.setVisible(b);
getMainFrameUi().clearScroll();
}
/**
* Navigate away from view - this may be on another thread hence the
* SwingUtilities.invokeLater.
*/
@Override
public void navigateAwayFromView(ViewEnum viewToNavigateAwayFrom) {
if (ViewEnum.YOUR_WALLETS_VIEW == viewToNavigateAwayFrom) {
// Do nothing
return;
}
final Viewable viewToNavigateAwayFromFinal = mainFrameUi.getViewFactory().getView(viewToNavigateAwayFrom);
// if (viewToNavigateAwayFromFinal != null) {
// if (EventQueue.isDispatchThread()) {
// viewToNavigateAwayFromFinal.navigateAwayFromView();
// } else {
// SwingUtilities.invokeLater(new Runnable() {
// @Override
// public void run() {
// viewToNavigateAwayFromFinal.navigateAwayFromView();
// }
// });
// }
// }
}
@Override
public void fireFilesHaveBeenChangedByAnotherProcess(Address perWalletModelData) {
if (Bither.getActionAddress() != null
&& Bither.getActionAddress().getAddress().equals(perWalletModelData.getAddress())) {
// Message message = new Message(BitherSetting.createTooltipText(LocaliserUtils.getString("singleWalletPanel.dataHasChanged.tooltip.1") + " "
// + LocaliserUtils.getString("singleWalletPanel.dataHasChanged.tooltip.2")), true);
// MessageManager.INSTANCE.addMessage(message);
}
fireDataChangedUpdateNow(DisplayHint.COMPLETE_REDRAW);
}
/**
* Mark that the UI needs to be updated as soon as possible.
*/
@Override
public void fireDataChangedUpdateNow(final DisplayHint displayHint) {
if (EventQueue.isDispatchThread()) {
mainFrameUi.fireDataChangedOnSwingThread(displayHint);
} else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrameUi.fireDataChangedOnSwingThread(displayHint);
}
});
}
}
@Override
@Deprecated
public void handleAbout(ApplicationEvent event) {
coreController.displayView(ViewEnum.TRANSACTIONS_VIEW);
event.setHandled(true);
}
@Override
@Deprecated
public void handleOpenApplication(ApplicationEvent event) {
// Ok, we know our application started.
// Not much to do about that..
}
@Override
@Deprecated
public void handleOpenFile(ApplicationEvent event) {
// TODO i18n required.
JOptionPane.showMessageDialog(this, "Sorry, opening of files with double click is not yet implemented. Wallet was "
+ event.getFilename());
}
@Override
@Deprecated
public void handlePreferences(ApplicationEvent event) {
}
@Override
@Deprecated
public void handlePrintFile(ApplicationEvent event) {
// TODO i18n required.
JOptionPane.showMessageDialog(this, "Sorry, printing not implemented");
}
@Override
@Deprecated
public void handleQuit(ApplicationEvent event) {
throw new UnsupportedOperationException("Deprecated.");
}
@Override
public void handleReOpenApplication(ApplicationEvent event) {
setVisible(true);
}
public void bringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
toFront();
repaint();
}
});
}
//todo exchange mainFrameUi.updateHeader();
}