2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../../core/juce_StandardHeader.h"
30 #include "juce_FileListComponent.h"
31 #include "../lookandfeel/juce_LookAndFeel.h"
32 #include "../../graphics/imaging/juce_ImageCache.h"
33 #include "../../../events/juce_AsyncUpdater.h"
35 Image
juce_createIconForFile (const File
& file
);
38 //==============================================================================
39 FileListComponent::FileListComponent (DirectoryContentsList
& listToShow
)
40 : ListBox (String::empty
, nullptr),
41 DirectoryContentsDisplayComponent (listToShow
)
44 fileList
.addChangeListener (this);
47 FileListComponent::~FileListComponent()
49 fileList
.removeChangeListener (this);
52 int FileListComponent::getNumSelectedFiles() const
54 return getNumSelectedRows();
57 const File
FileListComponent::getSelectedFile (int index
) const
59 return fileList
.getFile (getSelectedRow (index
));
62 void FileListComponent::deselectAllFiles()
67 void FileListComponent::scrollToTop()
69 getVerticalScrollBar()->setCurrentRangeStart (0);
72 //==============================================================================
73 void FileListComponent::changeListenerCallback (ChangeBroadcaster
*)
77 if (lastDirectory
!= fileList
.getDirectory())
79 lastDirectory
= fileList
.getDirectory();
84 //==============================================================================
85 class FileListItemComponent
: public Component
,
86 public TimeSliceClient
,
90 //==============================================================================
91 FileListItemComponent (FileListComponent
& owner_
, TimeSliceThread
& thread_
)
92 : owner (owner_
), thread (thread_
), index (0), highlighted (false)
96 ~FileListItemComponent()
98 thread
.removeTimeSliceClient (this);
101 //==============================================================================
102 void paint (Graphics
& g
)
104 getLookAndFeel().drawFileBrowserRow (g
, getWidth(), getHeight(),
106 &icon
, fileSize
, modTime
,
107 isDirectory
, highlighted
,
111 void mouseDown (const MouseEvent
& e
)
113 owner
.selectRowsBasedOnModifierKeys (index
, e
.mods
, false);
114 owner
.sendMouseClickMessage (file
, e
);
117 void mouseDoubleClick (const MouseEvent
&)
119 owner
.sendDoubleClickMessage (file
);
122 void update (const File
& root
,
123 const DirectoryContentsList::FileInfo
* const fileInfo
,
125 const bool highlighted_
)
127 thread
.removeTimeSliceClient (this);
129 if (highlighted_
!= highlighted
|| index_
!= index
)
132 highlighted
= highlighted_
;
137 String newFileSize
, newModTime
;
139 if (fileInfo
!= nullptr)
141 newFile
= root
.getChildFile (fileInfo
->filename
);
142 newFileSize
= File::descriptionOfSizeInBytes (fileInfo
->fileSize
);
143 newModTime
= fileInfo
->modificationTime
.formatted ("%d %b '%y %H:%M");
147 || fileSize
!= newFileSize
148 || modTime
!= newModTime
)
151 fileSize
= newFileSize
;
152 modTime
= newModTime
;
154 isDirectory
= fileInfo
!= nullptr && fileInfo
->isDirectory
;
159 if (file
!= File::nonexistent
&& icon
.isNull() && ! isDirectory
)
163 if (! icon
.isValid())
164 thread
.addTimeSliceClient (this);
174 void handleAsyncUpdate()
180 //==============================================================================
181 FileListComponent
& owner
;
182 TimeSliceThread
& thread
;
184 String fileSize
, modTime
;
187 bool highlighted
, isDirectory
;
189 void updateIcon (const bool onlyUpdateIfCached
)
193 const int hashCode
= (file
.getFullPathName() + "_iconCacheSalt").hashCode();
194 Image
im (ImageCache::getFromHashCode (hashCode
));
196 if (im
.isNull() && ! onlyUpdateIfCached
)
198 im
= juce_createIconForFile (file
);
201 ImageCache::addImageToCache (im
, hashCode
);
207 triggerAsyncUpdate();
212 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileListItemComponent
);
215 //==============================================================================
216 int FileListComponent::getNumRows()
218 return fileList
.getNumFiles();
221 void FileListComponent::paintListBoxItem (int, Graphics
&, int, int, bool)
225 Component
* FileListComponent::refreshComponentForRow (int row
, bool isSelected
, Component
* existingComponentToUpdate
)
227 FileListItemComponent
* comp
= dynamic_cast <FileListItemComponent
*> (existingComponentToUpdate
);
231 delete existingComponentToUpdate
;
232 comp
= new FileListItemComponent (*this, fileList
.getTimeSliceThread());
235 DirectoryContentsList::FileInfo fileInfo
;
237 if (fileList
.getFileInfo (row
, fileInfo
))
238 comp
->update (fileList
.getDirectory(), &fileInfo
, row
, isSelected
);
240 comp
->update (fileList
.getDirectory(), nullptr, row
, isSelected
);
245 void FileListComponent::selectedRowsChanged (int /*lastRowSelected*/)
247 sendSelectionChangeMessage();
250 void FileListComponent::deleteKeyPressed (int /*currentSelectedRow*/)
254 void FileListComponent::returnKeyPressed (int currentSelectedRow
)
256 sendDoubleClickMessage (fileList
.getFile (currentSelectedRow
));