[poincare] Separate the layout logic

This commit is contained in:
Romain Goyet
2015-09-21 10:37:22 +02:00
parent 986864afb9
commit fc08a651cc
20 changed files with 263 additions and 85 deletions

View File

@@ -1,5 +1,6 @@
SFLAGS += -Ipoincare/include
objs += $(addprefix poincare/src/, expression.o integer.o number.o fraction.o power.o expression_lexer.o expression_parser.o)
objs += $(addprefix poincare/src/, expression.o integer.o fraction.o expression_lexer.o expression_parser.o)
objs += $(addprefix poincare/src/layout/, fraction_layout.o horizontal_layout.o string_layout.o)
tests += $(addprefix poincare/test/, integer.cpp)
# Even though flex and bison will generate both implementation and headers at

View File

@@ -4,7 +4,6 @@
#include <poincare/expression.h>
#include <poincare/fraction.h>
#include <poincare/integer.h>
#include <poincare/number.h>
#include <poincare/power.h>
#endif

View File

@@ -0,0 +1,15 @@
#ifndef POINCARE_ADDITION_H
#define POINCARE_ADDITION_H
#include <poincare/expression.h>
class Addition : public Expression {
public:
Addition(Expression * first_operand, Expression * second_operand);
virtual ExpressionLayout * layout();
virtual float approximate();
private:
Expression * m_children[2];
};
#endif

View File

@@ -1,30 +1,26 @@
#ifndef POINCARE_EXPRESSION_H
#define POINCARE_EXPRESSION_H
extern "C" {
#include <kandinsky.h>
}
class Expression;
typedef void (Expression::*ExpressionAction)(void);
#include <poincare/expression_layout.h>
class Expression {
public:
static Expression * parse(char * string);
void recursiveDraw();
void recursiveLayout();
KDRect m_frame;
virtual Expression ** children() = 0; // NULL-terminated
virtual void draw();
virtual void layout();
//virtual Expression ** children() = 0; // NULL-terminated
virtual ExpressionLayout * createLayout() = 0; // Returned object must be deleted
// TODO: Consider std::unique_ptr - see https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Ownership_and_Smart_Pointers
/* identicalTo means strictly the same tree. For example, 3+5 is NOT identi-
* cal to 5+3. Those are equal, but not identical. */
virtual bool identicalTo(Expression * e);
//virtual bool identicalTo(Expression * e);
//virtual Expression * simplify();
virtual float approximate() = 0;
private:
/*private:
void forEachChild(ExpressionAction);
*/
};
#endif

View File

@@ -0,0 +1,14 @@
#ifndef POINCARE_EXPRESSION_LAYOUT_H
#define POINCARE_EXPRESSION_LAYOUT_H
extern "C" {
#include <kandinsky.h>
}
class ExpressionLayout {
public:
virtual void draw() = 0;
KDRect m_frame;
};
#endif

View File

@@ -6,10 +6,9 @@
class Fraction : public Expression {
public:
Fraction(Expression * numerator, Expression * denominator);
virtual void draw();
virtual Expression ** children();
// virtual Expression ** children();
// protected:
virtual void layout();
virtual ExpressionLayout * createLayout();
virtual float approximate();
private:
Expression * m_children[3];

View File

@@ -21,12 +21,11 @@ class Integer : public Expression {
Integer operator*(const Integer &other) const;
bool operator==(const Integer &other) const;
virtual void draw();
virtual Expression ** children();
/*virtual Expression ** children();
virtual bool identicalTo(Expression * e);
*/
virtual ExpressionLayout * createLayout();
virtual float approximate();
protected:
virtual void layout();
private:
/* WARNING: This constructor takes ownership of the bits array and will free it! */
Integer(native_uint_t * digits, uint16_t numberOfDigits);

View File

@@ -1,18 +0,0 @@
#ifndef POINCARE_NUMBER_H
#define POINCARE_NUMBER_H
#include <poincare/expression.h>
class Number : public Expression {
public:
Number(char * string);
//Number(int v);
virtual void draw();
virtual Expression ** children();
protected:
virtual void layout();
private:
char m_stringValue[16];
};
#endif

34
poincare/src/addition.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <poincare/fraction.h>
#include <string.h>
static inline KDCoordinate max(KDCoordinate a, KDCoordinate b) {
return (a > b ? a : b);
}
#define NUMERATOR m_children[0]
#define DENOMINATOR m_children[1]
#define FRACTION_BORDER_LENGTH 2
#define FRACTION_LINE_MARGIN 2
#define FRACTION_LINE_HEIGHT 1
Addition::Addition(Expression * first_operand, Expression * second_operand) {
m_children[0] = first_operand;
m_children[1] = second_operand;
}
Expression ** Fraction::children() {
return m_children;
}
int Addition::numberOfChildren() {
return 2;
}
float Addition::approximate() {
return m_children[0]->approximate() + m_children[1]->approximate();
}
ExpressionLayout * Addition::layout() {
return HorizontalLayout(m_children[0], "+", m_children[1]);
}

View File

@@ -19,6 +19,7 @@ Expression * Expression::parse(char * string) {
return expression;
}
/*
bool Expression::identicalTo(Expression * e) {
// By default, two expression are not identical.
// This should obviously be overriden in subclasses!
@@ -61,3 +62,4 @@ void Expression::draw() {
void Expression::layout() {
// No-op by default
}
*/

View File

@@ -92,7 +92,7 @@ Root:
exp:
INTEGER { $$ = new Integer($1); }
| exp DIVIDE exp { $$ = new Fraction($1,$3); }
| exp POW exp { $$ = new Power($1,$3); }
/* | exp POW exp { $$ = new Power($1,$3); } */
;
/*

View File

@@ -1,9 +1,12 @@
#include <poincare/fraction.h>
#include <string.h>
#include "layout/horizontal_layout.h"
/*
static inline KDCoordinate max(KDCoordinate a, KDCoordinate b) {
return (a > b ? a : b);
}
*/
#define NUMERATOR m_children[0]
#define DENOMINATOR m_children[1]
@@ -17,11 +20,17 @@ Fraction::Fraction(Expression * numerator, Expression * denominator) {
m_children[1] = denominator;
m_children[2] = NULL;
}
/*
Expression ** Fraction::children() {
return m_children;
}
*/
ExpressionLayout * Fraction::createLayout() {
return new HorizontalLayout(NUMERATOR, '-', DENOMINATOR);
}
/*
void Fraction::layout() {
KDRect numFrame = NUMERATOR->m_frame;
KDRect denFrame = DENOMINATOR->m_frame;
@@ -46,6 +55,7 @@ void Fraction::draw() {
KDDrawLine((KDPoint){.x = 0, .y = fractionLineY},
(KDPoint){.x = m_frame.width, .y = fractionLineY});
}
*/
float Fraction::approximate() {
// TODO: handle division by zero

View File

@@ -114,6 +114,7 @@ Integer& Integer::operator=(Integer&& other) {
other.m_numberOfDigits = 0;
other.m_digits = NULL;
}
return *this;
}
Integer Integer::operator+(const Integer &other) const {
@@ -167,6 +168,7 @@ Integer Integer::operator*(const Integer &other) const {
return Integer(digits, productSize);
}
#if 0
bool Integer::identicalTo(Expression * e) {
/* FIXME
Integer * i = dynamic_cast<Integer *>(e);
@@ -186,6 +188,7 @@ void Integer::layout() {
void Integer::draw() {
// KDDrawString(m_stringValue, KDPOINT(0,0));
}
#endif
float Integer::approximate() {
union {
@@ -227,3 +230,10 @@ float Integer::approximate() {
return float_result;
}
ExpressionLayout * Integer::createLayout() {
// 1 - Build string rep'
// 2 - return StringLayout
// FIXME
return nullptr;
}

View File

@@ -0,0 +1,40 @@
#include <poincare/fraction.h>
#include <string.h>
#include "fraction_layout.h"
static inline KDCoordinate max(KDCoordinate a, KDCoordinate b) {
return (a > b ? a : b);
}
#define FRACTION_BORDER_LENGTH 2
#define FRACTION_LINE_MARGIN 2
#define FRACTION_LINE_HEIGHT 1
FractionLayout::FractionLayout(Expression * numerator, Expression * denominator) {
m_numerator = numerator->createLayout();
m_denominator = denominator->createLayout();
KDRect numFrame = m_numerator->m_frame;
KDRect denFrame = m_denominator->m_frame;
m_frame.x = 0;
m_frame.y = 0;
m_frame.width = max(numFrame.width, denFrame.width) + 2*FRACTION_BORDER_LENGTH;
m_frame.height = numFrame.height + FRACTION_LINE_MARGIN + FRACTION_LINE_HEIGHT + FRACTION_LINE_MARGIN + denFrame.height;
m_numerator->m_frame.origin.x = (KDCoordinate)((m_frame.width - numFrame.width)/2);
m_numerator->m_frame.origin.y = 0;
m_denominator->m_frame.origin.x = (KDCoordinate)((m_frame.width - denFrame.width)/2);
m_denominator->m_frame.origin.y = (KDCoordinate)(numFrame.height + 2*FRACTION_LINE_MARGIN + FRACTION_LINE_HEIGHT);
}
void FractionLayout::draw() {
m_numerator->draw();
m_denominator->draw();
KDCoordinate fractionLineY = m_numerator->m_frame.height + FRACTION_LINE_MARGIN;
KDDrawLine((KDPoint){.x = 0, .y = fractionLineY},
(KDPoint){.x = m_frame.width, .y = fractionLineY});
}

View File

@@ -0,0 +1,16 @@
#ifndef POINCARE_FRACTION_LAYOUT_H
#define POINCARE_FRACTION_LAYOUT_H
#include <poincare/expression.h>
#include <poincare/expression_layout.h>
class FractionLayout : public ExpressionLayout {
public:
FractionLayout(Expression * numerator, Expression * denominator);
virtual void draw();
private:
ExpressionLayout * m_numerator;
ExpressionLayout * m_denominator;
};
#endif

View File

@@ -0,0 +1,45 @@
//#include <string.h>
#include "horizontal_layout.h"
static inline KDCoordinate max(KDCoordinate a, KDCoordinate b) {
return (a > b ? a : b);
}
HorizontalLayout::HorizontalLayout(Expression * left_expression, char symbol, Expression * right_expression) {
m_children[0] = left_expression->createLayout();
m_children[1] = right_expression->createLayout();
m_symbol = symbol;
/* Perform the layout */
m_frame.x = 0;
m_frame.y = 0;
m_frame.width = m_children[0]->m_frame.width + 12 + m_children[1]->m_frame.width; // FIXME: 12 is not actually 12
m_frame.height = max(m_children[0]->m_frame.height, m_children[1]->m_frame.height); // FIXME: height of m_symbol
}
HorizontalLayout::~HorizontalLayout() {
delete m_children[1];
delete m_children[2];
}
void HorizontalLayout::draw() {
m_children[0]->draw();
m_children[1]->draw();
}
/*
Expression ** Fraction::children() {
return m_children;
}
int Addition::numberOfChildren() {
return 2;
}
float Addition::approximate() {
return m_children[0]->approximate() + m_children[1]->approximate();
}
ExpressionLayout * Addition::layout() {
return HorizontalLayout(m_children[0], "+", m_children[1]);
}
*/

View File

@@ -0,0 +1,17 @@
#ifndef POINCARE_HORIZONTAL_LAYOUT_H
#define POINCARE_HORIZONTAL_LAYOUT_H
#include <poincare/expression.h>
#include <poincare/expression_layout.h>
class HorizontalLayout : public ExpressionLayout {
public:
HorizontalLayout(Expression * left_expression, char symbol, Expression * right_expression);
~HorizontalLayout();
virtual void draw();
private:
ExpressionLayout * m_children[2];
char m_symbol;
};
#endif

View File

@@ -0,0 +1,28 @@
#include "string_layout.h"
StringLayout::StringLayout(const char * string) {
m_string = string;
//FIXME: Copy the string?
}
void StringLayout::draw() {
KDDrawString(m_string, (KDPoint){.x = 0, .y = 0});
}
/*
Expression ** Fraction::children() {
return m_children;
}
int Addition::numberOfChildren() {
return 2;
}
float Addition::approximate() {
return m_children[0]->approximate() + m_children[1]->approximate();
}
ExpressionLayout * Addition::layout() {
return HorizontalLayout(m_children[0], "+", m_children[1]);
}
*/

View File

@@ -0,0 +1,14 @@
#ifndef POINCARE_STRING_LAYOUT_H
#define POINCARE_STRING_LAYOUT_H
#include <poincare/expression_layout.h>
class StringLayout : public ExpressionLayout {
public:
StringLayout(const char * string);
virtual void draw();
private:
const char * m_string;
};
#endif

View File

@@ -1,43 +0,0 @@
#include <poincare/number.h>
#include <kandinsky/text.h>
#include <string.h>
/*Number::Number(int v) : m_value(v) {
for (int i=0; i<16; i++) {
m_stringValue[i] = 0;
}
int value = v;
for (int i=0; i<15; i++) {
int digit = value - 10*(value/10);
m_stringValue[i] = '0' + digit;
value = value/10;
if (value == 0) {
break;
}
}
}*/
Number::Number(char * string) {
// FIXME: use strdup
memset(m_stringValue, 0, 16);
for (int i=0;i<15;i++) {
if (string[i] == 0) {
break;
}
m_stringValue[i] = string[i];
}
}
Expression ** Number::children() {
return NULL;
}
void Number::layout() {
m_frame.size = KDStringSize(m_stringValue);
}
void Number::draw() {
KDDrawString(m_stringValue, KDPOINT(0,0));
}