gamelan
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




See the Winners!


Developer Jobs

Be a Commerce Partner
Compare Prices
Disney World Tickets
PDA Phones & Cases
Domain registration
Home Improvement
GPS
Logo Design
Calling Cards
Corporate Gifts
Promos and Premiums
Imprinted Promotions
Laptops
Cell Phones
KVM Switches

 
Biz Resources
Network Security Services
VoIP
CRM Software

Access FREE HP Server Solutions Tools:
Access FREE HP Server Solutions Tools:
Whitepaper:
Continuous Real-time Data Protection and Disaster Recovery

Whitepaper:
Virtualization--It's Not Just for Enterprises Anymore

Whitepaper:
Rightsizing Blades for the Mid-market

Whitepaper:
VMware Infrastructure 3--Planning


  Rethinking the Datacenter
Sponsored by HP
Today's datacenters need to increase utilization, get control over power and cooling costs, and align with business objectives. Download this eBook to learn about the challenges facing the data center in a world where digital information is growing at a torrid pace and costs are being held in check. Learn more. »
 
  Putting the Green into IT
Sponsored by HP
Electricity use in data centers is skyrocketing, sending energy bills through the roof, creating environmental concerns and generating negative publicity. "Going Green" means looking to technologies like virtualization, energy-efficient chips and racks, and implementing policies that extend beyond the data center. Learn more. »
 
  Managing the Modern Network
Sponsored by HP
In a global economy where information crosses the globe in an instant, and where Web-based applications power business, it's more important than ever to ensure your network is safe from threats and optimized to deliver the data your business needs. »
 
  Evaluating Software as a Service for Your Business
Sponsored by Webroot
Is Software as a Service just hype, or is something really going on here? See if your company can benefit as SaaS tries to change the face of the enterprise. »
 
  Is Your Disaster Recovery Plan Good Enough?
Sponsored by HP
Preparing for a disaster is more often than not part of the storage planning process, and it is one of the most difficult tasks, since it includes local hardware and software, networking equipment, and a test plan. Learn how to get disaster recovery right. »
 
Developer News -
SaaS Tool Offers Custom Database Development    May 9, 2008
Microsoft’s Automated Agent: Can We Talk?    May 7, 2008
Borland Finally Sells CodeGear    May 7, 2008
Red Hat Heads For The JON 2.0    May 7, 2008
Free Tech Newsletter -

Project Management Guide: Developing a Web Site. Best Practices, Tips and Strategies. Download Exclusive eBook Now.

Brew & J2ME: Let's Be Friends! Part 2
By Radu Braniste

This is the second article in a series targeting mobile developers more accustomed to J2ME than BREW or BREW developers interested in lighter and more efficient code production. The last time[1], we presented a basic framework largely inspired by a Java GUI model easing the task of writing high-level interface code in BREW. For this installment, the framework was extended and refactored to properly handle real-life cases.

A basic example of multi-control screens allows us a detailed explanation of the inner mechanisms of the framework.

An Example

We start by directly presenting an example of a two-screens application:

class BJApp : public IMidlet
{
  typedef ListImpl<BJApp> List;
  typedef DateCtlImpl<BJApp> DateCtl;
  typedef List Command;
private:
  void BuildDateCtl(int year)
  {
    DateCtl* l = 
       (DateCtl*) getRegistered("DATE_CTL");
    if (!l)
    {
      l = DateCtl::createDateCtl("DATE_CTL", 
                                 this);
      if (!l) return ;
      Command* c = BuildDateCtlCommand(1);
      if (!c) return ;
      l->setScreen(8,20,110,60);
      l->installEventHandler(dateCtlHdl);
      l->installEventHandler(dateCtlHdl, 
                             TAB);
      l->setTitle("Select a Date");
      l->addDisplayable(c);
      l->addDisplayable(l);
    }
    l->setDate(year,12,31);
    l->setCurrent();
  }
  bool dateCtlHdl( DateCtl* l) 
  {
    l->setCurrentAt(0);
    return true;
  }
  Command* BuildDateCtlCommand(int ix)
  {
    Command* c = 
      (Command*) getRegistered("DATE_CTL_COMMAND");
    if (c)
      return c;
    c = Command::createCommand("DATE_CTL_COMMAND", 
                               this);
    if (!c) return 0;
    c->installEventHandler(dateCtlCmdHdl);
    c->installEventHandler(dateCtlCmdTabHdl,
                              TAB);
    WString a[] = {"Nowhere","Back"};
    c->append(a,SIZE_OF(a));
    c->setSelection(ix);
    return c;
  }
  bool dateCtlCmdTabHdl( Command* l)
  {
    setActive("DATE_CTL");
    return true;
  }
  bool dateCtlCmdHdl( Command* l)
  {
    int pos = l->getSelection();
    if (pos == INDEX_OUT_OF_BOUNDS)
      return false;
    if (pos == 1)
    {
      Command* c = 
        (Command*)getRegistered("DATE_COMMAND");
      if (!c) return false;
      c->setSelection(0);
      BuildInputList(0, "INPUT_LIST_0");
    }
    return true;
  }
  void BuildInputList(int focus, 
                      const String& lst)
  {
    List* l = (List*) getRegistered(lst);
    if (!l)
    {
      l = List::createList(lst, this);
      if (!l) return;
      Command* c = BuildDateCommand(0);
      if (!c) return;
      l->installEventHandler(inputListHdl);
      l->installEventHandler(inputListTabHdl,
                             TAB);
      l->setTitle("Start");
      l->setFullScreen(120);
      l->addDisplayable(c);
      l->addDisplayable(l);
    }
    l->setCurrentAt(focus);
  }
  bool inputListHdl( List* l)
  {
    int pos = l->getSelection();
    if (pos == INDEX_OUT_OF_BOUNDS)
      return false;
    Command* c = 
      (Command*)getRegistered("DATE_COMMAND");
    if (!c)
      return false;
    if (c->getSelection() == 0)
      BuildDateCtl(2003);
    else if (c->getSelection() == 1)
      BuildDateCtl(2004);
    else
      BuildDateCtl(9999);
    return true;
  }
  bool inputListTabHdl( List* l)
  {
    l->setCurrentAt(0);
    return true;
  }
  Command* BuildDateCommand(int ix)
  {
    Command* c = 
       (Command*) getRegistered("DATE_COMMAND");
    if (c)
      return c;
    c = Command::createCommand("DATE_COMMAND", 
                               this);
    if (!c) return 0;
    c->installEventHandler(dateCmdTabHdl);
    c->installEventHandler(dateCmdTabHdl,
                           TAB);
    WString a[] = {"2003","2004" };
    c->append(a,SIZE_OF(a));
    c->setSelection(ix);
    return c;
  }
  bool dateCmdTabHdl( Command* l)
  {
    int pos = l->getSelection();
    return dateManipulation(pos);
  }
  bool dateManipulation(int pos)
  {
    switch (pos)
    {
      case 0:
      {
        String s("INPUT_LIST_0");
        List* k = (List*) getRegistered(s);
        if (k && !k->size())
        {
          WString a[] = {"Conference","DevDay"};
          k->append(a,SIZE_OF(a));
        }
        BuildInputList(1,s);
        break;
      }
      case 1:
      {
        String s("INPUT_LIST_1");
        BuildInputList(1,s);
        List* k = (List*) getRegistered(s);
        if (k && !k->size())
        {
          WString a[] = {"Training","Vacation"};
          k->append(a,SIZE_OF(a));
        }
        BuildInputList(1,s);
        break;
      }
      default:
        return false;
    }
    return true;
  }
public:
  virtual bool onStart()
  {
    setColor(CLR_SYS_ITEM_SEL , 0,0, 255);
    setColor(CLR_USER_TEXT , 0,0, 255);
    BuildInputList(0, "INPUT_LIST_0");
    return true;
  }
};

All the widgets in this example register for EVT_CTL_TAB and EVT_COMMAND events and behave like singletons registered and retrieved by name. All the UI logic is conveniently implemented inside the event handlers.

The application starts in onStart() by creating a List (INPUT_LIST_0) and a Command (DATE_COMMAND).

INPUT_LIST_0 hosts both widgets. EVT_CTL_TAB switches the focus and EVT_COMMAND implements some date-related logic and switches the screen to DATE_CTL via BuildDateCtl.

DATE_COMMAND deals both events via the same handler (dateCmdTabHdl). Based on selection, a new List can be created (INPUT_LIST_1) associated with DATE_COMMAND and given focus, or the focus can be moved back to INPUT_LIST_0.

BuildDateCtl creates an association between DATE_CTL and DATE_CTL_COMMAND with simple UI logic—the "back" command brings the app back to the INPUT_LIST_0 state.

And Some Explanation...

Our application deals with three GUI widgets: List, Command, and DateCtl. Actually, List and Command are variations of the same basic type—ListImpl—but serve different purposes. All applications inherit from IMidlet and can override onStart(), onStop(), onResume(), and onSuspend() callbacks. IMidlet now exhibits a naïve setColor() functionality.

There is a new mechanism used to implement widget persistency. onStart() creates a list called "INPUT_LIST_0" inside BuildInputList. Widgets now can be retrieved by name (in the previous implementation it was possible by index only), eliminating the need of declaring them explicitly at the class scope:

List* l = (List*) getRegistered(lst);

A widget is always created by using the "Named Constructor Idiom"[2], using either createXXX(const String& name, T* t) or createXXX(T* t). The first form allows later retrieval by name and was used extensively in the example. Please note the change in method names: createXXX() now replaces getXXX().

Event handling was generalized. There is a new method replacing setCbk()—void installEventHandler(F f, LIST_EVT evt). Basically, this method registers one callback per event, as defined in the LIST_EVT definition:

typedef  enum  {TAB,CMD, EVT_SIZE} LIST_EVT;
// EVT_SIZE is a guard value
//currently only CMD & TAB supported
//CMD = EVT_COMMAND
//TAB = EVT_CTL_TAB

f is an application method.

Implementation detail: Event handling was packaged as a stand-alone service in

template <class T, class F>
class EvtHandler;

A Command (DATE_COMMAND) is created in BuildDateCommand(). A Command is a soft key wrapper and, from a BREW perspective, is a minor specialization of List.

And now comes the most interesting part: assembling widgets into richer displays. Our UI hierarchy slightly resembles J2ME—there are Displayables on top, Screens inheriting from Displayables (this is a new addition to the hierarchy), and finally Commands, Lists, and other widgets inheriting from Screens. From a BREW point of view, an IDisplayable is equivalent to an IControl. Screen adds the container capability—every Screen is capable of hosting any other Controls (IDisplayable), including itself.

class Screen: public IDisplayable
{
public:
  void addDisplayable(IDisplayable* d);
  void setDisplayableAt(IDisplayable* d, UINT pos);
  void setCurrent(bool isRedrawing = true);
  void setCurrentAt(UINT mainDisplayable, bool isRedrawing = true);
  virtual ~Screen()
  {}
protected:
  Screen(IMidlet* m):IDisplayable(m->getDisplayableRegistry()),
                                  m_(m)
  {}
private:
  void setCurrentImpl(IDisplayable* displayable, 
                      bool isRedrawing );
  void redrawDisplayables();
private:
  DISPLAYABLES displayables_;
  IMidlet* m_;
};

Widgets are implemented on top of Screens, making very flexible arrangements possible. For example, a Command can host a List or the other way around. The following code better explains the concept:

List*    l = List::createList("lst", this);
Command* c = Command::createCommand("cmd", this);
  l->addDisplayable(c);
  l->addDisplayable(l);
  l->setCurrentAt(0);

List l hosts both a Command c and itself (l) and at the very end everything is rendered on the screen and c is made active (setCurrentAt(0) ). setCurrentAt(index) uses a zero-based index notation, but a string (name)-based implementation is equally possible—with a slight performance penalty. A shortcut (setCurrent()) is available—setting the focus on the container directly.

As mentioned in the previous article, indexes are auto generated, considerably simplifying items' manipulation. Manipulation of indexes was packaged in a specialized class—Indexes—used by all interested parties (mainly widgets):

class Indexes
{
public:
  void append(int id);
  int size() const;
  template <class P>
  int getIDImpl(int ix);
private:
  BrewVector<int> indxs_;
};

Another useful mechanism was added in IMidlet. As mentioned before, setCurrent() and setCurrentAt() have dual functionality: They both redraw the screen and set the active widget inside a composite view. Internally, setCurrent() and setCurrentAt() use IMidlet::setActive(), whose unique role is to save a reference to the active IDisplayable.

IMidlet::setActive() can be used when no screen redrawing is necessary, for example:

bool dateCtlCmdTabHdl( Command* l)
  {
    setActive("DATE_CTL");
    return true;
  }

A DateCtl (with PickCtl as a minor variaton) was implemented in DateIml.h.

Wrapping Up

This framework can be easily extended—by adding new controls and new events as needed. It is easier to use than the original BREW API because it is similar to the J2ME model and provides automatic memory management. All the previously described frameworks (see Generic Connection Framework, and Cooperative Multitasking) easily fit inside this one.

References

  1. Brew & J2ME: Let's Be Friends! http://www.developer.com/ws/brew/article.php/3116331
  2. What Is the "Named Constructor Idiom?" http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8

Download Sample Program

Source code: cppapp.zip - 222 kb

About the Author

Radu Braniste is Director of Technology at Epicad. He can be contacted at rbraniste@epicad.com

# # #


Tools:
Add www.developer.com to your favorites
Add www.developer.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed


Java J2ME Archives

Work With InterSystems. Not Separate Systems. Rapidly develop and deploy connectable applications.
Five Trends for Application Development. Download Your Complimentary Report. Exclusive. Act Now.
Whitepaper: Enterprise Information Integration--Deployment Best Practices for Low-Cost Implementation
Is it time to make your move to the multi-threaded and parallel processing world? Find out!
Learn about expanding business opportunities for the reseller channel. Visit IT Channel Planet.



JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
Microsoft Article: HyperV-The Killer Feature in WinServer ‘08
Avaya Article: How to Feed Data into the Avaya Event Processor
Microsoft Article: Install What You Need with Win Server ‘08
HP eBook: Putting the Green into IT
Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
Avaya Article: Setting Up a SIP A/S Development Environment
IBM Article: How Cool Is Your Data Center?
Microsoft Article: Managing Virtual Machines with Microsoft System Center
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Intel Video: Are Multi-core Processors Here to Stay?
On-Demand Webcast: Five Virtualization Trends to Watch
HP Video: Page Cost Calculator
Intel Video: APIs for Parallel Programming
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Sun Download: Solaris 8 Migration Assistant
Sybase Download: SQL Anywhere Developer Edition
Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
Red Gate Download: SQL Compare Pro 6
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
IBM Article: Collaborating in the High-Performance Workplace
HP Demo: StorageWorks EVA4400
Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES