Fcitx
candidatelist.h
1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_CANDIDATELIST_H_
8 #define _FCITX_CANDIDATELIST_H_
9 
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 #include <fcitx-utils/key.h>
15 #include <fcitx-utils/macros.h>
16 #include <fcitx/candidateaction.h>
17 #include <fcitx/fcitxcore_export.h>
18 #include <fcitx/text.h>
19 
20 namespace fcitx {
21 
22 class InputContext;
23 class PageableCandidateList;
24 class BulkCandidateList;
25 class ModifiableCandidateList;
26 class CursorMovableCandidateList;
27 class CursorModifiableCandidateList;
28 class BulkCursorCandidateList;
29 class ActionableCandidateList;
30 class TabbedCandidateList;
31 
32 class CandidateListPrivate;
33 
34 enum class CandidateLayoutHint { NotSet, Vertical, Horizontal };
35 
36 class CandidateWordPrivate;
37 
38 /// Base class of candidate word.
39 class FCITXCORE_EXPORT CandidateWord {
40 public:
41  CandidateWord(Text text = {});
42  virtual ~CandidateWord();
43  /**
44  * Called when candidate is selected by user.
45  *
46  * @param inputContext the associated input context for the candidate.
47  */
48  virtual void select(InputContext *inputContext) const = 0;
49 
50  const Text &text() const;
51  /**
52  * Whether the candidate is only a place holder.
53  *
54  * If candidate is a place holder, it will not be displayed by UI, but it
55  * will still take one place in the candidate list.
56  */
57  bool isPlaceHolder() const;
58  bool hasCustomLabel() const;
59  const Text &customLabel() const;
60  /**
61  * Return comment corresponding to the candidate.
62  *
63  * @return value of comment.
64  * @since 5.1.9
65  */
66  const Text &comment() const;
67  /**
68  * Return text with comment.
69  *
70  * @param separator separator between text and comment.
71  * @return value of comment.
72  * @since 5.1.9
73  */
74  Text textWithComment(std::string separator = " ") const;
75 
76  /**
77  * Whether there should be no space between text and comment.
78  *
79  * This is optional and may not be used if UI doesn't support it.
80  * By default the value is true.
81  *
82  * This doesn't change the behavior of textWithComment. The caller of
83  * textWithComment should check this function and decide whether to add
84  * space or not.
85  *
86  * @return true if there should be space, false otherwise.
87  * @since 5.1.20
88  */
89  bool spaceBetweenComment() const;
90 
91 protected:
92  void setText(Text text);
93  void setPlaceHolder(bool placeHolder);
94  void resetCustomLabel();
95  void setCustomLabel(Text text);
96  void setComment(Text comment);
97  void setSpaceBetweenComment(bool space);
98 
99 private:
100  std::unique_ptr<CandidateWordPrivate> d_ptr;
101  FCITX_DECLARE_PRIVATE(CandidateWord);
102 };
103 
104 // basic stuff
105 class FCITXCORE_EXPORT CandidateList {
106 public:
107  CandidateList();
108  virtual ~CandidateList();
109 
110  virtual const Text &label(int idx) const = 0;
111  virtual const CandidateWord &candidate(int idx) const = 0;
112  virtual int size() const = 0;
113  virtual int cursorIndex() const = 0;
114  virtual CandidateLayoutHint layoutHint() const = 0;
115 
116  bool empty() const;
117 
118  PageableCandidateList *toPageable() const;
119  BulkCandidateList *toBulk() const;
120  ModifiableCandidateList *toModifiable() const;
121  CursorMovableCandidateList *toCursorMovable() const;
122  CursorModifiableCandidateList *toCursorModifiable() const;
123  BulkCursorCandidateList *toBulkCursor() const;
124  ActionableCandidateList *toActionable() const;
125 
126  /**
127  * Cast to TabbedCandidateList if available.
128  *
129  * @return TabbedCandidateList pointer or nullptr.
130  * @since 5.1.20
131  */
132  TabbedCandidateList *toTabbed() const;
133 
134 protected:
135  void setPageable(PageableCandidateList *list);
136  void setBulk(BulkCandidateList *list);
137  void setModifiable(ModifiableCandidateList *list);
138  void setCursorMovable(CursorMovableCandidateList *list);
139  void setCursorModifiable(CursorModifiableCandidateList *list);
140  void setBulkCursor(BulkCursorCandidateList *list);
141  void setActionable(ActionableCandidateList *list);
142 
143  /**
144  * Set the TabbedCandidateList implementation.
145  *
146  * @param list pointer to TabbedCandidateList.
147  * @since 5.1.20
148  */
149  void setTabbed(TabbedCandidateList *list);
150 
151 private:
152  std::unique_ptr<CandidateListPrivate> d_ptr;
153  FCITX_DECLARE_PRIVATE(CandidateList);
154 };
155 
156 // useful for regular input method
157 class FCITXCORE_EXPORT PageableCandidateList {
158 public:
159  // Need for paging
160  virtual bool hasPrev() const = 0;
161  virtual bool hasNext() const = 0;
162  virtual void prev() = 0;
163  virtual void next() = 0;
164 
165  virtual bool usedNextBefore() const = 0;
166 
167  // Following are optional.
168  virtual int totalPages() const { return -1; }
169  virtual int currentPage() const { return -1; }
170  virtual void setPage(int /*unused*/) {}
171 };
172 
173 class FCITXCORE_EXPORT CursorMovableCandidateList {
174 public:
175  virtual void prevCandidate() = 0;
176  virtual void nextCandidate() = 0;
177 };
178 
179 class FCITXCORE_EXPORT CursorModifiableCandidateList {
180 public:
181  virtual void setCursorIndex(int index) = 0;
182 };
183 
184 // useful for virtual keyboard
185 class FCITXCORE_EXPORT BulkCandidateList {
186 public:
187  /**
188  * If idx is out of range, it may raise exception. Catching the exception is
189  * useful to iterate over all candidate list for candidate list has no total
190  * size.
191  */
192  virtual const CandidateWord &candidateFromAll(int idx) const = 0;
193  /**
194  * It's possible for this function to return -1 if the implement has no
195  * clear number how many candidates are available.
196  */
197  virtual int totalSize() const = 0;
198 };
199 
200 // useful for module other than input method
201 class FCITXCORE_EXPORT ModifiableCandidateList : public BulkCandidateList {
202 public:
203  // All index used there are global index
204  virtual void insert(int idx, std::unique_ptr<CandidateWord> word) = 0;
205  virtual void remove(int idx) = 0;
206  virtual void replace(int idx, std::unique_ptr<CandidateWord> word) = 0;
207  virtual void move(int from, int to) = 0;
208 
209  void append(std::unique_ptr<CandidateWord> word) {
210  insert(totalSize(), std::move(word));
211  }
212 
213  template <typename CandidateWordType, typename... Args>
214  void append(Args &&...args) {
215  append(
216  std::make_unique<CandidateWordType>(std::forward<Args>(args)...));
217  }
218 };
219 
220 class FCITXCORE_EXPORT DisplayOnlyCandidateWord : public CandidateWord {
221 public:
222  DisplayOnlyCandidateWord(Text text) : CandidateWord(std::move(text)) {}
223  DisplayOnlyCandidateWord(Text text, Text comment)
224  : CandidateWord(std::move(text)) {
225  setComment(std::move(comment));
226  }
227 
228  void select(InputContext * /*inputContext*/) const override {}
229 };
230 
231 class FCITXCORE_EXPORT BulkCursorCandidateList {
232 public:
233  virtual int globalCursorIndex() const = 0;
234  virtual void setGlobalCursorIndex(int index) = 0;
235 };
236 
237 /**
238  * Interface for trigger actions on candidates.
239  *
240  * @since 5.1.10
241  */
242 class FCITXCORE_EXPORT ActionableCandidateList {
243 public:
244  virtual ~ActionableCandidateList();
245 
246  /**
247  * Check whether this candidate has action.
248  *
249  * This function should be fast and guarantee that candidateActions return a
250  * not empty vector.
251  */
252  virtual bool hasAction(const CandidateWord &candidate) const = 0;
253 
254  /**
255  * Return a list of actions.
256  */
257  virtual std::vector<CandidateAction>
258  candidateActions(const CandidateWord &candidate) const = 0;
259 
260  /**
261  * Trigger the action based on the index returned from candidateActions.
262  */
263  virtual void triggerAction(const CandidateWord &candidate, int id) = 0;
264 };
265 
266 /**
267  * Interface for tab-related actions on candidate list.
268  *
269  * @since 5.1.20
270  */
271 class FCITXCORE_EXPORT TabbedCandidateList {
272 public:
273  virtual ~TabbedCandidateList();
274 
275  /**
276  * Return a list of tab actions.
277  *
278  * @return vector of CandidateAction.
279  * @since 5.1.20
280  */
281  virtual std::vector<CandidateAction> tabActions() const = 0;
282 
283  /**
284  * Trigger the tab action based on the index returned from tabActions.
285  *
286  * @param id action index.
287  * @since 5.1.20
288  */
289  virtual void triggerTabAction(int id) = 0;
290 };
291 
293 
294 class FCITXCORE_EXPORT DisplayOnlyCandidateList : public CandidateList {
295 public:
298 
299  void setContent(const std::vector<std::string> &content);
300  void setContent(std::vector<Text> content);
301  void setLayoutHint(CandidateLayoutHint hint);
302  void setCursorIndex(int index);
303 
304  // CandidateList
305  const fcitx::Text &label(int idx) const override;
306  const CandidateWord &candidate(int idx) const override;
307  int cursorIndex() const override;
308  int size() const override;
309  CandidateLayoutHint layoutHint() const override;
310 
311 private:
312  std::unique_ptr<DisplayOnlyCandidateListPrivate> d_ptr;
313  FCITX_DECLARE_PRIVATE(DisplayOnlyCandidateList);
314 };
315 
317 
318 enum class CursorPositionAfterPaging { SameAsLast, DonotChange, ResetToFirst };
319 
320 /**
321  * A common simple candidate list that serves most of the purpose.
322  */
323 class FCITXCORE_EXPORT CommonCandidateList : public CandidateList,
324  public PageableCandidateList,
327 public:
330 
331  void clear();
332 
333  /**
334  * Set the label of candidate list.
335  *
336  * The labels less than 10 will be automatically filled with to empty ones
337  * up to 10 to be more error prone.
338  *
339  * @param labels list of labels.
340  *
341  * @since 5.0.4
342  */
343  void setLabels(const std::vector<std::string> &labels = {});
344 
345  /**
346  * Set the label of candidate list by key.
347  *
348  * @param keyList list of selection key
349  */
350  void setSelectionKey(const KeyList &keyList);
351 
352  void setPageSize(int size);
353  int pageSize() const;
354  void setLayoutHint(CandidateLayoutHint hint);
355  void setGlobalCursorIndex(int index);
356  /**
357  * Return Global cursor index.
358  *
359  * -1 means it is not selected.
360  *
361  * @return cursor index.
362  * @since 5.0.4
363  */
364  int globalCursorIndex() const;
365 
366  /**
367  * Set cursor index on current page.
368  *
369  * @param index index on current page;
370  * @since 5.1.9
371  */
372  void setCursorIndex(int index);
373 
374  // CandidateList
375  const fcitx::Text &label(int idx) const override;
376  const CandidateWord &candidate(int idx) const override;
377  int cursorIndex() const override;
378  int size() const override;
379 
380  // PageableCandidateList
381  bool hasPrev() const override;
382  bool hasNext() const override;
383  void prev() override;
384  void next() override;
385 
386  bool usedNextBefore() const override;
387 
388  int totalPages() const override;
389  int currentPage() const override;
390  void setPage(int page) override;
391 
392  CandidateLayoutHint layoutHint() const override;
393 
394  // BulkCandidateList
395  const CandidateWord &candidateFromAll(int idx) const override;
396  int totalSize() const override;
397 
398  // ModifiableCandidateList
399  void insert(int idx, std::unique_ptr<CandidateWord> word) override;
400  void remove(int idx) override;
401  void replace(int idx, std::unique_ptr<CandidateWord> word) override;
402  void move(int from, int to) override;
403 
404  // CursorMovableCandidateList
405  void prevCandidate() override;
406  void nextCandidate() override;
407 
408  // A simple switch to change the behavior of prevCandidate and nextCandidate
409  void setCursorIncludeUnselected(bool);
410  void setCursorKeepInSamePage(bool);
411  void setCursorPositionAfterPaging(CursorPositionAfterPaging afterPaging);
412 
413  /**
414  * Set an optional implementation of actionable candidate list
415  *
416  * @since 5.1.10
417  */
418  void setActionableImpl(std::unique_ptr<ActionableCandidateList> actionable);
419 
420  /**
421  * Set an optional implementation of tabbed candidate list.
422  *
423  * @param tabbed pointer to TabbedCandidateList.
424  * @since 5.1.20
425  */
426  void setTabbedImpl(std::unique_ptr<TabbedCandidateList> tabbed);
427 
428 private:
429  void fixAfterUpdate();
430  void moveCursor(bool prev);
431 
432  std::unique_ptr<CommonCandidateListPrivate> d_ptr;
433  FCITX_DECLARE_PRIVATE(CommonCandidateList);
434 };
435 } // namespace fcitx
436 
437 #endif // _FCITX_CANDIDATELIST_H_
Formatted string commonly used in user interface.
Definition: action.cpp:17
A class represents a formatted string.
Definition: text.h:27
void select(InputContext *) const override
Called when candidate is selected by user.
Interface for tab-related actions on candidate list.
Interface for trigger actions on candidates.
Base class of candidate word.
Definition: candidatelist.h:39
A common simple candidate list that serves most of the purpose.
An input context represents a client of Fcitx.
Definition: inputcontext.h:50
Class to represent a key.