dcsimg
October 20, 2018
Hot Topics:

BREW & J2ME: Let's Be Friends!

  • December 4, 2003
  • By Radu Braniste
  • Send Email »
  • More Articles »

What's a List?

BREW doesn't provide a List, but a MenuCtl. The short answer is "a List is a IDisplayable exposing MenuCtl functionality."

template <class T, 
          class P=ListStrategy, 
          class E = ErrorHandler>
class ListImpl : public IDisplayable
{
typedef bool (T::*FNC)(ListImpl<T,P,E>*);
public:
  static ListImpl* getList(
           const WString& title, T* t)
  {
    ListImpl* l = createList(t);
    if (l)
    {
      l->setTitle(title);
      l->setFullScreen();
    }
    return l;
  }

  virtual ~ListImpl()
  {
    if (list_) IMENUCTL_Release(list_);
  }

  void append(const WString& item)
  {
    if (!rr_)
      return;
    int id = rr_->getNextAvailableID();
    IMENUCTL_AddItem(list_, 0, 0, id, 
                  const_cast<AECHAR*>
                    (item.toCharArray()), 0);
    indxs_.append(id);
  }

  void append(const WString items[]s, int sz)
  {
    for(int i=0; i < sz; ++i)
    {
      append(items[i]);
    }
  }

  virtual IControl* getControl() const
  {
    return reinterpret_cast<IControl*>(list_);
  }

  bool onCmd()
  {
    if (fnc_ && t_)
      return (*t_.*fnc_)(this);
    return false;
  }

  int getSelectedIndex() const
  {
    return selected_;
  }

  virtual bool containsItem(int ix)
  {
    selected_ = getIDImpl(ix);
    return (selected_ != INDEX_OUT_OF_BOUNDS);
  }

  virtual int getID() const
  {
    return id_;
  }

  void setCbk(FNC f)
  {
    fnc_ = f;
  }

  void setSelection(int id)
  {
    int lid = IMENUCTL_GetItemID(list_, id);
    IMENUCTL_SetSel(list_, lid);
  }

  int size() const
  {
    return indxs_.size();
  }

  void setTitle(const WString& title)
  {
    if (title.length())
      IMENUCTL_SetTitle(list_, NULL, 0, const_cast<AECHAR*>
                       (title.toCharArray()));
  }

private:
  
  ListImpl( T* t, AEECLSID cid ): list_(0), t_(t) , rr_(0),
          shell_(getShell()), selected_(0)
  {
    if (shell_)
      ISHELL_CreateInstance(shell_, cid, (void **)&list_);
    if (!list_)
    {
      E::onMemAllocError(WString(__FILE__),
                         WString((long)__LINE__));
      return;
    }

    rr_ = t_->getDisplayable();
    if (rr_)
      id_ = rr_->registerResource(this);
  }

  static ListImpl* createList( T* t, AEECLSID cid =
                                     AEECLSID_MENUCTL)
  {
    ListImpl* l = new ListImpl( t, cid);
    if (!l->list_)
    {
      delete l;
      return 0;
    }
    return l;
  }

  void setFullScreen();

  int getIDImpl(int ix);

private:
  IMenuCtl *  list_;
  FNC fnc_;
  T* t_;
  DisplayableRegistry* rr_;
  int selected_;
  int id_;
  IShell * shell_;
  BrewVector<int> indxs_;
};

The next concern is event handling. Apparently, there are important differences between BREW and Java: a unique ID, event loop mechanism versus an implicit, observer-based one. I say "apparently" because one can move freely from one mechanism to the other. Even more: J2ME, for example, shares one of the weaknesses of BREW—the command listener implementation is a close relative of the BREW event loop—usually a hard-to-maintain, huge "switch." On top of this, listeners are weak-typed constructs, exposing a Displayable interface that has to be cast by the user. Our framework offers a safer approach with type safe, J2SE style listeners. For example, the ListImpl class defines a listener:

typedef bool (T::*FNC)(ListImpl<T,P,E>*);

implemented in:

  bool myListUsage( List* l)
  {
    int pos = l->getSelectedIndex();
    return (pos == INDEX_OUT_OF_BOUNDS) ?
            false : BuildCommand(pos), true;
  }

and registered like this:

l->setCommandListener(myListUsage);

Java has a more elegant getSelected() mechanism instead of unique labels to be passed to IMENUCTL_AddItem. This can be easily implemented by using the ubiquitous DisplayableRegistry, this time generating unique numbers to be used internally as IDs. Please note the use of a policy to faster retrieve the IDs in some particular cases.

A string implementation supporting AECHARs and CHARs was discussed extensively in [3].

A striking difference between BREW and Java is error handling, when RTTI based exception handling is not available or might be considered too expensive to be used in BREW. Emulating a try/catch mechanism using setjmp/longjmp is not directly applicable due to problems in destructing auto objects, but other techniques are available (see [4], [5]). As a convenience, we provided an ErrorHandler as a policy—a way to gracefully provide error tracking information.





Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.

Sitemap

Thanks for your registration, follow us on our social networks to keep up-to-date