aboutsummaryrefslogtreecommitdiff
path: root/source/30-game/EditorCommandPalette.hpp
blob: 101344d8f61ab0bc389bcf4e931dc1c191210b34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#pragma once

#include <imgui.h>
#include <cstddef>
#include <functional>
#include <string>
#include <string_view>

class EditorCommandExecuteContext;
class EditorCommand {
public:
	std::string name;
	std::function<void(EditorCommandExecuteContext& ctx)> callback;
	std::function<void(EditorCommandExecuteContext& ctx, size_t selectedOptionId)> subsequentCallback;
	std::function<void()> terminate;
};

class EditorCommandExecuteContext {
	friend class EditorCommandPalette;

private:
	const EditorCommand* mCommand = nullptr;
	std::vector<std::string> mCurrentOptions;
	int mDepth = 0;

public:
	bool IsInitiated() const;
	const EditorCommand* GetCurrentCommand() const;
	void Initiate(const EditorCommand& command);

	void Prompt(std::vector<std::string> options);
	void Finish();

	/// Return the number of prompts that the user is currently completing. For example, when the user opens command
	/// palette fresh and selects a command, 0 is returned. If the command asks some prompt, and then the user selects
	/// again, 1 is returned.
	int GetExecutionDepth() const;
};

class EditorCommandPalette {
private:
	struct SearchResult;
	struct Item;

	std::vector<EditorCommand> mCommands;
	std::vector<Item> mItems;
	std::vector<SearchResult> mSearchResults;
	std::string mSearchText;
	EditorCommandExecuteContext mExeCtx;
	int mFocusedItemId = 0;
	bool mFocusSearchBox = false;
	bool mShouldCloseNextFrame = false;

public:
	EditorCommandPalette();
	~EditorCommandPalette();

	EditorCommandPalette(const EditorCommandPalette&) = delete;
	EditorCommandPalette& operator=(const EditorCommandPalette&) = delete;
	EditorCommandPalette(EditorCommandPalette&&) = default;
	EditorCommandPalette& operator=(EditorCommandPalette&&) = default;

	void AddCommand(std::string_view category, std::string_view name, EditorCommand command);
	void RemoveCommand(std::string_view category, std::string_view name);
	void RemoveCommand(const std::string& commandName);

	void Show(bool* open = nullptr);

	enum ItemType {
		CommandItem,
		CommandOptionItem,
	};

	enum IndexType {
		DirectIndex,
		SearchResultIndex,
	};

	struct ItemInfo {
		const char* text;
		const EditorCommand* command;
		int itemId;
		ItemType itemType;
		IndexType indexType;
	};

	size_t GetItemCount() const;
	ItemInfo GetItem(size_t idx) const;

	void SelectFocusedItem();

private:
	void InvalidateSearchResults();
};