does anyone know if it is possible to disable or overwrite the native behavior of "alt+f4" (on windows closes the application) in an e4 application?
what is suggested solution to achieve this?
best regards
My solution is NOT pure SWT solution. It only works on Windows. But you mentioned Windows, and if you only target one platform this is good enough. It uses internal code from SWT, but it maps to Windows API, documented by Microsoft, so it will not change.
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.addListener(SWT.Close, new Listener() {
#Override
public void handleEvent(Event event) {
if (OS.GetKeyState(OS.VK_MENU) < 0 && OS.GetKeyState(OS.VK_F4) < 0) {
event.doit = false;
}
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
found a solution but i am not to happy with that one.
created a addon:
that is registering an event handler on the UIEvents.UILifeCycle.APP_STARTUP_COMPLETE topic.
then somehow retrieve the shell from the topics metadata and registering a filter on the display.
#PostConstruct
void hookListeners() {
eventHandler = new EventHandler() {
#Override
public void handleEvent(Event arg0) {
MElementContainer property = (MElementContainer) arg0.getProperty("org.eclipse.e4.data");
final Shell shell = (Shell) property.getSelectedElement().getWidget();
final Display display = shell.getDisplay();
display.addFilter(SWT.Close, new Listener() {
#Override
public void handleEvent(org.eclipse.swt.widgets.Event event) {
if (!MessageDialog.openQuestion(shell, "Exit",
"Do you really want to close the Application?")) {
//see api documentation display.addFilter(
event.type = SWT.NONE;
event.doit = false;
}
}
});
}
};
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, eventHandler);
}
this solution does not seem to correct to me so if anyone has a better one please share it :-)
Related
I am sure it's just a simple fault, but I'm not able to solve it.
My RecyclerView.Adapter loads its data with help of an AsyncTask (LoadAllPersonsFromDb) out of a SQLite DB. The response is handled by a callback interface (ILoadPersonFromDb.onFindAll).
Here is the code of the Adapter:
public class ListViewAdapter extends RecyclerView.Adapter<ListViewViewholder> implements LoadAllPersonsFromDb.ILoadPersonFromDb {
private int layout;
private List<Person> persons;
private Context context;
private AdapterDataSetListener adapterDataSetListener;
public ListViewAdapter(int layout, Context context,
AdapterDataSetListener adapterDataSetListener) {
this.layout = layout;
persons = new ArrayList<>();
this.context = context;
this.adapterDataSetListener = adapterDataSetListener;
new LoadAllPersonsFromDb(context, this).execute();
}
#Override
public ListViewViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ListViewViewholder(view, context);
}
#Override
public void onBindViewHolder(ListViewViewholder holder, int position) {
holder.assignData(persons.get(position));
}
#Override
public int getItemCount() {
return persons.size();
}
#Override
public void onFindAll(List<Person> persons) {
Log.d("LISTVIEW", "Counted: " + persons.size() + " elements in db");
if (this.persons != null) {
this.persons.clear();
this.persons.addAll(persons);
} else {
this.persons = persons;
}
adapterDataSetListener.onChangeDataSet();
//notifyDataSetChanged();
}
public interface AdapterDataSetListener {
void onChangeDataSet();
}
}
As you can see, I tried more than one way to get it running. The simple notifyDataSetChanged did not do anything, so I made another interface which is used to delegate the ui information to the relating fragment. Following code documents this interface which is implemented in the relating fragment:
#Override
public void onChangeDataSet() {
Log.d("Callback", "called");
listViewAdapter.notifyDataSetChanged();
/*
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
listViewAdapter.notifyDataSetChanged();
}
});
*/
}
Here I also tried to put it on the MainUiThread but nothing works. I'm just not able to see where my problem is. Hopefully any of you guys can give me a hint.
The logging works, which is the prove for the working callbacks.
Thank you in advance.
PS: If you need any more code, just tell me and I will provide it.
instead of using the interface-llistener pattern, try this
#Override
public void onFindAll(List<Person> persons) {
Log.d("LISTVIEW", "Counted: " + persons.size() + " elements in db");
if (this.persons != null) {
this.persons.clear();
this.persons.addAll(persons);
} else {
this.persons = persons;
}
refereshAdapter(persons);
}
public void refereshAdapter(List<Person> persons){
listViewAdapter.clear();
listViewAdapter.addAll(persons);
listViewAdapter.notifyDataSetChanged();
}
To tell the background, I used RecyclerView in Version 23.1.1 because the latest 23.2.0 had some weird behaviour in holding a huge space for each card.
//Update: the problem with the space between cards, was because of a failure of myself in the layout file (match_parent instead of wrap_content). -_-
The upshot was using the latest version again and everything worked just fine. I have no idea why, but at the moment I am just happy, that I can go on. This little problem wasted enough time.
Maybe somebody has a similar situation and can use this insight.
Thx anyway #yUdoDis.
I am making a media player which allows users to drag and drop media thumbnails onto a media player (using JavaFX MediaPlayer).
When I run it and try the drag/drop functionality, some of the time it works just as expected. However sometimes it produces a weird error.
The error in its fullness is:
Error:80de0001 in CallbackToJava(javaIDs.View.notifyDragDrop, grfKeyState, pt, pdwEffect)
COM Error:80de0001 Unknown Error 0x80DE0001
Error:80de0001 in :: DoDragDrop( pcd, IDropSourcePtr(new GlassDropSource(obj), getDROPEFFECT(supportedActions, &performedDropEffect)
COM Error:80de0001 Unknown error 0x80DE0001
The print-out in Eclipse looks like: (all double-spaced)
I really have no idea why this is happening - I'm clearly doing something wrong. The error doesn't point me to any line of code. I would suggest that the error is referring to a memory address? Are you able to help me, please?
The listeners/handlers which perform the Drag/Drop functionality are:
root.setOnMouseEntered(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
root.setStyle(highlightBackgroundStyle);
parentScene.setCursor(Cursor.OPEN_HAND);
}
});
root.setOnMouseExited(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
root.setStyle(backgroundStyle);
//parentScene.setCursor(Cursor.DEFAULT);
}
});
root.setOnDragDetected(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent arg0) {
parentScene.setCursor(Cursor.CLOSED_HAND);
Dragboard db = parentScene.startDragAndDrop(TransferMode.COPY);
ClipboardContent content = new ClipboardContent();
content.putString(mediaFile.toURI().toString());
db.setContent(content);
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragDropped(new EventHandler<DragEvent>(){
#Override
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOff();
Dragboard db = arg0.getDragboard();
if (db.hasString())
{
//System.out.println(db.getString());
String mediaURI = db.getString();
System.out.println(mediaURI);
mediaPanel.getMixerA().getJfxMediaPlayer().loadAndPlayMediaA(new Media(mediaURI));
mediaPanel.getMixerA().prepareMedia();
arg0.setDropCompleted(true);
}else{System.out.println("Drag error");arg0.setDropCompleted(false);}
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragExited(new EventHandler<DragEvent>(){
#Override
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOff();
arg0.consume();
}
});
mediaPanel.getDropZoneA().setOnDragOver(new EventHandler <DragEvent>() {
public void handle(DragEvent arg0) {
mediaPanel.getMixerA().dragGraphicsOn();
if (arg0.getGestureSource() != mediaPanel.getDropZoneB() && arg0.getDragboard().hasString())
{
arg0.acceptTransferModes(TransferMode.COPY);
}
arg0.consume();
}
});
Update 1
I am wondering whether this is caused by the way I 'change' the media for the MediaPlayer. I do the following:
public void loadAndPlayMediaA(Media playableMedia)
{
if((player != null))
{
player.stop();
}
media = playableMedia;
player = new MediaPlayer(media);
player.play();
}
I then immediately call:
public void prepareMedia()
{
view.setMediaPlayer(jfxMediaPlayer.getMediaPlayer());
view.setPreserveRatio(preserveRatio);
view.setFitWidth(miniaturePlayerX);
view.setFitHeight(miniaturePlayerY);
playerSlider.setValue(0.0);
}
...The key line being player = new MediaPlayer(media);. I wonder whether occasionally I am hitting the split second where the MediaView is trying to get the next frame, but failing because the media has been re instantiated. (?)
What's the best way to load up a new video?
I don't know if you haven't found a solution yet...
I had the same problem and solved it by following code:
setOnDragDropped(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragDropped");
event.setDropCompleted(true);
}
});
setOnDragExited(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragExited");
Dragboard db = event.getDragboard();
ArrayList<Object> f = (ArrayList<Object>) db.getContent(DataFormat.FILES);
for(Object o:f)
System.out.println(o.getClass().getName() + ":" + o);
File file = (File) f.get(0);
newMedia(file.toURI());
}
});
setOnDragOver(new EventHandler<DragEvent>()
{
#Override
public void handle(DragEvent event)
{
System.out.println("onDragOver");
event.acceptTransferModes(TransferMode.ANY);
}
});
public void newMedia(URI uri)
{
m = new Media(uri.toASCIIString());
mp = new MediaPlayer(m);
mV = new MediaView(mp);
mp.setOnReady(new Runnable()
{
#Override
public void run()
{
mp.play();
}
});
}
In the DragDropped handler I call setDropCompleted to call the DragExited handler. Then I get the File out of the Dragboard and create a new MediaPlayerInstance. And then, you aren't allowed to call play immideately, else nothing will happen. You need to call play in the OnReady Handler, or at least after the MediaPlayer's status has been changed to Ready.
The Error will still appear, but it should work now ;)
There is a ContextMenu which has two options and when the second option (item2 in the code) is pressed with the right mousebutton I want it to print out some text so I know I did actually activate it. Up till now nothing happens when I click on the second mousebutton.
I haven't had much experience yet with Eventhandlers so my apologies if I made a noobish mistake.
private void maakContextMenu() {
menu = new ContextMenu();
MenuItem item = new MenuItem("Kleur Assen");
MenuItem item2 = new MenuItem("tweede optie");
final LissajousCanvas canvas = this;
item.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new KiesKleur(canvas).show();
}
});
item2.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent t) {
System.out.println("in the loop");
if(t.getSource()==MouseButton.SECONDARY){
System.out.println("in too deep");
}
new KiesKleur(canvas).show();
}
});
menu.getItems().addAll(item, item2);
}
A MenuItem is not actually a Node, so it's not part of the scene graph in the way that Nodes are. So I'm not really sure if this is a bug or not; I think it probably only implements EventTarget so it can specifically generate ActionEvents. You'll have noticed there is no setOnMouseClicked(...) method available.
Here's a workaround. I'm not sure why it only works with MOUSE_PRESSED and not with MOUSE_CLICKED, but it's likely something to do with the default mouse event handling that generates the action events:
private void maakContextMenu() {
menu = new ContextMenu();
MenuItem item = new MenuItem("", new Label("Kleur Assen"));
Label menuItem2Label = new Label("tweede optie");
MenuItem item2 = new MenuItem("", menuItem2Label);
final LissajousCanvas canvas = this;
item.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
new KiesKleur(canvas).show();
}
});
menuItem2Label.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent t) {
System.out.println("in the loop");
if(t.getButton()==MouseButton.SECONDARY){
System.out.println("in too deep");
}
new KiesKleur(canvas).show();
}
});
menu.getItems().addAll(item, item2);
}
I am using gwt 2.3 with gwtp framework.In this application I wan to maintain a session time of 5 mins.This means if current user is not doing up to 5 min and he comes after five min then on his first event/action on screen a he should be be logged out.
In gwt there is class named Timer which can be used in this issues.But I am not getting how to recognize action of user on the screen.I did google on it, & found the code for gwt-ext.Below is the code of gwt-ext
Ext.get(“pagePanel”).addListener(“click”, new EventCallback() {
#Override
public void execute(EventObject e) {
MessageBox.alert(“On Mouse Click”);
}
});
Ext.get(“pagePanel”).addListener(“keydown”, new EventCallback() {
#Override
public void execute(EventObject e) {
MessageBox.alert(“On Key Press Click”);
}
});
In above code tag in working properly so I am attaching link from where I got this code.here
Same type of code I am looking in gwt.If there any other better way to do this then please let me know. Thanks in advance
If action/event can be really everythin, I would solve it with a
NativePreviewHandler in the following way:
boolean expired;
final Timer logoutTimer = new Timer() {
#Override
public void run() {
expired = true;
}
};
NativePreviewHandler nph = new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (!expired) {
logoutTimer.cancel();
logoutTimer.schedule(300000);
} else {
// do your logout stuff here
}
}
};
Event.addNativePreviewHandler(nph);
If the user shell be logged out without a new action after 5 minutes:
final Timer logoutTimer = new Timer() {
#Override
public void run() {
// do your logout stuff here
}
};
NativePreviewHandler nph = new NativePreviewHandler() {
#Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
// Of course do this only when logged in:
logoutTimer.cancel();
logoutTimer.schedule(300000);
}
};
Event.addNativePreviewHandler(nph);
It is possible to find an active page/editor in eclipse. How can we programmatically get hold of the instance of the open modal dialog in eclipse.
There are no corresponding interface in Eclipse to access any current model dialog. The best approximation is Display.getActiveShell(), which will return the shell that hosts the active dialog if one exists.
[Dialogs are implemented by having their own event loop, so it can be rather difficult to run your own code...]
EDIT: Based on your comment below, here is a small snippet I use constantly to test for the presence of specific preference pages. I guess this can be used used as the starting point for your own test... Note the use of Display.timerExec(...).
public void test(String pageId) {
try {
final IWorkbench workbench = PlatformUI.getWorkbench();
final Shell[] shells = workbench.getDisplay().getShells();
final ICommandService cs = (ICommandService) workbench.getService(ICommandService.class);
final ParameterizedCommand command = cs.deserialize("org.eclipse.ui.window.preferences(preferencePageId="
+ pageId + ")");
assertNotNull(command);
final IHandlerService hs = (IHandlerService) workbench.getService(IHandlerService.class);
// Have to use timerExec to get the runnable executed after the dialog is shown
workbench.getDisplay().timerExec(2000, new Runnable() {
#Override
public void run() {
assertEquals(shells.length + 1, workbench.getDisplay().getShells().length);
final Shell lastShell = findLastShell(workbench.getDisplay().getShells(), shells);
assertNotNull(lastShell);
final Object data = lastShell.getData();
assertNotNull(data);
assertTrue(data instanceof PreferenceDialog);
lastShell.close();
assertEquals(shells.length, workbench.getDisplay().getShells().length);
}
private Shell findLastShell(Shell[] currentShells, Shell[] oldShells) {
CheckNext: for (final Shell cs : currentShells) {
for (final Shell os : oldShells) {
if (os == cs) {
continue CheckNext;
}
}
return cs;
}
return null;
}
});
hs.executeCommand(command, null);
} catch (final Exception ex) {
fail(ex.getMessage());
}
}