Java GWT TreeViewModel SelectionHandler - java

In my project I need to fire an event after a node was clicked in my CellTree. I solved this with the following code.
model.setSelectionHandler(new SelectionChangeEvent.Handler()
{
#Override
public void onSelectionChange(SelectionChangeEvent event)
{
//My logic is here
}
});
The problem is that this only works if the node is not selected already. Clicking the node again will not fire the event. Is there a click handler or another event which is fired after a node was clicked?

Please try with SelectionHandler api .

This can be achieved by creating your own TreeItem that implements ClickHandler
public class CustomTreeItem extends TreeItem implements ClickHandler
{
//classes logic here
#Override
public void onClick(ClickEvent event)
{
// TODO Auto-generated method stub
}
}

Sometimes I use something like this:
model.setSelectionHandler(new SelectionChangeEvent.Handler()
{
#Override
public void onSelectionChange(SelectionChangeEvent event)
{
SomeType selected = model.getSelectedObject();
if (selected != null)
{
// Logic here...
model.clear();
}
}
});
But this solution obviously removes visual feedback what was selected.

You could add a DOM handler to your CellTree using [Widget.addDomHandler](http://www.gwtproject.org/javadoc/latest/com/google/gwt/user/client/ui/Widget.html#addDomHandler(H, com.google.gwt.event.dom.client.DomEvent.Type)):
cellTree.addDomHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
// TODO: check if a node is selected and it was clicked here
}
}, ClickEvent.getType());
Additionally you might need to prevent calling the handler twice if you use the selection handler as well and click a node.
Just a side note: Unfortunately I did not see an easy way to determine if the user actually clicked on a tree item like a bounds check for the click coordinates. So this might get a bit harder to achieve.

Related

GWT Widget Event Handler is Not Working When The Widget Inserted into GWT DIV Element

I have a custom widget which is can accept a widget inside of it. Here is the code:
public class CustomDivWidget extends Widget {
protected Element divElement = DOM.createDiv();
public CustomDivWidget() {
divElement.getStyle().setWidth(100, Unit.PX);
divElement.getStyle().setHeight(100, Unit.PX);
divElement.getStyle().setBorderStyle(BorderStyle.SOLID);
divElement.getStyle().setBorderWidth(1, Unit.PX);
divElement.getStyle().setBorderColor("blue");
setElement(divElement);
}
public void add(Widget child) {
divElement.appendChild(child.getElement());
}
}
Then this is how I used it:
public void onModuleLoad() {
CustomDivWidget customDiv = new CustomDivWidget();
TextButton button = new TextButton("Button 1");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("Button 1 clicked!");
}
});
customDiv.add(button);
RootPanel.get().add(customDiv);
}
When I run it, it show correctly the widget I want like this :
But the problem is, the click handler was not working when I tried to click the button. The questions are :
Why it is not working?
What should I do to make it working?
Any comments or suggestions will be appreciated. Thanks and regards.
I think you are bypassing GWT's event system this way (I'm not sure though). However, why not using a FlowPanel?
protected FlowPanel fp = new FlowPanel();
public CustomDivWidget() {
fp.getElement().getStyle().setWidth(100, Unit.PX);
fp.getElement().getStyle().setHeight(100, Unit.PX);
fp.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
fp.getElement().getStyle().setBorderWidth(1, Unit.PX);
fp.getElement().getStyle().setBorderColor("blue");
setElement(fp.getElement());
}
Apart from that, why are you using DOM elements instead of widgets? Using widgets instead of having to deal with the DOM is one of the key features of a toolkit like GWT (just my opinion here).
Edit : try to attach the handler directly to the DOM, to see if it makes any difference :
DOM.setEventListener(button.getElement(), new EventListener() {
#Override
public void onBrowserEvent(Event e) {
switch (DOM.eventGetType(e)) {
case Event.ONCLICK:
System.out.println("click");
break;
}
}
});

ChangeEvent is not received by other Composite Widgets

I have many ItemWidget which extends a Composite. If a click event is received on one of the items a change event should be fired and other item widgets should receive this event.
It tried the following:
public class ItemWidget extends Composite implements HasChangeHandlers {
FocusPanel focusPanel = new FocusPanel();
public ItemWidget() {
Label label = new Label("click me");
focusPanel.add(label);
initWidget(focusPanel);
focusPanel.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// inform other items
fireChange();
}
});
addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent event) {
GWT.log("ChangeEvent received");
}
});
}
private void fireChange() {
GWT.log("fire event");
NativeEvent nativeEvent = Document.get().createChangeEvent();
ChangeEvent.fireNativeEvent(nativeEvent, this);
}
#Override
public HandlerRegistration addChangeHandler(ChangeHandler handler) {
return addDomHandler(handler, ChangeEvent.getType());
}
}
Using the above code only the item which is clicked receives the ChangeEvent.
How can I receive the ChangeEvent on all the other item widgets too?
Typically, when an event fires, a presenter/Activity makes the necessary changes to the other widgets.
If you want multiple copies of you widget to listen to the same event, you may be better off using the EventBus, especially if you use this pattern more than once:
How to use the GWT EventBus
Then each of your ItemWidget can fire a custom event that all copies of this widget listen to.
By looking at the API quickly I think your problem comes from your implementation of
public void fireEvent(GwtEvent<?> event)
You did not override it in your composite view. You did not create any mechanism to send the event to the other widgets.
Have a deeper look at the method fireNativeEvent
http://www.gwtproject.org/javadoc/latest/com/google/gwt/event/dom/client/DomEvent.html
When you use ChangeEvent.fireNativeEvent the second param hasHandlers should be a kind of event bus.
To do what you want to do I think you need all the items to be on this eventBus.

Disable Key press event temporarily

Is it possible, in GWT, to temporarily suspend a certain key press until it is desired to allow that key press again? Like a global suspension. I have an issue where when I open the date picker on a RelativeDateItem in SmartGWT, that it causes the entire page to scroll out of view until the user hits the UP arrow again.
This is working for me for a JEditorPane:
#Override
public void keyTyped(KeyEvent evt) {
if (inTag() > -1) {
evt.consume();
}
The javadoc shows:
void java.awt.event.InputEvent.consume()
consume
public void consume()
Consumes this event so that it will not be processed in the default manner by the source which originated it.
The JEditorPane is in a JFrame which implements KeyListener and the JEditorPane does:
jEditorPaneSource.addKeyListener(this);
datepicker.addKeyPressHandler(new com.smartgwt.client.widgets.events.KeyPressHandler() {
public void onKeyPress(
com.smartgwt.client.widgets.events.KeyPressEvent event) {
event.preventDefault();
}
});
I believe you can block it with this.
Event.addNativePreviewHandler(new NativePreviewHandler(){
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
EventTarget eventTarget = event.getNativeEvent().getEventTarget();
Element el = Element.as(eventTarget);
switch (event.getTypeInt()){
case Event.ONKEYPRESS:
case Event.ONKEYUP:
case Event.ONKEYDOWN:
if (el.getNodeName().equalsIgnoreCase("NODE FROM DATEPICKER")) {
if (event.getNativeEvent().getKeyCode() == "yourKeyCodeToBlock"
event.cancel();
}
}
break;
}
}
});

In GWT is there a way to create a KeyPressEvent for the entire view instead of a single input element?

Right now I have the following code working:
#UiHandler("usernameTextBox")
void onUsernameTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
#UiHandler("passwordTextBox")
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
void keyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}
I would like the ability to have just one listener for all elements on the view without duplicating an event for each textbox.
The end goal is that if they press enter, regardless of where they are on the page, it should submit the form.
Thanks!
What works, but still requires you to specify it for each widget, but doesn't require duplicate code:
#UiHandler({"usernameTextBox", "passwordTextBox"})
void onPasswordTextBoxKeyPress(KeyPressEvent event) {
keyPress(event);
}
Yes jackcrews is correct. Also you can try the following. It may be VerticalPanel, DockLayoutPanel etc....
UiBinder.ui.xml
<gwt:VerticalPanel ui:field="mainPanel">
<gwt:Label>Name</gwt:TextBox>
<gwt:TextBox ui:field="textBox">
</gwt:VerticalPanel>
Main.java
#UiField
VerticalPanel mainPanel;
public Main() {
focushandler();
}
void focusHandler() {
mainPanel.addDomHandler(new Handler(), KeyPressEvent.getType());
}
final class Handler implements KeyPressHandler {
#Override
public void onKeyPress(KeyPressEvent event) {
//Code what you expect
}
}
Actually this has more number of lines. But it is good practice.
Regards,
Gnik
I found out that the g:FocusPanel allows me to capture events for everything inside the panel.
#UiHandler("focusPanel")
void onFocusPanelKeyPress(KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
submit();
}
}

MouseEvent of JTabbedPane

I want to show a small popup menu when you right-click a tab, now this is working fine but when you right click it also selects that tab which is unwanted.
So my idea was to make a new class, extend JTabbedPane and recode those mouse events. Problem is that I have no idea where to start, I was browsing its source but I can't find what part is handeling the mouseEvents.
Tabs.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
if(me.getButton()==3){
int tabNr = ((TabbedPaneUI)Tabs.getUI()).tabForCoordinate(Tabs, me.getX(), me.getY());
Component clickedTab = EventsConfig.window.MainTabs.getComponentAt(tabNr);
newMenu(clickedTab, me.getX(), me.getY());
}
}
});
Beware: dirty hack ahead! The only reason I recommend it, is that I consider the behaviour (select on right press) a bug in the BasicTabbedPaneUI's Handler.
The basic idea is to grab the listener installed by the ui, remove it, wrap into a custom listener which delegates everything except a right pressed to the original and add that to the pane:
private void installMouseListenerWrapper(JComponent tabbedPane) {
MouseListener handler = findUIMouseListener(tabbedPane);
tabbedPane.removeMouseListener(handler);
tabbedPane.addMouseListener(new MouseListenerWrapper(handler));
}
private MouseListener findUIMouseListener(JComponent tabbedPane) {
MouseListener[] listeners = tabbedPane.getMouseListeners();
for (MouseListener l : listeners) {
if (l.getClass().getName().contains("$Handler")) {
return l;
}
}
return null;
}
public static class MouseListenerWrapper implements MouseListener {
private MouseListener delegate;
public MouseListenerWrapper(MouseListener delegate) {
this.delegate = delegate;
}
#Override
public void mouseClicked(MouseEvent e) {
delegate.mouseClicked(e);
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) return;
delegate.mousePressed(e);
}
#Override
public void mouseReleased(MouseEvent e) {
delegate.mouseReleased(e);
}
#Override
public void mouseEntered(MouseEvent e) {
delegate.mouseEntered(e);
}
#Override
public void mouseExited(MouseEvent e) {
delegate.mouseExited(e);
}
}
then you have to add JPopupMenu (or JToolTip on MouseHoverOver ) to the JTabbedPane
A possible workaround is to set your custom tab component for each tab - see JTabbedPane#setTabComponentAt(...). Add a mouse handler to your custom tab component and redispatch left click events to the tabbedPane as described at http://www.jyloo.com/news/?pubId=1315817317000.
The custom tab component can be a simple JLabel (used for the tab title) or a container for multiple components. Depending on your requirements you can e.g. add an arrow button which will open a popup menu by left clicking the related button.
This article will helpful for removing unwanted tab selection when you click right mouse button.
Stop right click Event on JTabbedPane
I liked to add more about removing Mouse Listeners.
Try to override the method rather than removing it. It's better for future code updates.
The problem is BasicTabbedPaneUI's have inner class called Handler. That handler class override Mouse Listener.
To stop right click tab selection and show pop up menu; we need to override this method in BasicTabbedPaneUI,
protected MouseListener createMouseListener() {
return getHandler();
}
To get better look and feel we should override SynthTabbedPaneUI class.
SynthTabbedPaneUI is extends BasicTabbedPaneUI.
So our inner class is like this,
private class SynthTabbedPaneUIWrapper extends SynthTabbedPaneUI
{
private MouseAdapter menuAdapter;
private MouseAdapter getMenuAdapter()
{
if (menuAdapter == null)
{
menuAdapter =
new MouseAdapter()
{
#Override
public void mouseReleased(final MouseEvent e)
{
//implement to stop right click tab selection
//implement to show pop up menu
}
};
}
}
#Override
protected MouseListener createMouseListener()
{
return getMenuAdapter();
}
}
After that we can set our custom UI object into TabbedPane.
tabbedPane.setUI(new SynthTabbedPaneUIWrapper());

Categories

Resources