Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new toast UI and operation hint message #82

Merged
merged 2 commits into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions PlayTools/Controls/ControlMode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class ControlMode {
if !editor.editorMode {
if show {
if !visible {
NotificationCenter.default.post(name: NSNotification.Name.playtoolsKeymappingWillDisable,
object: nil, userInfo: [:])
if screen.fullscreen {
screen.switchDock(true)
}
Expand All @@ -26,6 +28,8 @@ public class ControlMode {
}
} else {
if visible {
NotificationCenter.default.post(name: NSNotification.Name.playtoolsKeymappingWillEnable,
object: nil, userInfo: [:])
if PlaySettings.shared.mouseMapping {
AKInterface.shared!.hideCursor()
}
Expand All @@ -40,3 +44,11 @@ public class ControlMode {
}
}
}

extension NSNotification.Name {
public static let playtoolsKeymappingWillEnable: NSNotification.Name
= NSNotification.Name("playtools.keymappingWillEnable")

public static let playtoolsKeymappingWillDisable: NSNotification.Name
= NSNotification.Name("playtools.keymappingWillDisable")
}
15 changes: 15 additions & 0 deletions PlayTools/Controls/PlayInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,21 @@ class PlayInput {
}

setupShortcuts()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 5) {
if !settings.mouseMapping || !mode.visible {
return
}
Toast.showHint(title: "Keymapping Disabled", text: ["Press ", "option ⌥", " to enable keymapping"],
notification: NSNotification.Name.playtoolsKeymappingWillEnable)
let center = NotificationCenter.default
var token: NSObjectProtocol?
token = center.addObserver(forName: NSNotification.Name.playtoolsKeymappingWillEnable,
object: nil, queue: OperationQueue.main) { _ in
center.removeObserver(token!)
Toast.showHint(title: "Keymapping Enabled", text: ["Press ", "option ⌥", " to disable keymapping"],
notification: NSNotification.Name.playtoolsKeymappingWillDisable)
}
}

// Fix beep sound
AKInterface.shared!
Expand Down
7 changes: 5 additions & 2 deletions PlayTools/Keymap/EditorController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@ class EditorController {
previousWindow?.makeKeyAndVisible()
PlayInput.shared.toggleEditor(show: false)
focusedControl = nil
Toast.showOver(msg: "Keymapping saved")
Toast.showHint(title: "Keymap Saved")
} else {
PlayInput.shared.toggleEditor(show: true)
previousWindow = screen.keyWindow
editorWindow = initWindow()
editorWindow?.makeKeyAndVisible()
showButtons()
Toast.showOver(msg: "Click to start keymmaping edit")
Toast.showHint(title: "Keymapping Editor",
text: ["Click a button to edit its position or key bind\n" +
"Click an empty area to open input menu"],
notification: NSNotification.Name.playtoolsKeymappingWillEnable)
}
// Toast.showOver(msg: "\(UIApplication.shared.windows.count)")
lock.unlock()
Expand Down
95 changes: 95 additions & 0 deletions PlayTools/Utils/Toast.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,101 @@ class Toast {
Toast.show(message: msg, parent: parent)
}
}
static var hintView: [UIView] = []

private static let gap: CGFloat = 40

public static func hideHint(hint: UIView) {
guard let id = hintView.firstIndex(of: hint) else {return}
for index in 0..<hintView.count {
if index < id {
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseOut, animations: {
hintView[index].layer.position.y -= hint.frame.size.height + gap
})
} else if index > id {
hintView[index-1] = hintView[index]
}
}
hintView.removeLast()
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseOut, animations: {
hint.alpha = 0.0
}, completion: {_ in
hint.removeFromSuperview()
})
}

private static func getAttributedString(title: String, text: [String]) -> NSMutableAttributedString {
var heading = title
if !text.isEmpty {
heading += "\n"
}
let txt = NSMutableAttributedString(string: text.reduce(into: heading, { result, string in
result += string
}))
var messageLength = 0
var highlight = false
for msg in text {
txt.addAttribute(.foregroundColor, value: highlight ? UIColor.cyan: UIColor.white,
range: NSRange(location: heading.count + messageLength, length: msg.count))
highlight = !highlight
messageLength += msg.count
}
let style = NSMutableParagraphStyle()
style.alignment = .center
txt.addAttribute(.paragraphStyle, value: style,
range: NSRange(location: 0, length: heading.count + messageLength))
txt.addAttribute(.font, value: UIFont.systemFont(ofSize: 28, weight: .bold),
range: NSRange(location: 0, length: heading.count))
txt.addAttribute(.foregroundColor, value: UIColor.white,
range: NSRange(location: 0, length: heading.count))
txt.addAttribute(.font, value: UIFont.systemFont(ofSize: 28),
range: NSRange(location: heading.count, length: messageLength))
return txt
}

public static func showHint(title: String, text: [String] = [], timeout: Double = 3,
notification: NSNotification.Name? = nil) {
let parent = screen.keyWindow!

// Width and height here serve as an upper limit.
// Text would fill width first, then wrap, then fill height, then scroll
let messageLabel = UITextView(frame: CGRect(x: 0, y: 0, width: 800, height: 800))
messageLabel.attributedText = getAttributedString(title: title, text: text)
messageLabel.backgroundColor = UIColor.black.withAlphaComponent(0.5)
messageLabel.alpha = 1.0
messageLabel.clipsToBounds = true
messageLabel.isUserInteractionEnabled = false
messageLabel.frame.size = messageLabel.sizeThatFits(messageLabel.frame.size)
messageLabel.layer.cornerCurve = CALayerCornerCurve.continuous
messageLabel.layer.cornerRadius = messageLabel.frame.size.height / 4
messageLabel.frame.size.width += messageLabel.layer.cornerRadius * 2
messageLabel.center.x = parent.center.x
messageLabel.center.y = -messageLabel.frame.size.height / 2

hintView.append(messageLabel)
parent.addSubview(messageLabel)

if hintView.count > 4 {
hideHint(hint: hintView.first!)
}
if let note = notification {
let center = NotificationCenter.default
var token: NSObjectProtocol?
token = center.addObserver(forName: note, object: nil, queue: OperationQueue.main) { _ in
center.removeObserver(token!)
hideHint(hint: messageLabel)
}
} else {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5 + timeout) {
hideHint(hint: messageLabel)
}
}
for view in hintView {
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: {
view.layer.position.y += messageLabel.frame.size.height + gap
})
}
}

// swiftlint:disable function_body_length

Expand Down