I have a really basic FormEditor and FormPage:
public class CustomFieldSetVersionEditor extends FormEditor {
#Override
protected void addPages() {
try {
addPage(new MyFormPage(this), getEditorInput());
} catch (final PartInitException ex) {
ex.printStackTrace();
}
}
#Override
public void doSave(final IProgressMonitor monitor) {}
#Override
public void doSaveAs() {}
#Override
public boolean isSaveAsAllowed() { return false; }
}
class MyFormPage extends FormPage {
public MyFormPage(final FormEditor editor) {
super(editor, "id", "Title");
}
#Override
protected void createFormContent(final IManagedForm managedForm) { }
}
This admittedly complex and exotic use case brings the following exception:
java.lang.StackOverflowError
at org.eclipse.swt.widgets.Widget.getData(Widget.java:525)
at org.eclipse.ui.part.MultiPageEditorPart.getEditor(MultiPageEditorPart.java:599)
at org.eclipse.ui.part.MultiPageEditorPart.getActiveEditor(MultiPageEditorPart.java:523)
at org.eclipse.ui.forms.editor.FormEditor.getActiveEditor(FormEditor.java:430)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:84)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
at org.eclipse.ui.forms.editor.FormEditor$FormEditorSelectionProvider.getSelection(FormEditor.java:89)
...
However, if I use addPage(IFormPage) instead of addPage(IEditorPart, IEditorInput) it works. There is even a "bug" report for this problem: Bug 283039 (it's no bug, because... there is no reason given).
We don't need to discuss if this is a bug, but what I want to know is: How do I add a FormPage to a FormEditor while still defining the IEditorInput?
The FormPage is being initialized twice, the second time with the same IEditorSite as the main FormEditor. This results in the same selection provider being used for the FormPage as the main editor, this selection provider does not expect this and gets in to a loop.
You can stop the second initialization by overriding the isEditor method of FormPage and return true:
#Override
public boolean isEditor() {
return true;
}
Also note that if you use the addPage(IFormPage) call the page is still initialized with the editor input (as long as isEditor returns false).
Related
I have to use an 3th party library to create a java driven plc. in this library you have to define the IO's etc and then you will auto generate some code to acces the IO. this will generate a lot of code which i want to split up to keep readable.
The BIhcs_Io class is where everything on the event driven plc is executed. Each time a value of a property changes (see example below of property) it will run the doExecute() method.
What i want to do is that when this method is called, instead i want to execute it on the child class.
any help would be greatly appreciated!
public class BIhcs_IO extends BComponent implements Runnable {
//Example of a created property for a PLC IO
public static final Property bool_1 = newProperty(Flags.EXECUTE_ON_CHANGE | Flags.OPERATOR | Flags.SUMMARY, ((BBoolean)((BValue)BBoolean.TYPE.getInstance())).getBoolean(), BFacets.tryMake(null));
public boolean getBool_1() { return getBoolean(bool_1); }
public void setBool_1(boolean v) { setBoolean(bool_1, v, null); }
public static final Action execute = newAction(Flags.ASYNC, null);
public void execute() { invoke(execute, null, null); }
#Override
public Type getType() { return TYPE; }
public static final Type TYPE = Sys.loadType(BIhcs_IO.class);
public BComponent getComponent() {
return this;
}
public void started() throws Exception {
}
//When the Property bool_1 changes it wil execute the doExecute() method below
public void changed(final Property prop, final Context cx) {
super.changed(prop, cx);
if (!this.isRunning()) {
return;
}
if (Flags.isExecuteOnChange((BComplex) this, (Slot) prop)) {
this.execute();
}
}
public void run() {
System.out.println("Source BProgram did not override run(). Exiting thread.");
}
//This is called when a property changes value. When this is called, instead of executing this i want to execute the code in BIhcsMain()
public void doExecute() throws Exception {
setDebug_1("called parent")
}
public void stopped() throws Exception {
}
}
Below is the child class that extends the parent class. Each time the doExecute() in the parent is called i want to override it and execute the one in the child class instead.
public class BIhcsMain extends BIhcs_IO {
#Override
public void doExecute(){
setDebug_2("called child");
}
}
I'm writing a simple solution for uploading files in GWT and recently encountered a tiny, but quite annoying problem. I'm using a standard GWT FileUpload widget inside a FormPanel. Everything works just fine (form is submitted and the file is being sent to the servlet) only if user clicks "physically" a button related to form, with an attached click handler (inside there is this form.submit() fired).
Unfortunately, I have to submit a form from the other place in a FormPanel's parent widget (another class). I tried to implement click simulation with this particular code and a button with Visible attribute set to "false":
public void buttonClick()
{
NativeEvent event = Document.get().createClickEvent(0, 0, 0, 0, 0, false, false, false, false);
DomEvent.fireNativeEvent(event, saveFileBtn);
}
saveFileBtn.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
});
After calling the buttonClick() method the click event is fired, but the form doesn't submit (just nothing happens). Are there any differences between those two approaches to firing a click event?
If so, what would be the best alternative approach instead? I thought about making my own widget performing similar operations to the standard GWT FormPanel, but encode a file in a base64 format and send to server using the RequestBuilder mechanism. Does it make sense?
EDIT:
According to #Pedro Pedruzzi answer, I've implemented an event:
public interface FormToSubmitEventHandler extends EventHandler {
void onFormToSubmit(FormToSubmitEvent event);
}
public class FormToSubmitEvent extends GwtEvent<FormToSubmitEventHandler> {
public static final Type<FormToSubmitEventHandler> TYPE = new Type<FormToSubmitEventHandler>();
public FormToSubmitEvent() {
super();
}
#Override
public Type<FormToSubmitEventHandler> getAssociatedType()
{
return TYPE;
}
#Override
protected void dispatch(FormToSubmitEventHandler handler)
{
handler.onFormToSubmit(this);
}
public static HandlerRegistration register(EventBus eventBus, FormToSubmitEventHandler handler)
{
return eventBus.addHandler(TYPE, handler);
}
}
In a widget class (implementing the interface above) added:
#Override
public void onFormToSubmit(FormToSubmitEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
And then:
FormToSubmitEvent event = new FormToSubmitEvent();
Events.getTactinEventBus().fireEvent(event);
Unfortunately - it still doesn't work. I'm completely confused about what is going on.
EDIT 2
Whole class with registered handler:
public class FileLinkPropertyControl implements FormToSubmitEventHandler
{
private FileUpload fileUpload;
protected FormPanel form;;
protected HorizontalPanel hPanel;
public FileLinkPropertyControl() {
fileUpload = new FileUpload();
FormToSubmitEvent.register(Events.getTactinEventBus(), this);
fileUpload.setName("fileUploadFormElement");
fileUpload.addChangeHandler(new ChangeHandler()
{
#Override
public void onChange(ChangeEvent event)
{
setValue(fileUpload.getFilename(), true);
}
});
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
form.setAction(GWT.getModuleBaseURL() + "fileUploadServlet");
form.setWidget(hPanel);
hPanel.add(fileUpload);
}
#Override
public void onFormToSubmit(FormToSubmitEvent event)
{
if(fileUpload.getFilename().isEmpty())
return;
else {
form.submit();
}
}
}
Don't try to simulate the click or to make the request manually. You have to reach form.submit() some way. If the widget hierarchy is too complex to have a simple call chain aproach, you should use an event (see http://www.gwtproject.org/doc/latest/DevGuideUiHandlers.html).
I'm working on a game engine, and the last question I had regarding this was what good way I can use to make "observers" or listeners. A user suggested that I should use Java's EventObject class to inherit from and make a Listener interface. However, this didn't provide me with good flexibility.
Here is the Handler annotation to state that a method is an event handler in a listener:
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.METHOD)
public #interface Handler {}
Here is the base class for Event, which is basically the same as EventObject (but I'll add abstract methods sooner or later):
public abstract class Event {
private Object source;
public Event(Object source) {
this.source = source;
}
public Object getSource() {
return source;
}
}
Here is the Listener class, which is empty:
public interface Listener {}
Here is the ListenerHandler class, used to handle all listeners. You register and unregister them here. I'll edit the register/unregister methods later for a better use:
public class ListenerHandler {
private ArrayList<Listener> listeners;
public ListenerHandler() {
this.listeners = new ArrayList<Listener>();
}
public void registerListener(Listener l) {
listeners.add(l);
}
public void unregisterListener(Listener l) {
listeners.remove(l);
}
public void onEvent(Event event) {
for(Listener l : listeners) {
Class<?> c = l.getClass();
Method[] methods = c.getDeclaredMethods();
for(Method m : methods) {
if(m.isAccessible()) {
if(m.isAnnotationPresent(Handler.class)) {
Class<?>[] params = m.getParameterTypes();
if(params.length > 1) {
continue;
}
Class<?> par = params[0];
if(par.getSuperclass().equals(Event.class)) {
try {
m.invoke(this, event);
}catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
From what I heard, it's a use of a lot of memory in order to get all methods of a class. I'm not going to assume this is the case, but I'm sure there is a better way as this will be a game engine with many components and such.
I'd like to know the best way to implement this, or if I'm doing it right. I'd also like to know if anyone can help me improve this in any way without hogging memory usage by the game (as of now it's not a big deal -- the "game engine" is not even close to rendering anything yet)
I tried to keep it a very simple example and will comment with different ideas to it:
First meet the Achievement class:
import java.util.Observable;
public class Achievement extends Observable {
public static class AchievementDetails {}
public Achievement() {
addObserver(EventsListener.getInstance());
}
public void achievementReached() {
AchievementDetails achievemetDetails = null;
setChanged();
notifyObservers(achievemetDetails);
}
}
And then the events listener class:
import com.test.Achievement.AchievementDetails;
public class EventsListener implements Observer {
private static EventsListener instance = new EventsListener();
public static EventsListener getInstance() {
return instance;
}
#Override
public void update(Observable o, Object arg) {
if(o instanceof Achievement) {
AchievementDetails achievemetDetails = (AchievementDetails) arg;
//do some logic here
}
}
}
The only one thing that is missing is to create an instance of your achievement (which register the EventsListener to itself) and handle the life cycle of it.
Hello i have got function like that:
#Override
public boolean checkExist(String name) {
final boolean check[] = new boolean[] { false };
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
//do some action set true when map key equals name
check[0] = true;
}
#Override
public void onSearchError(XMLPacket error) {
// TODO Auto-generated method stub
}
});
return check[0];
}
I`am looking for solution and found some article but i do not know how to do it in gwt :/
This code do not working properly ... as you know this is asynchronous callback.
How can i fix this problem i must return value after callback ends.
It is not possible to return a value from async call in a method as you have done. That is the basic nature of "Asynchronous" call. You never know when it will return ( network/server delay) and hence your code execution does not wait!!!!!
Do not return a boolean from your method. Instead make your method take a callback.
interface MyCallback {
execute(boolean successfl);
}
public void checkExist(String name, MyCallback callback) {
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
//do some action set true when map key equals name
callback.execute(true);
}
#Override
public void onSearchError(XMLPacket error) {
}
});
}
Maybe a cleaner solution might be to use events and an eventbus (which could be private to your class or maybe shared by everyone so that other components can react to that) when you get your result or not. Then listen for these events and treat them accordingly.
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult() {
eventBus.fireEvent(new FoundEvent());
}
#Override
public void onSearchError() {
eventBus.fireEvent(new NotFoundEvent());
}
});
This code is not working properly ...
The reason is that Your code is in synchronous model and you are making Asynchronous calls.
I am assuming that you are doing something after you got some result in onSearchResult.
So,stop executing your code until you got the response from server, Why because you dont know that the callmay fail sometime.
If you really want to use the value globally ,then
public boolean returnVal=false;
public void checkExist(String name, MyCallback callback) {
getAllRecordFromServer(new SearchCallback() {
#Override
public void onSearchResult(Map<String, Item> itemsMap) {
returnVal=true;
proceedFurther(itemsMap) //your next lines of code in this method.
}
#Override
public void onSearchError(XMLPacket error) {
stopProceedFurther(); //show some error message to user.
}
});
I have an editorpane which displays editable information which changes based on what the user has selected in a list. So, for implementing my undo/redo feature I must first re-select the item that the user had selected when making their edits prior to undoing/redoing them. However, I am finding it difficult to add functionality to default document events because when I attempt to extend that class I get the "No enclosing instance" error.
below is my undomanager code. I know there is no setSelection and getCurrentSelection for JEditorPane but just pretend I am using an extended version with those features to determine what item the user has selected.
public class MyUndoManager extends UndoManager {
private JEditorPane editor;
public MyUndoManager() {
super();
}
public void setEditor(JEditorPane editor) {
this.editor = editor;
}
#Override
public synchronized boolean addEdit(UndoableEdit anEdit) {
if (anEdit instanceof javax.swing.text.AbstractDocument.DefaultDocumentEvent) {
try {
MyDocumentEvent evt = ((MyDocumentEvent) anEdit);
evt.setCallbackObj(editor.getCurrentSelection());
return super.addEdit(anEdit);
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else {
return super.addEdit(anEdit);
}
}
private class MyDocumentEvent extends javax.swing.text.AbstractDocument.DefaultDocumentEvent {
private Object callbackObj;
public void setCallbackObj(Object o) {
this.callbackObj = o;
}
#Override
public void undo() throws CannotUndoException {
editor.setSelection(o);
super.undo();
}
#Override
public void redo() throws CannotRedoException {
editor.setSelection(o);
super.redo();
}
}
}
It could be accessible by your code if DefaultDocumentEvent were static field of AbstractDocument.