OSX Swift - Show modal second window - swift

I am trying to display a second window after a button click:
var winJ:WinJo // other window NSViewController
#IBAction func BtnNewWin(sender: AnyObject) {
winJ = WinJo()
winJ.showWindow(self)
}
This works fine but I want the new window to be modal. I accomplished this with the Xcode designer but I couldn't figure out how to do this in code.

After I was pointed in the right direction I found the solution to my problem:
NSApp.runModalForWindow(winJ.window!)
Where NSApp is actually the instance of NSApplication.
And very important in the second window:
func windowWillClose(notification: NSNotification) {
NSApp.stopModal()
}
Otherwise your main window will be blocked after closing the second.

Related

How to give an NSPopover focus when NSStatusItem is clicked?

I am building a macOS menubar app in Swift, using an NSStatusItem, which opens an NSPopover when the NSStatusItem's button is clicked.
How can I also give the NSPopover focus? Currently, the user needs to click on the popover to focus it, but I want to grab focus programmatically.
Thanks in Advance
The solution is to call makeKey() on the owning window.
This can be done either from the main NSApplicationDelegate, e.g.
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Other setup
popover.contentViewController?.view.window?.makeKey()
}
Or from the relevant NSViewController, e.g.
override func viewDidAppear() {
super.viewDidAppear()
view.window?.makeKey()
}
Documentation is here

NSWindowController: How to open only one time: macOS App in status bar

I create a simple app for only status bar in macOS Swift.
I create a new NSWindowController and xib, when I call #objc function
self.aboutWindows.showWindow(self)
if I click it opens, but every time I click it opens a new window. How can I avoid it.
Same for another function of an NSMenuItem, I would like to start it only once.
Thanks
EDIT:
ALL IN APPDELEGATE
var aboutWindows = AboutWindows()
...
//TAP ON MENU ITEM
#objc func aboutWindows(_ sender: Any) {
aboutWindows = AboutWindows(windowNibName: "AboutWindows")
self.aboutWindows.showWindow(self)
}

Programmatically hide and close the window of current NSViewController

I would like to hide/close my main app window in func viewDidLoad() and only show/unhide the main window if some event requires it.
I tried self.view.window?.close() but this leaves a white window. I also tried NSApp.hide(nil) but then I can't unhide with NSApp.unhide(nil). Here is some sample code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NSApp.hide(nil)
runTest()
}
func runTest () {
let check = false
if check == false {
NSApp.unhide(nil)
}
}
From the NSWindow documentation
func orderOut(_ sender: Any?)
Removes the window from the screen list, which hides the window.
func makeKeyAndOrderFront(_ sender: Any?)
Moves the window to the front of the screen list, within its level, and makes it the key window; that is, it shows the window.
Hide and Close are two different things:
If the window is the key or main window, the window object immediately behind it is made key or main in its place. Calling orderOut(_:) causes the window to be removed from the screen, but does not cause it to be released. See the close() method for information on when a window is released. Calling orderOut(_:) on a child window causes the window to be removed from its parent window before being removed.
Hiding the application (NSApp.hide(nil) is another different thing: It
Hides all the receiver’s windows, and the next app in line is activated.

Detect maximize/minimize window event and do it programmatically

How detect Minimize/Maximize window and do this programmatically. I know that i need use NSWindowdelegate, but:
class AppDelegate: NSObject, NSApplicationDelegate, NSWindowdelegate {
func windowWillMiniaturize(_ notification: Notification) {
print("1")
}
}
This not working. And how to maximize/minimize programmatically have no idea.
It is all in Apples documentation on NSWindowDelegate: https://developer.apple.com/reference/appkit/nswindowdelegate
You can implement in you class that is set as delegate for your window:
func windowWillMiniaturize(Notification)
Tells the delegate that the window is about to be minimized.
func windowDidMiniaturize(Notification)
Tells the delegate that the window has been minimized.
func windowDidDeminiaturize(Notification)
Tells the delegate that the window has been deminimized.
NSWindow has methods - easily to find when visiting the documentation: https://developer.apple.com/reference/appkit/nswindow
You can call from anywhere on your window:
func performMiniaturize(Any?)
Simulates the user clicking the minimize button by momentarily highlighting the button, then minimizing the window.
func miniaturize(Any?)
Removes the window from the screen list and displays the minimized window in the Dock.
func deminiaturize(Any?)
De-minimizes the window.

Tooltip doesn't show up again

I have a Mac app that exclusively live on the menu bar. It has a progress bar and a label. The label shows the percentage of the progress of the task that's being carried out. I want to show more info when the user hovers the mouse pointer over the progress indicator.
When I set the tooltip initially and hover over, it displays without an issue.
But if I head over somewhere and open the menu app again and hover over again, the tooltip doesn't come up. I can't figure out why. Here's my code.
ProgressMenuController.swift
import Cocoa
class ProgressMenuController: NSObject {
#IBOutlet weak var menu: NSMenu!
#IBOutlet weak var progressView: ProgressView!
let menuItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
var progressMenuItem: NSMenuItem!
override func awakeFromNib() {
menuItem.menu = menu
menuItem.image = NSImage(named: "icon")
progressMenuItem = menu.itemWithTitle("Progress")
progressMenuItem.view = progressView
progressView.update(42)
}
#IBAction func quitClicked(sender: NSMenuItem) {
NSApplication.sharedApplication().terminate(self)
}
}
ProgressView.swift
import Cocoa
class ProgressView: NSView {
#IBOutlet weak var progressIndicator: NSProgressIndicator!
#IBOutlet weak var progressPercentageLabel: NSTextField!
func update(value: Double) {
dispatch_async(dispatch_get_main_queue()) {
self.progressIndicator.doubleValue = value
self.progressIndicator.toolTip = "3 out of 5 files has been copied"
self.progressPercentageLabel.stringValue = "\(value)%"
}
}
}
This is a demo app similar to my actual app. So the update() function is called only once and the values are hardcoded. But in my actual app, the progress is tracked periodically and the update() function gets called with it to update the values. The label's percentage value and the progress indicator's value get updated without a problem. The issue is only with the tooltip.
Is this expected behavior or am I missing something?
I ran into the same problem, and realized the issue was that only the currently focused window will display tool-tips, but after my app lost focus, it would never get it back. Focus usually transfers automatically when the user clicks on your window, but it isn't automatic for menu bar apps. Using NSApp.activate, you can regain focus onto your app:
override func viewWillAppear() {
super.viewWillAppear()
NSApp.activate(ignoringOtherApps: true)
}
sanche's answer worked for me as well, but I ended up moving the tool tips to my NSMenuItems instead so I wouldn't have to steal focus from the foreground app. NSMenuItem's tool tips seem to be handled as a special case so the app doesn't need to be focused.
This solution would make the tool tip apply to everything in the menu item and appear next to the menu rather than over it, but it looks like that might not be a problem in your case.