Skip to content

Commit c8cbf82

Browse files
committed
horizontal scrollable candidates
1 parent 2146469 commit c8cbf82

File tree

6 files changed

+147
-6
lines changed

6 files changed

+147
-6
lines changed

patches/hallelujah.patch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
diff --git a/CMakeLists.txt b/CMakeLists.txt
2-
index 02daeea..bcc8397 100644
2+
index 7ffcf34..a57a061 100644
33
--- a/CMakeLists.txt
44
+++ b/CMakeLists.txt
55
@@ -12,8 +12,6 @@ option(ENABLE_TEST "Build Test" On)
66
option(BUILD_DATA "Build data" On)
77

88
find_package(Gettext REQUIRED)
9-
-find_package(Fcitx5Core 5.0.0 REQUIRED)
9+
-find_package(Fcitx5Core 5.1.9 REQUIRED)
1010
-find_package(Fcitx5Module REQUIRED COMPONENTS Spell TestFrontend)
1111
find_package(PkgConfig REQUIRED)
1212

@@ -75,7 +75,7 @@ index dcbd627..6b0f00d 100644
7575
+ \"
7676
+)
7777
diff --git a/src/hallelujah.h b/src/hallelujah.h
78-
index 115ad79..c35bd7e 100644
78+
index ace78e7..2a371b8 100644
7979
--- a/src/hallelujah.h
8080
+++ b/src/hallelujah.h
8181
@@ -71,7 +71,6 @@ private:

uipanel/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ add_library(KeyboardUI STATIC
22
keyboardui.swift
33
Key.swift
44
Keyboard.swift
5+
Candidate.swift
6+
CandidateBar.swift
57
)
68
set_target_properties(KeyboardUI PROPERTIES Swift_MODULE_NAME KeyboardUI)
79
target_compile_options(KeyboardUI PUBLIC "$<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>")

uipanel/Candidate.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import UIKit
2+
3+
class CandidateView: UICollectionViewCell {
4+
static let identifier = "CandidateView"
5+
6+
let wordLabel: UILabel = {
7+
let label = UILabel()
8+
label.textAlignment = .center
9+
label.font = UIFont.systemFont(ofSize: 18)
10+
label.translatesAutoresizingMaskIntoConstraints = false
11+
return label
12+
}()
13+
14+
override init(frame: CGRect) {
15+
super.init(frame: frame)
16+
contentView.addSubview(wordLabel)
17+
setupConstraints()
18+
}
19+
20+
required init?(coder: NSCoder) {
21+
fatalError("init(coder:) has not been implemented")
22+
}
23+
24+
private func setupConstraints() {
25+
NSLayoutConstraint.activate([
26+
wordLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
27+
wordLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
28+
])
29+
}
30+
31+
func configure(with word: String) {
32+
wordLabel.text = word
33+
}
34+
}

uipanel/CandidateBar.swift

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import UIKit
2+
3+
class CandidateCollectionView: UIView {
4+
5+
var words = [String]()
6+
7+
private var collectionView: UICollectionView!
8+
9+
override init(frame: CGRect) {
10+
super.init(frame: frame)
11+
setupCollectionView()
12+
setupConstraints()
13+
}
14+
15+
required init?(coder: NSCoder) {
16+
fatalError("init(coder:) has not been implemented")
17+
}
18+
19+
private func setupCollectionView() {
20+
let layout = UICollectionViewFlowLayout()
21+
layout.scrollDirection = .horizontal
22+
23+
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
24+
collectionView.translatesAutoresizingMaskIntoConstraints = false
25+
collectionView.backgroundColor = UIColor.clear
26+
collectionView.delegate = self
27+
collectionView.dataSource = self
28+
collectionView.register(
29+
CandidateView.self, forCellWithReuseIdentifier: CandidateView.identifier)
30+
31+
addSubview(collectionView)
32+
}
33+
34+
private func setupConstraints() {
35+
NSLayoutConstraint.activate([
36+
collectionView.leadingAnchor.constraint(equalTo: leadingAnchor),
37+
collectionView.trailingAnchor.constraint(equalTo: trailingAnchor),
38+
collectionView.topAnchor.constraint(equalTo: topAnchor),
39+
collectionView.bottomAnchor.constraint(equalTo: bottomAnchor),
40+
collectionView.heightAnchor.constraint(equalToConstant: 35),
41+
])
42+
}
43+
44+
func updateCandidates(_ candidates: [String]) {
45+
words = candidates
46+
collectionView.reloadData()
47+
}
48+
}
49+
50+
extension CandidateCollectionView: UICollectionViewDataSource {
51+
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int)
52+
-> Int
53+
{
54+
return words.count
55+
}
56+
57+
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)
58+
-> UICollectionViewCell
59+
{
60+
guard
61+
let cell = collectionView.dequeueReusableCell(
62+
withReuseIdentifier: CandidateView.identifier, for: indexPath) as? CandidateView
63+
else {
64+
return UICollectionViewCell()
65+
}
66+
cell.configure(with: words[indexPath.item])
67+
return cell
68+
}
69+
}
70+
71+
extension CandidateCollectionView: UICollectionViewDelegate {
72+
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
73+
logger.error("Selected word: \(words[indexPath.item])")
74+
}
75+
}
76+
77+
extension CandidateCollectionView: UICollectionViewDelegateFlowLayout {
78+
func collectionView(
79+
_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
80+
sizeForItemAt indexPath: IndexPath
81+
) -> CGSize {
82+
let word = words[indexPath.item]
83+
let width = word.size(withAttributes: [.font: UIFont.systemFont(ofSize: 18)]).width + 20
84+
return CGSize(width: width, height: 35)
85+
}
86+
87+
func collectionView(
88+
_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
89+
minimumLineSpacingForSectionAt section: Int
90+
) -> CGFloat {
91+
return 10
92+
}
93+
}

uipanel/keyboardui.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import OSLog
33
import UIKit
44

55
let logger = Logger(subsystem: "org.fcitx.Fcitx5", category: "FcitxLog")
6+
let candidateCollectionView = CandidateCollectionView()
67

78
private func setupMainLayout(_ client: FcitxProtocol) {
89
let mainStackView = client.getView()
910

11+
candidateCollectionView.translatesAutoresizingMaskIntoConstraints = false
12+
mainStackView.addArrangedSubview(candidateCollectionView)
13+
1014
let keyboardView = Keyboard(client)
1115
keyboardView.translatesAutoresizingMaskIntoConstraints = false
1216
mainStackView.addArrangedSubview(keyboardView)
@@ -21,3 +25,9 @@ public func showKeyboardAsync(_ clientPtr: UnsafeMutableRawPointer) {
2125
setupMainLayout(client)
2226
}
2327
}
28+
29+
public func setCandidatesAsync(_ candidates: [String]) {
30+
DispatchQueue.main.async {
31+
candidateCollectionView.updateCandidates(candidates)
32+
}
33+
}

uipanel/uipanel.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,17 @@ void UIPanel::update(UserInterfaceComponent component,
2121
case UserInterfaceComponent::InputPanel: {
2222
const InputPanel &inputPanel = inputContext->inputPanel();
2323
int size = 0;
24+
auto candidates = swift::Array<swift::String>::init();
2425
if (const auto &list = inputPanel.candidateList()) {
2526
size = list->size();
2627
for (int i = 0; i < size; i++) {
2728
const auto &candidate = list->candidate(i);
28-
FCITX_INFO()
29-
<< instance_->outputFilter(inputContext, candidate.text())
30-
.toString();
29+
candidates.append(
30+
instance_->outputFilter(inputContext, candidate.text())
31+
.toString());
3132
}
3233
}
34+
KeyboardUI::setCandidatesAsync(candidates);
3335
break;
3436
}
3537
case UserInterfaceComponent::StatusArea:

0 commit comments

Comments
 (0)