From 9aa83e6e30c6df3511d95853f33488328b9f66f6 Mon Sep 17 00:00:00 2001 From: LEO Yoon-Tsaw Date: Sun, 19 Feb 2023 23:56:17 -0500 Subject: [PATCH] Add new APIs, peek selection and change page Context:Peek --- src/rime/context.cc | 32 ++++++++++++++++++++++++-------- src/rime/context.h | 1 + src/rime_api.cc | 35 +++++++++++++++++++++++++++++++++++ src/rime_api.h | 6 ++++++ 4 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/rime/context.cc b/src/rime/context.cc index c3f62f294..dd8076c0e 100644 --- a/src/rime/context.cc +++ b/src/rime/context.cc @@ -110,17 +110,33 @@ void Context::Clear() { } bool Context::Select(size_t index) { - if (composition_.empty()) + bool result = Peek(index); + if (result) + select_notifier_(this); + return result; +} + +bool Context::Peek(size_t index) { + if (composition_.empty() || !composition_.back().menu) return false; Segment& seg(composition_.back()); - if (auto cand = seg.GetCandidateAt(index)) { - seg.selected_index = index; - seg.status = Segment::kSelected; - DLOG(INFO) << "Selected: '" << cand->text() << "', index = " << index; - select_notifier_(this); - return true; + size_t new_index = index; + if (index < 0) { + DLOG(INFO) << "selection index < 0, fallback to 0"; + new_index = 0; + } else { + size_t candidate_count = seg.menu->Prepare(index + 1); + if (index >= candidate_count) { + DLOG(INFO) << "selection index exceed candidate pool, fallback to last"; + new_index = candidate_count - 1; + } } - return false; + size_t previous_index = seg.selected_index; + seg.selected_index = new_index; + update_notifier_(this); + + DLOG(INFO) << "Selection changed from: " << previous_index << " to: " << new_index; + return true; } bool Context::DeleteCandidate( diff --git a/src/rime/context.h b/src/rime/context.h index d624f0203..8295637df 100644 --- a/src/rime/context.h +++ b/src/rime/context.h @@ -45,6 +45,7 @@ class Context { // return false if there is no candidate at index bool Select(size_t index); + bool Peek(size_t index); bool DeleteCandidate(size_t index); // return false if there's no candidate for current segment bool ConfirmCurrentSelection(); diff --git a/src/rime_api.cc b/src/rime_api.cc index 10c99f58f..3f64d499c 100644 --- a/src/rime_api.cc +++ b/src/rime_api.cc @@ -970,11 +970,43 @@ static bool do_with_candidate_on_current_page( return (ctx->*verb)(page_start + index); } +Bool RimeChangePage(RimeSessionId session_id, Bool previous) { + an session(Service::instance().GetSession(session_id)); + if (!session) + return False; + Context *ctx = session->context(); + if (!ctx || !ctx->HasMenu()) + return False; + Schema *schema = session->schema(); + if (!schema) + return False; + size_t page_size = (size_t)schema->page_size(); + const auto& seg(ctx->composition().back()); + size_t selected_index = seg.selected_index; + ctx->composition().back().tags.insert("paging"); + if (previous) { + size_t index = selected_index <= page_size ? 0 : selected_index - page_size; + DLOG(INFO) << "Current selection: " << selected_index << ", Previous page, Peek at " << index; + return ctx->Peek(index); + } else { + size_t index = selected_index + page_size; + DLOG(INFO) << "Current selection: " << selected_index << ", Next page, Peek at " << index; + return ctx->Peek(index); + } +} + +Bool RimePeekCandidate(RimeSessionId session_id, size_t index) { + return do_with_candidate(session_id, index, &Context::Peek); +} Bool RimeSelectCandidate(RimeSessionId session_id, size_t index) { return do_with_candidate(session_id, index, &Context::Select); } +Bool RimePeekCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { + return do_with_candidate_on_current_page(session_id, index, &Context::Peek); +} + Bool RimeSelectCandidateOnCurrentPage(RimeSessionId session_id, size_t index) { return do_with_candidate_on_current_page(session_id, index, &Context::Select); } @@ -1116,6 +1148,9 @@ RIME_API RimeApi* rime_get_api() { s_api.get_state_label = &RimeGetStateLabel; s_api.delete_candidate = &RimeDeleteCandidate; s_api.delete_candidate_on_current_page = &RimeDeleteCandidateOnCurrentPage; + s_api.peek_candidate = &RimePeekCandidate; + s_api.peek_candidate_on_current_page = &RimePeekCandidateOnCurrentPage; + s_api.change_page = &RimeChangePage; s_api.get_state_label_abbreviated = &RimeGetStateLabelAbbreviated; } return &s_api; diff --git a/src/rime_api.h b/src/rime_api.h index 671a1c160..ecdf44cba 100644 --- a/src/rime_api.h +++ b/src/rime_api.h @@ -524,6 +524,8 @@ typedef struct rime_api_t { //! select a candidate at the given index in candidate list. Bool (*select_candidate)(RimeSessionId session_id, size_t index); + //! peek a selection without commiting to it + Bool (*peek_candidate)(RimeSessionId session_id, size_t index); //! get the version of librime const char* (*get_version)(void); @@ -533,6 +535,10 @@ typedef struct rime_api_t { //! select a candidate from current page. Bool (*select_candidate_on_current_page)(RimeSessionId session_id, size_t index); + //! peek a selection without commiting to it + Bool (*peek_candidate_on_current_page)(RimeSessionId session_id, size_t index); + + Bool (*change_page)(RimeSessionId session_id, Bool previous); //! access candidate list. Bool (*candidate_list_begin)(RimeSessionId session_id, RimeCandidateListIterator* iterator);