// // AppLayoutDirection.swift // App for Indeed // import Cocoa /// Layout direction for the in-app language (Arabic and Hebrew are RTL). enum AppLayoutDirection { static var isRightToLeft: Bool { currentAppLanguage().isRightToLeft } static var interface: NSUserInterfaceLayoutDirection { isRightToLeft ? .rightToLeft : .leftToRight } static var naturalTextAlignment: NSTextAlignment { isRightToLeft ? .right : .natural } static var naturalWritingDirection: NSWritingDirection { isRightToLeft ? .rightToLeft : .natural } static func naturalParagraphStyle( alignment: NSTextAlignment? = nil, lineBreakMode: NSLineBreakMode = .byWordWrapping ) -> NSParagraphStyle { let paragraph = NSMutableParagraphStyle() paragraph.alignment = alignment ?? naturalTextAlignment paragraph.baseWritingDirection = naturalWritingDirection paragraph.lineBreakMode = lineBreakMode return paragraph } static func apply(to view: NSView) { view.userInterfaceLayoutDirection = interface } static func applyRecursively(to root: NSView) { var stack: [NSView] = [root] while let view = stack.popLast() { view.userInterfaceLayoutDirection = interface stack.append(contentsOf: view.subviews) } } static func configureTextField(_ field: NSTextField) { field.alignment = naturalTextAlignment field.baseWritingDirection = naturalWritingDirection if let cell = field.cell as? NSTextFieldCell { cell.alignment = naturalTextAlignment cell.baseWritingDirection = naturalWritingDirection } } static func placeholderAttributes( font: NSFont, color: NSColor, lineBreakMode: NSLineBreakMode = .byTruncatingTail ) -> [NSAttributedString.Key: Any] { [ .foregroundColor: color, .font: font, .paragraphStyle: naturalParagraphStyle(alignment: naturalTextAlignment, lineBreakMode: lineBreakMode) ] } static func attributedString( _ text: String, font: NSFont, color: NSColor, lineBreakMode: NSLineBreakMode = .byWordWrapping ) -> NSAttributedString { NSAttributedString(string: text, attributes: [ .font: font, .foregroundColor: color, .paragraphStyle: naturalParagraphStyle(lineBreakMode: lineBreakMode) ]) } static func refreshTextFields(in root: NSView) { var stack: [NSView] = [root] while let view = stack.popLast() { if let field = view as? NSTextField { configureTextField(field) } stack.append(contentsOf: view.subviews) } } @MainActor static func applyToAllWindows() { for window in NSApp.windows { guard let content = window.contentView else { continue } applyRecursively(to: content) refreshTextFields(in: content) } } } extension AppLanguage { var isRightToLeft: Bool { switch self { case .arabic, .hebrew: return true default: return false } } }