mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps] Code: use the FileSystem to store the scripts instead of an
accordion
This commit is contained in:
committed by
EmilieNumworks
parent
c37696133d
commit
19ca0f0640
@@ -3,7 +3,6 @@ snapshot_headers += apps/code/app.h
|
||||
|
||||
app_objs += $(addprefix apps/code/,\
|
||||
app.o\
|
||||
accordion.o\
|
||||
console_controller.o\
|
||||
console_edit_cell.o\
|
||||
console_line_cell.o\
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
#include "accordion.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
Accordion::Accordion(char * buffer, int bufferSize) :
|
||||
m_historySize(bufferSize),
|
||||
m_history(buffer),
|
||||
m_numberOfBuffers(0),
|
||||
m_startOfLastEditedBuffer(0)
|
||||
{
|
||||
for (int i = 0; i < m_historySize; i ++) {
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
const char * Accordion::bufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
return &m_history[startOfBuffer];
|
||||
}
|
||||
|
||||
char * Accordion::editableBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
return &m_history[startOfBuffer];
|
||||
}
|
||||
|
||||
int Accordion::sizeOfEditableBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int length = 0;
|
||||
for (int i = startOfBufferAtIndex(index); i < m_historySize-1; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker && m_history[i+1] != k_freeSpaceMarker) {
|
||||
break;
|
||||
}
|
||||
length++;
|
||||
// We do not count one Free Space Marker, in order to always have at a Free
|
||||
// Space of size at least one.
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
bool Accordion::appendBuffer(const char * buffer) {
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfHistory();
|
||||
int len = strlen(buffer);
|
||||
if (len + 1 > freeSpaceSize() - 1) { // We keep at keast one Free char.
|
||||
return false;
|
||||
}
|
||||
m_startOfLastEditedBuffer = startOfFreeSpace();
|
||||
memcpy(&m_history[m_startOfLastEditedBuffer], buffer, len+1);
|
||||
m_numberOfBuffers++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Accordion::replaceBufferAtIndex(int index, const char * buffer) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int len = strlen(buffer);
|
||||
if (len < sizeOfEditableBufferAtIndex(index)) {
|
||||
int startOfOldBuffer = startOfBufferAtIndex(index);
|
||||
memcpy(&m_history[startOfOldBuffer], buffer, len+1);
|
||||
m_startOfLastEditedBuffer = startOfOldBuffer;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Accordion::deleteBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(index);
|
||||
int i = startOfBufferAtIndex(index);
|
||||
while (i < m_historySize && m_history[i] != k_freeSpaceMarker) {
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
i++;
|
||||
}
|
||||
m_numberOfBuffers--;
|
||||
}
|
||||
|
||||
void Accordion::deleteLastBuffer() {
|
||||
cleanFreeSpace();
|
||||
if (m_numberOfBuffers > 0) {
|
||||
deleteBufferAtIndex(m_numberOfBuffers-1);
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::deleteAll() {
|
||||
cleanFreeSpace();
|
||||
for (int i = 0; i < m_historySize; i++){
|
||||
m_history[i] = k_freeSpaceMarker;
|
||||
}
|
||||
m_numberOfBuffers = 0;
|
||||
}
|
||||
|
||||
int Accordion::freeSpaceSize() {
|
||||
cleanFreeSpace();
|
||||
int sizeOfFreeSpace = 0;
|
||||
int freeSpaceStart = startOfFreeSpace();
|
||||
for (int i = freeSpaceStart; i < m_historySize; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker) {
|
||||
sizeOfFreeSpace++;
|
||||
} else {
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
}
|
||||
return sizeOfFreeSpace;
|
||||
}
|
||||
|
||||
int Accordion::startOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int bufferCount = 0;
|
||||
int startOfBuffer = 0;
|
||||
while (m_history[startOfBuffer] == k_freeSpaceMarker && startOfBuffer < m_historySize) {
|
||||
startOfBuffer++;
|
||||
}
|
||||
for (int i = startOfBuffer; i < m_historySize; i++) {
|
||||
if (bufferCount == index) {
|
||||
while (m_history[i] == k_freeSpaceMarker && i < m_historySize) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
if (m_history[i] == 0) {
|
||||
bufferCount++;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Accordion::endOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int startOfBuffer = startOfBufferAtIndex(index);
|
||||
for (int i = startOfBuffer; i < m_historySize; i++) {
|
||||
if (m_history[i] == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Accordion::startOfFreeSpace() {
|
||||
cleanFreeSpace();
|
||||
for (int i = 0; i < m_historySize; i++) {
|
||||
if (m_history[i] == k_freeSpaceMarker) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Accordion::cleanFreeSpace() {
|
||||
if (m_history[m_startOfLastEditedBuffer] == k_freeSpaceMarker) {
|
||||
return;
|
||||
}
|
||||
int indexOfCharToChangeIntoFreeSpaceMarker = m_startOfLastEditedBuffer
|
||||
+ strlen(&m_history[m_startOfLastEditedBuffer]) + 1;
|
||||
while (m_history[indexOfCharToChangeIntoFreeSpaceMarker] != k_freeSpaceMarker
|
||||
&& indexOfCharToChangeIntoFreeSpaceMarker < m_historySize)
|
||||
{
|
||||
m_history[indexOfCharToChangeIntoFreeSpaceMarker] = k_freeSpaceMarker;
|
||||
indexOfCharToChangeIntoFreeSpaceMarker++;
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtPosition(int i) {
|
||||
assert(i >= 0 && i <= m_historySize);
|
||||
cleanFreeSpace();
|
||||
int freeSpaceStart = startOfFreeSpace();
|
||||
int newFreeSpaceStart = freeSpaceStart;
|
||||
if (freeSpaceStart != i){
|
||||
|
||||
// First, move the chars that would be overriden by the free space.
|
||||
// The indexes depend on the relative positions of the free space and the
|
||||
// new destination.
|
||||
int sizeFreeSpace = freeSpaceSize();
|
||||
int len = 0;
|
||||
int src = 0;
|
||||
int dst = 0;
|
||||
if (freeSpaceStart > i) {
|
||||
len = freeSpaceStart - i;
|
||||
src = i;
|
||||
dst = i + sizeFreeSpace;
|
||||
newFreeSpaceStart = i;
|
||||
} else {
|
||||
src = freeSpaceStart + sizeFreeSpace;
|
||||
len = i - src;
|
||||
dst = freeSpaceStart;
|
||||
newFreeSpaceStart = i-sizeFreeSpace;
|
||||
}
|
||||
memmove(&m_history[dst], &m_history[src], len);
|
||||
|
||||
// Then move the free space.
|
||||
for (int j = newFreeSpaceStart ; j < newFreeSpaceStart+sizeFreeSpace; j++) {
|
||||
m_history[j] = k_freeSpaceMarker;
|
||||
}
|
||||
}
|
||||
|
||||
m_startOfLastEditedBuffer = newFreeSpaceStart-1;
|
||||
while (m_startOfLastEditedBuffer > 0 && m_history[m_startOfLastEditedBuffer-1] != 0 ) {
|
||||
m_startOfLastEditedBuffer--;
|
||||
}
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtEndOfBufferAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfBuffers());
|
||||
cleanFreeSpace();
|
||||
int endOfBuffer = endOfBufferAtIndex(index);
|
||||
moveFreeSpaceAtPosition(endOfBuffer+1);
|
||||
}
|
||||
|
||||
void Accordion::moveFreeSpaceAtEndOfHistory() {
|
||||
cleanFreeSpace();
|
||||
if (m_numberOfBuffers > 0) {
|
||||
moveFreeSpaceAtEndOfBufferAtIndex(m_numberOfBuffers-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef ESCHER_ACCORDION_H
|
||||
#define ESCHER_ACCORDION_H
|
||||
|
||||
/* Accordion sequentially stores null-terminated char buffers. It moves the free
|
||||
* space at the end of a buffer if it will be edited. */
|
||||
|
||||
class Accordion {
|
||||
public:
|
||||
Accordion(char * buffer, int bufferSize);
|
||||
int numberOfBuffers() { return m_numberOfBuffers; }
|
||||
const char * bufferAtIndex(int index);
|
||||
char * editableBufferAtIndex(int index);
|
||||
int sizeOfEditableBufferAtIndex(int index);
|
||||
/* sizeOfEditableBufferAtIndex appends the free space at the end of the buffer
|
||||
* and returns the length of the buffer plus the free space, minus one free
|
||||
* space char that we never edit in order to keep track of the position of the
|
||||
* last edited buffer. */
|
||||
bool appendBuffer(const char * buffer);
|
||||
bool replaceBufferAtIndex(int index, const char * buffer);
|
||||
void deleteBufferAtIndex(int index);
|
||||
void deleteLastBuffer();
|
||||
void deleteAll();
|
||||
int freeSpaceSize();
|
||||
private:
|
||||
static constexpr char k_freeSpaceMarker = 0x01;
|
||||
int startOfBufferAtIndex(int index);
|
||||
int endOfBufferAtIndex(int index);
|
||||
int startOfFreeSpace();
|
||||
void cleanFreeSpace();
|
||||
/* When a buffer is edited, there is garbage after the first null char of the
|
||||
* buffer. cleanFreeSpace() declares the space after this null char as free,
|
||||
* by marking it with the FreeSpaceMarker. Because we always keep at least one
|
||||
* Free Space char out of the editable zone, cleanFreeSpace() just needs to
|
||||
* put FreeSpaceMarkers after the first null char of the last edited Buffer,
|
||||
* until the first FreeSpaceMarker char.
|
||||
* WARNING: We have to call cleanFreeSpace() before any operation on m_history,
|
||||
* otherwise m_history might contain garbage chars. */
|
||||
void moveFreeSpaceAtPosition(int i);
|
||||
void moveFreeSpaceAtEndOfBufferAtIndex(int index);
|
||||
void moveFreeSpaceAtEndOfHistory();
|
||||
int m_historySize;
|
||||
char * m_history;
|
||||
/* The m_history variable sequentially stores null-terminated char buffers.
|
||||
* It also contains free space, which is marked with the FreeSpaceMarker. By
|
||||
* construction, there is always at least one free byte, and the free space is
|
||||
* always continuous. */
|
||||
int m_numberOfBuffers;
|
||||
int m_startOfLastEditedBuffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -77,7 +77,7 @@ bool ConsoleController::pythonEnvironmentIsLoaded() {
|
||||
|
||||
void ConsoleController::autoImport() {
|
||||
for (int i = 0; i < m_scriptStore->numberOfScripts(); i++) {
|
||||
autoImportScriptAtIndex(i);
|
||||
autoImportScript(m_scriptStore->scriptAtIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,13 +341,12 @@ void ConsoleController::printText(const char * text, size_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleController::autoImportScriptAtIndex(int index, bool force) {
|
||||
void ConsoleController::autoImportScript(Script script, bool force) {
|
||||
const char * importCommand1 = "from ";
|
||||
const char * importCommand2 = " import *";
|
||||
int lenImportCommand1 = strlen(importCommand1);
|
||||
int lenImportCommand2 = strlen(importCommand2);
|
||||
Script script = m_scriptStore->scriptAtIndex(index);
|
||||
if (script.autoImport() || force) {
|
||||
if (script.importationStatus() || force) {
|
||||
// Remove the name extension ".py" if there is one.
|
||||
int scriptOriginalNameLength = strlen(script.name());
|
||||
char scriptNewName[scriptOriginalNameLength];
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
bool pythonEnvironmentIsLoaded();
|
||||
|
||||
void autoImport();
|
||||
void autoImportScriptAtIndex(int index, bool force = false);
|
||||
void autoImportScript(Script script, bool force = false);
|
||||
void runAndPrintForCommand(const char * command);
|
||||
void removeExtensionIfAny(char * name);
|
||||
|
||||
|
||||
@@ -10,18 +10,38 @@ namespace Code {
|
||||
EditorController::EditorController(MenuController * menuController) :
|
||||
ViewController(nullptr),
|
||||
m_textArea(this),
|
||||
m_areaBuffer(nullptr),
|
||||
m_script(File()),
|
||||
m_menuController(menuController)
|
||||
{
|
||||
m_textArea.setDelegate(this);
|
||||
}
|
||||
|
||||
void EditorController::setScript(Script script){
|
||||
m_textArea.setText(script.editableContent(), script.contentBufferSize());
|
||||
EditorController::~EditorController() {
|
||||
delete m_areaBuffer;
|
||||
m_areaBuffer = nullptr;
|
||||
}
|
||||
|
||||
void EditorController::setScript(Script script) {
|
||||
m_script = script;
|
||||
const char * scriptBody = m_script.readContent();
|
||||
size_t scriptBodySize = strlen(scriptBody)+1;
|
||||
size_t availableScriptSize = scriptBodySize + FileSystem::sharedFileSystem()->availableSize();
|
||||
assert(m_areaBuffer == nullptr);
|
||||
m_areaBuffer = new char[availableScriptSize];
|
||||
strlcpy(m_areaBuffer, scriptBody, scriptBodySize);
|
||||
m_textArea.setText(m_areaBuffer, availableScriptSize);
|
||||
}
|
||||
|
||||
// TODO: this should be done in textAreaDidFinishEditing maybe??
|
||||
bool EditorController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::Back) {
|
||||
stackController()->pop();
|
||||
File::ErrorStatus err = m_script.writeContent(m_areaBuffer, strlen(m_areaBuffer)+1);
|
||||
if (err == File::ErrorStatus::NoEnoughSpaceAvailable) {
|
||||
assert(false); // This should not happen as we set the text area according to the available space in the File System
|
||||
} else {
|
||||
stackController()->pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -37,10 +57,8 @@ void EditorController::viewWillAppear() {
|
||||
|
||||
void EditorController::viewDidDisappear() {
|
||||
m_menuController->scriptContentEditionDidFinish();
|
||||
}
|
||||
|
||||
bool EditorController::textAreaShouldFinishEditing(TextArea * textArea, Ion::Events::Event event) {
|
||||
return false;
|
||||
delete[] m_areaBuffer;
|
||||
m_areaBuffer = nullptr;
|
||||
}
|
||||
|
||||
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
|
||||
@@ -114,7 +132,6 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ class ScriptParameterController;
|
||||
class EditorController : public ViewController, public TextAreaDelegate {
|
||||
public:
|
||||
EditorController(MenuController * menuController);
|
||||
~EditorController();
|
||||
void setScript(Script script);
|
||||
|
||||
/* ViewController */
|
||||
@@ -23,7 +24,6 @@ public:
|
||||
ViewController::DisplayParameter displayParameter() override { return ViewController::DisplayParameter::WantsMaximumSpace; }
|
||||
|
||||
/* TextAreaDelegate */
|
||||
bool textAreaShouldFinishEditing(TextArea * textArea, Ion::Events::Event event) override;
|
||||
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
|
||||
Toolbox * toolboxForTextInput(TextInput * textInput) override;
|
||||
|
||||
@@ -31,6 +31,8 @@ private:
|
||||
static constexpr int k_indentationSpacesNumber = 2;
|
||||
StackViewController * stackController();
|
||||
TextArea m_textArea;
|
||||
char * m_areaBuffer;
|
||||
Script m_script;
|
||||
MenuController * m_menuController;
|
||||
};
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ MenuController::MenuController(Responder * parentResponder, ScriptStore * script
|
||||
, lockOnConsole
|
||||
#endif
|
||||
),
|
||||
m_scriptParameterController(nullptr, I18n::Message::ScriptOptions, m_scriptStore, this),
|
||||
m_scriptParameterController(nullptr, I18n::Message::ScriptOptions, this),
|
||||
m_editorController(this),
|
||||
m_reloadConsoleWhenBecomingFirstResponder(false),
|
||||
m_shouldDisplayAddScriptRow(true)
|
||||
@@ -39,6 +39,7 @@ MenuController::MenuController(Responder * parentResponder, ScriptStore * script
|
||||
m_scriptCells[i].setParentResponder(&m_selectableTableView);
|
||||
m_scriptCells[i].editableTextCell()->textField()->setDelegate(this);
|
||||
m_scriptCells[i].editableTextCell()->textField()->setDraftTextBuffer(m_draftTextBuffer);
|
||||
m_scriptCells[i].editableTextCell()->textField()->setTextBufferSize(Script::k_nameSize);
|
||||
m_scriptCells[i].editableTextCell()->textField()->setAlignment(0.0f, 0.5f);
|
||||
m_scriptCells[i].editableTextCell()->setMargins(0, 0, 0, Metric::HistoryHorizontalMargin);
|
||||
}
|
||||
@@ -122,12 +123,11 @@ void MenuController::renameSelectedScript() {
|
||||
myCell->editableTextCell()->textField()->setEditing(true);
|
||||
myCell->editableTextCell()->textField()->setText(previousText);
|
||||
myCell->editableTextCell()->textField()->setCursorLocation(strlen(previousText) - strlen(ScriptStore::k_scriptExtension));
|
||||
}
|
||||
}
|
||||
|
||||
void MenuController::deleteScriptAtIndex(int i) {
|
||||
assert(i >= 0);
|
||||
assert(i < m_scriptStore->numberOfScripts());
|
||||
m_scriptStore->deleteScriptAtIndex(i);
|
||||
void MenuController::deleteScript(Script script) {
|
||||
assert(!script.isNull());
|
||||
script.remove();
|
||||
updateAddScriptRowDisplay();
|
||||
m_selectableTableView.reloadData();
|
||||
}
|
||||
@@ -141,11 +141,11 @@ void MenuController::loadPythonIfNeeded() {
|
||||
m_consoleController.loadPythonEnvironment(false);
|
||||
}
|
||||
|
||||
void MenuController::openConsoleWithScriptAtIndex(int scriptIndex) {
|
||||
void MenuController::openConsoleWithScript(Script script) {
|
||||
reloadConsole();
|
||||
if (m_consoleController.loadPythonEnvironment(false)) {
|
||||
stackViewController()->push(&m_consoleController);
|
||||
m_consoleController.autoImportScriptAtIndex(scriptIndex, true);
|
||||
m_consoleController.autoImportScript(script, true);
|
||||
}
|
||||
m_reloadConsoleWhenBecomingFirstResponder = true;
|
||||
}
|
||||
@@ -302,7 +302,8 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char
|
||||
} else {
|
||||
newName = text;
|
||||
}
|
||||
if (m_scriptStore->renameScriptAtIndex(m_selectableTableView.selectedRow(), newName)) {
|
||||
File::ErrorStatus error = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()).rename(newName);
|
||||
if (error == File::ErrorStatus::None) {
|
||||
updateAddScriptRowDisplay();
|
||||
textField->setText(newName);
|
||||
int currentRow = m_selectableTableView.selectedRow();
|
||||
@@ -316,9 +317,19 @@ bool MenuController::textFieldDidFinishEditing(TextField * textField, const char
|
||||
app()->setFirstResponder(&m_selectableTableView);
|
||||
static_cast<AppsContainer *>(const_cast<Container *>(app()->container()))->setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
|
||||
return true;
|
||||
} else {
|
||||
assert(error == File::ErrorStatus::NameTaken);
|
||||
// The name cannot be to long as the text field size was set accordingly
|
||||
|
||||
// TODO:
|
||||
// 2 solutions:
|
||||
// 1. display a warning with
|
||||
// app()->displayWarning(I18n::Message::ForbiddenValue);
|
||||
// But that have to be done in textFieldDidReceiveEvent when textFieldShouldFinishEditing to avoid losing edition
|
||||
// 2. Modify the name to take another one (add a number for instance).
|
||||
// This would raise issues about the available space? We can't always add a character...
|
||||
return false;
|
||||
}
|
||||
// TODO: add pop up to explain to the user that the name is too long.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MenuController::textFieldDidAbortEditing(TextField * textField, const char * text) {
|
||||
@@ -326,7 +337,8 @@ bool MenuController::textFieldDidAbortEditing(TextField * textField, const char
|
||||
// The previous text was an empty name. Use a numbered default script name.
|
||||
char numberedDefaultName[k_defaultScriptNameMaxSize];
|
||||
numberedDefaultScriptName(numberedDefaultName);
|
||||
m_scriptStore->renameScriptAtIndex(m_selectableTableView.selectedRow(), const_cast<const char *>(numberedDefaultName));
|
||||
File::ErrorStatus error = m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()).rename(numberedDefaultName);
|
||||
assert(error == File::ErrorStatus::None);
|
||||
updateAddScriptRowDisplay();
|
||||
m_selectableTableView.reloadData();
|
||||
}
|
||||
@@ -357,13 +369,13 @@ void MenuController::addScript() {
|
||||
void MenuController::configureScript() {
|
||||
assert(m_selectableTableView.selectedRow() >= 0);
|
||||
assert(m_selectableTableView.selectedRow() < m_scriptStore->numberOfScripts());
|
||||
m_scriptParameterController.setScript(m_selectableTableView.selectedRow());
|
||||
m_scriptParameterController.setScript(m_scriptStore->scriptAtIndex(m_selectableTableView.selectedRow()));
|
||||
stackViewController()->push(&m_scriptParameterController);
|
||||
}
|
||||
|
||||
void MenuController::editScriptAtIndex(int scriptIndex) {
|
||||
assert(scriptIndex >=0 && scriptIndex < m_scriptStore->numberOfScripts());
|
||||
Script script = m_scriptStore->scriptAtIndex(scriptIndex, ScriptStore::EditableZone::Content);
|
||||
Script script = m_scriptStore->scriptAtIndex(scriptIndex);
|
||||
m_editorController.setScript(script);
|
||||
stackViewController()->push(&m_editorController);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ public:
|
||||
ConsoleController * consoleController() { return &m_consoleController; }
|
||||
StackViewController * stackViewController();
|
||||
void renameSelectedScript();
|
||||
void deleteScriptAtIndex(int i);
|
||||
void deleteScript(Script script);
|
||||
void reloadConsole();
|
||||
void loadPythonIfNeeded();
|
||||
void openConsoleWithScriptAtIndex(int scriptIndex);
|
||||
void openConsoleWithScript(Script script);
|
||||
void scriptContentEditionDidFinish();
|
||||
|
||||
/* ViewController */
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
/* In the initializer list of the MenuController constructor, we initialize
|
||||
* m_scriptCells by copying k_maxNumberOfDisplayableScriptCells times the
|
||||
* constructor of an EvenOddEditableTextCell. */
|
||||
char m_draftTextBuffer[TextField::maxBufferSize()];
|
||||
char m_draftTextBuffer[Script::k_nameSize];
|
||||
EvenOddCellWithEllipsis m_scriptParameterCells[k_maxNumberOfDisplayableScriptCells];
|
||||
Shared::NewFunctionCell m_addNewScriptCell;
|
||||
EvenOddCell m_emptyCell;
|
||||
|
||||
@@ -2,35 +2,36 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
Script::Script(const char * marker, const char * name, size_t nameBufferSize, const char * content, size_t contentBufferSize) :
|
||||
m_marker(marker),
|
||||
m_name(name),
|
||||
m_nameBufferSize(nameBufferSize),
|
||||
m_content(content),
|
||||
m_contentBufferSize(contentBufferSize)
|
||||
Script::Script(File f) :
|
||||
File(f)
|
||||
{
|
||||
}
|
||||
|
||||
bool Script::isNull() const {
|
||||
if (m_marker == nullptr) {
|
||||
assert(m_name == nullptr);
|
||||
assert(m_nameBufferSize == 0);
|
||||
assert(m_content == nullptr);
|
||||
assert(m_contentBufferSize == 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Script::autoImport() const {
|
||||
bool Script::importationStatus() const {
|
||||
assert(!isNull());
|
||||
assert(m_marker != nullptr);
|
||||
if (m_marker[0] == AutoImportationMarker) {
|
||||
return true;
|
||||
const char * body = read();
|
||||
return (body[0] == 1);
|
||||
}
|
||||
|
||||
void Script::toggleImportationStatus() {
|
||||
assert(bodySize() >= 1);
|
||||
m_body[0] = importationStatus() ? 0 : 1;
|
||||
}
|
||||
|
||||
const char * Script::readContent() const {
|
||||
const char * body = read();
|
||||
return body+k_importationStatusSize;
|
||||
}
|
||||
|
||||
File::ErrorStatus Script::writeContent(const char * data, size_t size) {
|
||||
int deltaSize = (int)size+k_importationStatusSize - (int)bodySize();
|
||||
if (FileSystem::sharedFileSystem()->moveNextFile(start(), deltaSize)) {
|
||||
*m_size += deltaSize;
|
||||
strlcpy(m_body+k_importationStatusSize, data, size);
|
||||
return ErrorStatus::None;
|
||||
} else {
|
||||
return ErrorStatus::NoEnoughSpaceAvailable;
|
||||
}
|
||||
assert (m_marker[0] == NoAutoImportationMarker);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5,64 +5,22 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
class Script {
|
||||
/* File : | Total Size | Type | Name | Body |
|
||||
* Script: | AutoImportationStatus | Content |*/
|
||||
|
||||
class Script : public File {
|
||||
friend class ScriptStore;
|
||||
public:
|
||||
Script(const char * marker = nullptr, const char * name = nullptr, size_t nameBufferSize = 0, const char * content = nullptr, size_t contentBufferSize = 0);
|
||||
bool isNull() const;
|
||||
bool autoImport() const;
|
||||
Script(File f);
|
||||
|
||||
const char * name() const {
|
||||
assert(!isNull());
|
||||
assert(m_name != nullptr);
|
||||
return m_name;
|
||||
}
|
||||
bool importationStatus() const;
|
||||
void toggleImportationStatus();
|
||||
|
||||
char * editableName() {
|
||||
assert(!isNull());
|
||||
assert(m_name != nullptr);
|
||||
return const_cast<char *>(m_name);
|
||||
}
|
||||
const char * readContent() const;
|
||||
ErrorStatus writeContent(const char * data, size_t size);
|
||||
|
||||
/* nameBufferSize() might not be equal to strlen(name()): There might be free
|
||||
* space (chars equal to ScriptStore::FreeSpaceMarker), that is used to edit
|
||||
* the script name. */
|
||||
size_t nameBufferSize() const {
|
||||
assert(!isNull());
|
||||
return m_nameBufferSize;
|
||||
}
|
||||
|
||||
const char * content() const {
|
||||
assert(!isNull());
|
||||
assert(m_content != nullptr);
|
||||
return m_content;
|
||||
}
|
||||
|
||||
char * editableContent() {
|
||||
assert(!isNull());
|
||||
assert(m_content != nullptr);
|
||||
return const_cast<char *>(m_content);
|
||||
}
|
||||
|
||||
/* contentBufferSize() might not be equal to strlen(name()): There might be
|
||||
* free space (chars equal to ScriptStore::FreeSpaceMarker), that is used to
|
||||
* edit the script content. */
|
||||
size_t contentBufferSize() const {
|
||||
assert(!isNull());
|
||||
return m_contentBufferSize;
|
||||
}
|
||||
|
||||
static constexpr int NumberOfStringsPerScript = 3;
|
||||
static constexpr char AutoImportationMarker = 2;
|
||||
static constexpr char NoAutoImportationMarker = 3;
|
||||
static constexpr char DefaultAutoImportationMarker = AutoImportationMarker;
|
||||
/* We made sure that these chars are not used in ion/include/ion/charset.h,
|
||||
* nor used in the ScriptStore. */
|
||||
private:
|
||||
const char * m_marker;
|
||||
const char * m_name;
|
||||
size_t m_nameBufferSize;
|
||||
const char * m_content;
|
||||
size_t m_contentBufferSize;
|
||||
constexpr static size_t k_importationStatusSize = 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace Code {
|
||||
|
||||
ScriptParameterController::ScriptParameterController(Responder * parentResponder, I18n::Message title, ScriptStore * scriptStore, MenuController * menuController) :
|
||||
ScriptParameterController::ScriptParameterController(Responder * parentResponder, I18n::Message title, MenuController * menuController) :
|
||||
ViewController(parentResponder),
|
||||
m_pageTitle(title),
|
||||
m_executeScript(I18n::Message::ExecuteScript),
|
||||
@@ -12,21 +12,17 @@ ScriptParameterController::ScriptParameterController(Responder * parentResponder
|
||||
m_deleteScript(I18n::Message::DeleteScript),
|
||||
m_selectableTableView(this, this, 0, 1, Metric::CommonTopMargin, Metric::CommonRightMargin,
|
||||
Metric::CommonBottomMargin, Metric::CommonLeftMargin, this),
|
||||
m_scriptStore(scriptStore),
|
||||
m_menuController(menuController),
|
||||
m_autoImport(true),
|
||||
m_currentScriptIndex(-1)
|
||||
m_script(File()),
|
||||
m_menuController(menuController)
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptParameterController::setScript(int i){
|
||||
Script script = (m_scriptStore->scriptAtIndex(i, ScriptStore::EditableZone::Content));
|
||||
m_autoImport = script.autoImport();
|
||||
m_currentScriptIndex = i;
|
||||
void ScriptParameterController::setScript(Script script){
|
||||
m_script = script;
|
||||
}
|
||||
|
||||
void ScriptParameterController::dismissScriptParameterController() {
|
||||
m_currentScriptIndex = -1;
|
||||
m_script = Script(File());
|
||||
stackViewController()->pop();
|
||||
}
|
||||
|
||||
@@ -36,26 +32,25 @@ const char * ScriptParameterController::title() {
|
||||
|
||||
bool ScriptParameterController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
|
||||
int scriptIndex = m_currentScriptIndex;
|
||||
Script s = m_script;
|
||||
switch (selectedRow()) {
|
||||
case 0:
|
||||
dismissScriptParameterController();
|
||||
m_menuController->openConsoleWithScriptAtIndex(scriptIndex);
|
||||
m_menuController->openConsoleWithScript(s);
|
||||
return true;
|
||||
case 1:
|
||||
dismissScriptParameterController();
|
||||
m_menuController->renameSelectedScript();
|
||||
return true;
|
||||
case 2:
|
||||
m_scriptStore->switchAutoImportAtIndex(scriptIndex);
|
||||
m_autoImport = !m_autoImport;
|
||||
m_script.toggleImportationStatus();
|
||||
m_selectableTableView.reloadData();
|
||||
m_menuController->reloadConsole();
|
||||
app()->setFirstResponder(&m_selectableTableView);
|
||||
return true;
|
||||
case 3:
|
||||
dismissScriptParameterController();
|
||||
m_menuController->deleteScriptAtIndex(scriptIndex);
|
||||
m_menuController->deleteScript(s);
|
||||
m_menuController->reloadConsole();
|
||||
return true;
|
||||
default:
|
||||
@@ -86,7 +81,7 @@ HighlightCell * ScriptParameterController::reusableCell(int index) {
|
||||
void ScriptParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if (cell == &m_autoImportScript) {
|
||||
SwitchView * switchView = (SwitchView *)m_autoImportScript.accessoryView();
|
||||
switchView->setState(m_autoImport);
|
||||
switchView->setState(m_script.importationStatus());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ class MenuController;
|
||||
|
||||
class ScriptParameterController : public ViewController, public SimpleListViewDataSource, public SelectableTableViewDataSource {
|
||||
public:
|
||||
ScriptParameterController(Responder * parentResponder, I18n::Message title, ScriptStore * scriptStore, MenuController * menuController);
|
||||
void setScript(int i);
|
||||
ScriptParameterController(Responder * parentResponder, I18n::Message title, MenuController * menuController);
|
||||
void setScript(Script script);
|
||||
void dismissScriptParameterController();
|
||||
|
||||
/* ViewController */
|
||||
@@ -38,10 +38,8 @@ private:
|
||||
MessageTableCellWithSwitch m_autoImportScript;
|
||||
MessageTableCell m_deleteScript;
|
||||
SelectableTableView m_selectableTableView;
|
||||
ScriptStore * m_scriptStore;
|
||||
Script m_script;
|
||||
MenuController * m_menuController;
|
||||
bool m_autoImport;
|
||||
int m_currentScriptIndex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,101 +12,39 @@ namespace Code {
|
||||
constexpr char ScriptStore::k_scriptExtension[];
|
||||
constexpr char ScriptStore::k_defaultScriptName[];
|
||||
|
||||
ScriptStore::ScriptStore() :
|
||||
m_accordion(m_scriptData, k_scriptDataSize)
|
||||
ScriptStore::ScriptStore()
|
||||
{
|
||||
addScriptFromTemplate(ScriptTemplate::Factorial());
|
||||
addScriptFromTemplate(ScriptTemplate::Mandelbrot());
|
||||
addScriptFromTemplate(ScriptTemplate::Polynomial());
|
||||
}
|
||||
|
||||
const Script ScriptStore::scriptAtIndex(int index, EditableZone zone) {
|
||||
assert(index >= 0 && index < numberOfScripts());
|
||||
size_t nameBufferSize = 0;
|
||||
size_t contentBufferSize = 0;
|
||||
int accordionIndex;
|
||||
|
||||
// Move the Free Space at the end of the correct string.
|
||||
switch (zone) {
|
||||
case EditableZone::None:
|
||||
break;
|
||||
case EditableZone::Name:
|
||||
accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
|
||||
nameBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
|
||||
break;
|
||||
case EditableZone::Content:
|
||||
accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
|
||||
contentBufferSize = m_accordion.sizeOfEditableBufferAtIndex(accordionIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
// Compute the positions and lengths of the Script Marker, Name and Content.
|
||||
const char * marker = m_accordion.bufferAtIndex(accordionIndexOfMarkersOfScriptAtIndex(index));
|
||||
const char * name = m_accordion.bufferAtIndex(accordionIndexOfNameOfScriptAtIndex(index));
|
||||
if (nameBufferSize == 0) {
|
||||
nameBufferSize = strlen(name);
|
||||
}
|
||||
const char * content = m_accordion.bufferAtIndex(accordionIndexOfContentOfScriptAtIndex(index));
|
||||
if (contentBufferSize == 0) {
|
||||
contentBufferSize = strlen(content);
|
||||
}
|
||||
return Script(marker, name, nameBufferSize, content, contentBufferSize);
|
||||
Script ScriptStore::scriptAtIndex(int index) {
|
||||
File f = FileSystem::sharedFileSystem()->fileOfTypeAtIndex(File::Type::Script, index);
|
||||
return Script(f);
|
||||
}
|
||||
|
||||
const Script ScriptStore::scriptNamed(const char * name) {
|
||||
for (int i = 0; i < numberOfScripts(); i++) {
|
||||
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(i);
|
||||
const char * currentScriptName = m_accordion.bufferAtIndex(accordionIndex);
|
||||
if (strcmp(currentScriptName, name) == 0) {
|
||||
return scriptAtIndex(i);
|
||||
}
|
||||
}
|
||||
return Script();
|
||||
Script ScriptStore::scriptNamed(const char * name) {
|
||||
File f = FileSystem::sharedFileSystem()->getFile(File::Type::Script, name);
|
||||
return Script(f);
|
||||
}
|
||||
|
||||
int ScriptStore::numberOfScripts() {
|
||||
return (m_accordion.numberOfBuffers())/Script::NumberOfStringsPerScript;
|
||||
return FileSystem::sharedFileSystem()->numberOfFileOfType(File::Type::Script);
|
||||
}
|
||||
|
||||
bool ScriptStore::addNewScript() {
|
||||
return addScriptFromTemplate(ScriptTemplate::Empty());
|
||||
}
|
||||
|
||||
bool ScriptStore::renameScriptAtIndex(int index, const char * newName) {
|
||||
assert (index >= 0 && index < numberOfScripts());
|
||||
int accordionIndex = accordionIndexOfNameOfScriptAtIndex(index);
|
||||
return m_accordion.replaceBufferAtIndex(accordionIndex, newName);
|
||||
}
|
||||
|
||||
void ScriptStore::switchAutoImportAtIndex(int index) {
|
||||
assert(index >= 0 && index < numberOfScripts());
|
||||
Script script = scriptAtIndex(index);
|
||||
bool autoImportation = script.autoImport();
|
||||
int accordionIndex = accordionIndexOfMarkersOfScriptAtIndex(index);
|
||||
if (autoImportation) {
|
||||
const char autoImportationString[2] = {Script::NoAutoImportationMarker, 0};
|
||||
m_accordion.replaceBufferAtIndex(accordionIndex, autoImportationString);
|
||||
return;
|
||||
}
|
||||
const char autoImportationString[2] = {Script::AutoImportationMarker, 0};
|
||||
m_accordion.replaceBufferAtIndex(accordionIndex, autoImportationString);
|
||||
}
|
||||
|
||||
void ScriptStore::deleteScriptAtIndex(int index) {
|
||||
assert (index >= 0 && index < numberOfScripts());
|
||||
int accordionIndex = accordionIndexOfContentOfScriptAtIndex(index);
|
||||
// We delete in reverse order because we want the indexes to stay true.
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex);
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex-1);
|
||||
m_accordion.deleteBufferAtIndex(accordionIndex-2);
|
||||
}
|
||||
|
||||
void ScriptStore::deleteAllScripts() {
|
||||
m_accordion.deleteAll();
|
||||
for (int i = 0; i < numberOfScripts(); i++) {
|
||||
scriptAtIndex(i).remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool ScriptStore::isFull() {
|
||||
return (numberOfScripts() >= k_maxNumberOfScripts || m_accordion.freeSpaceSize() < k_fullFreeSpaceSizeLimit);
|
||||
return (numberOfScripts() >= k_maxNumberOfScripts || FileSystem::sharedFileSystem()->availableSize() < k_fullFreeSpaceSizeLimit);
|
||||
}
|
||||
|
||||
void ScriptStore::scanScriptsForFunctionsAndVariables(void * context, ScanCallback storeFunction, ScanCallback storeVariable) {
|
||||
@@ -114,7 +52,7 @@ void ScriptStore::scanScriptsForFunctionsAndVariables(void * context, ScanCallba
|
||||
// Handle lexer or parser errors with nlr.
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
const char * scriptContent = scriptAtIndex(scriptIndex).content();
|
||||
const char * scriptContent = scriptAtIndex(scriptIndex).readContent();
|
||||
if (scriptContent == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -196,44 +134,21 @@ const char * ScriptStore::contentOfScript(const char * name) {
|
||||
if (script.isNull()) {
|
||||
return nullptr;
|
||||
}
|
||||
return script.content();
|
||||
return script.readContent();
|
||||
}
|
||||
|
||||
bool ScriptStore::addScriptFromTemplate(const ScriptTemplate * scriptTemplate) {
|
||||
const char autoImportationString[2] = {Script::DefaultAutoImportationMarker, 0};
|
||||
if (!m_accordion.appendBuffer(autoImportationString)) {
|
||||
return false;
|
||||
size_t scriptSize = strlen(scriptTemplate->content())+1;
|
||||
char * body = new char[scriptSize+Script::k_importationStatusSize];
|
||||
body[0] = 1;
|
||||
strlcpy(body+1, scriptTemplate->content(), scriptSize);
|
||||
bool result = false;
|
||||
if (FileSystem::sharedFileSystem()->sizeOfFileWithBody(body) <= FileSystem::sharedFileSystem()->availableSize()) {
|
||||
FileSystem::sharedFileSystem()->addFile(scriptTemplate->name(), File::Type::Script, body);
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (!m_accordion.appendBuffer(scriptTemplate->name())) {
|
||||
// Delete the Auto Importation Marker
|
||||
m_accordion.deleteLastBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (copyStaticScriptOnFreeSpace(scriptTemplate)) {
|
||||
return true;
|
||||
}
|
||||
// Delete the Auto Importation Marker and the Name Of the Script
|
||||
m_accordion.deleteLastBuffer();
|
||||
m_accordion.deleteLastBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScriptStore::copyStaticScriptOnFreeSpace(const ScriptTemplate * scriptTemplate) {
|
||||
return m_accordion.appendBuffer(scriptTemplate->content());
|
||||
}
|
||||
|
||||
int ScriptStore::accordionIndexOfMarkersOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript;
|
||||
}
|
||||
|
||||
int ScriptStore::accordionIndexOfNameOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript + 1;
|
||||
}
|
||||
|
||||
int ScriptStore::accordionIndexOfContentOfScriptAtIndex(int index) const {
|
||||
return index * Script::NumberOfStringsPerScript + 2;
|
||||
delete[] body;
|
||||
return result;
|
||||
}
|
||||
|
||||
const char * ScriptStore::structID(mp_parse_node_struct_t *structNode) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef CODE_SCRIPT_STORE_H
|
||||
#define CODE_SCRIPT_STORE_H
|
||||
|
||||
#include "accordion.h"
|
||||
#include "script.h"
|
||||
#include "script_template.h"
|
||||
#include <python/port/port.h>
|
||||
@@ -13,24 +12,15 @@ namespace Code {
|
||||
|
||||
class ScriptStore : public MicroPython::ScriptProvider {
|
||||
public:
|
||||
enum class EditableZone {
|
||||
None,
|
||||
Name,
|
||||
Content
|
||||
};
|
||||
|
||||
static constexpr char k_scriptExtension[] = ".py";
|
||||
static constexpr char k_defaultScriptName[] = "script.py";
|
||||
static constexpr int k_maxNumberOfScripts = 8;
|
||||
|
||||
ScriptStore();
|
||||
const Script scriptAtIndex(int index, EditableZone zone = EditableZone::None);
|
||||
const Script scriptNamed(const char * name);
|
||||
Script scriptAtIndex(int index);
|
||||
Script scriptNamed(const char * name);
|
||||
int numberOfScripts();
|
||||
bool addNewScript();
|
||||
bool renameScriptAtIndex(int index, const char * newName);
|
||||
void switchAutoImportAtIndex(int index);
|
||||
void deleteScriptAtIndex(int index);
|
||||
void deleteAllScripts();
|
||||
bool isFull();
|
||||
|
||||
@@ -43,21 +33,13 @@ public:
|
||||
|
||||
bool addScriptFromTemplate(const ScriptTemplate * scriptTemplate);
|
||||
private:
|
||||
static constexpr int k_fullFreeSpaceSizeLimit = 50;
|
||||
// If m_accordion's free space has a size smaller than
|
||||
// If the system file free space has a size smaller than
|
||||
// k_fullFreeSpaceSizeLimit, we consider the script store as full.
|
||||
static constexpr size_t k_scriptDataSize = 4096;
|
||||
static constexpr int k_fullFreeSpaceSizeLimit = File::k_sizeSize+File::k_nameSize+File::k_typeSize+10;
|
||||
static constexpr size_t k_fileInput2ParseNodeStructKind = 1;
|
||||
static constexpr size_t k_functionDefinitionParseNodeStructKind = 3;
|
||||
static constexpr size_t k_expressionStatementParseNodeStructKind = 5;
|
||||
bool copyStaticScriptOnFreeSpace(const ScriptTemplate * scriptTemplate);
|
||||
int accordionIndexOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfMarkersOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfNameOfScriptAtIndex(int index) const;
|
||||
int accordionIndexOfContentOfScriptAtIndex(int index) const;
|
||||
const char * structID(mp_parse_node_struct_t *structNode);
|
||||
char m_scriptData[k_scriptDataSize];
|
||||
Accordion m_accordion;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ class TextArea;
|
||||
|
||||
class TextAreaDelegate : public TextInputDelegate {
|
||||
public:
|
||||
virtual bool textAreaShouldFinishEditing(TextArea * textArea, Ion::Events::Event event) = 0;
|
||||
virtual bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite);
|
||||
void setDelegate(TextFieldDelegate * delegate) { m_delegate = delegate; }
|
||||
void setDraftTextBuffer(char * draftTextBuffer);
|
||||
void setTextBufferSize(size_t size);
|
||||
bool isEditing() const;
|
||||
size_t draftTextLength() const;
|
||||
void setText(const char * text);
|
||||
@@ -30,6 +31,7 @@ protected:
|
||||
public:
|
||||
ContentView(char * textBuffer, char * draftTextBuffer, size_t textBufferSize, KDText::FontSize size, float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite);
|
||||
void setDraftTextBuffer(char * draftTextBuffer);
|
||||
void setTextBufferSize(size_t size);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
bool isEditing() const { return m_isEditing; }
|
||||
const char * text() const override;
|
||||
|
||||
@@ -22,6 +22,10 @@ void TextField::ContentView::setDraftTextBuffer(char * draftTextBuffer) {
|
||||
m_draftTextBuffer = draftTextBuffer;
|
||||
}
|
||||
|
||||
void TextField::ContentView::setTextBufferSize(size_t size) {
|
||||
m_textBufferSize = size;
|
||||
}
|
||||
|
||||
void TextField::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDColor bckCol = m_backgroundColor;
|
||||
if (m_isEditing) {
|
||||
@@ -172,6 +176,10 @@ void TextField::setDraftTextBuffer(char * draftTextBuffer) {
|
||||
m_contentView.setDraftTextBuffer(draftTextBuffer);
|
||||
}
|
||||
|
||||
void TextField::setTextBufferSize(size_t size) {
|
||||
m_contentView.setTextBufferSize(size);
|
||||
}
|
||||
|
||||
bool TextField::isEditing() const {
|
||||
return m_contentView.isEditing();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user