@@ -367,93 +367,138 @@ private extension SquirrelPanel {
367367 self . appearance = NSAppearance ( named: . aqua)
368368 }
369369
370- // Break line if the text is too long, based on screen size.
370+ view. textView. textContainerInset = theme. edgeInset
371+
371372 let textWidth = maxTextWidth ( )
372- let maxTextHeight = vertical ? screenRect. width - theme. edgeInset. width * 2 : screenRect. height - theme. edgeInset. height * 2
373- view. textContainer. size = NSSize ( width: textWidth, height: maxTextHeight)
373+ // 高度設置爲無窮大,放開限制,讓超大文本完全測量出真實自然高度
374+ view. textContainer. size = NSSize ( width: textWidth, height: . greatestFiniteMagnitude)
375+
376+ // 強制完成排版,並歸零 bounds
377+ view. textLayoutManager. ensureLayout ( for: view. textLayoutManager. documentRange)
378+ view. textView. bounds. origin = . zero
374379
375- var panelRect = NSRect . zero
376- // in vertical mode, the width and height are interchanged
377380 var contentRect = view. contentRect
378- if theme. memorizeSize && ( vertical && position. midY / screenRect. height < 0.5 ) ||
379- ( vertical && position. minX + max( contentRect. width, maxHeight) + theme. edgeInset. width * 2 > screenRect. maxX) {
380- if contentRect. width >= maxHeight {
381- maxHeight = contentRect. width
382- } else {
383- contentRect. size. width = maxHeight
384- view. textContainer. size = NSSize ( width: maxHeight, height: maxTextHeight)
385- }
386- }
387381
382+ // 計算出「不加限制時」需要的自然面板巨型尺寸
383+ var naturalPanelSize = NSSize . zero
388384 if vertical {
389- panelRect. size = NSSize ( width: min ( 0.95 * screenRect. width, contentRect. height + theme. edgeInset. height * 2 ) ,
390- height: min ( 0.95 * screenRect. height, contentRect. width + theme. edgeInset. width * 2 ) + theme. pagingOffset)
391-
392- // To avoid jumping up and down while typing, use the lower screen when
393- // typing on upper, and vice versa
394- if position. midY / screenRect. height >= 0.5 {
395- panelRect. origin. y = position. minY - SquirrelTheme. offsetHeight - panelRect. height + theme. pagingOffset
396- } else {
397- panelRect. origin. y = position. maxY + SquirrelTheme. offsetHeight
398- }
399- // Make the first candidate fixed at the left of cursor
400- panelRect. origin. x = position. minX - panelRect. width - SquirrelTheme. offsetHeight
401- if view. preeditRange. length > 0 , let preeditTextRange = view. convert ( range: view. preeditRange) {
402- let preeditRect = view. contentRect ( range: preeditTextRange)
403- panelRect. origin. x += preeditRect. height + theme. edgeInset. width
404- }
385+ naturalPanelSize. width = contentRect. height + theme. edgeInset. height * 2
386+ naturalPanelSize. height = contentRect. width + theme. edgeInset. width * 2 + theme. pagingOffset
405387 } else {
406- panelRect. size = NSSize ( width: min ( 0.95 * screenRect. width, contentRect. width + theme. edgeInset. width * 2 ) ,
407- height: min ( 0.95 * screenRect. height, contentRect. height + theme. edgeInset. height * 2 ) )
408- panelRect. size. width += theme. pagingOffset
409- panelRect. origin = NSPoint ( x: position. minX - theme. pagingOffset, y: position. minY - SquirrelTheme. offsetHeight - panelRect. height)
388+ naturalPanelSize. width = contentRect. width + theme. edgeInset. width * 2 + theme. pagingOffset
389+ naturalPanelSize. height = contentRect. height + theme. edgeInset. height * 2
410390 }
411- if panelRect. maxX > screenRect. maxX {
412- panelRect. origin. x = screenRect. maxX - panelRect. width
413- }
414- if panelRect. minX < screenRect. minX {
415- panelRect. origin. x = screenRect. minX
416- }
417- if panelRect. minY < screenRect. minY {
391+
392+ // 屏幕最大可用範圍(留白 5%)
393+ let maxAllowedWidth = screenRect. width * 0.95
394+ let maxAllowedHeight = screenRect. height * 0.95
395+
396+ // 判斷是否需要觸發「全屏模式」
397+ let requiresFullScreen = naturalPanelSize. width > maxAllowedWidth || naturalPanelSize. height > maxAllowedHeight
398+
399+ var panelRect = NSRect . zero
400+
401+ if requiresFullScreen {
402+ // --- 全屏縮放模式 ---
403+ let scaleX = maxAllowedWidth / naturalPanelSize. width
404+ let scaleY = maxAllowedHeight / naturalPanelSize. height
405+ let scale = min ( scaleX, scaleY) // 保持等比縮小
406+
407+ // 窗口實際物理大小被縮小
408+ panelRect. size = NSSize ( width: naturalPanelSize. width * scale, height: naturalPanelSize. height * scale)
409+
410+ // 屏幕正中央對齊
411+ panelRect. origin = NSPoint (
412+ x: screenRect. minX + ( screenRect. width - panelRect. width) / 2 ,
413+ y: screenRect. minY + ( screenRect. height - panelRect. height) / 2
414+ )
415+
416+ maxHeight = 0 // 重置記憶尺寸緩存
417+ } else {
418+ // --- 常規跟隨光標模式 ---
419+ // Apply memorizeSize
420+ if theme. memorizeSize && ( vertical && position. midY / screenRect. height < 0.5 ) ||
421+ ( vertical && position. minX + max( contentRect. width, maxHeight) + theme. edgeInset. width * 2 > screenRect. maxX) {
422+ if contentRect. width >= maxHeight {
423+ maxHeight = contentRect. width
424+ } else {
425+ contentRect. size. width = maxHeight
426+ // 需要根據記憶寬度更新自然尺寸
427+ if vertical {
428+ naturalPanelSize. height = contentRect. width + theme. edgeInset. width * 2 + theme. pagingOffset
429+ } else {
430+ naturalPanelSize. width = contentRect. width + theme. edgeInset. width * 2 + theme. pagingOffset
431+ }
432+ }
433+ }
434+
435+ panelRect. size = naturalPanelSize
436+
418437 if vertical {
419- panelRect. origin. y = screenRect. minY
438+ // To avoid jumping up and down while typing
439+ if position. midY / screenRect. height >= 0.5 {
440+ panelRect. origin. y = position. minY - SquirrelTheme. offsetHeight - panelRect. height + theme. pagingOffset
441+ } else {
442+ panelRect. origin. y = position. maxY + SquirrelTheme. offsetHeight
443+ }
444+ panelRect. origin. x = position. minX - panelRect. width - SquirrelTheme. offsetHeight
445+ if view. preeditRange. length > 0 , let preeditTextRange = view. convert ( range: view. preeditRange) {
446+ let preeditRect = view. contentRect ( range: preeditTextRange)
447+ panelRect. origin. x += preeditRect. height + theme. edgeInset. width
448+ }
420449 } else {
421- panelRect. origin. y = position. maxY + SquirrelTheme. offsetHeight
450+ panelRect. origin = NSPoint ( x : position. minX - theme . pagingOffset , y : position . minY - SquirrelTheme. offsetHeight - panelRect . height )
422451 }
452+
453+ // 常規模式下的邊界限制
454+ if panelRect. maxX > screenRect. maxX { panelRect. origin. x = screenRect. maxX - panelRect. width }
455+ if panelRect. minX < screenRect. minX { panelRect. origin. x = screenRect. minX }
456+ if panelRect. minY < screenRect. minY {
457+ if vertical { panelRect. origin. y = screenRect. minY } else { panelRect. origin. y = position. maxY + SquirrelTheme. offsetHeight }
458+ }
459+ if panelRect. maxY > screenRect. maxY { panelRect. origin. y = screenRect. maxY - panelRect. height }
460+ if panelRect. minY < screenRect. minY { panelRect. origin. y = screenRect. minY }
423461 }
424- if panelRect. maxY > screenRect. maxY {
425- panelRect. origin. y = screenRect. maxY - panelRect. height
426- }
427- if panelRect. minY < screenRect. minY {
428- panelRect. origin. y = screenRect. minY
429- }
462+
430463 self . setFrame ( panelRect, display: true )
431464
465+ // contentView 的 frame 決定了它在窗口上的物理大小;
466+ // contentView 的 bounds 決定了它內部的投影座標系。
467+ // 將 bounds 設爲 naturalPanelSize(自然尺寸),視圖內部畫的一切東西就會自動被縮小到窗口(frame)裏
468+ contentView!. frame = NSRect ( origin: . zero, size: panelRect. size)
469+ contentView!. bounds = NSRect ( origin: . zero, size: naturalPanelSize)
470+
432471 // rotate the view, the core in vertical mode!
433472 if vertical {
434473 contentView!. boundsRotation = - 90
435- contentView!. setBoundsOrigin ( NSPoint ( x: 0 , y: panelRect . width) )
474+ contentView!. setBoundsOrigin ( NSPoint ( x: 0 , y: naturalPanelSize . width) )
436475 } else {
437476 contentView!. boundsRotation = 0
438477 contentView!. setBoundsOrigin ( . zero)
439478 }
479+
440480 view. textView. boundsRotation = 0
441481 view. textView. setBoundsOrigin ( . zero)
442482
443- view. frame = contentView!. bounds
444- view. textView. frame = contentView!. bounds
445- view. textView. frame. size. width -= theme. pagingOffset
446- view. textView. frame. origin. x += theme. pagingOffset
447- view. textView. textContainerInset = theme. edgeInset
483+ // 下層所有組件的幾何尺寸全部基於自然巨型尺寸 (naturalPanelSize)
484+ let subviewFrame = NSRect ( origin: . zero, size: naturalPanelSize)
485+ view. frame = subviewFrame
486+
487+ var textFrame = subviewFrame
488+ textFrame. size. width -= theme. pagingOffset
489+ textFrame. origin. x += theme. pagingOffset
490+ view. textView. frame = textFrame
448491
449492 if theme. translucency {
450- back. frame = contentView!. bounds
451- back. frame. size. width += theme. pagingOffset
493+ var backFrame = subviewFrame
494+ backFrame. size. width += theme. pagingOffset
495+ back. frame = backFrame
452496 back. appearance = NSApp . effectiveAppearance
453497 back. isHidden = false
454498 } else {
455499 back. isHidden = true
456500 }
501+
457502 alphaValue = theme. alpha
458503 invalidateShadow ( )
459504 orderFront ( nil )
0 commit comments