simple_notepad_7.e 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. class SIMPLE_NOTEPAD_7
  2. insert
  3. IUP_INTERFACE
  4. create {ANY}
  5. make
  6. feature {ANY}
  7. ml: IUP_MULTILINE
  8. cfg: IUP_CONFIG
  9. str_find (str, str_to_find, casesensitive: STRING; pos: INTEGER): INTEGER
  10. do
  11. if str.count.is_equal(0) or str_to_find.count.is_equal(0) then
  12. Result := -1
  13. elseif casesensitive.is_equal("OFF") then
  14. str.to_lower
  15. str_to_find.to_lower
  16. end
  17. Result := str.substring_index(str_to_find, pos)
  18. end
  19. read_file (file_name: STRING): STRING
  20. local
  21. tfr: TEXT_FILE_READ
  22. str: STRING
  23. ms: IUP_MESSAGE
  24. do
  25. create str.make_empty
  26. create tfr.connect_to(file_name)
  27. if tfr.is_connected then
  28. from
  29. tfr.read_line
  30. until
  31. tfr.end_of_input
  32. loop
  33. str.append(tfr.last_string)
  34. str.append_character('%N')
  35. tfr.read_line
  36. end
  37. str.append(tfr.last_string)
  38. tfr.disconnect
  39. else
  40. str.append("Fail when reading from file: ")
  41. str.append(file_name)
  42. create ms.message("Error", str)
  43. end
  44. Result := str
  45. end
  46. write_file (file_name, text: STRING): INTEGER
  47. local
  48. tfw: TEXT_FILE_WRITE
  49. ms: IUP_MESSAGE
  50. str: STRING
  51. do
  52. create tfw.connect_to(file_name)
  53. if tfw.is_connected then
  54. tfw.put_string(text)
  55. tfw.disconnect
  56. Result := 1
  57. else
  58. str.make_empty
  59. str.append("Fail when writing to file: ")
  60. str.append(file_name)
  61. create ms.message("Error", str)
  62. Result := 0
  63. end
  64. end
  65. --********************************** Callbacks *****************************************
  66. item_recent_cb (c: IUP_CONFIG): STRING
  67. local
  68. text: STRING
  69. do
  70. text := read_file(c.get_title)
  71. ml.set_value(text)
  72. Result := "IUP_DEFAULT"
  73. end
  74. config_recent_cb (c: IUP_CONFIG): STRING
  75. local
  76. file, text: STRING
  77. do
  78. file := c.get_title
  79. text := read_file(file)
  80. ml.set_value(text)
  81. Result := "IUP_DEFAULT"
  82. end
  83. multitext_caret_cb (m: IUP_TEXT; lin, col, pos: INTEGER): STRING
  84. local
  85. lbl_statusbar: IUP_LABEL
  86. str: STRING
  87. do
  88. if lbl_statusbar ?:= m.get_dialog_child("STATUSBAR") then
  89. lbl_statusbar ::= m.get_dialog_child("STATUSBAR")
  90. str := "Line "
  91. str.append(lin.to_string)
  92. str.append(", Col ")
  93. str.append(col.to_string)
  94. lbl_statusbar.set_title(str)
  95. end
  96. Result := "IUP_DEFAULT"
  97. end
  98. item_open_action_cb (widget: IUP_WIDGET): STRING
  99. local
  100. status: INTEGER
  101. rv, name, text: STRING
  102. fd: IUP_FILE_DIALOG
  103. do
  104. create fd.file_dialog
  105. fd.set_dialog_type("OPEN")
  106. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  107. fd.set_title("Select a text file")
  108. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  109. if rv.is_equal("IUP_NOERROR") then
  110. status := fd.get_status
  111. if status.is_equal(0) then
  112. name := fd.get_value
  113. text := read_file(name)
  114. cfg.update_recent_file_menu(name)
  115. ml.set_value(text)
  116. end
  117. end
  118. fd.destroy
  119. Result := "IUP_DEFAULT"
  120. end
  121. item_saveas_action_cb (widget: IUP_WIDGET): STRING
  122. local
  123. status, r: INTEGER
  124. rv, name, text: STRING
  125. fd: IUP_FILE_DIALOG
  126. do
  127. create fd.file_dialog
  128. fd.set_dialog_type("SAVE")
  129. fd.set_ext_filter("Text files|*.txt|All Files|*.*|")
  130. fd.set_title("Select a text file")
  131. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  132. if rv.is_equal("IUP_NOERROR") then
  133. status := fd.get_status
  134. if not status.is_equal(-1) then
  135. name := fd.get_value
  136. text := ml.get_value
  137. r := write_file(name, text)
  138. if r.is_equal(1) then
  139. cfg.update_recent_file_menu(name)
  140. end
  141. end
  142. end
  143. fd.destroy
  144. Result := "IUP_DEFAULT"
  145. end
  146. item_font_action_cb (widget: IUP_MENU_ITEM): STRING
  147. local
  148. status: INTEGER
  149. rv, ft, selected: STRING
  150. fd: IUP_FONT_DIALOG
  151. do
  152. create fd.font_dialog
  153. ft := ml.get_font
  154. fd.set_value(ft)
  155. rv := fd.popup_predefined_xy("IUP_CENTER", "IUP_CENTER")
  156. if rv.is_equal("IUP_NOERROR") then
  157. status := fd.get_status
  158. if status.is_equal(1) then
  159. selected := fd.get_value
  160. ml.set_font(selected)
  161. cfg.set_variable_string("MainWindow", "Font", selected)
  162. end
  163. end
  164. fd.destroy
  165. Result := "IUP_DEFAULT"
  166. end
  167. item_about_action_cb (widget: IUP_MENU_ITEM): STRING
  168. local
  169. ms: IUP_MESSAGE
  170. do
  171. create ms.message("About"," Simple Notepad%N%NAutors:%N Gustavo Lyrio%N Antonio Scuri")
  172. Result := "IUP_DEFAULT"
  173. end
  174. item_exit_action_cb (widget: IUP_MENU_ITEM): STRING
  175. local
  176. i: INTEGER
  177. d: IUP_DIALOG
  178. do
  179. d := widget.get_dialog
  180. cfg.save_dialog (d, "MainWindow")
  181. i := cfg.save
  182. cfg.destroy
  183. Result := "IUP_CLOSE"
  184. end
  185. close_dialog_cb (d: IUP_DIALOG): STRING
  186. local
  187. i: INTEGER
  188. do
  189. cfg.save_dialog (d, "MainWindow")
  190. i := cfg.save
  191. cfg.destroy
  192. Result := "IUP_CLOSE"
  193. end
  194. goto_ok_action_cb(widget: IUP_BUTTON): STRING
  195. local
  196. line_count, line: INTEGER
  197. txt: IUP_TEXT
  198. ms: IUP_MESSAGE
  199. do
  200. if txt ?:= widget.get_dialog_child("LINE_TEXT") then
  201. txt ::= widget.get_dialog_child("LINE_TEXT")
  202. line_count := widget.get_attribute_integer("TEXT_LINECOUNT")
  203. line := txt.get_value.to_integer
  204. if line < 1 and line >= line_count then
  205. create ms.message("Error", "Invalid line number.")
  206. Result := "IUP_DEFAULT"
  207. end
  208. widget.get_dialog.set_attribute_integer("STATUS", 1)
  209. Result := "IUP_CLOSE"
  210. end
  211. end
  212. goto_cancel_action_cb(widget: IUP_BUTTON): STRING
  213. do
  214. widget.get_dialog.set_attribute_integer("STATUS", 0)
  215. Result := "IUP_CLOSE"
  216. end
  217. item_goto_action_cb (widget: IUP_WIDGET): STRING
  218. local
  219. dlg, d: IUP_DIALOG
  220. vbox: IUP_VBOX
  221. hbox: IUP_HBOX
  222. bt_ok, bt_cancel: IUP_BUTTON
  223. f: IUP_FILL
  224. lbl: IUP_LABEL
  225. txt: IUP_TEXT
  226. str, s: STRING
  227. line_count, line, pos: INTEGER
  228. item: IUP_MENU_ITEM
  229. do
  230. line_count := ml.get_line_count
  231. str := "Line Number [1-"
  232. str.append_string(ml.get_line_count.to_string)
  233. str.append_string("]:")
  234. create lbl.label(str)
  235. create txt.text
  236. txt.set_mask("IUP_MASK_UINT") -- unsigned integer numbers only
  237. txt.set_name("LINE_TEXT")
  238. txt.set_visible_columns(20)
  239. create bt_ok.button("OK")
  240. bt_ok.set_attribute_integer("TEXT_LINECOUNT", line_count)
  241. bt_ok.set_padding(10, 2)
  242. bt_ok.set_cb_action(agent goto_ok_action_cb(?))
  243. create bt_cancel.button("Cancel")
  244. bt_cancel.set_padding(10, 2)
  245. bt_cancel.set_cb_action(agent goto_cancel_action_cb(?))
  246. create f.fill
  247. create hbox.hbox({ARRAY[IUP_WIDGET] 1, << f, bt_ok, bt_cancel >>})
  248. hbox.set_normalize_size("HORIZONTAL")
  249. create vbox.vbox({ARRAY[IUP_WIDGET] 1, << lbl, txt, hbox >>})
  250. vbox.set_margin(10, 10)
  251. vbox.set_gap(5)
  252. create dlg.dialog(vbox)
  253. dlg.set_title("Go To Line")
  254. dlg.set_modal_dialog_frame(True)
  255. dlg.set_default_enter_widget(bt_ok)
  256. dlg.set_default_escape_widget(bt_cancel)
  257. if {IUP_MENU_ITEM} ?:= widget then
  258. item ::= widget
  259. dlg.set_parent_dialog_widget(item.get_dialog)
  260. elseif {IUP_DIALOG} ?:= widget then
  261. d ::= widget
  262. dlg.set_parent_dialog_widget(d)
  263. end
  264. s := dlg.popup_predefined_xy ("IUP_CENTERPARENT", "IUP_CENTERPARENT")
  265. if s.is_equal("IUP_NOERROR") and dlg.get_attribute_integer("STATUS").is_equal(1) then
  266. line := txt.get_value.to_integer
  267. pos := ml.text_convert_lin_col_to_pos(line, 0)
  268. ml.set_multiline_caret_pos(pos)
  269. ml.scroll_to_pos(pos)
  270. end
  271. dlg.destroy
  272. Result := "IUP_DEFAULT"
  273. end
  274. find_next_action_cb (widget: IUP_BUTTON): STRING
  275. local
  276. str, str_to_find, casesensitive: STRING
  277. find_pos, pos, end_pos: INTEGER
  278. txt: IUP_TEXT
  279. find_case: IUP_TOGGLE
  280. tup: TUPLE[INTEGER, INTEGER]
  281. pw: IUP_WIDGET
  282. ms: IUP_MESSAGE
  283. do
  284. str := ml.get_value
  285. find_pos := ml.get_attribute_integer("FIND_POS")
  286. if find_pos = 0 then
  287. find_pos := 1
  288. end
  289. if txt ?:= widget.get_dialog_child("FIND_TEXT") then
  290. txt ::= widget.get_dialog_child("FIND_TEXT")
  291. str_to_find := txt.get_value
  292. if find_case ?:= widget.get_dialog_child("FIND_CASE") then
  293. find_case ::= widget.get_dialog_child("FIND_CASE")
  294. casesensitive := find_case.get_value
  295. -- Rest 1 since the string start at 1, but multiline position
  296. -- start at 0.
  297. pos := str_find(str, str_to_find, casesensitive, find_pos) - 1
  298. if pos < 0 and find_pos > 0 then
  299. -- try again from the start
  300. pos := str_find(str, str_to_find, casesensitive, 1) - 1
  301. end
  302. if pos > 0 then
  303. end_pos := pos + str_to_find.count
  304. ml.set_attribute_integer("FIND_POS", end_pos)
  305. pw := ml.set_focus
  306. ml.set_multiline_selection_pos(pos, end_pos)
  307. tup := ml.text_convert_pos_to_lin_col(pos)
  308. -- position at col=0, just scroll lines
  309. pos := ml.text_convert_lin_col_to_pos(tup.item_1, 0)
  310. ml.scroll_to_pos(pos)
  311. else
  312. create ms.message("Warning", "Text not found.")
  313. end
  314. end
  315. end
  316. Result := "IUP_DEFAULT"
  317. end
  318. find_close_action_cb (widget: IUP_BUTTON): STRING
  319. do
  320. widget.get_dialog.hide
  321. Result := "IUP_DEFAULT"
  322. end
  323. item_find_action_cb (widget: IUP_WIDGET): STRING
  324. local
  325. dlg, main_dlg: IUP_DIALOG
  326. lbl: IUP_LABEL
  327. txt: IUP_TEXT
  328. btn, bt_next, bt_close: IUP_BUTTON
  329. find_case: IUP_TOGGLE
  330. f: IUP_FILL
  331. hbox: IUP_HBOX
  332. vbox: IUP_VBOX
  333. s: STRING
  334. item: IUP_MENU_ITEM
  335. do
  336. if btn ?:= widget then
  337. btn ::= widget
  338. main_dlg := btn.get_dialog
  339. elseif item ?:= widget then
  340. item ::= widget
  341. main_dlg := item.get_dialog
  342. elseif main_dlg ?:= widget then
  343. main_dlg ::= widget
  344. end
  345. if dlg ?:= main_dlg.get_attribute_widget("FIND_DIALOG") then
  346. dlg ::= main_dlg.get_attribute_widget("FIND_DIALOG")
  347. end
  348. if dlg = Void then
  349. create lbl.label("Find What:")
  350. create txt.text
  351. txt.set_name("FIND_TEXT")
  352. txt.set_visible_columns(20)
  353. create find_case.toggle("Case Sensitive")
  354. find_case.set_name("FIND_CASE")
  355. create bt_next.button("Find Next")
  356. bt_next.set_padding(10, 2)
  357. bt_next.set_cb_action(agent find_next_action_cb(?))
  358. create bt_close.button("Close")
  359. bt_close.set_padding(10, 2)
  360. bt_close.set_cb_action(agent find_close_action_cb(?))
  361. create f.fill
  362. create hbox.hbox({ARRAY[IUP_WIDGET] 1, << f, bt_next, bt_close >>})
  363. hbox.set_normalize_size("HORIZONTAL")
  364. create vbox.vbox({ARRAY[IUP_WIDGET] 1, << lbl, txt, find_case, hbox >>})
  365. vbox.set_margin(10, 10)
  366. vbox.set_gap(10)
  367. create dlg.dialog(vbox)
  368. dlg.set_title("Find")
  369. dlg.set_modal_dialog_frame(True)
  370. dlg.set_default_enter_widget(bt_next)
  371. dlg.set_default_escape_widget(bt_close)
  372. dlg.set_parent_dialog_widget(main_dlg)
  373. -- Save the dialog to reuse it
  374. main_dlg.set_attribute_widget("FIND_DIALOG", dlg)
  375. end
  376. -- center parent first time, next time reuse the last position
  377. s := dlg.show_predefined_xy("IUP_CURRENT", "IUP_CURRENT")
  378. Result := "IUP_DEFAULT"
  379. end
  380. key_pressed (dlg: IUP_DIALOG; k: INTEGER): STRING
  381. do
  382. if k.is_equal(iup_open.x_key_ctrl('O')) then
  383. Result := item_open_action_cb(dlg)
  384. elseif k.is_equal(iup_open.x_key_ctrl('S')) then
  385. Result := item_saveas_action_cb(dlg)
  386. elseif k.is_equal(iup_open.x_key_ctrl('F')) then
  387. Result := item_find_action_cb(dlg)
  388. elseif k.is_equal(iup_open.x_key_ctrl('G')) then
  389. Result := item_goto_action_cb(dlg)
  390. else
  391. Result := "IUP_DEFAULT"
  392. end
  393. end
  394. --********************************** Make *****************************************
  395. make
  396. local
  397. i: STRING
  398. x: INTEGER
  399. gui: IUP
  400. v: IUP_VBOX
  401. w: IUP_DIALOG
  402. item_exit, item_open, item_saveas, item_font, item_about: IUP_MENU_ITEM
  403. item_find, item_goto: IUP_MENU_ITEM
  404. sep: IUP_MENU_SEPARATOR
  405. file_menu, edit_menu, format_menu, help_menu, menu, recent_menu: IUP_MENU
  406. sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help, sub_menu_recent: IUP_SUBMENU
  407. btn_open, btn_save, btn_find: IUP_BUTTON
  408. lbl_statusbar, toolbar_sep: IUP_LABEL
  409. toolbar_hb: IUP_HBOX
  410. do
  411. gui := iup_open
  412. gui.load_images
  413. create cfg.config
  414. cfg.set_app_name("simple_notepad")
  415. x := cfg.load
  416. create ml.multiline
  417. ml.set_expand("YES")
  418. ml.set_cb_caret(agent multitext_caret_cb(?,?,?,?))
  419. i := cfg.get_variable_string("MainWindow", "Font")
  420. if not i.is_empty then
  421. ml.set_font(i)
  422. end
  423. create item_open.item("&Open... %TCtrl+O")
  424. item_open.set_hide_mark(True)
  425. item_open.set_cb_action(agent item_open_action_cb(?))
  426. create btn_open.button("")
  427. btn_open.set_image("IUP_FileOpen")
  428. btn_open.set_flat(True)
  429. btn_open.set_can_focus(False)
  430. btn_open.set_tip("Open (Ctrl+O)")
  431. btn_open.set_cb_action(agent item_open_action_cb(?))
  432. create item_saveas.item("Save &As...%TCtrl+S")
  433. item_saveas.set_hide_mark(True)
  434. item_saveas.set_cb_action(agent item_saveas_action_cb(?))
  435. create btn_save.button("")
  436. btn_save.set_image("IUP_FileSave")
  437. btn_save.set_flat(True)
  438. btn_save.set_can_focus(False)
  439. btn_save.set_tip("Save (Ctrl+S)")
  440. btn_save.set_cb_action(agent item_saveas_action_cb(?))
  441. create item_exit.item("E&xit")
  442. item_exit.set_hide_mark(True)
  443. item_exit.set_cb_action(agent item_exit_action_cb(?))
  444. create item_find.item("&Find...%TCtrl+F")
  445. item_find.set_hide_mark(True)
  446. item_find.set_cb_action(agent item_find_action_cb(?))
  447. create btn_find.button("")
  448. btn_find.set_image("IUP_EditFind")
  449. btn_find.set_flat(True)
  450. btn_find.set_can_focus(False)
  451. btn_find.set_tip("Find (Ctrl+F)")
  452. btn_find.set_cb_action(agent item_find_action_cb(?))
  453. create item_goto.item("&Go To...%TCtrl+G")
  454. item_goto.set_hide_mark(True)
  455. item_goto.set_cb_action(agent item_goto_action_cb(?))
  456. create item_font.item("&Font...%TCtrl+F")
  457. item_font.set_hide_mark(True)
  458. item_font.set_cb_action(agent item_font_action_cb(?))
  459. create item_about.item("&About...")
  460. item_about.set_hide_mark(True)
  461. item_about.set_cb_action(agent item_about_action_cb(?))
  462. create sep.separator
  463. create toolbar_sep.label_empty
  464. toolbar_sep.set_vertical_separator
  465. create recent_menu.menu_empty
  466. create sub_menu_recent.submenu("Recent &Files", recent_menu)
  467. create file_menu.menu({ARRAY[IUP_MENU_ELEMENT] 1, << item_open, item_saveas, sep, sub_menu_recent, item_exit >>})
  468. create edit_menu.menu({ARRAY[IUP_MENU_ELEMENT] 1, << item_find, item_goto >>})
  469. create format_menu.menu({ARRAY[IUP_MENU_ELEMENT] 1, << item_font >>})
  470. create help_menu.menu({ARRAY[IUP_MENU_ELEMENT] 1, << item_about >>})
  471. create sub_menu_file.submenu("&File", file_menu)
  472. create sub_menu_edit.submenu("&Edit", edit_menu)
  473. create sub_menu_format.submenu("F&ormat", format_menu)
  474. create sub_menu_help.submenu("&Help", help_menu)
  475. create menu.menu({ARRAY[IUP_MENU_ELEMENT] 1, << sub_menu_file, sub_menu_edit, sub_menu_format, sub_menu_help >>})
  476. create toolbar_hb.hbox({ARRAY[IUP_WIDGET] 1, << btn_open, btn_save, toolbar_sep, btn_find >>})
  477. toolbar_hb.set_margin(5, 5)
  478. toolbar_hb.set_gap(2)
  479. create lbl_statusbar.label("Lin 1, Col 1")
  480. lbl_statusbar.set_name("STATUSBAR")
  481. lbl_statusbar.set_expand("HORIZONTAL")
  482. lbl_statusbar.set_padding(10, 5)
  483. create v.vbox({ARRAY[IUP_WIDGET] 1, << toolbar_hb, ml, lbl_statusbar >>})
  484. create w.dialog(v)
  485. w.set_menu_widget(menu)
  486. w.set_cb_k_any(agent key_pressed(?, ?))
  487. w.set_title("Simple Notepad")
  488. w.set_predefined_size("HALF", "HALF")
  489. -- parent for some pre-defined dialogs in callbak functions
  490. gui.set_global_parent_dialog_widget(w)
  491. w.set_user_size(0, 0)
  492. w.set_cb_close(agent close_dialog_cb(?))
  493. cfg.set_recent_file_menu(recent_menu, agent config_recent_cb(?), 10)
  494. cfg.show_dialog(w, "MainWindow")
  495. gui.main_loop
  496. gui.close
  497. end
  498. end