1// Aseprite
2// Copyright (C) 2019-2022 Igara Studio S.A.
3// Copyright (C) 2001-2018 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifndef APP_UI_FILE_LIST_H_INCLUDED
9#define APP_UI_FILE_LIST_H_INCLUDED
10#pragma once
11
12#include "app/file_system.h"
13#include "base/paths.h"
14#include "base/time.h"
15#include "obs/signal.h"
16#include "ui/animated_widget.h"
17#include "ui/timer.h"
18#include "ui/widget.h"
19
20#include <deque>
21#include <string>
22#include <vector>
23
24namespace os {
25 class Surface;
26}
27
28namespace app {
29
30 class FileList : public ui::Widget
31 , private ui::AnimatedWidget {
32 public:
33 FileList();
34 virtual ~FileList();
35
36 const base::paths& extensions() const { return m_exts; }
37 void setExtensions(const base::paths& extensions);
38
39 IFileItem* currentFolder() const { return m_currentFolder; }
40 void setCurrentFolder(IFileItem* folder);
41
42 IFileItem* selectedFileItem() const { return m_selected; }
43 const FileItemList& fileList() const { return m_list; }
44 FileItemList selectedFileItems() const;
45 void deselectedFileItems();
46
47 bool multipleSelection() { return m_multiselect; }
48 void setMultipleSelection(bool multiple);
49
50 void goUp();
51
52 gfx::Rect mainThumbnailBounds();
53
54 double zoom() const { return m_zoom; }
55 void setZoom(const double zoom);
56 void animateToZoom(const double zoom);
57
58 obs::signal<void()> FileSelected;
59 obs::signal<void()> FileAccepted;
60 obs::signal<void()> CurrentFolderChanged;
61
62 protected:
63 virtual bool onProcessMessage(ui::Message* msg) override;
64 virtual void onPaint(ui::PaintEvent& ev) override;
65 virtual void onSizeHint(ui::SizeHintEvent& ev) override;
66 virtual void onFileSelected();
67 virtual void onFileAccepted();
68 virtual void onCurrentFolderChanged();
69
70 private:
71 enum {
72 ANI_NONE,
73 ANI_ZOOM,
74 };
75
76 struct ItemInfo {
77 gfx::Rect bounds;
78 gfx::Rect text;
79 gfx::Rect thumbnail;
80 };
81
82 void paintItem(ui::Graphics* g, IFileItem* fi, const int i);
83 void onGenerateThumbnailTick();
84 void onMonitoringTick();
85 void recalcAllFileItemInfo();
86 ItemInfo calcFileItemInfo(int i) const;
87 ItemInfo getFileItemInfo(int i) const;
88 void makeSelectedFileitemVisible();
89 void regenerateList();
90 int selectedIndex() const;
91 void selectIndex(int index);
92 void generateThumbnailForFileItem(IFileItem* fi);
93 void delayThumbnailGenerationForSelectedItem();
94 bool hasThumbnailsPerItem() const { return m_zoom > 1.0; }
95 bool isListView() const { return !hasThumbnailsPerItem(); }
96 bool isIconView() const { return hasThumbnailsPerItem(); }
97
98 // AnimatedWidget impl
99 void onAnimationStop(int animation) override;
100 void onAnimationFrame() override;
101
102 IFileItem* m_currentFolder;
103 FileItemList m_list;
104 std::vector<ItemInfo> m_info;
105
106 bool m_req_valid;
107 int m_req_w, m_req_h;
108 IFileItem* m_selected;
109 std::vector<bool> m_selectedItems;
110 base::paths m_exts;
111
112 // Incremental-search
113 std::string m_isearch;
114 base::tick_t m_isearchClock;
115
116 // Timer to start generating the thumbnail after an item is
117 // selected.
118 ui::Timer m_generateThumbnailTimer;
119
120 // Monitoring the progress of each thumbnail.
121 ui::Timer m_monitoringTimer;
122
123 // Used keep the last-selected item in the list so we know
124 // thumbnail to generate when the m_generateThumbnailTimer ticks.
125 IFileItem* m_itemToGenerateThumbnail;
126
127 // List of thumbnails to generate in the next m_monitoringTimer in
128 // a isIconView()
129 std::deque<IFileItem*> m_generateThumbnailsForTheseItems;
130
131 // True if this listbox accepts selecting multiple items at the
132 // same time.
133 bool m_multiselect;
134
135 double m_zoom;
136 double m_fromZoom;
137 double m_toZoom;
138
139 int m_itemsPerRow;
140 };
141
142} // namespace app
143
144#endif
145