/*
* Copyright � 2008, 2010, Oracle and/or its affiliates. All rights reserved
*/
package com.sun.lwuit.browser;
import com.sun.lwuit.Button;
import com.sun.lwuit.Container;
import com.sun.lwuit.Display;
import com.sun.lwuit.Image;
import com.sun.lwuit.TextField;
import com.sun.lwuit.animations.Motion;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.html.DocumentInfo;
import com.sun.lwuit.html.HTMLComponent;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.util.Resources;
import java.io.IOException;
import java.util.Vector;
/**
* A navigation toolbar that adds the back,forward,stop,refresh and home functionality
*
* @author Ofir Leitner
*/
public class BrowserToolbar extends Container implements ActionListener {
/**
* The prefix of the button images in the resource file
*/
private static String BUTTON_IMAGE_PREFIX="nav_button_";
/**
* The prefix of the selected button images in the resource file
*/
private static String BUTTON_IMAGE_PREFIX_SELECTED="nav_button_sel_";
/**
* The prefix of the disabled button images in the resource file
*/
private static String BUTTON_IMAGE_PREFIX_DISABLED="nav_button_disabled_";
/**
* The individual suffix names of the button images in the resource file
*/
private static String[] imgFiles= {"back","stop","forward","refresh","home"};
// Constants to identify the various navigation buttons
static int BTN_BACK = 0;
private static int BTN_CANCEL = 1;
private static int BTN_NEXT = 2;
private static int BTN_REFRESH = 3;
private static int BTN_HOME = 4;
/**
* The duration it takes the toolbar to slide in and out
*/
private static int SLIDE_DURATION = 300;
Button[] navButtons = new Button[imgFiles.length];
Image[] buttonsImages = new Image[imgFiles.length];
TextField address;
HTMLComponent htmlC;
Vector back=new Vector();
Vector forward=new Vector();
String homePage;
String currentURL="";
Motion slide;
boolean slidingOut;
int prefH;
private boolean backRequested=true;
/**
* A constant determining by which factor to scale the bar's buttons horizotally, specified as percentage of the original size (100 = original size).
* This is useful especially when using touch screens with very high resolutions or high DPI ratio.
* This value can be modified in the JAD property navbar_scalew
*/
static int scaleHorizontal = 100;
/**
* A constant determining by which factor to scale the bar's buttons horizotally, specified as percentage of the original size (100 = original size).
* This is useful especially when using touch screens with very high resolutions or high DPI ratio.
* This value can be modified in the JAD property navbar_scaleh
*/
static int scaleVertical = 100;
BrowserForm form;
public BrowserToolbar(HTMLComponent htmlComponent,BrowserForm form) {
Resources toolBarRes=null;
this.form=form;
setUIID("NavToolbar");
try {
toolBarRes = Resources.open("/toolbar.res");
} catch (IOException ex) {
ex.printStackTrace();
}
htmlC=htmlComponent;
setLayout(new BorderLayout());
address = new TextField() {
public void keyReleased(int keyCode) {
int action=Display.getInstance().getGameAction(keyCode);
super.keyReleased(keyCode);
if (action==Display.GAME_FIRE) {
htmlC.setPage(address.getText());
setEnabled(false);
}
}
};
Container buttons=new Container();
buttons.setHandlesInput(true); //to ignore the initial page load
buttons.setLayout(new BoxLayout(BoxLayout.X_AXIS));
for(int i=0;i<imgFiles.length;i++) {
Image img=null;
Image disabledImg=null;
Image selImg=null;
selImg=toolBarRes.getImage(BUTTON_IMAGE_PREFIX_SELECTED+imgFiles[i]);
img=toolBarRes.getImage(BUTTON_IMAGE_PREFIX+imgFiles[i]);
disabledImg=toolBarRes.getImage(BUTTON_IMAGE_PREFIX_DISABLED+imgFiles[i]);
if ((scaleHorizontal!=100) || (scaleVertical!=100)) {
img=img.scaled(img.getWidth()*scaleHorizontal/100, img.getHeight()*scaleVertical/100);
disabledImg=disabledImg.scaled(disabledImg.getWidth()*scaleHorizontal/100, disabledImg.getHeight()*scaleVertical/100);
selImg=selImg.scaled(selImg.getWidth()*scaleHorizontal/100, selImg.getHeight()*scaleVertical/100);
}
navButtons[i]=new NavButton(img,selImg,disabledImg);
buttons.addComponent(navButtons[i]);
navButtons[i].addActionListener(this);
navButtons[i].setEnabled(false);
}
addComponent(BorderLayout.CENTER, address);
addComponent(BorderLayout.SOUTH,buttons);
}
/**
* Sets the homepage of this toolbar to the specified URL
*
* @param url The homepage
*/
public void setHomePage(String url) {
homePage=url;
}
/**
* Called when a page loading has started and sets the buttons disabled/enablked mode accordingly.
*/
void notifyLoading() {
address.setEnabled(false);
navButtons[BTN_CANCEL].setEnabled(true);
navButtons[BTN_BACK].setEnabled(false);
navButtons[BTN_NEXT].setEnabled(false);
navButtons[BTN_HOME].setEnabled(false);
navButtons[BTN_REFRESH].setEnabled(false);
form.setCancelCmdOnly();
}
/**
* Called when a page loading has completed and sets the buttons disabled/enablked mode accordingly.
*/
void notifyLoadCompleted(String url) {
address.setEnabled(true);
navButtons[BTN_CANCEL].setEnabled(false);
navButtons[BTN_BACK].setEnabled(!back.isEmpty());
navButtons[BTN_NEXT].setEnabled(!forward.isEmpty());
navButtons[BTN_HOME].setEnabled(homePage!=null);
navButtons[BTN_REFRESH].setEnabled(true);
if (!backRequested) {
back.addElement(currentURL);
navButtons[BTN_BACK].setEnabled(true);
} else {
backRequested=false;
}
currentURL="";
DocumentInfo docInfo=htmlC.getDocumentInfo();
if (docInfo!=null) {
currentURL=docInfo.getFullUrl();
}
address.setText(currentURL);
form.addCommands(navButtons[BrowserToolbar.BTN_BACK].isEnabled());
}
public void actionPerformed(ActionEvent evt) {
if (evt.getSource()==navButtons[BTN_BACK]) {
back();
} else if (evt.getSource()==navButtons[BTN_NEXT]) {
forward();
} else if (evt.getSource()==navButtons[BTN_HOME]) {
home();
} else if (evt.getSource()==navButtons[BTN_REFRESH]) {
refresh();
} else if (evt.getSource()==navButtons[BTN_CANCEL]) {
stop();
}
}
/**
* Navigates to the previous page (if any)
*/
public void back() {
if (!back.isEmpty()) {
String url=(String)back.lastElement();
back.removeElementAt(back.size()-1);
forward.addElement(currentURL);
navButtons[BTN_NEXT].setEnabled(true);
if (back.isEmpty()) {
navButtons[BTN_BACK].setEnabled(false);
}
backRequested=true;
htmlC.setPage(url);
}
}
/**
* Navigates to the next page (if any)
*/
public void forward() {
if (!forward.isEmpty()) {
String url=(String)forward.lastElement();
forward.removeElementAt(forward.size()-1);
back.addElement(url);
if (forward.isEmpty()) {
navButtons[BTN_NEXT].setEnabled(false);
}
backRequested=true;
htmlC.setPage(url);
}
}
/**
* Navigates to the home page (if any)
*/
public void home() {
if (homePage!=null) {
htmlC.setPage(homePage);
} else {
System.out.println("No home page was set.");
}
}
/**
* Refreshes the current page
*/
public void refresh() {
backRequested=true;
htmlC.setPage(currentURL);
}
/**
* Stops the loading of the current page
*/
public void stop() {
System.out.println("Cancelling");
htmlC.cancel();
}
/**
* Starts the a slide in animation of the toolbar
*/
public void slideIn() {
slidingOut=false;
if (prefH==0) {
//prefH=getPreferredH();
prefH=calcPreferredSize().getHeight();
}
// if (slide!=null) {
// slide=Motion.createLinearMotion(slide.getValue(), prefH, SLIDE_DURATION);
// } else {
slide=Motion.createLinearMotion(0, prefH, SLIDE_DURATION);
getComponentForm().registerAnimated(this);
slide.start();
// }
}
/**
* Returns true if the toolbar is currently animating a slide, false otherwise
*
* @return true if the toolbar is currently animating a slide, false otherwise
*/
public boolean isSliding() {
return (slide!=null);
}
/**
* Starts the a slide out animation of the toolbar
*/
public void slideOut() {
slidingOut=true;
if (prefH==0) {
prefH=getPreferredH();
}
// if (slide!=null) {
// slide=Motion.createLinearMotion(slide.getValue(), 0, SLIDE_DURATION);
// } else {
slide=Motion.createLinearMotion(prefH, 0, SLIDE_DURATION);
getComponentForm().registerAnimated(this);
slide.start();
// }
}
/**
* {@inheritDoc}
*/
public boolean animate() {
if (slide!=null) {
setPreferredH(slide.getValue());
if (slide.isFinished()) {
slide=null;
}
getParent().revalidate();
return true;
} else {
getComponentForm().deregisterAnimated(this);
if (slidingOut) {
getComponentForm().removeComponent(this);
} else {
//getComponentForm().setFocused(this); // This seems unnecessary and it messes up pointer mode
}
return false;
}
}
}
/**
* A navigation button., mostly adds the disabled image functionality to Button and an animation effect when focused.
*
* @author Ofir Leitner
*/
class NavButton extends Button{
Image icon,disabledIcon,selIcon;
Image lastAnimatedIcon,currentAnimatedIcon;
long animationStartTime;
/**
* The selected icon animated speed in ms
*/
private static final int FOCUSED_ICON_ANIMATE_RATE = 400;
NavButton(Image icon,Image selIcon,Image disabledIcon) {
super(icon);
this.icon=icon;
this.selIcon=selIcon;
this.disabledIcon=disabledIcon;
setRolloverIcon(selIcon);
setPressedIcon(selIcon);
setDisabledStyle(getUnselectedStyle());
}
public String getUIID() {
return "NavButton";
}
/**
* {@inheritDoc}
*/
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (enabled) {
setIcon(icon);
} else {
setIcon(disabledIcon);
}
}
/**
* {@inheritDoc}
*/
protected void focusGained() {
super.focusGained();
getComponentForm().registerAnimated(this);
animationStartTime=System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
protected void focusLost() {
super.focusLost();
if (getComponentForm()!=null) {
getComponentForm().deregisterAnimated(this);
} //otherwise it deregistered in deinitialize
}
protected void deinitialize() {
getComponentForm().deregisterAnimated(this);
super.deinitialize();
}
public boolean animate() {
if ((System.currentTimeMillis()-animationStartTime)%(FOCUSED_ICON_ANIMATE_RATE<<1)>FOCUSED_ICON_ANIMATE_RATE) {
currentAnimatedIcon=selIcon;
} else {
currentAnimatedIcon=icon;
}
if (currentAnimatedIcon!=lastAnimatedIcon) {
lastAnimatedIcon=currentAnimatedIcon;
return true;
}
return false;
}
public Image getRolloverIcon() {
return currentAnimatedIcon;
}
}