simple_notepad_6.e 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. class SIMPLE_NOTEPAD_6
  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. multitext_caret_cb (m: IUP_TEXT; lin, col, pos: INTEGER): STRING
  64. local
  65. str: STRING
  66. do
  67. if attached {IUP_LABEL} m.get_dialog_child("STATUSBAR") as lbl_statusbar then
  68. str := "Line "
  69. str.append(lin.out)
  70. str.append(", Col ")
  71. str.append(col.out)
  72. lbl_statusbar.set_title(str)
  73. end
  74. Result := "IUP_DEFAULT"
  75. end
  76. item_open_action_cb (widget: IUP_MENU_ITEM): STRING
  77. -- Menu open action
  78. do
  79. Result := open_dialog
  80. end
  81. button_open_action_cb (widget: IUP_BUTTON): STRING
  82. -- Button open action
  83. do
  84. Result := open_dialog
  85. end
  86. open_dialog: STRING
  87. local
  88. status: INTEGER
  89. rv, name, text: STRING
  90. fd: IUP_FILE_DIALOG
  91. do
  92. create fd.file_dialog
  93. fd.set_dialog_type("OPEN")
  94. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  95. fd.set_title("Select a text file")
  96. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  97. if rv.is_equal("IUP_NOERROR") then
  98. status := fd.get_status
  99. if status.is_equal(0) then
  100. name := fd.get_value
  101. text := read_file(name)
  102. ml.set_value(text)
  103. end
  104. end
  105. fd.destroy
  106. Result := "IUP_DEFAULT"
  107. end
  108. item_save_as_action_cb (widget: IUP_MENU_ITEM): STRING
  109. -- Menu save as action
  110. do
  111. Result := save_as_dialog
  112. end
  113. button_save_as_action_cb (widget: IUP_BUTTON): STRING
  114. -- Buttib save as action
  115. do
  116. Result := save_as_dialog
  117. end
  118. save_as_dialog: STRING
  119. local
  120. status: INTEGER
  121. rv, name, text: STRING
  122. fd: IUP_FILE_DIALOG
  123. do
  124. create fd.file_dialog
  125. fd.set_dialog_type("SAVE")
  126. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  127. fd.set_title("Select a text file")
  128. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  129. if rv.is_equal("IUP_NOERROR") then
  130. status := fd.get_status
  131. if not status.is_equal(-1) then
  132. name := fd.get_value
  133. text := ml.get_value
  134. write_file(name, text)
  135. end
  136. end
  137. fd.destroy
  138. Result := "IUP_DEFAULT"
  139. end
  140. item_font_action_cb (widget: IUP_MENU_ITEM): STRING
  141. local
  142. status: INTEGER
  143. rv, ft, selected: STRING
  144. fd: IUP_FONT_DIALOG
  145. do
  146. create fd.font_dialog
  147. ft := ml.get_font
  148. fd.set_value(ft)
  149. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  150. if rv.is_equal("IUP_NOERROR") then
  151. status := fd.get_status
  152. if status.is_equal(1) then
  153. selected := fd.get_value
  154. ml.set_font(selected)
  155. end
  156. end
  157. fd.destroy
  158. Result := "IUP_DEFAULT"
  159. end
  160. item_about_action_cb (widget: IUP_MENU_ITEM): STRING
  161. local
  162. ms: IUP_MESSAGE
  163. do
  164. create ms.message("About"," Simple Notepad%N%NAuthors:%N Gustavo Lyrio%N Antonio Scuri")
  165. Result := "IUP_DEFAULT"
  166. end
  167. item_exit_action_cb (widget: IUP_MENU_ITEM): STRING
  168. do
  169. Result := "IUP_CLOSE"
  170. end
  171. goto_ok_action_cb(widget: IUP_BUTTON): STRING
  172. local
  173. line_count, line: INTEGER
  174. ms: IUP_MESSAGE
  175. do
  176. if attached widget.get_dialog as dlg and
  177. attached {IUP_TEXT} widget.get_dialog_child("LINE_TEXT") as txt then
  178. line_count := widget.get_attribute_integer("TEXT_LINECOUNT")
  179. line := txt.get_value.to_integer
  180. if line < 1 or line >= line_count then
  181. create ms.message("Error", "Invalid line number.")
  182. Result := "IUP_DEFAULT"
  183. else
  184. dlg.set_attribute_integer("STATUS", 1)
  185. Result := "IUP_CLOSE"
  186. end
  187. end
  188. Result := "IUP_CLOSE"
  189. end
  190. goto_cancel_action_cb(widget: IUP_BUTTON): STRING
  191. do
  192. if attached {IUP_DIALOG} widget.get_dialog as dlg then
  193. dlg.set_attribute_integer("STATUS", 0)
  194. end
  195. Result := "IUP_CLOSE"
  196. end
  197. item_goto_action_cb (widget: IUP_MENU_ITEM): STRING
  198. local
  199. dlg: IUP_DIALOG
  200. vbox: IUP_VBOX
  201. hbox: IUP_HBOX
  202. bt_ok, bt_cancel: IUP_BUTTON
  203. f: IUP_FILL
  204. lbl: IUP_LABEL
  205. txt: IUP_TEXT
  206. str, s: STRING
  207. line_count, line, pos: INTEGER
  208. pf: IUP_WIDGET
  209. do
  210. line_count := ml.get_line_count
  211. str := "Line Number [1-"
  212. str.append_string(ml.get_line_count.out)
  213. str.append_string("]:")
  214. create lbl.label(str)
  215. create txt.text
  216. txt.set_mask("IUP_MASK_UINT") -- unsigned integer numbers only
  217. txt.set_name("LINE_TEXT")
  218. txt.set_visible_columns(20)
  219. create bt_ok.button("OK")
  220. bt_ok.set_attribute_integer("TEXT_LINECOUNT", line_count)
  221. bt_ok.set_padding(10, 2)
  222. bt_ok.set_cb_action(agent goto_ok_action_cb)
  223. create bt_cancel.button("Cancel")
  224. bt_cancel.set_padding(10, 2)
  225. bt_cancel.set_cb_action(agent goto_cancel_action_cb)
  226. create f.fill
  227. create hbox.hbox({ARRAY[IUP_WIDGET]} << f, bt_ok, bt_cancel >>)
  228. hbox.normalize_size_horizontal
  229. create vbox.vbox({ARRAY[IUP_WIDGET]} << lbl, txt, hbox >>)
  230. vbox.set_margin(10, 10)
  231. vbox.set_gap(5)
  232. create dlg.dialog(vbox)
  233. dlg.set_title("Go To Line")
  234. dlg.set_modal_dialog_frame(True)
  235. dlg.set_default_enter_widget(bt_ok)
  236. dlg.set_default_escape_widget(bt_cancel)
  237. if attached widget.get_dialog as main_dlg then
  238. dlg.set_parent_dialog_widget(main_dlg)
  239. end
  240. s := dlg.popup_predefined_xy ("IUP_CENTERPARENT", "IUP_CENTERPARENT")
  241. if s.is_equal("IUP_NOERROR") and dlg.get_attribute_integer("STATUS").is_equal(1) then
  242. line := txt.get_value.to_integer
  243. pos := ml.text_convert_lin_col_to_pos(line, 0)
  244. ml.set_multiline_caret_pos(pos)
  245. ml.scroll_to_pos(pos)
  246. pf := ml.set_focus
  247. end
  248. dlg.destroy
  249. Result := "IUP_DEFAULT"
  250. end
  251. find_next_action_cb (widget: IUP_BUTTON): STRING
  252. local
  253. str, str_to_find: STRING
  254. casesensitive: BOOLEAN
  255. find_pos, pos, end_pos: INTEGER
  256. tup: TUPLE[INTEGER, INTEGER]
  257. pw: IUP_WIDGET
  258. ms: IUP_MESSAGE
  259. do
  260. str := ml.get_value
  261. find_pos := ml.get_attribute_integer("FIND_POS")
  262. if find_pos = 0 then
  263. find_pos := 1
  264. end
  265. if attached {IUP_TEXT} widget.get_dialog_child("FIND_TEXT") as txt then
  266. str_to_find := txt.get_value
  267. if attached {IUP_TOGGLE} widget.get_dialog_child("FIND_CASE") as find_case then
  268. casesensitive := find_case.is_off
  269. -- Rest 1 since the string start at 1, but multiline position
  270. -- start at 0.
  271. pos := str_find(str, str_to_find, casesensitive, find_pos) - 1
  272. if pos < 0 and find_pos > 0 then
  273. -- try again from the start
  274. pos := str_find(str, str_to_find, casesensitive, 1) - 1
  275. end
  276. if pos > 0 then
  277. end_pos := pos + str_to_find.count
  278. ml.set_attribute_integer("FIND_POS", end_pos)
  279. pw := ml.set_focus
  280. ml.set_multiline_selection_pos(pos, end_pos)
  281. tup := ml.text_convert_pos_to_lin_col(pos)
  282. -- position at col=0, just scroll lines
  283. pos := ml.text_convert_lin_col_to_pos(tup.integer_32_item(1), 0)
  284. ml.scroll_to_pos(pos)
  285. else
  286. create ms.message("Warning", "Text not found.")
  287. end
  288. end
  289. end
  290. Result := "IUP_DEFAULT"
  291. end
  292. find_close_action_cb (widget: IUP_BUTTON): STRING
  293. do
  294. if attached widget.get_dialog as dlg then
  295. dlg.hide
  296. end
  297. Result := "IUP_DEFAULT"
  298. end
  299. item_find_action_cb (widget: IUP_MENU_ITEM): STRING
  300. -- Find action from menu.
  301. do
  302. if attached widget.get_dialog as main_dlg then
  303. Result := find_dialog (main_dlg)
  304. else
  305. Result := "IUP_DEFAULT"
  306. end
  307. end
  308. button_find_action_cb (widget: IUP_BUTTON): STRING
  309. -- Find action from button.
  310. do
  311. if attached widget.get_dialog as main_dlg then
  312. Result := find_dialog (main_dlg)
  313. else
  314. Result := "IUP_DEFAULT"
  315. end
  316. end
  317. find_dialog (main_dlg: IUP_DIALOG): STRING
  318. local
  319. dlg: IUP_DIALOG
  320. lbl: IUP_LABEL
  321. txt: IUP_TEXT
  322. bt_next, bt_close: IUP_BUTTON
  323. find_case: IUP_TOGGLE
  324. f: IUP_FILL
  325. hbox: IUP_HBOX
  326. vbox: IUP_VBOX
  327. s: STRING
  328. do
  329. if attached {IUP_DIALOG} main_dlg.get_attribute_widget("FIND_DIALOG") as find_dlg then
  330. dlg := find_dlg
  331. else
  332. create lbl.label("Find What:")
  333. create txt.text
  334. txt.set_name("FIND_TEXT")
  335. txt.set_visible_columns(20)
  336. create find_case.toggle("Case Sensitive")
  337. find_case.set_name("FIND_CASE")
  338. create bt_next.button("Find Next")
  339. bt_next.set_padding(10, 2)
  340. bt_next.set_cb_action(agent find_next_action_cb)
  341. create bt_close.button("Close")
  342. bt_close.set_padding(10, 2)
  343. bt_close.set_cb_action(agent find_close_action_cb)
  344. create f.fill
  345. create hbox.hbox({ARRAY[IUP_WIDGET]} << f, bt_next, bt_close >>)
  346. hbox.normalize_size_horizontal
  347. create vbox.vbox({ARRAY[IUP_WIDGET]} << lbl, txt, find_case, hbox >>)
  348. vbox.set_margin(10, 10)
  349. vbox.set_gap(10)
  350. create dlg.dialog(vbox)
  351. dlg.set_title("Find")
  352. dlg.set_modal_dialog_frame(True)
  353. dlg.set_default_enter_widget(bt_next)
  354. dlg.set_default_escape_widget(bt_close)
  355. dlg.set_parent_dialog_widget(main_dlg)
  356. -- Save the dialog to reuse it
  357. main_dlg.set_attribute_widget("FIND_DIALOG", dlg)
  358. end
  359. -- centerparent first time, next time reuse the last position
  360. s := dlg.show_predefined_xy("IUP_CURRENT", "IUP_CURRENT")
  361. Result := "IUP_DEFAULT"
  362. end
  363. key_pressed (dlg: IUP_DIALOG; k: INTEGER): STRING
  364. do
  365. if k.is_equal(iup_open.x_key_ctrl('O')) then
  366. Result := open_dialog
  367. elseif k.is_equal(iup_open.x_key_ctrl('S')) then
  368. Result := save_as_dialog
  369. elseif k.is_equal(iup_open.x_key_ctrl('F')) then
  370. Result := find_dialog(dlg)
  371. elseif k.is_equal(iup_open.x_key_ctrl('G')) and
  372. attached {IUP_MENU_ITEM} dlg.get_dialog_child("ITEM_GOTO") as item then
  373. Result := item_goto_action_cb(item)
  374. else
  375. Result := "IUP_DEFAULT"
  376. end
  377. end
  378. --********************************** Make *****************************************
  379. make
  380. local
  381. i: STRING
  382. gui: IUP
  383. v: IUP_VBOX
  384. w: IUP_DIALOG
  385. item_exit, item_open, item_save_as, item_font, item_about: IUP_MENU_ITEM
  386. item_find, item_goto: IUP_MENU_ITEM
  387. sep: IUP_MENU_SEPARATOR
  388. file_menu, edit_menu, format_menu, help_menu, menu: IUP_MENU
  389. sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help: IUP_SUBMENU
  390. btn_open, btn_save, btn_find: IUP_BUTTON
  391. lbl_statusbar, toolbar_sep: IUP_LABEL
  392. toolbar_hb: IUP_HBOX
  393. do
  394. gui := iup_open
  395. gui.load_images
  396. create ml.multiline
  397. ml.expand_both_directions
  398. ml.set_cb_caret(agent multitext_caret_cb)
  399. create item_open.item("&Open... %TCtrl+O")
  400. item_open.set_hide_mark(True)
  401. item_open.set_cb_action(agent item_open_action_cb)
  402. create btn_open.button("")
  403. btn_open.set_image("IUP_FileOpen")
  404. btn_open.set_flat(True)
  405. btn_open.set_can_focus(False)
  406. btn_open.set_tip("Open (Ctrl+O)")
  407. btn_open.set_cb_action(agent button_open_action_cb)
  408. create item_save_as.item("Save &As...%TCtrl+S")
  409. item_save_as.set_hide_mark(True)
  410. item_save_as.set_cb_action(agent item_save_as_action_cb)
  411. create btn_save.button("")
  412. btn_save.set_image("IUP_FileSave")
  413. btn_save.set_flat(True)
  414. btn_save.set_can_focus(False)
  415. btn_save.set_tip("Save (Ctrl+S)")
  416. btn_save.set_cb_action(agent button_save_as_action_cb)
  417. create item_exit.item("E&xit")
  418. item_exit.set_hide_mark(True)
  419. item_exit.set_cb_action(agent item_exit_action_cb)
  420. create item_find.item("&Find...%TCtrl+F")
  421. item_find.set_hide_mark(True)
  422. item_find.set_cb_action(agent item_find_action_cb)
  423. create btn_find.button("")
  424. btn_find.set_image("IUP_EditFind")
  425. btn_find.set_flat(True)
  426. btn_find.set_can_focus(False)
  427. btn_find.set_tip("Find (Ctrl+F)")
  428. btn_find.set_cb_action(agent button_find_action_cb)
  429. create item_goto.item("&Go To...%TCtrl+G")
  430. item_goto.set_hide_mark(True)
  431. item_goto.set_name("ITEM_GOTO")
  432. item_goto.set_cb_action(agent item_goto_action_cb)
  433. create item_font.item("&Font...")
  434. item_font.set_hide_mark(True)
  435. item_font.set_cb_action(agent item_font_action_cb)
  436. create item_about.item("&About...")
  437. item_about.set_hide_mark(True)
  438. item_about.set_cb_action(agent item_about_action_cb)
  439. create sep.separator
  440. create toolbar_sep.label_empty
  441. toolbar_sep.set_vertical_separator
  442. create file_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_open, item_save_as, sep, item_exit >>)
  443. create edit_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_find, item_goto >>)
  444. create format_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_font >>)
  445. create help_menu.menu({ARRAY[IUP_MENU_ELEMENT]} << item_about >>)
  446. create sub_menu_file.submenu("&File", file_menu)
  447. create sub_menu_edit.submenu("&Edit", edit_menu)
  448. create sub_menu_format.submenu("F&ormat", format_menu)
  449. create sub_menu_help.submenu("&Help", help_menu)
  450. create menu.menu({ARRAY[IUP_MENU_ELEMENT]} << sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help >>)
  451. create toolbar_hb.hbox({ARRAY[IUP_WIDGET]} << btn_open, btn_save, toolbar_sep, btn_find >>)
  452. toolbar_hb.set_margin(5, 5)
  453. toolbar_hb.set_gap(2)
  454. create lbl_statusbar.label("Lin 1, Col 1")
  455. lbl_statusbar.set_name("STATUSBAR")
  456. lbl_statusbar.expand_horizontal
  457. lbl_statusbar.set_padding(10, 5)
  458. create v.vbox({ARRAY[IUP_WIDGET]} << toolbar_hb, ml, lbl_statusbar >>)
  459. create w.dialog(v)
  460. w.set_menu_widget(menu)
  461. w.set_title("Simple Notepad")
  462. w.set_predefined_size("HALF", "HALF")
  463. w.set_cb_k_any(agent key_pressed)
  464. -- parent for some pre-defined dialogs in callbak functions
  465. gui.set_global_parent_dialog_widget(w)
  466. i := w.show_predefined_xy("IUP_CENTER", "IUP_CENTER")
  467. w.set_user_size(0, 0)
  468. gui.main_loop
  469. gui.close
  470. end
  471. end