Skip to content

Commit

Permalink
add paging indicators (#953)
Browse files Browse the repository at this point in the history
  • Loading branch information
LEOYoon-Tsaw committed Jun 29, 2024
1 parent 75bef13 commit 08c410f
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/commit-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore
run: periphery scan --relative-results --skip-build --index-store-path build/Index.noindex/DataStore

- name: Upload Squirrel artifact
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore
run: periphery scan --relative-results --skip-build --index-store-path build/Index.noindex/DataStore

- name: Upload Squirrel artifact
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
run: brew install peripheryapp/periphery/periphery

- name: Check Unused Code
run: periphery scan --skip-build --index-store-path build/Index.noindex/DataStore
run: periphery scan --relative-results --skip-build --index-store-path build/Index.noindex/DataStore

- name: Build changelog
id: release_log
Expand Down
2 changes: 1 addition & 1 deletion action-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -e

rime_version=latest
rime_git_hash=6b1b41f
rime_git_hash=2f89098
sparkle_version=2.6.2

rime_archive="rime-${rime_git_hash}-macOS-universal.tar.bz2"
Expand Down
2 changes: 2 additions & 0 deletions data/squirrel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ style:
mutual_exclusive: false
# Whether to use a translucent background. Only visible when background color is transparent
translucency: false
# Enable to show small arrows that indicates if paging up/down is possible
show_paging: false

corner_radius: 7
hilited_corner_radius: 0
Expand Down
23 changes: 23 additions & 0 deletions sources/BridgingFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,26 @@ func ?=<T>(left: inout T?, right: T?) {
extension NSRange {
static let empty = NSRange(location: NSNotFound, length: 0)
}

extension NSPoint {
static func += (lhs: inout Self, rhs: Self) {
lhs.x += rhs.x
lhs.y += rhs.y
}
static func - (lhs: Self, rhs: Self) -> Self {
Self.init(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
static func -= (lhs: inout Self, rhs: Self) {
lhs.x -= rhs.x
lhs.y -= rhs.y
}
static func * (lhs: Self, rhs: CGFloat) -> Self {
Self.init(x: lhs.x * rhs, y: lhs.y * rhs)
}
static func / (lhs: Self, rhs: CGFloat) -> Self {
Self.init(x: lhs.x / rhs, y: lhs.y / rhs)
}
var length: CGFloat {
sqrt(pow(self.x, 2) + pow(self.y, 2))
}
}
10 changes: 7 additions & 3 deletions sources/SquirrelInputController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,13 @@ private extension SquirrelInputController {
}
}
// swiftlint:enable identifier_name
let page = Int(ctx.menu.page_no)
let lastPage = ctx.menu.is_last_page

let selRange = NSRange(location: start.utf16Offset(in: preedit), length: preedit.utf16.distance(from: start, to: end))
showPanel(preedit: inlinePreedit ? "" : preedit, selRange: selRange, caretPos: caretPos.utf16Offset(in: preedit),
candidates: candidates, comments: comments, labels: labels, highlighted: Int(ctx.menu.highlighted_candidate_index))
candidates: candidates, comments: comments, labels: labels, highlighted: Int(ctx.menu.highlighted_candidate_index),
page: page, lastPage: lastPage)
_ = rimeAPI.free_context(&ctx)
} else {
hidePalettes()
Expand Down Expand Up @@ -544,15 +547,16 @@ private extension SquirrelInputController {
}

// swiftlint:disable:next function_parameter_count
func showPanel(preedit: String, selRange: NSRange, caretPos: Int, candidates: [String], comments: [String], labels: [String], highlighted: Int) {
func showPanel(preedit: String, selRange: NSRange, caretPos: Int, candidates: [String], comments: [String], labels: [String], highlighted: Int, page: Int, lastPage: Bool) {
// print("[DEBUG] showPanelWithPreedit:...:")
guard let client = client else { return }
var inputPos = NSRect()
client.attributes(forCharacterIndex: 0, lineHeightRectangle: &inputPos)
if let panel = NSApp.squirrelAppDelegate.panel {
panel.position = inputPos
panel.inputController = self
panel.update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels, highlighted: highlighted, update: true)
panel.update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels,
highlighted: highlighted, page: page, lastPage: lastPage, update: true)
}
}
}
52 changes: 37 additions & 15 deletions sources/SquirrelPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ final class SquirrelPanel: NSPanel {
private var cursorIndex: Int = 0
private var scrollDirection: CGVector = .zero
private var scrollTime: Date = .distantPast
private var page: Int = 0
private var lastPage: Bool = true
private var pagingUp: Bool?

init(position: NSRect) {
self.position = position
Expand Down Expand Up @@ -68,33 +71,45 @@ final class SquirrelPanel: NSPanel {
override func sendEvent(_ event: NSEvent) {
switch event.type {
case .leftMouseDown:
let (index, _) = view.click(at: mousePosition())
if let index = index, index >= 0 && index < candidates.count {
let (index, _, pagingUp) = view.click(at: mousePosition())
if let pagingUp {
self.pagingUp = pagingUp
} else {
self.pagingUp = nil
}
if let index, index >= 0 && index < candidates.count {
self.index = index
}
case .leftMouseUp:
let (index, preeditIndex) = view.click(at: mousePosition())
if let preeditIndex = preeditIndex, preeditIndex >= 0 && preeditIndex < preedit.utf16.count {
let (index, preeditIndex, pagingUp) = view.click(at: mousePosition())

if let pagingUp, pagingUp == self.pagingUp {
_ = inputController?.page(up: pagingUp)
} else {
self.pagingUp = nil
}
if let preeditIndex, preeditIndex >= 0 && preeditIndex < preedit.utf16.count {
if preeditIndex < caretPos {
_ = inputController?.moveCaret(forward: true)
} else if preeditIndex > caretPos {
_ = inputController?.moveCaret(forward: false)
}
}
if let index = index, index == self.index && index >= 0 && index < candidates.count {
if let index, index == self.index && index >= 0 && index < candidates.count {
_ = inputController?.selectCandidate(index)
}
case .mouseEntered:
acceptsMouseMovedEvents = true
case .mouseExited:
acceptsMouseMovedEvents = false
if cursorIndex != index {
update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels, highlighted: index, update: false)
update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels, highlighted: index, page: page, lastPage: lastPage, update: false)
}
pagingUp = nil
case .mouseMoved:
let (index, _) = view.click(at: mousePosition())
let (index, _, _) = view.click(at: mousePosition())
if let index = index, cursorIndex != index && index >= 0 && index < candidates.count {
update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels, highlighted: index, update: false)
update(preedit: preedit, selRange: selRange, caretPos: caretPos, candidates: candidates, comments: comments, labels: labels, highlighted: index, page: page, lastPage: lastPage, update: false)
}
case .scrollWheel:
if event.phase == .began {
Expand All @@ -104,7 +119,7 @@ final class SquirrelPanel: NSPanel {
if abs(scrollDirection.dx) > abs(scrollDirection.dy) && abs(scrollDirection.dx) > 10 {
_ = inputController?.page(up: (scrollDirection.dx < 0) == vertical)
} else if abs(scrollDirection.dx) < abs(scrollDirection.dy) && abs(scrollDirection.dy) > 10 {
_ = inputController?.page(up: scrollDirection.dx > 0)
_ = inputController?.page(up: scrollDirection.dy > 0)
}
scrollDirection = .zero
// Mouse scroll wheel
Expand Down Expand Up @@ -141,7 +156,7 @@ final class SquirrelPanel: NSPanel {

// Main function to add attributes to text output from librime
// swiftlint:disable:next cyclomatic_complexity function_parameter_count
func update(preedit: String, selRange: NSRange, caretPos: Int, candidates: [String], comments: [String], labels: [String], highlighted index: Int, update: Bool) {
func update(preedit: String, selRange: NSRange, caretPos: Int, candidates: [String], comments: [String], labels: [String], highlighted index: Int, page: Int, lastPage: Bool, update: Bool) {
if update {
self.preedit = preedit
self.selRange = selRange
Expand All @@ -150,6 +165,8 @@ final class SquirrelPanel: NSPanel {
self.comments = comments
self.labels = labels
self.index = index
self.page = page
self.lastPage = lastPage
}
cursorIndex = index

Expand Down Expand Up @@ -266,7 +283,7 @@ final class SquirrelPanel: NSPanel {
// text done!
view.textView.textContentStorage?.attributedString = text
view.textView.setLayoutOrientation(vertical ? .vertical : .horizontal)
view.drawView(candidateRanges: candidateRanges, hilightedIndex: index, preeditRange: preeditRange, highlightedPreeditRange: highlightedPreeditRange)
view.drawView(candidateRanges: candidateRanges, hilightedIndex: index, preeditRange: preeditRange, highlightedPreeditRange: highlightedPreeditRange, canPageUp: page > 0, canPageDown: !lastPage)
show()
}

Expand Down Expand Up @@ -359,11 +376,12 @@ private extension SquirrelPanel {

if vertical {
panelRect.size = NSSize(width: min(0.95 * screenRect.width, contentRect.height + theme.edgeInset.height * 2),
height: min(0.95 * screenRect.height, contentRect.width + theme.edgeInset.width * 2))
height: min(0.95 * screenRect.height, contentRect.width + theme.edgeInset.width * 2) + theme.pagingOffset)

// To avoid jumping up and down while typing, use the lower screen when
// typing on upper, and vice versa
if position.midY / screenRect.height >= 0.5 {
panelRect.origin.y = position.minY - SquirrelTheme.offsetHeight - panelRect.height
panelRect.origin.y = position.minY - SquirrelTheme.offsetHeight - panelRect.height + theme.pagingOffset
} else {
panelRect.origin.y = position.maxY + SquirrelTheme.offsetHeight
}
Expand All @@ -376,7 +394,8 @@ private extension SquirrelPanel {
} else {
panelRect.size = NSSize(width: min(0.95 * screenRect.width, contentRect.width + theme.edgeInset.width * 2),
height: min(0.95 * screenRect.height, contentRect.height + theme.edgeInset.height * 2))
panelRect.origin = NSPoint(x: position.minX, y: position.minY - SquirrelTheme.offsetHeight - panelRect.height)
panelRect.size.width += theme.pagingOffset
panelRect.origin = NSPoint(x: position.minX - theme.pagingOffset, y: position.minY - SquirrelTheme.offsetHeight - panelRect.height)
}
if panelRect.maxX > screenRect.maxX {
panelRect.origin.x = screenRect.maxX - panelRect.width
Expand Down Expand Up @@ -412,10 +431,13 @@ private extension SquirrelPanel {

view.frame = contentView!.bounds
view.textView.frame = contentView!.bounds
view.textView.frame.size.width -= theme.pagingOffset
view.textView.frame.origin.x += theme.pagingOffset
view.textView.textContainerInset = theme.edgeInset

if theme.translucency {
back.frame = contentView!.bounds
back.frame.size.width += theme.pagingOffset
back.appearance = NSApp.effectiveAppearance
back.isHidden = false
} else {
Expand All @@ -434,7 +456,7 @@ private extension SquirrelPanel {
view.textContentStorage.attributedString = text
view.textView.setLayoutOrientation(vertical ? .vertical : .horizontal)
view.drawView(candidateRanges: [NSRange(location: 0, length: text.length)], hilightedIndex: -1,
preeditRange: .empty, highlightedPreeditRange: .empty)
preeditRange: .empty, highlightedPreeditRange: .empty, canPageUp: false, canPageDown: false)
show()

statusTimer?.invalidate()
Expand Down
10 changes: 10 additions & 0 deletions sources/SquirrelTheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ final class SquirrelTheme {
private(set) var vertical = false
private(set) var inlinePreedit = false
private(set) var inlineCandidate = false
private(set) var showPaging = false

private var fonts = [NSFont]()
private var labelFonts = [NSFont]()
Expand Down Expand Up @@ -182,6 +183,13 @@ final class SquirrelTheme {
_candidateFormat = newTemplate
}
}
var pagingOffset: CGFloat {
if showPaging {
(labelFontSize ?? fontSize ?? Self.defaultFontSize) * 1.5
} else {
0
}
}

func load(config: SquirrelConfig, dark: Bool) {
linear ?= config.getString("style/candidate_list_layout").map { $0 == "linear" }
Expand All @@ -191,6 +199,7 @@ final class SquirrelTheme {
translucency ?= config.getBool("style/translucency")
mutualExclusive ?= config.getBool("style/mutual_exclusive")
memorizeSize ?= config.getBool("style/memorize_size")
showPaging ?= config.getBool("style/show_paging")

statusMessageType ?= .init(rawValue: config.getString("style/status_message_type") ?? "")
candidateFormat ?= config.getString("style/candidate_format")
Expand Down Expand Up @@ -244,6 +253,7 @@ final class SquirrelTheme {
inlineCandidate ?= config.getBool("\(prefix)/inline_candidate")
translucency ?= config.getBool("\(prefix)/translucency")
mutualExclusive ?= config.getBool("\(prefix)/mutual_exclusive")
showPaging ?= config.getBool("\(prefix)/show_paging")
candidateFormat ?= config.getString("\(prefix)/candidate_format")
fontName ?= config.getString("\(prefix)/font_face")
fontSize ?= config.getDouble("\(prefix)/font_point")
Expand Down
Loading

0 comments on commit 08c410f

Please sign in to comment.