| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- //
- // CVResumeAppearance.swift
- // App for Indeed
- //
- // Shared résumé colours for gallery thumbnails and filled CV preview/export.
- // Résumés always use a print-style light palette regardless of app light/dark mode.
- //
- import AppKit
- @MainActor
- enum CVResumeAppearance {
- struct Colors {
- let paper: NSColor
- let ink: NSColor
- let muted: NSColor
- let rule: NSColor
- let cardBackground: NSColor
- let sidebarTint: NSColor
- let accentRed: NSColor
- let accentBlue: NSColor
- }
- /// Print-style palette — always light, even when the app chrome is in dark mode.
- static func colors() -> Colors {
- Colors(
- paper: NSColor.white,
- ink: NSColor(srgbRed: 38 / 255, green: 50 / 255, blue: 71 / 255, alpha: 1),
- muted: NSColor(srgbRed: 110 / 255, green: 118 / 255, blue: 132 / 255, alpha: 1),
- rule: NSColor(srgbRed: 228 / 255, green: 232 / 255, blue: 240 / 255, alpha: 1),
- cardBackground: NSColor.white,
- sidebarTint: NSColor(srgbRed: 244 / 255, green: 246 / 255, blue: 250 / 255, alpha: 1),
- accentRed: NSColor(srgbRed: 207 / 255, green: 67 / 255, blue: 50 / 255, alpha: 1),
- accentBlue: AppDashboardTheme.brandBlue
- )
- }
- /// Slight paper tint by layout variant (gallery + filled CV use the same rule).
- static func paperBackground(variant: Int, base: NSColor) -> NSColor {
- switch variant % 5 {
- case 0: return base
- case 1: return NSColor(srgbRed: 0.995, green: 0.992, blue: 0.985, alpha: 1)
- case 2: return NSColor(srgbRed: 0.96, green: 0.99, blue: 1, alpha: 1)
- case 3: return NSColor(srgbRed: 0.99, green: 0.99, blue: 0.99, alpha: 1)
- default: return NSColor(srgbRed: 0.99, green: 0.98, blue: 0.995, alpha: 1)
- }
- }
- static func accentColor(for template: CVTemplate) -> NSColor {
- let palette = colors()
- switch template.accent {
- case .redUnderline, .redBar:
- return palette.accentRed
- case .blueBar:
- return template.themeColor
- case .none:
- return template.themeColor.blended(withFraction: 0.5, of: palette.ink) ?? template.themeColor
- }
- }
- static func sectionHeadingColor(for template: CVTemplate) -> NSColor {
- accentColor(for: template)
- }
- // MARK: - Document layout (RTL for Arabic / Hebrew)
- static var isRightToLeft: Bool {
- AppLayoutDirection.isRightToLeft
- }
- static var documentInterfaceLayoutDirection: NSUserInterfaceLayoutDirection {
- isRightToLeft ? .rightToLeft : .leftToRight
- }
- static var documentTextAlignment: NSTextAlignment {
- isRightToLeft ? .right : .left
- }
- static var documentWritingDirection: NSWritingDirection {
- isRightToLeft ? .rightToLeft : .leftToRight
- }
- static func resolvedDocumentAlignment(_ alignment: NSTextAlignment) -> NSTextAlignment {
- alignment == .left ? documentTextAlignment : alignment
- }
- static func applyDocumentLayout(to view: NSView) {
- view.userInterfaceLayoutDirection = documentInterfaceLayoutDirection
- for child in view.subviews {
- applyDocumentLayout(to: child)
- }
- }
- static func documentParagraphStyle(
- alignment: NSTextAlignment,
- lineBreakMode: NSLineBreakMode = .byWordWrapping
- ) -> NSParagraphStyle {
- let paragraph = NSMutableParagraphStyle()
- paragraph.alignment = resolvedDocumentAlignment(alignment)
- paragraph.baseWritingDirection = documentWritingDirection
- paragraph.lineBreakMode = lineBreakMode
- return paragraph
- }
- static func applyDocumentTextLayout(to field: NSTextField, alignment: NSTextAlignment? = nil) {
- let sourceAlignment = alignment ?? field.alignment
- let resolved = resolvedDocumentAlignment(sourceAlignment)
- field.alignment = resolved
- field.baseWritingDirection = documentWritingDirection
- let lineBreak: NSLineBreakMode = field.maximumNumberOfLines == 0 ? .byWordWrapping : .byTruncatingTail
- field.attributedStringValue = NSAttributedString(string: field.stringValue, attributes: [
- .font: field.font ?? .systemFont(ofSize: 12),
- .foregroundColor: field.textColor ?? .labelColor,
- .paragraphStyle: documentParagraphStyle(alignment: resolved, lineBreakMode: lineBreak)
- ])
- }
- }
|