Files
Mikhail Filimonov d7022cbd40 Merge branch 'beta' into dev
# Conflicts:
#	Telegram-Mac/Info.plist
#	TelegramShare/Info.plist
#	submodules/telegram-ios
2024-03-01 11:20:45 +04:00

292 lines
8.7 KiB
Swift

//
// ScrollView.swift
// TGUIKit
//
// Created by keepcoder on 07/09/16.
// Copyright © 2016 Telegram. All rights reserved.
//
import Cocoa
import Foundation
public enum ScrollDirection {
case top;
case bottom;
case none;
}
public func calculateScrollSpeed(scrollPositions: [CGFloat]) -> CGFloat? {
guard scrollPositions.count >= 2 else {
return nil // Not enough data to calculate speed
}
let firstPosition = scrollPositions.max()!
let lastPosition = scrollPositions.min()!
let distance = lastPosition - firstPosition
let timeElapsed = CGFloat(scrollPositions.count - 1)
let speed = distance / timeElapsed
return speed
}
public struct ScrollPosition : Equatable {
public private(set) var rect:NSRect
public private(set) var visibleRows: NSRange
public private(set) var direction:ScrollDirection
public init(_ rect:NSRect = NSZeroRect, _ direction:ScrollDirection = .none, _ visibleRows: NSRange = NSMakeRange(NSNotFound, 0)) {
self.rect = rect
self.visibleRows = visibleRows
self.direction = direction
}
}
public func ==(lhs:ScrollPosition, rhs:ScrollPosition) -> Bool {
return NSEqualRects(lhs.rect, rhs.rect) && lhs.direction == rhs.direction && NSEqualRanges(lhs.visibleRows, rhs.visibleRows)
}
final class Scroller : NSScroller {
weak var scrollView: NSScrollView?
override func draw(_ dirtyRect: NSRect) {
NSColor.clear.set()
dirtyRect.fill()
if let scrollView = self.scrollView {
if scrollView.contentView.documentRect.height > scrollView.frame.height {
self.drawKnob()
}
}
}
}
extension NSScroller {
}
final class OverlayScroller : NSScroller {
weak var scrollView: NSScrollView?
init() {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var scrollerStyle: NSScroller.Style {
get {
return .overlay
}
set {
super.scrollerStyle = .overlay
}
}
private var drawKnowIfNeeded = false
override func draw(_ dirtyRect: NSRect) {
drawKnowIfNeeded = true
super.draw(dirtyRect)
// if let tableView = self.scrollView as? TableView {
// if tableView.liveScrolling || tableView.clipView.isAnimateScrolling, drawKnowIfNeeded {
// drawKnob()
// }
// }
}
override func drawKnob() {
super.drawKnob()
drawKnowIfNeeded = false
}
}
open class ScrollView: NSScrollView{
private var currentpos:ScrollPosition = ScrollPosition()
public var deltaCorner:Int64 = 60
public var applyExternalScroll:((NSEvent)->Bool)? = nil
override public static var isCompatibleWithResponsiveScrolling: Bool {
return true
}
// open override var translatesAutoresizingMaskIntoConstraints: Bool {
// get {
// return false
// }
// set {
//
// }
// }
public func scrollPosition(_ visibleRange: NSRange = NSMakeRange(NSNotFound, 0)) -> (current: ScrollPosition, previous: ScrollPosition) {
let rect = NSMakeRect(contentView.bounds.minX, contentView.bounds.maxY,contentView.documentRect.width, contentView.documentRect.height)
var d:ScrollDirection = currentpos.direction
if(currentpos.rect.minY > rect.minY) {
d = .top
} else if(currentpos.rect.minY < rect.minY) {
d = .bottom
}
let n = ScrollPosition(rect, d, visibleRange)
let previous = currentpos
currentpos = n
return (n, previous)
}
public var currentScroll: ScrollPosition {
return currentpos
}
open override func isAccessibilityElement() -> Bool {
return false
}
func resetScroll(_ visibleRange: NSRange = NSMakeRange(NSNotFound, 0)) -> Void {
self.currentpos = ScrollPosition(NSMakeRect(contentView.bounds.minX, contentView.bounds.maxY,contentView.documentRect.width, contentView.documentRect.height), .none, visibleRange)
}
public var documentOffset:NSPoint {
return clipView.documentOffset
}
open override func knowsPageRange(_ range: NSRangePointer) -> Bool {
return super.knowsPageRange(range)
}
public var documentSize:NSSize {
return self.contentView.documentRect.size;
}
//
//
// open override func draw(_ dirtyRect: NSRect) {
//
// }
public var _mouseDownCanMoveWindow: Bool = false
public override var mouseDownCanMoveWindow: Bool {
return _mouseDownCanMoveWindow
}
public var clipView:TGClipView {
return self.contentView as! TGClipView
}
override public init(frame frameRect: NSRect) {
super.init(frame: frameRect)
// self.layer?.delegate = self
// self.canDrawSubviewsIntoLayer = true
// self.layer?.drawsAsynchronously = System.drawAsync
// self.contentView.wantsLayer = true
// self.contentView.layerContentsRedrawPolicy = .onSetNeedsDisplay
// self.contentView.layer?.drawsAsynchronously = System.drawAsync
// self.layerContentsRedrawPolicy = .never;
//self.layer?.isOpaque = true
let clipView = TGClipView(frame:self.contentView.frame)
self.contentView = clipView;
self.automaticallyAdjustsContentInsets = false
drawsBackground = false
layerContentsRedrawPolicy = .never
// self.hasHorizontalScroller = false
// self.horizontalScrollElasticity = .automatic
// self.verticalScroller?.scrollerStyle = .overlay
autoresizingMask = []
self.wantsLayer = true;
layer?.backgroundColor = presentation.colors.background.cgColor
// verticalScrollElasticity = .automatic
//allowsMagnification = true
//self.hasVerticalScroller = false
self.scrollerStyle = .overlay
if NSScroller.preferredScrollerStyle == .legacy {
let scroller = Scroller()
scroller.scrollView = self
self.verticalScroller = scroller
}
}
open override func draw(_ dirtyRect: NSRect) {
}
//
open override func scrollWheel(with event: NSEvent) {
guard let window = window as? Window else {
super.scrollWheel(with: event)
return
}
if let applyExternalScroll = self.applyExternalScroll {
if applyExternalScroll(event) {
return
}
}
if !window.inLiveSwiping {
super.scrollWheel(with: event)
}
//
}
// open override func setNeedsDisplay(_ invalidRect: NSRect) {
//
// }
//
open override var scrollerStyle: NSScroller.Style {
set {
super.scrollerStyle = .overlay
}
get {
return .overlay
}
}
//
// open override var hasVerticalScroller: Bool {
// get {
// return true
// }
// set {
// super.hasVerticalScroller = newValue
// }
// }
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
assertOnMainThread()
}
public func change(pos position: NSPoint, animated: Bool, _ save:Bool = true, removeOnCompletion: Bool = true, duration:Double = 0.2, timingFunction: CAMediaTimingFunctionName = CAMediaTimingFunctionName.easeOut, completion:((Bool)->Void)? = nil) -> Void {
super._change(pos: position, animated: animated, save, removeOnCompletion: removeOnCompletion, duration: duration, timingFunction: timingFunction, completion: completion)
}
public func change(size: NSSize, animated: Bool, _ save:Bool = true, removeOnCompletion: Bool = true, duration:Double = 0.2, timingFunction: CAMediaTimingFunctionName = CAMediaTimingFunctionName.easeOut, completion:((Bool)->Void)? = nil) {
super._change(size: size, animated: animated, save, removeOnCompletion: removeOnCompletion, duration: duration, timingFunction: timingFunction, completion: completion)
}
public func change(opacity to: CGFloat, animated: Bool = true, _ save:Bool = true, removeOnCompletion: Bool = true, duration:Double = 0.2, timingFunction: CAMediaTimingFunctionName = CAMediaTimingFunctionName.easeOut, completion:((Bool)->Void)? = nil) {
super._change(opacity: to, animated: animated, save, removeOnCompletion: removeOnCompletion, duration: duration, timingFunction: timingFunction, completion: completion)
}
}