DirectoryTreeView.cpp

#include "StdAfx.h"
#include "DirectoryTreeView.h"

#include "Settings.h"


using namespace Core;

using namespace System;
using namespace System::Diagnostics;


/// [ Constructor ]
DirectoryTreeView::DirectoryTreeView()
{
}


/// ツリーを更新する
void DirectoryTreeView::RefreshTree()
{
    // 再描画を無効にする
    BeginUpdate();

    // すべてのツリーノードを削除する
    this->Nodes->Clear();


    String^ rootDirectory = Environment::CurrentDirectory;  // ルートディレクトリ

    // ... ノードを構築する
    Windows::Forms::TreeNode^ treeNode = gcnew Windows::Forms::TreeNode( rootDirectory, 0, 0 );

    // ... それをツリーのノードに追加する
    this->Nodes->Add( treeNode );

    // ... それをディレクトリに追加する
    AddDirectories( treeNode );


    // ツリーノードを展開する
    treeNode->Expand();


    // 再描画を有効にする
    EndUpdate();


    if( this->SelectedNode == nullptr )
    {
        // 選択されているノードがなければ、ルートを選択する
        this->SelectedNode = treeNode;
    }


    Debug::WriteLine( "ディレクトリ ツリーを更新した" );
}

/// ディレクトリを追加する
void DirectoryTreeView::AddDirectories( System::Windows::Forms::TreeNode^ treeNode )
{
    // ツリーから絶対パスを取得する
    String^ absolutePath = treeNode->FullPath;

    // ... ディレクトリを作成する
    IO::DirectoryInfo^ directoryInfo = gcnew IO::DirectoryInfo( absolutePath );


    Array^ subDirectories;    // サブディレクトリを格納するための配列

    try
    {
        // サブディレクトリを取得する
        subDirectories = directoryInfo->GetDirectories();
    }
    catch( System::IO::IOException^ e )
    {
        Debug::WriteLine( "サブディレクトリにアクセスできない : " + e->Message );

        // 処理を抜ける
        return;
    }
    catch( System::UnauthorizedAccessException^ e )
    {
        Debug::WriteLine( "オペレーティングシステムにより アクセスを拒否された : " + e->Message );

        // 処理を抜ける
        return;
    }


    for each( IO::DirectoryInfo^ directory in subDirectories )
    {
        if( directory->FullName != Settings::UserSettingFloder )
        {
            // 設定ファイルのディレクトリでなければ、ディレクトリのノードを構築する
            Windows::Forms::TreeNode^ newNode = gcnew Windows::Forms::TreeNode(
                directory->Name,   // ツリーノードのラベル
                1,      // 選択されていないときに表示する Image のインデックス値
                2       // 選択されているときに表示する Image のインデックス値
            );

            // ... それを新しいツリーノードとして追加する
            treeNode->Nodes->Add( newNode );

            // ... そのサブディレクトリを作成するため 再帰的に呼び出す
            AddDirectories( newNode );
        }
    }
}


/// キーが押された
void DirectoryTreeView::OnKeyDown( System::Windows::Forms::KeyEventArgs^ e )
{
    // 基本クラスの同一関数を呼び出す
    System::Windows::Forms::TreeView::OnKeyDown( e );


    // [ F5 ]が押されたならば、表示を更新する
    if( e->KeyCode == Windows::Forms::Keys::F5 )
    {
        // 現在 選択されているノードのフルパスを取得する
        String^ selectedNode = this->SelectedNode->FullPath;

        // ... ツリーを更新する
        RefreshTree();

        // ... ディレクトリを選択し直す
        SelectSpecifiedDirectory( selectedNode );
    }
}


/// 指定されたディレクトリを選択する
void DirectoryTreeView::SelectSpecifiedDirectory( System::String^ targetPath )
{
    // 指定されたディレクトリを ノードから検索する
    Windows::Forms::TreeNode^ findedNode = SearchNodeForString( targetPath, this->TopNode );

    if( findedNode != nullptr )
    {
        // 発見したノードを選択する
        this->SelectedNode = findedNode;

        Debug::WriteLine( "選択されたディレクトリ : " + findedNode->FullPath );
    }
}

/// 文字列に一致する ノードを検索する
System::Windows::Forms::TreeNode^ DirectoryTreeView::SearchNodeForString( System::String^ target, System::Windows::Forms::TreeNode^ treeNode )
{
    Windows::Forms::TreeNode^ result = nullptr;

    if( treeNode->FullPath == target )
    {
        // ノードのフルパスが対象の文字列と一致するならば、そのノードを返す
        result = treeNode;
    }
    else
    {
        for each( Windows::Forms::TreeNode^ node in treeNode->Nodes )
        {
            // 全てのノードを 再帰的に呼び出す
            result = SearchNodeForString( target, node );

             // 発見できたならば処理を中止する
            if( result != nullptr ) break;
        }
    }
    return result;
}