Using the FileTreeComponent

I’m setting up the FileTreeComponent to display the computer folder structure and files, so the user can pick the files. So far things are working correctly. The only thing I have no clue on how to do is how to know when a file was selected. I couldn’t find any examples of it. I know that a good programmer would know how to do it, but I’m doing so many things at once here, that my brain is melting and I can’t seem to figure it out… :expressionless: :oops:

File folder (File::getSpecialLocation (File::userDocumentsDirectory)); WildcardFileFilter* fileFilter=new WildcardFileFilter("*.dll;*.WusikPRST","Files"); directoryList = new DirectoryContentsList (fileFilter, thread); directoryList->setDirectory(folder, true, true); thread.startThread (3); addAndMakeVisible(cTreeView = new = FileTreeComponent(*directoryList)); cTreeView->setRootItemVisible(true);

Don’t forget to call “thread.stopThread (10000);” at the destructor.

Best Regards, WilliamK

A FileTreeComponent is just a TreeView, so you can override its itemSelectionChanged() method to handle the selection changes.

Sorry to be dense, but you mean like this?

[code]//-----------------------------------------------------------------------------------------------------------
class JUCE_API FileTreeComponentEx : public FileTreeComponent
{
public:

FileTreeComponentEx (DirectoryContentsList& listToShow);

[/code]

And instead of using

FileTreeComponent * tView

I use

FileTreeComponentEx* tView

?

It works for some things. But

itemSelectionChanged()

is part of TreeViewItem which I can’t seem to find a way to override. :frowning:

Wait, I think I get it now. I need to override and copy a lot of things. :wink:

I see the example TreeViewDemo.cpp used by the Juce Demo application.

I will use that as a base.

Sorry again. :oops:

Wk

I’m posting my partial solution here, just so any n00b people can also take a look at it. I’m still implementing the rest of the stuff I want to add. Like Loading, Deleting, Insert-new-directory, Move (copy and Paste) and so on…

Header:

[code]
class FileTreeComponentEx : public FileTreeComponent
{
public:
FileTreeComponentEx (DirectoryContentsList& listToShow);

const File getSelectedFile (const int index) const throw();

};[/code]

Cpp

[code]#define MessageBox(dd,ds) AlertWindow::showMessageBox(AlertWindow::WarningIcon, dd,ds)

//-----------------------------------------------------------------------------------------------------------
class FileListTreeItemEx : public TreeViewItem,
public TimeSliceClient,
public AsyncUpdater,
public ChangeListener
{
public:

//-----------------------------------------------------------------------------------------------------------
FileListTreeItemEx (FileTreeComponentEx& owner_,
                  DirectoryContentsList* const parentContentsList_,
                  const int indexInContentsList_,
                  const File& file_,
                  TimeSliceThread& thread_) throw()
    : file (file_),
      owner (owner_),
      parentContentsList (parentContentsList_),
      indexInContentsList (indexInContentsList_),
      subContentsList (0),
      canDeleteSubContentsList (false),
      thread (thread_),
      icon (0)
{
    DirectoryContentsList::FileInfo fileInfo;

    if (parentContentsList_ != 0
         && parentContentsList_->getFileInfo (indexInContentsList_, fileInfo))
    {
        fileSize = File::descriptionOfSizeInBytes (fileInfo.fileSize);
        modTime = fileInfo.modificationTime.formatted (T("%d %b '%y %H:%M"));
        isDirectory = fileInfo.isDirectory;
    }
    else
    {
        isDirectory = true;
    }
}

//-----------------------------------------------------------------------------------------------------------
~FileListTreeItemEx() throw()
{
    thread.removeTimeSliceClient (this);

    clearSubItems();
    ImageCache::release (icon);

    if (canDeleteSubContentsList)
        delete subContentsList;
}

bool mightContainSubItems()                 { return isDirectory; }
const String getUniqueName() const          { return file.getFullPathName(); }
int getItemHeight() const                   { return 22; }

const String getDragSourceDescription()     { return owner.getDragAndDropDescription(); }

//-----------------------------------------------------------------------------------------------------------
void itemOpennessChanged (bool isNowOpen)
{
    if (isNowOpen)
    {
        clearSubItems();

        isDirectory = file.isDirectory();

        if (isDirectory)
        {
            if (subContentsList == 0)
            {
                jassert (parentContentsList != 0);

                DirectoryContentsList* const l = new DirectoryContentsList (parentContentsList->getFilter(), thread);
                l->setDirectory (file, true, true);

                setSubContentsList (l);
                canDeleteSubContentsList = true;
            }

            changeListenerCallback (0);
        }
    }
}

//-----------------------------------------------------------------------------------------------------------
void setSubContentsList (DirectoryContentsList* newList) throw()
{
    jassert (subContentsList == 0);
    subContentsList = newList;
    newList->addChangeListener (this);
}

//-----------------------------------------------------------------------------------------------------------
void changeListenerCallback (void*)
{
    clearSubItems();

    if (isOpen() && subContentsList != 0)
    {
        for (int i = 0; i < subContentsList->getNumFiles(); ++i)
        {
            FileListTreeItemEx* const item
                = new FileListTreeItemEx (owner, subContentsList, i, subContentsList->getFile(i), thread);

            addSubItem (item);
        }
    }
}

//-----------------------------------------------------------------------------------------------------------
void paintItem (Graphics& g, int width, int height)
{
    if (file != File::nonexistent && ! isDirectory)
    {
        updateIcon (true);

        if (icon == 0)
            thread.addTimeSliceClient (this);
    }

    owner.getLookAndFeel()
        .drawFileBrowserRow (g, width, height,
                             file.getFileName(),
                             icon,
                             fileSize, modTime,
                             isDirectory, isSelected(),
                             indexInContentsList);
}

//-----------------------------------------------------------------------------------------------------------
void itemClicked (const MouseEvent& e)
{
    owner.sendMouseClickMessage (file, e);

	if (e.mods.isPopupMenu())
	{
		MessageBox(owner.getSelectedFile(0).getFullPathName(),"!");
	}
}

//-----------------------------------------------------------------------------------------------------------
void itemDoubleClicked (const MouseEvent& e)
{
    TreeViewItem::itemDoubleClicked (e);
    owner.sendDoubleClickMessage (file);
	
	if (!owner.getSelectedFile(0).isDirectory()) MessageBox(owner.getSelectedFile(0).getFullPathName(),"!");
}

//-----------------------------------------------------------------------------------------------------------
void itemSelectionChanged (bool)
{
    owner.sendSelectionChangeMessage();
}

//-----------------------------------------------------------------------------------------------------------
bool useTimeSlice()
{
    updateIcon (false);
    thread.removeTimeSliceClient (this);
    return false;
}

//-----------------------------------------------------------------------------------------------------------
void handleAsyncUpdate()
{
    owner.repaint();
}

const File file;

juce_UseDebuggingNewOperator

private:
FileTreeComponentEx& owner;
DirectoryContentsList* parentContentsList;
int indexInContentsList;
DirectoryContentsList* subContentsList;
bool isDirectory, canDeleteSubContentsList;
TimeSliceThread& thread;
Image* icon;
String fileSize;
String modTime;

void updateIcon (const bool onlyUpdateIfCached) throw() { }

};

//-----------------------------------------------------------------------------------------------------------
FileTreeComponentEx::FileTreeComponentEx (DirectoryContentsList& listToShow)
: FileTreeComponent (listToShow)
{
FileListTreeItemEx* const root
= new FileListTreeItemEx (*this, 0, 0, listToShow.getDirectory(),
listToShow.getTimeSliceThread());

root->setSubContentsList (&listToShow);
setRootItemVisible (false);
setRootItem (root);

}

//-----------------------------------------------------------------------------------------------------------
/FileTreeComponentEx::~FileTreeComponentEx()
{
TreeViewItem
const root = getRootItem();
setRootItem (0);
delete root;
}

//-----------------------------------------------------------------------------------------------------------
const File FileTreeComponentEx::getSelectedFile() const
{
return getSelectedFile (0);
}*/

//-----------------------------------------------------------------------------------------------------------
const File FileTreeComponentEx::getSelectedFile (const int index) const throw()
{
const FileListTreeItemEx* const item = dynamic_cast <const FileListTreeItemEx*> (getSelectedItem (index));

if (item != 0)
    return item->file;

return File::nonexistent;

}

//-----------------------------------------------------------------------------------------------------------
/*void FileTreeComponentEx::scrollToTop()
{
getViewport()->getVerticalScrollBar()->setCurrentRangeStart (0);
}

//-----------------------------------------------------------------------------------------------------------
void FileTreeComponentEx::setDragAndDropDescription (const String& description) throw()
{
dragAndDropDescription = description;
}*/[/code]

I’m not using the whole code yet. And I couldn’t really override some of the stuff as the FileListTreeItem class is NOT in the Juce .h files. At least I couldn’t find it… still, since I will do a lot of changes, I don’t mind copying the whole code.

Wk

One thing I still need to figure out, is how to hide folders with no files. Specially when I use a filter like “piano*.sfz” to search for piano sounds…

Wk