First part for adding history to the user input.

Change-Id: I9d2ff28641f0d3b7fe382a765ad8cc084840c2ef
This commit is contained in:
Felix Raimundo
2016-04-06 12:54:26 +02:00
parent 11a5550bfd
commit 23aef52622
3 changed files with 149 additions and 68 deletions

View File

@@ -5,35 +5,11 @@ extern "C" {
}
#include <poincare.h>
#include "../poincare/src/layout/string_layout.h"
#include "utils.h"
void draw_lines_from_center() {
KDCoordinate width = SCREEN_WIDTH;
KDCoordinate height = SCREEN_HEIGHT;
KDColor c = 0xFF;
KDPoint center = KDPointMake(width/2, height/2);
int step = 2;
for (KDCoordinate x=0; x<width; x+=step) {
KDDrawLine(center, KDPointMake(x,0), c);
ion_sleep();
}
for (KDCoordinate y=0; y<height; y+=step) {
KDDrawLine(center, KDPointMake(width-1,y), c);
ion_sleep();
}
for (KDCoordinate x=0; x<width; x+=step) {
KDDrawLine(center, KDPointMake(width-1-x,height-1), c);
ion_sleep();
}
for (KDCoordinate y=0; y<height; y+=step) {
KDDrawLine(center, KDPointMake(0,height-1-y), c);
ion_sleep();
}
}
const char* kParsingErrorMessage = "PARSING ERROR";
void plot(Expression * e, float xMin, float xMax, float yMin, float yMax) {
Context plotContext;
@@ -54,44 +30,129 @@ void plot(Expression * e, float xMin, float xMax, float yMin, float yMax) {
}
}
void funnyPlot() {
Expression * e = Expression::parse((char *)"1/x");
plot(e, 1.0f, 4.0f, 0.0f, 1.0f);
delete e;
//////////////////////////////////////////////////////
#define INPUT_MEMORY 15
typedef struct user_expression_t {
char* text_input;
Expression* expression;
Expression* simplified;
ExpressionLayout* expression_layout;
ExpressionLayout* simplified_layout;
} user_expression_t;
class UserExpressions {
public:
UserExpressions() {
m_numberOfExpressions = 0;
m_position = INPUT_MEMORY;
for (int i=0; i<INPUT_MEMORY; i++) {
m_expressions[i] = {nullptr, nullptr, nullptr, nullptr, nullptr};
}
}
// Adds a user expression as the most recent one.
void append_expression(user_expression_t user_expression) {
if (m_numberOfExpressions < INPUT_MEMORY) {
m_numberOfExpressions++;
}
m_position = (m_position + 1) % INPUT_MEMORY;
if (m_position < 0) {
m_numberOfExpressions += INPUT_MEMORY;
}
// The circular buffer is full, now we have to erase stuff.
if (m_numberOfExpressions == INPUT_MEMORY) {
user_expression_t tmp = m_expressions[m_position];
if (tmp.text_input) {
free(tmp.text_input);
if (tmp.expression) {
free(tmp.expression);
if (tmp.expression_layout) {
free(tmp.expression_layout);
}
if (tmp.simplified && tmp.simplified != tmp.expression) {
free(tmp.simplified);
if (tmp.simplified_layout) {
free(tmp.simplified_layout);
}
}
}
}
}
m_expressions[m_position] = user_expression;
}
// Gets the i th latest expression.
user_expression_t get_expression(uint8_t index) {
//assert(index < m_numberOfExpressions);
int pos = (m_position - index) % INPUT_MEMORY;
if (pos < 0) {
pos += INPUT_MEMORY;
}
return m_expressions[pos];
}
uint8_t numberOfExpressions() {
return m_numberOfExpressions;
}
private:
uint8_t m_numberOfExpressions;
uint8_t m_position;
user_expression_t m_expressions[INPUT_MEMORY];
};
/////////////////////////////////////////////////
static user_expression_t create_user_input(char* text) {
user_expression_t user_expression = {text, nullptr, nullptr, nullptr, nullptr};
user_expression.expression = Expression::parse(user_expression.text_input);
if (user_expression.expression) {
user_expression.expression_layout = user_expression.expression->createLayout();
user_expression.simplified = user_expression.expression->simplify();
user_expression.simplified_layout = user_expression.simplified->createLayout();
} else {
user_expression.expression_layout =
new StringLayout(kParsingErrorMessage, strlen(kParsingErrorMessage));
}
return user_expression;
}
static int16_t print_user_input(user_expression_t user_expression, int16_t yOffset) {
if (user_expression.expression_layout) {
int16_t height = user_expression.expression_layout->size().height;
if (yOffset + height < SCREEN_HEIGHT) {
user_expression.expression_layout->draw(KDPointMake(0, yOffset));
}
yOffset += height;
}
if (user_expression.simplified_layout) {
int16_t height = user_expression.simplified_layout->size().height;
if (yOffset + height < SCREEN_HEIGHT) {
int16_t xOffset = SCREEN_WIDTH - user_expression.simplified_layout->size().width;
user_expression.simplified_layout->draw(KDPointMake(xOffset, yOffset));
}
yOffset += height;
}
return yOffset;
}
static void interactive_expression_parsing() {
UserExpressions user_inputs;
while (1) {
char * text_input = get_text();
clear_screen();
Expression * e = Expression::parse(text_input);
if (e) {
ExpressionLayout * l = e->createLayout();
int16_t yOffset = 10;
if (l) {
l->draw(KDPointMake(0, yOffset));
yOffset += l->size().height;
delete l;
}
Expression * simplified = e->simplify();
// Print the simplification.
if (simplified) {
ExpressionLayout * simplified_l = simplified->createLayout();
if (simplified_l) {
int16_t xOffset = SCREEN_WIDTH - simplified_l->size().width;
simplified_l->draw(KDPointMake(xOffset, yOffset));
delete simplified_l;
}
if (simplified != e) {
delete simplified;
}
}
delete e;
} else {
KDDrawString("PARSING ERROR", KDPointMake(10,10), 0);
text_event_t text_event = get_text(nullptr);
if (text_event.event == EQUAL) {
user_inputs.append_expression(create_user_input(text_event.text));
}
int16_t yOffset = 0;
for (int i=0; i<user_inputs.numberOfExpressions(); i++) {
yOffset = print_user_input(user_inputs.get_expression(i), yOffset);
if (yOffset>SCREEN_HEIGHT) {
break;
}
}
// We dealocate the memory allocated by get_text;
free(text_input);
}
}

View File

@@ -1,10 +1,12 @@
extern "C" {
#include <assert.h>
#include <kandinsky.h>
#include <stdlib.h>
#include <string.h>
#include <ion.h>
}
#include "utils.h"
#define PROMPT_HEIGHT 30
void clear_screen() {
@@ -105,18 +107,27 @@ static int get_trig_input(char* input) {
}
}
char* get_text() {
text_event_t get_text(char* txt) {
char input[255] = {0};
int index = 0;
int max = 0;
input[max] = ' ';
input[max+1] = '\0';
text_event_t text_event = {nullptr, ERROR};
if (txt != nullptr) {
assert(false);
}
while (1) {
clear_prompt();
print_prompt(input, index);
ion_event_t event = ion_get_event();
if (event == EQUAL) {
input[max] = '\0';
text_event.event = EQUAL;
text_event.text = (char*) malloc(sizeof(char) * (index + 1));
memcpy(text_event.text, input, (size_t) (index + 1));
break;
} else if (event == LEFT_ARROW) {
index--;
@@ -158,8 +169,5 @@ char* get_text() {
}
clear_prompt();
input[max] = '\0';
char* output = (char*) malloc(sizeof(char) * (index + 1));
memcpy(output, input, (size_t) (index + 1));
return output;
return text_event;
}

View File

@@ -1,9 +1,21 @@
#ifndef APP_UTILS_H
#define APP_UTILS_H
/* Returns a pointer to an input text, allocated by the functions (it is thus
* the caller's role to free it). */
char* get_text();
extern "C" {
#include <ion.h>
}
typedef struct {
char* text;
ion_event_t event;
} text_event_t;
/* Returns a pointer to an input text allocated by the functions.
* Also returns an event, which is its return reason.
*
* This function can get a text to work on instead of starting from an empty
* string. */
text_event_t get_text(char* txt);
void clear_screen();