InputMethod.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. -- 在模块顶部添加 submit_callback 声明
  2. local input_method = {}
  3. local submit_callback = nil -- 添加模块级变量
  4. -- 输入法状态
  5. local input_state = "LOWERCASE"
  6. local input_text = ""
  7. local display_text = "" -- 单独存储显示文本
  8. local is_cipher = false
  9. local last_cipher_time = 0
  10. local prev_fun = nil
  11. local is_active = false -- 输入法激活状态
  12. local text_dirty = true -- 文本需要刷新的标志
  13. local last_text_length = 0 -- 记录上次文本长度,用于检测变化
  14. --local submit_callback = nil
  15. -- 字体指针(确保使用正确的字体指针)
  16. local font_ptr = nil
  17. -- 文本显示位置
  18. local TEXT_X = 20
  19. local TEXT_Y = 27
  20. local TEXT_X2 = 228 -- 文本区域右下角
  21. local TEXT_Y2 = 52 -- 文本区域右下角
  22. -- 按键映射表
  23. local key_mappings = {
  24. LOWERCASE = {
  25. { char = "1", x1 = 4, y1 = 77, x2 = 64, y2 = 124 },
  26. { char = "2", x1 = 66, y1 = 77, x2 = 126, y2 = 124 },
  27. { char = "3", x1 = 128, y1 = 77, x2 = 188, y2 = 124 },
  28. { char = "4", x1 = 190, y1 = 77, x2 = 250, y2 = 124 },
  29. { char = "5", x1 = 252, y1 = 77, x2 = 312, y2 = 124 },
  30. { char = "6", x1 = 4, y1 = 127, x2 = 64, y2 = 174 },
  31. { char = "7", x1 = 66, y1 = 127, x2 = 126, y2 = 174 },
  32. { char = "8", x1 = 128, y1 = 127, x2 = 188, y2 = 174 },
  33. { char = "9", x1 = 190, y1 = 127, x2 = 250, y2 = 174 },
  34. { char = "0", x1 = 252, y1 = 127, x2 = 312, y2 = 174 },
  35. { char = "a", x1 = 4, y1 = 177, x2 = 64, y2 = 224 },
  36. { char = "b", x1 = 66, y1 = 177, x2 = 126, y2 = 224 },
  37. { char = "c", x1 = 128, y1 = 177, x2 = 188, y2 = 224 },
  38. { char = "d", x1 = 190, y1 = 177, x2 = 250, y2 = 224 },
  39. { char = "e", x1 = 252, y1 = 177, x2 = 312, y2 = 224 },
  40. { char = "f", x1 = 4, y1 = 227, x2 = 64, y2 = 274 },
  41. { char = "g", x1 = 66, y1 = 227, x2 = 126, y2 = 274 },
  42. { char = "h", x1 = 128, y1 = 227, x2 = 188, y2 = 274 },
  43. { char = "i", x1 = 190, y1 = 227, x2 = 250, y2 = 274 },
  44. { char = "j", x1 = 252, y1 = 227, x2 = 312, y2 = 274 },
  45. { char = "k", x1 = 4, y1 = 277, x2 = 64, y2 = 324 },
  46. { char = "l", x1 = 66, y1 = 277, x2 = 126, y2 = 324 },
  47. { char = "m", x1 = 128, y1 = 277, x2 = 188, y2 = 324 },
  48. { char = "n", x1 = 190, y1 = 277, x2 = 250, y2 = 324 },
  49. { char = "o", x1 = 252, y1 = 277, x2 = 312, y2 = 324 },
  50. { char = "p", x1 = 4, y1 = 327, x2 = 64, y2 = 374 },
  51. { char = "q", x1 = 66, y1 = 327, x2 = 126, y2 = 374 },
  52. { char = "r", x1 = 128, y1 = 327, x2 = 188, y2 = 374 },
  53. { char = "s", x1 = 190, y1 = 327, x2 = 250, y2 = 374 },
  54. { char = "t", x1 = 252, y1 = 327, x2 = 312, y2 = 374 },
  55. { char = "u", x1 = 4, y1 = 377, x2 = 64, y2 = 424 },
  56. { char = "v", x1 = 66, y1 = 377, x2 = 126, y2 = 424 },
  57. { char = "w", x1 = 128, y1 = 377, x2 = 188, y2 = 424 },
  58. { char = "x", x1 = 190, y1 = 377, x2 = 250, y2 = 424 },
  59. { char = "y", x1 = 252, y1 = 377, x2 = 312, y2 = 424 },
  60. { char = "z", x1 = 4, y1 = 427, x2 = 64, y2 = 474 },
  61. },
  62. UPPERCASE = {
  63. { char = "1", x1 = 4, y1 = 77, x2 = 64, y2 = 124 },
  64. { char = "2", x1 = 66, y1 = 77, x2 = 126, y2 = 124 },
  65. { char = "3", x1 = 128, y1 = 77, x2 = 188, y2 = 124 },
  66. { char = "4", x1 = 190, y1 = 77, x2 = 250, y2 = 124 },
  67. { char = "5", x1 = 252, y1 = 77, x2 = 312, y2 = 124 },
  68. { char = "6", x1 = 4, y1 = 127, x2 = 64, y2 = 174 },
  69. { char = "7", x1 = 66, y1 = 127, x2 = 126, y2 = 174 },
  70. { char = "8", x1 = 128, y1 = 127, x2 = 188, y2 = 174 },
  71. { char = "9", x1 = 190, y1 = 127, x2 = 250, y2 = 174 },
  72. { char = "0", x1 = 252, y1 = 127, x2 = 312, y2 = 174 },
  73. { char = "A", x1 = 4, y1 = 177, x2 = 64, y2 = 224 },
  74. { char = "B", x1 = 66, y1 = 177, x2 = 126, y2 = 224 },
  75. { char = "C", x1 = 128, y1 = 177, x2 = 188, y2 = 224 },
  76. { char = "D", x1 = 190, y1 = 177, x2 = 250, y2 = 224 },
  77. { char = "E", x1 = 252, y1 = 177, x2 = 312, y2 = 224 },
  78. { char = "F", x1 = 4, y1 = 227, x2 = 64, y2 = 274 },
  79. { char = "G", x1 = 66, y1 = 227, x2 = 126, y2 = 274 },
  80. { char = "H", x1 = 128, y1 = 227, x2 = 188, y2 = 274 },
  81. { char = "I", x1 = 190, y1 = 227, x2 = 250, y2 = 274 },
  82. { char = "J", x1 = 252, y1 = 227, x2 = 312, y2 = 274 },
  83. { char = "K", x1 = 4, y1 = 277, x2 = 64, y2 = 324 },
  84. { char = "L", x1 = 66, y1 = 277, x2 = 126, y2 = 324 },
  85. { char = "M", x1 = 128, y1 = 277, x2 = 188, y2 = 324 },
  86. { char = "N", x1 = 190, y1 = 277, x2 = 250, y2 = 324 },
  87. { char = "O", x1 = 252, y1 = 277, x2 = 312, y2 = 324 },
  88. { char = "P", x1 = 4, y1 = 327, x2 = 64, y2 = 374 },
  89. { char = "Q", x1 = 66, y1 = 327, x2 = 126, y2 = 374 },
  90. { char = "R", x1 = 128, y1 = 327, x2 = 188, y2 = 374 },
  91. { char = "S", x1 = 190, y1 = 327, x2 = 250, y2 = 374 },
  92. { char = "T", x1 = 252, y1 = 327, x2 = 312, y2 = 374 },
  93. { char = "U", x1 = 4, y1 = 377, x2 = 64, y2 = 424 },
  94. { char = "V", x1 = 66, y1 = 377, x2 = 126, y2 = 424 },
  95. { char = "W", x1 = 128, y1 = 377, x2 = 188, y2 = 424 },
  96. { char = "X", x1 = 190, y1 = 377, x2 = 250, y2 = 424 },
  97. { char = "Y", x1 = 252, y1 = 377, x2 = 312, y2 = 424 },
  98. { char = "Z", x1 = 4, y1 = 427, x2 = 64, y2 = 474 },
  99. },
  100. SYMBOL = {
  101. { char = "!", x1 = 4, y1 = 77, x2 = 64, y2 = 124 },
  102. { char = "@", x1 = 66, y1 = 77, x2 = 126, y2 = 124 },
  103. { char = "#", x1 = 128, y1 = 77, x2 = 188, y2 = 124 },
  104. { char = "$", x1 = 190, y1 = 77, x2 = 250, y2 = 124 },
  105. { char = "%", x1 = 252, y1 = 77, x2 = 312, y2 = 124 },
  106. { char = "^", x1 = 4, y1 = 127, x2 = 64, y2 = 174 },
  107. { char = "&", x1 = 66, y1 = 127, x2 = 126, y2 = 174 },
  108. { char = "*", x1 = 128, y1 = 127, x2 = 188, y2 = 174 },
  109. { char = "(", x1 = 190, y1 = 127, x2 = 250, y2 = 174 },
  110. { char = ")", x1 = 252, y1 = 127, x2 = 312, y2 = 174 },
  111. { char = "-", x1 = 4, y1 = 177, x2 = 64, y2 = 224 },
  112. { char = "_", x1 = 66, y1 = 177, x2 = 126, y2 = 224 },
  113. { char = "+", x1 = 128, y1 = 177, x2 = 188, y2 = 224 },
  114. { char = "=", x1 = 190, y1 = 177, x2 = 250, y2 = 224 },
  115. { char = "{", x1 = 252, y1 = 177, x2 = 312, y2 = 224 },
  116. { char = "}", x1 = 4, y1 = 227, x2 = 64, y2 = 274 },
  117. { char = "[", x1 = 66, y1 = 227, x2 = 126, y2 = 274 },
  118. { char = "]", x1 = 128, y1 = 227, x2 = 188, y2 = 274 },
  119. { char = "|", x1 = 190, y1 = 227, x2 = 250, y2 = 274 },
  120. { char = string.char(92), x1 = 252, y1 = 227, x2 = 312, y2 = 274 }, --\
  121. { char = ":", x1 = 4, y1 = 277, x2 = 64, y2 = 324 },
  122. { char = ";", x1 = 66, y1 = 277, x2 = 126, y2 = 324 },
  123. { char = "\"", x1 = 128, y1 = 277, x2 = 188, y2 = 324 },
  124. { char = "'", x1 = 190, y1 = 277, x2 = 250, y2 = 324 },
  125. { char = "<", x1 = 252, y1 = 277, x2 = 312, y2 = 324 },
  126. { char = ">", x1 = 4, y1 = 327, x2 = 64, y2 = 374 },
  127. { char = "", x1 = 66, y1 = 327, x2 = 126, y2 = 374 },
  128. { char = ".", x1 = 128, y1 = 327, x2 = 188, y2 = 374 },
  129. { char = "?", x1 = 190, y1 = 327, x2 = 250, y2 = 374 },
  130. { char = "/", x1 = 252, y1 = 327, x2 = 312, y2 = 374 },
  131. { char = "~", x1 = 4, y1 = 377, x2 = 64, y2 = 424 },
  132. { char = "`", x1 = 66, y1 = 377, x2 = 126, y2 = 424 },
  133. { char = "¥", x1 = 128, y1 = 377, x2 = 188, y2 = 424 },
  134. { char = "€", x1 = 190, y1 = 377, x2 = 250, y2 = 424 },
  135. { char = "£", x1 = 252, y1 = 377, x2 = 312, y2 = 424 },
  136. { char = "§", x1 = 4, y1 = 427, x2 = 64, y2 = 474 },
  137. }
  138. }
  139. -- 初始化字体指针
  140. local function init_font()
  141. -- 尝试获取可用的中文字体
  142. if lcd.font_opposansm16_chinese then
  143. font_ptr = lcd.font_opposansm16_chinese
  144. elseif lcd.font_opposansm16 then
  145. font_ptr = lcd.font_opposansm16
  146. elseif lcd.font_opposanss16 then
  147. font_ptr = lcd.font_opposanss16
  148. else
  149. -- 如果没有中文字体,使用默认字体
  150. font_ptr = lcd.font_default
  151. end
  152. end
  153. -- 刷新输入框文本 - 直接显示文字
  154. local function refresh_input_text()
  155. if not text_dirty then return end
  156. -- 只显示最后20位内容
  157. display_text = string.sub(input_text, -25)
  158. -- 处理密文显示
  159. if is_cipher and input_text ~= "" then
  160. if mcu.ticks() - last_cipher_time < 1000 then
  161. -- 显示明文1秒
  162. else
  163. display_text = string.rep("*", #display_text)
  164. end
  165. end
  166. -- 添加省略号如果文本过长
  167. if #display_text > 20 then
  168. display_text = "..." .. string.sub(display_text, -12)
  169. end
  170. -- 设置文本框文本颜色
  171. lcd.setColor(0xFFFF,0x0000) --白底黑字
  172. -- 绘制文本(使用字体指针)
  173. -- lcd.setFont(font_ptr)
  174. lcd.fill(19,14,228,52,0xFFFFF)
  175. lcd.drawStr(TEXT_X, TEXT_Y, display_text)
  176. -- 更新上次文本长度
  177. last_text_length = #input_text
  178. text_dirty = false
  179. -- 刷新屏幕
  180. lcd.flush()
  181. end
  182. -- 检查文本长度是否变化
  183. local function check_text_length()
  184. if #input_text ~= last_text_length then
  185. text_dirty = true
  186. end
  187. return text_dirty
  188. end
  189. -- 初始化输入法
  190. function input_method.init(is_cipher_input, previous_fun, callback)
  191. submit_callback = callback -- 保存到模块级变量
  192. -- 初始化字体
  193. -- init_font()
  194. input_state = "LOWERCASE"
  195. input_text = ""
  196. display_text = ""
  197. --_cipher = is_cipher_input
  198. last_cipher_time = 0
  199. prev_fun = previous_fun
  200. is_active = true
  201. text_dirty = true
  202. last_text_length = 0
  203. -- 清除整个屏幕
  204. lcd.clear()
  205. lcd.flush()
  206. -- 显示键盘图片(覆盖整个屏幕)
  207. if input_state == "LOWERCASE" then
  208. lcd.showImage(0, 0, "/luadb/Lkeyboard.jpg")
  209. elseif input_state == "UPPERCASE" then
  210. lcd.showImage(0, 0, "/luadb/Ukeyboard.jpg")
  211. else
  212. lcd.showImage(0, 0, "/luadb/Skeyboard.jpg")
  213. end
  214. lcd.flush()
  215. -- 刷新输入文本
  216. refresh_input_text()
  217. return true
  218. end
  219. -- 切换键盘布局
  220. local function switch_keyboard_layout()
  221. -- 清除整个屏幕
  222. lcd.clear()
  223. lcd.flush()
  224. -- 显示对应键盘图片
  225. if input_state == "LOWERCASE" then
  226. lcd.showImage(0, 0, "/luadb/Lkeyboard.jpg")
  227. elseif input_state == "UPPERCASE" then
  228. lcd.showImage(0, 0, "/luadb/Ukeyboard.jpg")
  229. else
  230. lcd.showImage(0, 0, "/luadb/Skeyboard.jpg")
  231. end
  232. lcd.flush()
  233. -- 刷新输入文本
  234. text_dirty = true
  235. refresh_input_text()
  236. end
  237. -- 处理触摸事件
  238. function input_method.process_touch(x, y)
  239. if not is_active then return end
  240. -- 提交按钮
  241. if x >= 244 and x <= 304 and y >= 8 and y <= 58 then
  242. is_active = false
  243. if type(submit_callback) == "function" then -- 安全检查
  244. submit_callback(input_text) -- 调用回调
  245. else
  246. log.warn("submit_callback is not a function")
  247. end
  248. return
  249. end
  250. -- 删除按钮
  251. if x >= 252 and x <= 312 and y >= 427 and y <= 474 then
  252. if #input_text > 0 then
  253. input_text = string.sub(input_text, 1, -2)
  254. last_cipher_time = mcu.ticks()
  255. text_dirty = true
  256. refresh_input_text() -- 立即刷新文本
  257. end
  258. -- 切换大小写
  259. elseif x >= 66 and x <= 126 and y >= 427 and y <= 474 then
  260. if input_state == "LOWERCASE" then
  261. input_state = "UPPERCASE"
  262. elseif input_state == "UPPERCASE" then
  263. input_state = "LOWERCASE"
  264. elseif input_state == "SYMBOL" then
  265. input_state = "UPPERCASE"
  266. end
  267. switch_keyboard_layout() -- 切换键盘布局并刷新文本
  268. -- 切换符号
  269. elseif x >= 128 and x <= 188 and y >= 427 and y <= 474 then
  270. if input_state == "LOWERCASE" or input_state == "UPPERCASE" then
  271. input_state = "SYMBOL"
  272. elseif input_state == "SYMBOL" then
  273. input_state = "UPPERCASE"
  274. end
  275. switch_keyboard_layout() -- 切换键盘布局并刷新文本
  276. -- 空格键
  277. elseif x >= 190 and x <= 250 and y >= 427 and y <= 474 then
  278. input_text = input_text .. " "
  279. last_cipher_time = mcu.ticks()
  280. check_text_length() -- 检查文本长度是否变化
  281. refresh_input_text() -- 立即刷新文本
  282. else
  283. -- 查找按键映射
  284. for _, key in ipairs(key_mappings[input_state]) do
  285. if x >= key.x1 and x <= key.x2 and y >= key.y1 and y <= key.y2 then
  286. input_text = input_text .. key.char
  287. last_cipher_time = mcu.ticks()
  288. check_text_length() -- 检查文本长度是否变化
  289. refresh_input_text() -- 立即刷新文本
  290. break
  291. end
  292. end
  293. end
  294. end
  295. -- 添加定期刷新函数,确保文本显示正常
  296. function input_method.periodic_refresh()
  297. if is_active then
  298. -- 检查文本长度是否变化
  299. if #input_text ~= last_text_length then
  300. text_dirty = true
  301. end
  302. -- 检查密文状态
  303. if is_cipher and input_text ~= "" then
  304. if mcu.ticks() - last_cipher_time >= 1000 then
  305. text_dirty = true
  306. end
  307. end
  308. -- 刷新文本
  309. if text_dirty then
  310. refresh_input_text()
  311. end
  312. end
  313. end
  314. -- 检查输入法是否激活
  315. function input_method.is_active()
  316. return is_active
  317. end
  318. return input_method