1
1

Compare commits

...

124 Commits

Author SHA1 Message Date
Julian Eisel
37590a6a11 Merge branch 'master' into filebrowser_redesign 2019-09-03 15:39:09 +02:00
Julian Eisel
d35efde181 Fix crash saving files with preview saving enabled 2019-09-03 14:52:16 +02:00
Julian Eisel
82bc196736 Fix possible crash when opening files saved with new file browser open 2019-09-02 17:01:41 +02:00
Julian Eisel
99acf30edd Gray out number increment/decrement button for file open operations
The buttons are shown in the file browser context menu.
2019-09-02 16:39:39 +02:00
Julian Eisel
aa0db0038e Fix empty tool settings region with old files
E.g. visible in the VSE workspace.

Also removes redundant NULL checks (do_versions_find_region asserts, and
AFAIK they should never be NULL)
2019-09-02 16:14:45 +02:00
Julian Eisel
337ba032e4 Merge branch 'master' into filebrowser_redesign 2019-09-02 15:43:36 +02:00
Julian Eisel
cbe7143589 Remove flag to disable categories per region-type
Just set a dummy bl_category to avoid warning prints.
2019-09-01 14:03:41 +02:00
Julian Eisel
bee91a5a5a Remove 'HIDDEN' panel flag, use existing convention
Existing convention is to register the panels for a header, which means
they're not drawn by default anyway.
2019-09-01 13:55:36 +02:00
Julian Eisel
e859086b18 Merge branch 'master' into filebrowser_redesign 2019-09-01 13:39:30 +02:00
Julian Eisel
2f7718aa23 Merge branch 'master' into filebrowser_redesign 2019-08-30 14:21:30 +02:00
Julian Eisel
3b78360a46 Keymap: 'N' to toggle right side options region 2019-08-30 00:32:06 +02:00
Julian Eisel
e2dbf96fd4 Don't clear file name on directory selection 2019-08-30 00:16:06 +02:00
Julian Eisel
04e4852a99 Cleanup: Rename column types to be less ambiguous 2019-08-28 01:37:54 +02:00
Julian Eisel
b78b8cc17e Refactor inverted sorting to be applyied in sort callbacks already 2019-08-28 00:38:30 +02:00
Julian Eisel
8f6894a6ad Open file browser window in center of parent window 2019-08-27 16:19:54 +02:00
Julian Eisel
c3453e1667 Cleanup: Remove outdated TODO comments
Also add a comment on prop_with_popover usage.
2019-08-27 15:57:11 +02:00
Julian Eisel
ea94cade29 Remove confirmation popup for creating new directory 2019-08-27 15:54:16 +02:00
Julian Eisel
54d156288d Correct string translation logic
Refactors BLI_filelist_entry_datetime_to_string so that user message
strings are created in UI code, not BLI. That way we can also handle
translations correctly and better.
2019-08-27 15:21:55 +02:00
Julian Eisel
64f43d5367 Open "Volumes" panel by default 2019-08-27 14:21:42 +02:00
Julian Eisel
b95d371a83 Disable the file name button for directory-only browsing 2019-08-27 14:18:25 +02:00
Julian Eisel
c081ebb9a5 Fix strings not translated 2019-08-27 13:49:07 +02:00
Julian Eisel
02b18d7353 Fix missing dot for .gltf file recognition 2019-08-27 12:51:02 +02:00
Julian Eisel
8b08f487b2 General minor cleanup
* Remove dead code
* Correct comment position
* Use enum and bitshifting for PanelType.flag
* Remove final point from UI message
2019-08-27 12:48:39 +02:00
Julian Eisel
15bc4143fc Merge branch 'master' into filebrowser_redesign 2019-08-27 00:40:17 +02:00
Julian Eisel
adccfb33e5 Merge branch 'master' into filebrowser_redesign 2019-08-23 15:42:00 +02:00
Julian Eisel
4e2be2f39e Fix size column text missing when date column is disabled 2019-08-23 15:38:57 +02:00
Julian Eisel
20278a3776 Merge branch 'master' into filebrowser_redesign 2019-08-22 13:25:50 +02:00
854ea231c4 UI: File Browser Large Thumbnails with Drives
This updates the prvicon sheet to a version that includes storage drives
2019-08-19 09:30:46 -07:00
Julian Eisel
bb5b98e770 Fix warnings 2019-08-19 16:23:50 +02:00
Julian Eisel
86db4b0c3f Add prominent button to toggle properties sidebar
Located at the lower left.
2019-08-19 00:40:11 +02:00
Julian Eisel
de0bfa1d6a Only add new properties sidebar when there is an operator to execute
So don't add the sidebar (not even hidden) when the file browser is
opened as regular editor.
2019-08-18 23:22:29 +02:00
Julian Eisel
0a3866dc83 Only show new properties sidebar for specific operators 2019-08-18 23:04:30 +02:00
Julian Eisel
fcc54d06ce Don't limit with of execute region by tool properties region 2019-08-18 20:43:34 +02:00
Julian Eisel
935d622458 Add right sidebar region for operator properties
This always shows up right now. Hiding it correctly still has to be
done.
2019-08-18 15:21:18 +02:00
Julian Eisel
8209f25c3b Merge branch 'master' into filebrowser_redesign 2019-08-18 13:24:15 +02:00
4befee9e62 UI: File Browser Use Friendly Relative Dates
Show 'Today' or 'Yesterday' in file list
2019-08-13 10:52:10 -07:00
04e445ccfb UI: File Browser Icons That Allow Themes
This alters the prvicon sheet so icons are full opacity so can be themed later
2019-08-12 09:56:06 -07:00
dfd6bcf500 UI: File Browser with Light Background
This uses dark icons if using a theme with light background
2019-08-11 19:16:11 -07:00
Julian Eisel
98c0c32769 Correction to prev. commit: Avoid multiple specific file format types
Use a single generic `FILE_TYPE_OBJECT_IO` instead of specific ones
(e.g. `FILE_TYPE_FBX`). We better leave as many bits free as we can
(this is stored in files).
2019-08-12 00:54:30 +02:00
35f985fcd5 Icons: Add support for 3d model file types
OBJ, 3DS, GLTF, FBX, Collada
2019-08-12 00:29:30 +02:00
Julian Eisel
2360168b03 Show the workspace icon in the file browser
Actually, this is not just file-browser specific. It adds the icon
everywhere we try to show data-block icons (e.g. outliner).
2019-08-12 00:15:32 +02:00
Julian Eisel
f1b48a2957 Fix thumbnail border drawing off by one coordinates 2019-08-11 23:46:44 +02:00
Julian Eisel
ec498e00e5 Cleanup: Minor code-style adjustments 2019-08-11 23:19:45 +02:00
Julian Eisel
eb1ae3b788 Silence warning (shadowed variable) 2019-08-11 23:17:22 +02:00
fdd32d8a15 UI: File Browser File Type Changes
This adjusts the vertical aligment of the little icons show inside files and folders
2019-08-11 13:33:47 -07:00
e6065ee240 UI: File Browser Thumbnail Changes
This vertically centers thumbnails and fixes the horizontal alignment of the file name labels
2019-08-11 13:11:27 -07:00
c1015a13af UI: keymap tweaks fo File Browser 2019-08-11 21:16:14 +02:00
3c034eab5a UI: Thumbnail mode update
This adds the changes from D5375 by Harley Acheson to the File Browser branch.
2019-08-11 20:52:34 +02:00
Julian Eisel
d0a8796e34 Fix file table header and missing context menu in industry compat. keymap 2019-08-11 18:31:58 +02:00
Julian Eisel
ea96913ed5 Fix missing background in empty directories (vertical list) 2019-08-11 18:00:46 +02:00
Julian Eisel
bc5e7a2e49 Fix: Selecting directory changes active file name
This is an issue in master actually. The wrong bit flag is used.
2019-08-11 17:51:36 +02:00
Julian Eisel
1290e63e7e Tweaks to theme colors
Better addresses color clashes. rB5d99a8c083 made things appear too dark
for some screens.
Also fixes wrong versioning for execution region background color.
2019-08-11 17:44:04 +02:00
7ed7955c25 UI: Small naming tweaks to File Browser popovers 2019-08-11 10:47:48 +02:00
5d99a8c083 UI: Make File Browser background stand out from the UI chrome more
Avoids color clashes with source list.
2019-08-11 10:29:16 +02:00
Julian Eisel
1cfbd0e476 Improve display of 'Date Modified' & 'Size' column strings
* Left align 'Date Modified' column strings
* Cleaner & more clear format of date/time string
* Fix size column strings clipping after two digits
2019-08-10 15:56:45 +02:00
Julian Eisel
d37464461d Make search independent from filter enabled state 2019-08-10 15:15:33 +02:00
Julian Eisel
7b4f7592e3 Always hide '..' parent item 2019-08-10 14:07:45 +02:00
Julian Eisel
d64b275153 Silence warning in versioning code 2019-08-10 14:06:37 +02:00
Julian Eisel
b9898ebde4 Merge branch 'master' into filebrowser_redesign 2019-08-10 13:24:26 +02:00
b17380971a Add new file and folder icons
These are much larger and can use other icons superimposed on them.

Curtesy of @jendrych, Andrzej Ambroż.
2019-08-07 20:26:34 +02:00
4b8e4c9dfb Organize Cancel/Execute buttons according to the OS standard:
Windows: Execute/Cancel
Mac: Cancel/Execute

Linux uses same order as the Mac in this case. That platform doesn't really have as strongly defined standards.
2019-07-28 09:48:06 +02:00
354da16b7b Swap icons for vertical and horizontal list views
These were wrongly used before
2019-07-28 09:46:22 +02:00
02b00e4cf2 Clean up of header
Remove redundant controls, and rename Toolbar to Source List
2019-07-28 09:33:21 +02:00
02557510bf Use simple action names in the File Browser.
Previously this was overly verbose.

  - Open Blender File -> Open
  - Save As Blender File > Save As

etc
2019-07-28 09:32:05 +02:00
df79abdae8 Split Filter popover into Filter and Display
Filter contains options about *what* to show
Display contains options about *how* to show it

I used prop_with_popover for the Filter popover too to force it to show the disclosure triangle. Ideally this would not be needed.
2019-07-28 09:30:37 +02:00
909a48e382 Add context menu to File Browser 2019-07-28 09:26:33 +02:00
8d804f5d2b Keymap: Make File Browser keymap consistent:
- LMB Click to select
  - Double-click to open
  - Shift-click to select & fill
  - Ctrl-click to extend selection
  - Shift-drag to extend box
  - Ctrl-drag to subtract box

RMB will be used for the context menu
2019-07-28 09:24:58 +02:00
Julian Eisel
5c531c7f31 Merge branch 'master' into filebrowser_redesign 2019-07-26 01:28:25 +02:00
Julian Eisel
8aba00a673 Remove dead code
Now handled in Python.
2019-07-26 00:05:43 +02:00
Julian Eisel
33371915c9 Fix vertical list layout when thumnail view was active previously 2019-07-25 21:58:45 +02:00
Brian Meisenheimer
2f6831e691 Changed Displaytype to Vertical List and Horizontal List 2019-07-25 14:13:05 +02:00
Julian Eisel
b2bc426c00 Add new/changed settings to version patching
* Set flag to dynamically size file path region. Without this the region
  can be resized, which is not wanted.
* Enable modification date/time and size details columns
2019-07-25 03:20:32 +02:00
Julian Eisel
d9cf9c659c Use full area width for filepath region
Also adjusts size for old files.
2019-07-25 03:11:58 +02:00
Julian Eisel
5909e31087 Fix crash with narrow file list rendering 2019-07-25 02:40:53 +02:00
Julian Eisel
f8a39ae0e4 Bring back active-default blue highlight for execute button
It marks the button representing the operation executed with enter.
2019-07-25 02:30:22 +02:00
Julian Eisel
c5b872c060 Support toggling inverted sorting through column header (3 state) 2019-07-25 02:09:54 +02:00
Julian Eisel
109cd4640b Support inverted sorting
Adds a checkbox to the filter/display popup, to invert sorting. We do an
additional pass to reverse the listbase order, rather than modifying the
sort callbacks. That adds a overhead but guess it's not much of an
issue. The alternative would make return values a bit cryptic.
2019-07-25 01:52:03 +02:00
Julian Eisel
15fb122008 Fix background pattern not scrolling with view 2019-07-25 00:48:00 +02:00
Julian Eisel
3a09e34eb1 Align modification date column to center, size to the right 2019-07-25 00:24:32 +02:00
Julian Eisel
321e1cba4a Refactor drawing, use available with for name column
Makes drawing use padding sizes more correctly, removing need for
hardcoded alignment of elements. Since we now know the name column width
in advance, we can do drawing in order (not reversed).
2019-07-24 23:57:40 +02:00
Julian Eisel
ef7c697932 Show both size and date column by default 2019-07-24 21:34:31 +02:00
Julian Eisel
c9e7c6bef8 Merge date and time column 2019-07-24 21:26:53 +02:00
Julian Eisel
d400714a9a Merge branch 'master' into filebrowser_redesign 2019-07-24 20:56:31 +02:00
Julian Eisel
c3483c765b Merge branch 'master' into filebrowser_redesign 2019-07-23 00:22:00 +02:00
Julian Eisel
27f1d88382 Correct icons and text off center by few pixels 2019-07-23 00:06:58 +02:00
Julian Eisel
768091dd0a Use base 10 for file size strings (MB, KB, ... instead of MiB, KiB, ...) 2019-07-22 23:15:46 +02:00
Julian Eisel
6f67257ee0 Make the column header interactive
Clicking on the column header will sort the file list based on the
clicked column. Note that sorting by time only is not supported, sorting
by date already sorts by time and date.
2019-07-22 22:36:59 +02:00
Julian Eisel
d191cbe1d6 Cleanup: Use struct to wrap details column data
Also, related cleanup.
2019-07-22 19:52:12 +02:00
Julian Eisel
f7d848bfd5 Add padding to details columns 2019-07-22 19:29:13 +02:00
Julian Eisel
43e3dd87a5 Draw details columns right aligned 2019-07-22 19:19:12 +02:00
Julian Eisel
7b361c60b0 Show size column by default
Could version patch this so file browsers in old files show size column
too. IMHO not worth it though.
2019-07-22 18:50:43 +02:00
Julian Eisel
498bb3202f Display option to choose details to show (file size, mod. time, etc.)
Rather than letting the display mode have hardcoded details columns, let
users choose which to select. Display modes can then be entirely
different modes, not just detail levels.
2019-07-22 18:30:18 +02:00
Julian Eisel
d395d84c66 Draw column header in short-list view
Similar to what you know from other file browsers, at the table top
there's a row indicating column names and showing a little triangle to
mark which column is used for sorting. Later, this will become
interactive (to allow selecting sort method by clicking on a column
name).

I decided to hardcode drawing of this (like the rest of the file
browser) and just offset the file layout a bit. However that requires
some hacks for View2D and that the offset is respected in multiple
places. So now I think using a separate region instead makes more sense.
Leaving this as is now, code quality for file browser is pretty low
anyway.
2019-07-22 16:49:04 +02:00
Julian Eisel
b84bcc314f Hide header by default in temp-window mode
Also, place it at the bottom, the little triangle to toggle it looks
misplaced at the top.
2019-07-21 16:14:37 +02:00
Julian Eisel
4dbaa1bab3 Show view options in header if visible
Brings back most of the buttons that were previously in the header back
to it. When the header is visible, the filter (or better said display)
popup is hidden.

Also moves display type option into the filter/display popup.
2019-07-21 15:40:33 +02:00
Julian Eisel
18e1132c72 Fix error in previous commit 2019-07-21 15:17:36 +02:00
Julian Eisel
2e2dde7448 Add recursion level and display size options to filter popup
Those are the file-list specific options from the area 'View' menu.
2019-07-21 15:08:32 +02:00
Julian Eisel
03d2dcec7d Move sorting options into filter popup
Consistent to Outliner filter popup.
2019-07-21 14:46:45 +02:00
Brian Meisenheimer
6ad2056282 Vertical layout for short list display type 2019-07-21 14:29:21 +02:00
Julian Eisel
b9ebb9014f Fix directory-browse button shown next to file browser directory path
Its purpose was to open a file browser to select a path, which doesn't
make any sense for this button.
2019-07-20 19:46:56 +02:00
Julian Eisel
51117a044b Merge branch 'master' into filebrowser_redesign 2019-07-20 17:39:57 +02:00
Julian Eisel
ce6e34e131 Move filter settings into popup
Saves space, hides complexity and is more consistent to other editors
(e.g. viewport and outliner). The search button is in the popup too for
now, we may want to move that later.
Note the filter popup is not located in the header, but in the directory
path (`UI`) region.

Had to do two additional changes:
* Allow registering a panel without drawing it in the default location.
  Required so we can register the popup panel in the `UI` region without
  it drawing there. For other places that's no issue because they are
  registered for headers - which don't draw panels anyway.
* `UI` regions are used for category tabs by default. Added a flag to
  allow region types to disable categories entirely.
2019-07-20 17:37:54 +02:00
Julian Eisel
cb44212073 Merge branch 'master' into filebrowser_redesign 2019-06-06 10:55:20 +02:00
Julian Eisel
e4053cc785 Merge branch 'master' into filebrowser_redesign 2019-06-03 09:24:02 +02:00
Julian Eisel
d2269cfe6b Merge branch 'master' into filebrowser_redesign 2019-06-03 00:44:30 +02:00
Julian Eisel
965d4683c0 Add version patching for execution region theme 2019-05-24 20:20:35 +02:00
Julian Eisel
acadc67e07 Merge branch 'master' into filebrowser_redesign 2019-05-24 20:05:14 +02:00
Julian Eisel
d271955a92 Cleanup: Run Clang-Format 2019-05-24 16:21:12 +02:00
Julian Eisel
d50091024c Use temporary window for file browsing 2019-05-24 00:09:58 +02:00
Julian Eisel
9eb667b76d Merge branch 'master' into filebrowser_redesign 2019-05-23 21:28:49 +02:00
Julian Eisel
9a2c45a3b1 Merge branch 'master' into filebrowser_redesign 2019-05-15 22:28:16 +02:00
Julian Eisel
84012c2119 Merge branch 'master' into filebrowser_redesign 2019-05-09 18:38:22 +02:00
Julian Eisel
56cf28f427 Merge branch 'filebrowser_redesign' of git.blender.org:blender into filebrowser_redesign 2019-05-06 17:48:20 +02:00
Julian Eisel
f40a7b41ae Merge branch 'master' into filebrowser_redesign 2019-05-06 17:44:45 +02:00
Julian Eisel
2729290e36 Merge branch 'master' into filebrowser_redesign 2019-05-03 23:48:57 +02:00
Julian Eisel
e78d9946b8 Merge branch 'master' into filebrowser_redesign 2019-05-02 21:33:44 +02:00
Brian Meisenheimer
23cfdc948f Changed the layout of the directory buttons, display mode panel and the "Create new directory" button 2019-04-25 19:34:34 +02:00
Julian Eisel
9dc25744b3 Merge branch 'master' into filebrowser_redesign 2019-04-24 13:55:28 +02:00
Julian Eisel
903d0a35b3 Update to new clang-format code style 2019-04-20 00:14:54 +02:00
Julian Eisel
1be01b3d5b Merge 'master' into 'filebrowser_redesign' 2019-04-19 22:15:34 +02:00
Julian Eisel
da2e53c9e7 Merge 'master' into 'filebrowser_redesign' 2019-04-19 22:11:27 +02:00
Julian Eisel
bf7e9f6691 Merge 'master' into 'filebrowser_redesign' 2019-04-19 22:11:20 +02:00
Julian Eisel
4376965a2e Merge branch 'master' into filebrowser_redesign 2019-04-01 14:52:24 +02:00
Julian Eisel
d069dc9859 Initially split filename and directory-path into two regions 2019-04-01 14:48:35 +02:00
33 changed files with 1900 additions and 1584 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 562 KiB

After

Width:  |  Height:  |  Size: 543 KiB

48
release/datafiles/prvicons_update.py Executable file → Normal file
View File

@@ -1,23 +1,25 @@
#!/usr/bin/env python3
# This script updates icons from the SVG file
import os
import subprocess
import sys
BASEDIR = os.path.abspath(os.path.dirname(__file__))
inkscape_path = 'inkscape'
if sys.platform == 'darwin':
inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
if os.path.exists(inkscape_app_path):
inkscape_path = inkscape_app_path
cmd = (
inkscape_path,
os.path.join(BASEDIR, "prvicons.svg"),
"--without-gui",
"--export-png=" + os.path.join(BASEDIR, "prvicons.png"),
)
subprocess.check_call(cmd)
#!/usr/bin/env python3
# This script updates icons from the SVG file
import os
import subprocess
import sys
BASEDIR = os.path.abspath(os.path.dirname(__file__))
inkscape_path = 'inkscape'
if sys.platform == 'darwin':
inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script'
if os.path.exists(inkscape_app_path):
inkscape_path = inkscape_app_path
cmd = (
inkscape_path,
os.path.join(BASEDIR, "prvicons.svg"),
"--export-width=1536",
"--export-height=256",
"--without-gui",
"--export-png=" + os.path.join(BASEDIR, "prvicons.png"),
)
subprocess.check_call(cmd)

View File

@@ -370,7 +370,7 @@ const bTheme U_theme_default = {
.paint_curve_handle = RGBA(0x7fff7f7f),
},
.space_file = {
.back = RGBA(0x35353500),
.back = RGBA(0x33333300),
.title = RGBA(0xffffffff),
.text = RGBA(0xe6e6e6ff),
.text_hi = RGBA(0xffffffff),
@@ -381,13 +381,14 @@ const bTheme U_theme_default = {
.tab_inactive = RGBA(0x2b2b2bff),
.tab_back = RGBA(0x232323ff),
.tab_outline = RGBA(0x232323ff),
.button = RGBA(0x424242ff),
.button = RGBA(0x4b4b4bff),
.button_title = RGBA(0xffffffff),
.button_text = RGBA(0xe5e5e5ff),
.button_text_hi = RGBA(0xffffffff),
.execution_buts = RGBA(0x444444ff),
.panelcolors = {
.header = RGBA(0x424242cc),
.back = RGBA(0x333333b3),
.header = RGBA(0x4b4b4bff),
.back = RGBA(0x404040ff),
.sub_back = RGBA(0x0000003e),
},
.hilite = RGBA(0x4f76b3ff),

View File

@@ -1771,6 +1771,11 @@ def km_file_browser(_params):
)
items.extend([
*_template_space_region_type_toggle(
toolbar_key={"type": 'T', "value": 'PRESS'},
),
("screen.region_toggle", {"type": 'N', "value": 'PRESS'},
{"properties": [("region_type", 'TOOL_PROPS')]}),
("file.parent", {"type": 'UP_ARROW', "value": 'PRESS', "alt": True}, None),
("file.previous", {"type": 'LEFT_ARROW', "value": 'PRESS', "alt": True}, None),
("file.next", {"type": 'RIGHT_ARROW', "value": 'PRESS', "alt": True}, None),
@@ -1782,7 +1787,6 @@ def km_file_browser(_params):
{"properties": [("data_path", 'space_data.params.show_hidden')]}),
("file.directory_new", {"type": 'I', "value": 'PRESS'}, None),
("file.smoothscroll", {"type": 'TIMER1', "value": 'ANY', "any": True}, None),
("file.bookmark_toggle", {"type": 'T', "value": 'PRESS'}, None),
("file.bookmark_add", {"type": 'B', "value": 'PRESS', "ctrl": True}, None),
])
@@ -1801,17 +1805,13 @@ def km_file_browser_main(params):
("file.execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
{"properties": [("need_active", True)]}),
("file.refresh", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
{"properties": [("extend", True)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
{"properties": [("extend", True), ("fill", True)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK'},
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'},
{"properties": [("open", False)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK', "shift": True},
{"properties": [("extend", True), ("open", False)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK', "alt": True},
{"properties": [("extend", True), ("fill", True), ("open", False)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
{"properties": [("extend", True)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
{"properties": [("extend", True), ("fill", True)]}),
("file.select_walk", {"type": 'UP_ARROW', "value": 'PRESS'},
{"properties": [("direction", 'UP')]}),
("file.select_walk", {"type": 'UP_ARROW', "value": 'PRESS', "shift": True},
@@ -1843,8 +1843,11 @@ def km_file_browser_main(params):
("file.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None),
("file.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True},
{"properties": [("mode", 'ADD')]}),
("file.rename", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True}, None),
("file.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY', "ctrl": True},
{"properties": [("mode", 'SUB')]}),
("file.highlight", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None),
("file.sort_column_ui_context", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
op_menu("FILEBROWSER_MT_context_menu", params.context_menu_event),
("file.filenum", {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
{"properties": [("increment", 1)]}),
("file.filenum", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True},

View File

@@ -1196,10 +1196,11 @@ def km_file_browser_main(params):
("file.execute", {"type": 'LEFTMOUSE', "value": 'DOUBLE_CLICK'},
{"properties": [("need_active", True)]}),
("file.refresh", {"type": 'R', "value": 'PRESS', "ctrl": True}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'}, None),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True},
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK'},
{"properties": [("open", False)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True},
{"properties": [("extend", True)]}),
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True, "ctrl": True},
("file.select", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True,},
{"properties": [("extend", True), ("fill", True)]}),
("file.select", {"type": 'RIGHTMOUSE', "value": 'CLICK'},
{"properties": [("open", False)]}),
@@ -1239,6 +1240,8 @@ def km_file_browser_main(params):
("file.select_box", {"type": 'EVT_TWEAK_L', "value": 'ANY', "shift": True},
{"properties": [("mode", 'ADD')]}),
("file.highlight", {"type": 'MOUSEMOVE', "value": 'ANY', "any": True}, None),
("file.sort_column_ui_context", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
op_menu("FILEBROWSER_MT_context_menu", {"type": 'RIGHTMOUSE', "value": 'PRESS'}),
("file.filenum", {"type": 'NUMPAD_PLUS', "value": 'PRESS'},
{"properties": [("increment", 1)]}),
("file.filenum", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "shift": True},

View File

@@ -34,58 +34,131 @@ class FILEBROWSER_HT_header(Header):
layout.menu("FILEBROWSER_MT_view")
row = layout.row(align=True)
row.operator("file.previous", text="", icon='BACK')
row.operator("file.next", text="", icon='FORWARD')
row.operator("file.parent", text="", icon='FILE_PARENT')
row.operator("file.refresh", text="", icon='FILE_REFRESH')
layout.operator_context = 'EXEC_DEFAULT'
layout.operator("file.directory_new", icon='NEWFOLDER', text="")
layout.operator_context = 'INVOKE_DEFAULT'
# can be None when save/reload with a file selector open
if params:
is_lib_browser = params.use_library_browsing
layout.prop(params, "display_type", expand=True, text="")
layout.prop(params, "sort_method", expand=True, text="")
layout.prop(params, "show_hidden", text="", icon='FILE_HIDDEN')
layout.separator_spacer()
layout.template_running_jobs()
if params:
layout.prop(params, "use_filter", text="", icon='FILTER')
row = layout.row(align=True)
row.active = params.use_filter
row.prop(params, "use_filter_folder", text="")
class FILEBROWSER_PT_display(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'HEADER'
bl_label = "Display"
if params.filter_glob:
# if st.active_operator and hasattr(st.active_operator, "filter_glob"):
# row.prop(params, "filter_glob", text="")
row.label(text=params.filter_glob)
else:
row.prop(params, "use_filter_blender", text="")
row.prop(params, "use_filter_backup", text="")
row.prop(params, "use_filter_image", text="")
row.prop(params, "use_filter_movie", text="")
row.prop(params, "use_filter_script", text="")
row.prop(params, "use_filter_font", text="")
row.prop(params, "use_filter_sound", text="")
row.prop(params, "use_filter_text", text="")
@classmethod
def poll(cls, context):
# can be None when save/reload with a file selector open
return context.space_data.params is not None
if is_lib_browser:
row.prop(params, "use_filter_blendid", text="")
if params.use_filter_blendid:
row.separator()
row.prop(params, "filter_id_category", text="")
def draw(self, context):
layout = self.layout
row.separator()
row.prop(params, "filter_search", text="", icon='VIEWZOOM')
space = context.space_data
params = space.params
is_lib_browser = params.use_library_browsing
layout.label(text="Display as")
layout.column().prop(params, "display_type", expand=True)
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
if params.display_type == 'THUMBNAIL':
layout.prop(params, "display_size", text="Size")
else:
layout.prop(params, "show_details_size", text="Size")
layout.prop(params, "show_details_datetime", text="Date")
layout.prop(params, "recursion_level", text="Recursions")
layout.use_property_split = False
layout.separator()
layout.label(text="Sort by")
layout.column().prop(params, "sort_method", expand=True)
layout.prop(params, "use_sort_invert")
class FILEBROWSER_PT_filter(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'HEADER'
bl_label = "Filter"
@classmethod
def poll(cls, context):
# can be None when save/reload with a file selector open
return context.space_data.params is not None
def draw(self, context):
layout = self.layout
space = context.space_data
params = space.params
is_lib_browser = params.use_library_browsing
row = layout.row(align=True)
row.prop(params, "use_filter", text="", toggle=0)
row.label(text="Filter")
col = layout.column()
col.active = params.use_filter
row = col.row()
row.label(icon='FILE_FOLDER')
row.prop(params, "use_filter_folder", text="Folders", toggle=0)
if params.filter_glob:
col.label(text=params.filter_glob)
else:
row = col.row()
row.label(icon='FILE_BLEND')
row.prop(params, "use_filter_blender",
text=".blend Files", toggle=0)
row = col.row()
row.label(icon='FILE_BACKUP')
row.prop(params, "use_filter_backup",
text="Backup .blend Files", toggle=0)
row = col.row()
row.label(icon='FILE_IMAGE')
row.prop(params, "use_filter_image", text="Image Files", toggle=0)
row = col.row()
row.label(icon='FILE_MOVIE')
row.prop(params, "use_filter_movie", text="Movie Files", toggle=0)
row = col.row()
row.label(icon='FILE_SCRIPT')
row.prop(params, "use_filter_script",
text="Script Files", toggle=0)
row = col.row()
row.label(icon='FILE_FONT')
row.prop(params, "use_filter_font", text="Font Files", toggle=0)
row = col.row()
row.label(icon='FILE_SOUND')
row.prop(params, "use_filter_sound", text="Sound Files", toggle=0)
row = col.row()
row.label(icon='FILE_TEXT')
row.prop(params, "use_filter_text", text="Text Files", toggle=0)
col.separator()
if is_lib_browser:
row = col.row()
row.label(icon='BLANK1') # Indentation
row.prop(params, "use_filter_blendid",
text="Blender IDs", toggle=0)
if params.use_filter_blendid:
row = col.row()
row.label(icon='BLANK1') # Indentation
row.prop(params, "filter_id_category", text="")
col.separator()
layout.prop(params, "show_hidden")
def panel_poll_is_upper_region(region):
# The upper region is left-aligned, the lower is split into it then.
return region.alignment == 'LEFT'
class FILEBROWSER_UL_dir(UIList):
@@ -119,10 +192,13 @@ class FILEBROWSER_UL_dir(UIList):
class FILEBROWSER_PT_bookmarks_volumes(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'TOOLS'
bl_options = {'DEFAULT_CLOSED'}
bl_category = "Bookmarks"
bl_label = "Volumes"
@classmethod
def poll(cls, context):
return panel_poll_is_upper_region(context.region)
def draw(self, context):
layout = self.layout
space = context.space_data
@@ -141,7 +217,7 @@ class FILEBROWSER_PT_bookmarks_system(Panel):
@classmethod
def poll(cls, context):
return not context.preferences.filepaths.hide_system_bookmarks
return not context.preferences.filepaths.hide_system_bookmarks and panel_poll_is_upper_region(context.region)
def draw(self, context):
layout = self.layout
@@ -161,8 +237,10 @@ class FILEBROWSER_MT_bookmarks_context_menu(Menu):
layout.operator("file.bookmark_cleanup", icon='X', text="Cleanup")
layout.separator()
layout.operator("file.bookmark_move", icon='TRIA_UP_BAR', text="Move To Top").direction = 'TOP'
layout.operator("file.bookmark_move", icon='TRIA_DOWN_BAR', text="Move To Bottom").direction = 'BOTTOM'
layout.operator("file.bookmark_move", icon='TRIA_UP_BAR',
text="Move To Top").direction = 'TOP'
layout.operator("file.bookmark_move", icon='TRIA_DOWN_BAR',
text="Move To Bottom").direction = 'BOTTOM'
class FILEBROWSER_PT_bookmarks_favorites(Panel):
@@ -171,6 +249,10 @@ class FILEBROWSER_PT_bookmarks_favorites(Panel):
bl_category = "Bookmarks"
bl_label = "Favorites"
@classmethod
def poll(cls, context):
return panel_poll_is_upper_region(context.region)
def draw(self, context):
layout = self.layout
space = context.space_data
@@ -185,12 +267,15 @@ class FILEBROWSER_PT_bookmarks_favorites(Panel):
col = row.column(align=True)
col.operator("file.bookmark_add", icon='ADD', text="")
col.operator("file.bookmark_delete", icon='REMOVE', text="")
col.menu("FILEBROWSER_MT_bookmarks_context_menu", icon='DOWNARROW_HLT', text="")
col.menu("FILEBROWSER_MT_bookmarks_context_menu",
icon='DOWNARROW_HLT', text="")
if num_rows > 1:
col.separator()
col.operator("file.bookmark_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("file.bookmark_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
col.operator("file.bookmark_move", icon='TRIA_UP',
text="").direction = 'UP'
col.operator("file.bookmark_move", icon='TRIA_DOWN',
text="").direction = 'DOWN'
else:
layout.operator("file.bookmark_add", icon='ADD')
@@ -203,7 +288,7 @@ class FILEBROWSER_PT_bookmarks_recents(Panel):
@classmethod
def poll(cls, context):
return not context.preferences.filepaths.hide_recent_locations
return not context.preferences.filepaths.hide_recent_locations and panel_poll_is_upper_region(context.region)
def draw(self, context):
layout = self.layout
@@ -227,7 +312,7 @@ class FILEBROWSER_PT_advanced_filter(Panel):
@classmethod
def poll(cls, context):
# only useful in append/link (library) context currently...
return context.space_data.params.use_library_browsing
return context.space_data.params.use_library_browsing and panel_poll_is_upper_region(context.region)
def draw(self, context):
layout = self.layout
@@ -242,6 +327,133 @@ class FILEBROWSER_PT_advanced_filter(Panel):
col.prop(params, "filter_id")
class FILEBROWSER_PT_options_toggle(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'TOOLS'
bl_label = "Options Toggle"
bl_options = {'HIDE_HEADER'}
@classmethod
def poll(cls, context):
sfile = context.space_data
return context.region.alignment == 'BOTTOM' and sfile.active_operator
def is_option_region_visible(self, context):
for region in context.area.regions:
if region.type == 'TOOL_PROPS' and region.width <= 1:
return False
return True
def draw(self, context):
layout = self.layout
label = "Hide Options" if self.is_option_region_visible(
context) else "Options"
layout.scale_x = 1.3
layout.scale_y = 1.3
layout.operator("screen.region_toggle",
text=label).region_type = 'TOOL_PROPS'
class FILEBROWSER_PT_directory_path(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'UI'
bl_label = "Directory Path"
bl_category = "Attributes"
bl_options = {'HIDE_HEADER'}
def is_header_visible(self, context):
for region in context.area.regions:
if region.type == 'HEADER' and region.height <= 1:
return False
return True
def draw(self, context):
layout = self.layout
space = context.space_data
params = space.params
layout.scale_x = 1.3
layout.scale_y = 1.3
row = layout.row()
subrow = row.row(align=True)
subrow.operator("file.previous", text="", icon='BACK')
subrow.operator("file.next", text="", icon='FORWARD')
subrow.operator("file.parent", text="", icon='FILE_PARENT')
subrow.operator("file.refresh", text="", icon='FILE_REFRESH')
row.operator("file.directory_new", icon='NEWFOLDER', text="")
subrow = row.row()
subrow.prop(params, "directory", text="")
subrow = row.row()
subrow.scale_x = 0.5
subrow.prop(params, "filter_search", text="", icon='VIEWZOOM')
# Uses prop_with_popover() as popover() only adds the triangle icon in headers.
row.prop_with_popover(
params,
"display_type",
panel="FILEBROWSER_PT_display",
text="",
icon_only=True,
)
row.prop_with_popover(
params,
"display_type",
panel="FILEBROWSER_PT_filter",
text="",
icon='FILTER',
icon_only=True,
)
class FILEBROWSER_PT_file_operation(Panel):
bl_space_type = 'FILE_BROWSER'
bl_region_type = 'EXECUTE'
bl_label = "Execute File Operation"
bl_options = {'HIDE_HEADER'}
@classmethod
def poll(cls, context):
return context.space_data.active_operator
def draw(self, context):
import sys
layout = self.layout
space = context.space_data
params = space.params
layout.scale_x = 1.3
layout.scale_y = 1.3
row = layout.row()
sub = row.row()
sub.prop(params, "filename", text="")
sub = row.row()
sub.ui_units_x = 5
# subsub = sub.row(align=True)
# subsub.operator("file.filenum", text="", icon='ADD').increment = 1
# subsub.operator("file.filenum", text="", icon='REMOVE').increment = -1
# organize buttons according to the OS standard
if sys.platform != "win":
sub.operator("FILE_OT_cancel", text="Cancel")
subsub = sub.row()
subsub.active_default = True
subsub.operator("FILE_OT_execute", text=params.title)
if sys.platform == "win":
sub.operator("FILE_OT_cancel", text="Cancel")
class FILEBROWSER_MT_view(Menu):
bl_label = "View"
@@ -250,7 +462,7 @@ class FILEBROWSER_MT_view(Menu):
st = context.space_data
params = st.params
layout.prop(st, "show_region_toolbar")
layout.prop(st, "show_region_toolbar", text="Source List")
layout.prop(st, "show_region_ui", text="File Path")
layout.separator()
@@ -263,8 +475,46 @@ class FILEBROWSER_MT_view(Menu):
layout.menu("INFO_MT_area")
class FILEBROWSER_MT_context_menu(Menu):
bl_label = "Files Context Menu"
def draw(self, context):
layout = self.layout
st = context.space_data
params = st.params
layout.operator("file.previous", text="Back")
layout.operator("file.next", text="Forward")
layout.operator("file.parent", text="Go to Parent")
layout.operator("file.refresh", text="Refresh")
layout.separator()
layout.operator("file.filenum", text="Increase Number",
icon='ADD').increment = 1
layout.operator("file.filenum", text="Decrease Number",
icon='REMOVE').increment = -1
layout.separator()
layout.operator("file.rename", text="Rename")
# layout.operator("file.delete")
layout.operator("file.directory_new", text="New Folder")
layout.operator("file.bookmark_add", text="Add Bookmark")
layout.separator()
layout.prop_menu_enum(params, "display_type")
if params.display_type == 'THUMBNAIL':
layout.prop_menu_enum(params, "display_size")
layout.prop_menu_enum(params, "recursion_level", text="Recursions")
layout.prop_menu_enum(params, "sort_method")
classes = (
FILEBROWSER_HT_header,
FILEBROWSER_PT_display,
FILEBROWSER_PT_filter,
FILEBROWSER_UL_dir,
FILEBROWSER_PT_bookmarks_volumes,
FILEBROWSER_PT_bookmarks_system,
@@ -272,7 +522,11 @@ classes = (
FILEBROWSER_PT_bookmarks_favorites,
FILEBROWSER_PT_bookmarks_recents,
FILEBROWSER_PT_advanced_filter,
FILEBROWSER_PT_directory_path,
FILEBROWSER_PT_file_operation,
FILEBROWSER_PT_options_toggle,
FILEBROWSER_MT_view,
FILEBROWSER_MT_context_menu,
)
if __name__ == "__main__": # only for live edit.

View File

@@ -99,8 +99,13 @@ void BLI_filelist_entry_size_to_string(const struct stat *st,
void BLI_filelist_entry_mode_to_string(
const struct stat *st, const bool compact, char r_mode1[], char r_mode2[], char r_mode3[]);
void BLI_filelist_entry_owner_to_string(const struct stat *st, const bool compact, char r_owner[]);
void BLI_filelist_entry_datetime_to_string(
const struct stat *st, const int64_t ts, const bool compact, char r_time[], char r_date[]);
void BLI_filelist_entry_datetime_to_string(const struct stat *st,
const int64_t ts,
const bool compact,
char r_time[],
char r_date[],
bool *r_is_today,
bool *r_is_yesterday);
/* Files */

View File

@@ -261,36 +261,17 @@ unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_
*/
void BLI_filelist_entry_size_to_string(const struct stat *st,
const uint64_t sz,
const bool compact,
/* Used to change MB -> M, etc. - is that really useful? */
const bool UNUSED(compact),
char r_size[FILELIST_DIRENTRY_SIZE_LEN])
{
double size;
const char *fmt;
const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL};
const char *units_compact[] = {"K", "M", "G", "T", NULL};
const char *unit = "B";
/*
* Seems st_size is signed 32-bit value in *nix and Windows. This
* will buy us some time until files get bigger than 4GB or until
* everyone starts using __USE_FILE_OFFSET64 or equivalent.
*/
size = (double)(st ? st->st_size : sz);
if (size > 1024.0) {
const char **u;
for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1);
u++, size /= 1024.0) {
/* pass */
}
fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s");
unit = *u;
}
else {
fmt = "%.0f %s";
}
BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit);
double size = (double)(st ? st->st_size : sz);
BLI_str_format_byte_unit(r_size, size, true);
}
/**
@@ -366,14 +347,45 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st,
/**
* Convert given entry's time into human-readable strings.
*
* \param r_is_today: optional, returns true if the date matches today's.
* \param r_is_yesterday: optional, returns true if the date matches yesterday's.
*/
void BLI_filelist_entry_datetime_to_string(const struct stat *st,
const int64_t ts,
const bool compact,
char r_time[FILELIST_DIRENTRY_TIME_LEN],
char r_date[FILELIST_DIRENTRY_DATE_LEN])
char r_date[FILELIST_DIRENTRY_DATE_LEN],
bool *r_is_today,
bool *r_is_yesterday)
{
time_t ts_mtime = ts;
int today_year = 0;
int today_yday = 0;
int yesterday_year = 0;
int yesterday_yday = 0;
if (r_is_today || r_is_yesterday) {
/* Localtime() has only one buffer so need to get data out before called again. */
const time_t ts_now = time(NULL);
struct tm *today = localtime(&ts_now);
today_year = today->tm_year;
today_yday = today->tm_yday;
/* Handle a yesterday that spans a year */
today->tm_mday--;
mktime(today);
yesterday_year = today->tm_year;
yesterday_yday = today->tm_yday;
if (r_is_today) {
*r_is_today = false;
}
if (r_is_yesterday) {
*r_is_yesterday = false;
}
}
const time_t ts_mtime = ts;
const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime);
const time_t zero = 0;
@@ -385,12 +397,20 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st,
if (r_time) {
strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm);
}
if (r_date) {
strftime(r_date,
sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN,
compact ? "%d/%m/%y" : "%d-%b-%y",
compact ? "%d/%m/%y" : "%d %b %Y",
tm);
}
if (r_is_today && (tm->tm_year == today_year) && (tm->tm_yday == today_yday)) {
*r_is_today = true;
}
else if (r_is_yesterday && (tm->tm_year == yesterday_year) && (tm->tm_yday == yesterday_yday)) {
*r_is_yesterday = true;
}
}
/**

View File

@@ -3722,5 +3722,39 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
/* Versioning code until next subversion bump goes here. */
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_FILE) {
SpaceFile *sfile = (SpaceFile *)sl;
ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
ARegion *ar_ui = do_versions_find_region(regionbase, RGN_TYPE_UI);
ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
ARegion *ar_toolprops = do_versions_find_region_or_null(regionbase,
RGN_TYPE_TOOL_PROPS);
/* Reinsert UI region so that it spawns entire area width */
BLI_remlink(regionbase, ar_ui);
BLI_insertlinkafter(regionbase, ar_header, ar_ui);
ar_ui->flag |= RGN_FLAG_DYNAMIC_SIZE;
if (ar_toolprops && (ar_toolprops->alignment == (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
SpaceType *stype = BKE_spacetype_from_id(sl->spacetype);
/* Remove empty region at old location. */
BLI_assert(sfile->op == NULL);
BKE_area_region_free(stype, ar_toolprops);
BLI_freelinkN(regionbase, ar_toolprops);
}
if (sfile->params) {
sfile->params->details_flags |= FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
}
}
}
}
}
}
}

View File

@@ -150,6 +150,7 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
* Include next version bump.
*/
{
FROM_DEFAULT_V4_UCHAR(space_file.execution_buts);
}
#undef FROM_DEFAULT_V4_UCHAR

View File

@@ -34,17 +34,32 @@ struct wmWindowManager;
#define FILE_LAYOUT_HOR 1
#define FILE_LAYOUT_VER 2
#define MAX_FILE_COLUMN 4
typedef enum FileListColumns {
typedef enum FileAttributeColumnType {
COLUMN_NONE = -1,
COLUMN_NAME = 0,
COLUMN_DATE,
COLUMN_TIME,
COLUMN_DATETIME,
COLUMN_SIZE,
} FileListColumns;
ATTRIBUTE_COLUMN_MAX
} FileAttributeColumnType;
typedef struct FileAttributeColumn {
/** UI name for this column */
const char *name;
float width;
/* The sort type to use when sorting by this column. */
int sort_type; /* eFileSortType */
/* Alignment of column texts, header text is always left aligned */
int text_align; /* eFontStyle_Align */
} FileAttributeColumn;
typedef struct FileLayout {
/* view settings - XXX - move into own struct */
int offset_top;
/* Height of the header for the different FileAttributeColumn's. */
int attribute_column_header_h;
int prv_w;
int prv_h;
int tile_w;
@@ -54,13 +69,17 @@ typedef struct FileLayout {
int prv_border_x;
int prv_border_y;
int rows;
int columns;
/* Those are the major layout columns the files are distributed across, not to be confused with
* 'attribute_columns' array below. */
int flow_columns;
int width;
int height;
int flag;
int dirty;
int textheight;
float column_widths[MAX_FILE_COLUMN];
/* The columns for each item (name, modification date/time, size). Not to be confused with the
* 'flow_columns' above. */
FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX];
/* When we change display size, we may have to update static strings like size of files... */
short curr_size;
@@ -72,6 +91,7 @@ typedef struct FileSelection {
} FileSelection;
struct rcti;
struct View2D;
struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile);
@@ -87,6 +107,17 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *ar);
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y);
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const struct rcti *rect);
void ED_fileselect_layout_maskrect(const FileLayout *layout,
const struct View2D *v2d,
struct rcti *r_rect);
bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout,
const struct View2D *v2d,
int x,
int y);
bool ED_fileselect_layout_isect_rect(const FileLayout *layout,
const struct View2D *v2d,
const struct rcti *rect,
struct rcti *r_dst);
void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);

View File

@@ -2244,6 +2244,8 @@ int UI_idcode_icon_get(const int idcode)
return ICON_FONT_DATA;
case ID_WO:
return ICON_WORLD_DATA;
case ID_WS:
return ICON_WORKSPACE;
default:
return ICON_NONE;
}

View File

@@ -1265,9 +1265,6 @@ static void region_rect_recursive(
else if (ED_area_is_global(sa)) {
prefsizey = ED_region_global_size_y();
}
else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
}
else {
prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
}

View File

@@ -3935,6 +3935,65 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Region Toggle Operator
* \{ */
static int region_toggle_exec(bContext *C, wmOperator *op)
{
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "region_type");
ARegion *region;
if (RNA_property_is_set(op->ptr, prop)) {
region = BKE_area_find_region_type(CTX_wm_area(C), RNA_property_enum_get(op->ptr, prop));
}
else {
region = CTX_wm_region(C);
}
if (region) {
ED_region_toggle_hidden(C, region);
}
ED_region_tag_redraw(region);
return OPERATOR_FINISHED;
}
static bool region_toggle_poll(bContext *C)
{
ScrArea *area = CTX_wm_area(C);
/* don't flip anything around in topbar */
if (area && area->spacetype == SPACE_TOPBAR) {
CTX_wm_operator_poll_msg_set(C, "Toggling regions in the Top-bar is not allowed");
return 0;
}
return ED_operator_areaactive(C);
}
static void SCREEN_OT_region_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Toggle Region";
ot->idname = "SCREEN_OT_region_toggle";
ot->description = "Hide or unhide the region";
/* api callbacks */
ot->exec = region_toggle_exec;
ot->poll = region_toggle_poll;
ot->flag = 0;
RNA_def_enum(ot->srna,
"region_type",
rna_enum_region_type_items,
0,
"Region Type",
"Type of the region to toggle");
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Region Flip Operator
* \{ */
@@ -5361,6 +5420,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_area_swap);
WM_operatortype_append(SCREEN_OT_region_quadview);
WM_operatortype_append(SCREEN_OT_region_scale);
WM_operatortype_append(SCREEN_OT_region_toggle);
WM_operatortype_append(SCREEN_OT_region_flip);
WM_operatortype_append(SCREEN_OT_header_toggle_menus);
WM_operatortype_append(SCREEN_OT_region_context_menu);

View File

@@ -710,7 +710,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
FILE_SPECIAL,
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
#ifdef WITH_AUDASPACE

View File

@@ -26,6 +26,7 @@
#include <errno.h>
#include "BLI_blenlib.h"
#include "BLI_fileops_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -77,234 +78,6 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char
return BLI_strdup(dyn_tooltip);
}
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
* The controls are laid out as follows:
*
* -------------------------------------------
* | Directory input | execute |
* -------------------------------------------
* | Filename input | + | - | cancel |
* -------------------------------------------
*
* The input widgets will stretch to fill any excess space.
* When there isn't enough space for all controls to be shown, they are
* hidden in this order: x/-, execute/cancel, input widgets.
*/
void file_draw_buttons(const bContext *C, ARegion *ar)
{
/* Button layout. */
const int max_x = ar->winx - 10;
const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
const int input_minw = 20;
const int btn_h = UI_UNIT_Y;
const int btn_fn_w = UI_UNIT_X;
const int btn_minw = 80;
const int btn_margin = 20;
const int separator = 4;
/* Additional locals. */
char uiblockstr[32];
int loadbutton;
int fnumbuttons;
int min_x = 10;
int chan_offs = 0;
int available_w = max_x - min_x;
int line1_w = available_w;
int line2_w = available_w;
uiBut *but;
uiBlock *block;
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
ARegion *artmp;
const bool is_browse_only = (sfile->op == NULL);
/* Initialize UI block. */
BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
/* exception to make space for collapsed region icon */
for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
chan_offs = 16;
min_x += chan_offs;
available_w -= chan_offs;
}
}
/* Is there enough space for the execute / cancel buttons? */
if (is_browse_only) {
loadbutton = 0;
}
else {
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
CLAMP_MIN(loadbutton, btn_minw);
if (available_w <= loadbutton + separator + input_minw) {
loadbutton = 0;
}
}
if (loadbutton) {
line1_w -= (loadbutton + separator);
line2_w = line1_w;
}
/* Is there enough space for file number increment/decrement buttons? */
fnumbuttons = 2 * btn_fn_w;
if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
fnumbuttons = 0;
}
else {
line2_w -= (fnumbuttons + separator);
}
/* Text input fields for directory and file. */
if (available_w > 0) {
const struct FileDirEntry *file = sfile->files ?
filelist_file(sfile->files, params->active_file) :
NULL;
int overwrite_alert = file_draw_check_exists(sfile);
const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
/* callbacks for operator check functions */
UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
but = uiDefBut(block,
UI_BTYPE_TEXT,
-1,
"",
min_x,
line1_y,
line1_w - chan_offs,
btn_h,
params->dir,
0.0,
(float)FILE_MAX,
0,
0,
TIP_("File path"));
UI_but_func_complete_set(but, autocomplete_directory, NULL);
UI_but_flag_enable(but, UI_BUT_NO_UTF8);
UI_but_flag_disable(but, UI_BUT_UNDO);
UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
/* TODO, directory editing is non-functional while a library is loaded
* until this is properly supported just disable it. */
if (sfile->files && filelist_lib(sfile->files)) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
but = uiDefBut(
block,
UI_BTYPE_TEXT,
-1,
"",
min_x,
line2_y,
line2_w - chan_offs,
btn_h,
is_active_dir ? (char *)"" : params->file,
0.0,
(float)FILE_MAXFILE,
0,
0,
TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
UI_but_func_complete_set(but, autocomplete_file, NULL);
UI_but_flag_enable(but, UI_BUT_NO_UTF8);
UI_but_flag_disable(but, UI_BUT_UNDO);
/* silly workaround calling NFunc to ensure this does not get called
* immediate ui_apply_but_func but only after button deactivates */
UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
/* check if this overrides a file and if the operator option is used */
if (overwrite_alert) {
UI_but_flag_enable(but, UI_BUT_REDALERT);
}
}
/* clear func */
UI_block_func_set(block, NULL, NULL, NULL);
}
/* Filename number increment / decrement buttons. */
if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
UI_block_align_begin(block);
but = uiDefIconButO(block,
UI_BTYPE_BUT,
"FILE_OT_filenum",
0,
ICON_REMOVE,
min_x + line2_w + separator - chan_offs,
line2_y,
btn_fn_w,
btn_h,
TIP_("Decrement the filename number"));
RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
but = uiDefIconButO(block,
UI_BTYPE_BUT,
"FILE_OT_filenum",
0,
ICON_ADD,
min_x + line2_w + separator + btn_fn_w - chan_offs,
line2_y,
btn_fn_w,
btn_h,
TIP_("Increment the filename number"));
RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
UI_block_align_end(block);
}
/* Execute / cancel buttons. */
if (loadbutton) {
const struct FileDirEntry *file = sfile->files ?
filelist_file(sfile->files, params->active_file) :
NULL;
char const *str_exec;
if (file && FILENAME_IS_PARENT(file->relpath)) {
str_exec = IFACE_("Parent Directory");
}
else if (file && file->typeflag & FILE_TYPE_DIR) {
str_exec = IFACE_("Open Directory");
}
else {
str_exec = params->title; /* params->title is already translated! */
}
but = uiDefButO(block,
UI_BTYPE_BUT,
"FILE_OT_execute",
WM_OP_EXEC_REGION_WIN,
str_exec,
max_x - loadbutton,
line1_y,
loadbutton,
btn_h,
"");
/* Just a display hint. */
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
uiDefButO(block,
UI_BTYPE_BUT,
"FILE_OT_cancel",
WM_OP_EXEC_REGION_WIN,
IFACE_("Cancel"),
max_x - loadbutton,
line2_y,
loadbutton,
btn_h,
"");
}
UI_block_end(C, block);
UI_block_draw(C, block);
}
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
float color[4];
@@ -349,7 +122,7 @@ static void file_draw_string(int sx,
rcti rect;
char fname[FILE_MAXFILE];
if (string[0] == '\0') {
if (string[0] == '\0' || width < 1) {
return;
}
@@ -362,7 +135,7 @@ static void file_draw_string(int sx,
/* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
* (for buttons it works) */
rect.xmin = sx;
rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
rect.xmax = sx + round_fl_to_int(width);
rect.ymin = sy - height;
rect.ymax = sy;
@@ -404,8 +177,8 @@ static void file_draw_preview(uiBlock *block,
float scaledx, scaledy;
float scale;
int ex, ey;
bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
bool use_dropshadow = !is_icon &&
(typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
BLI_assert(imb != NULL);
@@ -442,13 +215,27 @@ static void file_draw_preview(uiBlock *block,
/* shadow */
if (use_dropshadow) {
UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
UI_draw_box_shadow(128, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
}
GPU_blend(true);
/* the image */
if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
/* the large image */
float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
if (is_icon) {
/* File and Folder icons draw with lowered opacity until we add themes */
col[3] = 0.6f;
/* Use dark images if background is light */
float bg[3];
UI_GetThemeColor3fv(TH_BACK, bg);
if (rgb_to_grayscale(bg) > 0.5f) {
col[0] = 0;
col[1] = 0;
col[2] = 0;
}
}
else if (typeflags & FILE_TYPE_FTFONT) {
UI_GetThemeColor4fv(TH_TEXT, col);
}
@@ -477,30 +264,61 @@ static void file_draw_preview(uiBlock *block,
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (icon) {
UI_icon_draw_ex((float)xco + (7 * UI_DPI_FAC),
(float)yco + (7 * UI_DPI_FAC),
icon,
icon_aspect,
1.0f,
0.0f,
NULL,
false);
if (icon && (icon != ICON_FILE_FONT)) {
/* size of center icon is scaled to fit container and UI scale */
float icon_x, icon_y;
if (is_icon) {
const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
float icon_opacity = MIN2(icon_aspect, 0.7);
uchar icon_color[4] = {255, 255, 255, 255};
float bg[3];
/* base this off theme color of file or folder later */
UI_GetThemeColor3fv(TH_BACK, bg);
if (rgb_to_grayscale(bg) > 0.5f) {
icon_color[0] = 0;
icon_color[1] = 0;
icon_color[2] = 0;
}
icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.65f));
UI_icon_draw_ex(
icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
}
else {
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
/* Smaller, fainter icon for preview image thumbnail. */
icon_x = xco + (2.0f * UI_DPI_FAC);
icon_y = yco + (2.0f * UI_DPI_FAC);
UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
}
}
/* border */
if (use_dropshadow) {
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint pos_attr = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint col_attr = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GPU_PRIM_LINE_LOOP, 4);
immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.15f);
immVertex2f(pos_attr, (float)xco + 1, (float)(yco + ey));
immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.2f);
immVertex2f(pos_attr, (float)(xco + ex), (float)(yco + ey));
immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.2f);
immVertex2f(pos_attr, (float)(xco + ex), (float)yco + 1);
immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.3f);
immVertex2f(pos_attr, (float)xco + 1, (float)yco + 1);
immEnd();
immUnbindProgram();
}
but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
/* dragregion */
if (drag) {
@@ -557,6 +375,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
static void draw_background(FileLayout *layout, View2D *v2d)
{
const int item_height = layout->tile_h + (2 * layout->tile_border_y);
int i;
int sy;
@@ -565,9 +384,11 @@ static void draw_background(FileLayout *layout, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -7);
/* alternating flat shade background */
for (i = 0; (i <= layout->rows); i += 2) {
sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) -
layout->tile_border_y;
for (i = 2; (i <= layout->rows + 1); i += 2) {
sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y;
/* Offsett pattern slightly to add scroll effect. */
sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height);
immRectf(pos,
v2d->cur.xmin,
@@ -632,6 +453,176 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
}
}
static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, 11);
immRectf(pos,
v2d->cur.xmin,
v2d->cur.ymax - layout->attribute_column_header_h,
v2d->cur.xmax,
v2d->cur.ymax);
immUnbindProgram();
}
static void draw_columnheader_columns(const FileSelectParams *params,
FileLayout *layout,
const View2D *v2d,
const uchar text_col[4])
{
const float divider_pad = 0.2 * layout->attribute_column_header_h;
int sx = v2d->cur.xmin, sy = v2d->cur.ymax;
for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
column_type++) {
if (!file_attribute_column_type_enabled(params, column_type)) {
continue;
}
const FileAttributeColumn *column = &layout->attribute_columns[column_type];
/* Active sort type triangle */
if (params->sort == column->sort_type) {
float tri_color[4];
rgba_uchar_to_float(tri_color, text_col);
UI_draw_icon_tri(sx + column->width - (0.3f * U.widget_unit) -
ATTRIBUTE_COLUMN_PADDING / 2.0f,
sy + (0.1f * U.widget_unit) - (layout->attribute_column_header_h / 2),
(params->flag & FILE_SORT_INVERT) ? 't' : 'v',
tri_color);
}
file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
sy - layout->tile_border_y,
IFACE_(column->name),
column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
layout->attribute_column_header_h - layout->tile_border_y,
UI_STYLE_TEXT_LEFT,
text_col);
/* Separator line */
if (column_type != COLUMN_NAME) {
uint pos = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, -10);
immBegin(GPU_PRIM_LINES, 2);
immVertex2f(pos, sx - 1, sy - divider_pad);
immVertex2f(pos, sx - 1, sy - layout->attribute_column_header_h + divider_pad);
immEnd();
immUnbindProgram();
}
sx += column->width;
}
/* Vertical separator lines line */
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, -10);
immBegin(GPU_PRIM_LINES, 4);
immVertex2f(pos, v2d->cur.xmin, sy);
immVertex2f(pos, v2d->cur.xmax, sy);
immVertex2f(pos, v2d->cur.xmin, sy - layout->attribute_column_header_h);
immVertex2f(pos, v2d->cur.xmax, sy - layout->attribute_column_header_h);
immEnd();
immUnbindProgram();
}
}
/**
* Updates the stat string stored in file->entry if necessary.
*/
static const char *filelist_get_details_column_string(FileAttributeColumnType column,
const FileDirEntry *file,
const bool small_size,
const bool update_stat_strings)
{
switch (column) {
case COLUMN_DATETIME:
if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) {
char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN];
bool is_today, is_yesterday;
BLI_filelist_entry_datetime_to_string(
NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday);
if (is_today || is_yesterday) {
BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date));
}
BLI_snprintf(
file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time);
}
return file->entry->datetime_str;
}
break;
case COLUMN_SIZE:
if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
!(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
BLI_filelist_entry_size_to_string(
NULL, file->entry->size, small_size, file->entry->size_str);
}
return file->entry->size_str;
}
break;
default:
break;
}
return NULL;
}
static void draw_details_columns(const FileSelectParams *params,
const FileLayout *layout,
const FileDirEntry *file,
const int pos_x,
const int pos_y,
const uchar text_col[4])
{
const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
int sx = pos_x - layout->tile_border_x - (UI_UNIT_X * 0.1f), sy = pos_y;
for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
column_type++) {
const FileAttributeColumn *column = &layout->attribute_columns[column_type];
/* Name column is not a detail column (should already be drawn), always skip here. */
if (column_type == COLUMN_NAME) {
sx += column->width;
continue;
}
if (!file_attribute_column_type_enabled(params, column_type)) {
continue;
}
const char *str = filelist_get_details_column_string(
column_type, file, small_size, update_stat_strings);
if (str) {
file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
sy - layout->tile_border_y,
IFACE_(str),
column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
layout->tile_h,
column->text_align,
text_col);
}
sx += column->width;
}
}
void file_draw_list(const bContext *C, ARegion *ar)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -652,18 +643,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
bool is_icon;
eFontStyle_Align align;
bool do_drag;
int column_space = 0.6f * UI_UNIT_X;
unsigned char text_col[4];
const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY);
const float thumb_icon_aspect = MIN2(64.0f / (float)(params->thumbnail_size), 1.0f);
numfiles = filelist_files_ensure(files);
if (params->display != FILE_IMGDISPLAY) {
draw_background(layout, v2d);
draw_dividers(layout, v2d);
}
@@ -679,13 +666,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
numfiles_layout += layout->rows;
}
else {
numfiles_layout += layout->columns;
numfiles_layout += layout->flow_columns;
}
filelist_file_cache_slidingwindow_set(files, numfiles_layout);
textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w :
(int)layout->column_widths[COLUMN_NAME];
textwidth = (FILE_IMGDISPLAY == params->display) ?
layout->tile_w :
round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width);
textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
@@ -719,11 +707,16 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLF_batch_draw_begin();
UI_GetThemeColor4ubv(TH_TEXT, text_col);
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
unsigned int file_selflag;
char path[FILE_MAX_LIBEXTRA];
int padx = 0.1f * UI_UNIT_X;
int icon_ofs = 0;
ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
sx += (int)(v2d->tot.xmin + padx);
sy = (int)(v2d->tot.ymax - sy);
file = filelist_file(files, i);
@@ -737,15 +730,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 :
0;
const short width = ELEM(params->display, FILE_VERTICALDISPLAY, FILE_HORIZONTALDISPLAY) ?
layout->tile_w - (2 * padx) :
layout->tile_w;
BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
draw_tile(sx,
sy - 1,
layout->tile_w + 4,
sfile->layout->tile_h + layout->tile_border_y,
colorid,
shade);
draw_tile(
sx, sy - 1, width, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
}
}
UI_draw_roundbox_corner_set(UI_CNR_NONE);
@@ -778,38 +770,28 @@ void file_draw_list(const bContext *C, ARegion *ar)
file_draw_icon(block,
path,
sx,
sy - (UI_UNIT_Y / 6),
sy - layout->tile_border_y,
filelist_geticon(files, i, true),
ICON_DEFAULT_WIDTH_SCALE,
ICON_DEFAULT_HEIGHT_SCALE,
do_drag);
sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
UI_GetThemeColor4ubv(TH_TEXT, text_col);
if (file_selflag & FILE_SEL_EDITING) {
uiBut *but;
short width;
if (params->display == FILE_SHORTDISPLAY) {
width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
}
else if (params->display == FILE_LONGDISPLAY) {
width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
}
else {
BLI_assert(params->display == FILE_IMGDISPLAY);
width = textwidth;
}
const short width = (params->display == FILE_IMGDISPLAY) ?
textwidth :
layout->attribute_columns[COLUMN_NAME].width -
ATTRIBUTE_COLUMN_PADDING;
but = uiDefBut(block,
UI_BTYPE_TEXT,
1,
"",
sx,
sx + icon_ofs,
sy - layout->tile_h - 0.15f * UI_UNIT_X,
width,
width - icon_ofs,
textheight,
sfile->params->renamefile,
1.0f,
@@ -825,74 +807,19 @@ void file_draw_list(const bContext *C, ARegion *ar)
sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
}
}
if (!(file_selflag & FILE_SEL_EDITING)) {
int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight :
sy;
file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
else {
const int txpos = (params->display == FILE_IMGDISPLAY) ? sx : sx + 1 + icon_ofs;
const int typos = (params->display == FILE_IMGDISPLAY) ?
sy - layout->tile_h + layout->textheight :
sy - layout->tile_border_y;
const int twidth = (params->display == FILE_IMGDISPLAY) ?
textwidth :
textwidth - 1 - icon_ofs - padx - layout->tile_border_x;
file_draw_string(txpos, typos, file->name, (float)twidth, textheight, align, text_col);
}
sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
if (params->display == FILE_SHORTDISPLAY) {
if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
!(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
BLI_filelist_entry_size_to_string(
NULL, file->entry->size, small_size, file->entry->size_str);
}
file_draw_string(sx,
sy,
file->entry->size_str,
layout->column_widths[COLUMN_SIZE],
layout->tile_h,
align,
text_col);
}
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
}
else if (params->display == FILE_LONGDISPLAY) {
if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
BLI_filelist_entry_datetime_to_string(
NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
}
file_draw_string(sx,
sy,
file->entry->date_str,
layout->column_widths[COLUMN_DATE],
layout->tile_h,
align,
text_col);
sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
file_draw_string(sx,
sy,
file->entry->time_str,
layout->column_widths[COLUMN_TIME],
layout->tile_h,
align,
text_col);
sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
}
else {
sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
}
if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
!(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
BLI_filelist_entry_size_to_string(
NULL, file->entry->size, small_size, file->entry->size_str);
}
file_draw_string(sx,
sy,
file->entry->size_str,
layout->column_widths[COLUMN_SIZE],
layout->tile_h,
align,
text_col);
}
sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
if (params->display != FILE_IMGDISPLAY) {
draw_details_columns(params, layout, file, sx, sy, text_col);
}
}
@@ -901,5 +828,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_block_end(C, block);
UI_block_draw(C, block);
/* Draw last, on top of file list. */
if (draw_columnheader) {
draw_columnheader_background(layout, v2d);
draw_columnheader_columns(params, layout, v2d, text_col);
}
layout->curr_size = params->thumbnail_size;
}

View File

@@ -30,9 +30,11 @@ struct ARegion;
struct ARegionType;
struct FileSelectParams;
struct SpaceFile;
struct View2D;
/* file_ops.c */
struct ARegion *file_tools_region(struct ScrArea *sa);
struct ARegion *file_tool_props_region(struct ScrArea *sa);
/* file_draw.c */
#define TILE_BORDER_X (UI_UNIT_X / 4)
@@ -42,9 +44,10 @@ struct ARegion *file_tools_region(struct ScrArea *sa);
#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2)
#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6)
#define ATTRIBUTE_COLUMN_PADDING (0.5f * UI_UNIT_X)
#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
void file_draw_buttons(const bContext *C, ARegion *ar);
void file_calc_previews(const bContext *C, ARegion *ar);
void file_draw_list(const bContext *C, ARegion *ar);
@@ -64,6 +67,7 @@ typedef enum WalkSelectDirection {
} WalkSelectDirections;
void FILE_OT_highlight(struct wmOperatorType *ot);
void FILE_OT_sort_column_ui_context(struct wmOperatorType *ot);
void FILE_OT_select(struct wmOperatorType *ot);
void FILE_OT_select_walk(struct wmOperatorType *ot);
void FILE_OT_select_all(struct wmOperatorType *ot);
@@ -112,6 +116,16 @@ void file_operator_to_sfile(bContext *C, struct SpaceFile *sfile, struct wmOpera
/* filesel.c */
void fileselect_file_set(SpaceFile *sfile, const int index);
bool file_attribute_column_type_enabled(const FileSelectParams *params,
FileAttributeColumnType column);
bool file_attribute_column_header_is_inside(const struct View2D *v2d,
const FileLayout *layout,
int x,
int y);
FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
const FileSelectParams *params,
FileLayout *layout,
int x);
float file_string_width(const char *str);
float file_font_pointsize(void);

View File

@@ -78,7 +78,12 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r
BLI_rctf_rcti_copy(&rect_region_fl, rect_region);
/* Okay, manipulating v2d rects here is hacky... */
v2d->mask.ymax -= sfile->layout->offset_top;
v2d->cur.ymax -= sfile->layout->offset_top;
UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl);
v2d->mask.ymax += sfile->layout->offset_top;
v2d->cur.ymax += sfile->layout->offset_top;
BLI_rcti_init(&rect_view,
(int)(v2d->tot.xmin + rect_view_fl.xmin),
@@ -190,7 +195,6 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath);
if (do_diropen == false) {
params->file[0] = '\0';
retval = FILE_SELECT_DIR;
}
/* the path is too long and we are not going up! */
@@ -262,8 +266,8 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i
cur->ymax = cur->ymin + ar->winy;
}
/* up */
else if (cur->ymax < rect.ymax) {
cur->ymax = rect.ymax + layout->tile_border_y;
else if ((cur->ymax - layout->offset_top) < rect.ymax) {
cur->ymax = rect.ymax + layout->tile_border_y + layout->offset_top;
cur->ymin = cur->ymax - ar->winy;
}
/* left - also use if tile is wider than viewbounds so view is aligned to file name */
@@ -278,7 +282,7 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i
}
else {
BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin &&
cur->ymax >= rect.ymax);
(cur->ymax - layout->offset_top) >= rect.ymax);
changed = false;
}
@@ -384,7 +388,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
if (result == OPERATOR_RUNNING_MODAL) {
WM_operator_properties_border_to_rcti(op, &rect);
BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
sel = file_selection_get(C, &rect, 0);
if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
@@ -440,7 +444,7 @@ static int file_box_select_exec(bContext *C, wmOperator *op)
file_deselect_all(sfile, FILE_SEL_SELECTED);
}
BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
@@ -493,7 +497,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
rect.xmin = rect.xmax = event->mval[0];
rect.ymin = rect.ymax = event->mval[1];
if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin)) {
if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &ar->v2d, rect.xmin, rect.ymin)) {
return OPERATOR_CANCELLED;
}
@@ -691,7 +695,7 @@ static bool file_walk_select_do(bContext *C,
if (has_selection) {
ARegion *ar = CTX_wm_region(C);
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->flow_columns;
if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT)) {
@@ -1185,7 +1189,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
mx -= ar->winrct.xmin;
my -= ar->winrct.ymin;
if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
if (ED_fileselect_layout_is_inside_pt(sfile->layout, v2d, mx, my)) {
float fx, fy;
int highlight_file;
@@ -1234,6 +1238,53 @@ void FILE_OT_highlight(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
static int file_column_sort_ui_context_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *event)
{
const ARegion *ar = CTX_wm_region(C);
SpaceFile *sfile = CTX_wm_space_file(C);
if (file_attribute_column_header_is_inside(
&ar->v2d, sfile->layout, event->mval[0], event->mval[1])) {
const FileAttributeColumnType column_type = file_attribute_column_type_find_isect(
&ar->v2d, sfile->params, sfile->layout, event->mval[0]);
if (column_type != COLUMN_NONE) {
const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type];
if (column->sort_type != FILE_SORT_NONE) {
if (sfile->params->sort == column->sort_type) {
/* Already sorting by selected column -> toggle sort invert (three state logic). */
sfile->params->flag ^= FILE_SORT_INVERT;
}
else {
sfile->params->sort = column->sort_type;
sfile->params->flag &= ~FILE_SORT_INVERT;
}
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
}
}
}
return OPERATOR_PASS_THROUGH;
}
void FILE_OT_sort_column_ui_context(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Sort from Column";
ot->description = "Change sorting to use column under cursor";
ot->idname = "FILE_OT_sort_column_ui_context";
/* api callbacks */
ot->invoke = file_column_sort_ui_context_invoke;
ot->poll = ED_operator_file_active;
ot->flag = OPTYPE_INTERNAL;
}
int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1713,7 +1764,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Number of items in a block (i.e. lines in a column in horizontal layout, or columns in a line
* in vertical layout).
*/
const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->columns;
const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->flow_columns;
/* Scroll offset is the first file in the row/column we are editing in. */
if (sfile->scroll_offset == 0) {
@@ -1998,7 +2049,6 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
ot->idname = "FILE_OT_directory_new";
/* api callbacks */
ot->invoke = WM_operator_confirm;
ot->exec = file_directory_new_exec;
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
@@ -2260,10 +2310,29 @@ ARegion *file_tools_region(ScrArea *sa)
arnew->regiontype = RGN_TYPE_TOOLS;
arnew->alignment = RGN_ALIGN_LEFT;
ar = MEM_callocN(sizeof(ARegion), "tool props for file");
BLI_insertlinkafter(&sa->regionbase, arnew, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
return arnew;
}
ARegion *file_tool_props_region(ScrArea *sa)
{
ARegion *ar, *arnew;
if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS)) != NULL) {
return ar;
}
/* add subdiv level; after execute region */
ar = BKE_area_find_region_type(sa, RGN_TYPE_EXECUTE);
/* is error! */
if (ar == NULL) {
return NULL;
}
arnew = MEM_callocN(sizeof(ARegion), "tool props for file");
BLI_insertlinkafter(&sa->regionbase, ar, arnew);
arnew->regiontype = RGN_TYPE_TOOL_PROPS;
arnew->alignment = RGN_ALIGN_RIGHT;
return arnew;
}
@@ -2292,6 +2361,17 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
static bool file_filenum_poll(bContext *C)
{
SpaceFile *sfile = CTX_wm_space_file(C);
if (!ED_operator_file_active(C)) {
return false;
}
return sfile->params && (sfile->params->action_type == FILE_SAVE);
}
/**
* Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
*/
@@ -2349,7 +2429,7 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = file_filenum_exec;
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
ot->poll = file_filenum_poll;
/* props */
RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);

View File

@@ -103,6 +103,7 @@ void file_panels_register(ARegionType *art)
strcpy(pt->idname, "FILE_PT_operator");
strcpy(pt->label, N_("Operator"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->flag = PNL_NO_HEADER;
pt->poll = file_panel_operator_poll;
pt->draw_header = file_panel_operator_header;
pt->draw = file_panel_operator;

View File

@@ -329,25 +329,20 @@ enum {
FL_IS_PENDING = 1 << 2,
FL_NEED_SORTING = 1 << 3,
FL_NEED_FILTERING = 1 << 4,
FL_SORT_INVERT = 1 << 5,
};
#define SPECIAL_IMG_SIZE 48
#define SPECIAL_IMG_ROWS 4
#define SPECIAL_IMG_COLS 4
#define SPECIAL_IMG_SIZE 256
#define SPECIAL_IMG_ROWS 1
#define SPECIAL_IMG_COLS 6
enum {
SPECIAL_IMG_FOLDER = 0,
SPECIAL_IMG_PARENT = 1,
SPECIAL_IMG_REFRESH = 2,
SPECIAL_IMG_BLENDFILE = 3,
SPECIAL_IMG_SOUNDFILE = 4,
SPECIAL_IMG_MOVIEFILE = 5,
SPECIAL_IMG_PYTHONFILE = 6,
SPECIAL_IMG_TEXTFILE = 7,
SPECIAL_IMG_FONTFILE = 8,
SPECIAL_IMG_UNKNOWNFILE = 9,
SPECIAL_IMG_LOADING = 10,
SPECIAL_IMG_BACKUP = 11,
SPECIAL_IMG_DOCUMENT = 0,
SPECIAL_IMG_FOLDER = 1,
SPECIAL_IMG_PARENT = 2,
SPECIAL_IMG_DRIVE_FIXED = 3,
SPECIAL_IMG_DRIVE_ATTACHED = 4,
SPECIAL_IMG_DRIVE_REMOTE = 5,
SPECIAL_IMG_MAX,
};
@@ -369,6 +364,19 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
/* ********** Sort helpers ********** */
struct FileSortData {
bool inverted;
};
static int compare_apply_inverted(int val, const struct FileSortData *sort_data)
{
return sort_data->inverted ? -val : val;
}
/**
* Handles inverted sorting itself (currently there's nothing to invert), so if this returns non-0,
* it should be used as-is and not inverted.
*/
static int compare_direntry_generic(const FileListInternEntry *entry1,
const FileListInternEntry *entry2)
{
@@ -420,10 +428,11 @@ static int compare_direntry_generic(const FileListInternEntry *entry1,
return 0;
}
static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
static int compare_name(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int ret;
@@ -434,13 +443,14 @@ static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
name1 = entry1->name;
name2 = entry2->name;
return BLI_strcasecmp_natural(name1, name2);
return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
static int compare_date(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int64_t time1, time2;
int ret;
@@ -452,22 +462,23 @@ static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
time1 = (int64_t)entry1->st.st_mtime;
time2 = (int64_t)entry2->st.st_mtime;
if (time1 < time2) {
return 1;
return compare_apply_inverted(1, sort_data);
}
if (time1 > time2) {
return -1;
return compare_apply_inverted(-1, sort_data);
}
name1 = entry1->name;
name2 = entry2->name;
return BLI_strcasecmp_natural(name1, name2);
return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
static int compare_size(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
const struct FileSortData *sort_data = user_data;
char *name1, *name2;
uint64_t size1, size2;
int ret;
@@ -479,22 +490,23 @@ static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
size1 = entry1->st.st_size;
size2 = entry2->st.st_size;
if (size1 < size2) {
return 1;
return compare_apply_inverted(1, sort_data);
}
if (size1 > size2) {
return -1;
return compare_apply_inverted(-1, sort_data);
}
name1 = entry1->name;
name2 = entry2->name;
return BLI_strcasecmp_natural(name1, name2);
return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2)
static int compare_extension(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int ret;
@@ -516,10 +528,10 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void
return -1;
}
if (entry1->blentype < entry2->blentype) {
return -1;
return compare_apply_inverted(-1, sort_data);
}
if (entry1->blentype > entry2->blentype) {
return 1;
return compare_apply_inverted(1, sort_data);
}
}
else {
@@ -539,48 +551,58 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void
}
if ((ret = BLI_strcasecmp(sufix1, sufix2))) {
return ret;
return compare_apply_inverted(ret, sort_data);
}
}
name1 = entry1->name;
name2 = entry2->name;
return BLI_strcasecmp_natural(name1, name2);
return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
void filelist_sort(struct FileList *filelist)
{
if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) {
void *sort_cb = NULL;
switch (filelist->sort) {
case FILE_SORT_ALPHA:
BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL);
sort_cb = compare_name;
break;
case FILE_SORT_TIME:
BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL);
sort_cb = compare_date;
break;
case FILE_SORT_SIZE:
BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL);
sort_cb = compare_size;
break;
case FILE_SORT_EXTENSION:
BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL);
sort_cb = compare_extension;
break;
case FILE_SORT_NONE: /* Should never reach this point! */
default:
BLI_assert(0);
break;
}
BLI_listbase_sort_r(
&filelist->filelist_intern.entries,
sort_cb,
&(struct FileSortData){.inverted = (filelist->flags & FL_SORT_INVERT) != 0});
filelist_filter_clear(filelist);
filelist->flags &= ~FL_NEED_SORTING;
}
}
void filelist_setsorting(struct FileList *filelist, const short sort)
void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort)
{
if (filelist->sort != sort) {
const bool was_invert_sort = filelist->flags & FL_SORT_INVERT;
if ((filelist->sort != sort) || (was_invert_sort != invert_sort)) {
filelist->sort = sort;
filelist->flags |= FL_NEED_SORTING;
filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) :
(filelist->flags & ~FL_SORT_INVERT);
}
}
@@ -635,9 +657,9 @@ static bool is_filtered_file(FileListInternEntry *file,
{
bool is_filtered = !is_hidden_file(file->relpath, filter);
if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
if (filter->filter) {
if (filter->filter && (filter->flags & FLF_DO_FILTER)) {
if (file->typeflag & FILE_TYPE_DIR) {
if (file->typeflag &
(FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
@@ -657,6 +679,7 @@ static bool is_filtered_file(FileListInternEntry *file,
}
}
}
/* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -676,9 +699,9 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
if (BLO_library_path_explode(path, dir, &group, &name)) {
is_filtered = !is_hidden_file(file->relpath, filter);
if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
if (filter->filter || filter->filter_id) {
if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
if (file->typeflag & FILE_TYPE_DIR) {
if (file->typeflag &
(FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
@@ -704,6 +727,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
}
}
}
/* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -904,42 +928,12 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char
if (FILENAME_IS_PARENT(relpath)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
}
else if (FILENAME_IS_CURRENT(relpath)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
}
else {
ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
}
}
else if (typeflag & FILE_TYPE_BLENDER) {
ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
}
else if (typeflag & FILE_TYPE_BLENDERLIB) {
ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
}
else if (typeflag & (FILE_TYPE_MOVIE)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
}
else if (typeflag & FILE_TYPE_SOUND) {
ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
}
else if (typeflag & FILE_TYPE_PYSCRIPT) {
ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
}
else if (typeflag & FILE_TYPE_FTFONT) {
ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
}
else if (typeflag & FILE_TYPE_TEXT) {
ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
}
else if (typeflag & FILE_TYPE_IMAGE) {
ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
}
else if (typeflag & FILE_TYPE_BLENDER_BACKUP) {
ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
}
else {
ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
ibuf = gSpecialFileImages[SPECIAL_IMG_DOCUMENT];
}
return ibuf;
@@ -1001,10 +995,13 @@ static int filelist_geticon_ex(const int typeflag,
return ICON_FILE_BLANK;
}
else if (typeflag & FILE_TYPE_COLLADA) {
return ICON_FILE_BLANK;
return ICON_FILE_3D;
}
else if (typeflag & FILE_TYPE_ALEMBIC) {
return ICON_FILE_BLANK;
return ICON_FILE_3D;
}
else if (typeflag & FILE_TYPE_OBJECT_IO) {
return ICON_FILE_3D;
}
else if (typeflag & FILE_TYPE_TEXT) {
return ICON_FILE_TEXT;
@@ -1243,7 +1240,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache)
BLI_task_pool_cancel(cache->previews_pool);
while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
// printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path,
// preview->img);
if (preview->img) {
IMB_freeImBuf(preview->img);
}
@@ -2128,6 +2126,9 @@ int ED_path_extension_type(const char *path)
else if (BLI_path_extension_check(path, ".abc")) {
return FILE_TYPE_ALEMBIC;
}
else if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", NULL)) {
return FILE_TYPE_OBJECT_IO;
}
else if (BLI_path_extension_check_array(path, imb_ext_image)) {
return FILE_TYPE_IMAGE;
}
@@ -2177,9 +2178,9 @@ int ED_file_extension_icon(const char *path)
case FILE_TYPE_BTX:
return ICON_FILE_BLANK;
case FILE_TYPE_COLLADA:
return ICON_FILE_BLANK;
case FILE_TYPE_ALEMBIC:
return ICON_FILE_BLANK;
case FILE_TYPE_OBJECT_IO:
return ICON_FILE_3D;
case FILE_TYPE_TEXT:
return ICON_FILE_TEXT;
default:

View File

@@ -55,7 +55,7 @@ void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
const char *folderlist_peeklastdir(struct ListBase *folderdist);
int folderlist_clear_next(struct SpaceFile *sfile);
void filelist_setsorting(struct FileList *filelist, const short sort);
void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort);
void filelist_sort(struct FileList *filelist);
void filelist_setfilter_options(struct FileList *filelist,

View File

@@ -49,6 +49,8 @@
#include "BLI_utildefines.h"
#include "BLI_fnmatch.h"
#include "BLT_translation.h"
#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -69,6 +71,8 @@
#include "file_intern.h"
#include "filelist.h"
#define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X)
FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
{
if (!sfile->params) {
@@ -99,6 +103,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
sfile->params->filter_glob[0] = '\0';
/* set the default thumbnails size */
sfile->params->thumbnail_size = 128;
/* Show size column by default. */
sfile->params->details_flags = FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
}
params = sfile->params;
@@ -161,6 +167,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->flag &= ~FILE_DIRSEL_ONLY;
}
if ((prop = RNA_struct_find_property(op->ptr, "hide_props_region"))) {
params->flag |= RNA_property_boolean_get(op->ptr, prop) ? FILE_HIDE_TOOL_PROPS : 0;
}
params->filter = 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) {
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
@@ -261,6 +271,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->sort = FILE_SORT_ALPHA;
}
if ((prop = RNA_struct_find_property(op->ptr, "action_type"))) {
params->action_type = RNA_property_enum_get(op->ptr, prop);
}
if (params->display == FILE_DEFAULTDISPLAY) {
if (params->display_previous == FILE_DEFAULTDISPLAY) {
if (U.uiflag & USER_SHOW_THUMBNAILS) {
@@ -268,11 +282,11 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->display = FILE_IMGDISPLAY;
}
else {
params->display = FILE_SHORTDISPLAY;
params->display = FILE_VERTICALDISPLAY;
}
}
else {
params->display = FILE_SHORTDISPLAY;
params->display = FILE_VERTICALDISPLAY;
}
}
else {
@@ -293,7 +307,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->type = FILE_UNIX;
params->flag |= FILE_HIDE_DOT;
params->flag &= ~FILE_DIRSEL_ONLY;
params->display = FILE_SHORTDISPLAY;
params->display = FILE_VERTICALDISPLAY;
params->display_previous = FILE_DEFAULTDISPLAY;
params->sort = FILE_SORT_ALPHA;
params->filter = 0;
@@ -344,7 +358,7 @@ void ED_fileselect_reset_params(SpaceFile *sfile)
void fileselect_file_set(SpaceFile *sfile, const int index)
{
const struct FileDirEntry *file = filelist_file(sfile->files, index);
if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) {
if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) {
BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
}
}
@@ -372,10 +386,10 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
}
else {
const int y_item = layout->tile_h + (2 * layout->tile_border_y);
const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur));
const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur)) - layout->offset_top;
const int y_over = y_item - (y_view % y_item);
numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
return numfiles * layout->columns;
return numfiles * layout->flow_columns;
}
}
@@ -395,19 +409,19 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
}
colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
rowmin = (rect->ymin) / (layout->tile_h + 2 * layout->tile_border_y);
rowmin = (rect->ymin - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
rowmax = (rect->ymax) / (layout->tile_h + 2 * layout->tile_border_y);
rowmax = (rect->ymax - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
if (is_inside(colmin, rowmin, layout->columns, layout->rows) ||
is_inside(colmax, rowmax, layout->columns, layout->rows)) {
CLAMP(colmin, 0, layout->columns - 1);
if (is_inside(colmin, rowmin, layout->flow_columns, layout->rows) ||
is_inside(colmax, rowmax, layout->flow_columns, layout->rows)) {
CLAMP(colmin, 0, layout->flow_columns - 1);
CLAMP(rowmin, 0, layout->rows - 1);
CLAMP(colmax, 0, layout->columns - 1);
CLAMP(colmax, 0, layout->flow_columns - 1);
CLAMP(rowmax, 0, layout->rows - 1);
}
if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) {
if ((colmin > layout->flow_columns - 1) || (rowmin > layout->rows - 1)) {
sel.first = -1;
}
else {
@@ -415,10 +429,10 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
sel.first = layout->rows * colmin + rowmin;
}
else {
sel.first = colmin + layout->columns * rowmin;
sel.first = colmin + layout->flow_columns * rowmin;
}
}
if ((colmax > layout->columns - 1) || (rowmax > layout->rows - 1)) {
if ((colmax > layout->flow_columns - 1) || (rowmax > layout->rows - 1)) {
sel.last = -1;
}
else {
@@ -426,7 +440,7 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
sel.last = layout->rows * colmax + rowmax;
}
else {
sel.last = colmax + layout->columns * rowmax;
sel.last = colmax + layout->flow_columns * rowmax;
}
}
@@ -443,9 +457,9 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
}
offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
offsety = (y) / (layout->tile_h + 2 * layout->tile_border_y);
offsety = (y - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
if (offsetx > layout->columns - 1) {
if (offsetx > layout->flow_columns - 1) {
return -1;
}
if (offsety > layout->rows - 1) {
@@ -456,27 +470,123 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
active_file = layout->rows * offsetx + offsety;
}
else {
active_file = offsetx + layout->columns * offsety;
active_file = offsetx + layout->flow_columns * offsety;
}
return active_file;
}
/**
* Get the currently visible bounds of the layout in screen space. Matches View2D.mask minus the
* top column-header row.
*/
void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect)
{
*r_rect = v2d->mask;
r_rect->ymax -= layout->offset_top;
}
bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y)
{
rcti maskrect;
ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
return BLI_rcti_isect_pt(&maskrect, x, y);
}
bool ED_fileselect_layout_isect_rect(const FileLayout *layout,
const View2D *v2d,
const rcti *rect,
rcti *r_dst)
{
rcti maskrect;
ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
return BLI_rcti_isect(&maskrect, rect, r_dst);
}
void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y)
{
if (layout->flag == FILE_LAYOUT_HOR) {
*x = layout->tile_border_x +
(tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
*y = layout->tile_border_y +
*y = layout->offset_top + layout->tile_border_y +
(tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
}
else {
*x = layout->tile_border_x +
((tile) % layout->columns) * (layout->tile_w + 2 * layout->tile_border_x);
*y = layout->tile_border_y +
((tile) / layout->columns) * (layout->tile_h + 2 * layout->tile_border_y);
((tile) % layout->flow_columns) * (layout->tile_w + 2 * layout->tile_border_x);
*y = layout->offset_top + layout->tile_border_y +
((tile) / layout->flow_columns) * (layout->tile_h + 2 * layout->tile_border_y);
}
}
/**
* Check if the region coordinate defined by \a x and \a y are inside the column header.
*/
bool file_attribute_column_header_is_inside(const View2D *v2d,
const FileLayout *layout,
int x,
int y)
{
rcti header_rect = v2d->mask;
header_rect.ymin = header_rect.ymax - layout->attribute_column_header_h;
return BLI_rcti_isect_pt(&header_rect, x, y);
}
bool file_attribute_column_type_enabled(const FileSelectParams *params,
FileAttributeColumnType column)
{
switch (column) {
case COLUMN_NAME:
/* Always enabled */
return true;
case COLUMN_DATETIME:
return (params->details_flags & FILE_DETAILS_DATETIME) != 0;
case COLUMN_SIZE:
return (params->details_flags & FILE_DETAILS_SIZE) != 0;
default:
return false;
}
}
/**
* Find the column type at region coordinate given by \a x (y doesn't matter for this).
*/
FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
const FileSelectParams *params,
FileLayout *layout,
int x)
{
float mx, my;
int offset_tile;
UI_view2d_region_to_view(v2d, x, v2d->mask.ymax - layout->offset_top - 1, &mx, &my);
offset_tile = ED_fileselect_layout_offset(
layout, (int)(v2d->tot.xmin + mx), (int)(v2d->tot.ymax - my));
if (offset_tile > -1) {
int tile_x, tile_y;
int pos_x = 0;
int rel_x; /* x relative to the hovered tile */
ED_fileselect_layout_tilepos(layout, offset_tile, &tile_x, &tile_y);
/* Column header drawing doesn't use left tile border, so subtract it. */
rel_x = mx - (tile_x - layout->tile_border_x);
for (FileAttributeColumnType column = 0; column < ATTRIBUTE_COLUMN_MAX; column++) {
if (!file_attribute_column_type_enabled(params, column)) {
continue;
}
const int width = layout->attribute_columns[column].width;
if (IN_RANGE(rel_x, pos_x, pos_x + width)) {
return column;
}
pos_x += width;
}
}
return COLUMN_NONE;
}
float file_string_width(const char *str)
{
uiStyle *style = UI_style_get();
@@ -512,20 +622,52 @@ float file_font_pointsize(void)
#endif
}
static void column_widths(FileSelectParams *params, struct FileLayout *layout)
static void file_attribute_columns_widths(const FileSelectParams *params, FileLayout *layout)
{
int i;
FileAttributeColumn *columns = layout->attribute_columns;
const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
const int pad = small_size ? 0 : ATTRIBUTE_COLUMN_PADDING * 2;
for (i = 0; i < MAX_FILE_COLUMN; ++i) {
layout->column_widths[i] = 0;
for (int i = 0; i < ATTRIBUTE_COLUMN_MAX; ++i) {
layout->attribute_columns[i].width = 0;
}
layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
/* Biggest possible reasonable values... */
layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89");
layout->column_widths[COLUMN_TIME] = file_string_width("23:59");
layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB");
columns[COLUMN_DATETIME].width = file_string_width(small_size ? "23/08/89" :
"23 Dec 6789, 23:59") +
pad;
columns[COLUMN_SIZE].width = file_string_width(small_size ? "98.7 M" : "098.7 MB") + pad;
if (params->display == FILE_IMGDISPLAY) {
columns[COLUMN_NAME].width = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
}
/* Name column uses remaining width */
else {
int remwidth = layout->tile_w;
for (FileAttributeColumnType column_type = ATTRIBUTE_COLUMN_MAX - 1; column_type >= 0;
column_type--) {
if ((column_type == COLUMN_NAME) ||
!file_attribute_column_type_enabled(params, column_type)) {
continue;
}
remwidth -= columns[column_type].width;
}
columns[COLUMN_NAME].width = remwidth;
}
}
static void file_attribute_columns_init(const FileSelectParams *params, FileLayout *layout)
{
file_attribute_columns_widths(params, layout);
layout->attribute_columns[COLUMN_NAME].name = N_("Name");
layout->attribute_columns[COLUMN_NAME].sort_type = FILE_SORT_ALPHA;
layout->attribute_columns[COLUMN_NAME].text_align = UI_STYLE_TEXT_LEFT;
layout->attribute_columns[COLUMN_DATETIME].name = N_("Date Modified");
layout->attribute_columns[COLUMN_DATETIME].sort_type = FILE_SORT_TIME;
layout->attribute_columns[COLUMN_DATETIME].text_align = UI_STYLE_TEXT_LEFT;
layout->attribute_columns[COLUMN_SIZE].name = N_("Size");
layout->attribute_columns[COLUMN_SIZE].sort_type = FILE_SORT_SIZE;
layout->attribute_columns[COLUMN_SIZE].text_align = UI_STYLE_TEXT_RIGHT;
}
void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
@@ -533,7 +675,6 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
FileSelectParams *params = ED_fileselect_get_params(sfile);
FileLayout *layout = NULL;
View2D *v2d = &ar->v2d;
int maxlen = 0;
int numfiles;
int textheight;
@@ -560,57 +701,66 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
if (layout->columns > 0) {
layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero
layout->flow_columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
layout->attribute_column_header_h = 0;
layout->offset_top = 0;
if (layout->flow_columns > 0) {
layout->rows = numfiles / layout->flow_columns + 1; // XXX dirty, modulo is zero
}
else {
layout->columns = 1;
layout->flow_columns = 1;
layout->rows = numfiles + 1; // XXX dirty, modulo is zero
}
layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
layout->tile_border_y * 2;
layout->tile_border_y * 2 - layout->offset_top;
layout->flag = FILE_LAYOUT_VER;
}
else {
int column_space = 0.6f * UI_UNIT_X;
int column_icon_space = 0.2f * UI_UNIT_X;
else if (params->display == FILE_VERTICALDISPLAY) {
int rowcount;
layout->prv_w = 0;
layout->prv_h = 0;
layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
layout->tile_border_x = 0.4f * UI_UNIT_X;
layout->tile_border_y = 0.1f * UI_UNIT_Y;
layout->prv_border_x = 0;
layout->prv_border_y = 0;
layout->tile_h = textheight * 3 / 2;
layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
layout->tile_w = layout->width;
layout->flow_columns = 1;
layout->attribute_column_header_h = layout->tile_h * 1.2f + 2 * layout->tile_border_y;
layout->offset_top = layout->attribute_column_header_h;
rowcount = (int)(BLI_rctf_size_y(&v2d->cur) - layout->offset_top - 2 * layout->tile_border_y) /
(layout->tile_h + 2 * layout->tile_border_y);
file_attribute_columns_init(params, layout);
layout->rows = MAX2(rowcount, numfiles);
BLI_assert(layout->rows != 0);
layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
layout->tile_border_y * 2 + layout->offset_top;
layout->flag = FILE_LAYOUT_VER;
}
else if (params->display == FILE_HORIZONTALDISPLAY) {
layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
layout->tile_border_x = 0.4f * UI_UNIT_X;
layout->tile_border_y = 0.1f * UI_UNIT_Y;
layout->tile_h = textheight * 3 / 2;
layout->attribute_column_header_h = 0;
layout->offset_top = layout->attribute_column_header_h;
layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
/* Padding by full scrollbar H is too much, can overlap tile border Y. */
layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) /
(layout->tile_h + 2 * layout->tile_border_y);
layout->tile_w = VERTLIST_MAJORCOLUMN_WIDTH;
file_attribute_columns_init(params, layout);
column_widths(params, layout);
if (params->display == FILE_SHORTDISPLAY) {
maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
(int)layout->column_widths[COLUMN_NAME] + column_space +
(int)layout->column_widths[COLUMN_SIZE] + column_space;
}
else {
maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
(int)layout->column_widths[COLUMN_NAME] + column_space +
(int)layout->column_widths[COLUMN_DATE] + column_space +
(int)layout->column_widths[COLUMN_TIME] + column_space +
(int)layout->column_widths[COLUMN_SIZE] + column_space;
}
layout->tile_w = maxlen;
if (layout->rows > 0) {
layout->columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
layout->flow_columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
}
else {
layout->rows = 1;
layout->columns = numfiles + 1; // XXX dirty, modulo is zero
layout->flow_columns = numfiles + 1; // XXX dirty, modulo is zero
}
layout->width = sfile->layout->columns * (layout->tile_w + 2 * layout->tile_border_x) +
layout->width = sfile->layout->flow_columns * (layout->tile_w + 2 * layout->tile_border_x) +
layout->tile_border_x * 2;
layout->flag = FILE_LAYOUT_HOR;
}

View File

@@ -72,23 +72,40 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */
ar->alignment = RGN_ALIGN_TOP;
/* Tools region */
ar = MEM_callocN(sizeof(ARegion), "tools region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
/* Tool props (aka operator) region */
ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
/* ui list region */
ar = MEM_callocN(sizeof(ARegion), "ui region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_UI;
ar->alignment = RGN_ALIGN_TOP;
ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* Tools region */
ar = MEM_callocN(sizeof(ARegion), "tools region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
/* Tools region (lower split region) */
ar = MEM_callocN(sizeof(ARegion), "lower tools region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* Execute region */
ar = MEM_callocN(sizeof(ARegion), "execute region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_EXECUTE;
ar->alignment = RGN_ALIGN_BOTTOM;
ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* Tool props region is added as needed. */
#if 0
/* Tool props (aka operator) region */
ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_RIGHT;
#endif
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for file");
@@ -204,6 +221,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
static void file_refresh(const bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
struct FSMenu *fsmenu = ED_fsmenu_get();
@@ -217,15 +235,16 @@ static void file_refresh(const bContext *C, ScrArea *sa)
}
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
filelist_setsorting(sfile->files, params->sort);
filelist_setfilter_options(sfile->files,
(params->flag & FILE_FILTER) != 0,
(params->flag & FILE_HIDE_DOT) != 0,
false, /* TODO hide_parent, should be controllable? */
params->filter,
params->filter_id,
params->filter_glob,
params->filter_search);
filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT);
filelist_setfilter_options(
sfile->files,
(params->flag & FILE_FILTER) != 0,
(params->flag & FILE_HIDE_DOT) != 0,
true, /* Just always hide parent, prefer to not add an extra user option for this. */
params->filter,
params->filter_id,
params->filter_glob,
params->filter_search);
/* Update the active indices of bookmarks & co. */
sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
@@ -254,7 +273,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
else {
filelist_cache_previews_set(sfile->files, false);
if (sfile->previews_timer) {
WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer);
WM_event_remove_timer_notifier(wm, win, sfile->previews_timer);
sfile->previews_timer = NULL;
}
}
@@ -269,10 +288,20 @@ static void file_refresh(const bContext *C, ScrArea *sa)
/* Might be called with NULL sa, see file_main_region_draw() below. */
if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
/* Create TOOLS/TOOL_PROPS regions. */
/* Create TOOLS region. */
file_tools_region(sa);
ED_area_initialize(wm, CTX_wm_window(C), sa);
ED_area_initialize(wm, win, sa);
}
if (sa && sfile->op && BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS) == NULL) {
/* Create TOOL_PROPS region. */
ARegion *region_props = file_tool_props_region(sa);
if (params->flag & FILE_HIDE_TOOL_PROPS) {
region_props->flag |= RGN_FLAG_HIDDEN;
}
ED_area_initialize(wm, win, sa);
}
ED_area_tag_redraw(sa);
@@ -406,6 +435,11 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
v2d->keepofs &= ~V2D_LOCKOFS_Y;
v2d->keepofs |= V2D_LOCKOFS_X;
}
else if (params->display == FILE_VERTICALDISPLAY) {
v2d->scroll = V2D_SCROLL_RIGHT;
v2d->keepofs &= ~V2D_LOCKOFS_Y;
v2d->keepofs |= V2D_LOCKOFS_X;
}
else {
v2d->scroll = V2D_SCROLL_BOTTOM;
v2d->keepofs &= ~V2D_LOCKOFS_X;
@@ -439,7 +473,9 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
rcti view_rect;
ED_fileselect_layout_maskrect(sfile->layout, v2d, &view_rect);
scrollers = UI_view2d_scrollers_calc(v2d, &view_rect);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
}
@@ -452,6 +488,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_select_box);
WM_operatortype_append(FILE_OT_select_bookmark);
WM_operatortype_append(FILE_OT_highlight);
WM_operatortype_append(FILE_OT_sort_column_ui_context);
WM_operatortype_append(FILE_OT_execute);
WM_operatortype_append(FILE_OT_cancel);
WM_operatortype_append(FILE_OT_parent);
@@ -538,7 +575,8 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
ED_region_panels_init(wm, ar);
ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
@@ -550,22 +588,18 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
static void file_ui_region_draw(const bContext *C, ARegion *ar)
{
float col[3];
/* clear */
UI_GetThemeColor3fv(TH_BACK, col);
GPU_clear_color(col[0], col[1], col[2], 0.0);
GPU_clear(GPU_COLOR_BIT);
ED_region_panels(C, ar);
}
/* scrolling here is just annoying, disable it */
ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
ar->v2d.cur.ymin = 0;
static void file_execution_region_init(wmWindowManager *wm, ARegion *ar)
{
ED_region_panels_init(wm, ar);
ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
}
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(&ar->v2d);
file_draw_buttons(C, ar);
UI_view2d_view_restore(C);
static void file_execution_region_draw(const bContext *C, ARegion *ar)
{
ED_region_panels(C, ar);
}
static void file_ui_region_listener(wmWindow *UNUSED(win),
@@ -656,13 +690,21 @@ void ED_spacetype_file(void)
/* regions: ui */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_UI;
art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
art->listener = file_ui_region_listener;
art->init = file_ui_region_init;
art->draw = file_ui_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: execution */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_EXECUTE;
art->keymapflag = ED_KEYMAP_UI;
art->listener = file_ui_region_listener;
art->init = file_execution_region_init;
art->draw = file_execution_region_draw;
BLI_addhead(&st->regiontypes, art);
/* regions: channels (directories) */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_TOOLS;
@@ -677,8 +719,8 @@ void ED_spacetype_file(void)
/* regions: tool properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
art->regionid = RGN_TYPE_TOOL_PROPS;
art->prefsizex = 0;
art->prefsizey = 360;
art->prefsizex = 240;
art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
art->listener = file_tools_region_listener;
art->init = file_tools_region_init;

View File

@@ -1538,7 +1538,7 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
FILE_SPECIAL,
FILE_OPENFILE,
WM_FILESEL_FILEPATH,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
RNA_def_float(ot->srna,

View File

@@ -677,8 +677,11 @@ typedef struct FileSelectParams {
/** Display mode flag. */
short display;
short display_previous;
/** Details toggles (file size, creation date, etc.) */
char details_flags;
/* The type of file action (opening or saving) */
char action_type; /* eFileSel_Action */
/** Filter when (flags & FILE_FILTER) is true. */
char _pad2[2];
int filter;
/** Max number of levels in dirtree to show at once, 0 to disable recursion. */
@@ -736,8 +739,8 @@ typedef struct SpaceFile {
/* FileSelectParams.display */
enum eFileDisplayType {
FILE_DEFAULTDISPLAY = 0,
FILE_SHORTDISPLAY = 1,
FILE_LONGDISPLAY = 2,
FILE_VERTICALDISPLAY = 1,
FILE_HORIZONTALDISPLAY = 2,
FILE_IMGDISPLAY = 3,
};
@@ -750,6 +753,12 @@ enum eFileSortType {
FILE_SORT_SIZE = 4,
};
/* FileSelectParams.details_flags */
enum eFileDetails {
FILE_DETAILS_SIZE = (1 << 0),
FILE_DETAILS_DATETIME = (1 << 1),
};
/* these values need to be hardcoded in structs, dna does not recognize defines */
/* also defined in BKE */
#define FILE_MAXDIR 768
@@ -787,6 +796,8 @@ typedef enum eFileSel_Params_Flag {
FILE_FILTER = (1 << 8),
FILE_PARAMS_FLAG_UNUSED_9 = (1 << 9), /* cleared */
FILE_GROUP_INSTANCE = (1 << 10),
FILE_SORT_INVERT = (1 << 11),
FILE_HIDE_TOOL_PROPS = (1 << 12)
} eFileSel_Params_Flag;
/* sfile->params->rename_flag */
@@ -824,6 +835,8 @@ typedef enum eFileSel_File_Types {
FILE_TYPE_OPERATOR = (1 << 14),
FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
FILE_TYPE_ALEMBIC = (1 << 16),
/** For all kinds of recognized import/export formats. No need for specialized types. */
FILE_TYPE_OBJECT_IO = (1 << 17),
/** An FS directory (i.e. S_ISDIR on its path is true). */
FILE_TYPE_DIR = (1 << 30),
@@ -882,8 +895,7 @@ typedef struct FileDirEntryRevision {
int64_t time;
/* Temp caching of UI-generated strings... */
char size_str[16];
char time_str[8];
char date_str[16];
char datetime_str[16 + 8];
} FileDirEntryRevision;
/* Container for a variant, only relevant in asset context.

View File

@@ -420,19 +420,19 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
{FILE_SORT_ALPHA,
"FILE_SORT_ALPHA",
ICON_SORTALPHA,
"Sort alphabetically",
"Name",
"Sort the file list alphabetically"},
{FILE_SORT_EXTENSION,
"FILE_SORT_EXTENSION",
ICON_SORTBYEXT,
"Sort by extension",
"Extension",
"Sort the file list by extension/type"},
{FILE_SORT_TIME,
"FILE_SORT_TIME",
ICON_SORTTIME,
"Sort by time",
"Modified Date",
"Sort files by modification time"},
{FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size"},
{FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Size", "Sort files by size"},
{0, NULL, 0, NULL, NULL},
};
@@ -2142,6 +2142,18 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain),
/* File browser. */
int rna_FileSelectParams_filename_editable(struct PointerRNA *ptr, const char **r_info)
{
FileSelectParams *params = ptr->data;
if (params && (params->flag & FILE_DIRSEL_ONLY)) {
*r_info = "Only directories can be chosen for the current operation.";
return 0;
}
return params ? PROP_EDITABLE : 0;
}
static bool rna_FileSelectParams_use_lib_get(PointerRNA *ptr)
{
FileSelectParams *params = ptr->data;
@@ -5133,25 +5145,25 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem file_display_items[] = {
{FILE_SHORTDISPLAY,
"LIST_SHORT",
ICON_SHORTDISPLAY,
"Short List",
"Display files as short list"},
{FILE_LONGDISPLAY,
"LIST_LONG",
{FILE_VERTICALDISPLAY,
"LIST_VERTICAL",
ICON_LONGDISPLAY,
"Long List",
"Display files as a detailed list"},
"Vertical List",
"Display files as a vertical list"},
{FILE_HORIZONTALDISPLAY,
"LIST_HORIZONTAL",
ICON_SHORTDISPLAY,
"Horizontal List",
"Display files as a horizontal list"},
{FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem display_size_items[] = {
{32, "TINY", 0, "Tiny", ""},
{64, "SMALL", 0, "Small", ""},
{64, "TINY", 0, "Tiny", ""},
{96, "SMALL", 0, "Small", ""},
{128, "NORMAL", 0, "Regular", ""},
{256, "LARGE", 0, "Large", ""},
{192, "LARGE", 0, "Large", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -5267,7 +5279,10 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Title", "Title for the file browser");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
/* Use BYTESTRING rather than DIRPATH as subtype so UI code doesn't add OT_directory_browse
* button when displaying this prop in the file browser (it would just open a file browser). That
* should be the only effective difference between the two. */
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_BYTESTRING);
RNA_def_property_string_sdna(prop, NULL, "dir");
RNA_def_property_ui_text(prop, "Directory", "Directory displayed in the file browser");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -5275,6 +5290,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME);
RNA_def_property_string_sdna(prop, NULL, "file");
RNA_def_property_ui_text(prop, "File Name", "Active file in the file browser");
RNA_def_property_editable_func(prop, "rna_FileSelectParams_filename_editable");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_library_browsing", PROP_BOOLEAN, PROP_NONE);
@@ -5295,6 +5311,19 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Recursion", "Numbers of dirtree levels to show simultaneously");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "show_details_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_SIZE);
RNA_def_property_ui_text(prop, "File Size", "Draw a column listing the size of each file");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "show_details_datetime", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_DATETIME);
RNA_def_property_ui_text(
prop,
"File Modification Date",
"Draw a column listing the date and time of modification for each file");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER);
RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files");
@@ -5311,6 +5340,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sort", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_sort_invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_SORT_INVERT);
RNA_def_property_ui_text(
prop, "Reverse Sorting", "Sort items descending, from highest value to lowest");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_filter_image", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_IMAGE);
RNA_def_property_ui_text(prop, "Filter Images", "Show image files");

View File

@@ -159,7 +159,7 @@ enum {
WM_WINDOW_USERPREFS,
WM_WINDOW_DRIVERS,
WM_WINDOW_INFO,
// WM_WINDOW_FILESEL // UNUSED
WM_WINDOW_FILESEL,
};
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
@@ -493,6 +493,8 @@ bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalPa
#define WM_FILESEL_FILENAME (1 << 2)
#define WM_FILESEL_FILEPATH (1 << 3)
#define WM_FILESEL_FILES (1 << 4)
/* Show the properties sidebar by default. */
#define WM_FILESEL_SHOW_PROPS (1 << 5)
/* operator as a python command (resultuing string must be freed) */
char *WM_operator_pystring_ex(struct bContext *C,

View File

@@ -2339,46 +2339,32 @@ static int wm_handler_fileselect_do(bContext *C,
switch (val) {
case EVT_FILESELECT_FULL_OPEN: {
ScrArea *sa;
wmWindow *win = CTX_wm_window(C);
const int sizex = 1020 * UI_DPI_FAC;
const int sizey = 600 * UI_DPI_FAC;
/* sa can be null when window A is active, but mouse is over window B
* in this case, open file select in original window A. Also don't
* use global areas. */
if (handler->context.area == NULL || ED_area_is_global(handler->context.area)) {
bScreen *screen = CTX_wm_screen(C);
sa = (ScrArea *)screen->areabase.first;
if (WM_window_open_temp(
C, win->sizex / 2, win->sizey / 2, sizex, sizey, WM_WINDOW_FILESEL) != NULL) {
ScrArea *area = CTX_wm_area(C);
ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
BLI_assert(area->spacetype == SPACE_FILE);
region_header->flag |= RGN_FLAG_HIDDEN;
/* Header on bottom, AZone triangle to toggle header looks misplaced at the top */
region_header->alignment = RGN_ALIGN_BOTTOM;
/* settings for filebrowser, sfile is not operator owner but sends events */
sfile = (SpaceFile *)area->spacedata.first;
sfile->op = handler->op;
ED_fileselect_set_params(sfile);
}
else {
sa = handler->context.area;
BKE_report(&wm->reports, RPT_ERROR, "Failed to open window!");
return OPERATOR_CANCELLED;
}
if (sa->full) {
/* ensure the first area becomes the file browser, because the second one is the small
* top (info-)area which might be too small (in fullscreens we have max two areas) */
if (sa->prev) {
sa = sa->prev;
}
ED_area_newspace(C, sa, SPACE_FILE, true); /* 'sa' is modified in-place */
/* we already had a fullscreen here -> mark new space as a stacked fullscreen */
sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE);
}
else if (sa->spacetype == SPACE_FILE) {
sa = ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
}
else {
sa = ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */
}
/* note, getting the 'sa' back from the context causes a nasty bug where the newly created
* 'sa' != CTX_wm_area(C). removed the line below and set 'sa' in the 'if' above */
/* sa = CTX_wm_area(C); */
/* settings for filebrowser, sfile is not operator owner but sends events */
sfile = (SpaceFile *)sa->spacedata.first;
sfile->op = handler->op;
ED_fileselect_set_params(sfile);
action = WM_HANDLER_BREAK;
break;
}
@@ -2390,14 +2376,27 @@ static int wm_handler_fileselect_do(bContext *C,
BLI_remlink(handlers, handler);
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
ScrArea *sa = CTX_wm_area(C);
for (wmWindow *win = wm->windows.first; win; win = win->next) {
if (WM_window_is_temp_screen(win)) {
bScreen *screen = WM_window_get_active_screen(win);
ScrArea *file_sa = screen->areabase.first;
if (sa->full) {
ED_screen_full_prevspace(C, sa);
}
/* user may have left fullscreen */
else {
ED_area_prevspace(C, sa);
BLI_assert(file_sa->spacetype == SPACE_FILE);
if (BLI_listbase_is_single(&file_sa->spacedata)) {
wmWindow *ctx_win = CTX_wm_window(C);
wm_window_close(C, wm, win);
CTX_wm_window_set(C, ctx_win); // wm_window_close() NULLs.
}
else if (file_sa->full) {
ED_screen_full_prevspace(C, file_sa);
}
else {
ED_area_prevspace(C, file_sa);
}
break;
}
}
}

View File

@@ -1205,6 +1205,8 @@ static ImBuf *blend_file_thumb(const bContext *C,
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
BlendThumbnail *thumb;
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *windrawable_old = wm->windrawable;
char err_out[256] = "unknown";
/* screen if no camera found */
@@ -1238,6 +1240,9 @@ static ImBuf *blend_file_thumb(const bContext *C,
/* gets scaled to BLEN_THUMB_SIZE */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* Offscreen drawing requires a drawable window context. */
wm_window_make_drawable(wm, CTX_wm_window(C));
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph,
scene,
@@ -1270,6 +1275,14 @@ static ImBuf *blend_file_thumb(const bContext *C,
err_out);
}
/* Reset to old drawable. */
if (windrawable_old) {
wm_window_make_drawable(wm, windrawable_old);
}
else {
wm_window_clear_drawable(wm);
}
if (ibuf) {
float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);
@@ -2322,7 +2335,7 @@ static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op)
void WM_OT_open_mainfile(wmOperatorType *ot)
{
ot->name = "Open Blender File";
ot->name = "Open";
ot->idname = "WM_OT_open_mainfile";
ot->description = "Open a Blender file";
@@ -2504,7 +2517,7 @@ void WM_OT_recover_auto_save(wmOperatorType *ot)
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH,
FILE_LONGDISPLAY,
FILE_HORIZONTALDISPLAY,
FILE_SORT_TIME);
}
@@ -2638,7 +2651,7 @@ void WM_OT_save_as_mainfile(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name = "Save As Blender File";
ot->name = "Save As";
ot->idname = "WM_OT_save_as_mainfile";
ot->description = "Save the current file in the desired location";

View File

@@ -561,7 +561,7 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
void WM_OT_link(wmOperatorType *ot)
{
ot->name = "Link from Library";
ot->name = "Link";
ot->idname = "WM_OT_link";
ot->description = "Link from a Library .blend file";
@@ -585,7 +585,7 @@ void WM_OT_link(wmOperatorType *ot)
void WM_OT_append(wmOperatorType *ot)
{
ot->name = "Append from Library";
ot->name = "Append";
ot->idname = "WM_OT_append";
ot->description = "Append from a Library .blend file";

View File

@@ -65,19 +65,27 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
0,
"Default",
"Automatically determine display type for files"},
{FILE_SHORTDISPLAY,
"LIST_SHORT",
ICON_SHORTDISPLAY,
{FILE_VERTICALDISPLAY,
"LIST_VERTICAL",
ICON_SHORTDISPLAY, /* Name of deprecated short list */
"Short List",
"Display files as short list"},
{FILE_LONGDISPLAY,
"LIST_LONG",
ICON_LONGDISPLAY,
{FILE_HORIZONTALDISPLAY,
"LIST_HORIZONTAL",
ICON_LONGDISPLAY, /* Name of deprecated long list */
"Long List",
"Display files as a detailed list"},
{FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem file_action_types[] = {
{FILE_OPENFILE,
"OPENFILE",
0,
"Open",
"Use the file browser for opening files or a directory"},
{FILE_SAVE, "SAVE", 0, "Save", "Use the file browser for saving a file"},
};
if (flag & WM_FILESEL_FILEPATH) {
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file");
@@ -99,6 +107,15 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if ((flag & WM_FILESEL_SHOW_PROPS) == 0) {
prop = RNA_def_boolean(ot->srna,
"hide_props_region",
true,
"Hide Operator Properties",
"Collapse the region displaying the operator settings");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if (action == FILE_SAVE) {
/* note, this is only used to check if we should highlight the filename area red when the
* filepath is an existing file. */
@@ -186,6 +203,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
prop = RNA_def_enum(
ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_enum(ot->srna, "action_type", file_action_types, action, "Action Type", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
static void wm_operator_properties_select_action_ex(wmOperatorType *ot,

View File

@@ -807,6 +807,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
ScrArea *sa;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
eSpace_Type space_type = SPACE_EMPTY;
const char *title;
/* convert to native OS window coordinates */
@@ -888,17 +889,24 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
CTX_wm_area_set(C, sa);
if (type == WM_WINDOW_RENDER) {
ED_area_newspace(C, sa, SPACE_IMAGE, false);
space_type = SPACE_IMAGE;
}
else if (type == WM_WINDOW_DRIVERS) {
ED_area_newspace(C, sa, SPACE_GRAPH, false);
space_type = SPACE_GRAPH;
}
else if (type == WM_WINDOW_USERPREFS) {
space_type = SPACE_USERPREF;
}
else if (type == WM_WINDOW_FILESEL) {
space_type = SPACE_FILE;
}
else if (type == WM_WINDOW_INFO) {
ED_area_newspace(C, sa, SPACE_INFO, false);
}
else {
ED_area_newspace(C, sa, SPACE_USERPREF, false);
BLI_assert(false);
}
ED_area_newspace(C, sa, space_type, false);
ED_screen_change(C, screen);
ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */