//+------------------------------------------------------------------+
//|                                                FileNavigator.mqh |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "TreeView.mqh"
//+------------------------------------------------------------------+
//| Класс для создания файлового навигатора                          |
//+------------------------------------------------------------------+
class CFileNavigator : public CElement
  {
private:
   //--- Объекты для создания элемента
   CTreeView         m_treeview;
   //--- Основные массивы для хранения данных
   int               m_g_list_index[];           // общий индекс
   int               m_g_prev_node_list_index[]; // общий индекс предыдущего узла
   string            m_g_item_text[];            // имя папки/файла
   int               m_g_item_index[];           // локальный индекс
   int               m_g_node_level[];           // уровень узла
   int               m_g_prev_node_item_index[]; // локальный индекс предыдущего узла
   int               m_g_items_total[];          // всего элементов в папке
   int               m_g_folders_total[];        // количество папок в папке
   bool              m_g_is_folder[];            // признак папки
   bool              m_g_item_state[];           // состояние пункта (свёрнут/открыт)
   //--- Вспомогательные массивы для сбора данных
   int               m_l_prev_node_list_index[];
   string            m_l_item_text[];
   string            m_l_path[];
   int               m_l_item_index[];
   int               m_l_item_total[];
   int               m_l_folders_total[];
   //--- Ширина области древовидного списка
   int               m_treeview_width;
   //--- Картинки для (1) папок и (2) файлов
   string            m_file_icon;
   string            m_folder_icon;
   //--- Текущий путь относительно файловой "песочницы" терминала
   string            m_current_path;
   //--- Текущий полный путь относительно файловой системы включая метку тома жёсткого диска
   string            m_current_full_path;
   //--- Область текущей директории
   int               m_directory_area;
   //--- Режим содержания файлового навигатора
   ENUM_FILE_NAVIGATOR_CONTENT m_navigator_content;
   //---
public:
                     CFileNavigator(void);
                    ~CFileNavigator(void);
   //--- Методы для создания файлового навигатора
   bool              CreateFileNavigator(const int x_gap,const int y_gap);
   //---
private:
   void              InitializeProperties(const int x_gap,const int y_gap);
   bool              CreateCanvas(void);
   bool              CreateTreeView(void);
   //---
public:
   //--- (1) Возвращает указатель древовидного списка, 
   //    (2) режим навигатора (Показывать все/Только папки), (3) содержание навигатора (Общая папка/Локальная/Всё)
   CTreeView        *GetTreeViewPointer(void)                                 { return(::GetPointer(m_treeview));          }
   void              NavigatorMode(const ENUM_FILE_NAVIGATOR_MODE mode)       { m_treeview.NavigatorMode(mode);            }
   void              NavigatorContent(const ENUM_FILE_NAVIGATOR_CONTENT mode) { m_navigator_content=mode;                  }
   //--- (1) ширина древовидного списка, (2) установка пути к файлам для файлов и папок
   void              TreeViewWidth(const int x_size)                          { m_treeview_width=x_size;                   }
   void              FileIcon(const string file_path)                         { m_file_icon=file_path;                     }
   void              FolderIcon(const string file_path)                       { m_folder_icon=file_path;                   }
   //--- Возвращает (1) текущий путь и (2) полный путь, (3) выделенный файл
   string            CurrentPath(void)                                  const { return(m_current_path);                    }
   string            CurrentFullPath(void)                              const { return(m_current_full_path);               }
   //--- Возвращает (1) область директории и (2) выделенный файл
   int               DirectoryArea(void)                                const { return(m_directory_area);                  }
   string            SelectedFile(void)                                 const { return(m_treeview.SelectedItemFileName()); }
   //---
public:
   //--- Обработчик событий графика
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- Управление
   virtual void      Delete(void);
   //--- Рисует элемент
   virtual void      Draw(void);
   //---
private:
   //--- Обработка события выбора нового пути в древовидном списке
   void              OnChangeTreePath(void);

   //--- Заполняет массивы параметрами элементов файловой системы терминала
   void              FillArraysData(void);
   //--- Читает файловую систему и записывает параметры в массивы
   void              FileSystemScan(const int root_index,int &list_index,int &node_level,int &item_index,int search_area);
   //--- Изменяет размер вспомогательных массивов относительно текущего уровня узла 
   void              AuxiliaryArraysResize(const int node_level);
   //--- Определяет, передано имя папки или файла
   bool              IsFolder(const string file_name);
   //--- Возвращает количество (1) элементов и (2) папок в указанной директории
   int               ItemsTotal(const string search_path,const int mode);
   int               FoldersTotal(const string search_path,const int mode);
   //--- Возвращает локальный индекс предыдущего узла относительно переданных параметров
   int               PrevNodeItemIndex(const int root_index,const int node_level);

   //--- Добавляет пункт в массивы
   void              AddItem(const int list_index,const string item_text,const int node_level,const int prev_node_item_index,
                             const int item_index,const int items_total,const int folders_total,const bool is_folder);
   //--- Переход на следующий узел
   void              ToNextNode(const int root_index,int list_index,int &node_level,
                                int &item_index,long &handle,const string item_text,const int search_area);

   virtual void      DrawText(void);

   //--- Изменить ширину по правому краю окна
   virtual void      ChangeWidthByRightWindowSide(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CFileNavigator::CFileNavigator(void) : m_current_path(""),
                                       m_current_full_path(""),
                                       m_treeview_width(200),
                                       m_directory_area(FILE_COMMON),
                                       m_navigator_content(FN_ONLY_MQL),
                                       m_file_icon("Images\\EasyAndFastGUI\\Icons\\bmp16\\text_file_w10.bmp"),
                                       m_folder_icon("Images\\EasyAndFastGUI\\Icons\\bmp16\\folder_w10.bmp")
  {
//--- Сохраним имя класса элемента в базовом классе
   CElementBase::ClassName(CLASS_NAME);
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CFileNavigator::~CFileNavigator(void)
  {
  }
//+------------------------------------------------------------------+
//| Обработчик событий                                               |
//+------------------------------------------------------------------+
void CFileNavigator::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Обработка события "Изменение пути в древовидном списке"
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE_TREE_PATH)
     {
      OnChangeTreePath();
      //--- Отобразим текущий путь в адресной строке
      Update(true);
      return;
     }
  }
//+------------------------------------------------------------------+
//| Создаёт файловый навигатор                                       |
//+------------------------------------------------------------------+
bool CFileNavigator::CreateFileNavigator(const int x_gap,const int y_gap)
  {
//--- Выйти, если нет указателя на главный элемент
   if(!CElement::CheckMainPointer())
      return(false);
//--- Сканируем файловую систему терминала и заносим данные в массивы
   FillArraysData();
//--- Инициализация свойств
   InitializeProperties(x_gap,y_gap);
//--- Создание элемента
   if(!CreateTreeView())
      return(false);
   if(!CreateCanvas())
      return(false);
//--- Отобразим текущий путь в адресной строке
   OnChangeTreePath();
   return(true);
  }
//+------------------------------------------------------------------+
//| Инициализация свойств                                            |
//+------------------------------------------------------------------+
void CFileNavigator::InitializeProperties(const int x_gap,const int y_gap)
  {
   m_x        =CElement::CalculateX(x_gap);
   m_y        =CElement::CalculateY(y_gap);
   m_x_size   =(m_x_size<1 || m_auto_xresize_mode)? m_main.X2()-CElementBase::X()-m_auto_xresize_right_offset : m_x_size;
   m_y_size   =(m_y_size<1)? 20 : m_y_size;
//--- Цвета по умолчанию
   m_border_color =(m_border_color!=clrNONE)? m_border_color : C'150,170,180';
   m_label_color  =(m_label_color!=clrNONE)? m_label_color : clrBlack;
//--- Отступы от крайней точки
   CElementBase::XGap(x_gap);
   CElementBase::YGap(y_gap);
  }
//+------------------------------------------------------------------+
//| Создаёт объект для рисования                                     |
//+------------------------------------------------------------------+
bool CFileNavigator::CreateCanvas(void)
  {
//--- Формирование имени объекта
   string name=CElementBase::ElementName("file_navigator");
//--- Создание объекта
   if(!CElement::CreateCanvas(name,m_x,m_y,m_treeview.XSize(),m_y_size))
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Создаёт древовидный список                                       |
//+------------------------------------------------------------------+
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\folder_w10.bmp"
#resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\text_file_w10.bmp"
//---
bool CFileNavigator::CreateTreeView(void)
  {
//--- Сохраним указатель на окно
   m_treeview.MainPointer(this);
//--- Координаты
   int x=0,y=m_y_size-1;
//--- Свойства
   m_treeview.XSize(m_x_size);
   m_treeview.TreeViewWidth(m_treeview_width);
   m_treeview.ResizeListMode(true);
   m_treeview.ShowItemContent(true);
   m_treeview.AutoXResizeMode(CElementBase::AutoXResizeMode());
   m_treeview.AutoXResizeRightOffset(0);
   m_treeview.AnchorRightWindowSide(CElementBase::AnchorRightWindowSide());
   m_treeview.AnchorBottomWindowSide(CElementBase::AnchorBottomWindowSide());
//--- Формируем массивы древовидного списка
   int items_total=::ArraySize(m_g_item_text);
   for(int i=0; i<items_total; i++)
     {
      //--- Определим картинку для пункта (папка/файл)
      string icon_path=(m_g_is_folder[i])? m_folder_icon : m_file_icon;
      //--- Если это папка, удалим последний символ ('\') в строке 
      if(m_g_is_folder[i])
         m_g_item_text[i]=::StringSubstr(m_g_item_text[i],0,::StringLen(m_g_item_text[i])-1);
      //--- Добавим пункт в древовидный список
      m_treeview.AddItem(i,m_g_prev_node_list_index[i],m_g_item_text[i],icon_path,m_g_item_index[i],
                         m_g_node_level[i],m_g_prev_node_item_index[i],m_g_items_total[i],m_g_folders_total[i],false,m_g_is_folder[i]);
     }
//--- Создать древовидный список
   if(!m_treeview.CreateTreeView(x,y))
      return(false);
//--- Добавить элемент в массив
   CElement::AddToArray(m_treeview);
   return(true);
  }
//+------------------------------------------------------------------+
//| Обработка события выбора нового пути в древовидном списке        |
//+------------------------------------------------------------------+
void CFileNavigator::OnChangeTreePath(void)
  {
//--- Получим текущий путь
   string path=m_treeview.CurrentFullPath();
//--- Если это общая папка терминалов
   if(::StringFind(path,"Common\\Files\\",0)>-1)
     {
      //--- Получим адрес общей папки терминалов
      string common_path=::TerminalInfoString(TERMINAL_COMMONDATA_PATH);
      //--- Удалим в строке (принятой в событии) префикс "Common\"
      path=::StringSubstr(path,7,::StringLen(common_path)-7);
      //--- Сформируем путь (краткую и полную версию)
      m_current_path      =::StringSubstr(path,6,::StringLen(path)-6);
      m_current_full_path =common_path+"\\"+path;
      //--- Сохраним область директории
      m_directory_area=FILE_COMMON;
     }
//--- Если это локальная папка терминала
   else if(::StringFind(path,"MQL5\\Files\\",0)>-1)
     {
      //--- Получим адрес данных в локальной папке терминала
      string local_path=::TerminalInfoString(TERMINAL_DATA_PATH);
      //--- Сформируем путь (краткую и полную версию)
      m_current_path      =::StringSubstr(path,11,::StringLen(path)-11);
      m_current_full_path =local_path+"\\"+path;
      //--- Сохраним область директории
      m_directory_area=0;
     }
  }
//+------------------------------------------------------------------+
//| Заполняет массивы параметрами элементов файловой системы         |
//+------------------------------------------------------------------+
void CFileNavigator::FillArraysData(void)
  {
//--- Счётчики (1) общих индексов, (2) уровней узлов, (3) локальных индексов
   int list_index =0;
   int node_level =0;
   int item_index =0;
//--- Если нужно отображать обе директории (Общая (0)/Локальная (1))
   int begin=0,end=1;
//--- Если нужно отображать содержимое только локальной директории
   if(m_navigator_content==FN_ONLY_MQL)
      begin=1;
//--- Если нужно отображать содержимое только общей директории
   else if(m_navigator_content==FN_ONLY_COMMON)
      begin=end=0;
//--- Пройдёмся по указанным директориям
   for(int root_index=begin; root_index<=end; root_index++)
     {
      //--- Определим директорию для сканирования файловой структуры
      int search_area=(root_index>0) ? 0 : FILE_COMMON;
      //--- Обнулим счётчик локальных индексов
      item_index=0;
      //--- Увеличим размер массивов на один элемент (относительно уровня узла)
      AuxiliaryArraysResize(node_level);
      //--- Получим кол-во файлов и папок в указанной директории (* - проверить все файлы/папки)
      string search_path   =m_l_path[0]+"*";
      m_l_item_total[0]    =ItemsTotal(search_path,search_area);
      m_l_folders_total[0] =FoldersTotal(search_path,search_area);
      //--- Добавим пункт с названием корневого каталога в начало списка
      string item_text=(root_index>0)? "MQL5\\Files\\" : "Common\\Files\\";
      AddItem(list_index,item_text,0,0,root_index,m_l_item_total[0],m_l_folders_total[0],true);
      //--- Увеличим счётчики общих индексов и уровней узлов
      list_index++;
      node_level++;
      //--- Увеличим размер массивов на один элемент (относительно уровня узла)
      AuxiliaryArraysResize(node_level);
      //--- Инициализация первых элементов для директории локальной папки терминала
      if(root_index>0)
        {
         m_l_item_index[0]           =root_index;
         m_l_prev_node_list_index[0] =list_index-1;
        }
      //--- Сканируем директории и заносим данные в массивы
      FileSystemScan(root_index,list_index,node_level,item_index,search_area);
     }
  }
//+------------------------------------------------------------------+
//| Читает файловую систему терминала и записывает                   |
//| параметры элементов в массивы                                    |
//+------------------------------------------------------------------+
void CFileNavigator::FileSystemScan(const int root_index,int &list_index,int &node_level,int &item_index,int search_area)
  {
   long   search_handle =INVALID_HANDLE; // Хэндл поиска папки/файла
   string file_name     ="";             // Имя найденного элемента (файла/папки)
   string filter        ="*";            // Фильтр поиска (* - проверить все файлы/папки)
//--- Сканируем директории и заносим данные в массивы
   while(!::IsStopped())
     {
      //--- Если это начало списка директории
      if(item_index==0)
        {
         //--- Путь для поиска всех элементов
         string search_path=m_l_path[node_level]+filter;
         //--- Получаем хэндл и имя первого файла
         search_handle=::FileFindFirst(search_path,file_name,search_area);
         //--- Получим кол-во файлов и папок в указанной директории
         m_l_item_total[node_level]    =ItemsTotal(search_path,search_area);
         m_l_folders_total[node_level] =FoldersTotal(search_path,search_area);
        }
      //--- Если индекс этого узла уже был, перейдём к следующему файлу
      if(m_l_item_index[node_level]>-1 && item_index<=m_l_item_index[node_level])
        {
         //--- Увеличим счётчик локальных индексов
         item_index++;
         //--- Переходим к следующему элементу
         ::FileFindNext(search_handle,file_name);
         continue;
        }
      //--- Если дошли до конца списка в корневом узле, закончим цикл
      if(node_level==1 && item_index>=m_l_item_total[node_level])
         break;
      //--- Если дошли до конца списка в любом узле, кроме корневого
      else if(item_index>=m_l_item_total[node_level])
        {
         //--- Перевести счётчик узлов на один уровень назад
         node_level--;
         //--- Обнулить счётчик локальных индексов
         item_index=0;
         //--- Закрываем хэндл поиска
         ::FileFindClose(search_handle);
         continue;
        }
      //--- Если это папка
      if(IsFolder(file_name))
        {
         //--- Перейдём на следующий узел
         ToNextNode(root_index,list_index,node_level,item_index,search_handle,file_name,search_area);
         //--- Увеличить счётчик общих индексов и начать новую итерацию
         list_index++;
         continue;
        }
      //--- Получим локальный индекс предыдущего узла
      int prev_node_item_index=PrevNodeItemIndex(root_index,node_level);
      //--- Добавим пункт с указанными данными в общие массивы
      AddItem(list_index,file_name,node_level,prev_node_item_index,item_index,0,0,false);
      //--- Увеличим счётчик общих индексов
      list_index++;
      //--- Увеличим счётчик локальных индексов
      item_index++;
      //--- Переходим к следующему элементу
      ::FileFindNext(search_handle,file_name);
     }
//--- Закрываем хэндл поиска
   ::FileFindClose(search_handle);
  }
//+------------------------------------------------------------------+
//| Изменяет размер вспомогательных массивов                         |
//| относительно текущего уровня узла                                |
//+------------------------------------------------------------------+
void CFileNavigator::AuxiliaryArraysResize(const int node_level)
  {
//--- Изменить размер массивов
   int new_size=node_level+1;
   ::ArrayResize(m_l_prev_node_list_index,new_size);
   ::ArrayResize(m_l_item_text,new_size);
   ::ArrayResize(m_l_path,new_size);
   ::ArrayResize(m_l_item_index,new_size);
   ::ArrayResize(m_l_item_total,new_size);
   ::ArrayResize(m_l_folders_total,new_size);
//--- Инициализация последнего значения
   m_l_prev_node_list_index[node_level] =0;
   m_l_item_text[node_level]            ="";
   m_l_path[node_level]                 ="";
   m_l_item_index[node_level]           =-1;
   m_l_item_total[node_level]           =0;
   m_l_folders_total[node_level]        =0;
  }
//+------------------------------------------------------------------+
//| Определяет, передано имя папки или файла                         |
//+------------------------------------------------------------------+
bool CFileNavigator::IsFolder(const string file_name)
  {
//--- Если в имени есть символы "\\", то это папка
   if(::StringFind(file_name,"\\",0)>-1)
      return(true);
//---
   return(false);
  }
//+------------------------------------------------------------------+
//| Считает количество файлов в текущей директории                   |
//+------------------------------------------------------------------+
int CFileNavigator::ItemsTotal(const string search_path,const int search_area)
  {
   int    counter       =0;              // счётчик элементов 
   string file_name     ="";             // имя файла
   long   search_handle =INVALID_HANDLE; // хэндл поиска
//--- Получаем первый файл в текущей директории
   search_handle=::FileFindFirst(search_path,file_name,search_area);
//--- Если директория не пуста
   if(search_handle!=INVALID_HANDLE && file_name!="")
     {
      //--- Посчитаем количество объектов в текущей директории
      counter++;
      while(::FileFindNext(search_handle,file_name))
         counter++;
     }
//--- Закрываем хэндл поиска
   ::FileFindClose(search_handle);
   return(counter);
  }
//+------------------------------------------------------------------+
//| Считает количество папок в текущей директории                    |
//+------------------------------------------------------------------+
int CFileNavigator::FoldersTotal(const string search_path,const int search_area)
  {
   int    counter       =0;              // счётчик элементов 
   string file_name     ="";             // имя файла
   long   search_handle =INVALID_HANDLE; // хэндл поиска
//--- Получаем первый файл в текущей директории
   search_handle=::FileFindFirst(search_path,file_name,search_area);
//--- Если не путо, то в цикле считаем кол-во объектов в текущей директории
   if(search_handle!=INVALID_HANDLE && file_name!="")
     {
      //--- Если это папка, увеличим счётчик
      if(IsFolder(file_name))
         counter++;
      //--- Пройдёмся далее по списку и посчитаем другие папки
      while(::FileFindNext(search_handle,file_name))
        {
         if(IsFolder(file_name))
            counter++;
        }
     }
//--- Закрываем хэндл поиска
   ::FileFindClose(search_handle);
   return(counter);
  }
//+------------------------------------------------------------------+
//| Возвращает локальный индекс предыдущего узла                     |
//| относительно переданных параметров                               |
//+------------------------------------------------------------------+
int CFileNavigator::PrevNodeItemIndex(const int root_index,const int node_level)
  {
   int prev_node_item_index=0;
//--- Если не в корневом каталоге
   if(node_level>1)
      prev_node_item_index=m_l_item_index[node_level-1];
   else
     {
      //--- Если не первый элемент списка
      if(root_index>0)
         prev_node_item_index=m_l_item_index[node_level-1];
     }
//--- Вернём локальный индекс предыдущего узла
   return(prev_node_item_index);
  }
//+------------------------------------------------------------------+
//| Добавляет пункт с указанными параметрами в массивы               |
//+------------------------------------------------------------------+
void CFileNavigator::AddItem(const int list_index,const string item_text,const int node_level,const int prev_node_item_index,
                             const int item_index,const int items_total,const int folders_total,const bool is_folder)
  {
//--- Резервный размер массива
   int reserve_size=100000;
//--- Увеличим размер массивов на один элемент
   int array_size =::ArraySize(m_g_list_index);
   int new_size   =array_size+1;
   ::ArrayResize(m_g_prev_node_list_index,new_size,reserve_size);
   ::ArrayResize(m_g_list_index,new_size,reserve_size);
   ::ArrayResize(m_g_item_text,new_size,reserve_size);
   ::ArrayResize(m_g_item_index,new_size,reserve_size);
   ::ArrayResize(m_g_node_level,new_size,reserve_size);
   ::ArrayResize(m_g_prev_node_item_index,new_size,reserve_size);
   ::ArrayResize(m_g_items_total,new_size,reserve_size);
   ::ArrayResize(m_g_folders_total,new_size,reserve_size);
   ::ArrayResize(m_g_is_folder,new_size,reserve_size);
//--- Сохраним значения переданных параметров
   m_g_prev_node_list_index[array_size] =(node_level==0)? -1 : m_l_prev_node_list_index[node_level-1];
   m_g_list_index[array_size]           =list_index;
   m_g_item_text[array_size]            =item_text;
   m_g_item_index[array_size]           =item_index;
   m_g_node_level[array_size]           =node_level;
   m_g_prev_node_item_index[array_size] =prev_node_item_index;
   m_g_items_total[array_size]          =items_total;
   m_g_folders_total[array_size]        =folders_total;
   m_g_is_folder[array_size]            =is_folder;
  }
//+------------------------------------------------------------------+
//| Переход на следующий узел                                        |
//+------------------------------------------------------------------+
void CFileNavigator::ToNextNode(const int root_index,int list_index,int &node_level,
                                int &item_index,long &handle,const string item_text,const int search_area)
  {
//--- Фильтр поиска (* - проверить все файлы/папки)
   string filter="*";
//--- Сформируем путь
   string search_path=m_l_path[node_level]+item_text+filter;
//--- Получим и сохраним данные
   m_l_item_total[node_level]           =ItemsTotal(search_path,search_area);
   m_l_folders_total[node_level]        =FoldersTotal(search_path,search_area);
   m_l_item_text[node_level]            =item_text;
   m_l_item_index[node_level]           =item_index;
   m_l_prev_node_list_index[node_level] =list_index;
//--- Получим индекс пункта предыдущего узла
   int prev_node_item_index=PrevNodeItemIndex(root_index,node_level);
//--- Добавим пункт с указанными данными в общие массивы
   AddItem(list_index,item_text,node_level,prev_node_item_index,
           item_index,m_l_item_total[node_level],m_l_folders_total[node_level],true);
//--- Увеличим счётчик узлов
   node_level++;
//--- Увеличим размер массивов на один элемент
   AuxiliaryArraysResize(node_level);
//--- Получим и сохраним данные
   m_l_path[node_level]          =m_l_path[node_level-1]+item_text;
   m_l_item_total[node_level]    =ItemsTotal(m_l_path[node_level]+filter,search_area);
   m_l_folders_total[node_level] =FoldersTotal(m_l_path[node_level]+item_text+filter,search_area);
//--- Обнулить счётчик локальных индексов
   item_index=0;
//--- Закрываем хэндл поиска
   ::FileFindClose(handle);
  }
//+------------------------------------------------------------------+
//| Удаление                                                         |
//+------------------------------------------------------------------+
void CFileNavigator::Delete(void)
  {
   CElement::Delete();
//--- Освобождение массивов элемента
   ::ArrayFree(m_g_prev_node_list_index);
   ::ArrayFree(m_g_list_index);
   ::ArrayFree(m_g_item_text);
   ::ArrayFree(m_g_item_index);
   ::ArrayFree(m_g_node_level);
   ::ArrayFree(m_g_prev_node_item_index);
   ::ArrayFree(m_g_items_total);
   ::ArrayFree(m_g_folders_total);
   ::ArrayFree(m_g_item_state);
//---
   ::ArrayFree(m_l_prev_node_list_index);
   ::ArrayFree(m_l_item_text);
   ::ArrayFree(m_l_path);
   ::ArrayFree(m_l_item_index);
   ::ArrayFree(m_l_item_total);
   ::ArrayFree(m_l_folders_total);
//--- Обнулить переменные
   m_current_path="";
  }
//+------------------------------------------------------------------+
//| Рисует элемент                                                   |
//+------------------------------------------------------------------+
void CFileNavigator::Draw(void)
  {
//--- Нарисовать фон
   CElement::DrawBackground();
//--- Нарисовать рамку
   CElement::DrawBorder();
//--- Нарисовать текст
   DrawText();
  }
//+------------------------------------------------------------------+
//| Рисует текст                                                     |
//+------------------------------------------------------------------+
void CFileNavigator::DrawText(void)
  {
//--- Координаты
   int x=5,y=m_y_size>>1;
//--- Свойства текста
   m_canvas.FontSet(CElement::Font(),-CElement::FontSize()*10,FW_NORMAL);
//--- Если путь ещё не установлен, показать строку по умолчанию
   if(m_current_full_path=="")
      m_current_full_path="Loading. Please wait...";
//--- Выведем путь в адресную строку файлового навигатора
   m_canvas.TextOut(x,y,m_current_full_path,::ColorToARGB(m_label_color),TA_LEFT|TA_VCENTER);
  }
//+------------------------------------------------------------------+
//| Изменить ширину по правому краю формы                            |
//+------------------------------------------------------------------+
void CFileNavigator::ChangeWidthByRightWindowSide(void)
  {
//--- Выйти, если включен режим привязки к правой части окна
   if(m_anchor_right_window_side)
      return;
//--- Рассчитать и установить новый размер фону элемента
   int x_size=m_main.X2()-CElementBase::X()-m_auto_xresize_right_offset;
//--- Установить новый размер
   CElementBase::XSize(x_size);
   m_canvas.XSize(x_size);
   m_canvas.Resize(x_size,m_y_size);
//--- Перерисовать элемент
   Draw();
  }
//+------------------------------------------------------------------+
