Tried to write a code similar to app called “MathStudio” but with a very basic functionality. I have used Simeon’s “Buffer” class here. Thanks Simeon.
Demo:
Main:
-- Use this function to perform your initial setup
function setup()
displayMode(STANDARD)
displayMode(FULLSCREEN)
screenWidth = 500
screenHeight = 400
drawFlag = false
initFlag = false
buffer = Buffer()
xcounter = 0
result = ""
errorMsg = ""
graphTable = {}
-- Initializing Textfields
textField = TextField("Formula", 500, 80)
resultField = TextField("Result", 500,40)
-- Initializing Buttons
button = {}
titles = {"sin()", "cos()", "tan()", "asin()", "acos()", "atan()", "log10()", "log()", "exp()","pow()", "sqrt()", "pi", "+", "-", "*", "/", "%", "(", ")", ",", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",".", "x", "Solve", "Plot", "Clear","Del", "<==", "==>",}
counter = 1
for _, v in pairs (titles) do
if counter < 13 then
fill(61, 71, 94, 156)
r,g,b,a = fill()
elseif counter >= 13 and counter <= 20 then
fill(61, 113, 31, 155)
r,g,b,a = fill()
else
fill(0, 0, 0, 160)
r,g,b,a = fill()
end
table.insert(button,Buttons(v,r,g,b,a,255,255,255,255,15,24))
counter = counter + 1
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(173, 173, 173, 93)
initializeScreen()
drawButtons()
textField.pos = vec2(centerPnt.x,HEIGHT - HEIGHT*0.1)
textField:draw()
resultField.pos = vec2(centerPnt.x,HEIGHT - HEIGHT*0.18)
resultField:draw()
equationStr = buffer:toString()
if initFlag then
generateEquation()
if equationStr ~= "y=" then
initializeTable()
executeEquation()
result = y
else
errorMsg = "Not a valid equation"
end
end
fontSize(16)
l,t = textSize(result)
text(result, resultField.pos.x-resultField.size.x/2+l/2+5,resultField.pos.y )
text(errorMsg,WIDTH*0.2,HEIGHT-HEIGHT*0.1)
if drawFlag==true and equationStr ~= "y=" then
drawCurves()
spriteMode(CENTER)
sprite(graph,centerPnt.x,centerPnt.y)
else
drawFlag=false
end
buffer:draw()
end
function drawButtons()
left = WIDTH - WIDTH*0.92
top = HEIGHT - HEIGHT * 0.265
counter = 1
for _, b in pairs(button) do
b.pos = vec2(left,top)
b:draw()
left=left+b.size.x+5
if counter == 4 then
counter = 1
left = WIDTH - WIDTH * 0.92
top = top - b.size.y-5
else
counter = counter + 1
end
end
end
function touched (touch)
for _, b in pairs (button) do
b:touched (touch)
end
end
Buffer:
Buffer = class()
function Buffer:init()
self.buffer = {}
self.font = "Inconsolata"
self.fontSize = 20
-- x = line, y = pos
self.cursor = vec2(1,1)
self.t = 0
self.cursorBlink = 0
end
function Buffer:setStyle()
textMode(CORNER)
font( self.font )
fill(0, 0, 0, 255)
fontSize( self.fontSize )
textWrapWidth(500)
end
function Buffer:cursorToScreen(c)
-- Get a subset of the buffer
local lines = table_slice( self.buffer, 1, c.x )
local l = self.buffer[c.x]
local upToStr = self:bufferToString(lines)
local lstr = nil
if l then
lstr = table.concat(l)
end
pushStyle()
self:setStyle()
local lw = 0
local _,lh = textSize("A")
local emptyLine = true
if lstr and lstr ~= "" then
lw,lh = textSize(string.sub(lstr,1,c.y - 1))
emptyLine = false
end
local pw,ph = textSize(upToStr)
if emptyLine then
ph = ph + lh
end
popStyle()
return lw,(ph - lh/2)
end
function Buffer:bufferToString(b)
local bstrings = {}
for k,v in pairs(b) do
table.insert(bstrings, table.concat( b[k] ) )
end
return table.concat( bstrings, "\
" )
end
function Buffer:moveCursor(o)
self.cursor = self.cursor + o
self.cursor.x = math.max(1, math.min(self.cursor.x, #self.buffer))
local l = self.buffer[self.cursor.x]
local y = self.cursor.y
y = math.max(1, math.min(y, #l + 1))
self.cursor.y = y
end
function Buffer:insertCharacter(c)
if c == "x" then
xcounter = xcounter + 1
end
local l = self.buffer[self.cursor.x]
if l == nil then
l = {}
self.buffer[self.cursor.x] = l
end
if c == "\
" then
local start = table_slice(l,1,self.cursor.y)
local tail = table_slice(l,self.cursor.y+1,#l)
table[self.cursor.x] = start
table.insert(self.buffer, self.cursor.x+1, tail)
self.cursor = vec2( self.cursor.x + 1, 1 )
elseif c == "Del" then
if self.cursor.y == 1 then
-- delete line
local prevLine = self.buffer[self.cursor.x - 1]
table.remove(self.buffer, self.cursor.x)
if prevLine then
self.cursor = vec2(self.cursor.x - 1, #prevLine + 1)
table_append( prevLine, l )
end
else
-- delete character
if (l[self.cursor.y-1] == "x") then
xcounter = xcounter-1
end
table.remove(l, self.cursor.y - 1 )
self.cursor = vec2(self.cursor.x, self.cursor.y - 1 )
end
else
table.insert(l, self.cursor.y, c)
self.cursor = vec2( self.cursor.x, self.cursor.y + 1 )
end
end
function Buffer:draw()
self.t = self.t + 8 * DeltaTime
self.cursorBlink = (math.sin(self.t) + 1) * 128
pushStyle()
self:setStyle()
local str = self:toString()
local w,h = textSize(str)
pushMatrix()
translate(textField.pos.x-textField.size.x/2+5,-40)
text(str, 0, HEIGHT - h)
-- Draw cursor
-- Cursor pos x,y
local cpx,cpy = self:cursorToScreen(self.cursor)
fill(0, 87, 255, self.cursorBlink)
rectMode(CENTER)
rect(cpx,HEIGHT - cpy,5,30)
popMatrix()
popStyle()
end
function Buffer:clear()
self.cursor = vec2(1,1)
self.buffer = {}
end
function Buffer:toString()
return self:bufferToString(self.buffer)
end
function Buffer:toStringWithoutActiveLine()
local bstrings = {}
for k,v in pairs(self.buffer) do
if k ~= self.cursor.x then
table.insert(bstrings, table.concat( self.buffer[k] ) )
end
end
return table.concat( bstrings, "\
" )
end
Other classes and function file is given in the next post as its not allowing to enter more characters in this post.