Skip to content

Commit

Permalink
Add basic interface for candidate action.
Browse files Browse the repository at this point in the history
  • Loading branch information
wengxt committed May 4, 2024
1 parent cd31d21 commit d8d0657
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/lib/fcitx-utils/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@
}

#define FCITX_DECLARE_READ_ONLY_PROPERTY(TYPE, GETTER) \
std::conditional_t<std::is_class<TYPE>::value, const TYPE &, TYPE> \
GETTER() const;
std::conditional_t<std::is_class_v<TYPE>, const TYPE &, TYPE> GETTER() \
const;

#define FCITX_DECLARE_PROPERTY(TYPE, GETTER, SETTER) \
FCITX_DECLARE_READ_ONLY_PROPERTY(TYPE, GETTER) \
void SETTER(TYPE);

#define FCITX_DEFINE_READ_ONLY_PROPERTY_PRIVATE(THIS, TYPE, GETTER) \
std::conditional_t<std::is_class<TYPE>::value, const TYPE &, TYPE> \
std::conditional_t<std::is_class_v<TYPE>, const TYPE &, TYPE> \
THIS::GETTER() const { \
FCITX_TYPED_D(const THIS##Private); \
return d->GETTER##_; \
Expand Down
2 changes: 2 additions & 0 deletions src/lib/fcitx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(FCITX_CORE_SOURCES
statusarea.cpp
inputpanel.cpp
candidatelist.cpp
candidateaction.cpp
icontheme.cpp
inputmethodengine.cpp
)
Expand All @@ -38,6 +39,7 @@ set(FCITX_CORE_HEADERS
inputcontextproperty.h
inputpanel.h
candidatelist.h
candidateaction.h
focusgroup.h
surroundingtext.h
addonloader.h
Expand Down
38 changes: 38 additions & 0 deletions src/lib/fcitx/candidateaction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* SPDX-FileCopyrightText: 2024-2024 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
*/
#include "candidateaction.h"
#include "fcitx-utils/macros.h"

namespace fcitx {

class CandidateActionPrivate {
public:
CandidateActionPrivate() = default;
FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE_WITHOUT_SPEC(
CandidateActionPrivate);

int id_ = 0;
std::string text_;
bool isSeparator_ = false;
std::string icon_;
bool isCheckable_ = false;
bool isChecked_ = false;
};

CandidateAction::CandidateAction()
: d_ptr(std::make_unique<CandidateActionPrivate>()) {}

FCITX_DEFINE_DPTR_COPY_AND_DEFAULT_DTOR_AND_MOVE(CandidateAction);

FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, int, id, setId);
FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, std::string, text, setText);
FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, bool, isSeparator, setSeparator);
FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, std::string, icon, setIcon);
FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, bool, isCheckable, setCheckable);
FCITX_DEFINE_PROPERTY_PRIVATE(CandidateAction, bool, isChecked, setChecked);

} // namespace fcitx
39 changes: 39 additions & 0 deletions src/lib/fcitx/candidateaction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: 2024-2024 CSSlayer <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
*/
#ifndef _FCITX_CANDIDATEACTION_H_
#define _FCITX_CANDIDATEACTION_H_

#include <memory>
#include <string>
#include <fcitx-utils/macros.h>
#include "fcitxcore_export.h"

namespace fcitx {

class CandidateActionPrivate;

class FCITXCORE_EXPORT CandidateAction {
public:
CandidateAction();
virtual ~CandidateAction();
FCITX_DECLARE_COPY_AND_MOVE(CandidateAction);

FCITX_DECLARE_PROPERTY(int, id, setId);
FCITX_DECLARE_PROPERTY(std::string, text, setText);
FCITX_DECLARE_PROPERTY(bool, isSeparator, setSeparator);
FCITX_DECLARE_PROPERTY(std::string, icon, setIcon);
FCITX_DECLARE_PROPERTY(bool, isCheckable, setCheckable);
FCITX_DECLARE_PROPERTY(bool, isChecked, setChecked);

private:
FCITX_DECLARE_PRIVATE(CandidateAction);
std::unique_ptr<CandidateActionPrivate> d_ptr;
};

} // namespace fcitx

#endif // _FCITX_CANDIDATEACTION_H_
22 changes: 22 additions & 0 deletions src/lib/fcitx/candidatelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class CursorModifiableAdaptorForCommonCandidateList

} // namespace

ActionableCandidateList::~ActionableCandidateList() = default;

class CandidateListPrivate {
public:
BulkCandidateList *bulk_ = nullptr;
Expand All @@ -85,6 +87,7 @@ class CandidateListPrivate {
CursorMovableCandidateList *cursorMovable_ = nullptr;
BulkCursorCandidateList *bulkCursor_ = nullptr;
CursorModifiableCandidateList *cursorModifiable_ = nullptr;
ActionableCandidateList *actionable_ = nullptr;
};

CandidateList::CandidateList()
Expand Down Expand Up @@ -124,6 +127,11 @@ BulkCursorCandidateList *CandidateList::toBulkCursor() const {
return d->bulkCursor_;
}

ActionableCandidateList *CandidateList::toActionable() const {
FCITX_D();
return d->actionable_;
}

void CandidateList::setBulk(BulkCandidateList *list) {
FCITX_D();
d->bulk_ = list;
Expand Down Expand Up @@ -154,6 +162,11 @@ void CandidateList::setBulkCursor(BulkCursorCandidateList *list) {
d->bulkCursor_ = list;
}

void CandidateList::setActionable(ActionableCandidateList *list) {
FCITX_D();
d->actionable_ = list;
}

class CandidateWordPrivate {
public:
CandidateWordPrivate(Text &&text) : text_(std::move(text)) {}
Expand Down Expand Up @@ -330,6 +343,7 @@ class CommonCandidateListPrivate {
bool cursorKeepInSamePage_ = false;
CursorPositionAfterPaging cursorPositionAfterPaging_ =
CursorPositionAfterPaging::DonotChange;
std::unique_ptr<ActionableCandidateList> actionable_;

int size() const {
auto start = currentPage_ * pageSize_;
Expand Down Expand Up @@ -711,4 +725,12 @@ void CommonCandidateList::fixAfterUpdate() {
}
}
}

void CommonCandidateList::setActionableImpl(
std::unique_ptr<ActionableCandidateList> actionable) {
FCITX_D();
d->actionable_ = std::move(actionable);
setActionable(d->actionable_.get());
}

} // namespace fcitx
42 changes: 42 additions & 0 deletions src/lib/fcitx/candidatelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
#define _FCITX_CANDIDATELIST_H_

#include <fcitx-utils/key.h>
#include <fcitx-utils/macros.h>
#include <fcitx/candidateaction.h>
#include <fcitx/text.h>
#include "fcitxcore_export.h"

namespace fcitx {

Expand All @@ -19,6 +22,7 @@ class ModifiableCandidateList;
class CursorMovableCandidateList;
class CursorModifiableCandidateList;
class BulkCursorCandidateList;
class ActionableCandidateList;

class CandidateListPrivate;

Expand Down Expand Up @@ -96,6 +100,7 @@ class FCITXCORE_EXPORT CandidateList {
CursorMovableCandidateList *toCursorMovable() const;
CursorModifiableCandidateList *toCursorModifiable() const;
BulkCursorCandidateList *toBulkCursor() const;
ActionableCandidateList *toActionable() const;

protected:
void setPageable(PageableCandidateList *list);
Expand All @@ -104,6 +109,7 @@ class FCITXCORE_EXPORT CandidateList {
void setCursorMovable(CursorMovableCandidateList *list);
void setCursorModifiable(CursorModifiableCandidateList *list);
void setBulkCursor(BulkCursorCandidateList *list);
void setActionable(ActionableCandidateList *list);

private:
std::unique_ptr<CandidateListPrivate> d_ptr;
Expand Down Expand Up @@ -187,6 +193,35 @@ class FCITXCORE_EXPORT BulkCursorCandidateList {
virtual void setGlobalCursorIndex(int index) = 0;
};

/**
* Interface for trigger actions on candidates.
*
* @since 5.1.10
*/
class FCITXCORE_EXPORT ActionableCandidateList {
public:
virtual ~ActionableCandidateList();

/**
* Check whether this candidate has action.
*
* This function should be fast and guarantee that candidateActions return a
* not empty vector.
*/
virtual bool hasAction(const CandidateWord &candidate) const = 0;

/**
* Return a list of actions.
*/
virtual std::vector<CandidateAction>
candidateActions(const CandidateWord &candidate) const = 0;

/**
* Trigger the action based on the index returned from candidateActions.
*/
virtual void triggerAction(const CandidateWord &candidate, int id) = 0;
};

class DisplayOnlyCandidateListPrivate;

class FCITXCORE_EXPORT DisplayOnlyCandidateList : public CandidateList {
Expand Down Expand Up @@ -308,6 +343,13 @@ class FCITXCORE_EXPORT CommonCandidateList : public CandidateList,
void setCursorKeepInSamePage(bool);
void setCursorPositionAfterPaging(CursorPositionAfterPaging afterPaging);

/**
* Set an optional implemenation of actionable candidate list
*
* @since 5.1.10
*/
void setActionableImpl(std::unique_ptr<ActionableCandidateList> actionable);

private:
void fixAfterUpdate();
void moveCursor(bool prev);
Expand Down
33 changes: 33 additions & 0 deletions test/testcandidatelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <stdexcept>
#include "fcitx-utils/log.h"
#include "fcitx/candidateaction.h"
#include "fcitx/candidatelist.h"

using namespace fcitx;
Expand Down Expand Up @@ -327,11 +328,43 @@ void test_cursor() {
FCITX_ASSERT(candidatelist.toBulkCursor()->globalCursorIndex(), 5);
}

void test_candidateaction() {
CandidateAction action;
action.setText("Test");
action.setId(1);
action.setCheckable(true);
action.setChecked(false);
action.setSeparator(false);
action.setIcon("Icon");

CandidateAction action2;
action2 = std::move(action);

FCITX_ASSERT(action2.text() == "Test");
FCITX_ASSERT(action2.id() == 1);
FCITX_ASSERT(action2.isCheckable());
FCITX_ASSERT(!action2.isChecked());
FCITX_ASSERT(!action2.isSeparator());
FCITX_ASSERT(action2.icon() == "Icon");

CandidateAction action3(action2);

for (const auto &action : {action2, action3}) {
FCITX_ASSERT(action.text() == "Test");
FCITX_ASSERT(action.id() == 1);
FCITX_ASSERT(action.isCheckable());
FCITX_ASSERT(!action.isChecked());
FCITX_ASSERT(!action.isSeparator());
FCITX_ASSERT(action.icon() == "Icon");
}
}

int main() {
test_basic();
test_faulty_placeholder();
test_label();
test_comment();
test_cursor();
test_candidateaction();
return 0;
}

0 comments on commit d8d0657

Please sign in to comment.