EA-Setka-2/Libs/MQL5Trace/View/TreeView.mqh
super.admin a4b861dd93 convert
2025-05-30 14:50:44 +02:00

286 lines
No EOL
11 KiB
MQL5

//+------------------------------------------------------------------+
//| TreeView |
//| 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 "View.mqh"
#include "ScrollView.mqh"
#include "..\Tree.mqh"
#define BTN_CLEAR 0
#define BTN_COLLAPS 1
#define BTN_RESET 2
#define BTN_EXPAND 3
#define BTN_OPEN 4
#define BTN_SHOW 5
#define BTN_LABEL 6
#define BTN_CHECK 7
#define BTN_SCROLL 8
#define BTN_DESCRIPT 9
#define BTN_BREAK 10
//------------------------------------------------------------------ class CTreeView
class CTreeView: public CView
{
//--- базовые функции
public:
CTreeView(); // конструктор
~CTreeView(); // деструктор
virtual void Create(long chart, string name, int wnd, color clr, color bgclr, color selclr, int x, int y, int dx, int dy, int corn=0, int fontsize=8, string font="Arial");
//--- функции обработки состояния
public:
CTreeCtrl *m_tree; // указатель на объект дерева для отображения
int m_sid; // последний выделенный объект (для подсветки)
virtual int OnClick(string name); // обработка события клика на объекте
//--- функции отображения
public:
int m_ndx, m_ndy; // размер отступов от кнопки для отрисовки
int m_bdx, m_bdy; // размер кнопки узлов
CScrollView m_scroll;
bool m_bDesc; // показывать описание рядом с узлом
virtual void Draw(); // обновить вид
virtual void DrawTree(CNode *first, int xpos, int &ypos, int &up, int &dn); // перерисовать
virtual void DrawNode(CNode *node, int x, int y); // отрисовать узел
virtual void DeleteView(CNode *root=NULL, bool delparent=true); // удалить все элементы отображения, начиная с заданного узла
};
//------------------------------------------------------------------ CTreeView
void CTreeView::CTreeView()
{
m_bdx=12; m_bdy=12; // размер кнопки узлов
m_ndx=m_bdx+17; m_ndy=14; // размер отступов от кнопки
m_sid=0; m_bDesc=false;
}
//------------------------------------------------------------------ ~CTreeView
void CTreeView::~CTreeView()
{
ObjectDelete(m_chart, m_name);
ObjectDelete(m_chart, m_name+".collaps");
ObjectDelete(m_chart, m_name+".expand");
ObjectDelete(m_chart, m_name+".clear");
ObjectDelete(m_chart, m_name+".reset");
ObjectDelete(m_chart, m_name+".desc");
DeleteView();
m_scroll.DeleteView();
}
//------------------------------------------------------------------ Create
void CTreeView::Create(long achart, string name, int wnd, color clr, color bgclr, color selclr, int x, int y, int dx, int dy, int corn=0, int fontsize=8, string font="Arial")
{
CView::Create(achart, name, wnd, clr, bgclr, selclr, x, y, dx, dy, corn, fontsize, font);
x=m_x+m_dx-20; dx=16;
y=m_y+2*m_bdy; dy=m_dy-3*m_bdy;
m_scroll.Create(m_chart, m_name+".scroll", m_wnd, m_selclr, m_bgclr, m_bgclr, x, y, dx, dy, m_corn, m_fontsize);
m_scroll.m_dir=SV_VDIR;
OnClick(m_name+string(m_sid)+".lbl");
}
//------------------------------------------------------------------ OnClick
int CTreeView::OnClick(string name) // имя объекта на который кликнули
{
int start=StringLen(m_name); int len=StringFind(name, ".")-start;
int id=(int)StringToInteger(StringSubstr(name, start, len));
if (StringFind(name, ".clear")>=0)
{
DeleteView(); m_tree.Clear(); Draw();
ObjectSetInteger(m_chart, name, OBJPROP_STATE, false);
return(BTN_CLEAR);
}
else if (StringFind(name, ".reset")>=0)
{
m_tree.Reset(); Draw();
ObjectSetInteger(m_chart, name, OBJPROP_STATE, false);
return(BTN_RESET);
}
else if (StringFind(name, ".collaps")>=0)
{
DeleteView(); m_tree.ExpandBy(TG_ALL, NULL, false); Draw();
ObjectSetInteger(m_chart, name, OBJPROP_STATE, false);
return(BTN_COLLAPS);
}
else if (StringFind(name, ".expand")>=0)
{
m_tree.ExpandBy(TG_ALL, NULL, true); Draw();
ObjectSetInteger(m_chart, name, OBJPROP_STATE, false);
return(BTN_EXPAND);
}
else if (StringFind(name, ".desc")>=0)
{
m_bDesc=!m_bDesc;
return(BTN_DESCRIPT);
}
else if (StringFind(name, ".break")>=0)
{
m_tree.m_bBreak=ObjectGetInteger(m_chart, name, OBJPROP_STATE);
return(BTN_BREAK);
}
else if (StringFind(name, ".btn")>=0) // если кнопка
{
m_tree.ExpandIt(id, !m_tree.IsExpand(id)); // сменили состояние
CNode *node=m_tree.FindNode(id); if (NIL(node)) return(0); // если ошибка взятия узла
DeleteView(node); // удалили все объекты от этого узла
Draw(); // отрисовали снова
return(BTN_SHOW);
}
else if (StringFind(name, ".lbl")>=0) // если клик на элементе дерева
{
m_tree.SelectBy(TG_ALL, NULL, false);// если нет предыдущего то гасим все
m_tree.CheckBy(TG_ALL, NULL, false);
if (m_sid>=0) // иначе только один
{
ObjectSetInteger(m_chart, m_name+string(m_sid)+".lbl", OBJPROP_COLOR, m_clr);
ObjectSetInteger(m_chart, m_name+string(m_sid)+".chk", OBJPROP_COLOR, m_clr);
if (m_tree.IsCheck(m_sid)) m_tree.CheckIt(m_sid, false);
if (m_tree.IsSelect(m_sid)) m_tree.SelectIt(m_sid, false);
}
// и выделяем один новый
m_sid=id; // запоминаем
ObjectSetInteger(m_chart, m_name+string(m_sid)+".lbl", OBJPROP_COLOR, m_selclr);
ObjectSetInteger(m_chart, m_name+string(m_sid)+".chk", OBJPROP_COLOR, m_selclr);
m_tree.CheckIt(m_sid, true);
m_tree.SelectIt(m_sid, true);
Draw(); // отрисовали снова
return(BTN_LABEL);
}
else if (StringFind(name, ".chk")>=0) // если клик на элементе выбора
{
m_tree.SelectBy(TG_ALL, NULL, false);// если нет предыдущего то гасим все
m_tree.CheckBy(TG_ALL, NULL, false);
if (m_sid>=0) if (m_tree.IsCheck(m_sid)) m_tree.CheckIt(m_sid, false); // сменили состояние
m_sid=id; // сменили выделение
m_tree.CheckIt(m_sid, true); // сменили состояние
Draw(); // отрисовали снова
return(BTN_CHECK);
}
else if (StringFind(name, ".scroll")>=0)
{
int s=m_scroll.OnClick(name); // передали дальше
if (s!=0) { m_y0=(int)-m_scroll.m_value*m_ndy; Draw(); } // отрисовали, если было обновление
return(BTN_SCROLL);
}
return(-1);
}
//------------------------------------------------------------------ Draw
void CTreeView::Draw()
{
if (!IsOpenView()) return; // если не создан просмотр, то выходим
SetRectLbl(m_chart, m_name+".rect", m_wnd, "", m_clr, m_bgclr, m_x, m_y, m_dx, m_dy, m_corn, m_fontsize, m_font, true);
int ax=int(m_x+m_dx-1.5*m_bdx); int adx=int(1.2*m_bdx); int i=-1;
i++; SetButton(m_chart, m_name+".collaps", 0, "-", m_bgclr, m_selclr, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", false);
i++; SetButton(m_chart, m_name+".expand", 0, "+", m_bgclr, m_selclr, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", false);
if (m_tree.m_mode==1)
{
i++; SetButton(m_chart, m_name+".clear", 0, "X", m_bgclr, m_selclr, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", false);
i++; SetButton(m_chart, m_name+".reset", 0, "0", m_bgclr, m_selclr, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", false);
i++; SetButton(m_chart, m_name+".desc", 0, "i", m_bgclr, clrDarkOliveGreen, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", m_bDesc);
i++; SetButton(m_chart, m_name+".break", 0, "D", m_bgclr, clrRed, ax-i*adx, int(m_y+0.5*m_bdy), m_bdx, m_bdy, 0, 7, "Tahoma", m_tree.m_bBreak);
}
int show=0, up=0, dn=0;
DrawTree(m_tree.m_root, 1, show, up, dn); // нарисовали дерево
if (up<=0 && dn<=0) m_scroll.DeleteView(); // убрали полосу прокрутки для перерисовки
else
{
m_scroll.m_max=up+dn; m_scroll.m_value=up;
m_scroll.m_x=m_x+m_dx-20; m_scroll.m_dx=16;
m_scroll.m_y=m_y+2*m_bdy; m_scroll.m_dy=m_dy-3*m_bdy+8;
m_scroll.Draw(); // отрисовали полосу прокрутки
}
}
//------------------------------------------------------------------ DrawTree
void CTreeView::DrawTree(CNode *root, int xpos, int &ypos, int &up, int &dn)
{
if (xpos==1) { root=m_tree.m_root; ypos=0; } // если начали с первого элемента, то берем корень и левое положение
if (root==NULL) { root=m_tree.m_root; xpos=1; } // если не указан первый узел, то берем корень и верхнее положение
if (NIL(root)) return; // правильность указателя
string name=m_name+string(root.m_id);
if (!IsOpenView()) return; // если не создан просмотр, то выходим
int x=m_x0+m_x+5+(xpos-1)*m_bdx;
int y=m_y0+m_y+5+ypos*m_ndy;
bool ishide=(y<=m_y || y>=m_y+m_dy-m_ndy);
if (root.m_break && ishide)
{
while (y<m_y) { m_y0+=m_ndy; y=m_y0+m_y+5+ypos*m_ndy; }// подвинули вниз
while (y>m_y+m_dy-m_ndy) { m_y0-=m_ndy; y=m_y0+m_y+5+ypos*m_ndy; }// подвинули вверх
up=0; dn=0;
DrawTree(m_tree.m_root, 1, ypos, up, dn); // отрисовали снова все дерево
}
if (!ishide) DrawNode(root, x, y); // если не уходит за область видимости
else
{
ObjectDelete(m_chart, name+".lbl"); ObjectDelete(m_chart, name+".btn");
ObjectDelete(m_chart, name+".chk"); ObjectDelete(m_chart, name+".dbg");
if (y<m_y) up++; else dn++;
}
if (!root.m_expand) return; // если не раскрыт, то пропускаем
for (int i=0; i<ArraySize(root.m_next); i++)
{
if (NIL(root.m_next[i])) continue;
ypos++; // увеличили положение
DrawTree(root.m_next[i], xpos+1, ypos, up, dn); // отрисовали следующую ветку
}
}
//------------------------------------------------------------------ DrawNode
void CTreeView::DrawNode(CNode *node, int x, int y)
{
if (NIL(node)) return;
string name=m_name+string(node.m_id);
string txt=node.m_text;
StringTrimLeft(node.m_desc); // подчистили строку слева
if (m_bDesc && node.m_desc!="") txt+=" | "+node.m_desc; //если надо выводить описание
// определяем цвет
color clr=node.m_select ? m_selclr : m_clr;
if (node.m_break) clr=clrRed;
// выводим текст для узла
SetLabel(m_chart, name+".lbl", m_wnd, txt, clr, x+m_ndx, y-1, m_corn, m_fontsize, m_font);
// отметка узла
string state;
if (!node.m_break)
{
state=node.m_check ? CharToString(110) : CharToString(112);
SetLabel(m_chart, name+".chk", m_wnd, state, clr, x+m_ndx-m_bdx, y, m_corn, m_fontsize, "Wingdings");
}
else ObjectDelete(m_chart, name+".chk");
// кнопку раскрытости узла
state=node.m_expand ? "-" : "+";
if (ArraySize(node.m_next)>0)
SetButton(m_chart, name+".btn", m_wnd, state, m_clr, m_bgclr, x, y, m_bdx, m_bdy, m_corn, m_fontsize, m_font, node.m_expand);
else ObjectDelete(m_chart, name+".btn");
// кнопка дебага (её имя принадлежит всему дереву, так как она одна)
if (node.m_break)
SetButton(m_chart, name+".dbg", m_wnd, "*", clr, clr, x+m_ndx-m_bdx-2, y, m_bdx, m_bdy, m_corn, m_fontsize, m_font, false);
else ObjectDelete(m_chart, name+".dbg");
}
//------------------------------------------------------------------ DeleteView
void CTreeView::DeleteView(CNode *root=NULL, bool delparent=true)
{
CView::DeleteView(); // метод базового
if (root==NULL) root=m_tree.m_root; if (NIL(root)) return;
if(delparent) // удаляем узел родителя
{
string name=m_name+string(root.m_id);
ObjectDelete(m_chart, name+".btn");
ObjectDelete(m_chart, name+".lbl");
ObjectDelete(m_chart, name+".chk");
}
for (int i=0; i<ArraySize(root.m_next); i++)
if (!NIL(root.m_next[i])) DeleteView(root.m_next[i], true);
}