GWT: How to disable the anchor link event when clicked - gwt

I want to disable the anchor link event when it clicked one time. I used anchor.setenabled(false) but nothing happend. When I click the same button again the event e is true. I want false at that time.
public void onCellClick(GridPanel grid, int rowIndex, int colindex,EventObject e)
{
if(rowIndex==0 && colindex==2){
tomcatHandler = "Start";
anchorStart.setEnabled(false);
}else if(rowIndex==0 && colindex==3){
tomcatHandler = "Stop";
****anchorStop.setEnabled(false);
anchorStart.setEnabled(false);
anchorRestart.setEnabled(true);****
}else if(rowIndex==0 &&colindex==4){
tomcatHandler = "Restart";
anchorRestart.setEnabled(false);
}
AdminService.Util.getInstance().tomcat(tomcatHandler,new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
imageChangeEvent(result);
}
#Override
public void onFailure(Throwable caught) {
}
});}

Anchors in GWT have always had a problem with setEnabled() because HTML doesn't support such a property. A quick workaround is to create a new widget that subclasses GWT's Anchor, adding the following override:
#Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONDBLCLICK:
case Event.ONFOCUS:
case Event.ONCLICK:
if (!isEnabled()) {
return;
}
break;
}
super.onBrowserEvent(event);
}
This disables the passing of the browser event to GWT's Anchor class (summarily disabling all related handlers) when the link is double clicked, focused or clicked and is in a disabled state.
Source

It doesn't seem to actually disable the anchor, but it does retain the status that has been set with anchor.setEnabled(), so just test that within your handler e.g.
myAnchor.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent evt) {
// write to filter and then call reload
if (((Anchor) evt.getSource()).isEnabled()) {
//do stuff
}
}
});

Related

My selection listener doesn't seem to be registering properly

I am creating an Eclipse RCP application with multiple views. One of my views is a multi-page editor view. Each of those pages has a a master/details block. I need to register all of those TableViewers as selection providers for my other view to listen to.
After much research online, I came across this article about multiple selection providers in a single view. I followed the instructions to create this selection provider for multiple viewers.
class MyMultipleSelectionProvider implements ISelectionProvider {
private final ListenerList selectionListeners = new ListenerList();
private ISelectionProvider delegate;
private final ISelectionChangedListener selectionListener = new ISelectionChangedListener() {
#Override
public void selectionChanged(final SelectionChangedEvent event) {
if (event.getSelectionProvider() == AdaptabilityProfileSelectionProvider.this.delegate) {
fireSelectionChanged( event.getSelection() );
}
}
};
/**
* Sets a new selection provider to delegate to. Selection listeners
* registered with the previous delegate are removed before.
*
* #param newDelegate new selection provider
*/
public void setSelectionProviderDelegate(final ISelectionProvider newDelegate) {
if (this.delegate == newDelegate) {
return;
}
if (this.delegate != null) {
this.delegate.removeSelectionChangedListener(this.selectionListener);
}
this.delegate = newDelegate;
if (newDelegate != null) {
newDelegate.addSelectionChangedListener(this.selectionListener);
fireSelectionChanged(newDelegate.getSelection());
}
}
#Override
public void addSelectionChangedListener(final ISelectionChangedListener listener) {
this.selectionListeners.add(listener);
}
#Override
public ISelection getSelection() {
return this.delegate == null ? null : this.delegate.getSelection();
}
#Override
public void removeSelectionChangedListener(final ISelectionChangedListener listener) {
this.selectionListeners.remove(listener);
}
#Override
public void setSelection(final ISelection selection) {
if (this.delegate != null) {
this.delegate.setSelection(selection);
}
}
protected void fireSelectionChanged(final ISelection selection) {
fireSelectionChanged(this.selectionListeners, selection);
}
private void fireSelectionChanged(final ListenerList list, final ISelection selection) {
final SelectionChangedEvent event = new SelectionChangedEvent(this.delegate, selection);
final Object[] listeners = list.getListeners();
for (int i = 0; i < listeners.length; i++) {
final ISelectionChangedListener listener = (ISelectionChangedListener) listeners[i];
listener.selectionChanged(event);
}
}
}
I added a focusListener on all of the edior's viewers so they become the delegate:
tree.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(final FocusEvent e) {
editor.getSelectionProvider().setSelectionProviderDelegate(MyEditorPage.this.treeViewer);
}
});
And I registered this as the selection provider for my editor:
site.setSelectionProvider( this.selectionProvider );
Then, within my view that needs to hear about the selection, I registered a selection listener for this editor:
getSite().getPage().addSelectionListener(MyEditor.ID, this.selectionListener);
When I run the application, I see that the delegate is being changed and the selection events are being fired. However, the listener list is empty.
I am never calling addSelectionChangeListener() directly. I was under the impression that that was what the selection service is for. Am I wrong? Should I be calling it? If so, when? If not, who is supposed to be adding the listener, and why isn't it happening?
If your code is based on FormEditor (or MultiPageEditorPart) then the selection provider is set to MultiPageSelectionProvider at the end of the init method. This may be overriding your site.setSelectionProvider call.
Using:
#Override
public void init(IEditorSite site, IEditorInput input)
throws PartInitException {
super.init(site, input);
site.setSelectionProvider(this.selectionProvider);
}
should make sure your provider is the one used.

GWT Drag and Drop File Upload not working

So I have implemented a very simple drag and drop file upload widget. Basically my widget is a vertical panel with a couple of labels and a button inside. The user can either drag file into vertical panel or click button and browse for file.
My problem is that when I drag a file into the vertical panel it fires the DragLeaveEvent every time I drag the item over the space that the labels or button occupies. I want it to know that the item is in the vertical panel even when it is on top of the label or button. Im sure I am missing something simple. I provide the drag functionality by adding these dom handlers to the vertical panel:
addDomHandler(new DragEnterHandler() {
#Override
public void onDragEnter(DragEnterEvent event) {
System.out.println("drag enter");
highlight(true);
}
}, DragEnterEvent.getType());
addDomHandler(new DragLeaveHandler() {
#Override
public void onDragLeave(DragLeaveEvent event) {
System.out.println("drag leave");
highlight(false);
}
}, DragLeaveEvent.getType());
addDomHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
}
}, DragOverEvent.getType());
addDomHandler(new DropHandler() {
#Override
public void onDrop(DropEvent event) {
System.out.println("drop");
// stop default behaviour
event.preventDefault();
event.stopPropagation();
// starts the fetching, reading and callbacks
if (fileUploadHandler != null) {
handleFiles(event.getDataTransfer(), fileUploadHandler);
}
highlight(false);
}
}, DropEvent.getType());
Check that the event target is a child (or grand child) of your panel, or in this case maybe rather whether the event target is exactly your panel's element:
if (verticalPanel.getElement().isOrHasChild(Node.as(event.getNativeEvent().getEventTarget()))) {
// within the panel (possibly on a child)
}
if (verticalPanel.getElement() == Node.as(event.getNativeEvent().getEventTarget())) {
// targetting exactly the panel (e.g. leaving the panel, not one of its children)
}
Through lots of research I have come to the only solution I could find. I set highlight to true in the dragover handler instead of drag enter.
panel.addDomHandler(new DragEnterHandler() {
#Override
public void onDragEnter(DragEnterEvent event) {
}
}, DragEnterEvent.getType());
panel.addDomHandler(new DragLeaveHandler() {
#Override
public void onDragLeave(DragLeaveEvent event) {
highlight(false);
}
}, DragLeaveEvent.getType());
panel.addDomHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
highlight(true);
}
}, DragOverEvent.getType());
panel.addDomHandler(new DropHandler() {
#Override
public void onDrop(DropEvent event) {
// stop default behaviour
event.preventDefault();
event.stopPropagation();
// starts the fetching, reading and callbacks
handleFiles(event.getDataTransfer());
highlight(false);
}
}, DropEvent.getType());
I copy pasted your code, but also added a:
RootPanel.get().addHandler(dropHandler, DropEvent.getType());
My drophandler looks like this:
DropHandler dropHandler = new DropHandler() {
#Override
public void onDrop(DropEvent event) {
handleFiles(event.getDataTransfer(), new FileUploadHandler() {
#Override
public TYPE specifyFileType() {
return TYPE.BINARY;
}
#Override
public void handleFileContent(String fileName, String fileContent) {
// do stuff with filename and content
}
#Override
public boolean checkFileName(String fileName) {
return true;
}
});
event.preventDefault();
event.stopPropagation();
}
};
and the file-upload interface:
public interface FileUploadHandler {
static public enum TYPE {
TEXT, BINARY, DATAURL
};
// check the filename and extension and return true if you are happy with
// proceeding
// returnning false will prevent the file from being read
boolean checkFileName(String fileName);
// tell the method to use to read this file
TYPE specifyFileType();
// do your stuff here, eg upload to a server
void handleFileContent(String fileName, String fileContent);
}
and the handle files func: (note you will have to change classpath to the FileUploadHandler-interface)
// native method to make use of the HTML5 file API functionality
private final native void handleFiles(JavaScriptObject dataTransfer, FileUploadHandler fileUploadHandler) /*-{
var files = dataTransfer.files;
var i;
var file;
var reader = new FileReader();
for (i = 0; i < files.length; i++) {
file = files[i];
if (fileUploadHandler.#<classpath_to>.FileUploadHandler::checkFileName(Ljava/lang/String;)(file.name)) {
var type = fileUploadHandler.#<classpath_to>.FileUploadHandler::specifyFileType()();
reader.onload = function(e) {
fileUploadHandler.#<classpath_to>.FileUploadHandler::handleFileContent(Ljava/lang/String;Ljava/lang/String;)(file.name, e.target.result);
}
if (type == "TEXT") {
reader.readAsText(file);
} else if (type == "BINARY") {
reader.readAsBinaryString(file);
} else if (type == "DATAURL") {
reader.readAsDataURL(file);
// not supported
} else if (type == "ARRAYBUFFER") {
reader.readAsArrayBuffer(file);
} else {
}
}
}
}-*/;

How to capture doubleClickEvent in GWT CellTable

I'm trying to make a GWT CellTable catch events of type DoubleClickEvent, but while the CellTable correctly receives events of type ClickEvent when a row is clicked in the UI, it not see any DoubleClickEvent when the row is double-clicked.
So, if I click a row in the UI, the handler declared for ClickEvent is correctly triggered, but if I double click the handler declared for DoubleClickEvent is not triggered, instead.
Am I doing something wrong or CellTable itself cannot handle DoubleClickEvent at all?
In the latter case, what could be a good way to capture double-clicks in a table?
Below, the code for my CellTable declaration:
CellTable<ServiceTypeUI> contentTable = new CellTable<ServiceTypeUI>(10, style);
contentTable.setSelectionModel(new SingleSelectionModel<ServiceTypeUI>());
contentTable.addHandler(new DoubleClickHandler() { // HANDLER NOT CORRECTLY TRIGGERED
#Override
#SuppressWarnings("unchecked")
public void onDoubleClick(DoubleClickEvent event) {
presenter.doubleClickHandler(event);
}
}, DoubleClickEvent.getType());
contentTable.addHandler(new ClickHandler() { // HANDLER CORRECTLY TRIGGERED
#Override
#SuppressWarnings("unchecked")
public void onClick(ClickEvent event) {
presenter.clickHandler(event);
}
}, ClickEvent.getType());
I've also tried removing ClickEvent handler declaration and the SelectionModel declaration, to avoid that any of those capture the DoubleClickEvent event and treat it as a ClickEvent but the DoubleClickHandler has not been triggered even in this case.
CellTable<ServiceTypeUI> contentTable = new CellTable<ServiceTypeUI>(10, style);
contentTable.addHandler(new DoubleClickHandler() { // HANDLER NOT CORRECTLY TRIGGERED
#Override
#SuppressWarnings("unchecked")
public void onDoubleClick(DoubleClickEvent event) {
presenter.doubleClickHandler(event);
}
}, DoubleClickEvent.getType());
SingleSelectionModel<T> selectionModel
= new SingleSelectionModel<T>();
cellTable.setSelectionModel(selectionModel);
cellTable.addDomHandler(new DoubleClickHandler() {
#Override
public void onDoubleClick(final DoubleClickEvent event) {
T selected = selectionModel
.getSelectedObject();
if (selected != null) {
//DO YOUR STUFF
}
}
},
DoubleClickEvent.getType());
You have to replace the T with the your "ServiceTypeUI" . The value selected will be the object which was been chosen from the user.

style for GXT menu button

I see GXT Menu can only be set on CellButtonBase subclasses' instances through setMenu() method.
I'd like to show an image instead of a button and show a menu when user clicks that image. unfortunately, Image is not a subclass of CellButtonBase and thus I can't attach a GXT Menu to it.
so how can I make TextButton (which seems to be my only choice here) look like an image if I have to use it?
There's no documentation or examples on this subject. I asked on Sencha GXT forum support, but got no response.
ok, I found a way to do this without TextButton. add an Image and call menu.show(...) in click handler.
private void createMenu() {
menu = new Menu();
Image menuButtonImage = new Image(Resources.INSTANCE.nav_preferences());
menuButtonImage.addStyleName(CSS.header_bar_icon());
menuButtonImage.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
menu.showAt(getAbsoluteLeft(), getAbsoluteTop() + MENU_OFFSET_FROM_IMAGE_TOP);
}
});
menu.addShowHandler(new ShowEvent.ShowHandler() {
#Override
public void onShow(ShowEvent event) {
highlight();
}
});
menu.addHideHandler(new HideEvent.HideHandler() {
#Override
public void onHide(HideEvent event) {
removeHighlight();
}
});
menu.setStyleName(CSS.menu());
add(menuButtonImage);
}
private void addUserSettings() {
MenuItem userSettingsItem = new MenuItem("User Settings");
userSettingsItem.addSelectionHandler(new SelectionHandler<Item>() {
#Override
public void onSelection(SelectionEvent<Item> event) {
_coreLayout.showUserSettingsPage();
}
});
userSettingsItem.setStyleName(CSS.menu_item());
menu.add(userSettingsItem);
}
private void highlight() {
addStyleName(CSS.header_bar_icon_box_selected());
}
private void removeHighlight() {
removeStyleName(CSS.header_bar_icon_box_selected());
}

GWT: how can i add/remove a button in a celltable on the go

I have this button cell in my CellTable
ButtonCell reListCell = new ButtonCell();
reListColumn = new Column<EmployerJobs, String>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return "ReList";
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
but i only want this cell to be appear if the below condition pass
public void getDateDiff(final EmployerJobs object) {
rpcService.getDateDiff(object.getJobValidDate(), new AsyncCallback<Boolean>() {
public void onFailure(Throwable caught) {
}
public void onSuccess(Boolean jobExpired) {
if(jobExpired) {
// HERE I WANT TO SHOW MY RELISTCELL, means if the job is expired only then
// there will be a button showing relist would be appear in that row ,for
// the jobs which are not expired NO button should appear..
}
}
});
}
how can i achieve this?
thanks
I agree with DTing.
Quering the backend for each cell/row is not really efficient.
I would rather put the info (jobExpired) into your EmployerJobs class and transfer the info when you request the list of your EmployerJobs to be displayed in your CellTable.
You can update the list periodically to account for changes (see the expenses sample on how to do that).
But to your initial question (hiding the cell). There are two solutions:
Use an ActionCell and override the render method.
ActionCell:
ActionCell<EmployerJobs> reListCell = new ActionCell<EmployerJobs>("ReList",
new ActionCell.Delegate<EmployerJobs>() {
#Override
public void execute(EmployerJobs object) {
// code to be executed
}
})
{
#Override
public void render(Cell.Context context,EmployerJobs value,SafeHtmlBuilder sb) {
if (value.isJobExpired()) // isJobExpired returns the field jobExpired.
super.render(context,value,sb);
}
};
reListColumn = new Column<EmployerJobs, EmployerJobs>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return object;
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
Use a ButtonCell and override the render method of your Column.
ButtonCell:
ButtonCell reListCell = new ButtonCell();
reListColumn = new Column<EmployerJobs, String>(reListCell) {
#Override
public String getValue(EmployerJobs object) {
return "ReList";
}
#Override
public void render(Cell.Context context,EmployerJobs object,SafeHtmlBuilder sb) {
if (value.isJobExpired()) // isJobExpired returns the field jobExpired.
super.render(context,value,sb);
}
};
ctJobs.addColumn(reListColumn,
EmployerDashBoardConstants.EMPTYHEADERCOLUMN);
Just tried Umit solution #2 ButtonCell. It works!
To link an specific action to the button, reListColumn.setFieldUpdater(new FieldUpdater....
would be needed
I tried ButtonCell solution too. But if you click in a cell who as no button then an error on client side occur:
com.google.gwt.core.client.JavaScriptException: (TypeError) #com.google.gwt.core.client.impl.Impl::apply(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)([JavaScript object(445), JavaScript object(240), JavaScript object(637)]): parent is null
So I added this to override the Event and avoid Event if I want:
#Override
public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context,
Element parent, YourObject object, NativeEvent event) {
if (object.isCompleted())
super.onBrowserEvent( context, parent, object, event);
}
I don't know if it's the better way to do it but it works.