[apps/code] Display source and description in var box

This commit is contained in:
Léa Saviot
2020-04-06 17:49:08 +02:00
committed by Émilie Feral
parent 96d68d6b44
commit d5e1e620fd
5 changed files with 66 additions and 43 deletions

View File

@@ -8,25 +8,27 @@ namespace Code {
class ScriptNode {
public:
constexpr static uint16_t CurrentScriptIndex = -1;
enum class Type : bool {
Function,
Variable
};
ScriptNode(Type type = Type::Variable, const char * name = nullptr, int nameLength = 0, uint16_t scriptIndex = 0) :
ScriptNode(Type type = Type::Variable, const char * name = nullptr, int nameLength = -1, const char * nodeSourceName = nullptr, const char * description = nullptr) :
m_type(type),
m_name(name),
m_scriptIndex(-1),
m_nodeSourceName(nodeSourceName),
m_description(description),
m_nameLength(nameLength)
{}
Type type() const { return m_type; }
const char * name() const { return m_name; }
int nameLength() const { return m_nameLength; }
uint16_t scriptIndex() const { return m_scriptIndex; }
const char * nodeSourceName() const { return m_nodeSourceName; }
const char * description() const { return m_description; }
private:
Type m_type;
const char * m_name;
uint16_t m_scriptIndex; // TODO LEA smaller type ?
const char * m_nodeSourceName;
const char * m_description;
int m_nameLength; // TODO LEA smaller type ?
};

View File

@@ -7,22 +7,38 @@ namespace Code {
constexpr char ScriptNodeCell::k_parentheses[];
constexpr char ScriptNodeCell::k_parenthesesWithEmpty[];
// TODO LEA remove static inline KDCoordinate maxCoordinate(KDCoordinate x, KDCoordinate y) { return x > y ? x : y; }
void ScriptNodeCell::ScriptNodeView::drawRect(KDContext * ctx, KDRect rect) const {
const KDColor backgroundColor = isHighlighted()? Palette::Select : KDColorWhite;
/* If it exists, draw the description name. If it did not fit, we would have
* put nullptr at the node creation. */
const char * descriptionName = m_scriptNode->description();
bool drawDescription = descriptionName != nullptr;
KDCoordinate rectHeightPerLine = rect.height();
if (drawDescription) {
rectHeightPerLine = rect.height() / 2;
ctx->drawString(descriptionName, KDPoint(0, rectHeightPerLine + k_verticalMargin / 2), k_font, Palette::GreyDark, backgroundColor);
}
// Draw the node name
const char * nodeName = m_scriptNode->name();
const int nodeNameLength = m_scriptNode->nameLength();
const KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength);
const KDCoordinate nodeNameY = (rect.height() - nameSize.height()) / 2;
KDSize nameSize = k_font->stringSize(nodeName, nodeNameLength);
const KDCoordinate nodeNameY = rectHeightPerLine - k_verticalMargin / 2 - nameSize.height() ;
ctx->drawString(nodeName, KDPoint(0, nodeNameY), k_font, KDColorBlack, backgroundColor, nodeNameLength);
// If it is a function, draw the parentheses
if (m_scriptNode->type() == ScriptNode::Type::Function) {
ctx->drawString(ScriptNodeCell::k_parentheses, KDPoint(nameSize.width(), nodeNameY), k_font, KDColorBlack, backgroundColor);
}
if (m_scriptNode->scriptIndex() != ScriptNode::CurrentScriptIndex) {
ctx->drawString(m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName(), KDPoint(0, Metric::TableCellVerticalMargin + nameSize.height() + k_verticalMargin), k_font, Palette::GreyDark, backgroundColor);
/* If it exists, draw the source name. If it did not fit, we would have put
* nullptr at the node creation. */
const char * sourceName = m_scriptNode->nodeSourceName();
if (sourceName != nullptr) {
KDSize sourceNameSize = k_font->stringSize(sourceName);
ctx->drawString(sourceName, KDPoint(rect.width() - sourceNameSize.width(), nodeNameY), k_font, Palette::GreyDark, backgroundColor);
}
}
@@ -30,13 +46,25 @@ KDSize ScriptNodeCell::ScriptNodeView::minimalSizeForOptimalDisplay() const {
if (m_scriptNode->name() == nullptr) {
return KDSizeZero;
}
KDSize size1 = k_font->stringSize(m_scriptNode->name(), m_scriptNode->nameLength());
KDSize size2 = m_scriptNode->scriptIndex() == ScriptNode::CurrentScriptIndex ? KDSizeZero : k_font->stringSize(m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName());
KDSize size3 = KDSizeZero;
return KDSize(300 /*TODO LEA*/, 2*k_topBottomMargin + m_scriptNode->description() == nullptr ? k_font->glyphSize().height() : k_font->glyphSize().height() * 2 + k_verticalMargin);
#if 0
KDSize nameLineSize = k_font->stringSize(m_scriptNode->name(), m_scriptNode->nameLength());
if (m_scriptNode->type() == ScriptNode::Type::Function) {
size3 = k_font->stringSize(ScriptNodeCell::k_parentheses);
nameLineSize = KDSize(nameLineSize.width() + k_font->stringSize(k_parentheses).width(), nameLineSize.height());
}
return KDSize(size1.width() + size3.width() > size2.width() ? size1.width() + size3.width() : size2.width(), Metric::TableCellVerticalMargin + size1.width() + k_verticalMargin + size2.width());
const char * sourceName = m_scriptNode->nodeSourceName();
if (sourceName != nullptr) {
KDSize sourceNameSize = k_font->stringSize(sourceName, nodeNameLength);
nameLineSize = KDSize(nameLineSize.width() + sourceNameSize.width() + k_font->glyphSize().width(), nameLineSize.height());
}
const char * descriptionName = m_scriptNode->description();
if (descriptionName == nullptr) {
return nameLineSize;
}
const KDSize descriptionNameSize = k_font->stringSize(descriptionName);
return KDSize(maxCoordinate(nameLineSize.width(), descriptionNameSize.width()),2*Metric::TableCellVerticalMargin + nameLineSize.width() + k_verticalMargin + descriptionNameSize.height());
#endif
}
void ScriptNodeCell::setScriptNode(ScriptNode * scriptNode) {

View File

@@ -15,7 +15,6 @@ public:
m_scriptNodeView()
{}
void setScriptNode(ScriptNode * node);
void setScriptStore(ScriptStore * scriptStore) { m_scriptNodeView.setScriptStore(scriptStore); }
/* TableCell */
View * labelView() const override { return const_cast<View *>(static_cast<const View *>(&m_scriptNodeView)); }
@@ -34,21 +33,19 @@ protected:
public:
ScriptNodeView() :
HighlightCell(),
m_scriptNode(nullptr),
m_scriptStore(nullptr)
m_scriptNode(nullptr)
{}
void setScriptNode(ScriptNode * node) { m_scriptNode = node; }
void setScriptStore(ScriptStore * scriptStore) { m_scriptStore = scriptStore; }
void drawRect(KDContext * ctx, KDRect rect) const override;
virtual KDSize minimalSizeForOptimalDisplay() const override;
const char * text() const override {
return m_scriptStore->scriptAtIndex(m_scriptNode->scriptIndex()).fullName();
return m_scriptNode->description();
}
private:
constexpr static const KDFont * k_font = KDFont::SmallFont;
constexpr static KDCoordinate k_topBottomMargin = Metric::TableCellVerticalMargin;
constexpr static KDCoordinate k_verticalMargin = 7;
ScriptNode * m_scriptNode;
ScriptStore * m_scriptStore;
};
ScriptNodeView m_scriptNodeView;
};

View File

@@ -53,9 +53,6 @@ VariableBoxController::VariableBoxController(ScriptStore * scriptStore) :
m_builtinNodesCount(0),
m_importedNodesCount(0)
{
for (int i = 0; i < k_maxNumberOfDisplayedRows; i++) {
m_itemCells[i].setScriptStore(scriptStore);
}
for (int i = 0; i < k_scriptOriginsCount; i++) {
m_subtitleCells[i].setBackgroundColor(Palette::WallScreen);
m_subtitleCells[i].setTextColor(Palette::BlueishGrey);
@@ -447,7 +444,7 @@ void VariableBoxController::loadBuiltinNodes(const char * textToAutocomplete, in
};
assert(sizeof(builtinNames) / sizeof(builtinNames[0]) == k_totalBuiltinNodesCount);
for (int i = 0; i < k_totalBuiltinNodesCount; i++) {
ScriptNode node = ScriptNode(builtinNames[i].type, builtinNames[i].name, -1, 0);
ScriptNode node = ScriptNode(builtinNames[i].type, builtinNames[i].name);
int startsWith = textToAutocomplete == nullptr ? 0 : NodeNameStartsWith(&node, textToAutocomplete, textToAutocompleteLength);
if (startsWith == 0) {
m_builtinNodes[m_builtinNodesCount++] = node;
@@ -548,7 +545,7 @@ void VariableBoxController::loadCurrentVariablesInScript(const char * scriptCont
}
}
assert(strncmp(tokenInText, name, nameLength) == 0);
addNode(defToken ? ScriptNode::Type::Function : ScriptNode::Type::Variable, NodeOrigin::CurrentScript, tokenInText, nameLength, ScriptNode::CurrentScriptIndex);
addNode(defToken ? ScriptNode::Type::Function : ScriptNode::Type::Variable, NodeOrigin::CurrentScript, tokenInText, nameLength);
}
}
@@ -569,7 +566,7 @@ void VariableBoxController::loadCurrentVariablesInScript(const char * scriptCont
}
}
void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength) {
void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(const char * scriptName, const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
@@ -582,7 +579,7 @@ void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(con
uint structKind = (uint)MP_PARSE_NODE_STRUCT_KIND(pns);
if (structKind == PN_funcdef || structKind == PN_expr_stmt) {
// The script is only a single function or variable definition
addImportStruct(pns, structKind, textToAutocomplete, textToAutocompleteLength);
addImportStruct(pns, structKind, scriptName, textToAutocomplete, textToAutocompleteLength);
} else if (addNodesFromImportMaybe(pns, textToAutocomplete, textToAutocompleteLength)) {
// The script is is only an import, handled in addNodesFromImportMaybe
} else if (structKind == PN_file_input_2) {
@@ -597,7 +594,7 @@ void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(con
mp_parse_node_struct_t *child_pns = (mp_parse_node_struct_t*)(child);
structKind = (uint)MP_PARSE_NODE_STRUCT_KIND(child_pns);
if (structKind == PN_funcdef || structKind == PN_expr_stmt) {
addImportStruct(child_pns, structKind, textToAutocomplete, textToAutocompleteLength);
addImportStruct(child_pns, structKind, scriptName, textToAutocomplete, textToAutocompleteLength);
} else {
addNodesFromImportMaybe(child_pns, textToAutocomplete, textToAutocompleteLength);
}
@@ -634,7 +631,7 @@ bool VariableBoxController::addNodesFromImportMaybe(mp_parse_node_struct_t * par
if (MP_PARSE_NODE_IS_LEAF(child) && MP_PARSE_NODE_LEAF_KIND(child) == MP_PARSE_NODE_ID) {
// Parsing something like "import math"
const char * id = qstr_str(MP_PARSE_NODE_LEAF_ARG(child));
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, ScriptNode::Type::Variable, NodeOrigin::Importation, id, -1, 1/*TODO LEA*/);
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, ScriptNode::Type::Variable, NodeOrigin::Importation, id, -1, "math", "desc" /*TODO LEA*/);
} else if (MP_PARSE_NODE_IS_STRUCT(child)) {
// Parsing something like "from math import sin"
addNodesFromImportMaybe((mp_parse_node_struct_t *)child, textToAutocomplete, textToAutocompleteLength);
@@ -695,7 +692,7 @@ bool VariableBoxController::addNodesFromImportMaybe(mp_parse_node_struct_t * par
assert(numberOfChildren > numberOfNodesToSkip);
for (int i = 3; i < numberOfChildren; i++) {
const char * name = I18n::translate((moduleChildren + i)->label());
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, ScriptNode::Type::Variable, NodeOrigin::Importation, name, -1, 1/*TODO LEA*/);
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, ScriptNode::Type::Variable, NodeOrigin::Importation, name, -1, importationSourceName, I18n::translate((moduleChildren + i)->text()) /*TODO LEA text or label?*/);
}
} else {
// Try fetching the nodes from a script
@@ -703,7 +700,7 @@ bool VariableBoxController::addNodesFromImportMaybe(mp_parse_node_struct_t * par
if (!importedScript.isNull()) {
const char * scriptContent = importedScript.scriptContent();
assert(scriptContent != nullptr);
loadGlobalAndImportedVariablesInScriptAsImported(scriptContent, textToAutocomplete, textToAutocompleteLength);
loadGlobalAndImportedVariablesInScriptAsImported(importationSourceName, scriptContent, textToAutocomplete, textToAutocompleteLength);
}
}
}
@@ -726,23 +723,23 @@ const char * structName(mp_parse_node_struct_t * structNode) {
return nullptr;
}
void VariableBoxController::addImportStruct(mp_parse_node_struct_t * pns, uint structKind, const char * textToAutocomplete, int textToAutocompleteLength) {
void VariableBoxController::addImportStruct(mp_parse_node_struct_t * pns, uint structKind, const char * scriptName, const char * textToAutocomplete, int textToAutocompleteLength) {
assert(structKind == PN_funcdef || structKind == PN_expr_stmt);
// Find the id child node, which stores the struct's name
const char * name = structName(pns);
if (name == nullptr) {
return;
}
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, structKind == PN_funcdef ? ScriptNode::Type::Function : ScriptNode::Type::Variable, NodeOrigin::Importation, name, -1, 1/*TODO LEA*/);
checkAndAddNode(textToAutocomplete, textToAutocompleteLength, structKind == PN_funcdef ? ScriptNode::Type::Function : ScriptNode::Type::Variable, NodeOrigin::Importation, name, -1, scriptName);
}
void VariableBoxController::checkAndAddNode(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * nodeName, int nodeNameLength, int scriptIndex) {
void VariableBoxController::checkAndAddNode(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * nodeName, int nodeNameLength, const char * nodeSourceName, const char * description) {
if (nodeNameLength < 0) {
nodeNameLength = strlen(nodeName);
}
if (shouldAddNode(textToAutocomplete, textToAutocompleteLength, nodeName, nodeNameLength)) {
// Add the node in alphabetical order
addNode(type, origin, nodeName, nodeNameLength, scriptIndex);
addNode(type, origin, nodeName, nodeNameLength, nodeSourceName, description);
}
}
@@ -796,7 +793,7 @@ bool VariableBoxController::contains(const char * name, int nameLength) {
return alreadyInVarBox;
}
void VariableBoxController::addNode(ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, int scriptIndex) {
void VariableBoxController::addNode(ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, const char * nodeSourceName, const char * description) {
assert(origin == NodeOrigin::CurrentScript || origin == NodeOrigin::Importation);
int * currentNodeCount = nodesCountPointerForOrigin(origin);
if (*currentNodeCount >= MaxNodesCountForOrigin(origin)) {
@@ -822,7 +819,7 @@ void VariableBoxController::addNode(ScriptNode::Type type, NodeOrigin origin, co
nodes[i+1] = nodes[i];
}
// Add the node
nodes[insertionIndex] = ScriptNode(type, name, nameLength, scriptIndex);
nodes[insertionIndex] = ScriptNode(type, name, nameLength, nodeSourceName, description);
// Increase the node count
*currentNodeCount = *currentNodeCount + 1;
}

View File

@@ -85,17 +85,16 @@ private:
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(const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength);
void loadGlobalAndImportedVariablesInScriptAsImported(const char * scriptName, const char * scriptContent, const char * textToAutocomplete, int textToAutocompleteLength);
// Returns true if this was an import structure
bool addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength);
void addImportStruct(mp_parse_node_struct_t * pns, uint structKind, const char * textToAutocomplete, int textToAutocompleteLength);
void addImportStruct(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. */
void checkAndAddNode(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, int scriptIndex = 0);
void checkAndAddNode(const char * textToAutocomplete, int textToAutocompleteLength, ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, const char * nodeSourceName = nullptr, const char * description = nullptr);
bool shouldAddNode(const char * textToAutocomplete, int textToAutocompleteLength, const char * name, int nameLength);
bool contains(const char * name, int nameLength);
void addNode(ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, int scriptIndex = 0);
void addNode(ScriptNode::Type type, NodeOrigin origin, const char * name, int nameLength, const char * nodeSourceName = nullptr, const char * description = nullptr);
ScriptNode m_currentScriptNodes[k_maxScriptNodesCount];
ScriptNode m_builtinNodes[k_totalBuiltinNodesCount];
ScriptNode m_importedNodes[k_maxScriptNodesCount];