simple_notepad_4.e 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. class SIMPLE_NOTEPAD_4
  2. inherit
  3. IUP_INTERFACE
  4. create {ANY}
  5. make
  6. feature {ANY}
  7. ml: IUP_MULTILINE
  8. str_find (str, str_to_find: STRING; casesensitive: BOOLEAN; pos: INTEGER): INTEGER
  9. do
  10. if str.count.is_equal(0) or str_to_find.count.is_equal(0) then
  11. Result := -1
  12. elseif casesensitive then
  13. str.to_lower
  14. str_to_find.to_lower
  15. end
  16. Result := str.substring_index(str_to_find, pos)
  17. end
  18. read_file (file_name: STRING): STRING
  19. local
  20. tfr: PLAIN_TEXT_FILE
  21. str: STRING
  22. ms: IUP_MESSAGE
  23. do
  24. create str.make_empty
  25. create tfr.make_open_read(file_name)
  26. if tfr.is_access_readable then
  27. from
  28. tfr.read_line
  29. until
  30. tfr.end_of_file
  31. loop
  32. str.append(tfr.last_string)
  33. str.append_character('%N')
  34. tfr.read_line
  35. end
  36. str.append(tfr.last_string)
  37. tfr.close
  38. else
  39. str.append("Fail when reading from file: ")
  40. str.append(file_name)
  41. create ms.message("Error", str)
  42. end
  43. Result := str
  44. end
  45. write_file (file_name, text: STRING)
  46. local
  47. tfw: PLAIN_TEXT_FILE
  48. ms: IUP_MESSAGE
  49. str: STRING
  50. do
  51. create tfw.make_open_write(file_name)
  52. if tfw.is_access_writable then
  53. tfw.put_string(text)
  54. tfw.close
  55. else
  56. create str.make_empty
  57. str.append("Fail when writing to file: ")
  58. str.append(file_name)
  59. create ms.message("Error", str)
  60. end
  61. end
  62. --********************************** Callbacks *****************************************
  63. item_open_action_cb (widget: IUP_MENU_ITEM): STRING
  64. local
  65. status: INTEGER
  66. rv, name, text: STRING
  67. fd: IUP_FILE_DIALOG
  68. do
  69. create fd.file_dialog
  70. fd.set_dialog_type("OPEN")
  71. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  72. fd.set_title("Select a text file")
  73. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  74. if rv.is_equal("IUP_NOERROR") then
  75. status := fd.get_status
  76. if status.is_equal(0) then
  77. name := fd.get_value
  78. text := read_file(name)
  79. ml.set_value(text)
  80. end
  81. end
  82. fd.destroy
  83. Result := "IUP_DEFAULT"
  84. end
  85. item_save_as_action_cb (widget: IUP_MENU_ITEM): STRING
  86. local
  87. status: INTEGER
  88. rv, name, text: STRING
  89. fd: IUP_FILE_DIALOG
  90. do
  91. create fd.file_dialog
  92. fd.set_dialog_type("SAVE")
  93. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  94. fd.set_title("Select a text file")
  95. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  96. if rv.is_equal("IUP_NOERROR") then
  97. status := fd.get_status
  98. if not status.is_equal(-1) then
  99. name := fd.get_value
  100. text := ml.get_value
  101. write_file(name, text)
  102. end
  103. end
  104. fd.destroy
  105. Result := "IUP_DEFAULT"
  106. end
  107. item_font_action_cb (widget: IUP_MENU_ITEM): STRING
  108. local
  109. status: INTEGER
  110. rv, ft, selected: STRING
  111. fd: IUP_FONT_DIALOG
  112. do
  113. create fd.font_dialog
  114. ft := ml.get_font
  115. fd.set_value(ft)
  116. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  117. if rv.is_equal("IUP_NOERROR") then
  118. status := fd.get_status
  119. if status.is_equal(1) then
  120. selected := fd.get_value
  121. ml.set_font(selected)
  122. end
  123. end
  124. fd.destroy
  125. Result := "IUP_DEFAULT"
  126. end
  127. item_about_action_cb (widget: IUP_MENU_ITEM): STRING
  128. local
  129. ms: IUP_MESSAGE
  130. do
  131. create ms.message("About"," Simple Notepad%N%NAutors:%N Gustavo Lyrio%N Antonio Scuri")
  132. Result := "IUP_DEFAULT"
  133. end
  134. item_exit_action_cb (widget: IUP_MENU_ITEM): STRING
  135. do
  136. Result := "IUP_CLOSE"
  137. end
  138. goto_ok_action_cb(widget: IUP_BUTTON): STRING
  139. local
  140. line_count, line: INTEGER
  141. ms: IUP_MESSAGE
  142. do
  143. if attached widget.get_dialog as dlg and
  144. attached {IUP_TEXT} widget.get_dialog_child("LINE_TEXT") as txt then
  145. line_count := widget.get_attribute_integer("TEXT_LINECOUNT")
  146. line := txt.get_value.to_integer
  147. if line < 1 or line >= line_count then
  148. create ms.message("Error", "Invalid line number.")
  149. Result := "IUP_DEFAULT"
  150. else
  151. dlg.set_attribute_integer("STATUS", 1)
  152. Result := "IUP_CLOSE"
  153. end
  154. end
  155. Result := "IUP_CLOSE"
  156. end
  157. goto_cancel_action_cb(widget: IUP_BUTTON): STRING
  158. do
  159. if attached widget.get_dialog as dlg then
  160. dlg.set_attribute_integer("STATUS", 0)
  161. end
  162. Result := "IUP_CLOSE"
  163. end
  164. item_goto_action_cb (widget: IUP_MENU_ITEM): STRING
  165. local
  166. dlg: IUP_DIALOG
  167. vbox: IUP_VBOX
  168. hbox: IUP_HBOX
  169. bt_ok, bt_cancel: IUP_BUTTON
  170. f: IUP_FILL
  171. lbl: IUP_LABEL
  172. txt: IUP_TEXT
  173. str, s: STRING
  174. line_count, line, pos: INTEGER
  175. pf: IUP_WIDGET
  176. do
  177. line_count := ml.get_line_count
  178. str := "Line Number [1-"
  179. str.append_string(ml.get_line_count.out)
  180. str.append_string("]:")
  181. create lbl.label(str)
  182. create txt.text
  183. txt.set_mask("IUP_MASK_UINT") -- unsigned integer numbers only
  184. txt.set_name("LINE_TEXT")
  185. txt.set_visible_columns(20)
  186. create bt_ok.button("OK")
  187. bt_ok.set_attribute_integer("TEXT_LINECOUNT", line_count)
  188. bt_ok.set_padding(10, 2)
  189. bt_ok.set_cb_action(agent goto_ok_action_cb)
  190. create bt_cancel.button("Cancel")
  191. bt_cancel.set_padding(10, 2)
  192. bt_cancel.set_cb_action(agent goto_cancel_action_cb)
  193. create f.fill
  194. create hbox.hbox({ARRAY[IUP_WIDGET]} << f, bt_ok, bt_cancel >>)
  195. hbox.normalize_size_horizontal
  196. create vbox.vbox({ARRAY[IUP_WIDGET]} << lbl, txt, hbox >>)
  197. vbox.set_margin(10, 10)
  198. vbox.set_gap(5)
  199. create dlg.dialog(vbox)
  200. dlg.set_title("Go To Line")
  201. dlg.set_modal_dialog_frame(True)
  202. dlg.set_default_enter_widget(bt_ok)
  203. dlg.set_default_escape_widget(bt_cancel)
  204. if attached widget.get_dialog as main then
  205. dlg.set_parent_dialog_widget(main)
  206. end
  207. s := dlg.popup_predefined_xy ("IUP_CENTERPARENT", "IUP_CENTERPARENT")
  208. if s.is_equal("IUP_NOERROR") and dlg.get_attribute_integer("STATUS").is_equal(1) then
  209. line := txt.get_value.to_integer
  210. pos := ml.text_convert_lin_col_to_pos(line, 0)
  211. ml.set_multiline_caret_pos(pos)
  212. ml.scroll_to_pos(pos)
  213. pf := ml.set_focus
  214. end
  215. dlg.destroy
  216. Result := "IUP_DEFAULT"
  217. end
  218. find_next_action_cb (widget: IUP_BUTTON): STRING
  219. local
  220. str, str_to_find: STRING
  221. casesensitive: BOOLEAN
  222. find_pos, pos, end_pos: INTEGER
  223. tup: TUPLE[INTEGER, INTEGER]
  224. pw: IUP_WIDGET
  225. ms: IUP_MESSAGE
  226. do
  227. str := ml.get_value
  228. find_pos := ml.get_attribute_integer("FIND_POS")
  229. if find_pos = 0 then
  230. find_pos := 1
  231. end
  232. if attached {IUP_TEXT} widget.get_dialog_child("FIND_TEXT") as txt then
  233. str_to_find := txt.get_value
  234. if attached {IUP_TOGGLE} widget.get_dialog_child("FIND_CASE") as find_case then
  235. casesensitive := find_case.is_off
  236. -- Rest 1 since the string start at 1, but multiline position
  237. -- start at 0.
  238. pos := str_find(str, str_to_find, casesensitive, find_pos) - 1
  239. if pos < 0 and find_pos > 0 then
  240. -- try again from the start
  241. pos := str_find(str, str_to_find, casesensitive, 1) - 1
  242. end
  243. if pos > 0 then
  244. end_pos := pos + str_to_find.count
  245. ml.set_attribute_integer("FIND_POS", end_pos)
  246. pw := ml.set_focus
  247. ml.set_multiline_selection_pos(pos, end_pos)
  248. tup := ml.text_convert_pos_to_lin_col(pos)
  249. -- position at col=0, just scroll lines
  250. pos := ml.text_convert_lin_col_to_pos(tup.integer_32_item(1), 0)
  251. ml.scroll_to_pos(pos)
  252. else
  253. create ms.message("Warning", "Text not found.")
  254. end
  255. end
  256. end
  257. Result := "IUP_DEFAULT"
  258. end
  259. find_close_action_cb (widget: IUP_BUTTON): STRING
  260. do
  261. if attached widget.get_dialog as dlg then
  262. dlg.hide
  263. end
  264. Result := "IUP_DEFAULT"
  265. end
  266. item_find_action_cb (widget: IUP_MENU_ITEM): STRING
  267. local
  268. dlg: IUP_DIALOG
  269. lbl: IUP_LABEL
  270. txt: IUP_TEXT
  271. bt_next, bt_close: IUP_BUTTON
  272. find_case: IUP_TOGGLE
  273. f: IUP_FILL
  274. hbox: IUP_HBOX
  275. vbox: IUP_VBOX
  276. s: STRING
  277. do
  278. if attached {IUP_DIALOG} widget.get_attribute_widget("FIND_DIALOG") as find_dlg then
  279. dlg := find_dlg
  280. else
  281. create lbl.label("Find What:")
  282. create txt.text
  283. txt.set_name("FIND_TEXT")
  284. txt.set_visible_columns(20)
  285. create find_case.toggle("Case Sensitive")
  286. find_case.set_name("FIND_CASE")
  287. create bt_next.button("Find Next")
  288. bt_next.set_padding(10, 2)
  289. bt_next.set_cb_action(agent find_next_action_cb)
  290. create bt_close.button("Close")
  291. bt_close.set_padding(10, 2)
  292. bt_close.set_cb_action(agent find_close_action_cb)
  293. create f.fill
  294. create hbox.hbox({ARRAY[IUP_WIDGET]} << f, bt_next, bt_close >>)
  295. hbox.normalize_size_horizontal
  296. create vbox.vbox({ARRAY[IUP_WIDGET]} << lbl, txt, find_case, hbox >>)
  297. vbox.set_margin(10, 10)
  298. vbox.set_gap(10)
  299. create dlg.dialog(vbox)
  300. dlg.set_title("Find")
  301. dlg.set_modal_dialog_frame(True)
  302. dlg.set_default_enter_widget(bt_next)
  303. dlg.set_default_escape_widget(bt_close)
  304. if attached widget.get_dialog as main then
  305. dlg.set_parent_dialog_widget(main)
  306. end
  307. -- Save the dialog to reuse it
  308. widget.set_attribute_widget("FIND_DIALOG", dlg)
  309. end
  310. -- centerparent first time, next time reuse the last position
  311. s := dlg.show_predefined_xy("IUP_CURRENT", "IUP_CURRENT")
  312. Result := "IUP_DEFAULT"
  313. end
  314. --********************************** Make *****************************************
  315. make
  316. local
  317. i: STRING
  318. gui: IUP
  319. v: IUP_VBOX
  320. w: IUP_DIALOG
  321. item_exit, item_open, item_save_as, item_font, item_about: IUP_MENU_ITEM
  322. item_find, item_goto: IUP_MENU_ITEM
  323. sep: IUP_MENU_SEPARATOR
  324. file_menu, edit_menu, format_menu, help_menu, menu: IUP_MENU
  325. sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help: IUP_SUBMENU
  326. do
  327. gui := iup_open
  328. create ml.multiline
  329. ml.expand_both_directions
  330. create v.vbox({ARRAY[IUP_WIDGET]} << ml >>)
  331. create item_open.item("Open...")
  332. item_open.set_hide_mark(True)
  333. item_open.set_cb_action(agent item_open_action_cb(?))
  334. create item_save_as.item("Save As...")
  335. item_save_as.set_hide_mark(True)
  336. item_save_as.set_cb_action(agent item_save_as_action_cb(?))
  337. create item_exit.item("Exit")
  338. item_exit.set_hide_mark(True)
  339. item_exit.set_cb_action(agent item_exit_action_cb(?))
  340. create item_find.item("Find...")
  341. item_find.set_hide_mark(True)
  342. item_find.set_cb_action(agent item_find_action_cb(?))
  343. create item_goto.item("Go To...")
  344. item_goto.set_hide_mark(True)
  345. item_goto.set_cb_action(agent item_goto_action_cb(?))
  346. create item_font.item("Font...")
  347. item_font.set_hide_mark(True)
  348. item_font.set_cb_action(agent item_font_action_cb(?))
  349. create item_about.item("About...")
  350. item_about.set_hide_mark(True)
  351. item_about.set_cb_action(agent item_about_action_cb(?))
  352. create sep.separator
  353. create file_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_open, item_save_as, sep, item_exit >>)
  354. create edit_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_find, item_goto >>)
  355. create format_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_font >>)
  356. create help_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_about >>)
  357. create sub_menu_file.submenu("File", file_menu)
  358. create sub_menu_edit.submenu("Edit", edit_menu)
  359. create sub_menu_format.submenu("Format", format_menu)
  360. create sub_menu_help.submenu("Help", help_menu)
  361. create menu.menu({ARRAY[IUP_MENU_ELEMENT]} << sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help >>)
  362. create w.dialog(v)
  363. w.set_menu_widget(menu)
  364. w.set_title("Simple Notepad")
  365. w.set_predefined_size("HALF", "HALF")
  366. -- parent for pre-defined dialogs in callbak functions
  367. gui.set_global_parent_dialog_widget(w)
  368. i := w.show_predefined_xy("IUP_CENTER", "IUP_CENTER")
  369. w.set_user_size(0, 0)
  370. gui.main_loop
  371. gui.close
  372. end
  373. end