I have a my own widget which simulates a multi select list box.
It will have a list of check boxes.
public class MultiListBox extends Composite implements IsWidget
{
private static MultiListBoxUiBinder uiBinder = GWT
.create(MultiListBoxUiBinder.class);
interface MultiListBoxUiBinder extends
UiBinder<Widget, MultiListBox> {
}
public MultiListBox() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiField ScrollPanel scrollPanel;
#UiField FlowPanel flowPanel;
private final List<CheckBox> checkboxes = new ArrayList<CheckBox>();
private final List<String> selectedValues = new ArrayList<String>();
#Override
public void addItem(final String value, final String text){
final CheckBox checkbox = new CheckBox(text);
checkbox.setFormValue(value);
checkbox.addClickHandler(new ClickHandler()
{
public void onClick(final ClickEvent event)
{
final CheckBox chkbox = (CheckBox)event.getSource();
if(chkbox.getValue())
{
selectedValues.add(value);
}
else
{
selectedValues.remove(value);
}
}
});
flowPanel.add(checkbox);
checkboxes.add(checkbox);
}
#Override
public List<String> getSelectedValues(){
return selectedValues;
}
#Override
public void clear() {
checkboxes.clear();
selectedValues.clear();
flowPanel.clear();
}
#Override
public int getItemCount() {
return checkboxes.size();
}
}
I am consuming this in my views like
<my:MultiListBox ui:field="myList"></my:MultiListBox>
Now, I wanted to create a onClick handler for this "myList" field in my view like
#UiHandler("myList")
void onMyListCliced(ClickEvent e) {
//TODO: handle it
}
Can anyone please guide how to achieve it.
Regards,
Sree
Your MultiListBox has to implement interface HasClickHandlers (in case of click event).
If you want to allow usage of other events via UiHandler there is a bunch of other interfaces in a form of Has*Handlers, which you will have to implement on your custom widget.
Related
i got a Presenter that is supposed to present a popup window what contains a DataGrip to show log file entries from a String list. I try to set the appropriate settings, but the number of log file lines that are displayed do not match the String list. I tried to enhance the data assignment, resulting in the Presenter not being shown any more.
Could you please give me a hint what i am doing wrong?
The parts of my presenter related to the DataGrid are:
// Create a list data provider.
final ListDataProvider<String> dataProvider = new ListDataProvider<String>();
public interface MyView extends PopupView, HasUiHandlers<DeviceLogfileUiHandlers> {
DataGrid<String> getDataGrid();
}
#Inject
DeviceLogfilePresenterWidget(final EventBus eventBus, final MyView view) {
super(eventBus, view);
getView().setUiHandlers(this);
}
protected void onBind() {
super.onBind();
// Add the cellList to the dataProvider.
dataProvider.addDataDisplay(getView().getDataGrid());
TextColumn<String> stringColumn = new TextColumn<String>() {
#Override
public String getValue(String s) {
return s;
}
};
getView().getDataGrid().addColumn(stringColumn);
}
#Override
protected void onReveal() {
super.onReveal();
}
public void setDeviceLog(List<String> logEntries) {
getView().getDataGrid().setRowData(0, logEntries);
//These entries make the presenter not show up any more:
dataProvider.addDataDisplay(getView().getDataGrid());
dataProvider.setList(logEntries);
getView().getDataGrid().setRowCount(logEntries.size(), true);
getView().getDataGrid().setVisibleRange(0, logEntries.size());
getView().getDataGrid().setPageSize(logEntries.size());
getView().getDataGrid().redraw();
}
how already stated here i am currently trying to get into gwt editors.
I figured i was missing a backing list to hold the data i manipulate.
I tried to assign that backing list with a setValue call from the parent view. Now the compiler complains it is missing the getter for groupList.
I understand that by convention the groupList property is derived by naming the Editor groupListEditor. What would be the right way to attach the lists? It seems i need to somehow call setValue with a list or else it does not seem to work. What would be the right way to do it?
My Editor looks like this:
public class GroupListEditor extends Composite implements
IsEditor<ListEditor<String, GroupItemEditor>> {
private static StringListEditorUiBinder uiBinder = GWT
.create(StringListEditorUiBinder.class);
interface StringListEditorUiBinder extends
UiBinder<Widget, GroupListEditor> {
}
#UiField
FlowPanel pWidget;
#UiField
PushButton bAdd;
#UiField
FlowPanel pList;
private class StringItemEditorSource extends EditorSource<GroupItemEditor> {
#Override
public GroupItemEditor create(final int index) {
GroupItemEditor subEditor = new GroupItemEditor();
pList.insert(subEditor, index);
subEditor
.addDeleteHandler(new EditorDeleteEvent.EditorDeleteHandler() {
public void onEditorDeleteEvent(EditorDeleteEvent event) {
remove(index);
}
});
return subEditor;
}
#Override
public void dispose(GroupItemEditor subEditor) {
subEditor.removeFromParent();
}
#Override
public void setIndex(GroupItemEditor editor, int index) {
pList.insert(editor, index);
}
}
private ListEditor<String, GroupItemEditor> editor = ListEditor
.of(new StringItemEditorSource());
public GroupListEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("bAdd")
void onBAddClick(ClickEvent event) {
Log.debug("Add button clicked");
add();
}
private void add() {
String s = "";
//TODO: Problem is there is no backing list, FIx this
editor.getList().add(s);
}
#Override
public ListEditor<String, GroupItemEditor> asEditor() {
return editor;
}
private void remove(final int index) {
editor.getList().remove(index);
}
}
The Editor is used as a sub-editor in a editor widget like this:
I tried to set the backing list:
public class ContainerEditorDialogPresenterWidget extends PresenterWidget<ContainerEditorDialogPresenterWidget.MyView> implements
ContainerEditorDialogUiHandlers {
private final PlaceManager placeManager;
#Inject
ContainerEditorDialogPresenterWidget(EventBus eventBus,
MyView view, PlaceManager placeManager) {
super(eventBus, view);
getView().setUiHandlers(this);
this.eventBus = eventBus;
this.placeManager = placeManager;
}
/**
* {#link LocalDialogPresenterWidget}'s PopupView.
*/
public interface MyView extends PopupView, ContainerEditView<ContainerDto>, HasUiHandlers<ContainerEditorDialogUiHandlers> {
}
private ContainerDto currentContainerDTO = null;
private DeviceDto currentDeviceDTO = null;
private final EventBus eventBus;
private SimpleBeanEditorDriver<ContainerDto, ?> driver;
public ContainerDto getCurrentContainerDTO() {
return currentContainerDTO;
}
public void setCurrentContainerDTO(ContainerDto currentContainerDTO) {
this.currentContainerDTO = currentContainerDTO;
}
public void setCurrentDeviceDTO(DeviceDto currentDeviceDTO) {
this.currentDeviceDTO = currentDeviceDTO;
}
#Override
public void onReveal() {
super.onReveal();
driver.edit(currentContainerDTO);
}
#Override
protected void onBind() {
super.onBind();
driver = getView().createEditorDriver();
}
#Override
public void updateContainer() {
ContainerDto dev = driver.flush();
eventBus.fireEvent(new ContainerUpdatedEvent(dev));
}
}
I tried to assign the backing list (just an empty string list) in the view:
public class ContainerEditorDialogView extends
PopupViewWithUiHandlers<ContainerEditorDialogUiHandlers> implements
ContainerEditorDialogPresenterWidget.MyView, Editor<ContainerDto> {
interface Binder extends UiBinder<PopupPanel, ContainerEditorDialogView> {
}
public interface Driver extends SimpleBeanEditorDriver<ContainerDto, ContainerEditorDialogView> {
}
#UiField
TextBox uuid;
#UiField
TextBox name;
#UiField
TextBox groups;
//#UiField
//TextBox device;
//public TextBox getDevice() {
// return device;
//}
#UiField
GroupListEditor groupListEditor;
#UiField
TextBox imei;
#UiField
TextBox type;
#UiField
TextBox user;
#UiField
Button okButton;
#UiField
Button cancelButton;
#Inject
ContainerEditorDialogView(Binder uiBinder, EventBus eventBus) {
super(eventBus);
initWidget(uiBinder.createAndBindUi(this));
ListEditor<String, GroupItemEditor> ed = null;
groupListEditor.asEditor().setValue(new ArrayList<String>());
}
#Override
public SimpleBeanEditorDriver<ContainerDto, ?> createEditorDriver() {
Driver driver = GWT.create(Driver.class);
driver.initialize(this);
return driver;
}
//Should this handled by a presenter?
#UiHandler("okButton")
void okButtonClicked(ClickEvent event) {
getUiHandlers().updateContainer();
hide();
}
#UiHandler("cancelButton")
void cancelButtonClicked(ClickEvent event) {
hide();
}
}
Thank you!
Update:
A version of the GroupListEditor without a separate ArrayList would look like this and is what i started with:
public class GroupListEditor extends Composite implements
IsEditor<ListEditor<String, GroupItemEditor>> {
private static StringListEditorUiBinder uiBinder = GWT
.create(StringListEditorUiBinder.class);
interface StringListEditorUiBinder extends
UiBinder<Widget, GroupListEditor> {
}
#UiField
FlowPanel pWidget;
#UiField
PushButton bAdd;
#UiField
FlowPanel pList;
private class StringItemEditorSource extends EditorSource<GroupItemEditor> {
#Override
public GroupItemEditor create(final int index) {
GroupItemEditor subEditor = new GroupItemEditor();
pList.insert(subEditor, index);
subEditor
.addDeleteHandler(new EditorDeleteEvent.EditorDeleteHandler() {
public void onEditorDeleteEvent(EditorDeleteEvent event) {
remove(index);
}
});
return subEditor;
}
#Override
public void dispose(GroupItemEditor subEditor) {
subEditor.removeFromParent();
}
#Override
public void setIndex(GroupItemEditor editor, int index) {
pList.insert(editor, index);
}
}
private ListEditor<String, GroupItemEditor> editor = ListEditor
.of(new StringItemEditorSource());
public GroupListEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("bAdd")
void onBAddClick(ClickEvent event) {
Log.debug("Add button clicked");
add();
}
private void add() {
String s = "Stuff";
editor.getList().add(s);
}
#Override
public ListEditor<String, GroupItemEditor> asEditor() {
return editor;
}
private void remove(final int index) {
editor.getList().remove(index);
}
}
Since i declare the Editor as
#UiField
GroupListEditor groupListEditor;
Should the required getter of ContainerDto not be named getGroupList() ?
You refer to DeviceDto, which is just carried around and should not interfere with the editor.
Since the GroupListEditor implements
IsEditor<ListEditor<String, GroupItemEditor>>
it should expect a List, right?
My ContainerDto has the field
protected ArrayList<String> groupList;
So that should be fine, i guess. This was my starting point before trying to manually call setValue.
When i that, i get this error, when clicking the "Add" button.
Caused by: java.lang.NullPointerException: null at
testproject.client.application.containers.editor.GroupListEditor.add(GroupListEditor.java:81)
at testproject.client.application.containers.editor.GroupListEditor.onBAddClick(GroupListEditor.java:76)
which refers to editor.getList().add(s) which means there is no list...
Update 2:
I changed the declaration of the UIField to:
#UiField
#Path("groupList")
GroupListEditor groupListEditor;
But i still get the NullPointerException when trying to add stuff to the list like before: editor.getList().add(s);
You don't have to manually call setList to pass the list to your SubEditor. That should be taken care of for you by the parent/container Editor.
However the Editor will use the UiField name to match the corresponding getter in your backing DTO.
In your above example this will only work if your DeviceDTO has a getGroupListEditor() getter that returns the type that your ListEditor expects (beacuse of #UiField GroupListEditor groupListEditor;).
If your DeviceDTO doesn't contain the corresponding getter you can do 3 things:
Rename your #UiField GroupListEditor groupListEditor; (i.e. groupItems)
Rename the getter in your DeviceDTO to getGroupListEditor
add Path('groupItems') to your #UiField GroupListEditor groupListEditor;
Solution 3 is usually the way to go:
#UiField
#Path('groupItems')
GroupListEditor groupListEditor;
Note: Change groupItems has to match the getter in your DeviceDTO that returns the group items.
Update:
This is how your DeviceDTO looks like and how you use Path to point your editor to the correct getter. As long as your groupList class variable is initialized to an empty ArrayList everything should work fine.
class DeviceDTO {
protected List<String> groupList = new ArrayList<String>();
public List<String> getGroupList() {
return groupList;
}
}
public class ContainerEditorDialogView extends
PopupViewWithUiHandlers<ContainerEditorDialogUiHandlers> implements
ContainerEditorDialogPresenterWidget.MyView, Editor<ContainerDto> {
....
#UiField
#Path("groupList")
GroupListEditor groupListEditor;
}
A want to make my Widget dragable..
A use GWT and d&d. It's my code, but it isn't work..
#SuppressWarnings("deprecation")
public class StickWidget extends Composite implements SourcesMouseEvents {
private static StickWidgetUiBinder uiBinder = GWT
.create(StickWidgetUiBinder.class);
#UiField Label title;
#UiField HTML content;
interface StickWidgetUiBinder extends UiBinder<Widget, StickWidget> {
}
public StickWidget(String title, String content, String width, String height) {
super();
initWidget(uiBinder.createAndBindUi(this));
this.content.setText(content);
this.title.setText(title);
this.setWidth(width);
this.setHeight(height);
}
public StickWidget(String title, String content) {
initWidget(uiBinder.createAndBindUi(this));
this.content.setText(content);
this.title.setText(title);
}
#Override
public void addMouseListener(MouseListener listener) {
// TODO Auto-generated method stub
}
#Override
public void removeMouseListener(MouseListener listener) {
// TODO Auto-generated method stub
}
}
and fragment of my EntryPoint:
StickWidget a = new StickWidget("gg", "gg", "20px", "200px");
DropTargetStick dropT = new DropTargetStick(new Label("fdgf"));
PickupDragController dragController = new PickupDragController (RootPanel.get(), false);
dragController.registerDropController(dropT);
dragController.makeDraggable(a);
I think I done all steps which allow me to drag & drop My widget.. But it doesn't work..
I solve this problem. You must implement HasAllMouseHandlers and HasClickHandlers. And in implementation give somelike this -
#Override
public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
// TODO Auto-generated method stub
return addDomHandler(handler, MouseUpEvent.getType());
}
I'm trying to bind a GWT view with its presentation layer, but it doesn't seem to be doing anything.
It's a Spring Roo GWT generated project and I'm trying to use the scaffold given as far as possible.
The view is a simple button (R.ui.xml) and the rest of the view is defined in R.java:
public class R extends Composite implements RPresenter.Display {
interface MyUiBinder extends UiBinder<Widget, R> {}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
#UiField Button myButton;
private ClickHandler buttonClickHandler = null;
public R(){
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("myButton")
void onButtonClick(ClickEvent event){
GWT.log('Button clicked');
if (buttonClickHandler != null){
GWT.log("buttonClickHandler event triggered");
buttonClickHandler.onClick(event);
}
}
#Override
public void setButtonClickHandler(ClickHandler buttonClickHandler) {
GWT.log("setButtonClickHandler");
this.buttonClickHandler = buttonClickHandler;
}
}
The presenter:
public class RPresenter {
public interface Display extends IsWidget {
void setButtonClickHandler(ClickHandler buttonClickHandler);
}
private final Display display;
private final EventBus eventBus;
#Inject
public RPresenter(EventBus eventBus, Display display){
this.display = display;
this.eventBus = eventBus;
bind();
}
private void bind(){
display.setButtonClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
GWT.log("onClick event triggered");
}
});
}
public void go(HasWidgets container){
container.add(display.asWidget());
}
}
And for my GIN module I use the generated ScaffoldModule in the ...client.scaffold.ioc package:
public class ScaffoldModule extends AbstractGinModule {
#Override
protected void configure() {
GWT.log("ScaffoldModule configure");
bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
bind(ApplicationRequestFactory.class).toProvider(RequestFactoryProvider.class).in(Singleton.class);
bind(PlaceController.class).toProvider(PlaceControllerProvider.class).in(Singleton.class);
//bind(RPresenter.Display.class).to(R.class).in(Singleton.class);
bind(RPresenter.Display.class).to(R.class);
}
static class PlaceControllerProvider implements Provider<PlaceController> {
private final EventBus eventBus;
#Inject
public PlaceControllerProvider(EventBus eventBus) {
this.eventBus = eventBus;
}
public PlaceController get() {
return new PlaceController(eventBus);
}
}
static class RequestFactoryProvider implements Provider<ApplicationRequestFactory> {
private final EventBus eventBus;
#Inject
public RequestFactoryProvider(EventBus eventBus) {
this.eventBus = eventBus;
}
public ApplicationRequestFactory get() {
ApplicationRequestFactory requestFactory = GWT.create(ApplicationRequestFactory.class);
requestFactory.initialize(eventBus);
return requestFactory;
}
}
}
In the GWT development mode console, the "ScaffoldModule configure" never displays, yet the generated scaffold seems to binding just fine as the events get passed along from component to component without a hitch, unless the binding is magically happening somewhere else and that is dead code.
When I put my bind(RPresenter.Display.class).to(R.class) in, it doesn't seem to do the binding. The only output I get in the GWT console is "Button clicked" which is called in the view and then nothing further. I'm clearly missing something, any ideas?
The call to GWT.log() will not output anything from an AbstractGinModule - classes that extend AbstractGinModule (ScaffoldModule in your situation) are used by gin at compile time to decide which concrete implementations to use for injected interfaces. From the rest of your description (i.e. that the UI shows up in the application) it appears that your dependency injection is working correctly.
I have a gwt VerticalPanel class that i need to handel KeyDown events for it.
the method i used to implement keyboard handler in my class is:
i add :
this.sinkEvents(Event.ONKEYDOWN);
to constructor
then i override method onBrowserEvent() to handle key down event.
#Override
public void onBrowserEvent(Event event) {
// TODO Auto-generated method stub
super.onBrowserEvent(event);
int type = DOM.eventGetType(event);
switch (type) {
case Event.ONKEYDOWN:
//call method to handle this keydown event
onKeyDownEvent(event);
break;
default:
return;
}
}
however this method doesn’t work for this VerticalPanel class.no KeyDown Event is fired when i press a key!
there are specific gwt widgets that support KeyDownHandler like Button etc..VerticalPanel is not one of them..so we need a work around to register a KeyDownHandler on a class extending VerticalPanel.
can you suggest an idea or hint?
thanks
You could create a Composite that wrappes a FocusPanel and a VerticalPanel. This way you can catch all key events provided the FocusPanel is focused. Simply delegate the needed methods to the panels:
public void onModuleLoad() {
ExtendedVerticalPanel panel = new ExtendedVerticalPanel();
panel.add(new Label("some content"));
panel.addKeyDownHandler(new KeyDownHandler() {
#Override
public void onKeyDown(KeyDownEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
Window.alert("enter hit");
}
}
});
RootPanel.get().add(panel);
}
private class ExtendedVerticalPanel extends Composite implements HasWidgets, HasAllKeyHandlers {
private VerticalPanel fVerticalPanel;
private FocusPanel fFocusPanel;
public ExtendedVerticalPanel() {
fVerticalPanel = new VerticalPanel();
fFocusPanel = new FocusPanel();
fFocusPanel.setWidget(fVerticalPanel);
initWidget(fFocusPanel);
}
#Override
public void add(Widget w) {
fVerticalPanel.add(w);
}
#Override
public void clear() {
fVerticalPanel.clear();
}
#Override
public Iterator<Widget> iterator() {
return fVerticalPanel.iterator();
}
#Override
public boolean remove(Widget w) {
return fVerticalPanel.remove(w);
}
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
return fFocusPanel.addKeyUpHandler(handler);
}
#Override
public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
return fFocusPanel.addKeyDownHandler(handler);
}
#Override
public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
return fFocusPanel.addKeyPressHandler(handler);
}
}
UPDATE
Your question on how to prevent the browser from scrolling when the arrow keys are pressed. Here a small example that works for me:
public void onModuleLoad() {
ExtendedVerticalPanel panel = new ExtendedVerticalPanel();
// make panel reeeeaally big
panel.setHeight("3000px");
panel.add(new TextBox());
panel.addKeyDownHandler(new KeyDownHandler() {
#Override
public void onKeyDown(KeyDownEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_DOWN) {
Window.alert("down hit");
event.preventDefault();
}
}
});
RootPanel.get().add(panel);
}
Add the handlers you need and call preventDefault() on the events the browser must not take care of.