#ifndef CODE_VARIABLE_BOX_CONTROLLER_H #define CODE_VARIABLE_BOX_CONTROLLER_H #include #include #include #include "script_node.h" #include "script_node_cell.h" #include "script_store.h" #include "variable_box_empty_controller.h" namespace Code { class VariableBoxController : public AlternateEmptyNestedMenuController { public: VariableBoxController(ScriptStore * scriptStore); /* Responder */ bool handleEvent(Ion::Events::Event event) override; void didEnterResponderChain(Responder * previousFirstResponder) override; /* TableViewDataSource */ KDCoordinate rowHeight(int j) override; int numberOfRows() const override; HighlightCell * reusableCell(int index, int type) override; int reusableCellCount(int type) override; int typeAtLocation(int i, int j) override; /* ListViewDataSource */ void willDisplayCellForIndex(HighlightCell * cell, int index) override; /* SelectableTableViewDelegate */ void tableViewDidChangeSelection(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override; //AlternateEmptyNestedMenuController ViewController * emptyViewController() override { return &m_variableBoxEmptyController; } /* VariableBoxController */ void setDisplaySubtitles(bool display) { m_displaySubtitles = display; } void loadFunctionsAndVariables(int scriptIndex, const char * textToAutocomplete, int textToAutocompleteLength); const char * autocompletionAlternativeAtIndex(int textToAutocompleteLength, int * textToInsertLength, bool * addParentheses, int index, int * indexToUpdate = nullptr); void loadVariablesImportedFromScripts(); void empty(); void insertAutocompletionResultAtIndex(int index); private: constexpr static size_t k_maxNumberOfDisplayedItems = (Ion::Display::Height - Metric::TitleBarHeight - Metric::PopUpTopMargin) / ScriptNodeCell::k_simpleItemHeight + 2; // +2 if the cells are cropped on top and at the bottom constexpr static size_t k_maxScriptNodesCount = 128; // Chosen without particular reasons (Number of variables in the variables box) constexpr static int k_totalBuiltinNodesCount = 107; constexpr static uint8_t k_scriptOriginsCount = 8; // Number of scripts loaded in the variable box constexpr static uint8_t k_subtitleCellType = NodeCellType; // We don't care as it is not selectable constexpr static uint8_t k_itemCellType = LeafCellType; // So that upper class NestedMenuController knows it's a leaf constexpr static KDCoordinate k_subtitleRowHeight = 23; enum class NodeOrigin : uint8_t { CurrentScript = 0, Builtins = 1, Importation = 2 }; /* Returns: * - a negative int if the node name is before name in alphabetical * order * - 0 if they are equal * - a positive int if it is after in alphabetical order. * strictlyStartsWith is set to True if the node name starts with name but * they are not equal.*/ static int NodeNameCompare(ScriptNode * node, const char * name, int nameLength, bool * strictlyStartsWith = nullptr); // Nodes and nodes count static size_t MaxNodesCountForOrigin(NodeOrigin origin) { return origin == NodeOrigin::Builtins ? k_totalBuiltinNodesCount : k_maxScriptNodesCount; } int nodesCountForOrigin(NodeOrigin origin) const; size_t * nodesCountPointerForOrigin(NodeOrigin origin); ScriptNode * nodesForOrigin(NodeOrigin origin); ScriptNode * scriptNodeAtIndex(int index); // Cell getters int typeAndOriginAtLocation(int i, NodeOrigin * resultOrigin = nullptr, int * cumulatedOriginsCount = nullptr) const; // NestedMenuController HighlightCell * leafCellAtIndex(int index) override { assert(false); return nullptr; } HighlightCell * nodeCellAtIndex(int index) override { assert(false); return nullptr; } bool selectLeaf(int rowIndex) override; void insertTextInCaller(const char * text, int textLength = -1); // Loading void loadBuiltinNodes(const char * textToAutocomplete, int textToAutocompleteLength); void loadImportedVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength); void loadCurrentVariablesInScript(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength); void loadGlobalAndImportedVariablesInScriptAsImported(Script script, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true); // Returns true if this was an import structure bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules = true); const char * importationSourceNameFromNode(mp_parse_node_t & node); bool importationSourceIsModule(const char * sourceName, const ToolboxMessageTree * * moduleChildren = nullptr, int * numberOfModuleChildren = nullptr); bool importationSourceIsScript(const char * sourceName, const char * * scriptFullName, Script * retreivedScript = nullptr); bool addImportStructFromScript(mp_parse_node_struct_t * pns, uint structKind, const char * scriptName, const char * textToAutocomplete, int textToAutocompleteLength); /* Add a node if it completes the text to autocomplete and if it is not * already contained in the variable box. The returned boolean means we * should escape the node scanning process (due to the lexicographical order * or full node table). */ bool addNodeIfMatches(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * nodeName, int nodeNameLength = -1, const char * nodeSourceName = nullptr, const char * description = nullptr); VariableBoxEmptyController m_variableBoxEmptyController; ScriptNode m_currentScriptNodes[k_maxScriptNodesCount]; ScriptNode m_builtinNodes[k_totalBuiltinNodesCount]; ScriptNode m_importedNodes[k_maxScriptNodesCount]; ScriptNodeCell m_itemCells[k_maxNumberOfDisplayedItems]; MessageTableCell m_subtitleCells[k_scriptOriginsCount]; ScriptStore * m_scriptStore; size_t m_currentScriptNodesCount; size_t m_builtinNodesCount; size_t m_importedNodesCount; int m_shortenResultCharCount; // This is used to send only the completing text when we are autocompleting bool m_displaySubtitles; }; } #endif