iup_file_dialog.e 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. class IUP_FILE_DIALOG
  2. -- Creates the File Dialog element. It is a predefined dialog for selecting
  3. -- files or a directory.
  4. --
  5. -- This a native pre-defined dialog that is not altered by IupSetLanguage.
  6. --
  7. -- In Windows, the FILE and the DIRECTORY attributes also accept strings
  8. -- containing "/" as path separators, but the VALUE attribute will always
  9. -- return strings using the "\" character.
  10. --
  11. -- In Windows, the dialog will be modal relative only to its parent or to the
  12. -- active dialog.
  13. --
  14. -- In Windows, when using UTF-8 strings (UTF8MODE=True), attributes that return
  15. -- file names are still using the current locale, because the standard file I/O
  16. -- functions, like fopen, use ANSI file names. To use UTF-8 filenames (that can
  17. -- be lately be converted to UTF-16) set the global attribute UTF8MODE_FILE to
  18. -- True. In a specific case, the application can set before popup, and unset
  19. -- after, so for just that call will return in UTF-8.
  20. --
  21. -- When saving a file, the overwrite check is done before the FILE_CB callback
  22. -- is called with status=OK. If the application wants to add an extension to
  23. -- the file name inside the FILE_CB callback when status=OK, then it must
  24. -- manually check if the file with the extension exits and asks the user if the
  25. -- file should be replaced, if not then the callback can set the FILE attribute
  26. -- and returns IUP_CONTINUE, so the file dialog will remain open and the user
  27. -- will have an opportunity to change the file name now that it contains the
  28. -- extension.
  29. inherit
  30. IUP_WIDGET
  31. redefine
  32. execute_help,
  33. execute_file,
  34. execute_button,
  35. execute_motion,
  36. execute_wheel
  37. end
  38. IUP_WIDGET_TITLE
  39. IUP_WIDGET_POPUP
  40. IUP_WIDGET_ICON
  41. IUP_WIDGET_PARENT_DIALOG
  42. create {ANY}
  43. file_dialog
  44. feature {ANY}
  45. file_dialog
  46. local
  47. a_file_dialog: POINTER
  48. do
  49. a_file_dialog := int_file_dialog
  50. set_widget(a_file_dialog)
  51. end
  52. -- Attributes
  53. set_allow_new (state: BOOLEAN)
  54. -- Indicates if non-existent file names are accepted. If equals "False"
  55. -- and the user specifies a non-existing file, an alert dialog is shown.
  56. -- Default: if the dialog is of type "OPEN", default is "False"; if the
  57. -- dialog is of type "SAVE", default is "True". Not used when
  58. -- DIALOGTYPE=DIR.
  59. do
  60. iup_open.set_attribute(Current, "ALLOWNEW", boolean_to_yesno(state))
  61. end
  62. set_dialog_type (type: STRING)
  63. -- Type of dialog (Open, Save or Directory). Can have values "OPEN",
  64. -- "SAVE" or "DIR". Default: "OPEN".
  65. --
  66. -- In Windows, when DIALOGTYPE=DIR the dialog shown is not the same
  67. -- dialog for OPEN and SAVE, this new dialog does not have the Help
  68. -- button neither filters. Also this new dialog needs CoInitializeEx with
  69. -- COINIT_APARTMENTTHREADED (done in iup_open), if the COM library was
  70. -- initialized with COINIT_MULTITHREADED prior to iup_open then the new
  71. -- dialog will have limited functionality. In Motif or GTK the dialog is
  72. -- the same, but it only allows the user to select a directory.
  73. require
  74. is_valid_type(type)
  75. do
  76. iup_open.set_attribute(Current, "DIALOGTYPE", type)
  77. end
  78. set_directory (dir: STRING)
  79. -- Initial directory. When set the last separator does not need to be
  80. -- specified, but when get the returned value will always contains the
  81. -- last separator.
  82. --
  83. -- In Motif or GTK, if not defined, the dialog opens
  84. -- in the current directory.
  85. --
  86. -- In Windows, if not defined and the application has used the dialog in
  87. -- the past, the path most recently used is selected as the initial
  88. -- directory. However, if an application is not run for a long time, its
  89. -- saved selected path is discarded. Also if not defined and the current
  90. -- directory contains any files of the specified filter types, the
  91. -- initial directory is the current directory. Otherwise, the initial
  92. -- directory is the "My Documents" directory of the current user.
  93. -- Otherwise, the initial directory is the Desktop folder.
  94. do
  95. iup_open.set_attribute(Current, "DIRECTORY", dir)
  96. end
  97. get_directory: STRING
  98. -- When consulted after the dialog is closed and the user pressed the
  99. -- OK button, it will contain the directory of the selected file. The
  100. -- returned value will always contains the last separator.
  101. do
  102. Result := iup_open.get_attribute(Current, "DIRECTORY")
  103. end
  104. set_ext_filter (filter: STRING)
  105. -- [Windows and GTK Only]: Defines several file filters. It has priority
  106. -- over FILTERINFO and FILTER. Must be a text with the format
  107. -- "FilterInfo1|Filter1|FilterInfo2|Filter2|...". The list ends with
  108. -- character '|'. Example: "Text files|*.txt;*.doc|Image
  109. -- files|*.gif;*.jpg;*.bmp|". In GTK there is no way how to overwrite the
  110. -- filters, so it is recommended to always add a less restrictive filter
  111. -- to the filter list, for example "All Files|*.*".
  112. do
  113. iup_open.set_attribute(Current, "EXTFILTER", filter)
  114. end
  115. set_ext_default (ext: STRING)
  116. -- Default extension to be used if selected file does not have an
  117. -- extension. The inspected extension will consider to have the same
  118. -- number of characters of the default extension. It must NOT include the
  119. -- period ".".
  120. do
  121. iup_open.set_attribute(Current, "EXTDEFAULT", ext)
  122. end
  123. set_file (file: STRING)
  124. -- Name of the file initially shown in the "File Name" field in the
  125. -- dialog. If contains a full path, then it is used as the initial
  126. -- directory and DIRECTORY is ignored.
  127. do
  128. iup_open.set_attribute(Current, "FILE", file)
  129. end
  130. file_exist: BOOLEAN
  131. -- Indicates if the file defined by the FILE attribute exists or not. It
  132. -- is only valid if the user has pressed OK in the dialog. Not set when
  133. -- DIALOGTYPE=DIR or MULTIPLEFILES=True.
  134. local
  135. str: STRING
  136. do
  137. str := iup_open.get_attribute(Current, "FILEEXIST")
  138. Result := yesno_to_boolean(str)
  139. end
  140. set_filter (filter: STRING)
  141. -- String containing a list of file filters separated by ';' without
  142. -- spaces. Example: "*.C;*.LED;test.*". In Motif only the first filter is
  143. -- used.
  144. do
  145. iup_open.set_attribute(Current, "FILTER", filter)
  146. end
  147. set_filter_info (info: STRING)
  148. -- [Windows and GTK Only]: Filter's description. If not defined the
  149. -- filter itself will be used as its description. String containing a
  150. -- list of file filters separated by ';'.
  151. do
  152. iup_open.set_attribute(Current, "FILTERINFO", info)
  153. end
  154. set_filter_used (id: INTEGER)
  155. -- [Windows and GTK Only]: the index of the filter in EXTFILTER to use
  156. -- starting at 1. Set only if EXTFILTER is defined.
  157. require
  158. id >= 1
  159. do
  160. iup_open.set_attribute(Current, "FILTERUSED", id.out)
  161. end
  162. get_filter_used: INTEGER
  163. -- It returns the selection made by the user.
  164. local
  165. str: STRING
  166. do
  167. str := iup_open.get_attribute(Current, "FILTERUSED")
  168. if str.is_integer then
  169. Result := str.to_integer
  170. end
  171. end
  172. set_multiple_files (state: BOOLEAN)
  173. -- When "True", this attribute allows the user to select multiple files
  174. -- when DIALOGTYPE=OPEN. The value returned by VALUE is to be changed the
  175. -- following way: the directory and the files are passed separately, in
  176. -- this order. The character used for separating the directory and the
  177. -- files is '|'. The file list ends with character '|'. When the user
  178. -- selects just one file, the directory and the file are not separated by
  179. -- '|'. For example:
  180. --
  181. -- "/tecgraf/iup/test|a.txt|b.txt|c.txt|" or
  182. -- "/tecgraf/iup/test/a.txt" (only one file is selected)
  183. do
  184. iup_open.set_attribute(Current, "MULTIPLEFILES",
  185. boolean_to_yesno(state))
  186. end
  187. set_no_change_dir (state: BOOLEAN)
  188. -- Indicates if the current working directory must be restored after the
  189. -- user navigation. Default: "True".
  190. do
  191. iup_open.set_attribute(Current, "NOCHANGEDIR",
  192. boolean_to_yesno(state))
  193. end
  194. set_no_overwrite_prompt (state: BOOLEAN)
  195. -- Do not prompt to overwrite an existent file when in "SAVE" dialog.
  196. -- Default is "False", i.e. prompt before overwrite.
  197. do
  198. iup_open.set_attribute(Current, "NOOVERWRITEPROMPT",
  199. boolean_to_yesno(state))
  200. end
  201. set_no_places_bar (state: BOOLEAN)
  202. -- [Windows Only]: do not show the places bar.
  203. do
  204. iup_open.set_attribute(Current, "NOPLACESBAR", boolean_to_yesno(state))
  205. end
  206. set_show_edit_box (state: BOOLEAN)
  207. -- [Windows Only]: Show an edit box in a dialog selection dialog. (since
  208. -- 3.20). Default: False.
  209. do
  210. iup_open.set_attribute(Current, "SHOWEDITBOX",
  211. boolean_to_yesno(state))
  212. end
  213. set_show_hidden (state: BOOLEAN)
  214. -- Show hidden files. Default: False.
  215. do
  216. iup_open.set_attribute(Current, "SHOWHIDDEN",
  217. boolean_to_yesno(state))
  218. end
  219. -- set_show_preview
  220. get_status: INTEGER
  221. -- Indicates the status of the selection made:
  222. --
  223. -- "1": New file.
  224. -- "0": Normal, existing file or directory.
  225. -- "-1": Operation cancelled.
  226. local
  227. str: STRING
  228. do
  229. str := iup_open.get_attribute(Current, "STATUS")
  230. if str.is_integer then
  231. Result := str.to_integer
  232. end
  233. end
  234. get_value: STRING
  235. -- Name of the selected file(s), or Void if no file was selected. When
  236. -- MULTIPLEFILES=True it contains the path and several file names
  237. -- separated by the '|' character.
  238. local
  239. r, sf: STRING
  240. do
  241. r := iup_open.get_attribute(Current, "VALUE")
  242. create sf.make_from_c(get_pointer(r.to_c))
  243. Result := sf
  244. end
  245. get_multivalue_count: INTEGER
  246. -- Number of returned values when MULTIPLEFILES=True. It includes the
  247. -- path.
  248. local
  249. str: STRING
  250. do
  251. str := iup_open.get_attribute(Current, "MULTIVALUECOUNT")
  252. if str.is_integer then
  253. Result := str.to_integer
  254. end
  255. end
  256. get_multivalue_at (id: INTEGER): STRING
  257. -- Almost the same sequence returned in VALUE when MULTIPLEFILES=Yes but
  258. -- split in several attributes. VALUE0 contains the path (same value
  259. -- returned in DIRECTORY), and VALUE1,VALUE2,... contains each file name
  260. -- without the path.
  261. require
  262. id >= 0
  263. do
  264. Result := iup_open.get_attribute_id(Current, "MULTIVALUE", id)
  265. end
  266. set_multivalue_path (state: BOOLEAN)
  267. -- Force a full path in VALUE attribute when MULTIPLEFILES=True (id=0 will
  268. -- still contains the path of the first file). In Windows and Motif, only
  269. -- files in the same folder may be selected, but in GTK when using the
  270. -- "Recent Files" files from different folders can be selected. (since
  271. -- 3.20)
  272. do
  273. iup_open.set_attribute(Current, "MULTIVALUEPATH",
  274. boolean_to_yesno(state))
  275. end
  276. -- Callbacks
  277. set_cb_help (act: detachable PROCEDURE[TUPLE[IUP_FILE_DIALOG]])
  278. -- Action generated when the user press F1 at a control. In Motif
  279. -- is also activated by the Help button in some workstations
  280. -- keyboard.
  281. -- Returns: IUP_CLOSE will be processed.
  282. local
  283. operation: INTEGER
  284. do
  285. cb_help := act
  286. if cb_help /= Void then
  287. operation := 1
  288. else
  289. operation := 0
  290. end
  291. iup_open.set_callback (Current, "HELP_CB", "NONEEDED", operation)
  292. end
  293. set_cb_file (act: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, STRING, STRING], STRING])
  294. -- Action generated when a file is selected. Not called when
  295. -- DIALOGTYPE=DIR. When MULTIPLEFILES=True it is called only for one
  296. -- file. Can be used with SHOWPREVIEW=False also.
  297. local
  298. operation: INTEGER
  299. do
  300. cb_file := act
  301. if cb_file /= Void then
  302. operation := 1
  303. else
  304. operation := 0
  305. end
  306. iup_open.set_callback (Current, "FILE_CB", "NONEEDED", operation)
  307. end
  308. set_cb_button (act: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
  309. -- Action generated when any mouse button is pressed or released over the
  310. -- preview canvas. Both calls occur before the ACTION callback when
  311. -- button 1 is being used.
  312. --
  313. -- IUP_CANVAS: identifies the element that activated the event.
  314. -- button: identifies the activated mouse button:
  315. --
  316. -- 1 - left mouse button (button 1);
  317. -- 2 - middle mouse button (button 2);
  318. -- 3 - right mouse button (button 3).
  319. --
  320. -- pressed: indicates the state of the button:
  321. --
  322. -- 0 - mouse button was released;
  323. -- 1 - mouse button was pressed.
  324. --
  325. -- x, y: position in the canvas where the event has occurred, in pixels.
  326. --
  327. -- status: status of the mouse buttons and some keyboard keys at the
  328. -- moment the event is generated. The following IUP features must be used
  329. -- for verification:
  330. --
  331. -- is_shift(status)
  332. -- is_control(status)
  333. -- is_button_1(status)
  334. -- is_button_2(status)
  335. -- is_button_3(status)
  336. -- is_button_4(status)
  337. -- is_button_5(status)
  338. -- is_double(status)
  339. -- is_alt(status)
  340. -- is_sys(status)
  341. --
  342. -- Returns: IUP_CLOSE will be processed. On some controls if IUP_IGNORE
  343. -- is returned the action is ignored (this is system dependent).
  344. local
  345. operation: INTEGER
  346. do
  347. cb_button := act
  348. if cb_button /= Void then
  349. operation := 1
  350. else
  351. operation := 0
  352. end
  353. iup_open.set_callback (Current, "BUTTON_CB", "NONEEDED", operation)
  354. end
  355. set_cb_motion (act: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, STRING], STRING])
  356. -- Action generated when the mouse is moved over the preview canvas.
  357. -- ih: identifier of the element that activated the event.
  358. -- x, y: position in the canvas where the event has occurred, in pixels.
  359. -- status: status of mouse buttons and certain keyboard keys at the
  360. -- moment the event was generated. The same macros used for BUTTON_CB can
  361. -- be used for this status.
  362. local
  363. operation: INTEGER
  364. do
  365. cb_motion := act
  366. if cb_motion /= Void then
  367. operation := 1
  368. else
  369. operation := 0
  370. end
  371. iup_open.set_callback (Current, "MOTION_CB", "NONEEDED", operation)
  372. end
  373. set_cb_wheel (act: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, REAL_32, INTEGER, INTEGER, STRING], STRING])
  374. -- Action generated when the mouse wheel is rotated over the preview
  375. -- canvas. If this callback is not defined the wheel will automatically
  376. -- scroll the canvas in the vertical direction by some lines, the
  377. -- SCROLL_CB callback if defined will be called with the IUP_SBDRAGV
  378. -- operation.
  379. --
  380. -- ih: identifier of the element that activated the event.
  381. -- delta: the amount the wheel was rotated in notches.
  382. -- x, y: position in the canvas where the event has occurred, in pixels.
  383. -- status: status of mouse buttons and certain keyboard keys at the
  384. -- moment the event was generated. The same macros used for BUTTON_CB can
  385. -- be used for this status.
  386. --
  387. -- In Motif and GTK delta is always 1 or -1. In Windows is some
  388. -- situations delta can reach the value of two. In the future with more
  389. -- precise wheels this increment can be changed.
  390. local
  391. operation: INTEGER
  392. do
  393. cb_wheel := act
  394. if cb_wheel /= Void then
  395. operation := 1
  396. else
  397. operation := 0
  398. end
  399. iup_open.set_callback (Current, "WHEEL_CB", "NONEEDED", operation)
  400. end
  401. -- Validations
  402. is_valid_type(type: STRING): BOOLEAN
  403. do
  404. if type.is_equal("OPEN") or
  405. type.is_equal("SAVE") or
  406. type.is_equal("DIR") then
  407. Result := True
  408. else
  409. Result := False
  410. end
  411. end
  412. feature {IUP}
  413. -- Common callbacks
  414. execute_help
  415. do
  416. if attached cb_help as int_cb then
  417. int_cb.call([Current])
  418. end
  419. end
  420. -- Extra
  421. execute_file (file_name, status: STRING): STRING
  422. do
  423. if attached cb_file as int_cb then
  424. Result := int_cb.item([Current, file_name, status])
  425. else
  426. Result := "IUP_DEFAULT"
  427. end
  428. end
  429. execute_button (btn, pressed, x, y: INTEGER; status: STRING): STRING
  430. do
  431. if attached cb_button as int_cb then
  432. Result := int_cb.item([Current, btn, pressed, x, y, status])
  433. else
  434. Result := "IUP_DEFAULT"
  435. end
  436. end
  437. execute_motion (x, y: INTEGER; status: STRING): STRING
  438. do
  439. if attached cb_motion as int_cb then
  440. Result := int_cb.item([Current, x, y, status])
  441. else
  442. Result := "IUP_DEFAULT"
  443. end
  444. end
  445. execute_wheel (delta: REAL_32; x, y: INTEGER; status: STRING): STRING
  446. do
  447. if attached cb_wheel as int_cb then
  448. Result := int_cb.item([Current, delta, x, y, status])
  449. else
  450. Result := "IUP_DEFAULT"
  451. end
  452. end
  453. feature {NONE}
  454. -- For callbacks
  455. cb_help: detachable PROCEDURE[TUPLE[IUP_FILE_DIALOG]]
  456. cb_file: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, STRING, STRING], STRING]
  457. cb_button: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
  458. cb_motion: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, STRING], STRING]
  459. cb_wheel: detachable FUNCTION[TUPLE[IUP_FILE_DIALOG, REAL_32, INTEGER, INTEGER, STRING], STRING]
  460. -- Internal
  461. int_file_dialog: POINTER
  462. external
  463. "C inline use %"eiffel-iup.h%""
  464. alias
  465. "return IupFileDlg();"
  466. end
  467. end
  468. -- The MIT License (MIT)
  469. -- Copyright (c) 2016, 2017, 2019, 2020 by German A. Arias
  470. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  471. -- of this software and associated documentation files (the "Software"), to deal
  472. -- in the Software without restriction, including without limitation the rights
  473. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  474. -- copies of the Software, and to permit persons to whom the Software is
  475. -- furnished to do so, subject to the following conditions:
  476. --
  477. -- The above copyright notice and this permission notice shall be included in
  478. -- all copies or substantial portions of the Software.
  479. --
  480. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  481. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  482. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  483. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  484. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  485. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  486. -- SOFTWARE.