RSS

Search Engine

Saturday, August 28, 2010

Android, Symbian Expected To Become One OS

Nokia (NYSE: NOK)-owned Symbian and Google (NSDQ: GOOG)-created Android are destined to be combined to provide a single open source operating system for smartphones, an analyst firm said Thursday.

The merger of the two operating systems will begin within three to six months, driven mostly by the fact that Nokia and Google are pursuing similar open source strategies with their respective technology, J. Gold Associates said in a research note.

Nokia and other users of Symbian, which has the largest share of smartphones in the market, do not want to compete in the OS market, the firm said. With Google, the search engine entered the OS market to push the industry toward openness and a level playing field in offering applications and services on the devices.

"We expect that within the next three-six months, Symbian and Android will combine to provide a single open source OS," J. Gold said. "Many of the same sponsors are involved in both initiatives."

Nokia recently acquired 100% ownership of Symbian and announced plans to turn it over to a new Symbian Foundation to create an open source OS, which would be offered to foundation members sometime in the first half of 2009.

In pursuing the same open source strategy, Google and supporters have formed the Open Handset Alliance for Android. Members include Motorola (NYSE: MOT) and Japan-based DoCoMo, which are also participants in the Symbian Foundation.

J. Gold said both sides have good reasons for joining. Google's investment in Android is "diluting the potential for it [Google] to build compelling cross-device applications where it can generate substantial revenues," the firm said. Symbian, on the other hand, could cement its position with the open source community by not appearing as just a Nokia public relations stunt.

For the market as a whole, the consolidation would reduce the number of major platforms, making it easier for developers to write applications, which means more software would hit the market, J. Gold said. In addition, consolidation means lower support costs.

Finally, it may help discourage carriers from creating their own unique user experiences on specifically altered and customized devices "in order to maintain customer control, but which is also suppressing the growth of apps," the firm said.

"A combination of the Android and Symbian efforts would be good for the industry, good for Google and good for Symbian," J. Gold said. "It would also help spur a growth in the availability of applications and services. The downside is minimal. Everyone wins."

Android, Google Will Threaten Garmin

The convergence of Mobile continues. The arms race for megapixel packed phones has somewhat taken the spotlight as several 8MP Camera Phones vie for dominance. Meanwhile, your traditional GPS navigation system is quietly tiptoeing towards the mobile edge… and at the bottom of that big cliff might lie Android.

Lets play a game called free association - say what comes to mind after this statement: GPS company… let me guess, you said “Garmin”. So would 99 out of 100 other people. Garmin simply dominates the GPS game. A lot of that could be due to superior branding (a la Coca-Cola) but most of it is they simply have a better product. The proof is in the pudding and Garmin’s proprietary product pool is filled to the brim.

How do we know? Well, if you’ve used Verizon Wireless’ GPS system, VZNavigator, which costs $9.99/month then you probably know what we mean. Or if you’ve used AT&T’s GPS Navigation system, appropriately boringly dubbed AT&T Navigator. They simply aren’t as precise: the directions/roads are sometimes wrong, the graphics are subpar, it can be hard to determine where a turn is coming, etc…

An important thing to note is that Garmin’s main competitive edge is in their software and knowledge base - NOT in their hardware. So, the transition to developing mobile phone navigation systems should be a smooth one. That sentiment is proven true with Garmin Mobile, a recently announced downloadable app for smartphones and BlackBerries for a one-time fee of $99.

We haven’t gotten a chance to play with Garmin Mobile’s nav system, but we’re guessing its some pretty solid stuff. Oh yeah, and they pull real-time traffic data from Traffic.com so you find alternate roots and such based on accidents, road work and the like.

Don’t get us wrong, Garmin isn’t going anywhere anytime soon - they’ve built a huge competitive edge in the navigation industry that is practically unrivaled. But, there seem to be plenty of companies gaining ground and one of them is Google.

Part of Garmin’s success comes from its accurate and updated maps. As Google covers more and more ground with their Google Street View and Google Earth systems, they are slowly building an infrastructure that could one day replace what Garmin has took so long to build. Its a matter of preference, I suppose, but if your GPS system asks you to turn right… would you rather see a fake map showing you which direction the road goes or a street view picture that shows you exactly what the road looks like where you are supposed to turn?

My guess would be the latter - if it is properly implemented that is. Implementation could take some time but the fundamentals are in place. Right now Garmin is using Traffic.com for updated traffic information… perhaps it won’t be long before they’re using Google Maps, Google Earth and Google Street View for graphical overlays?

Or perhaps Google will replace the need for Garmin altogether. The whole community element of what many call “Web 2.0″ really illustrates the power in numbers. Android is able to deliver this power of numbers and integration so that PEOPLE can update new maps, new pictures, new everything while different applications interface with eathother to deliver the most seamless GPS navigational experience possible.

The missing link here is screen size - most phones don’t come with a screen nearly the size of the best GPS units which can make determining the streets/directions difficult depending on the device. But is there a reason Android couldn’t run on a device with a larger screen… or even on a piece of hardware designed specifically for GPS? We don’t see why not… first things first of course.

And if your mobile phone is already running Android and has all the necessary software, hardware and CPU components, minus the screen, why not sell GPS focused SCREENS without everything else… just plug your phone into your GPS Flat Screen via USB (or whatever custom connection they can charge you most for) and run navigation perfectly.

The navigational industry is going to be shook up and Android might be one of the primary responsible parties. If you pay for an Android device that has all these navigational capabilities via 3rd party applications, why pay for a completely new device to do GPS when your mobile phone does it best anyways? Why not just pay for the one thing you need - a dedicated screen for your car - and plug the first into the second?

That would make the most sense and we’re eagerly anticipating that day. Our guess is the first company to offer something like this is going to make bank. Don’t forget to tip us on your way to the top.

Oh… and another thing… GPS/mapping DOES fit into Google’s goal of “organizing the world’s information” but one has to think to themselves: how long will they let 3rd party developers play in the field before they try to trump them all with their own solution? We won’t take any guesses or even claim that will happen… but if you’re developing a GPS related solution for Android, it has to of crossed your mind.

Tuesday, August 24, 2010

Mapping with Google APIs in Android

Mapping functionality has become a must-have feature for new mobile devices. With all the new technology advances, mobile devices, especially cell phones, are more than capable of handling complicated mathematical calculations on their own or keeping up with the high-traffic communication with the servers. GPS devices used to be the dominant player with the mapping capabilities, but more and more mobile devices are offering almost full-featured GPS functionalities. Google's Android provides direct access to its popular mapping tools. You will explore key programming APIs that power its mapping features.

What Google APIs Are Available for Mapping?

Before you start, all the necessary development tools, plug-ins, and sample code you need are from Google's own Android site at http://code.google.com/android/. It also provides simple-to-follow instructions to get you started. I recommend you do that first if you have not done so already.

The majority of the mapping APIs are within the package com.google.android.maps. At a minimum, two of them are required to embed the mapping tools inside your software: MapActivity and MapView. MapActivity manages the activity life cycle and services behind a MapView. MapView is an Android View that displays a map. Other than these APIs, you also have MapController to perform panning and zooming a map. MyLocationOverlay and Overlay are used to draw the user's info or objects on top of the map.

Discussing mapping without mentioning GPS is nearly impossible now because GPS has become one of the indispensable features most people would want from their mobile devices. The package android.location is included for GPS support. LocationManager is the most important API; it provides access to the system location services. The mapping and GPS APIs are the essential elements for building location-based services (LBS). You will pretty much cover all these APIs in a working example later.

Constructing a MapView by a MapActivity

You can construct a MapView only by a MapActivity because it depends on background threads that access the network and filesystem managed by MapActivity. That is to say, you should always start by extending your class from MapActivity as follows:

public class TutorialOnMaps extends MapActivity {
private static MapView mMapView;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);

// Get the map view from resource file
mMapView = (MapView)findViewById(R.id.mv);
}
}

While in the default resource file main.xml, you add in some on-screen buttons with transparent panels. To properly "inflate" the MapView, you use a well-known solution among Android developers to declare a MapView. Figure 1 shows the initial screen on the emulator with your on-screen buttons.









Figure 1: Initial map centered on a specified position

Panning, Zooming, and Toggling Map Modes

As was mentioned before, MapController is used to pan and zoom a map. You need to associate each button with a click listener. One example is as follows:

// Set up the button for "Pan East"
mPanE = (Button)findViewById(R.id.pane);
mPanE.setOnClickListener(new OnClickListener(){
// @Override
public void onClick(View arg0) {
panEast();
}
});

The panEast() function is implemented to pan a quarter of the current screen size. Other panning functionalities are done in a similar fashion. Actually, the map itself is already draggable if the device is equipped with a touch screen LCD. For non-touch-screen devices, you use these buttons or the arrow keys of the rocker pad to pan the map.

public void panEast() {
Point pt = new Point(
mMapView.getMapCenter().getLatitudeE6(),
mMapView.getMapCenter().getLongitudeE6()
+ mMapView.getLongitudeSpan() / 4);
mMapView.getController().centerMapTo(pt, true);
}

Zooming is done simply by increasing or decreasing the current zoom level through the controller.

public void zoomIn() {
mMapView.getController().zoomTo(mMapView.getZoomLevel() + 1);
}

To toggle the map display for viewing satellite imagery or traffic, you can enable it directly from MapView. The results are shown in Figures 2 and 3.

public void toggleSatellite() {
mMapView.toggleSatellite();
}

public void toggleTraffic() {
mMapView.toggleTraffic();
}

Figure 2: Satellite imagery

Figure 3: Traffic on satellite imagery

Retrieving Info in Current MapView

When a MapView is successfully created, lots of info pertaining to the current view can be queried. Here is a list of the main functions to help you better understand the current map status.

  • getMapCenter: Returns the longitude and latitude of the map center point

  • getLatitudeSpan and getLongitudeSpan: Return the span sizes of the current view's bounding rectangle

  • getZoomLevel and getMaxZoomLevel: Return the zoom level. Each zoom level is scaled by a factor of 2.

  • isSatellite: Checks whether the map view is currently in satellite imagery mode

  • isTraffic: Checks whether the map view is displaying traffic info

  • isShowMyLocation: Checks whether the current location is displayed on the map

  • isStreetView: Checks whether the map view is currently in street-view mode

Displaying Your Info on MapView

The base class Overlay represents an overlay that can be used to draw and display custom graphic objects on top of a map. Your code basically overrides the draw method by drawing a circle for the default position as well as enclosing its caption within a transparent rounded rectangle. Watch how I convert the position into screen coordinates with PixelCalculator, how I calculate the font metrics with Paint's measureText, and how I draw anti-aliased text with Paint's setAntiAlias.

// This is used draw an overlay on the map
protected class MyOverlay extends Overlay {
@Override
public void draw(Canvas canvas, PixelCalculator pc,
boolean shadow) {
super.draw(canvas, pc, shadow);

if (mDefCaption.length() == 0) {
return;
}

Paint p = new Paint();
int[] scoords = new int[2];
int sz = 5;

// Convert to screen coords
pc.getPointXY(mDefPoint, scoords);

// Draw point caption and its bounding rectangle
p.setTextSize(14);
p.setAntiAlias(true);
int sw = (int)(p.measureText(mDefCaption) + 0.5f);
int sh = 25;
int sx = scoords[0] - sw / 2 - 5;
int sy = scoords[1] - sh - sz - 2;
RectF rec = new RectF(sx, sy, sx + sw + 10, sy + sh);

p.setStyle(Style.FILL);
p.setARGB(128, 255, 0, 0);
canvas.drawRoundRect(rec, 5, 5, p);
p.setStyle(Style.STROKE);
p.setARGB(255, 255, 255, 255);
canvas.drawRoundRect(rec, 5, 5, p);

canvas.drawText(mDefCaption, sx + 5, sy + sh - 8, p);

// Draw point body and outer ring
p.setStyle(Style.FILL);
p.setARGB(88, 255, 0, 0);
p.setStrokeWidth(1);
RectF spot = new RectF(scoords[0] - sz, scoords[1] + sz,
scoords[0] + sz, scoords[1] - sz);
canvas.drawOval(spot, p);

p.setARGB(255, 255, 0, 0);
p.setStyle(Style.STROKE);
canvas.drawCircle(scoords[0], scoords[1], sz, p);
}
}

The overlay just created needs to be added to MapView's overlay controller before it goes into effect. Here is the code segment showing how you set up the overlay controller.

// Set up the overlay controller
mOverlayController = mMapView.createOverlayController();
MyOverlay mo = new MyOverlay();
mOverlayController.add(mo, true);

Figure 4: Label overlay on the map

Integrating with the Current GPS Location

android.location is the package that contains APIs allowing you to query the list of location providers as well as registering for periodic updates of current positions. Each location provider maintains the files under the /data/misc/location/ directory. Therefore, the default mock GPS provider "gps" can be found on the emulator in /data/misc/location/gps/. Different providers can generate the GPS files in different formats. More info can be found at Android's site in the references. Please note that, when you try to activate LocationManager the first time, it takes longer to initialize. Subsequent calls are immediately responsive. The following code segment gets the GPS position from the provider and then feeds it to MapView's controller.

private void centerOnGPSPosition() {
String provider = "gps";
LocationManager lm =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);

// NOTE: When LocationManager is called the first time,
// lat / lon is initialized to 0.
// Subsequent calls are fine and fast.
Location loc = lm.getCurrentLocation(provider);

mDefPoint = new Point((int)(loc.getLatitude() * 1000000),
(int)(loc.getLongitude() * 1000000));
mDefCaption = "GPS location";

mMapView.getController().animateTo(mDefPoint);
mMapView.getController().centerMapTo(mDefPoint, true);
}

Figure 5: GPS info overlay on the map

Conclusion

After this introduction, you are probably very excited to experiment with the mapping software and perhaps add in your own features. The entire software package is available for download from the references and you can simply import the project into Eclipse.

Android's mapping APIs are simple to use and yet powerful, with direct access to Google's already popular tools. As Android continues to grow with more advanced APIs, I believe more map features will be ported to this platform as well. Here are what I can think of if you would like to give it a try:

  • If you are an avid user of Google Maps, I am sure you will like its style of a draggable tool bar to control the map zooming and panning. You can go ahead and model after that user interface and functionalities. It will be an excellent addition.

  • What about adding an address search functionality, just like Google Maps can do through the web? Parsing the search results is really the key to this feature.

  • Usually, GPS needs a little while to initialize when it is taken to a new location, so you might get an ANR dialog (Application Not Responding) if the wait is longer than approximately five seconds. To make your software execute smoothly without any system interruption, you should create a child thread for this purpose and allow it to communicate with the main thread through a message handling scheme.

Sunday, August 22, 2010

Eclipse BIRT

1.1. Overview

Eclipse BIRT allows the creation of reports using various data sources.

These data sources define where the data is stored. Data sets defines the query for the report.

BIRT provides for example the following data sources:

  • Databases (via JDBC)

  • Text Files (cvs, XML)

  • WebServices (via WSDL-Files)

  • Scripting Data sources

In a Java program it is often convenient to use directly Java objects as a data source for reports. This article will focus on the usage of plain old Java objects (POJO) as data sources for BIRT reports.

1.2. Example

In this tutorial we will build a report which will show us information about the stock market. We get the information from a Java Object. The data will be displayed in a chart and in a table with detailed information. The result should look like this:

Installation

Use the Eclipse Update Manager to install BIRT. This package can be found in the Galileo update site under "Business Intelligence, Reporting and Charting" -> BIRT Framework.


Project

Create a new Java Project with the name "sawan.modi.birt.stocks".

Create a new report "stock_report.rptdesign" via File -> New -> Other -> Business Intelligence and Reporting -> Report.

The new report is displayed in the "Report Design" perspective.

Delete now everything except the report header. The result should look like the following.

Java classes

4.1. Overview

The report will display stock data. To demonstrate BIRT we use a Mock object for providing the data. The appendix demonstrates how to get real stock data via a Yahoo service.

4.2. Domain Model

Create package "sawan.modi.birt.stocks.model" and then the following class. This class will represent the domain model.

   
package sawan.modi.birt.stocks.model;

import java.util.Date;

/**
* Domain model for stock data
* @author Lars Vogel
*/

public class StockData {
private Date date;
private double open;
private double high;
private double low;
private double close;
private long volume;

public double getClose() {
return close;
}

public void setClose(double close) {
this.close = close;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

public double getHigh() {
return high;
}

public void setHigh(double high) {
this.high = high;
}

public double getLow() {
return low;
}

public void setLow(double low) {
this.low = low;
}

public double getOpen() {
return open;
}

public void setOpen(double open) {
this.open = open;
}

public long getVolume() {
return volume;
}

public void setVolume(long volume) {
this.volume = volume;
}

}

4.3. Data Access Object - Mock

Create the package "sawan.modi.birt.stocks.daomock" and then the following class.

   
package sawan.modi.birt.stocks.daomock;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import sawan.modi.birt.stocks.model.StockData;

public class StockDaoMock {

public List getStockValues(String company) {
// Ignore the company and always return the data
// A real implementation would of course use the company string
List history = new ArrayList();
// We fake the values, we will return fake value for 01.01.2009 -
// 31.01.2009
double begin = 2.5;
for (int i = 1; i <= 31; i++) {
Calendar day = Calendar.getInstance();
day.set(Calendar.HOUR, 0);
day.set(Calendar.MINUTE, 0);
day.set(Calendar.SECOND, 0);
day.set(Calendar.MILLISECOND, 0);
day.set(Calendar.YEAR, 2009);
day.set(Calendar.MONTH, 0);
day.set(Calendar.DAY_OF_MONTH, i);
StockData data = new StockData();
data.setOpen(begin);
double close = Math.round(begin + Math.random() * begin * 0.1);
data.setClose(close);
data.setLow(Math.round(Math.min(begin, begin - Math.random() * begin * 0.1)));
data.setHigh(Math.round(Math.max(begin, close) + Math.random() * 2));
data.setVolume(1000 + (int) (Math.random() * 500));
begin = close;
data.setDate(day.getTime());
history.add(data);
}
return history;
}
}

Datasource and Dataset

To use Java Objects (POJO's) as datasource in Eclipse BIRT you have to map the fields of your Java classes to JavaScript. This JavaScript is then used to access the Java Object.

5.1. The Datasource

The datasource connects your data with your report. Birt provides different types of datasources, we use the "Scripted Data Source". Go back to your stocks_report, use the "Report Design" perspective and select the "Data Explorer" View.

Tip

You have to select your report to display the content of the datasource view.

Create a new datasource, named "srcStocks" in your report.

5.2. The Dataset

The dataset defines the mapping for the datasource data and the birt data.

Create a new dataset named "dataSetSocks".

Press next and define the columns for your report.

5.3. JavaScript

Now we have to write the JavaScript for our dataset. Select the dataset and choose "open" as script. The open script is called before the first access to the dataset. We use this to load our List with the stock objects. To access a Java class you only have to use the following syntax: Packages.myJavaClass where myJavaClass is the full qualified Java class name.

Tip

In case you don't see the script please node that the editor for the report has several tab. One of it is labeled "source".

    
count = 0;

// Create instance of
// the GetStockHistory class
gsh = new Packages.sawan.modi.birt.stocks.daomock.StockDaoMock();

//Load the List

stock = gsh.getStockValues("Java");

Place the following coding in the fetch script.

    
if(count < stock.size()){
row["columnDate"] = stock.get(count).getDate();
row["columnOpen"] = stock.get(count).getOpen();
row["columnHigh"] = stock.get(count).getHigh();
row["columnLow"] = stock.get(count).getLow();
row["columnClose"] = stock.get(count).getClose();
row["columnVolume"] = stock.get(count).getVolume();
count++;
return true;
}

return false;

Check if your Script works by doubleclicking on the dataset -> Preview Result.

Display the data in a table

6.1. Overview

We will now display the data in a table.

6.2. Create a table

Switch from "Data Explorer" to the "Palette". Select the tab "Layout".

Drag and drop the table element on the report.

Define the following settings for the table.

Change back to the "Data Explorer". And drag and drop the dataset columns into the "Details row" of the table.

The result should look like the following.

Done. You can see a preview of the report if you click on the "Review" Tab. The result should look like the following:

Chart

7.1. Create a Chart

Switch back to the Palette, select a chart and drag and drop it on your report.

Choose the Line Chart with the standard settings.

Press Next and select your data set.

At the next step we have to assign the columns to the axis. We assign the date to the x axis and the open value to the y axis via drag and drop.

Define 5 series in total. Assign the columns to these series by dragging the column to the Sum sign.

Currently the x axis shows first the newest date. Reverse the x axis by you have to sort the data ascending. Press the highlighted button.

Go to the next tab and give titles to your columns. Hide the last one.

The display of the dates use a long format, we would like to change this. Perform the following and choose "short" as date type of the x axis

Change the display of the lines via the following.

Press finish to include your chart into your report.

Deploying in Tomcat

8.1. Overview

The following explains how to use BIRT reports in Tomcat. In general you have to:

  • Install the BIRT webviewer in Tomcat

  • Export your BIRT project into a .jar file

  • Move the .jar file to the birt-install-directory/WEB-INF/lib directory

  • Move the report design file into the root directory of birt in tomcat

  • Restart Tomcat

8.2. Install BIRT in Tomcat

We will use a standalone Tomcat 6.0 which we assume is already installed.

You need the "Deployment components of BIRT" http://download.eclipse.org/birt/downloads/ .

Copy the birt.war of this download into the Tomcat webappsfolder.

The Birt example should be available under http://localhost:8080/birt/.If you see something like this, your Tomcat an your Web Viewer should work correct.

8.3. Install your BIRT reports in Tomcat

To run your own reports you have to copy the .rptdesign file in the root of the birt folder in Tomcat. To make your Java classes available export your project into a jar file.

After that the jar file has to be copied to the Tomcat webapps/birt/WEB-INF/lib/ directory. Restart the Tomcat and navigate to your report.

Your report should be found under http://localhost:8080/birt/frameset?__report=stock_report.rptdesign

Deploying in Eclipse RCP application

9.1. BIRT deploying to an RCP Application

We can use the Birtviewer also in a local RCP Application, it isn't more than an browser view which shows a HTML Page generated by an integrated Webserver.

The following assumes that you are already familiar with Eclipse RCP development. See Eclipse RCP Tutorials in case you need an introduction.

Convert "sawan.modi.birt.stocks" to a plugin project, via right mouse click -> Configure -> "Convert to plug-in project".

Create an new plugin project "sawan.modi.birt.stocks.rcp". Select the template "RCP Application with a view".

Add the following plugins as dependendies to "sawan.modi.birt.stocks.rcp".

    
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Rcp
Bundle-SymbolicName: sawan.modi.birt.stocks.rcp; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: sawan.modi.birt.stocks.rcp.Activator
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.birt.report.viewer;bundle-version="2.5.0",
org.eclipse.birt.report.engine.emitter.html;bundle-version="2.5.0",
sawan.modi.birt.stocks;bundle-version="1.0.0",
org.eclipse.birt;bundle-version="2.5.0",
org.eclipse.birt.chart.ui;bundle-version="2.5.0",
org.eclipse.birt.chart.cshelp;bundle-version="2.5.0",
org.eclipse.birt.chart.device.extension;bundle-version="2.5.0",
org.eclipse.birt.chart.device.pdf;bundle-version="2.5.0",
org.eclipse.birt.chart.device.svg;bundle-version="2.5.0",
org.eclipse.birt.chart.device.swt;bundle-version="2.5.0",
org.eclipse.birt.chart.engine.extension;bundle-version="2.5.0",
org.eclipse.birt.chart.examples;bundle-version="2.5.0",
org.eclipse.birt.chart.reportitem;bundle-version="2.5.0",
org.eclipse.birt.chart.reportitem.ui;bundle-version="2.5.0",
org.eclipse.birt.chart.ui.extension;bundle-version="2.5.0",
org.eclipse.birt.core.script.function;bundle-version="2.5.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

Copy your report to "stock_report_rcp.rptdesign" into this new project. Open this report and change the "open" JavaScript to the following.

    
count = 0;
/*
* load and init data reader
* import Platform from org.eclipse.core.runtime
*/
importPackage(Packages.org.eclipse.core.runtime);

/* load bundle with POJOs and data loading class */

myBundle = Platform.getBundle("sawan.modi.birt.stocks");

/* load data reader class */
readerClass = myBundle.loadClass("sawan.modi.birt.stocks.daomock.StockDaoMock");

/* create new instance of DataReader */
readerInstance = readerClass.newInstance();


/* read data */
stock = readerInstance.getStockValues("Java");



Use this code as View.java.

    
package sawan.modi.birt.stocks.rcp;

import java.net.MalformedURLException;
import java.net.URL;

import org.eclipse.birt.report.viewer.utilities.WebViewer;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.Bundle;

public class View extends ViewPart {
public static final String ID = "sawan.modi.birt.stocks.rcp.view";

public void createPartControl(Composite parent) {
String path = "";

try {
Bundle bundle = Platform.getBundle("sawan.modi.birt.stocks.rcp");
path = new URL(bundle.getLocation()).getPath();
path = path .substring(6); //"file:/" 0 bis 5
path = path .replace("/", "\\");
path = path + "stock_report_rcp.rptdesign";
}
catch (MalformedURLException me){
System.out.println(me.getStackTrace());
}

Browser browser = new Browser(parent, SWT.NONE);
// Use the filename of your report
WebViewer.display(path, WebViewer.HTML, browser, "frameset"); }

/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}
}

Appendix: Using the Yahoo Service

10.1. Overview

What is an report without the correct data? Correct, nothing! We want to display the newest data of our favorite stock. Yahoo! Finance provides automatically generated CSV files of all stocks on the market. To get this we only have to download a file from this link http://ichart.finance.yahoo.com/table.csv?s=JAVA . It gives you a csv file with the history of the stock. As you can see, this "service" has the parameter s=JAVA with the name of the stock.

10.2. The Code

The following code is using the Apache HttpClient library. The Apache HttpClient library allow you to simulate a browser and send and receive HTTP data. Download the necessary libraries from http://hc.apache.org/

As the time of the writing HttpClient requires also additional libraries, currently they are described here: http://hc.apache.org/httpclient-3.x/dependencies.html

Download all required libraries and add them add them to your classpath.

Interesting for you is that we need the method updateHistory of the GetStocksHistory class with a string parameter(stock name) , which returns us a ArrayList.

   
package sawan.modi.stockticker;

import java.util.ArrayList;

public class StockHistory {
ArrayList m_stockHistory;

public StockHistory() {
m_stockHistory = new ArrayList();
}
public void add (StockData data) {
m_stockHistory.add(data);
}
}

   
package sawan.modi.stockticker;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;

public class GetStockHistory {

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.US);

NumberFormat nf = NumberFormat.getInstance(Locale.US);

NumberFormat pf = NumberFormat.getInstance(Locale.US);

StockHistory history = new StockHistory();

public ArrayList updateHistory(String company) {

Calendar from = Calendar.getInstance();
Calendar to = Calendar.getInstance();
to.set(2009, 01, 01);
from.set(2006, 01, 01);
System.out.println(to.toString());
StringBuffer url = new StringBuffer(
"http://ichart.finance.yahoo.com/table.csv" + "?s=");
url.append(company);

try {
HttpClient client = new HttpClient();
client.getHostConfiguration().setProxy("proxy", 8080); // Delete
// this Line
// if you
// don't use
// a proxy
client.getHttpConnectionManager().getParams().setConnectionTimeout(
5000);
System.out.println(url.toString());
HttpMethod method = new GetMethod(url.toString());
method.setFollowRedirects(true);
client.executeMethod(method);
BufferedReader in = new BufferedReader(new InputStreamReader(method
.getResponseBodyAsStream()));
// The first line is the header, ignoring
String inputLine = in.readLine();

while ((inputLine = in.readLine()) != null) {
if (inputLine.startsWith("<"))
continue;
String[] item = inputLine.split(",");
if (item.length < 6)
continue;

Calendar day = Calendar.getInstance();
day.setTime(df.parse(item[0].replace("\"", "")));
day.set(Calendar.HOUR, 0);
day.set(Calendar.MINUTE, 0);
day.set(Calendar.SECOND, 0);
day.set(Calendar.MILLISECOND, 0);
StockData data = new StockData();
data.setOpen(Double.parseDouble(item[1].replace(',', '.')));
data.setHigh(Double.parseDouble(item[2].replace(',', '.')));
data.setLow(Double.parseDouble(item[3].replace(',', '.')));
data.setClose(Double.parseDouble(item[4].replace(',', '.')));
data.setVolume(Long.parseLong(item[5]));
data.setDate(df.parse(item[0].replace("\"", "")));
history.add(data);
}
in.close();
return history.m_stockHistory;

} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}

}



public static void main(String[] args) {
// GetStockHistory gsh = new GetStockHistory();
// ArrayList sd = gsh.getNewHistory();
//
// for(int i=0;i < sd.size(); i++)
// {
// System.out.println(sd.get(i).getDate());
// }
}
}

Thank you

Thank you for practicing with this tutorial.

I maintain this tutorial in my private time. If you like the information please help me by using flatter or donating or by recommending this tutorial to other people.

Wednesday, August 18, 2010

5 Reasons Why Android Will Revolutionize The Mobile Industry

The “GPhone” rumor has been circulating the internet for ages, with technophiles getting excited at the prospect of a phone from the company who has simplified everything from internet search to advertising. Speculation had it that Google was producing a phone to rival the iPhone; surprising, since Google collaborated with Apple in creating the iPhone’s Google Maps application. Some analysts predicted that Google was working on a cheap, advertising-supported mobile phone that would allow users access to their online suite of office-like applications. Further speculation centered around Google’s involvement in the purchase of the 700 MHz radio communications spectrum.

AndroidLogo

On November 5, Google revealed its plans to the world. Instead of spearheading the initiative alone, Google formed the Open Handset Alliance, a group of mobile operators, hardware manufacturers, and software developers. Today, they officially released the SDK and announced a challenge where they plan to give out $10 million in awards to the best developers and apps.

The Open Handset Alliance will revolutionize mobile communication.

Here’s why.

1. It’s Time for a Change.
For years, mobile phone users have been stuck using phone carrier’s proprietary and ugly interfaces. Prior to the purchase of an iPhone, I had a Motorola Razr V3 and a Blackberry 7100t. Leaving my Mac every day and using the other phones was like torture. Android finally brings attractive design to anyone, regardless of what phone you’re using. Additionally, features typically only available on high-end phones, like mapping applications and threaded text messages, are available with Android. Sergey Brin’s demonstration goes further into Android’s design.

AndroidHome

Android’s Home Screen

2. Android Scales to Every Device
Android isn’t dependent on device hardware. Instead, it changes which features it offers. iPhone-like features would be reserved for individuals with pricier phones, but those with lesser-priced phones need not worry about lacking applications like mapping and address books.

3. It’s Supported by Dozens of Hardware Manufacturers.
Sure, the iPhone created a change throughout the mobile phone industry. To benefit from that trade, you must sign a two-year contract with AT&T, and you must use the iPhone. Android finally allows individuals to get the features they want in the phone they want, without a ridiculously high premium. Thus far, HTC, Motorola, LG, and Samsung have signed on to produce hardware that runs Android. This support ensures that Android, unlike the Symbian OS, has widespread adoption.

AndroidMaps

Android’s Mapping Application

4. It’s Open Source
The average consumer doesn’t have to know what open source is to benefit from it. The participation of thousands of volunteer programmers means the interface will get the upgrades it needs without the corporate oversight it doesn’t.

5. Third Party Development is Encouraged
iPhone developers are renegades, constantly playing a cat-and-mouse game with Apple until the official SDK is released in February 2008. Android, meanwhile, is taking the opposite approach, relying on third-party developers to make the platform viable for consumers. The Android Developer Challenge has more than ten million dollars to award to programmers who create new and innovative applications for the Android platform. Development on the iPhone has been remarkable, and there is no incentive for developers there. Imagine the success the Open Handset Alliance will have with Android when they encourage the development of new applications.

Monday, August 16, 2010

Android's First Phone

Several reputable sources (Forbes, InfoWorld) have published rumors that the HTC Dream will be the first Android Phone. The rumors seem to be from industry and company insiders who have spilled the beans. You wonder how many of these “leaks” are actually planned buzz from the public relations and/or marketing departments.

Most people are attributing the name “Dream” to the fact that the Android enabled handset will do whatever it’s users could ever imagine… and more. If you remember the “Magic Phone” promotional video created for Android in which young children discussed what THEIR phones of the future would do… you kind of get the idea:

Of course the adult-tempered version of believing in magic is believing in your dreams. So while a “Magic” branded phone might be in the plans for an OHA company, HTC settles for the more tempered “Dream” moniker. Its hard to underpromise and overdeliver with a name like “Dream” and our expectations are high - the first Android Phone should set an example for the possibilities and potential for which Android stands.

While the rumors seem to be solid, Samsung reportedly seems hard pressed to debunk the claims by pushing their own Android phone to market first. We just hope they aren’t rushing the phone simply to be first, because a poor first showing of Android enabled handsets could spell trouble. Hey, Samsung, why not wait a few months to perfect that gadget and slap the “Magic” name on it?

There aren’t many juicy details about the HTC Dream yet but with CTIA 2008 coming up we’re hoping some new news (redundant much?) pops up. Until then, feast your eyes on what little there is to know about the device that we’re all waiting for:

  • Large touchscreen with haptic feedback

  • Full QWERTY keypad

  • 5 inches long and 3 inches wide

  • Keypad that either slides or swivels open for easy typing/texting

  • Internet navigation controls below the touchscreen display

Google branded mobile phone













How many times does the distinction between an Android enabled phone and a gPhone need to be made before people get the hint? We’ve been through this before… but yet again, unfounded and baseless rumors about an apparent “gPhone” - a physical Google branded piece of hardware - have escaped the mouths of those who should know better.

Let me explain it to you:

When Google announced Android they said they were NOT announcing a gPhone but rather a device that would allow for hundreds of different gPhones meaning any hardware running Android could essentially be called a gPhone.

It is entirely within the realm of possibilities that Google will one day release HARDWARE called the gPhone, but any rumors you hear about that now are nothing more than confusions. Take for example the most recent suggestion that a gPhone is in the works:

Dan Cox of the Hollywood Reporter wrote an article saying, ““The trio of Google execs also used the opportunity to talk about the inroads the company is making with its own branded mobile phone as a replacement for the iPhone.”

Google branded mobile phone? Google branded mobile phone. Google branded mobile phone.

That is the only thing many people read/heard and they immediately pointed to this as juicy evidence that Google was in fact plotting to take over the world with a phone of their own! Its not so… folks… at least not yet. This is a simple misunderstanding of one reporter trying to explain Android phones, slipping up the semantics and everyone else reading between the lines that don’t exist.

So now you’ve got the spark for a rumor fire and TechCrunch poured on a couple barrels of gasoline, saying they have a reliable source who swears Google IS developing a gPhone and that it is being developed by Ammunition Group. TechCrunch is an incredibly reliable source themselves and Arrington and his gang get the rumors right more often than not, which explains the storm of “The gPhone Lives!” posts made around the world shortly after.

Phandroid is here to tell you that you should NOT expect a gPhone anytime soon and we have an incredibly reliable source named LOGIC.

Google wants desperately for Android to become a success and to make this happen they MUST have the support of their OHA partners. There is no WAY that Google would release a Google Branded gPhone, stealing the spotlight of the OHA whom Google would begin competing with directly.

Hate to tell ya, Betty but it ain’t gonna happen.

Apple building the iPhone was not a stretch… it was a shift into a very similar, parallel market. They already built hardware. They begun dominating consumer electronics with their MP3 player. The iPhone was the logical next step.

Google doesn’t do hardware… Google does software. That’s why Android was the next, logical step - it makes perfect sense. Plus, Google wouldn’t actually be MAKING their own gPhone, would they? Nope. That’s why the Ammunition Group rumors seem somewhat logical. Much like Garmin is contracting a seperate company to create their upcoming phone - the Garmin Nuvifone - Google would be doing the same.

So whats the point? Is it really a gPhone if someone else is making it? Uhhh, thats what an Android phone is anyways, what is the point in branding the hardware as Google’s when we know Google doesn’t make it? Would Google design it? This is all getting very confusing…

Google COULD release a gPhone, sure. But what would be the motivation? Competing in the hardware business seems like much too far of a stretch in and of itself, at least in the short term. How would releasing a phone align with Google’s current strengths and goals?

Google’s current model seems to be providing products and services for free and monetizing the usage with targeted and relevant advertising. So what if Google had a company like Ammunition Group create a gPhone, customers would pay for it but service was 100% free and subsidized by built-in advertising?

THAT would align with Google’s core goals MUCH better than these other rumors. I doubt Google has much intentions of making 1 gPhone device to go head to head with the iPhone when not only do they have NO experience with hardware, but their much more experienced OHA brothers and sisters have had a difficult time competing with the iPhone as well.

Who really knows what will happen and if/when an actual gPhone will surface? Regardless, that shouldn’t be the focus… for us OR Google. The focus should be making sure Android -as a PLATFORM - is successful. And after that, perhaps discussion about some kind of gPhone will have merit.

But until we have something more decisive and Android is actually on the market, can we please put these gPhone rumors to rest? Afterall we still don’t have any real information on the HTC Dream gPhone which is supposed to be the first gPhone.

Thursday, August 12, 2010

Eclipse Zest

1.1. Overview

Eclipse Zest is a visualization toolkit for graphs. It is based on SWT / Draw2D. Zest supports the viewer concept from JFace and therefore allows to separate the model from the graphical representation of the model. This article assumes that you are already familiar with Eclipse RCP Tutorials .

1.2. Components

Eclipse Zest has the following components:

  • GraphNode - Node in the graph with the properties

  • GraphConnections - Arrow / Edge of the graph which connections to two nodes

  • GraphContainer - Use for a graph within a graph

  • Graph - holds the other elements (nodes, connections, container)

1.3. Layout Manager

Eclipse Zest provides graph layout managers. A graph layout manager determines how the nodes (and the arrows) of a graph are arranged on the screen. The following layout managers are provided:

Table 1. Layout Manager

Layout Manager Description
TreeLayoutAlgorithmGraph is displayed in the form of a vertical tree
HorizontalTreeLayoutAlgorithmSimilar to TreeLayoutAlgorithm but layout is horizontal
RadialLayoutAlgorithmRoot is in the center, the others nodes are placed around this node
GridLayoutAlgorithm
SpringLayoutAlgorithmLayout the graph so that all connections should have approx. the same length and that the edges overlap minimal
HorizontalShiftMoves overlapping nodes to the right
CompositeLayoutAlgorithmCombines other layout algorithms, for example HorizontalShift can be the second layout algorithm to move nodes which were still overlapping if another algorithm is used

1.4. Filter

You can also define filters (org.eclipse.zest.layouts.Filter) on the layout managers via the method setFilter(filter). This defines which nodes and connections should be displayed. The filter receives an LayoutItem, the actual graph element can be received with the method getGraphData().

Installation

Use the Eclipse IDE Tuorials to install the "Graphical Editing Framework Zest Visualization Toolkit". You may have to unflag "Group items by category" to see Zest.

This Tutorials was all installation procedure.

Your first Zest Project

3.1. Getting started

Create a new Eclipse RCP application "sawan.modi.zest.first". Use the "Eclipse RCP with a view" as a template. Add "org.eclipse.zest.core" and "org.eclipse.zest.layouts" as dependencies to your MANIFEST.MF.

Change the coding of "View.java" to the following. This coding creates a simple graph and connects its elements.

    
package sawan.modi.zest.first;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphConnection;
import org.eclipse.zest.core.widgets.GraphNode;
import org.eclipse.zest.core.widgets.ZestStyles;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;

public class View extends ViewPart {
public static final String ID = "sawan.modi.zest.first.view";
private Graph graph;
private int layout = 1;

public void createPartControl(Composite parent) {
// Graph will hold all other objects
graph = new Graph(parent, SWT.NONE);
// Now a few nodes
GraphNode node1 = new GraphNode(graph, SWT.NONE, "Jim");
GraphNode node2 = new GraphNode(graph, SWT.NONE, "Jack");
GraphNode node3 = new GraphNode(graph, SWT.NONE, "Joe");
GraphNode node4 = new GraphNode(graph, SWT.NONE, "Bill");
// Lets have a directed connection
new GraphConnection(graph, ZestStyles.CONNECTIONS_DIRECTED, node1,
node2);
// Lets have a dotted graph connection
new GraphConnection(graph, ZestStyles.CONNECTIONS_DOT, node2, node3);
// Standard connection
new GraphConnection(graph, SWT.NONE, node3, node1);
// Change line color and line width
GraphConnection graphConnection = new GraphConnection(graph, SWT.NONE,
node1, node4);
graphConnection.changeLineColor(parent.getDisplay().getSystemColor(
SWT.COLOR_GREEN));
// Also set a text
graphConnection.setText("This is a text");
graphConnection.setHighlightColor(parent.getDisplay().getSystemColor(
SWT.COLOR_RED));
graphConnection.setLineWidth(3);
graphConnection.addListener(SWT.SELECTED, new Listener() {

@Override
public void handleEvent(Event event) {
System.out.println("Selected");
}

});
graph.setLayoutAlgorithm(new SpringLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING), true);

}

public void setLayoutManager() {
switch (layout) {
case 1:
graph.setLayoutAlgorithm(new TreeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING), true);
layout++;
break;
case 2:
graph.setLayoutAlgorithm(new SpringLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING), true);
layout = 1;
break;

}

}

/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}
}

Run you application and you should see the graph.

3.2. Select layout manager via a command

Create a command with the following default handler "sawan.modi.zest.first.handler.ChangeLayout" which will change the layout for the graph. Assign the command to the menu.

    
package sawan.modi.zest.first.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.handlers.HandlerUtil;

import sawan.modi.zest.first.View;

public class ChangeLayout extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IViewPart findView = HandlerUtil.getActiveWorkbenchWindow(event)
.getActivePage().findView("sawan.modi.zest.first.view");
View view = (View) findView;
view.setLayoutManager();
return null;
}

}

Run your application, if you select your command the layout of your view should change.

Zest and JFace

JFace provides viewers to encapsulate the data from the presentation. For an introduction to JFace viewer please see Eclipse JFace Table Viewer. A JFace viewer requires a content provider and a label provider. Zest provides as a viewer the class "GraphViewer". Content provider in Zest are either based on the connections or on the nodes.

Standard Zest Content providers are:

Table 2. Zest JFace Content Provider

Content ProviderDescription
IGraphContentProviderBased on the connections. The connections contain the information which nodes they refer to. Cannot display nodes without connections.
IGraphEntityContentProviderBased on the Node which contain the information about which relationship they have. These relationship are available in the label provider as EntityConnectionData objects.
IGraphEntityRelationshipContentProvider Node based, the content provider defines getRelationShips(sourceNode, destinationNode) which determines the connections. The advantages compared with IGraphEntityContentProvider is that you decide which objects you return.

As label provider Zest can use the standard JFace interface ILabelProvider (implemented for example by the class LabelProvider) or the Zest specific IEntityStyleProvider.

Zest and JFace Example

5.1. Create Project

Create a new RCP application "sawan.modi.zest.jface". Use the " RCP application with a view" as a template. Add the zest dependencies to your MANIFEST.MF. Change the Perspective.java to the following (we don't want a standalone view).

    
package sawan.modi.zest.jface;

import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;

public class Perspective implements IPerspectiveFactory {

public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);
layout.setFixed(true);

layout.addView(View.ID, IPageLayout.LEFT, 1.0f, editorArea);
}

}

5.2. Model

Create the following model. Please note that the model can be anything as long as you can logically convert it into a connected Graph.

    
package sawan.modi.zest.jface.model;

import java.util.ArrayList;
import java.util.List;

public class MyNode {
private final String id;
private final String name;
private List connections;

public MyNode(String id, String name) {
this.id = id;
this.name = name;
this.connections = new ArrayList();
}

public String getId() {
return id;
}

public String getName() {
return name;
}

public List getConnectedTo() {
return connections;
}

}

    
package sawan.modi.zest.jface.model;

public class MyConnection {
final String id;
final String label;
final MyNode source;
final MyNode destination;

public MyConnection(String id, String label, MyNode source, MyNode destination) {
this.id = id;
this.label = label;
this.source = source;
this.destination = destination;
}

public String getLabel() {
return label;
}

public MyNode getSource() {
return source;
}
public MyNode getDestination() {
return destination;
}

}


Also build this class which provides an instance of the data model.

    
package sawan.modi.zest.jface.model;

import java.util.ArrayList;
import java.util.List;

public class NodeModelContentProvider {
private List connections;
private List nodes;

public NodeModelContentProvider() {
// Image here a fancy DB access
// Now create a few nodes
nodes = new ArrayList();
MyNode node = new MyNode("1", "Hamburg");
nodes.add(node);
node = new MyNode("2", "Frankfurt");
nodes.add(node);
node = new MyNode("3", "Berlin");
nodes.add(node);
node = new MyNode("4", "Munich");
nodes.add(node);
node = new MyNode("5", "Eppelheim");
nodes.add(node);
node = new MyNode("6", "Ahrensboek");
nodes.add(node);

connections = new ArrayList();
MyConnection connect = new MyConnection("1", "1", nodes.get(0),
nodes.get(1));
connections.add(connect);
connect = new MyConnection("2", "2", nodes.get(0), nodes.get(4));
connections.add(connect);
connect = new MyConnection("3", "3", nodes.get(2), nodes.get(1));
connections.add(connect);
connect = new MyConnection("4", "3", nodes.get(1), nodes.get(3));
connections.add(connect);

// Because we are lasy we save the info about the connections in the
// nodes

for (MyConnection connection : connections) {
connection.getSource().getConnectedTo()
.add(connection.getDestination());
}
}

public List getNodes() {
return nodes;
}
}

5.3. Providers

Create the following content and label providers.

    
package sawan.modi.zest.jface.zestviewer;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.zest.core.viewers.IGraphEntityContentProvider;

import sawan.modi.zest.jface.model.MyNode;

public class ZestNodeContentProvider extends ArrayContentProvider implements IGraphEntityContentProvider {

@Override
public Object[] getConnectedTo(Object entity) {
if (entity instanceof MyNode) {
MyNode node = (MyNode) entity;
return node.getConnectedTo().toArray();
}
throw new RuntimeException("Type not supported");
}
}

    
package sawan.modi.zest.jface.zestviewer;

import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.zest.core.viewers.EntityConnectionData;

import sawan.modi.zest.jface.model.MyConnection;
import sawan.modi.zest.jface.model.MyNode;

public class ZestLabelProvider extends LabelProvider {
@Override
public String getText(Object element) {
if (element instanceof MyNode){
MyNode myNode = (MyNode) element;
return myNode.getName();
}
if (element instanceof MyConnection){
MyConnection myConnection = (MyConnection) element;
return myConnection.getLabel();
}

if (element instanceof EntityConnectionData){
return "";
}
throw new RuntimeException("Wrong type: " + element.getClass().toString() );
}
}

5.4. View

Change the view to the following.

    
package sawan.modi.zest.jface;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.ZoomContributionViewItem;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;

import sawan.modi.zest.jface.model.NodeModelContentProvider;
import sawan.modi.zest.jface.zestviewer.ZestLabelProvider;
import sawan.modi.zest.jface.zestviewer.ZestNodeContentProvider;

public class View extends ViewPart implements IZoomableWorkbenchPart {
public static final String ID = "sawan.modi.zest.jface.view";
private GraphViewer viewer;

public void createPartControl(Composite parent) {
viewer = new GraphViewer(parent, SWT.BORDER);
viewer.setContentProvider(new ZestNodeContentProvider());
viewer.setLabelProvider(new ZestLabelProvider());
NodeModelContentProvider model = new NodeModelContentProvider();
viewer.setInput(model.getNodes());
LayoutAlgorithm layout = setLayout();
viewer.setLayoutAlgorithm(layout, true);
viewer.applyLayout();
fillToolBar();
}

private LayoutAlgorithm setLayout() {
LayoutAlgorithm layout;
// layout = new
// SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
layout = new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// HorizontalTreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new
// RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
return layout;

}

/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}

private void fillToolBar() {
ZoomContributionViewItem toolbarZoomContributionViewItem = new ZoomContributionViewItem(
this);
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().add(toolbarZoomContributionViewItem);

}

@Override
public AbstractZoomableViewer getZoomableViewer() {
return viewer;
}
}

The result should look like the following.

5.5. Filter

You can define a filter on the viewer via setFilters();

For example define the following filter.

    
package sawan.modi.zest.jface.zestviewer;

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;

import sawan.modi.zest.jface.model.MyNode;

public class NodeFilter extends ViewerFilter {

@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {

if (element instanceof MyNode) {
MyNode node = (MyNode) element;
return node.getName().toLowerCase().contains("a");

}
return true;
}

}

Apply the filter to the view to filter all elements.

    
package sawan.modi.zest.jface;

import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.zest.core.viewers.AbstractZoomableViewer;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IZoomableWorkbenchPart;
import org.eclipse.zest.core.viewers.ZoomContributionViewItem;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;

import sawan.modi.zest.jface.model.NodeModelContentProvider;
import sawan.modi.zest.jface.zestviewer.NodeFilter;
import sawan.modi.zest.jface.zestviewer.ZestLabelProvider;
import sawan.modi.zest.jface.zestviewer.ZestNodeContentProvider;

public class View extends ViewPart implements IZoomableWorkbenchPart {
public static final String ID = "sawan.modi.zest.jface.view";
private GraphViewer viewer;

public void createPartControl(Composite parent) {
viewer = new GraphViewer(parent, SWT.BORDER);
viewer.setContentProvider(new ZestNodeContentProvider());
viewer.setLabelProvider(new ZestLabelProvider());
NodeModelContentProvider model = new NodeModelContentProvider();
viewer.setInput(model.getNodes());
LayoutAlgorithm layout = setLayout();
viewer.setLayoutAlgorithm(layout, true);
viewer.applyLayout();
NodeFilter filter = new NodeFilter();
ViewerFilter[] filters = new ViewerFilter[1];
filters[0]= filter;
viewer.setFilters(filters);
fillToolBar();
}

private LayoutAlgorithm setLayout(){
LayoutAlgorithm layout;
// layout = new SpringLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
layout = new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new HorizontalTreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
// layout = new RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
return layout;

}

/**
* Passing the focus request to the viewer's control.
*/
public void setFocus() {
}

private void fillToolBar() {
ZoomContributionViewItem toolbarZoomContributionViewItem = new ZoomContributionViewItem(this);
IActionBars bars = getViewSite().getActionBars();
bars.getMenuManager().add(toolbarZoomContributionViewItem);

}

@Override
public AbstractZoomableViewer getZoomableViewer() {
return viewer;
}
}

Tip

Tips and Tricks

6.1. Disable that nodes can be moved manually

Per default the user can move the nodes in Zest. To disable this you have to extend the Graph.

    
package sawan.modi.zest.movenodes.graph;

import org.eclipse.draw2d.SWTEventDispatcher;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.zest.core.widgets.Graph;

public class NonMovableGraph extends Graph {

public NonMovableGraph(Composite parent, int style) {
super(parent, style);
this.getLightweightSystem().setEventDispatcher(
new SWTEventDispatcher() {
public void dispatchMouseMoved(
org.eclipse.swt.events.MouseEvent me) {
// Doing nothing
}
});
}

}

The usage is demonstrated in project "sawan.modi.zest.movenodes".

PDE Dependency Visualization

A good and extensive example for the usage of Zest for visualization of plug-in dependencies is the PDE Incubator Dependency Visualization.

Thank you

Thank you for practicing with this tutorial.

I maintain this tutorial in my private time. If you like the information please help me by donating or by recommending this tutorial to other people.

Tuesday, August 10, 2010

Top 50 Applications

As you may have heard, the results from Android Developer Challenge Part 1, Round 1 were announced to all the participants late last week. We're still working on pulling together a more extensive listing for each application that made it into the top 50, but in the spirit of releasing early and often, here's a list containing the name of the application and its author(s):

  • AndroidScan - Jeffrey Sharkey
  • Beetaun - Sergey Gritsyuk and Dmitri Shipilov
  • BioWallet - Jose Luis Huertas Fernandez
  • BreadCrumbz - Amos Yoffe
  • CallACab - Konrad Huebner and Henning Boeger
  • City Slikkers - PoroCity Media and Virtual Logic Systems
  • Commandro - Alex Pisarev, Andrey Tapekha
  • Cooking Capsules - Mary Ann Cotter and Muthuselvam Ramadoss
  • Diggin - Daniel Johansson, Aramis Waernbaum, Andreas Hedin
  • Dyno - Virachat Boondharigaputra
  • e-ventr - Michael Zitzelsberger
  • Eco2go - Taneem Talukdar, Gary Pong, Jeff Kao and Robert Lam
  • Em-Radar - Jack Kwok
  • fingerprint - Robert Mickle
  • FreeFamilyWatch - Navee Technologies LLC
  • goCart - Rylan Barnes
  • GolfPlay - Inizziativa Networks
  • gWalk - Prof. Dr.-Ing. Klaus ten Hagen, Christian Klinger, Marko Modsching, Rene Scholze
  • HandWx - Weathertop Consulting LLC
  • IMEasy - Yan Shi
  • Jigsaw - Mikhail Ksenzov
  • JOYity - Zelfi AG
  • LifeAware - Gregory Moore, Aaron L. Obrien, Jawad Akhtar
  • Locale - Clare Bayley, Christina Wright, Jasper Lin, Carter Jernigan
  • LReady Emergency Manager - Chris Hulls, Dilpreet Singh, Luis Carvalho, Phuong Nguyen
  • Marvin - Pontier Laurent
  • Mobeedo - Sengaro GmbH
  • Multiple Facets Instant Messenger - Virgil Dobjanschi
  • MyCloset - Mamoru Tokashiki
  • PedNav - RouteMe2 Technologies Inc.
  • Phonebook 2.0 - Voxmobili
  • PicSay - Eric Wijngaard
  • PiggyBack - Christophe Petit and Sebastien Petit
  • Pocket Journey - Anthony Stevens and Rosie Pongracz
  • Rayfarla - Stephen Oldmeadow
  • Safety Net - Michael DeJadon
  • SocialMonster - Ben Siu-Lung Hui and Tommy Ng
  • SplashPlay
  • Sustain- Keeping Your Social Network Alive - Niraj Swami
  • SynchroSpot - Shaun Terry
  • Talkplay - Sung Suh Park
  • Teradesk - José Augusto Athayde Ferrarini
  • The Weather Channel for Android - The Weather Channel Interactive Inc.
  • TuneWiki - TuneWiki Inc.
  • Wikitude-the Mobile Travel Guide - Philipp Breuss
  • Writing Pad - ShapeWriter Inc

Those of you following along carefully at home (or who bothered to read this far) will notice that there's only 46 in this list. 4 winners opted to continue their efforts in secret and so while we congratulate them too, we can't list them here.

Regardless, congratulations to all those who made it this far!