How can I configure a Swing JFrame to close on Cmd-W? - macos

On OS X, users expect to be able to press Cmd-W to close a window.
Can I configure a JFrame to do this?

Typically, keybindings for the top-level windows are handled exclusively by the underlying OS. So on a Mac they should be already there, on a different system there is no meta key (? not sure, though, maybe has some simulation).
Anyway, you can add whatever additional keybinding you like to the JFrame's rootPane:
private void addMacCloseBinding(JFrame frame) {
frame.getRootPane().getActionMap().put("close-window", new CloseAction(frame));
frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke("control W"), "close-window");
frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
.put(KeyStroke.getKeyStroke("meta W"), "close-window");
}
public class CloseAction extends AbstractAction {
private Window window;
public CloseAction(Window window) {
this.window = window;
}
#Override
public void actionPerformed(ActionEvent e) {
if (window == null) return;
window.dispatchEvent(new WindowEvent(
window, WindowEvent.WINDOW_CLOSING));
}
}

You should be able to specify the menu shortcut like this:
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W,
ActionEvent.META_MASK));

Related

Unity3D: How to detect when a button is being held down and released [duplicate]

This question already has answers here:
How to detect click/touch events on UI and GameObjects
(4 answers)
Closed 3 years ago.
I have a UI button. I want to show a text when the user is pressing the button and hide the text when the user releases the button.
How can I do this?
this anwser is basically fine but there is a huge drawback: You can't have additional fields in the Inspector since Button already has a built-in EditorScript which overwrites the default Inspector - You would need to extend this via a custom Inspector every time.
I would instead implement it as completely additional component implementing IPointerDownHandler and IPointerUpHandler (and maybe also IPointerExitHandler to reset also when exiting the button while holding the mouse/pointer still pressed).
For the doing something while the button stays pressed I'ld use a Coroutine.
In general I'ld use UnityEvents:
[RequireComponent(typeof(Button))]
public class PointerDownUpHandler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler
{
public UnityEvent onPointerDown;
public UnityEvent onPointerUp;
// gets invoked every frame while pointer is down
public UnityEvent whilePointerPressed;
private Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
private IEnumerator WhilePressed()
{
// this looks strange but is okey in a Coroutine
// as long as you yield somewhere
while(true)
{
whilePointerPressed?.Invoke();
yield return null;
}
}
public void OnPointerDown(PointerEventData eventData)
{
// ignore if button not interactable
if(!_button.interactable) return;
// just to be sure kill all current routines
// (although there should be none)
StopAllCoroutines();
StartCoroutine(WhilePressed);
onPointerDown?.Invoke();
}
public void OnPointerUp(PointerEventData eventData)
{
StopAllCoroutines();
onPointerUp?.Invoke();
}
public void OnPointerExit(PointerEventData eventData)
{
StopAllCoroutines();
onPointerUp?.Invoke();
}
// Afaik needed so Pointer exit works .. doing nothing further
public void OnPointerEnter(PointerEventData eventData) { }
}
Than you can reference any callback in onPointerDown, onPointerUp and whilePointerPressed just the way you would do it with the onClick event of the Button.
You have to create your own custom button by extending Button class and override method OnPoiterDown and OnPointerUp.
Attach MyButton component instead of Button to your gameobject
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class MyButton : Button
{
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
Debug.Log("Down");
//show text
}
public override void OnPointerUp(PointerEventData eventData)
{
base.OnPointerUp(eventData);
Debug.Log("Up");
//hide text
}
}

nsmenufx MenuToolkit.setApplicationMenu producing inconsistent behavior

I have a JavaFX application for Mac and I'm using NSMenuFX to create the menu bar. I create my application menu using MenuToolkit. If I use the method setApplicationMenu the menu displays correctly. For example it says Quit MyApplication instead of Quit com.example.MyApplication. However, I have code that cancels the closing of the application if certain conditions are met. I have an EventHandler on the Stage that handles the on close request. If the application should not close the WindowEvent is consumed. The problem is the application still closes. However, if I do not use setApplicationMenu, the menu does not display correctly (it says Quit com.example.MyApplication) but consuming the WindowEvent does stop the closing of the application. I am using Java 1.8u77. Any ideas on what I'm doing incorrectly? I cannot reproduce this problem in the sample code that comes with NSMenuFX. Below is the code that creates the menu bar.
private void createMenu(VBox appBox) {
// Create the menubar
MenuBar menuBar = new MenuBar();
menuBar.useSystemMenuBarProperty().set(true);
MenuToolkit tk = MenuToolkit.toolkit();
String appName = "MyApplication";
Menu appMenu = new Menu(appName);
menuBar.getMenus().add(appMenu);
MenuItem aboutItem = tk.createAboutMenuItem("MyApplication");
aboutItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
AboutDialog aboutDialog = new AboutDialog(null);
aboutDialog.initOwner(stage);
aboutDialog.showAndWait();
}
});
appMenu.getItems().add(aboutItem);
appMenu.getItems().addAll(new SeparatorMenuItem(),
tk.createHideMenuItem(appName), tk.createHideOthersMenuItem(),
tk.createUnhideAllMenuItem(),
new SeparatorMenuItem(), tk.createQuitMenuItem(appName));
tk.setApplicationMenu(appMenu);
// Add the File menu
Menu file = new Menu("File");
menuBar.getMenus().add(file);
// Add the Print item
print = new MenuItem("Print");
print.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
PrinterJob job = PrinterJob.createPrinterJob();
if (job != null && job.showPrintDialog(
lineChart.getChart().getScene().getWindow())) {
boolean success = job.printPage(lineChart.getChart());
if (success) {
job.endJob();
}
}
});
file.getItems().add(print);
// Window Menu
Menu windowMenu = new Menu("Window");
windowMenu.getItems().addAll(
tk.createMinimizeMenuItem(), tk.createZoomMenuItem(),
tk.createCycleWindowsItem(), new SeparatorMenuItem(),
tk.createBringAllToFrontItem());
menuBar.getMenus().add(windowMenu);
tk.autoAddWindowMenuItems(windowMenu);
tk.setGlobalMenuBar(menuBar);
}
NSMenuFX has been modified to correct this problem. Look for version 2.1.4 or higher.

Eclipse RCP detached views: How to control the z-index?

Let's say I have 2 views(A,B) detached. View A on top of view B on top of workbench shell.
Question 1:
How to let user click at a view to make it on top?
Question 2:
Now I use a window of other app, say, notepad, to cover view A.
Is it possible to let user just click at view A to flip it on top of the notepad while keeping view B and the main behind notepad?
Thanks for all your answer
I did some dirty work finally:
<extension
point="org.eclipse.ui.internalTweaklets">
<tweaklet
definition="org.eclipse.ui.internal.tweaklets.WorkbenchImplementation"
description="Customized Detached View"
id="id1"
implementation="tweaklets.WorkbenchImplementation"
name="Customized Detached View">
</tweaklet>
</extension>
My WorkbenchImplementation.java
public class WorkbenchImplementation extends Workbench3xImplementation {
private static final Logger logger = LoggerFactory.getLogger(WorkbenchImplementation.class);
#Override
public WorkbenchWindow createWorkbenchWindow(int newWindowNumber) {
// return super.createWorkbenchWindow(newWindowNumber);
return new WorkbenchWindow(newWindowNumber) {
#Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
try {
Field field = WorkbenchWindow.class.getDeclaredField("detachedWindowShells");
field.setAccessible(true);
field.set(this, createShellPool(shell));
} catch (Exception e) {
logger.error("Error tweaking WorkbenchWindow", e);
}
}
};
}
protected ShellPool createShellPool(Shell shell) {
// return new ShellPool(null, SWT.TOOL | SWT.TITLE | SWT.MAX | SWT.RESIZE | Window.getDefaultOrientation());
return new ShellPool(null, SWT.NO_TRIM | Window.getDefaultOrientation());
}
}
There are not general answer to this question. The behavior of the window manager depends a lot on the native window manager. E.g. Windows 7 and OSX behaves differently.

How do I mask the current page behind a modal dialog box in vanilla GWT?

I've built a log-in composite that I am displaying in my application entry-point to the user. Upon entry of the username and password, I am sending the username and password to the server via a RemoteService and will receive back an object containing the ClientSession. If the ClientSession is a valid object (recognised username and password), I wish to display the main application panel otherwise I want to display the login dialog again (with an error message).
My question is, that during the async call to the server, how to I mask the screen so that the user cannot click anything whilst the Session is obtained from the server?
I know that the login should be fast, but the Session object contains a lot of Client Side cached values for the current user that is used to generate the main panel. This may take a fraction of a second or up to 5 seconds (I can't control the speed of the underlying infrastructure unfortunately) so I want to mask the screen until a timeout is reached then allow the user to try again.
I have done this exact operation before using GWT Ext, but vanilla GWT seems to have a lot less samples unfortunately.
Thanks
Chris
The GWT class PopupPanel has an optional "glass panel" that blocks interaction with the page underneath.
final PopupPanel popup = new PopupPanel(false, true); // Create a modal dialog box that will not auto-hide
popup.add(new Label("Please wait"));
popup.setGlassEnabled(true); // Enable the glass panel
popup.center(); // Center the popup and make it visible
You might want to check out GlassPanel from the GWT Incubator project. AFAICT it's not perfect, but should be of some help nevertheless ;)
You can also use a dialog box for this purpose.
Here is the code how to use it.
public class NTMaskAlert extends DialogBox {
private String displayText;
private String message;
private static NTMaskAlert alert;
Label lable;
private NTMaskAlert(String text) {
setText(text);
setWidget(new Image(GWT.getModuleBaseURL()
+ "/images/ajax-loader_1.gif"));
setGlassEnabled(true);
setAnimationEnabled(true);
super.show();
super.center();
WorkFlowSessionFactory.putValue(WorkFlowSesisonKey.MASKING_PANEL, this);
}
public static void mask(String text) {
if (text != null)
new NTMaskAlert(text);
else
new NTMaskAlert("Processing");
}
public static void unMask() {
NTMaskAlert alert = (NTMaskAlert) WorkFlowSessionFactory
.getValue(WorkFlowSesisonKey.MASKING_PANEL);
if (alert != null) {
alert.hide();
alert = null;
}
}
public void setDisplayText(String displayText) {
this.displayText = displayText;
alert.setText(displayText);
}
public String getDisplayText() {
return displayText;
}
public void setMessage(String message) {
this.message = message;
lable.setText(message);
}
public String getMessage() {
return message;
}
}
Use static mask and unmask method for operations.
This is my solution:
public class CustomPopupPanel extends PopupPanel {
private Label label = new Label();
public CustomPopupPanel() {
super(false, true); // Create a modal dialog box that will not auto-hide
super.setGlassEnabled(true); // Enable the glass panel
super.add(label); // Add the widget label into the panel
}
public CustomPopupPanel(String text) {
this();
this.mask(text);
}
public final void mask(String text) {
label.setText(text);
super.center(); // Center the popup and make it visible
}
public void unmask() {
super.hide(); // Hide the popup
}
}

How to navigate back to the previous screen in Blackberry?

In Blackberry I can navigate from one screen to the next screen, but I can't navigate back to the previous screen. Pressing the escape key in the emulator terminates the entire application. Is there any other key in the emulator to go to the previous screen or any code to navigate back? If you know please help me.
As Andrey said, there is a display stack, so if you push screens without popping them, they will stay in stack, so closing current screen, previous screen will be shown automattically, and if there is no prev. screen, application will close.
However it's not good to hold many screens in display stack, so you can implement kind of stack inside of screens, to handle navigation manually.
Abstract screen class for screen stack implementation:
public abstract class AScreen extends MainScreen {
Screen prevScreen = null;
void openScreen(AScreen nextScreen) {
nextScreen.prevScreen = this;
UiApplication.getUiApplication().popScreen(this);
UiApplication.getUiApplication().pushScreen(nextScreen);
}
void openPrevScreen() {
UiApplication.getUiApplication().popScreen(this);
if (null != prevScreen)
UiApplication.getUiApplication().pushScreen(prevScreen);
}
}
Sample first screen:
public class FirstScreen extends AScreen implements FieldChangeListener {
ButtonField mButton = null;
public FirstScreen() {
super();
mButton = new ButtonField("Go second screen", ButtonField.CONSUME_CLICK);
mButton.setChangeListener(this);
add(mButton);
}
public void fieldChanged(Field field, int context) {
if (mButton == field) {
openScreen(new SecondScreen());
}
}
}
Sample second screen:
public class SecondScreen extends AScreen implements FieldChangeListener {
ButtonField mButton = null;
public SecondScreen() {
super();
mButton = new ButtonField("Go first screen", ButtonField.CONSUME_CLICK);
mButton.setChangeListener(this);
add(mButton);
}
public void fieldChanged(Field field, int context) {
if (mButton == field) {
openPrevScreen();
}
}
public boolean onClose() {
openPrevScreen();
return true;
}
}
The BlackBerry maintains a stack of screens; the display stack.
Screens are popped onto the stack, and popped off the stack through the UiApplication in charge of them. Popping the last screen off the stack closes the application by default.
If you are running a UiApplication, named MyUiApplication, you can add the screen to the stack by calling pushScreen(new SomeScreen());
The screen, if derived from MainScreen, as most BlackBerry screens are, is created with the DEFAULT_CLOSE flag, meaning that the ESCAPE button on the BlackBerry will naturally close the screen, causing popScreen() to be called. You can, of course, call popScreen() following any keypress or trackwheel/trackball click. The screen can also call close() on itself, which has the same result; the screen is popped off the stack, returning the application to the previous screen, or terminating the application if the last screen is popped off the display stack.
If the application is not created as a UiApplication, or if the screen was initially pushed onto the display stack from a non-UI thread (such as a background thread), then one must make sure that the call to close the screen is also done from the UI thread. This can be done by making sure that the eventLock is taken on the Application class prior to performing any UI operation (one would typically call invokeLater as well, in this situation).
If the original screen was popped onto the stack as a global screen (modeless, on top of all other screens), then it must be popped off the stack using something like:
Ui.getUiEngine().dismissStatus(this);
In any case, overriding onClose() and close() of the derived Screen will allow you to trap the occurring exception for debugging and further analysis.

Resources