2 Commits
Author SHA1 Message Date
Ivan Sapozhnik f51f80c5e0 Documentation and small refactoring 2020-04-04 23:38:01 +02:00
Ivan Sapozhnik bb87a2dc3a Right edge margin 2020-04-04 23:09:40 +02:00
4 changed files with 58 additions and 28 deletions
+13 -12
View File
@@ -10,7 +10,7 @@ import Cocoa
public class Popover: NSObject {
var item: NSStatusItem!
private let windowConfiguration: PopoverConfiguration
private let wConfig: PopoverConfiguration
private var popoverWindowController: PopoverWindowController?
private var statusItemContainer: StatusItemContainerView?
private var eventMonitor: EventMonitor?
@@ -19,10 +19,10 @@ public class Popover: NSObject {
return (popoverWindowController != nil) ? popoverWindowController!.windowIsOpen : false
}
/// Create a Popover with given PopoverConfiguration. Popover configuration can be either `DefaultConfiguration` or you can sublclass this class and override some of the properties.
/// By default Popover is using Event Monitor and by doing left or right clicl ouside of the Popover's frame, the system will automatically dismiss the Popover.
public init(with configuration: PopoverConfiguration) {
windowConfiguration = configuration
/// Creates a Popover with given PopoverConfiguration. Popover configuration can be either `DefaultConfiguration` or you can sublclass this class and override some of the properties.
/// By default Popover is using Event Monitor and by doing left or right click ouside of the Popover's frame, the Popover will be automatically dismissed.
public init(with windowConfiguration: PopoverConfiguration) {
wConfig = windowConfiguration
super.init()
@@ -32,18 +32,23 @@ public class Popover: NSObject {
})
}
/// Convenience initializer which is using default configuration
public convenience override init() {
self.init(with: DefaultConfiguration())
}
/// Creates a Popover with given image and contentViewController
/// By default it won't present any Popover until the user clicks on status bar item
public func createPopover(with image: NSImage, contentViewController viewController: NSViewController) {
configureStatusBarButton(with: image)
popoverWindowController = PopoverWindowController(with: self, contentViewController: viewController, windowConfiguration: windowConfiguration)
popoverWindowController = PopoverWindowController(with: self, contentViewController: viewController, windowConfiguration: wConfig)
}
/// Creates a Popover with given view and contentViewController. The view's height will be scaled down to 18pt and also will be vertically aligned. The wdith can be any.
/// By default it won't present any Popover until the user clicks on status bar item
public func createPopover(with view: NSView, contentViewController viewController: NSViewController) {
configureStatusBarButton(with: view)
popoverWindowController = PopoverWindowController(with: self, contentViewController: viewController, windowConfiguration: windowConfiguration)
popoverWindowController = PopoverWindowController(with: self, contentViewController: viewController, windowConfiguration: wConfig)
}
/// Shows the Popover with no animation
@@ -85,10 +90,6 @@ public class Popover: NSObject {
}
@objc private func handleStatusItemButtonAction(_ sender: Any?) {
if isPopoverWindowVisible {
dismiss()
} else {
show()
}
isPopoverWindowVisible ? dismiss() : show()
}
}
+40 -10
View File
@@ -8,14 +8,40 @@
import Cocoa
public protocol PopoverConfiguration {
var popoverToStatusItemMargin: CGFloat { get }
var backgroundColor: NSColor { get }
var borderColor: NSColor? { get }
var borderWidth: CGFloat { get }
var arrowHeight: CGFloat { get }
var arrowWidth: CGFloat { get }
var cornerRadius: CGFloat { get }
var contentInset: NSEdgeInsets { get }
/// The distance from Popover's arrow to a status item.
var popoverToStatusItemMargin: CGFloat { get }
/// Popover's background color.
var backgroundColor: NSColor { get }
/// Popover's border color.
/// - Important:
/// If `borderColor` returns `nil`, settings `borderWidth` won't make any affect. See also: `borderWidth`.
var borderColor: NSColor? { get }
/// Popover's border width.
/// - Important:
/// If Popover's border color is set to `nil`, setting `borderWidth` won't make any affect.
var borderWidth: CGFloat { get }
/// Defines Popover arrow height.
var arrowHeight: CGFloat { get }
/// Defines Popover arrow width.
var arrowWidth: CGFloat { get }
/// Defines Popover corner radius.
/// - Warning:
/// If this value is too big and if the Popover's status item (menu bar view) is too close to the right edge, the appearence of the Popover might be odd.
var cornerRadius: CGFloat { get }
/// Defines Popover content edge insets.
var contentEdgeInsets: NSEdgeInsets { get }
/// The distance from the right side of the Popover to the screen's edge.
/// - Warning:
/// If this value is too big and if the Popover's status item (menu bar view) is too close to the right edge, the appearence of the Popover might be odd.
var rightEdgeMargin: CGFloat { get }
}
open class DefaultConfiguration: PopoverConfiguration {
@@ -46,10 +72,14 @@ open class DefaultConfiguration: PopoverConfiguration {
}
open var cornerRadius: CGFloat {
return 12
return 5
}
open var contentInset: NSEdgeInsets {
open var contentEdgeInsets: NSEdgeInsets {
return NSEdgeInsetsZero
}
open var rightEdgeMargin: CGFloat {
return 12.0
}
}
+4 -4
View File
@@ -74,10 +74,10 @@ class PopoverWindow: NSPanel {
backgroundView.addSubview(userContentView)
let borderWidth = wConfig.borderColor != nil ? wConfig.borderWidth : 0
let left = borderWidth + wConfig.contentInset.left
let right = borderWidth + wConfig.contentInset.right
let top = wConfig.arrowHeight + borderWidth + wConfig.contentInset.top
let bottom = borderWidth + wConfig.contentInset.bottom
let left = borderWidth + wConfig.contentEdgeInsets.left
let right = borderWidth + wConfig.contentEdgeInsets.right
let top = wConfig.arrowHeight + borderWidth + wConfig.contentEdgeInsets.top
let bottom = borderWidth + wConfig.contentEdgeInsets.bottom
NSLayoutConstraint.activate([
userContentView.leadingAnchor.constraint(equalTo: backgroundView.leadingAnchor, constant: left),
@@ -59,9 +59,8 @@ class PopoverWindowController: NSWindowController {
guard let window = self.window else { return (.zero, 0.0) }
let rightEdgeMargin: CGFloat = 5.0
let borderWidth = wConfig.borderColor != nil ? wConfig.borderWidth : 0
let x = min(NSMinX(statusItemRect) - NSWidth(window.frame) / 2 + NSWidth(statusItemRect) / 2 + borderWidth, NSMaxX(screenFrame) - NSWidth(window.frame) - rightEdgeMargin)
let x = min(NSMinX(statusItemRect) - NSWidth(window.frame) / 2 + NSWidth(statusItemRect) / 2 + borderWidth, NSMaxX(screenFrame) - NSWidth(window.frame) - wConfig.rightEdgeMargin)
let y = min(NSMinY(statusItemRect), NSMaxY(screenFrame)) - NSHeight(window.frame) - wConfig.popoverToStatusItemMargin + borderWidth / 2
let windowFrame = NSMakeRect(x, y, NSWidth(window.frame), NSHeight(window.frame))