ぬの部屋(仮)
nu-no-he-ya
  •     123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
       1234
    567891011
    12131415161718
    19202122232425
    26272829   
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28      
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
    1234567
    891011121314
    15161718192021
    22232425262728
           
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
         12
    3456789
    10111213141516
    17181920212223
    242526272829 
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
        123
    45678910
    11121314151617
    18192021222324
    25262728   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    15161718192021
    293031    
           
         12
    3456789
    10111213141516
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    2627282930  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728     
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
        123
    45678910
    11121314151617
    18192021222324
    252627282930 
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
     123456
    78910111213
    14151617181920
    21222324252627
    28293031   
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
     123456
    78910111213
    14151617181920
    21222324252627
    282930    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31      
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
      12345
    6789101112
    13141516171819
    20212223242526
    27282930   
           
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    3031     
          1
    2345678
    9101112131415
    16171819202122
    232425262728 
           
       1234
    567891011
    12131415161718
    19202122232425
    262728293031 
           
    1234567
    891011121314
    15161718192021
    22232425262728
    293031    
           
         12
    3456789
    10111213141516
    17181920212223
    24252627282930
           
      12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
           
    1234567
    891011121314
    15161718192021
    22232425262728
    2930     
           
        123
    45678910
    11121314151617
    18192021222324
    25262728293031
           
  • wxListBoxで自作ツリー構造を表示する

    tree.hpp

    #ifndef TREE_H
    #define TREE_H
    
    #endif //TREE_H
    
    #include <algorithm>
    #include <memory>
    
    using namespace std::literals::string_literals;
    
    // ノードを継承したクラスに asString() メンバ関数があるかを判定するコンセプト
    template<typename T>
    concept HasAsString = requires(T a) {
        { a.asString() } -> std::same_as<std::string>;
    };
    
    // ノードの基底クラス
    class NodeBase {
    protected:
    public:
        std::shared_ptr<NodeBase> parent;
    
        virtual ~NodeBase() = default;
        virtual std::string asString() const = 0;  // 必ず実装させる仮想関数
        virtual std::shared_ptr<NodeBase> getParent() const { return parent; }
        virtual bool isFolder() const = 0;
    };
    
    // フォルダクラス
    template <HasAsString T>
    class Folder : public NodeBase, public std::enable_shared_from_this < Folder<T> > {
        std::vector<std::shared_ptr<NodeBase>> children;  // 子ノードは NodeBase 型を保持
    
        T value;
        bool isOpen;
    public:
        Folder(const T& data) : value(data), isOpen(false) {}
    
        // 子ノードを追加するメソッド
        void add(const std::shared_ptr<NodeBase>& node) {
            children.push_back(node);
            node->parent = std::dynamic_pointer_cast<NodeBase>(this->shared_from_this());
        }
    
        const T& getName() const {
            return value;
        }
    
        std::string asString() const override {
            return value.asString();
        }
    
        const std::vector<std::shared_ptr<NodeBase>>& getChildren() const {
            return children;
        }
        std::vector<std::shared_ptr<NodeBase>>& getChildren() {
            return children;
        }
    
        bool getIsOpen() const {
            return isOpen;
        }
    
        void setIsOpen(bool open) {
            isOpen = open;
        }
    
        bool isFolder() const override {
    		return true;
    	}
    
    
    };
    
    // アイテムクラス
    // フォルダに入れるデータを保持するクラス
    template <HasAsString T>
    class Item : public NodeBase, public std::enable_shared_from_this < Item<T> > {
        T value;
    public:
        Item(const T& data) : value(data) {}
    
        std::string asString() const override {
            return value.asString();
        }
    
        bool isFolder() const override {
            return false;
        }
    };
    
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////
    
    // 全てのノードの数をカウントする関数
    template <HasAsString FT>
    int getAllNodeCount(const std::shared_ptr<NodeBase>& node) {
        int count = 1;  // 自分自身をカウント
    
        // フォルダの場合は、子ノードも再帰的にカウント
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            for (const auto& child : folder->getChildren()) {
                count += getAllNodeCount<FT>(child);
            }
        }
    
        return count;
    }
    
    
    
    // 開いているノードの数をカウントする関数
    template <HasAsString FT>
    int getOpenNodeCount(const std::shared_ptr<NodeBase>& node) {
        int count = 1;  // 自分自身をカウント
    
        // フォルダの場合、開いているかどうかを確認
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (folder->getIsOpen()) {
                // 開いている場合、子ノードも再帰的にカウント
                for (const auto& child : folder->getChildren()) {
                    count += getOpenNodeCount<FT>(child);
                }
            }
        }
    
        return count;
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    // 指定した index のノードを取得する関数の補助関数
    template <HasAsString FT>
    std::shared_ptr<NodeBase> getNodeHelper(const std::shared_ptr<NodeBase>& node, int& currentIndex, int targetIndex, bool open = false) {
        // 現在のノードをカウント
        if (currentIndex == targetIndex) {
            return node;
        }
        currentIndex++;
    
        // フォルダの場合は、開閉状態を確認し、再帰的に子ノードを探索
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (open || folder->getIsOpen()) {
                for (const auto& child : folder->getChildren()) {
                    auto result = getNodeHelper<FT>(child, currentIndex, targetIndex, open);
                    if (result) {
                        return result;
                    }
                }
            }
        }
    
        return nullptr; // 見つからなかった場合
    }
    
    // 指定した index のノードを取得する関数
    // ここでの index は、開いているノードのみでカウントする
    template <HasAsString FT>
    std::shared_ptr<NodeBase> getNodeOnlyOpen(const std::shared_ptr<NodeBase>& root, int targetIndex) {
        int currentIndex = 0; // ノードのカウント用
        return getNodeHelper<FT>(root, currentIndex, targetIndex, false);
    }
    
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    
    
    
    // ノードを削除する関数
    template <HasAsString FT>
    void deleteNode(std::shared_ptr<NodeBase> node) {
        if (auto parent = node->getParent()) {
            if (auto parentFolder = std::dynamic_pointer_cast<Folder<FT>>(parent)) {
                auto& siblings = parentFolder->getChildren();
                siblings.erase(std::remove(siblings.begin(), siblings.end(), node), siblings.end());
            }
        }
    }
    
    // 指定したノードの管理情報を取得する関数
    // 戻り値 1 親ノード
    // 戻り値 2 posで指定したノードを持つ親ノードの、子ノードリストのインデクス
    template <HasAsString FT>
    std::pair< std::shared_ptr<NodeBase>, int> GetNodeListPos(std::shared_ptr<NodeBase> root, int pos) {
    
        // posの位置の現在のノードを取得
        auto now_node = getNodeOnlyOpen<FT>(root, pos);
    
        // now_nodeの親ノードを取得
        auto parent_node = now_node->getParent();
    
        // now_nodeの親ノードの子ノードリストを取得
        auto parent_folder = std::dynamic_pointer_cast<Folder<FT>>(parent_node);
        auto& siblings = parent_folder->getChildren();
    
        // now_nodeの親ノードの子ノードリストのインデクスを取得
        auto it = std::find(siblings.begin(), siblings.end(), now_node);
        int index = std::distance(siblings.begin(), it);
    
    
        return { parent_node,index };
    
    }
    
    template <HasAsString FT, HasAsString IT>
    void addNodeUnder(std::shared_ptr<NodeBase> root, std::shared_ptr<NodeBase> node) {
        // nodeをrootの最後に追加
        auto folder = std::dynamic_pointer_cast<Folder<FT>>(root);
        folder->getChildren().push_back(node);
        node->parent = root;
    
    }
    
    template <HasAsString FT, HasAsString IT>
    void addNodeHere(std::shared_ptr<NodeBase> root, std::shared_ptr<NodeBase> node, int pos) {
        // ノードを追加する関数
        // 挿入位置は番号posで指定する
        // 新しく追加したアイテムが必ずpos番目になる
        // 必ず、追加前のposのノードと同じ階層に追加する
    
        // 番号posは開いているノードのみでカウントする
        // 例えばfolder21がノードを持っていても、folder21は開いていないのでその中のノードはカウントしない
        // 1 - folder1
        // 2   - folder2
        // 3      item21
        // 4      item22
        // 5      + folder21
        // 6   - folder3
        // 7      item31
        // 8      item32
        // 9      item33
    
        // getNode(folder1,3) == item21
        // この時、
        // 例1 addNode(NewFolder,3) で
        // 2   - folder2
        // 3      + NewFolder
        // 4      item21
        // 5      item22
    
    
        auto childinfo = GetNodeListPos<FT>(root, pos);
        std::shared_ptr<NodeBase> childlist = childinfo.first;
        auto index = childinfo.second;
    
        // nodeをchildlistのindex番に追加
        auto folder = std::dynamic_pointer_cast<Folder<FT>>(childlist);
        folder->getChildren().insert(folder->getChildren().begin() + index, node);
        node->parent = childlist;
    
    }
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    
    
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    
    struct TreeSliceItem {
        int pos;
        std::shared_ptr<NodeBase> node;
        int hierarchy;
    };
    template <HasAsString FT>
    void GetTreeSliceTraverse(const std::shared_ptr<NodeBase>& node, int hierarchy, int& currentIndex, int from, int to, std::vector<TreeSliceItem>& slice) {
        if (currentIndex >= from && currentIndex <= to) {
            slice.push_back({ currentIndex, node, hierarchy });
        }
        currentIndex++;
    
        if (auto folder = std::dynamic_pointer_cast<Folder<FT>>(node)) {
            if (folder->getIsOpen()) {
                for (const auto& child : folder->getChildren()) {
                    GetTreeSliceTraverse<FT>(child, hierarchy + 1, currentIndex, from, to, slice);
                }
            }
        }
    }
    
    // ツリーから一部を取り出す関数
    template <HasAsString FT>
    std::vector< TreeSliceItem> GetTreeSlice(std::shared_ptr<NodeBase> root, int from, int to) {
        // 例えば、以下の状態の時、
        // 1 - folder1
        // 2   - folder2
        // 3      item21
        // 4      item22
        // 5      + folder21
        // 6   - folder3
        // 7      item31
        // 8      item32
        // 9      item33
    
        // GetTreeSlice(folder1,3,7) で
        // 3      item21
        // 4      item22
        // 5      + folder21
        // 6   - folder3
        // 7      item31
        // を取得
    
        std::vector<TreeSliceItem> slice;
        int currentIndex = 0;
        int currentHierarchy = 0;
    
        GetTreeSliceTraverse<FT>(root, currentHierarchy, currentIndex, from, to, slice);
    
        return slice;
    
    }
    

    TreeSlice.hpp

    ツリーの一部を取得するクラスを取得するクラス。

    #include "tree.hpp"
     
    // ツリーの一部を取り出すクラス
    template
    <HasAsString FT, HasAsString IT> class TreeSlice { std::shared_ptr<Folder<FT>> _root; std::vector< TreeSliceItem> _items; int _size; int _pos; public: void SetTree(const std::shared_ptr<Folder<FT>>& r) { _root = r; } void SetSliceInfo(int size,int pos) { _size = size; _pos = pos; } void GetSlice() { _items = GetTreeSlice<FT>(_root, _pos, _pos + _size - 1); } const std::vector< TreeSliceItem>& GetItems() const { return _items; } };
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
    ////////////////////////////////////////////////////
     
    struct FolderData {
        std::string name;
        std::string asString() const {
            return name;
        }
    
        // コンストラクタ
        FolderData(const std::string& n) : name(n) {}
    
    };
    
          
    struct ItemData {
        std::string name;
        std::string asString() const {
            return name;
        }
    
        // コンストラクタ
        ItemData(const std::string& n) : name(n) {}
    
    };
    

    main.cpp

    #ifndef WX_PRECOMP
    #include <wx/wx.h>
    #endif
    
    #include <wx/gdicmn.h> // wxPointに必要
    #include <wx/frame.h>  // wxFrameに必要
    
    
    // wxBufferedPaintDC のinclude
    #include <wx/dcbuffer.h>
    
    /////////////////////////////////////
    /////////////////////////////////////
    /////////////////////////////////////
    
    #include <string>
    #include <memory>
    #include <unordered_map>
    
    #include "tree_data.hpp"
    
    
    // データを作成
    std::shared_ptr<Folder<FolderData>> create_data() {
        // ツリー構造を作成
        auto root = std::make_shared<Folder<FolderData>>(FolderData{ "folder1" });
    
        for (size_t i = 0; i < 10; i++) {
            auto folder = std::make_shared<Folder<FolderData>>(FolderData{ "folder" + std::to_string(i) });
            root->add(folder);
            for (size_t j = 0; j < 10; j++) {
                auto item = std::make_shared<Item<ItemData>>(ItemData{ "item" + std::to_string(i) + std::to_string(j) });
                folder->add(item);
            }
        }
        root->setIsOpen(true);
    
        return root;
    }
    
          
    // リストボックスが一度に表示可能なアイテム数を取得
    int GetVisibleItemCount(wxListBox * listBox)
    {
        // リストボックスのDCを使って一行の高さを取得し
        // リストボックスのクライアントサイズから表示可能なアイテム数を計算する
    
    
        // リストボックスのクライアントサイズを取得
        wxSize clientSize = listBox->GetClientSize();
    
        // wxClientDCを使用してデフォルトのアイテム高さを取得
        wxClientDC dc(listBox);
        wxCoord textWidth, textHeight;
        // 指定した文字列の幅と高さを取得
        dc.GetTextExtent("TEXT", &textWidth, &textHeight);
    
        // 表示可能なアイテム数を計算
        int visibleItemCount = clientSize.GetHeight() / textHeight;
    
        return visibleItemCount;
    }
    

    // スクロールバー付きリスト
    class ExList : public wxPanel {
    
        int itemCount;// アイテム数
        int visibleItemCount;// 一度に表示できるアイテム数
    
        wxBoxSizer* mainSizer;
        wxScrollBar* scrollBar;
    
        // リストコントロール
        wxListBox* listBox;
    
        TreeSlice<FolderData, ItemData> _treeSlice;// リストの一部を取得
        std::shared_ptr<Folder<FolderData>> _root;// ツリーのルート
    
        std::vector< TreeSliceItem> _now_valid_items;// 表示する範囲のツリーのアイテム
    
        void PostCreate() {
    
    
            _root = create_data();// アイテム作成
            _treeSlice.SetTree(_root);// ツリーの一部を切り出す準備
    
            visibleItemCount = GetVisibleItemCount(listBox);// 表示可能なアイテム個数を更新
    
            disp();
    
        }
    
    public:
        // コンストラクタ
        ExList(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
            // メインSizer
            mainSizer = new wxBoxSizer(wxHORIZONTAL);
            this->SetSizer(mainSizer);
    
            // リストコントロール
            listBox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_SINGLE);
            mainSizer->Add(listBox, 1, wxEXPAND | wxALL, 5);
    
            // スクロールバー
            scrollBar = new wxScrollBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL);
            mainSizer->Add(scrollBar, 0, wxEXPAND | wxALL, 5);
    
    
            this->Layout();
            CallAfter(&ExList::PostCreate);
    
            // スクロールバーのイベント
            scrollBar->Bind(wxEVT_SCROLL_PAGEUP, &ExList::OnScrollPageUp, this);
            scrollBar->Bind(wxEVT_SCROLL_PAGEDOWN, &ExList::OnScrollPageDown, this);
            scrollBar->Bind(wxEVT_SCROLL_THUMBTRACK, &ExList::OnScrollThumbTrack, this);
            scrollBar->Bind(wxEVT_SCROLL_LINEUP, &ExList::OnScrollUp, this);
            scrollBar->Bind(wxEVT_SCROLL_LINEDOWN, &ExList::OnScrollDown, this);
    
            // リストボックスのアイテムをクリックした時のイベント
            listBox->Bind(wxEVT_LISTBOX, &ExList::OnListBox, this);
    
            // サイズイベント
            this->Bind(wxEVT_SIZE, &ExList::OnSize, this);
    
        }
    
    
        void disp() {
            listBox->Clear();
    
            int offset = scrollBar->GetThumbPosition();
    
            itemCount = getOpenNodeCount<FolderData>(_root);
            // スクロールバーの範囲とサムサイズを設定
            scrollBar->SetScrollbar(offset, visibleItemCount, itemCount, 5, true);
    
    
    
    
            _treeSlice.SetSliceInfo(visibleItemCount, offset);
            _treeSlice.GetSlice();
            _now_valid_items = _treeSlice.GetItems();
    
    
            // デバッグにposを表示
            std::string debugMessage = "pos: " + std::to_string(offset) + "\n";
            OutputDebugStringA(debugMessage.c_str());
            
            /////////////////////////////////////////////
            // 現在の表示範囲のアイテムを追加
            for (int i = 0; i < _now_valid_items.size(); i++) {
    
    
                std::string itemstr;
                // itemstr にアイテムの文字列を設定
                // hierarchy個のスペースを追加
                for (int j = 0; j < _now_valid_items[i].hierarchy; j++) {
                    itemstr += "   ";
                }
                auto node = _now_valid_items[i].node;
                if (node->isFolder()) {
                    std::dynamic_pointer_cast<Folder<FolderData>>(node)->getIsOpen() ? itemstr += "- " : itemstr += "+ ";
                }
                else {
                    itemstr += "  ";
                }
    
                itemstr += node->asString();
                listBox->Append(itemstr);// アイテムをリストに追加
    
            }
        }
        
        // スクロールバーのつまみ以外の部分をクリックしたとき
        void OnScrollPageUp(wxScrollEvent& event) {
    
            disp();
        }
    
        void OnScrollPageDown(wxScrollEvent& event) {
    
            disp();
        }
    
        void OnScrollThumbTrack(wxScrollEvent& event) {
            
            disp();
        }
    
        // 下方向クリック
        void OnScrollDown(wxScrollEvent& event) {
    
            disp();
        }
        // 上方向クリック
        void OnScrollUp(wxScrollEvent& event) {
    
            disp();
        }
    
        // リストボックスのアイテムをクリックした時のイベント
        void OnListBox(wxCommandEvent& event) {
            // 選択されたアイテムのインデックスを取得
            int index = listBox->GetSelection();
            if (index == wxNOT_FOUND) {
                return;
            }
    
            auto node = _now_valid_items[index].node;
            
            std::string debugMessage = "Selected: " + node->asString() + "\n";
            OutputDebugStringA(debugMessage.c_str());
    
            auto folder = std::dynamic_pointer_cast<Folder<FolderData>>(node);
    
            if (folder) {
                folder->setIsOpen(!folder->getIsOpen());// クリックしたフォルダをオープン
                disp();
            }
    
        }
    
    
    
        void OnSize(wxSizeEvent& event) {       
    
            visibleItemCount = GetVisibleItemCount(listBox);// 表示可能なアイテム個数を更新
    
            disp();
    
            // イベントを処理済みにする
            event.Skip();
        }
    
    
    };
    
    // ウィンドウ作成
    class MyFrame : public wxFrame
    {
        wxBoxSizer* mainSizer;
    
        ExList* exList; // スクロールバー付きリスト
    
    public:
    
        void PostCreate() {
    
    
            this->Layout(); // レイアウトの更新
        }
    
    
        MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
            : wxFrame(NULL, wxID_ANY, title, pos, size)
        
        {
    
            // メインSizer
            mainSizer = new wxBoxSizer(wxHORIZONTAL);
            this->SetSizer(mainSizer);
    
    
            // リストコントロール
            exList = new ExList(this);
            mainSizer->Add(exList, 1, wxEXPAND | wxALL, 5);
    
    
            // CallAfter : 現在処理中のイベントが終わったらPostCreateを実行
            // コンストラクタはウィンドウ生成イベント扱い
            CallAfter(&MyFrame::PostCreate);
    
    
        }
    
    private:
    };
    
    /////////////////////////////////////
    /////////////////////////////////////
    /////////////////////////////////////
    
    // wxWidgetsのアプリケーション作成
    class MyApp : public wxApp {
    public:
    
        virtual bool OnInit() {
            MyFrame* frame = new MyFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
            frame->Show(true);
    
            return true;
        }
    
    };
    
    /////////////////////////////////////
    /////////////////////////////////////
    /////////////////////////////////////
    
    // WinMainをマクロで定義
    wxIMPLEMENT_APP(MyApp);