iup_file_dialog.e 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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.to_string)
  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_show_edit_box (state: BOOLEAN)
  202. -- [Windows Only]: Show an edit box in a dialog selection dialog. (since
  203. -- 3.20). Default: False.
  204. do
  205. iup_open.set_attribute(Current, "SHOWEDITBOX",
  206. boolean_to_yesno(state))
  207. end
  208. set_show_hidden (state: BOOLEAN)
  209. -- Show hidden files. Default: False.
  210. do
  211. iup_open.set_attribute(Current, "SHOWHIDDEN",
  212. boolean_to_yesno(state))
  213. end
  214. -- set_show_preview
  215. get_status: INTEGER
  216. -- Indicates the status of the selection made:
  217. --
  218. -- "1": New file.
  219. -- "0": Normal, existing file or directory.
  220. -- "-1": Operation cancelled.
  221. local
  222. str: STRING
  223. do
  224. str := iup_open.get_attribute(Current, "STATUS")
  225. if str.is_integer then
  226. Result := str.to_integer
  227. end
  228. end
  229. get_value: STRING
  230. -- Name of the selected file(s), or Void if no file was selected. When
  231. -- MULTIPLEFILES=True it contains the path and several file names
  232. -- separated by the '|' character.
  233. local
  234. sf: STRING
  235. do
  236. create sf.from_external_copy(iup_open.get_attribute(Current, "VALUE").to_external)
  237. Result := sf
  238. end
  239. get_multivalue_count: INTEGER
  240. -- Number of returned values when MULTIPLEFILES=True. It includes the
  241. -- path.
  242. local
  243. str: STRING
  244. do
  245. str := iup_open.get_attribute(Current, "MULTIVALUECOUNT")
  246. if str.is_integer then
  247. Result := str.to_integer
  248. end
  249. end
  250. get_multivalue_at (id: INTEGER): STRING
  251. -- Almost the same sequence returned in VALUE when MULTIPLEFILES=Yes but
  252. -- split in several attributes. VALUE0 contains the path (same value
  253. -- returned in DIRECTORY), and VALUE1,VALUE2,... contains each file name
  254. -- without the path.
  255. require
  256. id >= 0
  257. do
  258. Result := iup_open.get_attribute_id(Current, "MULTIVALUE", id)
  259. end
  260. set_multivalue_path (state: BOOLEAN)
  261. -- Force a full path in VALUE attribute when MULTIPLEFILES=True (id=0 will
  262. -- still contains the path of the first file). In Windows and Motif, only
  263. -- files in the same folder may be selected, but in GTK when using the
  264. -- "Recent Files" files from different folders can be selected. (since
  265. -- 3.20)
  266. do
  267. iup_open.set_attribute(Current, "MULTIVALUEPATH",
  268. boolean_to_yesno(state))
  269. end
  270. -- Callbacks
  271. set_cb_help (act: PROCEDURE[TUPLE[IUP_FILE_DIALOG]])
  272. -- Action generated when the user press F1 at a control. In Motif
  273. -- is also activated by the Help button in some workstations
  274. -- keyboard.
  275. -- Returns: IUP_CLOSE will be processed.
  276. local
  277. operation: INTEGER
  278. do
  279. cb_help := act
  280. if cb_help /= Void then
  281. operation := 1
  282. else
  283. operation := 0
  284. end
  285. iup_open.set_callback (Current, "HELP_CB", "NONEEDED", operation)
  286. end
  287. set_cb_file (act: FUNCTION[TUPLE[IUP_FILE_DIALOG, STRING, STRING], STRING])
  288. -- Action generated when a file is selected. Not called when
  289. -- DIALOGTYPE=DIR. When MULTIPLEFILES=True it is called only for one
  290. -- file. Can be used with SHOWPREVIEW=False also.
  291. local
  292. operation: INTEGER
  293. do
  294. cb_file := act
  295. if cb_file /= Void then
  296. operation := 1
  297. else
  298. operation := 0
  299. end
  300. iup_open.set_callback (Current, "FILE_CB", "NONEEDED", operation)
  301. end
  302. set_cb_button (act: FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
  303. -- Action generated when any mouse button is pressed or released over the
  304. -- preview canvas. Both calls occur before the ACTION callback when
  305. -- button 1 is being used.
  306. --
  307. -- IUP_CANVAS: identifies the element that activated the event.
  308. -- button: identifies the activated mouse button:
  309. --
  310. -- 1 - left mouse button (button 1);
  311. -- 2 - middle mouse button (button 2);
  312. -- 3 - right mouse button (button 3).
  313. --
  314. -- pressed: indicates the state of the button:
  315. --
  316. -- 0 - mouse button was released;
  317. -- 1 - mouse button was pressed.
  318. --
  319. -- x, y: position in the canvas where the event has occurred, in pixels.
  320. --
  321. -- status: status of the mouse buttons and some keyboard keys at the
  322. -- moment the event is generated. The following IUP features must be used
  323. -- for verification:
  324. --
  325. -- is_shift(status)
  326. -- is_control(status)
  327. -- is_button_1(status)
  328. -- is_button_2(status)
  329. -- is_button_3(status)
  330. -- is_button_4(status)
  331. -- is_button_5(status)
  332. -- is_double(status)
  333. -- is_alt(status)
  334. -- is_sys(status)
  335. --
  336. -- Returns: IUP_CLOSE will be processed. On some controls if IUP_IGNORE
  337. -- is returned the action is ignored (this is system dependent).
  338. local
  339. operation: INTEGER
  340. do
  341. cb_button := act
  342. if cb_button /= Void then
  343. operation := 1
  344. else
  345. operation := 0
  346. end
  347. iup_open.set_callback (Current, "BUTTON_CB", "NONEEDED", operation)
  348. end
  349. set_cb_motion (act: FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, STRING], STRING])
  350. -- Action generated when the mouse is moved over the preview canvas.
  351. -- ih: identifier of the element that activated the event.
  352. -- x, y: position in the canvas where the event has occurred, in pixels.
  353. -- status: status of mouse buttons and certain keyboard keys at the
  354. -- moment the event was generated. The same macros used for BUTTON_CB can
  355. -- be used for this status.
  356. local
  357. operation: INTEGER
  358. do
  359. cb_motion := act
  360. if cb_motion /= Void then
  361. operation := 1
  362. else
  363. operation := 0
  364. end
  365. iup_open.set_callback (Current, "MOTION_CB", "NONEEDED", operation)
  366. end
  367. set_cb_wheel (act: FUNCTION[TUPLE[IUP_FILE_DIALOG, REAL_32, INTEGER, INTEGER, STRING], STRING])
  368. -- Action generated when the mouse wheel is rotated over the preview
  369. -- canvas. If this callback is not defined the wheel will automatically
  370. -- scroll the canvas in the vertical direction by some lines, the
  371. -- SCROLL_CB callback if defined will be called with the IUP_SBDRAGV
  372. -- operation.
  373. --
  374. -- ih: identifier of the element that activated the event.
  375. -- delta: the amount the wheel was rotated in notches.
  376. -- x, y: position in the canvas where the event has occurred, in pixels.
  377. -- status: status of mouse buttons and certain keyboard keys at the
  378. -- moment the event was generated. The same macros used for BUTTON_CB can
  379. -- be used for this status.
  380. --
  381. -- In Motif and GTK delta is always 1 or -1. In Windows is some
  382. -- situations delta can reach the value of two. In the future with more
  383. -- precise wheels this increment can be changed.
  384. local
  385. operation: INTEGER
  386. do
  387. cb_wheel := act
  388. if cb_wheel /= Void then
  389. operation := 1
  390. else
  391. operation := 0
  392. end
  393. iup_open.set_callback (Current, "WHEEL_CB", "NONEEDED", operation)
  394. end
  395. feature {IUP}
  396. -- Common callbacks
  397. execute_help
  398. do
  399. cb_help.call([Current])
  400. end
  401. -- Extra
  402. execute_file (file_name, status: STRING): STRING
  403. do
  404. Result := cb_file.item([Current, file_name, status])
  405. end
  406. execute_button (btn, pressed, x, y: INTEGER; status: STRING): STRING
  407. do
  408. Result := cb_button.item([Current, btn, pressed, x, y, status])
  409. end
  410. execute_motion (x, y: INTEGER; status: STRING): STRING
  411. do
  412. Result := cb_motion.item([Current, x, y, status])
  413. end
  414. execute_wheel (delta: REAL_32; x, y: INTEGER; status: STRING): STRING
  415. do
  416. Result := cb_wheel.item([Current, delta, x, y, status])
  417. end
  418. feature {}
  419. -- For callbacks
  420. cb_help: PROCEDURE[TUPLE[IUP_FILE_DIALOG]]
  421. cb_file: FUNCTION[TUPLE[IUP_FILE_DIALOG, STRING, STRING], STRING]
  422. cb_button: FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
  423. cb_motion: FUNCTION[TUPLE[IUP_FILE_DIALOG, INTEGER, INTEGER, STRING], STRING]
  424. cb_wheel: FUNCTION[TUPLE[IUP_FILE_DIALOG, REAL_32, INTEGER, INTEGER, STRING], STRING]
  425. -- Internal
  426. int_file_dialog: POINTER
  427. external "plug_in"
  428. alias "{
  429. location: "${sys}/plugins"
  430. module_name: "iup"
  431. feature_name: "IupFileDlg()"
  432. }"
  433. end
  434. -- Validations
  435. is_valid_type(type: STRING): BOOLEAN
  436. do
  437. if type.is_equal("OPEN") or
  438. type.is_equal("SAVE") or
  439. type.is_equal("DIR") then
  440. Result := True
  441. else
  442. Result := False
  443. end
  444. end
  445. end
  446. -- The MIT License (MIT)
  447. -- Copyright (c) 2016, 2017 by German A. Arias
  448. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  449. -- of this software and associated documentation files (the "Software"), to deal
  450. -- in the Software without restriction, including without limitation the rights
  451. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  452. -- copies of the Software, and to permit persons to whom the Software is
  453. -- furnished to do so, subject to the following conditions:
  454. --
  455. -- The above copyright notice and this permission notice shall be included in
  456. -- all copies or substantial portions of the Software.
  457. --
  458. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  459. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  460. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  461. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  462. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  463. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  464. -- SOFTWARE.