123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886 |
- //
- // KMLineWell.swift
- // PDF Reader Pro
- //
- // Created by tangchao on 2023/11/6.
- //
- import Cocoa
- private let SKPasteboardTypeLineStyle = "net.sourceforge.skim-app.pasteboard.line-style"
- private let SKLineWellLineWidthKey = "lineWidth"
- private let SKLineWellStyleKey = "style"
- private let SKLineWellDashPatternKey = "dashPattern"
- private let SKLineWellStartLineStyleKey = "startLineStyle"
- private let SKLineWellEndLineStyleKey = "endLineStyle"
- private let ACTION_KEY = "action"
- private let TARGET_KEY = "target"
- private let DISPLAYSTYLE_KEY = "lwFlagsdisplayStyle"
- private let ACTIVE_KEY = "active"
- private let SKLineWellWillBecomeActiveNotification = "SKLineWellWillBecomeActiveNotification"
- private let EXCLUSIVE_KEY = "exclusive"
- enum KMLineWellDisplayStyle: Int {
- case line = 0
- case simpleLine
- case rectangle
- case oval
- }
- class KMLineWell: NSControl {
-
- public static let widthKey = SKLineWellLineWidthKey
- public static let styleKey = SKLineWellStyleKey
- public static let dashPatternKey = SKLineWellDashPatternKey
- public static let startLineStyleKey = SKLineWellStartLineStyleKey
- public static let endLineStyleKey = SKLineWellEndLineStyleKey
-
- public static let lineStylePboardTypeString = SKPasteboardTypeLineStyle
- public static let lineStylePboardType = NSPasteboard.PasteboardType(rawValue: SKPasteboardTypeLineStyle)
-
- private var _lineWidth: CGFloat = 2
- var lineWidth: CGFloat {
- get {
- return self._lineWidth
- }
- set {
- if (abs(self._lineWidth - newValue) > 0.00001) {
- self._lineWidth = newValue
- self._changedValue(forKey: SKLineWellLineWidthKey)
- }
- }
- }
- private var _style: CPDFBorderStyle = .solid
- var style: CPDFBorderStyle {
- get {
- return self._style
- }
- set {
- if (newValue != self._style) {
- self._style = newValue
- self._changedValue(forKey: SKLineWellStyleKey)
- }
- }
- }
- private var _startLineStyle: CPDFLineStyle = .none
- var startLineStyle: CPDFLineStyle {
- get {
- return self._startLineStyle
- }
- set {
- if (newValue != self._startLineStyle) {
- self._startLineStyle = newValue
- self._changedValue(forKey: SKLineWellStartLineStyleKey)
- }
- }
- }
- private var _endLineStyle: CPDFLineStyle = .none
- var endLineStyle: CPDFLineStyle {
- get {
- return self._endLineStyle
- }
- set {
- if (newValue != self._endLineStyle) {
- self._endLineStyle = newValue
- self._changedValue(forKey: SKLineWellEndLineStyleKey)
- }
- }
- }
- private var _dashPattern: NSArray?
- var dashPattern: NSArray? {
- get {
- return self._dashPattern
- }
- set {
- var _pattern: NSArray? = newValue
- if (NSIsControllerMarker(_pattern)) {
- _pattern = nil
- }
- if _pattern?.isEqual(to: self._dashPattern) == false && _pattern != nil || self._dashPattern != nil {
- self._dashPattern = _pattern
- self._changedValue(forKey: SKLineWellDashPatternKey)
- }
- }
- }
-
- var displayStyle: KMLineWellDisplayStyle {
- get {
- return KMLineWellDisplayStyle(rawValue: Int(__lwFlags.displayStyle)) ?? .line
- }
- set {
- if __lwFlags.displayStyle != newValue.rawValue {
- __lwFlags.displayStyle = UInt8(newValue.rawValue)
- self.needsDisplay = true
- }
- }
- }
-
- private struct _lwFlags {
- var displayStyle: UInt8 = 0
- var active = false
- var canActivate = false
- var existsActiveLineWell: UInt8 = 0
- var highlighted: Bool = false
- }
-
- private var __lwFlags = _lwFlags()
-
- var canActivate: Bool {
- get {
- return __lwFlags.canActivate
- }
- set {
- if __lwFlags.canActivate != newValue {
- __lwFlags.canActivate = newValue
- if self.isActive && __lwFlags.canActivate == false {
- self._deactivate()
- }
- }
- }
- }
-
- var isActive: Bool {
- get {
- return __lwFlags.active
- }
- }
-
- override var isHighlighted: Bool {
- get {
- return self.__lwFlags.highlighted
- }
- set {
- if self.__lwFlags.highlighted != newValue {
- self.__lwFlags.highlighted = newValue
- }
- }
- }
-
- private var _pri_target: AnyObject?
- private var _pri_action: Selector?
-
- deinit {
- KMPrint("KMLineWell deinit.")
-
- NotificationCenter.default.removeObserver(self)
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- lineWidth = 1.0
- style = .solid
- dashPattern = nil;
- startLineStyle = .none
- endLineStyle = .none
- __lwFlags.displayStyle = UInt8(KMLineWellDisplayStyle.line.rawValue)
- __lwFlags.active = false
- __lwFlags.canActivate = false
- __lwFlags.existsActiveLineWell = 0
-
- self.target = nil
- self.action = nil
-
- self._commonInit()
- }
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
-
- lineWidth = coder.decodeDouble(forKey: SKLineWellLineWidthKey)
- style = CPDFBorderStyle(rawValue: coder.decodeInteger(forKey: SKLineWellStyleKey)) ?? .solid
- dashPattern = coder.decodeObject(forKey: SKLineWellDashPatternKey) as? NSArray
- startLineStyle = CPDFLineStyle(rawValue: coder.decodeInteger(forKey: SKLineWellStartLineStyleKey)) ?? .none
- endLineStyle = CPDFLineStyle(rawValue: coder.decodeInteger(forKey: SKLineWellEndLineStyleKey)) ?? .none
-
- __lwFlags.displayStyle = UInt8(coder.decodeInteger(forKey: DISPLAYSTYLE_KEY))
- __lwFlags.active = coder.decodeBool(forKey: ACTIVE_KEY)
- action = NSSelectorFromString(coder.decodeObject(forKey: ACTION_KEY) as? String ?? "")
- target = coder.decodeObject(forKey: TARGET_KEY) as AnyObject?
-
- self._commonInit()
- }
-
- override func encode(with coder: NSCoder) {
- super.encode(with: coder)
-
- coder.encode(lineWidth, forKey: SKLineWellLineWidthKey)
- coder.encode(style.rawValue, forKey: SKLineWellStyleKey)
-
- coder.encode(dashPattern, forKey: SKLineWellDashPatternKey)
- coder.encode(startLineStyle.rawValue, forKey: SKLineWellStartLineStyleKey)
- coder.encode(endLineStyle.rawValue, forKey: SKLineWellEndLineStyleKey)
- coder.encode(__lwFlags.displayStyle, forKey: DISPLAYSTYLE_KEY)
- coder.encode(__lwFlags.active, forKey: ACTIVE_KEY)
-
- if let data = self.action {
- coder.encode(NSStringFromSelector(data), forKey: ACTION_KEY)
- }
- coder.encode(target, forKey: TARGET_KEY)
- }
-
- override var isOpaque: Bool {
- return true
- }
-
- override var acceptsFirstResponder: Bool {
- return self.canActivate
- }
-
- override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
- return self.canActivate
- }
-
- override func viewWillMove(toWindow newWindow: NSWindow?) {
- self._deactivate()
- super.viewWillMove(toWindow: newWindow)
- }
- override func draw(_ dirtyRect: NSRect) {
- super.draw(dirtyRect)
- let bounds = self.bounds
-
- KMDrawTextFieldBezel(bounds, self)
-
- if (self.isActive) {
- NSGraphicsContext.saveGraphicsState()
- NSColor.selectedControlColor.setFill()
- bounds.fill(using: .plusDarker)
- NSGraphicsContext.restoreGraphicsState()
- }
- if (self.isHighlighted) {
- NSGraphicsContext.saveGraphicsState()
- NSColor(calibratedWhite: 0, alpha: 0.1).setFill()
- self.bounds.frame(withWidth: 1, using: .plusDarker)
- NSGraphicsContext.restoreGraphicsState()
- }
-
- if (lineWidth > 0.0) {
- NSGraphicsContext.saveGraphicsState()
- NSBezierPath(rect: NSInsetRect(bounds, 2.0, 2.0)).addClip()
- NSColor.black.setStroke()
- self._path().stroke()
- NSGraphicsContext.restoreGraphicsState()
- }
-
- if self.refusesFirstResponder == false && NSApp.isActive && self.isEqual(to: self.window?.firstResponder) {
- if let data = self.window?.isKeyWindow, data {
- NSGraphicsContext.saveGraphicsState()
- NSFocusRingPlacement.only.set()
- bounds.fill()
- NSGraphicsContext.restoreGraphicsState()
- }
- }
- }
-
- override func mouseDown(with event: NSEvent) {
- if (self.isEnabled) {
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- // NSUInteger modifiers = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
- var modifiers = event.modifierFlags
- // modifiers.insert(.deviceIndependentFlagsMask)
- if modifiers.contains(.deviceIndependentFlagsMask) {
- modifiers.remove(.deviceIndependentFlagsMask)
- }
- var keepOn = true
- var _event: NSEvent = event
- while (keepOn) {
- // theEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask | NSLeftMouseDraggedMask];
- if let data = self.window?.nextEvent(matching: [.leftMouseUp, .leftMouseDragged]) {
- _event = data
- switch (_event.type) {
- case .leftMouseDragged:
- // {
- // NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- // [NSNumber numberWithDouble:lineWidth], , [NSNumber numberWithInteger:style], , dashPattern, , nil];
- var dict = [SKLineWellLineWidthKey : NSNumber(value: self.lineWidth),
- SKLineWellStyleKey : NSNumber(value: self.style.rawValue),
- SKLineWellDashPatternKey : self.dashPattern ?? []]
- if self.displayStyle == .line {
- // if ([self displayStyle] == SKLineWellDisplayStyleLine) {
- dict[SKLineWellStartLineStyleKey] = NSNumber(value: self.startLineStyle.rawValue)
- dict[SKLineWellEndLineStyleKey] = NSNumber(value: self.endLineStyle.rawValue)
- }
-
- let pboard = NSPasteboard(name: .drag)
- pboard.clearContents()
- pboard.setPropertyList(dict, forType: Self.lineStylePboardType)
-
- let bounds = self.bounds
- /*beginDraggingSessionWithItems:event:source: instead*/
- // [self dragImage:[self dragImage] at:bounds.origin offset:NSZeroSize event:theEvent pasteboard:pboard source:self slideBack:YES];
- keepOn = false
- break
- // }
- case .leftMouseUp:
- if (self.isActive) {
- self._deactivate()
- } else {
- // [self activate:(modifiers & NSShiftKeyMask) == 0];
- self._activate(modifiers.contains(.shift) == false)
- }
- keepOn = false
- break
- default:
- break
- }
- }
- }
- }
- }
-
- override func performClick(_ sender: Any?) {
- if (self.isEnabled) {
- if (self.isActive) {
- self._deactivate()
- } else {
- self._activate(true)
- }
- }
-
- }
-
- override var target: AnyObject? {
- get {
- return self._pri_target
- }
- set {
- self._pri_target = newValue
- }
- }
-
- override var action: Selector? {
- get {
- return self._pri_action
- }
- set {
- self._pri_action = newValue
- }
- }
-
- func takeValue(for key: String, from object: AnyObject) {
- if let inspector = object as? KMLineInspector {
- if key == Self.widthKey {
- self.lineWidth = inspector.lineWidth
- } else if key == Self.styleKey {
- self.style = CPDFBorderStyle(rawValue: inspector.style) ?? .solid
- } else if key == Self.startLineStyleKey {
- self.startLineStyle = CPDFLineStyle(rawValue: inspector.startLineStyle) ?? .none
- } else if key == Self.endLineStyleKey {
- self.endLineStyle = CPDFLineStyle(rawValue: inspector.endLineStyle) ?? .none
- } else if key == Self.dashPatternKey {
- self.dashPattern = inspector.dashPattern as NSArray
- }
- }
- }
-
- // MARK: - NSDraggingDestination
- // - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
- // return NSDragOperationGeneric;
- // }
- override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
- if self.isEnabled && self.isEqual(to: sender.draggingSource) == false && sender.draggingPasteboard.canReadItem(withDataConformingToTypes: [Self.lineStylePboardTypeString]) {
- self.isHighlighted = true
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- return .every
- }
- return NSDragOperation(rawValue: 0)
- }
- override func draggingExited(_ sender: NSDraggingInfo?) {
- if self.isEnabled && self.isEqual(to: sender?.draggingSource) == false {
- if let pboard = sender?.draggingPasteboard, pboard.canReadItem(withDataConformingToTypes: [Self.lineStylePboardTypeString]) {
- self.isHighlighted = false
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- }
- }
- }
-
- override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {
- if self.isEnabled == false {
- return self.isEnabled
- }
- if self.isEqual(to: sender.draggingSource) == false {
- return false
- }
- return sender.draggingPasteboard.canReadItem(withDataConformingToTypes: [Self.lineStylePboardTypeString])
- }
- override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
- let pboard = sender.draggingPasteboard
- _ = pboard.types
- let dict = pboard.propertyList(forType: Self.lineStylePboardType) as? [String : Any]
- if let data = dict?[Self.widthKey] as? NSNumber {
- self.lineWidth = data.floatValue.cgFloat
- } else if let data = dict?[Self.styleKey] as? NSNumber {
- self.style = CPDFBorderStyle(rawValue: data.intValue) ?? .solid
- } else if let data = dict?[Self.dashPatternKey] {
- self.dashPattern = data as? NSArray ?? []
- } else {
- if self.displayStyle == .line || self.displayStyle == .simpleLine {
- if let data = dict?[Self.startLineStyleKey] as? NSNumber {
- self.startLineStyle = CPDFLineStyle(rawValue: data.intValue) ?? .none
- } else if let data = dict?[Self.endLineStyleKey] as? NSNumber {
- self.endLineStyle = CPDFLineStyle(rawValue: data.intValue) ?? .none
- }
- }
- }
- self.sendAction(self.action, to: self.target)
- self.isHighlighted = false
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- return dict != nil
- }
-
- // - (void)takeValueForKey:(NSString *)key from:(id)object {
- // [self setValue:[object valueForKey:key] forKey:key];
- // NSDictionary *info = [self infoForBinding:key];
- // [[info objectForKey:NSObservedObjectKey] setValue:[self valueForKey:key] forKeyPath:[info objectForKey:NSObservedKeyPathKey]];
- // }
- /*
- + (void)initialize {
- // SKINITIALIZE;
-
- [self exposeBinding:SKLineWellLineWidthKey];
- [self exposeBinding:SKLineWellStyleKey];
- [self exposeBinding:SKLineWellDashPatternKey];
- [self exposeBinding:SKLineWellStartLineStyleKey];
- [self exposeBinding:SKLineWellEndLineStyleKey];
- }
- - (Class)valueClassForBinding:(NSString *)binding {
- if ([binding isEqualToString:SKLineWellDashPatternKey])
- return [NSArray class];
- else
- return [NSNumber class];
- }
- - (void)dealloc {
- // SKENSURE_MAIN_THREAD(
- [self unbind:SKLineWellLineWidthKey];
- [self unbind:SKLineWellStyleKey];
- [self unbind:SKLineWellDashPatternKey];
- [self unbind:SKLineWellStartLineStyleKey];
- [self unbind:SKLineWellEndLineStyleKey];
- // );
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- // SKDESTROY(dashPattern);
- // [super dealloc];
- }
- #pragma mark Accessors
- - (SEL)action { return action; }
- - (void)setAction:(SEL)newAction { action = newAction; }
- - (id)target { return target; }
- - (void)setTarget:(id)newTarget { target = newTarget; }
- - (void)setNilValueForKey:(NSString *)key {
- if ([key isEqualToString:SKLineWellLineWidthKey] || [key isEqualToString:SKLineWellStyleKey] ||
- [key isEqualToString:SKLineWellStartLineStyleKey] || [key isEqualToString:SKLineWellEndLineStyleKey]) {
- [self setValue:[NSNumber numberWithInteger:0] forKey:key];
- } else {
- [super setNilValueForKey:key];
- }
- }
- #pragma mark Notification handlers
- #pragma mark NSDraggingSource protocol
- - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
- return NSDragOperationGeneric;
- }
- #pragma mark NSDraggingDestination protocol
- - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
- if ([self isEnabled] && [sender draggingSource] != self && [[sender draggingPasteboard] canReadItemWithDataConformingToTypes:[NSArray arrayWithObjects:SKPasteboardTypeLineStyle, nil]]) {
- [self setHighlighted:YES];
- [self setKeyboardFocusRingNeedsDisplayInRect:[self bounds]];
- [self setNeedsDisplay:YES];
- return NSDragOperationEvery;
- } else
- return NSDragOperationNone;
- }
- - (void)draggingExited:(id <NSDraggingInfo>)sender {
- if ([self isEnabled] && [sender draggingSource] != self && [[sender draggingPasteboard] canReadItemWithDataConformingToTypes:[NSArray arrayWithObjects:SKPasteboardTypeLineStyle, nil]]) {
- [self setHighlighted:NO];
- [self setKeyboardFocusRingNeedsDisplayInRect:[self bounds]];
- [self setNeedsDisplay:YES];
- }
- }
- - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
- return [self isEnabled] && [sender draggingSource] != self && [[sender draggingPasteboard] canReadItemWithDataConformingToTypes:[NSArray arrayWithObjects:SKPasteboardTypeLineStyle, nil]];
- }
- - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender{
- NSPasteboard *pboard = [sender draggingPasteboard];
-
- [pboard types];
-
- NSDictionary *dict = [pboard propertyListForType:SKPasteboardTypeLineStyle];
-
- if ([dict objectForKey:SKLineWellLineWidthKey])
- [self takeValueForKey:SKLineWellLineWidthKey from:dict];
- if ([dict objectForKey:SKLineWellStyleKey])
- [self takeValueForKey:SKLineWellStyleKey from:dict];
- [self takeValueForKey:SKLineWellDashPatternKey from:dict];
- if ([self displayStyle] == SKLineWellDisplayStyleLine) {
- if ([dict objectForKey:SKLineWellStartLineStyleKey])
- [self takeValueForKey:SKLineWellStartLineStyleKey from:dict];
- if ([dict objectForKey:SKLineWellEndLineStyleKey])
- [self takeValueForKey:SKLineWellEndLineStyleKey from:dict];
- }
- [self sendAction:[self action] to:[self target]];
-
- [self setHighlighted:NO];
- [self setKeyboardFocusRingNeedsDisplayInRect:[self bounds]];
- [self setNeedsDisplay:YES];
-
- return dict != nil;
- }
- #pragma mark Accessibility
- - (NSArray *)accessibilityAttributeNames {
- static NSArray *attributes = nil;
- if (attributes == nil) {
- attributes = [[NSArray alloc] initWithObjects:
- NSAccessibilityRoleAttribute,
- NSAccessibilityRoleDescriptionAttribute,
- NSAccessibilityValueAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityHelpAttribute,
- NSAccessibilityFocusedAttribute,
- NSAccessibilityParentAttribute,
- NSAccessibilityWindowAttribute,
- NSAccessibilityTopLevelUIElementAttribute,
- NSAccessibilityPositionAttribute,
- NSAccessibilitySizeAttribute,
- nil];
- }
- return attributes;
- }
- - (id)accessibilityAttributeValue:(NSString *)attribute {
- if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- return NSAccessibilityCheckBoxRole;
- } else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
- return NSAccessibilityRoleDescription(NSAccessibilityCheckBoxRole, nil);
- } else if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
- return [NSNumber numberWithInteger:[self isActive]];
- } else if ([attribute isEqualToString:NSAccessibilityTitleAttribute]) {
- return [NSString stringWithFormat:@"%@ %ld", NSLocalizedString(@"line width", @"Accessibility description"), (long)[self lineWidth]];
- } else if ([attribute isEqualToString:NSAccessibilityHelpAttribute]) {
- return [self toolTip];
- } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- // Just check if the app thinks we're focused.
- id focusedElement = [NSApp accessibilityAttributeValue:NSAccessibilityFocusedUIElementAttribute];
- return [NSNumber numberWithBool:[focusedElement isEqual:self]];
- } else if ([attribute isEqualToString:NSAccessibilityParentAttribute]) {
- return NSAccessibilityUnignoredAncestor([self superview]);
- } else if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) {
- // We're in the same window as our parent.
- return [NSAccessibilityUnignoredAncestor([self superview]) accessibilityAttributeValue:NSAccessibilityWindowAttribute];
- } else if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) {
- // We're in the same top level element as our parent.
- return [NSAccessibilityUnignoredAncestor([self superview]) accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute];
- } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) {
- return [NSValue valueWithPoint:[[self window] convertBaseToScreen:[self convertPoint:[self bounds].origin toView:nil]]];
- } else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) {
- return [NSValue valueWithSize:[self convertSize:[self bounds].size toView:nil]];
- } else {
- return nil;
- }
- }
- - (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
- if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- return [self canActivate];
- } else {
- return NO;
- }
- }
- - (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
- if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
- [[self window] makeFirstResponder:self];
- }
- }
- // actions
- - (NSArray *)accessibilityActionNames {
- return [NSArray arrayWithObject:NSAccessibilityPressAction];
- }
- - (NSString *)accessibilityActionDescription:(NSString *)anAction {
- return NSAccessibilityActionDescription(anAction);
- }
- - (void)accessibilityPerformAction:(NSString *)anAction {
- if ([anAction isEqualToString:NSAccessibilityPressAction])
- [self performClick:self];
- }
- // misc
- - (BOOL)accessibilityIsIgnored {
- return NO;
- }
- - (id)accessibilityHitTest:(NSPoint)point {
- return NSAccessibilityUnignoredAncestor(self);
- }
- - (id)accessibilityFocusedUIElement {
- return NSAccessibilityUnignoredAncestor(self);
- }
- @end
- */
- }
- // MARK: - Private Methods
- extension KMLineWell {
- private func _commonInit() {
- __lwFlags.canActivate = true
- __lwFlags.existsActiveLineWell = 0
-
- self.isEnabled = true
-
- self.registerForDraggedTypes([Self.lineStylePboardType])
- }
-
- private func _deactivate() {
- if self.isActive {
- NotificationCenter.default.removeObserver(self)
- __lwFlags.active = false
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- }
- }
-
- private func _changedValue(forKey key: String) {
- if (self.isActive) {
- // [[SKLineInspector sharedLineInspector] setValue:[self valueForKey:key] forKey:key];
- }
- self.needsDisplay = true
- }
-
- private func _dragImage() -> NSImage? {
- let bounds = self.bounds
- let path = self.lineWidth > 0.0 ? self._path() : nil
- // CGFloat scale = [self backingScale];
- let scale = 1.0
-
- let image = NSImage.bitmapImage(with: bounds.size, scale: scale) { rect in
- KMContextSetAlpha(NSGraphicsContext.current?.cgContext, 0.7)
- NSColor.darkGray.setFill()
- _ = NSRect.fill(NSInsetRect(rect, 1.0, 1.0))
- NSColor.controlBackgroundColor.setFill()
- _ = NSRect.fill(NSInsetRect(rect, 2.0, 2.0))
- NSColor.black.setStroke()
- path?.stroke()
- }
-
- return image
- }
-
- private func _path() -> NSBezierPath {
- let path = NSBezierPath()
- let bounds = self.bounds
-
- if self.displayStyle == .line {
- let offset = 0.5 * lineWidth - floor(0.5 * lineWidth)
- let startPoint = NSMakePoint(NSMinX(bounds) + ceil(0.5 * NSHeight(bounds)), round(NSMidY(bounds)) - offset)
- let endPoint = NSMakePoint(NSMaxX(bounds) - ceil(0.5 * NSHeight(bounds)), round(NSMidY(bounds)) - offset)
-
- switch (self.startLineStyle) {
- case .none:
- break
- case .square:
- path.appendRect(NSMakeRect(startPoint.x - 1.5 * lineWidth, startPoint.y - 1.5 * lineWidth, 3 * lineWidth, 3 * lineWidth))
- break
- case .circle:
- path.appendOval(in: NSMakeRect(startPoint.x - 1.5 * lineWidth, startPoint.y - 1.5 * lineWidth, 3 * lineWidth, 3 * lineWidth))
- break
- case .diamond:
- path.move(to: NSMakePoint(startPoint.x - 1.5 * lineWidth, startPoint.y))
- path.line(to: NSMakePoint(startPoint.x, startPoint.y + 1.5 * lineWidth))
- path.line(to: NSMakePoint(startPoint.x + 1.5 * lineWidth, startPoint.y))
- path.line(to: NSMakePoint(startPoint.x, startPoint.y - 1.5 * lineWidth))
- path.close()
- break
- case .openArrow:
- path.move(to: NSMakePoint(startPoint.x + 3.0 * lineWidth, startPoint.y - 1.5 * lineWidth))
- path.line(to: NSMakePoint(startPoint.x, startPoint.y))
- path.line(to: NSMakePoint(startPoint.x + 3.0 * lineWidth, startPoint.y + 1.5 * lineWidth))
- break
- case .closedArrow:
- path.move(to: NSMakePoint(startPoint.x + 3.0 * lineWidth, startPoint.y - 1.5 * lineWidth))
- path.line(to: NSMakePoint(startPoint.x, startPoint.y))
- path.line(to: NSMakePoint(startPoint.x + 3.0 * lineWidth, startPoint.y + 1.5 * lineWidth))
- path.close()
- break
- @unknown default:
- fatalError()
- }
-
- path.move(to: startPoint)
- path.line(to: endPoint)
-
- switch (self.endLineStyle) {
- case .none:
- break
- case .square:
- path.appendRect(NSMakeRect(endPoint.x - 1.5 * lineWidth, endPoint.y - 1.5 * lineWidth, 3 * lineWidth, 3 * lineWidth))
- break
- case .circle:
- path.appendOval(in: NSMakeRect(endPoint.x - 1.5 * lineWidth, endPoint.y - 1.5 * lineWidth, 3 * lineWidth, 3 * lineWidth))
- break
- case .diamond:
- path.move(to: NSMakePoint(endPoint.x + 1.5 * lineWidth, endPoint.y))
- path.line(to: NSMakePoint(endPoint.x, endPoint.y + 1.5 * lineWidth))
- path.line(to: NSMakePoint(endPoint.x - 1.5 * lineWidth, endPoint.y))
- path.line(to: NSMakePoint(endPoint.x, endPoint.y - 1.5 * lineWidth))
- path.close()
- break
- case .openArrow:
- path.move(to: NSMakePoint(endPoint.x - 3.0 * lineWidth, endPoint.y + 1.5 * lineWidth))
- path.line(to: NSMakePoint(endPoint.x, endPoint.y))
- path.line(to: NSMakePoint(endPoint.x - 3.0 * lineWidth, endPoint.y - 1.5 * lineWidth))
- break
- case .closedArrow:
- path.move(to: NSMakePoint(endPoint.x - 3.0 * lineWidth, endPoint.y + 1.5 * lineWidth))
- path.line(to: NSMakePoint(endPoint.x, endPoint.y))
- path.line(to: NSMakePoint(endPoint.x - 3.0 * lineWidth, endPoint.y - 1.5 * lineWidth))
- path.close()
- break
- @unknown default:
- fatalError()
- }
- } else if self.displayStyle == .simpleLine {
- let offset = 0.5 * lineWidth - floor(0.5 * lineWidth)
- path.move(to: NSMakePoint(NSMinX(bounds) + ceil(0.5 * NSHeight(bounds)), round(NSMidY(bounds)) - offset))
- path.line(to: NSMakePoint(NSMaxX(bounds) - ceil(0.5 * NSHeight(bounds)), round(NSMidY(bounds)) - offset))
- } else if self.displayStyle == .rectangle {
- let inset = 7.0 + 0.5 * lineWidth
- path.appendRect(NSInsetRect(bounds, inset, inset))
- } else {
- let inset = 7.0 + 0.5 * lineWidth
- path.appendOval(in: NSInsetRect(bounds, inset, inset))
- }
-
- path.lineWidth = self.lineWidth
- if self.style == .dashed {
- path.setLineDash(self.dashPattern as? [CGFloat], count: self.dashPattern?.count ?? 0, phase: 0)
- }
- return path
- }
-
- private func _activate(_ exclusive: Bool) {
- if (self.canActivate) {
- let nc = NotificationCenter.default
- let inspector = KMLineInspector.shared
- _ = inspector.window
-
- __lwFlags.existsActiveLineWell = 0
-
- nc.post(name: NSNotification.Name(rawValue: SKLineWellWillBecomeActiveNotification), object: self, userInfo: [EXCLUSIVE_KEY : NSNumber(value: exclusive)])
-
- if (__lwFlags.existsActiveLineWell != 0) {
- self.takeValue(for: SKLineWellLineWidthKey, from: inspector)
- self.takeValue(for: SKLineWellDashPatternKey, from: inspector)
- self.takeValue(for: SKLineWellStyleKey, from: inspector)
- if (self.displayStyle == .line) {
- self.takeValue(for: SKLineWellStartLineStyleKey, from: inspector)
- self.takeValue(for: SKLineWellEndLineStyleKey, from: inspector)
- }
- } else {
- inspector.lineWidth = self.lineWidth
- inspector.dashPattern = self.dashPattern as? [CGFloat] ?? []
- inspector.style = self.style.rawValue
- if (self.displayStyle == .line) {
- inspector.startLineStyle = self.startLineStyle.rawValue
- inspector.endLineStyle = self.endLineStyle.rawValue
- }
- }
- inspector.window?.orderFront(self)
-
- nc.addObserver(self, selector: #selector(_lineWellWillBecomeActive), name: NSNotification.Name(SKLineWellWillBecomeActiveNotification), object: nil)
- nc.addObserver(self, selector: #selector(_lineInspectorWindowWillClose), name: NSWindow.willCloseNotification, object: inspector.window)
- nc.addObserver(self, selector: #selector(_lineInspectorLineAttributeChanged), name: KMLineInspector.lineAttributeDidChangeNotification, object: inspector)
-
- __lwFlags.active = true
-
- self.setKeyboardFocusRingNeedsDisplay(self.bounds)
- self.needsDisplay = true
- }
- }
-
- @objc private func _lineWellWillBecomeActive(_ notification: NSNotification) {
- let sender = notification.object
- if (self.isEqual(to: sender) == false && self.isActive) {
- if let data = notification.userInfo?[EXCLUSIVE_KEY] as? NSNumber, data.boolValue {
- self._deactivate()
- } else {
- (sender as? KMLineWell)?._existsActiveLineWell()
- }
- }
- }
-
- @objc private func _lineInspectorWindowWillClose(_ notification: Notification) {
- self._deactivate()
- }
-
- @objc private func _lineInspectorLineAttributeChanged(_ notification: Notification) {
- guard let inspector = notification.object as? KMLineInspector else {
- return
- }
- let action = inspector.currentLineChangeAction
- var key: String?
- if action == .lineWidth {
- key = Self.widthKey
- } else if action == .style {
- key = Self.styleKey
- } else if action == .dashPattern {
- key = Self.dashPatternKey
- } else if action == .startLineStyle {
- key = Self.startLineStyleKey
- } else if action == .endLineStyle {
- key = Self.endLineStyleKey
- }
-
- if let _key = key {
- self.takeValue(for: _key, from: inspector)
- self.sendAction(self._pri_action, to: self._pri_target)
- }
- }
-
- private func _existsActiveLineWell() {
- __lwFlags.existsActiveLineWell = 1
- }
- }
|