/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 blackberry.web.widget;
import java.util.Enumeration;
import java.util.Hashtable;
import net.rim.device.api.notification.NotificationsConstants;
import net.rim.device.api.notification.NotificationsManager;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.EventLogger;
import net.rim.device.api.system.GlobalEventListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.web.WidgetConfig;
import blackberry.common.push.PushDaemon;
import blackberry.common.settings.SettingsManager;
import blackberry.common.util.ID;
import blackberry.core.ApplicationEventHandler;
import blackberry.core.ApplicationRegistry;
import blackberry.core.EventService;
import blackberry.core.WidgetProperties;
import blackberry.web.widget.bf.BrowserFieldScreen;
import blackberry.web.widget.impl.WidgetConfigImpl;
import blackberry.web.widget.listener.HardwareKeyListener;
import blackberry.web.widget.loadingScreen.PageManager;
import blackberry.web.widget.settings.SettingsStoreFactoryImpl;
public class Widget extends UiApplication implements GlobalEventListener {
private WidgetConfig _wConfig;
private HardwareKeyListener _hardwareKeyListener;
public BrowserFieldScreen _bfScreen;
private String _locationURI;
public static final long WIDGET_GUID = Long.parseLong( Widget.class.getName().hashCode() + "", 16 );
private static final String WIDGET_STARTUP_ENTRY = "rim:runOnStartup";
private static final String WIDGET_FOREGROUND_ENTRY = "rim:foreground";
private static final String DEBUG_ARGUMENT = "WIDGET;";
public Widget( WidgetConfig wConfig, String locationURI ) {
_wConfig = wConfig;
initialize();
_locationURI = locationURI;
// Set our orientation
WidgetConfigImpl configImpl = (WidgetConfigImpl) _wConfig;
if( configImpl.isOrientationDefined() ) {
int direction;
if( configImpl.getOrientation() == 0 ) {
direction = net.rim.device.api.system.Display.DIRECTION_NORTH;
} else {
direction = net.rim.device.api.system.Display.DIRECTION_LANDSCAPE;
}
net.rim.device.api.ui.Ui.getUiEngineInstance().setAcceptableDirections( direction );
}
// Create PageManager
PageManager pageManager = new PageManager( this, (WidgetConfigImpl) _wConfig );
// Push screen
WidgetScreen wScreen = new BrowserFieldScreen( this, pageManager, _locationURI );
_bfScreen = (BrowserFieldScreen) wScreen;
pageManager.pushScreens( _bfScreen );
this.addGlobalEventListener( this );
}
public WidgetConfig getConfig() {
return _wConfig;
}
/**
* @see net.rim.device.api.system#activate
*/
public void activate() {
EventService.getInstance().fireEvent( ApplicationEventHandler.EVT_APP_FOREGROUND, null, false );
// If we're switching application from the background we should change location to the widget content source.\r
if( _locationURI.equals( ( (WidgetConfigImpl) _wConfig ).getBackgroundSource() ) ) {
changeLocation( ( (WidgetConfigImpl) _wConfig ).getForegroundSource() );
}
}
/**
* @see net.rim.device.api.system#deactivate
*/
public void deactivate() {
EventService.getInstance().fireEvent( ApplicationEventHandler.EVT_APP_BACKGROUND, null, false );
}
public static void main( String[] args ) {
WidgetConfigImpl wConfig = new blackberry.web.widget.autogen.WidgetConfigAutoGen();
ID.init( wConfig );
ApplicationRegistry.getInstance().notifyStarted();
WidgetProperties.getInstance().setGuid( WIDGET_GUID );
EventLogger.register( WIDGET_GUID, wConfig.getName(), EventLogger.VIEWER_STRING );
SettingsManager.setFactory( new SettingsStoreFactoryImpl() );
// push entry
if( ApplicationRegistry.isDaemon( args ) ) {
String page = args[ 1 ];
int maxQueueCap = Integer.parseInt( args[ 2 ] );
PushDaemon daemon = new PushDaemon( page, maxQueueCap );
daemon.enterEventDispatcher();
return;
}
if( ApplicationRegistry.isAppRunning() ) {
/*
* rim:foreground is a special case. If the widget is running, just bring it to front, otherwise load the default
* page. So we need to differentiate ribbon presses from invokes and handle bringing apps to the foreground vs
* forceful refresh.
*/
String qsParams;
// If we're launching via rim:foreground, pass that directly.
if( args.length > 0 && args[ 0 ].indexOf( WIDGET_FOREGROUND_ENTRY ) != -1 ) {
qsParams = args[ 0 ];
} else {
qsParams = argsToQuery( args, wConfig );
}
ApplicationManager mgr = ApplicationManager.getApplicationManager();
mgr.postGlobalEvent( WIDGET_GUID, 0, 0, qsParams, null );
} else {
/*
* If the WebWorks Application is launched during system startup, wait until system startup is complete. This will
* allow startup widget to create BrowserField without the ApplicaitonRegistry timeout error.
*/
if( ApplicationManager.getApplicationManager().inStartup() ) {
waitForStartupComplete();
}
Widget widget = makeWidget( args, wConfig );
widget.enterEventDispatcher();
MemoryMaid mm = MemoryMaid.getInstance();
if( mm != null ) {
mm.stop();
}
}
}
private static void waitForStartupComplete() {
// use ApplicationManager.waitForStartup() in 6.0 when it's available
ApplicationManager manager = ApplicationManager.getApplicationManager();
while( manager.inStartup() ) {
try {
Thread.sleep( 2000 );
} catch( InterruptedException e ) {
}
}
try {
Thread.sleep( 1500 );
} catch( InterruptedException e ) {
}
}
private static Widget makeWidget( String[] args, WidgetConfigImpl wConfig ) {
String queryString = argsToQuery( args, wConfig );
Widget widget = null;
// Handle background only cases here.
if( wConfig.getForegroundSource().length() == 0 ) {
widget = new Widget( wConfig, queryString ) {
protected boolean acceptsForeground() {
return false;
}
};
widget.requestBackground(); // This may not be necessary.
} else {
widget = new Widget( wConfig, queryString );
}
return widget;
}
private static String argsToQuery( String[] args, WidgetConfigImpl wConfig ) {
// If parameters are not specified return a query string that handles default cases
// If the WebWorks Application is launched from the icon "WIDGET;" will be present.
// If allow invoke params is false then fall back on the default cases.
boolean rimEntryPoint = args.length > 0 && args[ 0 ].indexOf( "rim:" ) != -1;
String foregroundSource = wConfig.getForegroundSource();
String backgroundSource = wConfig.getBackgroundSource();
ApplicationManager.getApplicationManager();
if( !wConfig.allowInvokeParams() && !rimEntryPoint ) {
args = new String[ 0 ];
}
if( args.length == 0 || args[ 0 ].indexOf( DEBUG_ARGUMENT ) != -1 || rimEntryPoint ) {
if( foregroundSource.length() == 0 ) {
return backgroundSource;
} else if( rimEntryPoint ) {
if( args[ 0 ].indexOf( WIDGET_FOREGROUND_ENTRY ) != -1 ) {
return foregroundSource;
} else if( args[ 0 ].indexOf( WIDGET_STARTUP_ENTRY ) != -1 ) {
return backgroundSource;
}
} else {
return foregroundSource;
}
}
// Otherwise form the query string
StringBuffer strBuf = new StringBuffer();
for( int i = 0; i < args.length; i++ ) {
strBuf.append( args[ i ] + "&" );
}
String queryString = strBuf.toString();
queryString = queryString.substring( 0, queryString.length() - 1 );
return queryString;
}
public void eventOccurred( long guid, int data0, int data1, Object object0, Object object1 ) {
if( guid == WIDGET_GUID ) {
String location = (String) object0;
// if widget is already open then rim:foreground does not change/load the page
if( location.indexOf( WIDGET_FOREGROUND_ENTRY ) == -1 ) {
changeLocation( location );
}
this.requestForeground();
}
}
public void changeLocation( String uri ) {
if( !_locationURI.equals( uri ) ) {
_locationURI = uri;
_bfScreen.setLocation( uri );
}
}
public HardwareKeyListener getHardwareKeyListener() {
return _hardwareKeyListener;
}
private void initialize() {
// create hardware key listener
_hardwareKeyListener = new HardwareKeyListener( (WidgetConfigImpl) _wConfig );
// Register notification profile
Hashtable notifications = _wConfig.getNotifications();
for( Enumeration e = notifications.keys(); e.hasMoreElements(); ) {
Object name = e.nextElement();
NotificationsManager.registerSource( ( (Long) notifications.get( name ) ).longValue(), name,
NotificationsConstants.DEFAULT_LEVEL );
}
}
}