| | |
| | | detailScrollView.borderType = .noBorder |
| | | detailScrollView.documentView = detailLabel |
| | | |
| | | closeButton.action = { [weak self] in self?.hideUsageTips() } |
| | | closeButton.action = { [weak self] in self?.requestHideUsageTips() } |
| | | previousButton.action = { [weak self] in self?.selectUsageTip(offset: -1) } |
| | | nextButton.action = { [weak self] in self?.selectUsageTip(offset: 1) } |
| | | |
| | |
| | | applyCoordinatorState() |
| | | } |
| | | |
| | | private func hideUsageTips() { |
| | | private func requestHideUsageTips() { |
| | | Diagnostics.log("usageTips.hud.close") |
| | | clearHoverState() |
| | | isHidden = true |
| | | coordinator?.onHideUsageTips() |
| | | } |
| | | |
| | |
| | | let closeHitOutset: CGFloat = 8 |
| | | if closeButton.frame.insetBy(dx: -closeHitOutset, dy: -closeHitOutset).contains(point) { |
| | | closeButton.performPressFeedback() |
| | | hideUsageTips() |
| | | requestHideUsageTips() |
| | | return true |
| | | } |
| | | let hitOutset: CGFloat = 6 |
| | |
| | | let columnWidth = floor((availableWidth - gap * CGFloat(columnCount - 1)) / CGFloat(columnCount)) |
| | | var columnHeights = Array(repeating: outerPadding, count: columnCount) |
| | | var items: [LayoutItem] = [] |
| | | let bottomPinnedGroups = groups.enumerated().filter { $0.element.containerID == AppContainerID.appleBuiltIn } |
| | | let bottomPinnedIndexes = Set(bottomPinnedGroups.map { $0.offset }) |
| | | |
| | | for (index, group) in groups.enumerated() { |
| | | if bottomPinnedIndexes.contains(index) { continue } |
| | | |
| | | let columnIndex = columnHeights.indices.min { columnHeights[$0] < columnHeights[$1] } ?? 0 |
| | | let x = outerPadding + CGFloat(columnIndex) * (columnWidth + gap) |
| | | let y = columnHeights[columnIndex] |
| | |
| | | columnHeights[columnIndex] = y + height + gap |
| | | } |
| | | |
| | | let tallest = columnHeights.max() ?? outerPadding |
| | | let contentHeight = (groups.isEmpty ? outerPadding * 2 : tallest - gap + outerPadding) |
| | | var contentBottom = columnHeights.max() ?? outerPadding |
| | | for (index, group) in bottomPinnedGroups { |
| | | let y = max(outerPadding, contentBottom) |
| | | let height = AppGridCollectionMetrics.cardHeight( |
| | | appCount: group.apps.count, |
| | | width: availableWidth, |
| | | iconSize: iconSize |
| | | ) |
| | | items.append( |
| | | LayoutItem( |
| | | index: index, |
| | | frame: NSRect(x: outerPadding, y: y, width: availableWidth, height: height) |
| | | ) |
| | | ) |
| | | contentBottom = y + height + gap |
| | | } |
| | | |
| | | let contentHeight = (items.isEmpty ? outerPadding * 2 : contentBottom - gap + outerPadding) |
| | | + max(0, bottomContentPadding) |
| | | return LayoutPlan( |
| | | items: items, |