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