package org.bbssh.ui.components; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.ui.MenuItem; import net.rim.device.api.ui.component.BasicEditField; import net.rim.device.api.ui.component.Menu; /** * Specialized basic edit field that automatically invokes the Symbol menu on request. The using class must register as * a FieldChangeListener instance * * @author marc * */ public class SymbolMenuCaptureField extends BasicEditField implements FieldChangeListener { private boolean capturing = false; private FieldChangeListener listener; /** * Creates a new object instance. Registers self as field change listener in order to filter only desired events to * our caller, who also must register as a listener. */ public SymbolMenuCaptureField() { super(); // Capture our own changes -t his will let us filter // what we pass on to whoever is using us. super.setChangeListener(this); } /** * Displays the symbol menu and sets state to indicate capture is enabled. Symbol menu is captured by ID. * * @todo testing is required to ensure that ID stays consistent across different platform versions. */ public void captureSymbol(Menu menu) { for (int x = menu.getSize() - 1; x >= 0; x--) { MenuItem it = menu.getItem(x); if (it != null) { // OS 7.0 - switched ID to 441 int id =it.getId() ; if (id == 10065 || id == 441) { capturing = true; it.run(); } } } } protected void onExposed() { super.onExposed(); // This combination of events will occur only // when the user cancels from the symbol screen. if (capturing && getText().length() == 0) { capturing = false; if (listener != null) { // This will signal our parent that a change occurred - // teh special value "1" indicates that the user canceled, // and so parent should close. listener.fieldChanged(this, 1); } } } /* * (non-Javadoc) * * @see net.rim.device.api.ui.FieldChangeListener#fieldChanged(net.rim.device.api.ui.Field, int) * * This will delegate the fieldChanged event to the registered listener only if the field is presently capturing the * symbol operation. Otherwise the event is discarded. * * In any case, if the field is non-blank it will be cleared, as this field is not intended for use as an edit * field. */ public void fieldChanged(Field field, int context) { if (capturing) { capturing = false; if (listener != null) { listener.fieldChanged(field, context); } } // Ensure that we never retain a value in this field. if (getText().length() > 0) { setText(""); } } /** * Workaround for a weird RIM bug. Orderinally we would override setFieldListener, bceause we want to filter the * events that the registered listener receives. However, when we do that we find that the BB framework is invoking * "setListener" *after* the owning class calls it, and it's passing in this field itself as the listener. My best * guess is that because we call super.setFieldListener(this) in the constructor, someone along the line is calling * oru setFieldChangeListener(((Field)x).getFieldChangeListener) * * Which is fairly stupid, but it's hte only explanation so far that works... * */ public void setListener(FieldChangeListener listener) { this.listener = listener; } public int getPreferredWidth() { return 1; } }