April 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

BREW & J2ME: Let's Be Friends!, Page 3

  • December 4, 2003
  • By Radu Braniste, 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.

 

 


Sitemap | Contact Us

Rocket Fuel