I want make a validation when pulse close button of tab in eclipse RCP 4 application and if some validation fails then prevent de close.
If you don't want to use part.setDirty(true) together with an ISaveHandler like greg-449 montioned, you could listen to the model events and correct things there. Something in the direction of this:
public class PreventCloseAddon {
#PostConstruct
public void init(final IEventBroker eventBroker, final EPartService partService) {
EventHandler tbrHandler = new EventHandler() {
#Override
public void handleEvent(Event event) {
if (!UIEvents.isSET(event))
return;
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (element instanceof MPart) {
MPart part = (MPart) element;
if (!part.isToBeRendered()) {
// ... validate here ...
part.setToBeRendered(true);
partService.activate(part);
}
}
}
};
eventBroker.subscribe(UIEvents.UIElement.TOPIC_TOBERENDERED, tbrHandler);
}
}
You should be aware that the part will be rendered again with this code.
Related
How can I open a popup without using AjaxRequestTarget or open a pop up without a click event occurring (AjaxRequestTarget is fine)? I am using wicket/Java
Below is what i tried but however i receive a NullException
dialog = new MessageDialog("dialog", "Notice", "Decision Matches ", DialogButtons.OK_CANCEL, DialogIcon.WARN) {
public void onClose(AjaxRequestTarget target, DialogButton button) {
}
};
AjaxRequestTarget target = RequestCycle.get().find(AjaxRequestTarget.class);
dialog.open( target);
Your code isn't working since you don't have an AjaxRequestTarget present when you just render your page. The easiest approach here would be to initiate an AjaxCallback after your page is loaded and trigger your logic there.
public class HomePage extends WebPage {
private AbstractDefaultAjaxBehavior onPageLoadBehavior;
public HomePage(final PageParameters parameters) {
super(parameters);
(...)
onPageLoadBehavior = new AbstractDefaultAjaxBehavior() {
#Override
protected void respond(AjaxRequestTarget target) {
//will be called after Dom is ready
dialog.open(target);
}
};
add(onPageLoadBehavior);
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
//OnDomReady execute our onPageLoadBehavior callback
response.render(OnDomReadyHeaderItem.forScript(onPageLoadBehavior.getCallbackScript()));
}
}
In my application I have a screen where I use Accelerators. I'm using the function key F3 to execute an operation in my application. It works fine everytime, but when I click in any TextField on this screen the function key doesn't execute.
Here is the code where I set the Accelerator:
scene.getAccelerators().put(
new KeyCodeCombination(KeyCode.F3),
new Runnable() {
#Override
public void run() {
// do sth here
}
}
);
When I click my textfield and then hit the F3 function key it doesn't work.
Someone knows the solution?
This works for me using Java 1.8.0_45. However I encounter a similar issue with an editable Combobox field.
Edited:
Upon further investigation it does seem to occur with text field as well. I worked around it using the following custom class in place of text field:
public class ShortcutFriendlyTextField extends TextField{
public ShortcutFriendlyTextField() {
super();
addEventHandler(KeyEvent.KEY_RELEASED,new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
//handle shortcuts if defined
Runnable r=getScene().getAccelerators().get(new KeyCodeCombination(event.getCode()));
if(r!=null) {
r.run();
}
}
});
}
}
This answer is based on tikerman's. I added the code to handle modifier keys.
if (!event.getCode().isModifierKey()) {
Consumer<KeyCombination.Modifier[]> runAccelerator = (modifiers) -> {
Runnable r = getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), modifiers));
if (r != null) {
r.run();
}
};
List<KeyCombination.Modifier> modifiers = new ArrayList<>();
if (event.isControlDown()) modifiers.add(KeyCodeCombination.CONTROL_DOWN);
if (event.isShiftDown()) modifiers.add(KeyCodeCombination.SHIFT_DOWN);
if (event.isAltDown()) modifiers.add(KeyCodeCombination.ALT_DOWN);
runAccelerator.apply(modifiers.toArray(new KeyCombination.Modifier[modifiers.size()]));
}
Edit: fix consumer spelling.
If you have accelerators setup else where, such as a MenuBar, using some of the other solutions will cause the shortcut to be executed twice.
In my case, using modifiers with my shortcut (SHIFT + F3) works while in focus in the text area, but not while using just an accelerator such as just F3.
I set mine up to only use the event handler for shortcuts that do not use a modifier.
public static final double JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version"));
public static void makeInputFieldShortCutFriendly(Node node) {
//this bug wasn't fixed until 9.0
if (JAVA_VERSION < 9) {
node.addEventHandler(KeyEvent.KEY_RELEASED, (KeyEvent event) -> {
if (!event.getCode().isModifierKey()) {
if (!event.isAltDown() && !event.isShiftDown() && !event.isAltDown()) {
Runnable r = node.getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), KeyCodeCombination.SHORTCUT_ANY));
if (r != null) {
r.run();
}
}
}
});
}
}
Edit: No modifier shortcuts was fixed in Java 9. Given the popularity of JDK 8 right now, we should probably provide some backwards capatability or request users update there JRE to 9+.
I you are using JavaFx+Scene builder then just make a function that redirect all the event to the respective functions and then add this function to every element in the scene with OnKeyReleased event
today I changed my Eclipse IDE from 3.7 to 4.2 and my plugin-project has a new feature in the Statusbar of the UI called QuickAccess. But I dont need it, so how can I disable this feature, because the position of my button bar has changed...
For all who have the same problem, it seems that this new feature is hardcoded and can't be disabled :/ https://bugs.eclipse.org/bugs/show_bug.cgi?id=362420
Go to Help --> Install New Software
https://raw.github.com/atlanto/eclipse-4.x-filler/master/pdt_tools.eclipse-4.x-filler.update/
Install that Plugin and Restart the Eclipse. Quick Access automatically hide.
or else you have an option to hide Window --> Hide Quick Access.
Here's a post that shows a way to hide it with CSS. Verified with Eclipse 4.3
Lars Vogel just reported in his blog post "Porting Eclipse 3.x RCP application to Eclipse 4.4 – now without QuickAccess box":
Bug 411821 ([QuickAccess] Contribute SearchField through a fragment or other means)
is now solved.
Thanks to René Brandstetter:
If a RCP app doesn't provide the QuickAccess element in its model, than it will not be visible. So the default is no QuickAcces, easy enough? :)
See the commit 839ee2 for more details
Provide the "QuickAccess" via a e4 application model fragment inside of the "org.eclipse.ui.ide.application".
This removes the "QuickAccess" search field from every none "org.eclipse.ui.ide.application".
You could also hide it and make it work comparable to how it used to work in Eclipse3.7: when user presses ctrl+3 Quick Access functionality pops up (In Eclipse4.3 the ctrl+3 shortcut is still available).
Example of code you could add to your implementation of WorkbenchWindowAdvisor (for Eclipse4.3 rcp application)
private IHandlerActivation quickAccessHandlerActivation;
#Override
public void postWindowOpen() {
hideQuickAccess();
}
private void hideQuickAccess() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
setQuickAccessVisible(window, false);
final IHandlerService service = (IHandlerService) window.getService(IHandlerService.class);
quickAccessHandlerActivation = service.activateHandler(QUICK_ACCESS_COMMAND_ID, new CustomQuickAccessHandler());
}
private void setQuickAccessVisible(IWorkbenchWindow window, boolean visible) {
if (window instanceof WorkbenchWindow) {
MTrimBar topTrim = ((WorkbenchWindow) window).getTopTrim();
for (MTrimElement element : topTrim.getChildren()) {
if (QUICK_ACCESS_ELEMENT_ID.equals(element.getElementId())) {
element.setVisible(visible);
if (visible) {
Composite control = (Composite) element.getWidget();
control.getChildren()[0].addFocusListener(new QuickAccessFocusListener());
}
break;
}
}
}
}
private class QuickAccessFocusListener implements FocusListener {
#Override
public void focusGained(FocusEvent e) {
//not interested
}
#Override
public void focusLost(FocusEvent e) {
((Control) e.widget).removeFocusListener(this);
hideQuickAccess();
}
}
private class CustomQuickAccessHandler extends AbstractHandler {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
final IHandlerService service = (IHandlerService) window.getService(IHandlerService.class);
setQuickAccessVisible(window, true);
if (quickAccessHandlerActivation != null) {
service.deactivateHandler(quickAccessHandlerActivation);
try {
return service.executeCommand(QUICK_ACCESS_COMMAND_ID, null);
} catch (NotDefinedException e) {
} catch (NotEnabledException e) {
} catch (NotHandledException e) {
}
}
return null;
}
}
Is there a way to disable the Back button in a browser (basically clearing the History token stack) in GWT? Once I browse to a certain page in my application I want to make sure that the user can't use the back button to go back, but only be able to use links on the page to navigate the site.
You cannot disable a button just intercept it and change its return to something the browser does not understand.
This removes the history:
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
To understand it see: http://groups.google.com/group/google-web-toolkit/browse_thread/thread/8b2a7ddad5a47af8/154ec7934eb6be42?lnk=gst&q=disable+back+button#154ec7934eb6be42
However, I would recommend not doing this because your it goes against good UI practices. Instead you should figure out a way that the back button does not cause a problem with your code.
Call the method below in the onModuleLoad().
private void setupHistory() {
final String initToken = History.getToken();
if (initToken.length() == 0) {
History.newItem("main");
}
// Add history listener
HandlerRegistration historyHandlerRegistration = History.addValueChangeHandler(new ValueChangeHandler() {
#Override
public void onValueChange(ValueChangeEvent event) {
String token = event.getValue();
if (initToken.equals(token)) {
History.newItem(initToken);
}
}
});
// Now that we've setup our listener, fire the initial history state.
History.fireCurrentHistoryState();
Window.addWindowClosingHandler(new ClosingHandler() {
boolean reloading = false;
#Override
public void onWindowClosing(ClosingEvent event) {
if (!reloading) {
String userAgent = Window.Navigator.getUserAgent();
if (userAgent.contains("MSIE")) {
if (!Window.confirm("Do you really want to exit?")) {
reloading = true;
Window.Location.reload(); // For IE
}
}
else {
event.setMessage("My App"); // For other browser
}
}
}
});
}
I found a way to make GWT ignore the back-button: Just add historyitem x if no historyitem was set and do nothing on x.
set a historyitem on startup
History.newItem("x")
in the ValueChangeHandler of History add the following:
String historyToken = event.getValue();
if (!historyToken.equals("x"))
History.newItem("x");
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("My program");
}
});
That is not a fool proof solution. In fire fox I can press the back button and the onWindowClosing method is never invoked. The reason is that I have used History.newItem() and since history exists the back button or backspace buttons simply navigate through the browser history.
So....fix that :)
Put this in your index.html file:
window.open('html page(For example trial.html)', 'Name of the desired site', width='whatever you want',height='whatever you want', centerscreen=yes, menubar=no,toolbar=no,location=no,
personalbar=no, directories=no,status=no, resizable=yes, dependent=no, titlebar=no,dialog=no');
I am writing a GWT app that involves interacting with an external document in an iframe. As a proof of concept, I am trying to attach a click handler to a button.
The following works in javascript
var iframe = document.getElementById("rawJSIFrame");
var doc = iframe.contentDocument;
var body = doc.body;
var button = doc.getElementsByTagName("input").namedItem("submit");
button.onclick = function() {
alert("Clicked!");
};
Trying to do the equivalent in GWT, I did the following:
public void addClickHandlerToSubmitButton(String buttonElementName, ClickHandler clickHandler) {
IFrameElement iframe = IFrameElement.as(frame.getElement());
Document frameDocument = getIFrameDocument(iframe);
if (frameDocument != null) {
Element buttonElement = finder(frameDocument).tag("input").name(buttonElementName).findOne();
ElementWrapper wrapper = new ElementWrapper(buttonElement);
HandlerRegistration handlerRegistration = wrapper.addClickHandler(clickHandler);
}
}
private native Document getIFrameDocument(IFrameElement iframe)/*-{
return iframe.contentDocument;
}-*/;
The following is the ElementWrapper class:
public class ElementWrapper extends Widget implements HasClickHandlers {
public ElementWrapper(Element theElement) {
setElement(theElement);
}
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
}
The code to find the button works fine but the actual click event handler is not getting invoked. Has anybody had a similar issue before, and how did you resolve it?
Thanks in advance,
Tin
Hilbrand is right about the problem being that the GWT method onAttach() was not called.
I implemented your original solution, adding the following method to ElementWrapper:
public void onAttach() {
super.onAttach();
}
And called added wrapper.onAttach() after the ElementWrapper is created. Works like a charm!
I expect the problem is that the GWT method onAttach() is not called when you use the wrapping as in your first example. You can try to use the static wrap method on the Button widget. Although to use this the input must be of type button. Or have a look at the implementation of the wrap method. Here is the modified code when using the wrap method:
Element buttonElement = finder(frameDocument).tag("input").name(buttonElementName).findOne();
Button button = Button.wrap(buttonElement);
HandlerRegistration handlerRegistration = button.addClickHandler(clickHandler);
After researching this further, I found that the iframe is irrelevant. The same behaviour doesn't work on a normal button on the host page.
I basically fixed it by using JSNI to replicate part of GWT's event handling mechanism. The following works:
Element buttonElement = DOM.getElementById("externalButton");
new CustomElementWrapper(buttonElement).addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert("GWT hooked into button");
}
});
Where CustomElementWrapper is:
public class CustomElementWrapper extends Widget implements HasClickHandlers {
private ClickEventManager clickEventManager;
public CustomElementWrapper(Element theElement) {
setElement(theElement);
clickEventManager = new ClickEventManager(theElement);
}
public HandlerRegistration addClickHandler(ClickHandler handler) {
//The 'right' way of doing this would be the code below. However, this doesn't work
// A bug in GWT?
//
// return addDomHandler(handler, ClickEvent.getType());
return clickEventManager.registerClickHandler(handler);
}
void invokeClickHandler() {
clickEventManager.invokeClickHandler();
}
public boolean isClickHandlerRegistered() {
return clickEventManager.isClickHandlerRegistered();
}
}
Finally, the ClickEventManager, where the actual work happens is:
public class ClickEventManager {
private boolean clickHandlerRegistered = false;
private ClickHandler clickHandler;
private Element element;
public ClickEventManager(Element element) {
this.element = element;
}
public void invokeClickHandler() {
//This shouldn't really be null but we are bypassing GWT's native event mechanism
//so we can't create an event
clickHandler.onClick(null);
}
public boolean isClickHandlerRegistered() {
return clickHandlerRegistered;
}
HandlerRegistration registerClickHandler(ClickHandler handler) {
clickHandler = handler;
if (!clickHandlerRegistered) {
registerClickHandlerInJS(element);
clickHandlerRegistered = true;
}
return new HandlerRegistration() {
public void removeHandler() {
//For now, we don't support the removal of handlers
throw new UnsupportedOperationException();
}
};
}
private native void registerClickHandlerInJS(Element element)/*-{
element.__clickManager = this;
element.onclick
= function() {
var cm = this.__clickManager;
cm.#com.talktactics.agent2.client.widgets.ClickEventManager::invokeClickHandler()();
}
}-*/;
}
Personally, I hate this solution because I appear to be duplicating GWT's event handling and quite possibly introducing nasty javascript memory leaks. Any ideas on why my first post doesn't work (remembering that the iframe aspect is a red herring), would be appreciated.
Thanks,
Tin
You may find this helpful:
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.AbsolutePanel;
public class DirectPanel extends AbsolutePanel implements HasClickHandlers {
public DirectPanel(Element elem) {
super(elem.<com.google.gwt.user.client.Element> cast());
onAttach();
}
#Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
}
You will then be able to make arbitrary containers into widget containers:
Element root = Document.get().getElementById("target");
DirectPanel p = new DirectPanel(root);
Button register = new Button("Register");
register.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// ...
}
});
p.add(register);
And bind events to arbitrary elements:
Element root = Document.get().getElementById("target");
DirectPanel p = new DirectPanel(root);
p.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// ...
}
});
Specifically in your case, try this:
IFrameElement frm = Document.get().createIFrameElement();
Document d = frm.getContentDocument();
NodeList<Element> inputs = d.getElementsByTagName("input");
InputElement target = null;
for(int i = 0; i < inputs.getLength(); ++i) {
Element e = inputs.getItem(0);
if (e.getNodeName().equals("submit")) {
target = InputElement.as(e);
break;
}
}
if (target != null) {
DirectPanel p = new DirectPanel(target);
p.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// TODO Auto-generated method stub
}
});
}
It's always mystified me that GWT makes doing this so difficult and poorly documented.
Instead of using iframes i suggest you simply make a http request from GWT via com.google.gwt.http.client.RequestBuilder. Like so:
private void getHtml(String url) {
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, url);
rb.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
HTMLPanel html = new HTMLPanel(response.getText());
// Now you have a widget with the requested page
// thus you may do whatever you want with it.
}
#Override
public void onError(Request request, Throwable exception) {
Log.error("error " + exception);
}
});
try {
rb.send();
} catch (RequestException e) {
Log.error("error " + e);
}
}
You could use JSNI to reuse your JavaScript piece of code. Your javascript code would call a gwt method on an object that would throw it on behalf of the button in the iframe.
As to why GWT code does not work -- I guess that is because they use some layer on top of regular browser events that probably cannot span more than 1 frame. That's just a guess though. You could file this as a feature/bug request agains GWT team. If I am right your code looks just fine.
Please see my previous answer. A slight modification to your original solution will make it work.