diff --git a/blitbuffer.c b/blitbuffer.c index c8a51de7f..8ea96a7a6 100644 --- a/blitbuffer.c +++ b/blitbuffer.c @@ -366,6 +366,63 @@ static int paintRect(lua_State *L) { return 0; } +static int invertRect(lua_State *L) { + BlitBuffer *dst = (BlitBuffer*) luaL_checkudata(L, 1, "blitbuffer"); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + uint8_t *dstptr; + + int cy, cx; + if(w <= 0 || h <= 0 || x >= dst->w || y >= dst->h) { + return 0; + } + if(x + w > dst->w) { + w = dst->w - x; + } + if(y + h > dst->h) { + h = dst->h - y; + } + + if(x & 1) { + /* This will invert the leftmost column + * in the case when x is odd. After this, + * x will become even. */ + dstptr = (uint8_t*)(dst->data + + y * dst->pitch + + x / 2); + for(cy = 0; cy < h; cy++) { + *dstptr ^= 0x0F; + dstptr += dst->pitch; + } + x++; + w--; + } + dstptr = (uint8_t*)(dst->data + + y * dst->pitch + + x / 2); + for(cy = 0; cy < h; cy++) { + for(cx = 0; cx < w/2; cx++) { + *(dstptr+cx) ^= 0xFF; + } + dstptr += dst->pitch; + } + if(w & 1) { + /* This will invert the rightmost column + * in the case when (w & 1) && !(x & 1) or + * !(w & 1) && (x & 1). */ + dstptr = (uint8_t*)(dst->data + + y * dst->pitch + + (x + w) / 2); + for(cy = 0; cy < h; cy++) { + *dstptr ^= 0xF0; + dstptr += dst->pitch; + } + } + return 0; +} + static const struct luaL_reg blitbuffer_func[] = { {"new", newBlitBuffer}, {NULL, NULL} @@ -378,6 +435,7 @@ static const struct luaL_reg blitbuffer_meth[] = { {"addblitFrom", addblitToBuffer}, {"blitFullFrom", blitFullToBuffer}, {"paintRect", paintRect}, + {"invertRect", invertRect}, {"free", freeBlitBuffer}, {"__gc", freeBlitBuffer}, {NULL, NULL} diff --git a/graphics.lua b/graphics.lua index 1ebb13cce..bebefc419 100644 --- a/graphics.lua +++ b/graphics.lua @@ -6,6 +6,7 @@ blitbuffer.paintBorder = function (bb, x, y, w, h, bw, c) bb:paintRect(x+w-bw, y+bw, bw, h - 2*bw, c) end + --[[ Draw a progress bar according to following args: @@ -27,3 +28,69 @@ blitbuffer.progressBar = function (bb, x, y, w, h, fb.bb:paintRect(x+load_m_w, y+load_m_h, (w-2*load_m_w)*load_percent, (h-2*load_m_h), c) end + + + +------------------------------------------------ +-- Start of Cursor class +------------------------------------------------ + +Cursor = { + x_pos = 0, + y_pos = 0, + --color = 15, + h = 10, + w = nil, + line_w = nil, +} + +function Cursor:new(o) + o = o or {} + o.x_pos = o.x_pos or self.x_pos + o.y_pos = o.y_pos or self.y_pos + o.h = o.h or self.h + + o.w = o.h / 2 + o.line_w = math.floor(o.h / 10) + + setmetatable(o, self) + self.__index = self + return o +end + +function Cursor:_draw(x, y) + local body_h = self.h - self.line_w + blitbuffer.invertRect(fb.bb, x, y, self.w, self.line_w) + --print("self.w: "..self.w..", self.line_w: "..self.line_w) + blitbuffer.invertRect(fb.bb, x+(self.w/2)-(self.line_w/2), y+self.line_w, + self.line_w, body_h-self.line_w) + blitbuffer.invertRect(fb.bb, x, y+body_h, self.w, self.line_w) +end + +function Cursor:draw() + self:_draw(self.x_pos, self.y_pos) +end + +function Cursor:clear() + self:_draw(self.x_pos, self.y_pos) +end + +function Cursor:move(x_off, y_off) + self:clear() + self.x_pos = self.x_pos + x_off + self.y_pos = self.y_pos + y_off + self:draw() +end + +function Cursor:moveHorizontal(x_off) + self:clear() + self.x_pos = self.x_pos + x_off + self:draw() +end + +function Cursor:moveVertical(y_off) + self:clear() + self.y_pos = self.y_pos + y_off + self:draw() +end + diff --git a/inputbox.lua b/inputbox.lua index 6e3fc6667..e845ccd79 100644 --- a/inputbox.lua +++ b/inputbox.lua @@ -4,6 +4,7 @@ require "graphics" InputBox = { -- Class vars: + h = 100, input_start_x = 145, input_start_y = nil, input_cur_x = nil, -- points to the start of next input pos @@ -15,6 +16,8 @@ InputBox = { shiftmode = false, altmode = false, + cursor = nil, + -- font for displaying input content face = freetype.newBuiltinFace("mono", 25), fhash = "m25", @@ -22,13 +25,6 @@ InputBox = { fwidth = 16, } -function InputBox:setDefaultInput(text) - self.input_string = "" - self:addString(text) - --self.input_cur_x = self.input_start_x + (string.len(text) * self.fwidth) - --self.input_string = text -end - function InputBox:addString(str) for i = 1, #str do self:addChar(str:sub(i,i)) @@ -36,9 +32,13 @@ function InputBox:addString(str) end function InputBox:addChar(char) - renderUtf8Text(fb.bb, self.input_cur_x, self.input_start_y, self.face, self.fhash, - char, true) - fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight) + self.cursor:moveHorizontal(self.fwidth) + renderUtf8Text(fb.bb, self.input_cur_x, self.input_start_y, + self.face, self.fhash, + char, true) + fb:refresh(1, self.input_cur_x - self.cursor.w - self.fwidth, + self.input_start_y-25, + self.fwidth*2 + self.cursor.w*2, self.h-25) self.input_cur_x = self.input_cur_x + self.fwidth self.input_string = self.input_string .. char end @@ -50,8 +50,10 @@ function InputBox:delChar() self.input_cur_x = self.input_cur_x - self.fwidth --fill last character with blank rectangle fb.bb:paintRect(self.input_cur_x, self.input_start_y-19, - self.fwidth, self.fheight, self.input_bg) - fb:refresh(1, self.input_cur_x, self.input_start_y-19, self.fwidth, self.fheight) + self.fwidth, self.fheight, self.input_bg) + self.cursor:moveHorizontal(-self.fwidth) + fb:refresh(1, self.input_cur_x, self.input_start_y-25, + self.fwidth + self.cursor.w, self.h-25) self.input_string = self.input_string:sub(0,-2) end @@ -66,35 +68,36 @@ function InputBox:drawBox(ypos, w, h, title) end ---[[ - || d_text default to nil (used to set default text in input slot) ---]] +---------------------------------------------------------------------- +-- InputBox:input() +-- +-- @title: input prompt for the box +-- @d_text: default to nil (used to set default text in input slot) +---------------------------------------------------------------------- function InputBox:input(ypos, height, title, d_text) - local pagedirty = true -- do some initilization + self.h = height self.input_start_y = ypos + 35 self.input_cur_x = self.input_start_x + self.cursor = Cursor:new { + x_pos = 140, + y_pos = ypos + 13, + h = 30, + } - if d_text then -- if specified default text, draw it - w = fb.bb:getWidth() - 40 - h = height - 45 - self:drawBox(ypos, w, h, title) - self:setDefaultInput(d_text) - fb:refresh(1, 20, ypos, w, h) - pagedirty = false - else -- otherwise, leave the draw task to the main loop - self.input_string = "" + if d_text then + self.input_string = d_text end - while true do - if pagedirty then - w = fb.bb:getWidth() - 40 - h = height - 45 - self:drawBox(ypos, w, h, title) - fb:refresh(1, 20, ypos, w, h) - pagedirty = false - end + -- draw box and content + w = fb.bb:getWidth() - 40 + h = height - 45 + self:drawBox(ypos, w, h, title) + self.cursor:draw() + self:addString(self.input_string) + fb:refresh(1, 20, ypos, w, h) + while true do local ev = input.waitForEvent() ev.code = adjustKeyEvents(ev) if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then