/**
* 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.browser;
import java.awt.Cursor;
import java.awt.Font;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import org.multibit.controller.Controller;
import org.multibit.message.Message;
import org.multibit.message.MessageManager;
import org.multibit.model.core.CoreModel;
import org.multibit.viewsystem.swing.ColorAndFontConstants;
import org.multibit.viewsystem.swing.MultiBitFrame;
import org.multibit.viewsystem.swing.view.components.FontSizer;
import org.multibit.viewsystem.swing.view.panels.HelpContentsPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Browser extends javax.swing.JEditorPane {
private static final long serialVersionUID = 1L;
private Logger log = LoggerFactory.getLogger(Browser.class);
private String loadingMessage;
private String currentHref;
private boolean loading = false;
private MultiBitFrame mainFrame;
private Controller controller;
public Browser(Controller controller, MultiBitFrame mainFrame, String currentHref) {
super();
this.controller = controller;
this.currentHref = currentHref;
this.mainFrame = mainFrame;
try {
if (mainFrame != null) {
mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
addHyperlinkListener(new ActivatedHyperlinkListener(mainFrame, this));
loadingMessage = controller.getLocaliser().getString("browser.loadingMessage");
setEditable(false);
setBackground(ColorAndFontConstants.VERY_LIGHT_BACKGROUND_COLOR);
String fontName = controller.getModel().getUserPreference(CoreModel.FONT_NAME);
if (fontName == null || "".equals(fontName)) {
fontName = ColorAndFontConstants.MULTIBIT_DEFAULT_FONT_NAME;
}
// Add in san-serif as a fallback.
fontName = fontName + ", san-serif";
int fontSize = ColorAndFontConstants.MULTIBIT_DEFAULT_FONT_SIZE;
boolean isItalic = false;
boolean isBold = false;
FontSizer.INSTANCE.initialise(controller);
Font adjustedFont = FontSizer.INSTANCE.getAdjustedDefaultFont();
if (adjustedFont != null) {
setFont(adjustedFont);
fontSize = adjustedFont.getSize();
isItalic = adjustedFont.isItalic();
isBold = adjustedFont.isBold();
}
String fontCSS = "font-size:" + fontSize + "pt; font-family:" + fontName + ";";
if (isItalic) {
fontCSS = fontCSS + "font-style:italic;";
} else {
fontCSS = fontCSS + "font-style:normal;";
}
if (isBold) {
fontCSS = fontCSS + "font-weight:bold;";
} else {
fontCSS = fontCSS + "font-weight:normal;";
}
HTMLEditorKit kit = new HTMLEditorKit();
setEditorKit(kit);
javax.swing.text.html.StyleSheet styleSheet = kit.getStyleSheet();
styleSheet.addRule("body {" + fontCSS + "}");
Document doc = kit.createDefaultDocument();
setDocument(doc);
log.debug("Trying to load '" + currentHref + "'...");
Message message = new Message(getLoadingMessage(currentHref, loadingMessage), true);
MessageManager.INSTANCE.addMessage(message);
setPage(currentHref);
MessageManager.INSTANCE.addMessage(new Message(" "));
} catch (Exception ex) {
showUnableToLoadMessage(ex.getClass().getCanonicalName() + " " + ex.getMessage());
}
}
public static String getLoadingMessage(String href, String loadingMessage) {
return href + HelpContentsPanel.SPACER + loadingMessage + "...";
}
/**
* This internal method attempts to load and display the specified URL.
**/
public boolean visit(String newHref, boolean forceLoad) {
try {
if (forceLoad || !newHref.equals(currentHref)) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Message message = new Message(getLoadingMessage(newHref, loadingMessage));
message.setShowInMessagesTab(false);
MessageManager.INSTANCE.addMessage(message);
// Load and display the URL.
getUrlContentInBackground(this, new URL(newHref), forceLoad);
currentHref = newHref;
// Remember the new helpContext.
int index = newHref.indexOf(HelpContentsPanel.HELP_BASE_URL);
if (index > -1) {
String helpContext = newHref.substring(index + HelpContentsPanel.HELP_BASE_URL.length());
mainFrame.setHelpContext(helpContext);
}
}
return true; // Return success.
} catch (IOException ex) {
showUnableToLoadMessage(ex.getClass().getCanonicalName() + " " + ex.getMessage());
return false; // Return failure.
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
/**
* Get the URL contents in a background thread.
*/
private void getUrlContentInBackground(final Browser browser, final URL url, final boolean forceLoad) {
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
private String message = null;
private StringBuffer stringBuffer = new StringBuffer();
@Override
protected Boolean doInBackground() throws Exception {
try {
browser.setLoading(true);
InputStream in = url.openStream();
byte [] buffer = new byte[256];
while(true){
int byteRead = in.read(buffer);
if(byteRead == -1)
break;
for(int i = 0; i < byteRead; i++){
stringBuffer.append((char)buffer[i]);
}
}
return true;
} catch (IOException ioe) {
message = ioe.getClass().getCanonicalName() + " " + ioe.getMessage();
return false;
} finally {
browser.setLoading(false);
}
}
@Override
protected void done() {
Boolean wasSuccessful = false;
try {
wasSuccessful = get();
if (wasSuccessful) {
String result = stringBuffer.toString();
if (result != null && result.length() > 0) {
browser.setText(result);
// Scroll to top.
browser.setCaretPosition(0);
MessageManager.INSTANCE.addMessage(new Message(" "));
} else {
if (message != null) {
showUnableToLoadMessage(message);
}
}
} else {
if (message != null) {
showUnableToLoadMessage(message);
}
}
} catch (InterruptedException e) {
showUnableToLoadMessage(message);
e.printStackTrace();
} catch (ExecutionException e) {
showUnableToLoadMessage(message);
e.printStackTrace();
} finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
};
worker.execute();
}
public void setLoading(boolean loading) {
this.loading = loading;
}
public boolean isLoading() {
return loading;
}
private void showUnableToLoadMessage(String message) {
Message messageToShow = new Message(controller.getLocaliser().getString("browser.unableToLoad", new String[]{currentHref, message}), true);
MessageManager.INSTANCE.addMessage(messageToShow);
}
}