505 lines
23 KiB
MQL5
505 lines
23 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Tree |
|
|
//| Copyright 2006-2011, www.FXmaster.de |
|
|
//| www.FXmaster.de |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2006-2011, www.FXmaster.de"
|
|
#property link "www.FXmaster.de"
|
|
#property version "1.00"
|
|
|
|
#include "Node.mqh"
|
|
|
|
//------------------------------------------------------------------ class CTreeBase
|
|
class CTreeBase
|
|
{
|
|
public:
|
|
CNode *m_root; // первый узел дерева
|
|
int m_maxid; // счетчик ID
|
|
|
|
//--- базовые функции
|
|
public:
|
|
CTreeBase(); // конструктор
|
|
~CTreeBase(); // деструктор
|
|
void Clear(CNode *root=NULL); // удаления всех узлов после указанного
|
|
CNode* FindNode(int id, CNode *root=NULL); // поиск узла по ID, начиная с заданного узла
|
|
CNode* FindNode(string txt, CNode *root=NULL); // поиск узла по txt, начиная с заданного узла
|
|
int GetID(string txt, CNode *root=NULL); // получение ID для указанного Text, поиск с заданного узла
|
|
int GetMaxID(CNode *root=NULL); // получение максимального ID в дереве
|
|
int AddNode(int id, string text, CNode *root=NULL); // добавление в список с поиском по ID узла, начиная с заданного узла
|
|
int AddNode(string txt, string text, CNode *root=NULL); // добавление в список с поиском по тексту узла, начиная с заданного узла
|
|
int AddNode(CNode *root, string text); // добавление под root
|
|
};
|
|
//------------------------------------------------------------------ CTreeBase
|
|
void CTreeBase::CTreeBase()
|
|
{
|
|
m_maxid=0; m_root=new CNode;
|
|
m_root.m_id=m_maxid; m_root.m_text="__base__";
|
|
}
|
|
//------------------------------------------------------------------ ~CTreeBase
|
|
void CTreeBase::~CTreeBase()
|
|
{
|
|
delete m_root; m_maxid=0; // сбросили счетчик
|
|
}
|
|
//------------------------------------------------------------------ Reset
|
|
void CTreeBase::Clear(CNode *root=NULL)
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
root.m_uses=0; root.m_tick=0; // обнулили в текущем узле
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // обнуляем всю ветку
|
|
if (!NIL(root.m_next[i])) // правильность указателя
|
|
delete root.m_next[i];
|
|
ArrayResize(root.m_next, 0);
|
|
m_maxid=GetMaxID(); // сбросили счетчик
|
|
}
|
|
//------------------------------------------------------------------ FindNode
|
|
CNode* CTreeBase::FindNode(int id, CNode *root=NULL)
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return(NULL); // правильность указателя
|
|
if (root.m_id==id) return(root); // если нашли, то присваиваем и выходим
|
|
CNode *node; int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
node=FindNode(id, root.m_next[i]); if (!NIL(node)) return(node); // проверили на узле
|
|
}
|
|
return(NULL);
|
|
}
|
|
//------------------------------------------------------------------ FindNode
|
|
CNode* CTreeBase::FindNode(string txt, CNode *root=NULL)
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return(NULL); // правильность указателя
|
|
if (root.m_text==txt) return(root); // если нашли, то присваиваем и выходим
|
|
CNode *node; int n;
|
|
n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
node=FindNode(txt, root.m_next[i]); if (!NIL(node)) return(node); // проверили на узле
|
|
}
|
|
return(NULL);
|
|
}
|
|
//------------------------------------------------------------------ GetID
|
|
int CTreeBase::GetID(string txt, CNode *root=NULL)
|
|
{
|
|
CNode *node=FindNode(txt, root); if (NIL(node)) return(-1);
|
|
return(node.m_id);
|
|
}
|
|
//------------------------------------------------------------------ GetMaxID
|
|
int CTreeBase::GetMaxID(CNode *root=NULL) // получение максимального ID
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return(-1); // правильность указателя
|
|
int max=root.m_id;
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
max=MathMax(max, GetMaxID(root.m_next[i]));
|
|
}
|
|
return(max);
|
|
}
|
|
//------------------------------------------------------------------ AddNode
|
|
int CTreeBase::AddNode(int id, string text, CNode *root=NULL)
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(-1);
|
|
int size=ArraySize(node.m_next); bool b=false; int i;
|
|
for (i=0; i<size; i++) // ищем узел с таким же текстом
|
|
{
|
|
if (NIL(node.m_next[i])) continue; // правильность указателя
|
|
if (node.m_next[i].m_text==text) { b=true; break; }
|
|
}
|
|
if (b) return(node.m_next[i].m_id); // если узел найден
|
|
// иначе добавляем
|
|
ArrayResize(node.m_next, size+1); node.m_next[size]=new CNode; m_maxid++;
|
|
node.m_next[size].m_id=m_maxid; node.m_next[size].m_text=text; node.m_next[size].m_prev=node;
|
|
return(node.m_next[size].m_id);
|
|
}
|
|
//------------------------------------------------------------------ AddNode
|
|
int CTreeBase::AddNode(string txt, string text, CNode *root=NULL)
|
|
{
|
|
CNode *node=FindNode(txt, root); if (NIL(node)) return(-1);
|
|
int size=ArraySize(node.m_next); bool b=false; int i;
|
|
for (i=0; i<size; i++) // ищем узел с таким же текстом
|
|
{
|
|
if (NIL(node.m_next[i])) continue; // правильность указателя
|
|
if (node.m_next[i].m_text==text) { b=true; break; }
|
|
}
|
|
if (b) return(node.m_next[i].m_id); // если узел найден
|
|
// иначе добавляем
|
|
ArrayResize(node.m_next, size+1); node.m_next[size]=new CNode; m_maxid++;
|
|
node.m_next[size].m_id=m_maxid; node.m_next[size].m_text=text; node.m_next[size].m_prev=node;
|
|
return(node.m_next[size].m_id);
|
|
}
|
|
//------------------------------------------------------------------ AddNode
|
|
int CTreeBase::AddNode(CNode *node, string text)
|
|
{
|
|
if (node==NULL) node=m_root; if (NIL(node)) return(-1);
|
|
int size=ArraySize(node.m_next); bool b=false; int i;
|
|
for (i=0; i<size; i++) // ищем узел с таким же текстом
|
|
{
|
|
if (NIL(node.m_next[i])) continue; // правильность указателя
|
|
if (node.m_next[i].m_text==text) { b=true; break; }
|
|
}
|
|
if (b) return(node.m_next[i].m_id); // если узел найден
|
|
// иначе добавляем
|
|
ArrayResize(node.m_next, size+1);
|
|
node.m_next[size]=new CNode; m_maxid++;
|
|
node.m_next[size].m_id=m_maxid; node.m_next[size].m_prev=node;
|
|
node.m_next[size].m_text=text;
|
|
return(node.m_next[size].m_id);
|
|
}
|
|
|
|
|
|
#define TG_ALL 0x00000001
|
|
#define TG_ID 0x00000002
|
|
#define TG_TEXT 0x00000004
|
|
#define TG_PATH 0x00000008
|
|
#define TG_FILE 0x00000010
|
|
#define TG_CLASS 0x00000020
|
|
#define TG_FUNC 0x00000040
|
|
#define TG_DESC 0x00000080
|
|
#define TG_EDIT 0x00000100
|
|
#define TG_BRKUSE 0x00000200
|
|
#define TG_UP 0x00000400
|
|
//------------------------------------------------------------------ class CTreeCtrl
|
|
class CTreeCtrl : public CTreeBase
|
|
{
|
|
public:
|
|
int m_mode; // тип дерева (для вида отображения TraceView)
|
|
|
|
//--- базовые функции
|
|
public:
|
|
CTreeCtrl() { m_bBreak=true; m_mode=0; m_root.m_path=""; m_root.m_file="__base__"; m_root.m_line=0; m_root.m_func="__base__"; m_root.m_class="__base__"; } // конструктор
|
|
~CTreeCtrl() { delete m_root; m_maxid=0; } // деструктор
|
|
void Reset(CNode *root=NULL); // сброс состояния всех узлов
|
|
void SetDataBy(int mode, int id, string text, CNode *root=NULL); // изменение свойства для указанного ID, поиск с заданного узла
|
|
void SetDataBy(int mode, int id, int data, CNode *root=NULL); // изменение свойства для указанного ID, поиск с заданного узла
|
|
string GetDataBy(int mode, int id, CNode *root=NULL); // получение свойства для указанного ID, поиск с заданного узла
|
|
|
|
//--- обработка состояния
|
|
public:
|
|
bool IsExpand(int id, CNode *root=NULL); // получение свойства m_expand для указанного ID, поиск с заданного узла
|
|
bool ExpandIt(int id, bool state, CNode *root=NULL); // меняем состояние m_expand, поиск с заданного узла
|
|
void ExpandBy(int mode, CNode *node, bool state, CNode *root=NULL); // раксрываем узлы только указанного
|
|
|
|
bool IsCheck(int id, CNode *root=NULL); // получение свойства m_check для указанного ID, поиск с заданного узла
|
|
bool CheckIt(int id, bool state, CNode *root=NULL); // меняем состояние m_check на требуемую, начиная с заданного узла
|
|
void CheckBy(int mode, CNode *node, bool state, CNode *root=NULL); // отмечаем все дерево
|
|
|
|
bool IsSelect(int id, CNode *root=NULL); // получение свойства m_select для указанного ID, поиск с заданного узла
|
|
bool SelectIt(int id, bool state, CNode *root=NULL); // меняем состояние m_select на требуемую, начиная с заданного узла
|
|
void SelectBy(int mode, CNode *node, bool state, CNode *root=NULL); // подсвечиваем все дерево
|
|
|
|
bool IsBreak(int id, CNode *root=NULL); // получение свойства m_break для указанного ID, поиск с заданного узла
|
|
bool BreakIt(int id, bool state, CNode *root=NULL); // меняем состояние m_break, поиск с заданного узла
|
|
void BreakBy(int mode, CNode *node, bool state, CNode *root=NULL); // задаем только для указанного
|
|
bool m_bBreak; // флаг разрешения режима дебага
|
|
|
|
//--- операции с нодами
|
|
public:
|
|
void SortBy(int mode, bool ascend, CNode *root=NULL); // сортировка по свойству
|
|
void GroupBy(int mode, CTreeCtrl* atree, CNode* node=NULL); // группировка по свойству
|
|
};
|
|
//------------------------------------------------------------------ Reset
|
|
void CTreeCtrl::Reset(CNode *root=NULL)
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
root.m_uses=0; root.m_tick=0; // обнулили в текущем узле
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // обнуляем всю ветку
|
|
if (!NIL(root.m_next[i])) // правильность указателя
|
|
Reset(root.m_next[i]);
|
|
}
|
|
//------------------------------------------------------------------ SetDataBy
|
|
void CTreeCtrl::SetDataBy(int mode, int id, string text, CNode *root=NULL)
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return;
|
|
if (bool(mode&TG_TEXT)) node.m_text=text;
|
|
if (bool(mode&TG_PATH)) node.m_path=text;
|
|
if (bool(mode&TG_FILE)) node.m_file=text;
|
|
if (bool(mode&TG_CLASS)) node.m_class=text;
|
|
if (bool(mode&TG_FUNC)) node.m_func=text;
|
|
if (bool(mode&TG_DESC)) node.m_desc=text;
|
|
}
|
|
//------------------------------------------------------------------ SetDataBy
|
|
void CTreeCtrl::SetDataBy(int mode, int id, int data, CNode *root=NULL)
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return;
|
|
if (bool(mode&TG_ID)) node.m_id=data;
|
|
if (bool(mode&TG_EDIT)) node.m_edit=bool(data);
|
|
if (bool(mode&TG_BRKUSE)) node.m_brkuse=data;
|
|
}
|
|
//------------------------------------------------------------------ GetDataBy
|
|
string CTreeCtrl::GetDataBy(int mode, int id, CNode *root=NULL) // получение текста для указанного ID, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return("");
|
|
switch(mode)
|
|
{
|
|
case TG_ID: return(string(node.m_id));
|
|
case TG_TEXT: return(node.m_text);
|
|
case TG_PATH: return(node.m_path);
|
|
case TG_FILE: return(node.m_file);
|
|
case TG_CLASS: return(node.m_class);
|
|
case TG_FUNC: return(node.m_func);
|
|
case TG_DESC: return(node.m_desc);
|
|
case TG_EDIT: return(string(node.m_edit));
|
|
case TG_BRKUSE: return(string(node.m_brkuse));
|
|
}
|
|
return("");
|
|
}
|
|
//------------------------------------------------------------------ IsExpand
|
|
bool CTreeCtrl::IsExpand(int id, CNode *root=NULL) // получение свойства m_expand для указанного ID, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
return(node.m_expand);
|
|
}
|
|
//------------------------------------------------------------------ ExpandIt
|
|
bool CTreeCtrl::ExpandIt(int id, bool state, CNode *root=NULL) // меняем состояние m_expand, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
node.m_expand=state; return(true); // если нашли, то меняем и выходим
|
|
}
|
|
//------------------------------------------------------------------ ExpandBy
|
|
void CTreeCtrl::ExpandBy(int mode, CNode *node, bool state, CNode *root=NULL) // раскрываем все дерево
|
|
{
|
|
if (mode!=TG_ALL && mode!=TG_UP && mode!=(TG_ALL|TG_UP))
|
|
if (NIL(node)) { Print(__FUNCTION__+" node==0"); return; } // правильность указателя
|
|
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
bool b=true;
|
|
if (bool(mode&TG_ID)) b=b&&(root.m_id==node.m_id);
|
|
if (bool(mode&TG_TEXT)) b=b&&(root.m_text==node.m_text);
|
|
if (bool(mode&TG_PATH)) b=b&&(root.m_path==node.m_path);
|
|
if (bool(mode&TG_FILE)) b=b&&(root.m_file==node.m_file);
|
|
if (bool(mode&TG_CLASS)) b=b&&(root.m_class==node.m_class);
|
|
if (bool(mode&TG_FUNC)) b=b&&(root.m_func==node.m_func);
|
|
if (bool(mode&TG_DESC)) b=b&&(root.m_desc==node.m_desc);
|
|
if (bool(mode&TG_EDIT)) b=b&&(root.m_edit==node.m_edit);
|
|
if (bool(mode&TG_BRKUSE)) b=b&&(root.m_brkuse==node.m_brkuse);
|
|
|
|
if (b) root.m_expand=state; // раскрываем
|
|
|
|
if (!bool(mode&TG_UP))
|
|
{
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
ExpandBy(mode, node, state, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|
|
else if (!NIL(root.m_prev)) // правильность указателя
|
|
ExpandBy(TG_UP, node, state, root.m_prev); // проверили на узле
|
|
}
|
|
|
|
//------------------------------------------------------------------ IsCheck
|
|
bool CTreeCtrl::IsCheck(int id, CNode *root=NULL) // получение свойства m_check для указанного ID, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
return(node.m_check);
|
|
}
|
|
//------------------------------------------------------------------ CheckIt
|
|
bool CTreeCtrl::CheckIt(int id, bool state, CNode *root=NULL) // меняем состояние m_check на требуемую, начиная с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
node.m_check=state; return(true); // если нашли, то меняем и выходим
|
|
}
|
|
//------------------------------------------------------------------ CheckBy
|
|
void CTreeCtrl::CheckBy(int mode, CNode *node, bool state, CNode *root=NULL) // отмечаем все дерево
|
|
{
|
|
if (mode!=TG_ALL) if (NIL(node)) { Print(__FUNCTION__+" node==0"); return; } // правильность указателя
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
bool b=true;
|
|
if (bool(mode&TG_ID)) b=b&&(root.m_id==node.m_id);
|
|
if (bool(mode&TG_TEXT)) b=b&&(root.m_text==node.m_text);
|
|
if (bool(mode&TG_PATH)) b=b&&(root.m_path==node.m_path);
|
|
if (bool(mode&TG_FILE)) b=b&&(root.m_file==node.m_file);
|
|
if (bool(mode&TG_CLASS)) b=b&&(root.m_class==node.m_class);
|
|
if (bool(mode&TG_FUNC)) b=b&&(root.m_func==node.m_func || node.m_func=="");
|
|
if (bool(mode&TG_DESC)) b=b&&(root.m_desc==node.m_desc);
|
|
if (bool(mode&TG_EDIT)) b=b&&(root.m_edit==node.m_edit);
|
|
if (bool(mode&TG_BRKUSE)) b=b&&(root.m_brkuse==node.m_brkuse);
|
|
|
|
if (b) root.m_check=state; // отмечаем
|
|
|
|
if (!bool(mode&TG_UP))
|
|
{
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
CheckBy(mode, node, state, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|
|
else if (!NIL(root.m_prev)) // правильность указателя
|
|
CheckBy(TG_UP, node, state, root.m_prev); // проверили на узле
|
|
}
|
|
|
|
//------------------------------------------------------------------ IsSelect
|
|
bool CTreeCtrl::IsSelect(int id, CNode *root=NULL) // получение свойства m_select для указанного ID, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
return(node.m_select);
|
|
}
|
|
//------------------------------------------------------------------ SelectIt
|
|
bool CTreeCtrl::SelectIt(int id, bool state, CNode *root=NULL) // меняем состояние m_select на требуемую, начиная с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
node.m_select=state; return(true); // если нашли, то меняем и выходим
|
|
}
|
|
//------------------------------------------------------------------ SelectBy
|
|
void CTreeCtrl::SelectBy(int mode, CNode *node, bool state, CNode *root=NULL) // подсвечиваем все дерево
|
|
{
|
|
if (mode!=TG_ALL) if (NIL(node)) { Print(__FUNCTION__+" node==0"); return; } // правильность указателя
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) { Print(__FUNCTION__+" root==0"); return; } // правильность указателя
|
|
bool b=true;
|
|
if (bool(mode&TG_ID)) b=b&&(root.m_id==node.m_id);
|
|
if (bool(mode&TG_TEXT)) b=b&&(root.m_text==node.m_text);
|
|
if (bool(mode&TG_PATH)) b=b&&(root.m_path==node.m_path);
|
|
if (bool(mode&TG_FILE)) b=b&&(root.m_file==node.m_file);
|
|
if (bool(mode&TG_CLASS)) b=b&&(root.m_class==node.m_class);
|
|
if (bool(mode&TG_FUNC)) b=b&&(root.m_func==node.m_func || node.m_func=="");
|
|
if (bool(mode&TG_DESC)) b=b&&(root.m_desc==node.m_desc);
|
|
if (bool(mode&TG_EDIT)) b=b&&(root.m_edit==node.m_edit);
|
|
if (bool(mode&TG_BRKUSE)) b=b&&(root.m_brkuse==node.m_brkuse);
|
|
|
|
if (b) root.m_select=state; // подсвечиваем
|
|
|
|
if (!bool(mode&TG_UP))
|
|
{
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
SelectBy(mode, node, state, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|
|
else if (!NIL(root.m_prev)) // правильность указателя
|
|
SelectBy(TG_UP, node, state, root.m_prev); // проверили на узле
|
|
}
|
|
//------------------------------------------------------------------ IsBreak
|
|
bool CTreeCtrl::IsBreak(int id, CNode *root=NULL) // получение свойства m_break для указанного ID, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
return(node.m_break);
|
|
}
|
|
//------------------------------------------------------------------ BreakIt
|
|
bool CTreeCtrl::BreakIt(int id, bool state, CNode *root=NULL) // меняем состояние m_break, поиск с заданного узла
|
|
{
|
|
CNode *node=FindNode(id, root); if (NIL(node)) return(false);
|
|
node.m_break=state; return(true); // если нашли, то меняем и выходим
|
|
}
|
|
//------------------------------------------------------------------ BreakBy
|
|
void CTreeCtrl::BreakBy(int mode, CNode *node, bool state, CNode *root=NULL) // задаем только для указанного
|
|
{
|
|
if (mode!=TG_ALL) if (NIL(node)) { Print(__FUNCTION__+" node==0"); return; } // правильность указателя
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) { Print(__FUNCTION__+" root==0"); return; } // правильность указателя
|
|
bool b=true;
|
|
if (bool(mode&TG_ID)) b=b&&(root.m_id==node.m_id);
|
|
if (bool(mode&TG_TEXT)) b=b&&(root.m_text==node.m_text);
|
|
if (bool(mode&TG_PATH)) b=b&&(root.m_path==node.m_path);
|
|
if (bool(mode&TG_FILE)) b=b&&(root.m_file==node.m_file);
|
|
if (bool(mode&TG_CLASS)) b=b&&(root.m_class==node.m_class);
|
|
if (bool(mode&TG_FUNC)) b=b&&(root.m_func==node.m_func || node.m_func=="");
|
|
if (bool(mode&TG_DESC)) b=b&&(root.m_desc==node.m_desc);
|
|
if (bool(mode&TG_EDIT)) b=b&&(root.m_edit==node.m_edit);
|
|
if (bool(mode&TG_BRKUSE)) b=b&&(root.m_brkuse==node.m_brkuse);
|
|
|
|
if (b) root.m_break=state; // подсвечиваем
|
|
|
|
if (!bool(mode&TG_UP))
|
|
{
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
BreakBy(mode, node, state, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|
|
else if (!NIL(root.m_prev)) // правильность указателя
|
|
BreakBy(TG_UP, node, state, root.m_prev); // проверили на узле
|
|
}
|
|
|
|
//------------------------------------------------------------------ SortBy
|
|
void CTreeCtrl::SortBy(int mode, bool ascend, CNode *root=NULL) // сортировка по свойству
|
|
{
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
|
|
int n=ArraySize(root.m_next);
|
|
bool b=true; CNode *node;
|
|
while (b && n>1)
|
|
{
|
|
b=false;string st1="", st2="";
|
|
for (int i=1; i<n; i++) // сравниваем и упорядочиваем
|
|
{
|
|
// требуемая группа сортировки
|
|
st1=root.m_next[i-1].m_text; st2=root.m_next[i].m_text;
|
|
if (mode==TG_ID) { st1=string(root.m_next[i-1].m_id); st2=string(root.m_next[i].m_id); }
|
|
if (mode==TG_PATH) { st1=root.m_next[i-1].m_path; st2=root.m_next[i].m_path; }
|
|
if (mode==TG_FILE) { st1=root.m_next[i-1].m_file; st2=root.m_next[i].m_file; }
|
|
if (mode==TG_CLASS) { st1=root.m_next[i-1].m_class; st2=root.m_next[i].m_class; }
|
|
if (mode==TG_FUNC) { st1=root.m_next[i-1].m_func; st2=root.m_next[i].m_func; }
|
|
if (mode==TG_DESC) { st1=root.m_next[i-1].m_desc; st2=root.m_next[i].m_desc; }
|
|
if (mode==TG_EDIT) { st1=string(root.m_next[i-1].m_edit); st2=string(root.m_next[i].m_edit); }
|
|
if (mode==TG_BRKUSE) { st1=string(root.m_next[i-1].m_brkuse); st2=string(root.m_next[i].m_brkuse); }
|
|
StringToLower(st1); StringToLower(st2);
|
|
|
|
if ((ascend && st1>=st2) || (!ascend && st1<st2))
|
|
{ b=true; node=root.m_next[i-1]; root.m_next[i-1]=root.m_next[i]; root.m_next[i]=node; }
|
|
}
|
|
}
|
|
for (int i=0; i<n; i++) // проверяем массив глубже
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
SortBy(mode, ascend, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|
|
//------------------------------------------------------------------ GroupBy
|
|
void CTreeCtrl::GroupBy(int mode, CTreeCtrl* atree, CNode* root=NULL)
|
|
{
|
|
if (NIL(atree) || atree==NULL) return; // правильность указателя
|
|
if (root==NULL) root=m_root; // если только начали, то задаем первый
|
|
if (NIL(root)) return; // правильность указателя
|
|
if (root!=m_root)
|
|
{
|
|
int id; string st=" ";
|
|
if (mode==TG_PATH) st=root.m_path; // группируем по пути файла
|
|
if (mode==TG_FILE) st=root.m_file; // группируем по имени файла
|
|
if (mode==TG_CLASS) st=root.m_class; // группируем по имени класса
|
|
id=atree.AddNode(0, st);
|
|
atree.SetDataBy(TG_PATH, id, root.m_path);
|
|
atree.SetDataBy(TG_FILE, id, root.m_file);
|
|
atree.SetDataBy(TG_CLASS, id, root.m_class);
|
|
|
|
id=atree.AddNode(st, root.m_func);
|
|
CNode *node=atree.FindNode(id);
|
|
node.m_uses=root.m_uses; // число обращений к узлу
|
|
node.m_tick=root.m_tick; // время проведенное в узле
|
|
node.m_tick0=root.m_tick0; // время входа в узел
|
|
node.m_last=root.m_last; // время входа в узел
|
|
node.m_path=root.m_path; // путь файла
|
|
node.m_file=root.m_file; // имя файла
|
|
node.m_line=root.m_line; // номер линии в файле
|
|
node.m_class=root.m_class; // имя класса
|
|
node.m_func=root.m_func; // имя функции
|
|
node.m_desc=root.m_desc; // доп.инфо
|
|
node.m_edit=root.m_edit; // редактируемое поле
|
|
node.m_brkuse=root.m_brkuse; // редактируемое поле
|
|
}
|
|
int n=ArraySize(root.m_next);
|
|
for (int i=0; i<n; i++) // иначе проверяем массив
|
|
{
|
|
if (NIL(root.m_next[i])) continue; // правильность указателя
|
|
GroupBy(mode, atree, root.m_next[i]); // проверили на узле
|
|
}
|
|
}
|