In the top of my page I want a dropdown to change the preferred language. If it alters the page is to be reloaded and rendered with the selected langauge.
In my solution the language is not loaded immediately though.
#SuppressWarnings("serial")
public class CurrentLanguageDropdown extends LanguageDropDown {
private String sessionlanguage;
private IModel<String> model;
public CurrentLanguageDropdown(String id, Locale locale) {
super(id, locale);
this.sessionlanguage = locale.getCountry();
GlobalAccountSession session = GlobalAccountSession.get();
model = new SelectedLocaleModel("sessionlanguage", this, new Model<Serializable>(session.getLocale()),
locale.getCountry());
setModel(model);
}
#Override
public void onSelectionChanged(String newSelection) {
GlobalAccountSession session = GlobalAccountSession.get();
model = new SelectedLocaleModel("sessionlanguage", this, new Model<Serializable>(session.getLocale()),
newSelection);
}
#Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
String getSessionlanguage() {
return sessionlanguage;
}
private class SelectedLocaleModel extends StringResourceModel {
private String selectedValue = "";
private Component parent;
public SelectedLocaleModel(String resourceKey, Component parent, IModel<?> model, String selectedValue) {
super(resourceKey, parent, model);
this.selectedValue = selectedValue;
this.parent = parent;
}
#Override
public void setObject(java.lang.String object) {
GlobalAccountSession session = GlobalAccountSession.get();
Locale locale = new Locale(object.toString());
session.setLocale(locale);
selectedValue = locale.getLanguage();
}
#Override
public String getObject() {
GlobalAccountSession session = GlobalAccountSession.get();
selectedValue = session.getLocale().getLanguage();
return selectedValue;
}
}
}
Looking at my code I see that getObject is called first, and setObject after that. So rendering seems to be done before the change made by the user is handled.
Can anyone tell me what I'm doing wrong?
You're creating a new model object in onSelectionChanged. This defeats the purpose of a model which should be modified but not replaced. If you need to create a new model object, you'll have to replace the model used by your component too (call setModel(model) again).
I know this isnt a component but an implementation of one but shows the general idea
public class LocaleDropDownPanel extends Panel
{
private Locale sessionLocale;
public LocaleDropDownPanel(String id, Locale locale)
{
super(id);
ArrayList<Locale> choices = Lists.newArrayList(Locale.getAvailableLocales());
//didnt know if you need country or language
IChoiceRenderer<Locale> choiceRenderer = new ChoiceRenderer<Locale>("language");
DropDownChoice<Locale> ddc = new DropDownChoice<Locale>("ddc", new PropertyModel<Locale>(this, "sessionLocale"),
new Model<ArrayList<Locale>>(choices), choiceRenderer)
{
#Override
protected void onSelectionChanged(Locale newSelection)
{
//if you want to save the selected locale in your session.
GlobalAccountSession session = GlobalAccountSession.get();
session.setLocale(newSelection);
}
};
//This Language selected to begin with
ddc.setDefaultModelObject(locale);
}
public Locale getSessionLocale() {
return sessionLocale;
}
public void setSessionLocale(Locale sessionLocale) {
this.sessionLocale = sessionLocale;
}
}
Related
I am developing the project in mvvm architecture. Here I have a class like create profile and also another class like edit profile. Edit profile is a fragment class. here I created a same view model class for both the create profile and edit profile fragment classes.In edit profile class when I call view model class getting null pointer exception.
In Edit Profile Fragment Class I am calling the view model class
public class EditProfileFragment extends BaseFragment {
private UserService userService;
private String eId;
private final static String TAG = "EditProfile";
#Override
protected int getFragmentLayoutID() {
return R.layout.activity_create_profile;
}
#Override
protected boolean isSubscribedToEvents() {
return true;
}
#Override
protected Class<ProfileVM> getVMClass() {
return ProfileVM.class;
}
#Override
protected int getVMVariableId() {
return BR.profileVM;
}
#Override
protected void init() {
userService = getApiClient().create(UserService.class);
ProfileVM profileVM = (ProfileVM) getViewModel();
UserDTO userDTO = getUserDao().getUserDetails();
eId = userDTO.getId();
Log.d(TAG,"editprofileenigma"+eId);
Log.d(TAG,"userdtoedit"+userDTO);
userService.getUserProfile(eId);// this is the api call
profileVM.user.setValue(userDTO); // here iam getting null pointer exception
profileVM.individual.setValue(getUserDao().getUserIndividual());
profileVM.individualProfile.setValue(getUserDao().getIndividualProfile());
profileVM.individualAttributePermission.setValue(getUserDao().getIndividualAttributePermission());
}
}
My View Model Class
#Bindable
public MutableLiveData<String> heading = new MutableLiveData<>("Create Profile");
#Bindable
public MutableLiveData<UserDTO> user = new MutableLiveData<>(new UserDTO());
#Bindable
public MutableLiveData<Individual> individual = new MutableLiveData<>(new Individual());
#Bindable
public MutableLiveData<Boolean> isDemographicExpanded = new MutableLiveData<>(true);
#Bindable
public MutableLiveData<Boolean> isLiveNInterestExpanded = new MutableLiveData<>(true);
#Bindable
public MutableLiveData<IndividualProfile> individualProfile = new MutableLiveData<>(new IndividualProfile());
#Bindable
public MutableLiveData<IndividualAttributePermission> individualAttributePermission = new MutableLiveData<>(new IndividualAttributePermission());
#Bindable
public MutableLiveData<ProfileSwitchModel> profileSwitchModel = new MutableLiveData<>(new ProfileSwitchModel(new IndividualAttributePermission()));
private Individual getIndividual() {
return individual.getValue()==null? new Individual() : individual.getValue();
}
private IndividualProfile getIndividualProfiles() {
return individualProfile.getValue()==null? new IndividualProfile() : individualProfile.getValue();
}
private IndividualAttributePermission getIndividualAttributePermissions() {
return individualAttributePermission.getValue()==null? new IndividualAttributePermission() : individualAttributePermission.getValue();
}
There is a vey nice libray(https://github.com/Applandeo/Material-Calendar-View) for customizing the android calenderview . Like for example, for adding events to the calenderview there is class named Eventday.java, which takes calender object and a drawable object as parameters to initialize. I wish it could have take a string value too so that i can also store a descrption of the event, because there is no point in adding events to the calender if one cannot add details about the event(string datatype). Can some one provide a workaround for my problem?
List<EventDay> events = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
//we cannot details about the event(string data) while initializing the EventDay class
events.add(new EventDay(calendar, R.drawable.absentic));
First Make a Custom Class
import com.applandeo.materialcalendarview.EventDay;
import java.util.Calendar;
public class MyEventDay extends EventDay implements Parcelable {
private String mNote;
public MyEventDay(Calendar day, int imageResource, String note) {
super(day, imageResource);
mNote = note;
}
public String getNote() {
return mNote;
}
private MyEventDay(Parcel in) {
super((Calendar) in.readSerializable(), in.readInt());
mNote = in.readString();
}
public static final Creator<MyEventDay> CREATOR = new Creator<MyEventDay>() {
#Override
public MyEventDay createFromParcel(Parcel in) {
return new MyEventDay(in);
}
#Override
public MyEventDay[] newArray(int size) {
return new MyEventDay[size];
}
};
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeSerializable(getCalendar());
parcel.writeInt(getImageResource());
parcel.writeString(mNote);
}
#Override
public int describeContents() {
return 0;
}
}
Adding Event In Calender
mEventDays.add(new MyEventDay(calender, R.drawable.ic_note_sticky, "I am Event");
For Retriving String
calendarView.setOnDayClickListener(new OnDayClickListener() {
#Override
public void onDayClick(EventDay eventDay) {
Log.e("Event",((MyEventDay) eventDay).getNote()+" <--");
}
});
Its Work For me , I Hope its Helpfull to you also
I used this method to display small popup note when user clicks on any date.
Declared: Map<Date,String> eventNotes = new HashMap<>()
While updating calendar events for every date, populated the eventNotes with required notes and date as key
In Calendar setOnDayClickListener retrieved eventNote using the key eventDay.getCalendar().getTime()
Then used a dialog popup to show that note
Even after some time trying to read and understand the topics already posted here, I am still confused on how to create events in Java.
Assuming that I have this class in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
OnHighlightsJsonChanged( EventArgs.Empty );
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
OnHighlightsContentChanging( EventArgs.Empty );
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged( EventArgs.Empty );
}
}
// Events
internal void OnHighlightsJsonChanged( EventArgs eventArgs ) {
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
}
internal void OnHighlightsContentChanging( EventArgs eventArgs ) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
}
internal void OnHighlightsContentChanged( EventArgs eventArgs ) {
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
How would I make a copy of this in Java?
I somewhat understand that I need to create an interface that would hold the 3 EventHandlers that I have in this code. Then, I would have to implement that interface in the class. Let's assume that the class would have the exact same name and the result would be something like this:
public class HighlightsObjectHandler implements SomeListener { ... }
But, from what I see from tutorials and forums, they would fire, for instance, the HighlightsContentChanging directly instead of calling the OnHighlightsContentChanging ( where I would like to set a variable - HighlightsUpdating - to a value and then calling the listeners associated with the event ).
And there is where I'm losing my mind. How would I make this happen? In the Windows Phone app, that variable would help me whenever a page that had this content in it to set the page as loading or to display a message if the page has nothing to show.
UPDATE:
I've managed to create the code I as able to, or had acknowledge to. I'll leave here the code so far:
package com.example.nlsonmartins.myapplication.Highlights;
import java.util.ArrayList;
import org.json.*;
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
// Variables
private String
_json;
private Boolean
_updating;
private ArrayList<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if(highlightsJson != _json && highlightsJson != null) {
_json = highlightsJson;
// Fire the Java equivalent of C# 'OnHighlightsJsonChanged( EventArgs.Empty );'
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public ArrayList<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
try {
JSONObject
jsonObject = new JSONObject(HighlightsJson());
// Fire the Java equivalent of C# 'OnHighlightsContentsChanging( EventArgs.Empty );'
// Parse the JSON object
// Fire the Java equivalent of C# 'OnHighlightsContentsChanged( EventArgs.Empty );'
} catch (JSONException exception) {
}
}
// Events
/* Create the event handler for 'OnHighlightsJsonChanged' */
/* Create the event handler for 'OnHighlightsContentsChanging' and call the 'HighlightsUpdating(true);' method */
/* Create the event handler for 'OnHighlightsContentsChanged' and call the 'HighlightsUpdating(false);' method */
// Constructors
public HighlightsObjectHandler() {
_highlights = new ArrayList<HighlightObject>();
}
}
I don't have an equivalent for the 'JsonObject' type, but other than that I think the following may work for you, using your own custom EventHandler functional interface, custom EventArgs class, and generic 'Event' helper class:
import java.util.*;
public class HighlightsObjectHandler
{
// Constants
private static final String JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Handlers
public Event<CustomEventHandler> HighlightsJsonChanged = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanging = new Event<CustomEventHandler>();
public Event<CustomEventHandler> HighlightsContentChanged = new Event<CustomEventHandler>();
// Variables
private String _json;
// Properties
public final String getHighlightsJson()
{
return _json;
}
public final void setHighlightsJson(String value)
{
if (!_json.equals(value) && value != null)
{
_json = value;
OnHighlightsJsonChanged(CustomEventArgs.Empty);
ParseJson();
}
}
private boolean HighlightsUpdating;
public final boolean getHighlightsUpdating()
{
return HighlightsUpdating;
}
private void setHighlightsUpdating(boolean value)
{
HighlightsUpdating = value;
}
private ArrayList<HighlightObject> Highlights;
public final ArrayList<HighlightObject> getHighlights()
{
return Highlights;
}
private void setHighlights(ArrayList<HighlightObject> value)
{
Highlights = value;
}
// Methods
private void ParseJson()
{
//todo: no equivalent to 'JsonObject':
JsonObject jsonObject = null;
//todo: no equivalent to 'out' parameter:
if (JsonObject.TryParse(HighlightsJson, jsonObject))
{
OnHighlightsContentChanging(CustomEventArgs.Empty);
// Json parsing and other stuff...
// ... it shouldn't matter for this question.
OnHighlightsContentChanged(CustomEventArgs.Empty);
}
}
// Events
public final void OnHighlightsJsonChanged(CustomEventArgs eventArgs)
{
if (HighlightsJsonChanged != null)
{
for (CustomEventHandler listener : HighlightsJsonChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanging(CustomEventArgs eventArgs)
{
setHighlightsUpdating(true);
if (HighlightsContentChanging != null)
{
for (CustomEventHandler listener : HighlightsContentChanging.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
public final void OnHighlightsContentChanged(CustomEventArgs eventArgs)
{
setHighlightsUpdating(false);
if (HighlightsContentChanged != null)
{
for (CustomEventHandler listener : HighlightsContentChanged.listeners())
{
listener.invoke(this, eventArgs);
}
}
}
// Constructors
public HighlightsObjectHandler()
{
setHighlights(new ArrayList<HighlightObject>());
}
}
#FunctionalInterface
public interface CustomEventHandler
{
void invoke(object sender, CustomEventArgs e);
}
public class CustomEventArgs
{
public static readonly CustomEventArgs Empty;
public CustomEventArgs()
{
}
}
//this is produced as a helper class by C# to Java Converter:
public final class Event<T>
{
private java.util.Map<String, T> namedListeners = new java.util.HashMap<String, T>();
public void addListener(String methodName, T namedEventHandlerMethod)
{
if (!namedListeners.containsKey(methodName))
namedListeners.put(methodName, namedEventHandlerMethod);
}
public void removeListener(String methodName)
{
if (namedListeners.containsKey(methodName))
namedListeners.remove(methodName);
}
private java.util.List<T> anonymousListeners = new java.util.ArrayList<T>();
public void addListener(T unnamedEventHandlerMethod)
{
anonymousListeners.add(unnamedEventHandlerMethod);
}
public java.util.List<T> listeners()
{
java.util.List<T> allListeners = new java.util.ArrayList<T>();
allListeners.addAll(namedListeners.values());
allListeners.addAll(anonymousListeners);
return allListeners;
}
}
import java.util.*;
interface HelloListener
{ void someoneSaidHello();}
NOTE
I'm going to have this StackOverflow answer as a base for what I'm going to explain in this answer.
Okay, so, for what I could read and understand, it isn't that much different building C#-like events in Java ( or, in another point of view, it isn't that hard from someone who develops in C# to build events in Java ).
First, from my perspective, I'd like to point that the way I build the events in Java are almost a copy-paste from C# ( maybe it's the correct way to do it, maybe it isn't ).
Second, I'm going to - hopefully - put this in a way people might understand ( based on tutorials I saw here on StackOverflow and other sites ):
The events on C# are wrapped in a method that is set as internal - usually the OnSomethingChanging or OnSomethingChanged - whereas the Java events are not. Imagine this method in Java:
List<HelloListener> listeners = new ArrayList<HelloListener>();
public void sayHello() {
System.out.println("Hello!!");
// Notify everybody that may be interested.
for (HelloListener hl : listeners)
hl.someoneSaidHello();
}
Now, to make it more C# like, I would to make it like this:
public event EventHandler HelloListener;
public void SayHello() {
Console.WriteLine("Hello!!");
// Notify everybody that may be interested.
if(HelloListener != null) {
HelloListener(this, EventArgs.Empty);
}
}
Basically I was expecting to have to make an OnHelloListener method, then trigger the events on that very method but, on the majority of examples and tutorials that I saw, they would do something like I wrote above. That was what was messing my head really badly ( and probably others too if they come from C# to Java ).
In conclusion
If I was to translate the HighlightsObjectHandler class from C# to Java - and keeping the C# soul in it - I would end with something like this:
public class HighlightsObjectHandler {
// Constants
private final String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
private List<HighlightsListener>
_highlightsListeners = new ArrayList<HighlightsListener>();
// Variables
private String
_json;
private Boolean
_updating;
private List<HighlightObject>
_highlights;
// Properties
public String HighlightsJson() {
return _json;
}
public void HighlightsJson(String highlightsJson) {
// Validate the json. This cannot be null nor equal to the present one ( to prevent firing events on the same data )
if (!highlightsJson.equals(_json) && highlightsJson != null) {
_json = highlightsJson;
OnHighlightsJsonChanged();
ParseJson();
}
}
public Boolean HighlightsUpdating() {
return _updating;
}
private void HighlightsUpdating(Boolean isUpdating) {
_updating = isUpdating;
}
public List<HighlightObject> Highlights() {
return _highlights;
}
// Methods
private void ParseJson() {
if (HighlightsUpdating()) {
return;
}
try {
OnHighlightsContentsChanging();
// Parse the JSON object
OnHighlightsContentsChanged();
} catch (JSONException exception) {
}
}
// Events
private void OnHighlightsJsonChanged() {
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsJsonChanged();
}
}
private void OnHighlightsContentsChanging() {
HighlightsUpdating(true);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanging();
}
}
private void OnHighlightsContentsChanged() {
HighlightsUpdating(false);
for(HighlightsListener highlightsListener : _highlightsListeners) {
highlightsListener.HighlightsContentChanged();
}
}
// Constructors
public HighlightsObjectHandler() {
_highlights = new List<HighlightObject>();
}
}
Once again, my problem was basically me expecting to have to create the OnSomethingChanged methods that would trigger the events and not the code directly placed on the methods when I want them to be triggered.
You could say that I was an app that was crashing when you typed this while expecting you to type that.
Java to C#
WARNING If you're easily confused or you're still trying to understand this, I recommend you to not read this part of the answer. This is just an for fun and curiosity block that I found somewhat funny and interesting...
So, let's say that my problem was the opposite that is now, I had a Java class with events and would like to translate it to C#. From what I know to this point I would end with something like this in C#:
public class HighlightsObjectHandler {
// Constants
private const String
JsonKeysHighlightsHolder = "Items",
JsonKeysHighlightUrl = "Url",
JsonKeysHighlightTranslationsHolder = "Traducoes",
JsonKeysHighlightTranslationLanguage = "Idioma",
JsonKeysHighlightTranslationText = "Titulo",
JsonKeysHighlightTranslationImage = "Imagem";
// Enumerators
// Handlers
public event EventHandler HighlightsJsonChanged;
public event EventHandler HighlightsContentChanging;
public event EventHandler HighlightsContentChanged;
// Variables
private String
_json;
// Properties
public String HighlightsJson {
get {
return _json;
}
set {
if (value != _json && value != null) {
_json = value;
if (HighlightsJsonChanged != null) {
HighlightsJsonChanged( this, eventArgs );
}
ParseJson();
}
}
}
public Boolean HighlightsUpdating { get; private set; }
public List<HighlightObject> Highlights { get; private set; }
// Methods
private void ParseJson() {
JsonObject
jsonObject;
if (JsonObject.TryParse( HighlightsJson, out jsonObject )) {
HighlightsUpdating = true;
if (HighlightsContentChanging != null) {
HighlightsContentChanging( this, eventArgs );
}
// Json parsing
HighlightsUpdating = false;
if (HighlightsContentChanged != null) {
HighlightsContentChanged( this, eventArgs );
}
}
}
// Events
// Constructors
public HighlightsObjectHandler() {
Highlights = new List<HighlightObject>();
}
}
Note how instead the OnHighlightsJsonChanged and the other internal methods are removed and, instead of having the code I had on the methods they are instead where I called the methods.
P.S.: I will mark this answer as the answer to the this question on the next Monday so I can see others answers and select one of them if they fit more as a final answer.
First of all - I am a beginner with Java and GWT. I have a scripting language background so please be explicit.
I have a CellTable that is populated with data from a database( ServerKeyWord class gets the data ).
myCellTable.addColumn(new TextColumn<ServerKeyWord>() {
#Override
public String getValue(ServerKeyWord object) {
// TODO Auto-generated method stub
return object.getName();
}
});
The example from above works, but it only shows the data as a text. I need to make it a hyperlink, that when you click it, it opens a new tab to that location.
I've surfed the web and got to the conclusion that I need to override render.
public class HyperTextCell extends AbstractCell<ServerKeyWord> {
interface Template extends SafeHtmlTemplates {
#Template("<a target=\"_blank\" href=\"{0}\">{1}</a>")
SafeHtml hyperText(SafeUri link, String text);
}
private static Template template;
public static final int LINK_INDEX = 0, URL_INDEX = 1;
/**
* Construct a new linkCell.
*/
public HyperTextCell() {
if (template == null) {
template = GWT.create(Template.class);
}
}
#Override
public void render(Context context, ServerKeyWord value, SafeHtmlBuilder sb) {
if (value != null) {
// The template will sanitize the URI.
sb.append(template.hyperText(UriUtils.fromString(value.getName()), value.getName()));
}
}
}
Now ... How do I use the HyperTextCell class with the addColumn method as in the first code example?!
Thank you in advance!
HyperTextCell hyperTextCell = new HyperTextCell();
Column<ServerKeyWord, ServerKeyWord> hyperColumn = new Column<ServerKeyWord, ServerKeyWord>(
hyperTextCell) {
#Override
public ServerKeyWord getValue(ServerKeyWord keyWord) {
return keyWord;
}
};
myCellTable.addColumn(hyperColumn);
CompositeCell let us customize the content of a table cell's in GWT using Java. We can put almost any other group of widget within the table's cell and layout them as we want. Problem is that if we used the html tags to define the layout of the CompositeCell as yet another table (see CompositeCell anonymous class implementation bellow) we loose the event handling for the components of the cell :(.
Running the following code, when we click in the buttons of the cell will realize the popup in response of the event handling IF WE COMMENT the CompositeCell anonymous implementation.
I've been debugging CompositeCell.onBrowserEvent(Context, Element, C, NativeEvent, ValueUpdater) because i think that the definition of the cell layout using HTML table tags breaks the event chain within GWT widgets hierarchy but haven't been successful so far.
Remark: both commented and uncommented versions of the code realize the same GUI layout. This example just intent to show that we loose event handling when customizing cell's content.
public class ActionCellTest implements EntryPoint {
private static final String SERVER_ERROR = "An error occurred while " + "attempting to contact the server. Please check your network "
+ "connection and try again.";
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
public void onModuleLoad() {
CellTable<Person> table = new CellTable<ActionCellTest.Person>();
final List<HasCell<Person, ?>> cells = new LinkedList<HasCell<Person, ?>>();
cells.add(new HasCellImpl("first name", new ActionCell.Delegate<Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getFirstName());
}
}));
cells.add(new HasCellImpl("last name", new ActionCell.Delegate<ActionCellTest.Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getLastName());
}
}));
CompositeCell<Person> cell = new CompositeCell<Person>(cells) {
#Override
public void render(Context context, Person value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<table><tbody><tr>");
for (HasCell<Person, ?> hasCell : cells) {
render(context, value, sb, hasCell);
}
sb.appendHtmlConstant("</tr></tbody></table>");
}
#Override
protected <X> void render(Context context, Person value, SafeHtmlBuilder sb, HasCell<Person, X> hasCell) {
Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</td>");
}
#Override
protected Element getContainerElement(Element parent) {
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
};
table.addColumn(new TextColumn<ActionCellTest.Person>() {
#Override
public String getValue(ActionCellTest.Person object) {
return object.getFirstName() + " " + object.getLastName();
}
}, "name");
table.addColumn(new Column<Person, Person>(cell) {
#Override
public Person getValue(ActionCellTest.Person object) {
return object;
}
}, "composite");
LinkedList<Person> data = new LinkedList<ActionCellTest.Person>();
data.add(new Person("Amy", "Reed"));
data.add(new Person("Tim", "Gardner"));
table.setRowData(data);
RootPanel.get().add(table);
}
private class HasCellImpl implements HasCell<Person, Person> {
private ActionCell<Person> fCell;
public HasCellImpl(String text, Delegate<Person> delegate) {
fCell = new ActionCell<Person>(text, delegate);
}
#Override
public Cell<Person> getCell() {
return fCell;
}
#Override
public FieldUpdater<Person, Person> getFieldUpdater() {
return null;
}
#Override
public Person getValue(Person object) {
return object;
}
}
private class Person {
private String fFirstName;
private String fLastName;
public Person(String first, String last) {
fFirstName = first;
fLastName = last;
}
public String getFirstName() {
return fFirstName;
}
public String getLastName() {
return fLastName;
}
}
}
This is a known issue which will be fixed in the upcoming GWT 2.5 (a matter of weeks): http://code.google.com/p/google-web-toolkit/issues/detail?id=5714
(in the mean time, you can run off trunk or try backporting the change)