Files
TelegramSwift/Telegram-Mac/StickerSetTableRowItem.swift
2024-03-20 17:27:58 +04:00

274 lines
12 KiB
Swift

//
// StickerSetTableRowItem.swift
// Telegram
//
// Created by keepcoder on 28/03/2017.
// Copyright © 2017 Telegram. All rights reserved.
//
import Cocoa
import TGUIKit
import TelegramCore
import Postbox
import SwiftSignalKit
enum ItemListStickerPackItemControl: Equatable {
case none
case installation(installed: Bool)
case remove
case empty
case selected
}
class StickerSetTableRowItem: GeneralRowItem {
fileprivate let context: AccountContext
fileprivate let info:StickerPackCollectionInfo
fileprivate let topItem:StickerPackItem?
fileprivate let unread: Bool
fileprivate let editing: ItemListStickerPackItemEditing
fileprivate let _stableId:AnyHashable
fileprivate let itemCount:Int32
fileprivate let control: ItemListStickerPackItemControl
fileprivate let nameLayout:TextViewLayout
fileprivate let countLayout:TextViewLayout
let addPack: () -> Void
let removePack: () -> Void
init(_ initialSize: NSSize, context:AccountContext, stableId:AnyHashable, info:StickerPackCollectionInfo, topItem:StickerPackItem?, itemCount:Int32, unread: Bool, editing: ItemListStickerPackItemEditing, enabled: Bool, control: ItemListStickerPackItemControl, viewType: GeneralViewType = .legacy, action:@escaping()->Void, addPack:@escaping()->Void = {}, removePack:@escaping() -> Void = {}) {
self.context = context
self._stableId = stableId
self.info = info
self.topItem = topItem
self.unread = unread
self.editing = editing
self.itemCount = itemCount
self.control = control
self.addPack = addPack
self.removePack = removePack
nameLayout = TextViewLayout(.initialize(string: info.title, color: theme.colors.text, font: .normal(.title)), maximumNumberOfLines: 1)
countLayout = TextViewLayout(.initialize(string: strings().stickersSetCount1Countable(Int(itemCount)), color: theme.colors.grayText, font: .normal(.text)), maximumNumberOfLines: 1)
super.init(initialSize, height: 50, stableId: stableId, type: .none, viewType: viewType, action: action, inset: NSEdgeInsets(left: 20, right: 20), enabled: enabled)
_ = makeSize(initialSize.width, oldWidth: 0)
}
override func makeSize(_ width: CGFloat, oldWidth: CGFloat) -> Bool {
let success = super.makeSize(width, oldWidth: oldWidth)
switch self.viewType {
case .legacy:
nameLayout.measure(width: width - 50 - inset.left - inset.right)
countLayout.measure(width: width - 50 - inset.left - inset.right)
case let .modern(_, insets):
nameLayout.measure(width: self.blockWidth - 80 - insets.left - insets.right)
countLayout.measure(width: self.blockWidth - 80 - insets.left - insets.right)
}
return success
}
override func viewClass() -> AnyClass {
return StickerSetTableRowView.self
}
}
class StickerSetTableRowView : TableRowView, ViewDisplayDelegate {
private let containerView = GeneralRowContainerView(frame: NSZeroRect)
private let contentView = StickerMediaContentView(frame: NSMakeRect(0, 0, 35, 35))
private let nameView:TextView = TextView()
private let countView:TextView = TextView()
private let installationControl:ImageView = ImageView()
private let removeControl = ImageButton()
private let loadedStickerPackDisposable = MetaDisposable()
required init(frame frameRect: NSRect) {
super.init(frame: frameRect)
containerView.addSubview(contentView)
containerView.addSubview(nameView)
containerView.addSubview(countView)
countView.userInteractionEnabled = false
nameView.userInteractionEnabled = false
containerView.addSubview(installationControl)
containerView.displayDelegate = self
containerView.set(handler: { control in
if let event = NSApp.currentEvent {
control.superview?.mouseDown(with: event)
}
}, for: .Down)
containerView.set(handler: { control in
if let event = NSApp.currentEvent {
control.superview?.mouseDragged(with: event)
}
}, for: .MouseDragging)
containerView.set(handler: { control in
if let event = NSApp.currentEvent {
control.superview?.mouseUp(with: event)
}
}, for: .Up)
containerView.set(handler: { [weak self] _ in
if let `self` = self, let item = self.item as? StickerSetTableRowItem, let event = NSApp.currentEvent {
let point = self.containerView.convert(event.locationInWindow, from: nil)
if NSPointInRect(point, self.installationControl.frame) {
switch item.control {
case .installation:
item.addPack()
case .none:
break
case .remove:
item.removePack()
case .empty:
item.action()
case .selected:
break
}
} else {
item.action()
}
}
}, for: .Click)
removeControl.set(handler: { [weak self] _ in
if let item = self?.item as? StickerSetTableRowItem {
item.removePack()
}
}, for: .SingleClick)
containerView.addSubview(removeControl)
self.addSubview(containerView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ layer: CALayer, in ctx: CGContext) {
super.draw(layer, in: ctx)
if let item = item as? StickerSetTableRowItem, layer == containerView.layer {
ctx.setFillColor(theme.colors.border.cgColor)
switch item.viewType {
case .legacy:
ctx.fill(NSMakeRect(item.inset.left + 50, frame.height - .borderSize, frame.width - item.inset.left - item.inset.right - 50, .borderSize))
case let .modern(position, insets):
switch position {
case .first, .inner:
ctx.fill(NSMakeRect(insets.left + 50, containerView.frame.height - .borderSize, containerView.frame.width - insets.left - insets.right - 50, .borderSize))
default:
break
}
}
}
}
override func layout() {
super.layout()
if let item = item as? StickerSetTableRowItem {
switch item.viewType {
case .legacy:
self.containerView.frame = self.bounds
self.containerView.setCorners([])
contentView.centerY(x: item.inset.left)
nameView.update(item.nameLayout, origin: NSMakePoint(item.inset.left + 50, 7))
countView.update(item.countLayout, origin: NSMakePoint(item.inset.left + 50, containerView.frame.height - item.countLayout.layoutSize.height - 7))
installationControl.centerY(x: containerView.frame.width - item.inset.left - installationControl.frame.width)
removeControl.centerY(x: containerView.frame.width - item.inset.left - removeControl.frame.width)
case let .modern(position, innerInsets):
self.containerView.frame = NSMakeRect(floorToScreenPixels(backingScaleFactor, (frame.width - item.blockWidth) / 2), item.inset.top, item.blockWidth, frame.height - item.inset.bottom - item.inset.top)
self.containerView.setCorners(position.corners)
nameView.update(item.nameLayout, origin: NSMakePoint(innerInsets.left + 50, 7))
countView.update(item.countLayout, origin: NSMakePoint(innerInsets.left + 50, containerView.frame.height - item.countLayout.layoutSize.height - 7))
installationControl.centerY(x: containerView.frame.width - innerInsets.right - installationControl.frame.width)
removeControl.centerY(x: containerView.frame.width - innerInsets.right - removeControl.frame.width)
contentView.centerY(x: innerInsets.left)
}
}
}
override var backdorColor: NSColor {
return theme.colors.background
}
override func updateColors() {
nameView.backgroundColor = backdorColor
countView.backgroundColor = backdorColor
containerView.background = backdorColor
if let item = item as? GeneralRowItem {
self.backgroundColor = item.viewType.rowBackground
}
}
override func set(item: TableRowItem, animated: Bool) {
super.set(item: item, animated: animated)
self.updateMouse(animated: animated)
self.contentView.userInteractionEnabled = false
if let item = item as? StickerSetTableRowItem {
removeControl.set(image: theme.icons.stickerPackDelete, for: .Normal)
_ = removeControl.sizeToFit()
var file: TelegramMediaFile?
if let thumbnail = item.info.thumbnail {
file = TelegramMediaFile(fileId: MediaId(namespace: 0, id: item.info.id.id), partialReference: nil, resource: thumbnail.resource, previewRepresentations: [thumbnail], videoThumbnails: [], immediateThumbnailData: nil, mimeType: thumbnail.typeHint == .video ? "video/webm" : "application/x-tgsticker", size: nil, attributes: [.FileName(fileName: "sticker.tgs"), .Sticker(displayText: "", packReference: .id(id: item.info.id.id, accessHash: item.info.accessHash), maskData: nil)])
} else if let item = item.topItem {
file = item.file
}
if let file = file {
self.contentView.update(with: file, size: NSMakeSize(35, 35), context: item.context, parent: nil, table: item.table, parameters: nil, animated: animated, positionFlags: nil, approximateSynchronousValue: false)
}
nameView.update(item.nameLayout)
countView.update(item.countLayout)
switch item.control {
case let .installation(installed: installed):
installationControl.image = installed ? theme.icons.stickersAddedFeatured : theme.icons.stickersAddFeatured
installationControl.sizeToFit()
case .remove:
installationControl.image = theme.icons.stickersRemove
installationControl.sizeToFit()
case .selected:
installationControl.image = theme.icons.generalSelect
installationControl.sizeToFit()
default:
break
}
switch item.control {
case .installation:
installationControl.isHidden = false//!containerView.mouseInside()
removeControl.isHidden = true
case .none:
installationControl.isHidden = true
removeControl.isHidden = false//!containerView.mouseInside()
case .remove:
removeControl.isHidden = true
installationControl.isHidden = false//!containerView.mouseInside()
case .empty:
removeControl.isHidden = true
installationControl.isHidden = true
case .selected:
removeControl.isHidden = true
installationControl.isHidden = false//!containerView.mouseInside()
}
}
needsLayout = true
}
deinit {
loadedStickerPackDisposable.dispose()
}
}