Blackberry OS6: implementing click event on extended MapLocation class - blackberry

I need to change what happens when a user clicks on a pin in a RichMapField, and these pins happen to be MapLocation objects, these MapLocations also optionally handle a different datatype known as a "Partner" class which contains an ID, Address, Label, Latitude and Longitude.
Everything runs great, and as it stands at the moment when you hover over the pin it still gives the label and such, but when you click on the pin, does nothing.
This behaviour is expected! So to this point, everything went great.
What I cant seem to figure out, is how to attach a click or touch listener to the new custom MapLocation object.
heres the code without much further adu:
import net.rim.device.api.lbs.maps.model.MapLocation;
import net.rim.device.api.ui.component.Dialog;
public class CustomMapLocation extends MapLocation {
private Partner partner;
public KRMapLocation(double lat, double lon, String label, String address) {
setLat(lat);
setLon(lon);
setName(label);
setDescription(address);
}
public KRMapLocation(Partner p) {
this.partner = p;
setLat(partner.getLatitude());
setLon(partner.getLongitude());
setName(partner.getName());
setDescription(partner.getAddress());
}
// this does nothing...
protected boolean trackwheelClick(int status, int time) {
Dialog.alert("Trackwheel click");
return true;
}
}
This is literally the last thing I got to figure out, is Touch and Trackwheel listeners. Help on either or or both would be amazing... I have run google dry, and by now Google things I'm some sort of blackberry fanboy lol
Wits end guys, I hope someone can help me out!
(I know this is possible, as it used to have a click event that opened up a detail page, I just do not know what to do or even what I'm supposed to be looking for.)

My guess is that it's not the MapLocation that handles clicks. It's handled by the field, which uses MapLocation data just to get the coordinates, label, etc. I also had no luck yet in finding the right hook. It would be nice to at least be able to extend the default Details dialog that comes up.

Related

Vaadin 7.6.7 - Navigator does not working

In 7.6.6, it worked fine!
From version 7.6.7, navigator enter function is called once only within page display. So navigation within the page can not make sense. Vaadin may change the "enter" function call mechanism.
I want to use navigator for keeping the status change within the page.
How can i make navigator change effect to the page without enter function?
I solve this problem. Use UriFragmentChangedListener.
Enroll URI fragment listener
Page.getCurrent().addUriFragmentChangedListener(new UriFragmentChangedListener() {
#Override
public void uriFragmentChanged(UriFragmentChangedEvent event) {
String frag = event.getUriFragment();
if (frag.contains("query"))
enterForFragment(event.getUriFragment());
}
});
fire fragment listener
Page.getCurrent().setUriFragment(navTo);
PS.
'enterForFragment' fuction do same task of 'enter'

Getting selected ListBox values on button Click | ZK

I am very new to ZK framework and trying to customize few things and have struck at one point which I am not sure how to achieve that.
I have a predefined section where I need to show 2 drop down and a button and need to persist those drop down values on button click event.
This is how It has been define in Spring file
<bean id="mybean" parent="parentBean" class="WidgetRenderer">
<property name="detailRenderer">
<bean class="DetailsListRenderer" parent="abstractWidgetDetailRenderer"/>
</property>
</bean>
Here mybean is being used to show main section and I am adding my drop down using this bean while button are being added to detailRenderer.
Save button is bind to onClick event, but I am not sure how I can fetch values from my custom drop down?
I am aware about binding those Dropdown with onClick event but they have to be in same class.
Can any one suggest me how I can fetch values of those drop down.I am creating down down with following code
Listbox listbox = new Listbox();
listbox.appendItem("item1", "item1");
listbox.appendItem("item2", "item2");
This is my button code in another class
protected void createUpdateStatusButton(Widget widget,Div container)
{
Button button = new Button(LabelUtils.getLabel(widget, buttonLabelName, new Object[0]));
button.setParent(container);
button.addEventListener("onClick", new EventListener()
{
public void onEvent(Event event)throws Exception
{
MyClass.this.handleSaveStatusEvent(widget, event);
}
});
}
You may want to listen to the onSelect (I prefer to use Events.ON_SELECT rather than writing the strings) which is more specific to when the Listbox selection changes.
Either way, the key is to get the information you want from the Event passed to your EventListener, rather than going back to your Listbox itself. The basic Event usually carries useful information on getTarget and getData but using more specific events (SelectEvent in this case) will give you access to more relevant info.
button.addEventListener(Events.ON_SELECT, new EventListener<SelectEvent<Listitem, MyDataObject>() {
public void onEvent(SelectEvent<Listitem, MyDataObject> event) {
// Now you can access the details of the selection event..
List<Listitem> selectedItems = event.getSelectedItems();
List<MyDataObject> selectedObjects = event.getSelectedObjects();
}
});
You can find out what events are available for different ZK widgets in their Component Reference documentation.
If I understand the question (I don't think I did in my previous response) you want to gather information from the page (eg: Listbox selection state) when the user clicks a button. Your problem being that you are using disparate classes to compose the page and so don't have access to the various ZK Components when the button is clicked.
(Ignoring the multiple class issue for a minute)
From a high level, there are sort of two camps in the ZK community. The newer MVVM approach suggests the view should push the relevant state to the back end as the user interacts with the front end. This way, the back end never needs to ask for the client state, and when the button is clicked, the values/state are on the server ready to be used.
The other camp binds the client to the server such that the back end always has access to the client Components and when the button is clicked, the values/state can easily be retrieved by interacting with the components.
Another approach is more like what I was talking about in my previous answer, to not bind the back end to the client at all but to rely on event data as much as possible. I favor this approach where it is sufficient.
Now, you're free to choose your favored approach and ZK has lots of documentation on how to work in either of these camps. The question then is where is the client state stored on the server (either pushed there by the client in MVVM or bound there in MVC). I don't think that's a question that can be solved here, that's a software engineering challenge. I personally suggest you take on standard ZK patterns so as not to but heads with the framework. If you really want to go your route, you can grab a reference to the Listbox on the fly like so:
public class Foo {
public static final String LISTBOX_ID = "myListbox";
public void renderListbox(Component parent, MyItem items) {
Listbox listbox = new Listbox();
listbox.setId(LISTBOX_ID);
listbox.setParent(parent);
for (MyItem item : items) {
listbox.appendItem(item.getName(), item);
}
}
}
public class Bar {
#Listen(Events.ON_CLICK + " = #saveButton")
public void saveButtonClicked(Event event) {
Component saveButton = event.getTarget();
Listbox listbox = (Listbox) saveButton.getFellow(Foo.LISTBOX_ID);
Set<Listitem> selection = listbox.getSelectedItems();
// do something
}

Cannot discard changes made in fields in TableFieldFactory

I have a simple Table where I present some data using an IndexedContainer as data source.
I want my users to be able to edit some of this data, so I'm using a TableFieldFactory (DefaultFieldFactory) to generate these columns (properties) editable.
Now, if a user is in editing mode (table.setEditable(true)) and have been changing some fields, he or she should be able to discard those changes - for this purpose, I have a "Cancel" button. This "Cancel" button is supposed to discard all changes made in the Table generated fields since the user entered editing mode and then setEditable(false) - now everything should be the way it was before setEditable(true) was called.
This didn't sound very hard, until I tried implementing it.
If I understand the functionality of the Table vs. Container vs. TableFieldFactory correctly, the following happens:
Properties are added to the Container
The Container is set as the Table data source
The User clicks the "Edit Table" button (table.setEditable(true))
The Table calls the TableFieldFactory's overridden createField() method
The createField() method creates the editable fields
The user edits the fields and at the same time the Container gets updated <-- not 100% sure about this one
The user clicks the "Cancel" button <-- HERE is my problem
Question: When I press the "Cancel" button, what should I do discard() on? I can't do table.discard(), because the changes has already taken place. I can't do container.discard() becase, yeah, the Container interface doesn't inherit that method. I can't do field.discard(), because I cannot reach the fields from outside the createField() method.
I have tried different variations of setBuffered, markAsDirty, refreshRowCache and setImmediate without success.
Here's (hopefully all) relevant code:
The table, container and the "Cancel" button (roughly):
table.setContainerDataSource(container);
Button cancel = new Button("Cancel", new Button.ClickListener() {
private static final long serialVersionUID = 1L;
#Override
public void buttonClick(ClickEvent event) {
// table.setImmediate(false); //tried variations of this
// table.refreshRowCache(); //tried variations of this
// table.markAsDirty(); //tried variations of this
// table.setBuffered(true); //tried variations of this
// table.discard(); //tried this, but here it's too late
table.setEditable(false);
}
});
The TableFieldFactory:
table.setTableFieldFactory(new DefaultFieldFactory() {
private static final long serialVersionUID = 1L;
#Override
public Field<?> createField(Container container, Object itemId, Object propertyId, com.vaadin.ui.Component uiContext) {
TextField tField = (TextField) DefaultFieldFactory.get().createField(container, itemId, propertyId, uiContext);
tField.setImmediate(true);
if (propertyId.equals("Foo")) {
// field.setImmediate(true); //tried variations of this
// field.setBuffered(false); //tried variations of this
return tField;
}
else {
tField.setReadOnly(true);
}
return tField;
}
});
By keeping track of the fields created in the factory (and making those fields buffered), you can then Commit/Discard as you wish.
I've created a simple example of buffered table editing in this self-contained GitHub Gist. Select a row and click Edit (or double click). Make changes, and click Save/Hit Enter to commit, or Cancel/Escape to discard.
I've deliberately made only one row-at-a-time editable, because frankly that's the only thing that makes any sense to me. Obviously, that's easily changed.

Editing a BrowserField's History

I have a BrowserField in my app, which works great. It intercept NavigationRequests to links on my website which go to external sites, and brings up a new windows to display those in the regular Browser, which also works great.
The problem I have is that if a user clicks a link to say "www.google.com", my app opens that up in a new browser, but also logs it into the BrowserHistory. So if they click back, away from google, they arrive back at my app, but then if they hit back again, the BrowserHistory would land them on the same page they were on (Because going back from Google doesn't move back in the history) I've tried to find a way to edit the BrowserField's BrowserHistory, but this doesn't seem possible. Short of creating my own class for logging the browsing history, is there anything I can do?
If I didn't do a good job explaining the problem, don't hesitate for clarification.
Thanks
One possible solution to this problem would be to keep track of the last inner URL visited before the current NavigationRequest URL. You could then check to see whether the link clicked is an outside link, as you already do, and if it is call this method:
updateHistory(String url, boolean isRedirect)
with the last URL before the outside link. Using your example this should overwrite "www.google.com" with the last inner URL before the outside link was clicked.
Here is some half pseudocode/half Java to illustrate my solution:
BrowserFieldHistory history = browserField.getHistory():
String lastInnerURL = "";
if navigationRequest is an outside link {
history.updateHistory(lastInnerURL, true);
// Handle loading of outer website
} else {
lastInnerURL = navigationRequest;
// Visit inner navigation request as normal
}
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/browser/field2/BrowserFieldHistory.html#updateHistory(java.lang.String, boolean)
I had a similar but a little bit different issue. Special links in html content like device:smth are used to open barcode scanner, logout etc and I wanted them not to be saved in BrowserFieldHistory. I found in WebWork source code interesting workaround for that. All that you need is throw exception at the end like below:
public void handleNavigationRequest( BrowserFieldRequest request ) throws Exception {
if scheme equals to device {
// perform logout, open barcode scanner, etc
throw new Exception(); // this exception prevent saving history
} else {
// standard behavior
}
}

Clicking on scrollbar causes unintential firing of event

Morning - I'm having a little problem.
I have an autocomplete extender textbox where a user types in words and suggestions are provide. Should the term be rather generic, a list appears and the user can scroll up or down using the mouse wheel with no problems at all.
However, if the user attempts to click on the scroll bar and scroll through the list, it fires the textchanged event - which I don't want it to do.
This event should only fire once the user has actually selected the appropriate product from the list supplied.
I can set the autopost back of the text file off which has the desired effect but I do require the post back to be performed once the user selects a suggestion.
Does anyone know how I can get around this?
I managed to find a resolution.
Stick this in the page load event:
string contactPostBackFunction = null;
contactPostBackFunction = Page.ClientScript.GetPostBackEventReference(this.tbxProdAC, "", false);
string contactPostBackScript = null;
contactPostBackScript = string.Format("function postBackOnContactSelectedFromDropDown() {0} {1} {2}", "{", contactPostBackFunction, "}");
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "contactPostBackScript", contactPostBackScript, true);
And have this in your Autocomplete extender properties:
OnClientItemSelected="postBackOnContactSelectedFromDropDown"

Resources