Add gitignore
@@ -0,0 +1,62 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| A_LotSizeCal.mqh |
|
||||
//| Copyright 2021, Nkondog Anselme Venceslas |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2021, Nkondog Anselme Venceslas"
|
||||
#property link "https://www.mql5.com"
|
||||
|
||||
//Lot Size Calculator
|
||||
void LotSizeCalculate(double SL=0)
|
||||
{
|
||||
//If the position size is dynamic
|
||||
if(RiskDefaultSize==RISK_DEFAULT_AUTO)
|
||||
{
|
||||
//If the stop loss is not zero then calculate the lot size
|
||||
if(SL!=0)
|
||||
{
|
||||
double RiskBaseAmount=0;
|
||||
//TickValue is the value of the individual price increment for 1 lot of the instrument, expressed in the account currenty
|
||||
TickValue=SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE);
|
||||
//Define the base for the risk calculation depending on the parameter chosen
|
||||
if(RiskBase==RISK_BASE_BALANCE)
|
||||
RiskBaseAmount=AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(RiskBase==RISK_BASE_EQUITY)
|
||||
RiskBaseAmount=AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
if(RiskBase==RISK_BASE_FREEMARGIN)
|
||||
RiskBaseAmount=AccountInfoDouble(ACCOUNT_FREEMARGIN);
|
||||
//Calculate the Position Size
|
||||
Print("Multiplier ", lotMultiplier, "Before lot multiplier ", (RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue));
|
||||
Print("RiskBaseAmount ", RiskBaseAmount, " MaxRiskPerTrade ", MaxRiskPerTrade, "Stop loss ", SL, " TickValue ", TickValue);
|
||||
|
||||
LotSize=((RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue));
|
||||
|
||||
Print("After lot multiplier ", LotSize, " Lot multiplier ", lotMultiplier);
|
||||
if(ActiveMartingale)
|
||||
{
|
||||
LotSize = LotSize * lotMultiplier;
|
||||
}
|
||||
}
|
||||
//If the stop loss is zero then the lot size is the default one
|
||||
if(SL==0)
|
||||
{
|
||||
LotSize=DefaultLotSize;
|
||||
}
|
||||
}
|
||||
//Normalize the Lot Size to satisfy the allowed lot increment and minimum and maximum position size
|
||||
LotSize=MathFloor(LotSize/SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP))*SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP);
|
||||
|
||||
//Limit the lot size in case it is greater than the maximum allowed by the user
|
||||
if(LotSize>MaxLotSize)
|
||||
LotSize=MaxLotSize;
|
||||
//Limit the lot size in case it is greater than the maximum allowed by the broker
|
||||
if(LotSize>SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX))
|
||||
LotSize=SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX);
|
||||
Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX));
|
||||
//If the lot size is too small then set it to 0 and don't trade
|
||||
if(LotSize < SymbolInfoDouble(Symb,SYMBOL_VOLUME_MIN))
|
||||
{
|
||||
LotSize=0;
|
||||
Print("Lot size too small");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| A_Parameters.mqh |
|
||||
//| Copyright 2021, Nkondog Anselme Venceslas |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2021, Nkondog Anselme Venceslas"
|
||||
#property link "https://www.mql5.com"
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//-ENUMERATIVE VARIABLES-//
|
||||
//Enumerative variables are useful to associate numerical values to easy to remember strings
|
||||
//It is similar to constants but also helps if the variable is set from the input page of the EA
|
||||
//The text after the // is what you see in the input paramenters when the EA loads
|
||||
//It is good practice to place all the enumberative at the start
|
||||
|
||||
//Enumerative for the entry signal value
|
||||
enum ENUM_SIGNAL_ENTRY
|
||||
{
|
||||
SIGNAL_ENTRY_NEUTRAL=0, //SIGNAL ENTRY NEUTRAL
|
||||
SIGNAL_ENTRY_BUY=1, //SIGNAL ENTRY BUY
|
||||
SIGNAL_ENTRY_SELL=-1, //SIGNAL ENTRY SELL
|
||||
};
|
||||
|
||||
//Enumerative for the exit signal value
|
||||
enum ENUM_SIGNAL_EXIT
|
||||
{
|
||||
SIGNAL_EXIT_NEUTRAL=0, //SIGNAL EXIT NEUTRAL
|
||||
SIGNAL_EXIT_BUY=1, //SIGNAL EXIT BUY
|
||||
SIGNAL_EXIT_SELL=-1, //SIGNAL EXIT SELL
|
||||
SIGNAL_EXIT_ALL=2, //SIGNAL EXIT ALL
|
||||
};
|
||||
|
||||
//Enumerative for the allowed trading direction
|
||||
enum ENUM_TRADING_ALLOW_DIRECTION
|
||||
{
|
||||
TRADING_ALLOW_BOTH=0, //ALLOW BOTH BUY AND SELL
|
||||
TRADING_ALLOW_BUY=1, //ALLOW BUY ONLY
|
||||
TRADING_ALLOW_SELL=-1, //ALLOW SELL ONLY
|
||||
};
|
||||
|
||||
//Enumerative for the base used for risk calculation
|
||||
enum ENUM_RISK_BASE
|
||||
{
|
||||
RISK_BASE_EQUITY=1, //EQUITY
|
||||
RISK_BASE_BALANCE=2, //BALANCE
|
||||
RISK_BASE_FREEMARGIN=3, //FREE MARGIN
|
||||
};
|
||||
|
||||
//Enumerative for the default risk size
|
||||
enum ENUM_RISK_DEFAULT_SIZE
|
||||
{
|
||||
RISK_DEFAULT_FIXED=1, //FIXED SIZE
|
||||
RISK_DEFAULT_AUTO=2, //AUTOMATIC SIZE BASED ON RISK
|
||||
};
|
||||
|
||||
//Enumerative for the Stop Loss mode
|
||||
enum ENUM_MODE_SL
|
||||
{
|
||||
SL_FIXED=0, //FIXED STOP LOSS
|
||||
SL_AUTO=1, //AUTOMATIC STOP LOSS
|
||||
};
|
||||
|
||||
//Enumerative for the Take Profit Mode
|
||||
enum ENUM_MODE_TP
|
||||
{
|
||||
TP_FIXED=0, //FIXED TAKE PROFIT
|
||||
TP_AUTO=1, //AUTOMATIC TAKE PROFIT
|
||||
};
|
||||
|
||||
//Enumerative for the stop loss calculation
|
||||
enum ENUM_MODE_SL_BY
|
||||
{
|
||||
SL_BY_POINTS=0, //STOP LOSS PASSED IN POINTS
|
||||
SL_BY_PRICE=1, //STOP LOSS PASSED BY PRICE
|
||||
};
|
||||
|
||||
//Enumerative for candle type
|
||||
enum ENUM_CANDLE_TYPE
|
||||
{
|
||||
NEUTRAL_CANDLE=0,
|
||||
BEARISH_CANDLE=1,
|
||||
BULLISH_CANDLE=2,
|
||||
};
|
||||
|
||||
//Enumerative for price momentum
|
||||
enum ENUM_PRICE_MOMENTUM
|
||||
{
|
||||
UP=2,
|
||||
DOWN=1,
|
||||
NEUTRAL=0,
|
||||
};
|
||||
|
||||
struct LastTransaction
|
||||
{
|
||||
string time;
|
||||
int type;
|
||||
double profit;
|
||||
} lt;
|
||||
|
||||
//-INPUT PARAMETERS-//
|
||||
//The input parameters are the ones that can be set by the user when launching the EA
|
||||
//If you place a comment following the input variable this will be shown as description of the field
|
||||
|
||||
//This is where you should include the input parameters for your entry and exit signals
|
||||
input string Comment_strategy="=========="; //Entry And Exit Settings
|
||||
//Add in this section the parameters for the indicators used in your entry and exit
|
||||
|
||||
//General input parameters
|
||||
input string Comment_0="=========="; //Risk Management Settings
|
||||
input ENUM_RISK_DEFAULT_SIZE RiskDefaultSize=RISK_DEFAULT_AUTO; //Position Size Mode
|
||||
input double DefaultLotSize=1; //Position Size (if fixed or if no stop loss defined)
|
||||
input ENUM_RISK_BASE RiskBase=RISK_BASE_BALANCE; //Risk Base
|
||||
input double MaxRiskPerTrade=0.5; //Percentage To Risk Each Trade
|
||||
input double MinLotSize=0.01; //Minimum Position Size Allowed
|
||||
input double MaxLotSize=100; //Maximum Position Size Allowed
|
||||
|
||||
input string Comment_1="=========="; //Trading Hours Settings
|
||||
input bool UseTradingHours=false; //Limit Trading Hours
|
||||
input string TradingHourStart="01"; //Trading Start Hour (Broker Server Hour)
|
||||
input string TradingHourEnd="23"; //Trading End Hour (Broker Server Hour)
|
||||
input string TradingStartMin="30"; //Trading Start minute (Broker Server Hour)
|
||||
input string TradingEndMin="00"; //Trading End minute
|
||||
|
||||
input string Comment_2="=========="; //Stop Loss And Take Profit Settings
|
||||
input ENUM_MODE_SL StopLossMode=SL_AUTO; //Stop Loss Mode
|
||||
input int DefaultStopLoss=0; //Default Stop Loss In Points (0=No Stop Loss)
|
||||
input int MinStopLoss=0; //Minimum Allowed Stop Loss In Points
|
||||
input int MaxStopLoss=5000; //Maximum Allowed Stop Loss In Points
|
||||
input bool AtrStopLoss=false; //Set Stop loss based on ATR
|
||||
input int atr_sl_factor=3; //Multiplicator for ATR stop loss
|
||||
input ENUM_MODE_TP TakeProfitMode=TP_AUTO; //Take Profit Mode
|
||||
input int DefaultTakeProfit=0; //Default Take Profit In Points (0=No Take Profit)
|
||||
input int MinTakeProfit=0; //Minimum Allowed Take Profit In Points
|
||||
input int MaxTakeProfit=5000; //Maximum Allowed Take Profit In Points
|
||||
input double TakeProfitPercent=1.0; //Take Profit percent on risk base
|
||||
input double Breakevent=1.0; //Minimum Profit to breakeven
|
||||
input bool ProfitRun=true;
|
||||
input bool ActiveMartingale=false;
|
||||
|
||||
input string Comment_3="=========="; //Trailing Stop Settings
|
||||
input bool UseTrailingStop=false; //Use Trailing Stop
|
||||
|
||||
input string Comment_4="=========="; //Additional Settings
|
||||
input int MagicNumber=0; //Magic Number For The Orders Opened By This EA
|
||||
input string OrderNote=""; //Comment For The Orders Opened By This EA
|
||||
input int Slippage=5; //Slippage in points
|
||||
input double MaxSpread=10.0; //Maximum Allowed Spread To Trade In Points
|
||||
|
||||
input string Comment_5="==========="; //Zigzag indicator setting
|
||||
input int Depth=5;
|
||||
input int Deviation=5;
|
||||
input int Backstep=3;
|
||||
input int GapPoint=100; //Minimum gap between peaks
|
||||
input int Sensitivity=2; //Minimum peak at same level
|
||||
input int LookBack=50; //Maximum peak to consider
|
||||
|
||||
input int NumberOfCandles=3;
|
||||
|
||||
//-GLOBAL VARIABLES-//
|
||||
//The variables included in this section are global, hence they can be used in any part of the code
|
||||
string Symb=Symbol(), server_time;
|
||||
|
||||
long current_chart_id = ChartID();
|
||||
|
||||
bool IsPreChecksOk=false; //Indicates if the pre checks are satisfied
|
||||
bool IsNewCandle=false; //Indicates if this is a new candle formed
|
||||
bool IsSpreadOK=false; //Indicates if the spread is low enough to trade
|
||||
bool IsOperatingHours=false; //Indicates if it is possible to trade at the current time (server time)
|
||||
bool IsTradedThisBar=false; //Indicates if an order was already executed in the current candle
|
||||
bool In_Trade = true; //Indicates if trade range has been formed
|
||||
bool CanBuy = true;
|
||||
bool CanSell = true;
|
||||
bool ClosePosition = false;
|
||||
bool FollowProfit = false;
|
||||
bool UpTrendingMarket = false;
|
||||
bool DownTrendingMarket = false;
|
||||
|
||||
double TickValue=0; //Value of a tick in account currency at 1 lot
|
||||
double LotSize=0; //Lot size for the position
|
||||
double Tick_Size = SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_SIZE); //Tick size
|
||||
double High[];
|
||||
double Low[];
|
||||
double PositionProfit;
|
||||
|
||||
//Indicators
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
long Spread = SymbolInfoInteger(Symb,SYMBOL_SPREAD) / 100; //Check the impact. It's originally a double
|
||||
int OrderOpRetry=10; //Number of attempts to retry the order submission
|
||||
int TotalOpenOrders=0; //Number of total open orders
|
||||
int TotalOpenBuy=0; //Number of total open buy orders
|
||||
int TotalOpenSell=0; //Number of total open sell orders
|
||||
int StopLossBy=SL_BY_POINTS; //How the stop loss is passed for the lot size calculation
|
||||
double lotMultiplier =1; //Adust lot size according to loosing trades
|
||||
int candleCounter =0;
|
||||
double firstCandleOpen =0;
|
||||
double lastCandleClose=0;
|
||||
double ProfitRunTargetPercent=10.0;
|
||||
|
||||
datetime LastBarTraded;
|
||||
|
||||
MqlDateTime dt;
|
||||
MqlTick last_tick;
|
||||
|
||||
ENUM_SIGNAL_ENTRY SignalEntry=SIGNAL_ENTRY_NEUTRAL; //Entry signal variable
|
||||
ENUM_SIGNAL_EXIT SignalExit=SIGNAL_EXIT_NEUTRAL;
|
||||
ENUM_CANDLE_TYPE candleType=NEUTRAL_CANDLE;
|
||||
ENUM_PRICE_MOMENTUM priceMomentum=NEUTRAL;
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,123 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| A_PositionsManager.mqh |
|
||||
//| Copyright 2021, Nkondog Anselme Venceslas |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2021, Nkondog Anselme Venceslas"
|
||||
#property link "https://www.mql5.com"
|
||||
CTrade trade;
|
||||
|
||||
//Scan all positions to find the ones submitted by the EA
|
||||
//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails
|
||||
bool ScanPositions()
|
||||
{
|
||||
|
||||
//Scan all the orders, retrieving some of the details
|
||||
TotalOpenOrders = 0;
|
||||
TotalOpenBuy = 0;
|
||||
TotalOpenSell = 0;
|
||||
for(int i=0; i<PositionsTotal(); i++)
|
||||
{
|
||||
//If there is a problem reading the order print the error, exit the function and return false
|
||||
if(PositionGetTicket(i) == 0)
|
||||
{
|
||||
int Error=GetLastError();
|
||||
string ErrorText=GetLastErrorText(Error);
|
||||
Print("ERROR - Unable to select the order - ",Error," - ",ErrorText);
|
||||
return false;
|
||||
}
|
||||
//If the order is not for the instrument on chart we can ignore it
|
||||
if(PositionGetSymbol(i)!=Symb)
|
||||
continue;
|
||||
//If the order has Magic Number different from the Magic Number of the EA then we can ignore it
|
||||
if(PositionGetInteger(POSITION_MAGIC)!=MagicNumber)
|
||||
continue;
|
||||
//If it is a buy order then increment the total count of buy orders
|
||||
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
|
||||
TotalOpenBuy++;
|
||||
//If it is a sell order then increment the total count of sell orders
|
||||
if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
|
||||
TotalOpenSell++;
|
||||
//Increment the total orders count
|
||||
TotalOpenOrders++;
|
||||
//Find what is the open time of the most recent trade and assign it to LastBarTraded
|
||||
//this is necessary to check if we already traded in the current candle
|
||||
if((datetime)PositionGetInteger(POSITION_TIME)>LastBarTraded || LastBarTraded==0)
|
||||
LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME);
|
||||
}
|
||||
Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We declare a function CloseOpenPositions of type int and we want to return
|
||||
// the number of positions that are closed.
|
||||
void CloseOpenPositions()
|
||||
{
|
||||
|
||||
int TotalClose=0; // We want to count how many orders have been closed.
|
||||
int c_slippage = Slippage;
|
||||
Print("Close position status ", ClosePosition);
|
||||
// Normalization of the slippage.
|
||||
if(_Digits==3 || _Digits==5)
|
||||
{
|
||||
c_slippage=c_slippage*10;
|
||||
}
|
||||
|
||||
// We scan all the orders backwards.
|
||||
// This is required as if we start from the first order, we will have problems with the counters and the loop.
|
||||
for(int i=PositionsTotal()-1; i>=0; i--)
|
||||
{
|
||||
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
|
||||
Print("Position profit is ", PositionGetDouble(POSITION_PROFIT));
|
||||
PositionProfit = PositionGetDouble(POSITION_PROFIT);
|
||||
/*if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspana)
|
||||
{
|
||||
// We select the order of index i, selecting by position and from the pool of market/pending trades.
|
||||
//If the selection is successful we try to close the order.
|
||||
if(trade.PositionClose(ticket, c_slippage))
|
||||
{
|
||||
TotalClose++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the order fails to be closed, we print the error.
|
||||
Print("Order failed to close with error - ",GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspana)
|
||||
{
|
||||
// We select the order of index i, selecting by position and from the pool of market/pending trades.
|
||||
//If the selection is successful we try to close the order.
|
||||
if(trade.PositionClose(ticket, c_slippage))
|
||||
{
|
||||
TotalClose++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the order fails to be closed, we print the error.
|
||||
Print("Order failed to close with error - ",GetLastError());
|
||||
}
|
||||
}*/
|
||||
|
||||
if(ClosePosition)
|
||||
{
|
||||
if(trade.PositionClose(ticket, c_slippage))
|
||||
{
|
||||
TotalClose++;
|
||||
ClosePosition = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the order fails to be closed, we print the error.
|
||||
Print("Order failed to close with error - ",GetLastError());
|
||||
}
|
||||
}
|
||||
// We can use a delay if the execution is too fast.
|
||||
// Sleep() will wait X milliseconds before proceeding with the code.
|
||||
// Sleep(300);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,23 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| A_TradeManager.mqh |
|
||||
//| Copyright 2021, Nkondog Anselme Venceslas |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2021, Nkondog Anselme Venceslas"
|
||||
#property link "https://www.mql5.com"
|
||||
|
||||
void ProfitRunner()
|
||||
{
|
||||
if(ProfitRun)
|
||||
{
|
||||
if(iClose(Symb, _Period, 1) < iClose(Symb, _Period, 2) && TotalOpenBuy > 0)
|
||||
{
|
||||
ClosePosition = true;
|
||||
}
|
||||
if(iClose(Symb, _Period, 1) > iClose(Symb, _Period, 2) && TotalOpenSell > 0)
|
||||
{
|
||||
ClosePosition = true;
|
||||
}
|
||||
}
|
||||
Print("Looking to close this position ", ClosePosition);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| A_TradingHour.mqh |
|
||||
//| Copyright 2021, Nkondog Anselme Venceslas |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2021, Nkondog Anselme Venceslas"
|
||||
#property link "https://www.mql5.com"
|
||||
//+------------------------------------------------------------------+
|
||||
//| defines |
|
||||
//+------------------------------------------------------------------+
|
||||
// #define MacrosHello "Hello, world!"
|
||||
// #define MacrosYear 2010
|
||||
//+------------------------------------------------------------------+
|
||||
//| DLL imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "user32.dll"
|
||||
// int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
|
||||
// #import "my_expert.dll"
|
||||
// int ExpertRecalculate(int wParam,int lParam);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
//| EX5 imports |
|
||||
//+------------------------------------------------------------------+
|
||||
// #import "stdlib.ex5"
|
||||
// string ErrorDescription(int error_code);
|
||||
// #import
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,182 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Array.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Object.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArray |
|
||||
//| Purpose: Base class of dynamic arrays. |
|
||||
//| Derives from class CObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArray : public CObject
|
||||
{
|
||||
protected:
|
||||
int m_step_resize; // increment size of the array
|
||||
int m_data_total; // number of elements
|
||||
int m_data_max; // maximmum size of the array without memory reallocation
|
||||
int m_sort_mode; // mode of array sorting
|
||||
|
||||
public:
|
||||
CArray(void);
|
||||
~CArray(void);
|
||||
//--- methods of access to protected data
|
||||
int Step(void) const { return(m_step_resize); }
|
||||
bool Step(const int step);
|
||||
int Total(void) const { return(m_data_total); }
|
||||
int Available(void) const { return(m_data_max-m_data_total); }
|
||||
int Max(void) const { return(m_data_max); }
|
||||
bool IsSorted(const int mode=0) const { return(m_sort_mode==mode); }
|
||||
int SortMode(void) const { return(m_sort_mode); }
|
||||
//--- cleaning method
|
||||
void Clear(void) { m_data_total=0; }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- sorting method
|
||||
void Sort(const int mode=0);
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0) { m_sort_mode=-1; }
|
||||
//--- templates for methods of searching for minimum and maximum
|
||||
template<typename T>
|
||||
int Minimum(const T &data[],const int start,const int count) const;
|
||||
template<typename T>
|
||||
int Maximum(const T &data[],const int start,const int count) const;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArray::CArray(void) : m_step_resize(16),
|
||||
m_data_total(0),
|
||||
m_data_max(0),
|
||||
m_sort_mode(-1)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArray::~CArray(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method Set for variable m_step_resize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArray::Step(const int step)
|
||||
{
|
||||
//--- check
|
||||
if(step>0)
|
||||
{
|
||||
m_step_resize=step;
|
||||
return(true);
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sorting an array in ascending order |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArray::Sort(const int mode)
|
||||
{
|
||||
//--- check
|
||||
if(IsSorted(mode))
|
||||
return;
|
||||
m_sort_mode=mode;
|
||||
if(m_data_total<=1)
|
||||
return;
|
||||
//--- sort
|
||||
QuickSort(0,m_data_total-1,mode);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing header of array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArray::Save(const int file_handle)
|
||||
{
|
||||
//--- check handle
|
||||
if(file_handle!=INVALID_HANDLE)
|
||||
{
|
||||
//--- write start marker - 0xFFFFFFFFFFFFFFFF
|
||||
if(FileWriteLong(file_handle,-1)==sizeof(long))
|
||||
{
|
||||
//--- write array type
|
||||
if(FileWriteInteger(file_handle,Type(),INT_VALUE)==INT_VALUE)
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading header of array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArray::Load(const int file_handle)
|
||||
{
|
||||
//--- check handle
|
||||
if(file_handle!=INVALID_HANDLE)
|
||||
{
|
||||
//--- read and check start marker - 0xFFFFFFFFFFFFFFFF
|
||||
if(FileReadLong(file_handle)==-1)
|
||||
{
|
||||
//--- read and check array type
|
||||
if(FileReadInteger(file_handle,INT_VALUE)==Type())
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find minimum of array |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int CArray::Minimum(const T &data[],const int start,const int count) const
|
||||
{
|
||||
int real_count;
|
||||
//--- check for empty array
|
||||
if(m_data_total<1)
|
||||
{
|
||||
SetUserError(ERR_USER_ARRAY_IS_EMPTY);
|
||||
return(-1);
|
||||
}
|
||||
//--- check for start is out of range
|
||||
if(start<0 || start>=m_data_total)
|
||||
{
|
||||
SetUserError(ERR_USER_ITEM_NOT_FOUND);
|
||||
return(-1);
|
||||
}
|
||||
//--- compute count of elements
|
||||
real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count;
|
||||
#ifdef __MQL5__
|
||||
return(ArrayMinimum(data,start,real_count));
|
||||
#else
|
||||
return(ArrayMinimum(data,real_count,start));
|
||||
#endif
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find maximum of array |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename T>
|
||||
int CArray::Maximum(const T &data[],const int start,const int count) const
|
||||
{
|
||||
int real_count;
|
||||
//--- check for empty array
|
||||
if(m_data_total<1)
|
||||
{
|
||||
SetUserError(ERR_USER_ARRAY_IS_EMPTY);
|
||||
return(-1);
|
||||
}
|
||||
//--- check for start is out of range
|
||||
if(start<0 || start>=m_data_total)
|
||||
{
|
||||
SetUserError(ERR_USER_ITEM_NOT_FOUND);
|
||||
return(-1);
|
||||
}
|
||||
//--- compute count of elements
|
||||
real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count;
|
||||
#ifdef __MQL5__
|
||||
return(ArrayMaximum(data,start,real_count));
|
||||
#else
|
||||
return(ArrayMaximum(data,real_count,start));
|
||||
#endif
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,771 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayChar.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayChar. |
|
||||
//| Purpose: Class of dynamic array of variables |
|
||||
//| of char or uchar type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayChar : public CArray
|
||||
{
|
||||
protected:
|
||||
char m_data[]; // data array
|
||||
|
||||
public:
|
||||
CArrayChar(void);
|
||||
~CArrayChar(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_CHAR); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const char element);
|
||||
bool AddArray(const char &src[]);
|
||||
bool AddArray(const CArrayChar *src);
|
||||
bool Insert(const char element,const int pos);
|
||||
bool InsertArray(const char &src[],const int pos);
|
||||
bool InsertArray(const CArrayChar *src,const int pos);
|
||||
bool AssignArray(const char &src[]);
|
||||
bool AssignArray(const CArrayChar *src);
|
||||
//--- method of access to the array
|
||||
char At(const int index) const;
|
||||
char operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const char element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const char &array[]) const;
|
||||
bool CompareArray(const CArrayChar *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const char element);
|
||||
int Search(const char element) const;
|
||||
int SearchGreat(const char element) const;
|
||||
int SearchLess(const char element) const;
|
||||
int SearchGreatOrEqual(const char element) const;
|
||||
int SearchLessOrEqual(const char element) const;
|
||||
int SearchFirst(const char element) const;
|
||||
int SearchLast(const char element) const;
|
||||
int SearchLinear(const char element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const char element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayChar::CArrayChar(void)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayChar::~CArrayChar(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Add(const char element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::AddArray(const char &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::AddArray(const CArrayChar *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Insert(const char element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::InsertArray(const char &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::InsertArray(const CArrayChar *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::AssignArray(const char &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::AssignArray(const CArrayChar *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
char CArrayChar::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(CHAR_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Update(const int index,const char element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Shift(const int index,const int shift)
|
||||
{
|
||||
char tmp_char;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_char=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_char;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::CompareArray(const char &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::CompareArray(const CArrayChar *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayChar::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
char p_char;
|
||||
char t_char;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_char=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_char)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_char)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_char=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_char;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::InsertSort(const char element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- find position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchLinear(const char element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]==element)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::QuickSearch(const char element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
char t_char;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_char=m_data[m];
|
||||
if(t_char==element)
|
||||
break;
|
||||
if(t_char>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::Search(const char element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchGreat(const char element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]<=element)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchLess(const char element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]>=element)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchGreatOrEqual(const char element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchLessOrEqual(const char element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchFirst(const char element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayChar::SearchLast(const char element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteInteger(file_handle,m_data[i],CHAR_VALUE)!=CHAR_VALUE)
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayChar::Load(const int file_handle)
|
||||
{
|
||||
int i,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=(char)FileReadInteger(file_handle,CHAR_VALUE);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,777 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayDouble.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayDouble. |
|
||||
//| Puprpose: Class of dynamic array variables of double type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayDouble : public CArray
|
||||
{
|
||||
protected:
|
||||
double m_data[]; // data array
|
||||
double m_delta; // search tolerance
|
||||
|
||||
public:
|
||||
CArrayDouble(void);
|
||||
~CArrayDouble(void);
|
||||
//--- methods of access to protected data
|
||||
void Delta(const double delta) { m_delta=MathAbs(delta); }
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_DOUBLE); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const double element);
|
||||
bool AddArray(const double &src[]);
|
||||
bool AddArray(const CArrayDouble *src);
|
||||
bool Insert(const double element,const int pos);
|
||||
bool InsertArray(const double &src[],const int pos);
|
||||
bool InsertArray(const CArrayDouble *src,const int pos);
|
||||
bool AssignArray(const double &src[]);
|
||||
bool AssignArray(const CArrayDouble *src);
|
||||
//--- method of access to the array
|
||||
double At(const int index) const;
|
||||
double operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const double element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const double &array[]) const;
|
||||
bool CompareArray(const CArrayDouble *array) const;
|
||||
//--- methods for working with a sorted array
|
||||
bool InsertSort(const double element);
|
||||
int Search(const double element) const;
|
||||
int SearchGreat(const double element) const;
|
||||
int SearchLess(const double element) const;
|
||||
int SearchGreatOrEqual(const double element) const;
|
||||
int SearchLessOrEqual(const double element) const;
|
||||
int SearchFirst(const double element) const;
|
||||
int SearchLast(const double element) const;
|
||||
int SearchLinear(const double element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const double element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayDouble::CArrayDouble(void) : m_delta(0.0)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayDouble::~CArrayDouble(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Add(const double element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::AddArray(const double &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::AddArray(const CArrayDouble *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Insert(const double element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::InsertArray(const double &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::InsertArray(const CArrayDouble *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::AssignArray(const double &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::AssignArray(const CArrayDouble *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
double CArrayDouble::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(DBL_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Update(const int index,const double element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Shift(const int index,const int shift)
|
||||
{
|
||||
double tmp_double;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_double=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_double;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::CompareArray(const double &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::CompareArray(const CArrayDouble *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayDouble::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
double p_double,t_double;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_double=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_double)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_double)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_double=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_double;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::InsertSort(const double element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- search position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchLinear(const double element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(MathAbs(m_data[i]-element)<=m_delta)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::QuickSearch(const double element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
double t_double;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_double=m_data[m];
|
||||
//--- compare with delta
|
||||
if(MathAbs(t_double-element)<=m_delta)
|
||||
break;
|
||||
if(t_double>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::Search(const double element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
if(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchGreat(const double element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
while(m_data[pos]<=element+m_delta)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchLess(const double element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
while(m_data[pos]>=element-m_delta)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchGreatOrEqual(const double element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchLessOrEqual(const double element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchFirst(const double element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
//--- compare with delta
|
||||
while(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayDouble::SearchLast(const double element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
//--- compare with delta
|
||||
while(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteDouble(file_handle,m_data[i])!=sizeof(double))
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayDouble::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=FileReadDouble(file_handle);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,778 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayFloat.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayFloat. |
|
||||
//| Purpose: Class of dynamic array of variable |
|
||||
//| of float type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayFloat : public CArray
|
||||
{
|
||||
protected:
|
||||
float m_data[]; // data array
|
||||
float m_delta; // search tolerance
|
||||
|
||||
public:
|
||||
CArrayFloat(void);
|
||||
~CArrayFloat(void);
|
||||
//--- methods of access to protected data
|
||||
void Delta(const float delta) { m_delta=(float)MathAbs(delta); }
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_FLOAT); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const float element);
|
||||
bool AddArray(const float &src[]);
|
||||
bool AddArray(const CArrayFloat *src);
|
||||
bool Insert(const float element,const int pos);
|
||||
bool InsertArray(const float &src[],const int pos);
|
||||
bool InsertArray(const CArrayFloat *src,const int pos);
|
||||
bool AssignArray(const float &src[]);
|
||||
bool AssignArray(const CArrayFloat *src);
|
||||
//--- method of access to the array
|
||||
float At(const int index) const;
|
||||
float operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const float element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const float &array[]) const;
|
||||
bool CompareArray(const CArrayFloat *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const float element);
|
||||
int Search(const float element) const;
|
||||
int SearchGreat(const float element) const;
|
||||
int SearchLess(const float element) const;
|
||||
int SearchGreatOrEqual(const float element) const;
|
||||
int SearchLessOrEqual(const float element) const;
|
||||
int SearchFirst(const float element) const;
|
||||
int SearchLast(const float element) const;
|
||||
int SearchLinear(const float element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const float element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayFloat::CArrayFloat(void) : m_delta(0.0)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayFloat::~CArrayFloat(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Add(const float element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::AddArray(const float &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::AddArray(const CArrayFloat *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Insert(const float element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::InsertArray(const float &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::InsertArray(const CArrayFloat *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::AssignArray(const float &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::AssignArray(const CArrayFloat *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
float CArrayFloat::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(FLT_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Update(const int index,const float element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Shift(const int index,const int shift)
|
||||
{
|
||||
float tmp_float;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_float=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_float;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::CompareArray(const float &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::CompareArray(const CArrayFloat *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array)) return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayFloat::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
float p_float,t_float;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_float=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_float)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_float)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_float=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_float;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::InsertSort(const float element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- search position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchLinear(const float element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(MathAbs(m_data[i]-element)<=m_delta)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::QuickSearch(const float element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
float t_float;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_float=m_data[m];
|
||||
//--- compare with delta
|
||||
if(MathAbs(t_float-element)<=m_delta)
|
||||
break;
|
||||
if(t_float>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::Search(const float element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
if(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchGreat(const float element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
while(m_data[pos]<=element+m_delta)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchLess(const float element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
//--- compare with delta
|
||||
while(m_data[pos]>=element-m_delta)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchGreatOrEqual(const float element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchLessOrEqual(const float element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchFirst(const float element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
//--- compare with delta
|
||||
while(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayFloat::SearchLast(const float element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
//--- compare with delta
|
||||
while(MathAbs(m_data[pos]-element)<=m_delta)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteFloat(file_handle,m_data[i])!=sizeof(float))
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayFloat::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=FileReadFloat(file_handle);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,770 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayInt.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayInt. |
|
||||
//| Puprose: Class of dynamic array of variables |
|
||||
//| of int or uint type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayInt : public CArray
|
||||
{
|
||||
protected:
|
||||
int m_data[]; // data array
|
||||
|
||||
public:
|
||||
CArrayInt(void);
|
||||
~CArrayInt(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_INT); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const int element);
|
||||
bool AddArray(const int &src[]);
|
||||
bool AddArray(const CArrayInt *src);
|
||||
bool Insert(const int element,const int pos);
|
||||
bool InsertArray(const int &src[],const int pos);
|
||||
bool InsertArray(const CArrayInt *src,const int pos);
|
||||
bool AssignArray(const int &src[]);
|
||||
bool AssignArray(const CArrayInt *src);
|
||||
//--- method of access to the array
|
||||
int At(const int index) const;
|
||||
int operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const int element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const int &array[]) const;
|
||||
bool CompareArray(const CArrayInt *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const int element);
|
||||
int Search(const int element) const;
|
||||
int SearchGreat(const int element) const;
|
||||
int SearchLess(const int element) const;
|
||||
int SearchGreatOrEqual(const int element) const;
|
||||
int SearchLessOrEqual(const int element) const;
|
||||
int SearchFirst(const int element) const;
|
||||
int SearchLast(const int element) const;
|
||||
int SearchLinear(const int element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const int element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayInt::CArrayInt(void)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayInt::~CArrayInt(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Add(const int element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::AddArray(const int &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::AddArray(const CArrayInt *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Insert(const int element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::InsertArray(const int &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::InsertArray(const CArrayInt *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::AssignArray(const int &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::AssignArray(const CArrayInt *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(INT_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Update(const int index,const int element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Shift(const int index,const int shift)
|
||||
{
|
||||
int tmp_int;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_int=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_int;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::CompareArray(const int &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::CompareArray(const CArrayInt *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayInt::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
int p_int,t_int;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_int=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_int)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_int)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_int=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_int;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::InsertSort(const int element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- find position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchLinear(const int element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]==element)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::QuickSearch(const int element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
int t_int;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_int=m_data[m];
|
||||
if(t_int==element)
|
||||
break;
|
||||
if(t_int>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::Search(const int element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchGreat(const int element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]<=element)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchLess(const int element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]>=element)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchGreatOrEqual(const int element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchLessOrEqual(const int element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchFirst(const int element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayInt::SearchLast(const int element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteInteger(file_handle,m_data[i],INT_VALUE)!=INT_VALUE)
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayInt::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=FileReadInteger(file_handle,INT_VALUE);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,770 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayLong.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayLong. |
|
||||
//| Purpose: Class of dynamic array of variables |
|
||||
//| of long or ulong type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayLong : public CArray
|
||||
{
|
||||
protected:
|
||||
long m_data[]; // data array
|
||||
|
||||
public:
|
||||
CArrayLong(void);
|
||||
~CArrayLong(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_LONG); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const long element);
|
||||
bool AddArray(const long &src[]);
|
||||
bool AddArray(const CArrayLong *src);
|
||||
bool Insert(const long element,const int pos);
|
||||
bool InsertArray(const long &src[],const int pos);
|
||||
bool InsertArray(const CArrayLong *src,const int pos);
|
||||
bool AssignArray(const long &src[]);
|
||||
bool AssignArray(const CArrayLong *src);
|
||||
//--- method of access to the array
|
||||
long At(const int index) const;
|
||||
long operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods change
|
||||
bool Update(const int index,const long element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods for deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for compare arrays
|
||||
bool CompareArray(const long &array[]) const;
|
||||
bool CompareArray(const CArrayLong *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const long element);
|
||||
int Search(const long element) const;
|
||||
int SearchGreat(const long element) const;
|
||||
int SearchLess(const long element) const;
|
||||
int SearchGreatOrEqual(const long element) const;
|
||||
int SearchLessOrEqual(const long element) const;
|
||||
int SearchFirst(const long element) const;
|
||||
int SearchLast(const long element) const;
|
||||
int SearchLinear(const long element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const long element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayLong::CArrayLong(void)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayLong::~CArrayLong(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Add(const long element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::AddArray(const long &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::AddArray(const CArrayLong *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Insert(const long element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::InsertArray(const long &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::InsertArray(const CArrayLong *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::AssignArray(const long &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::AssignArray(const CArrayLong *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
long CArrayLong::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(LONG_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Update(const int index,const long element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Shift(const int index,const int shift)
|
||||
{
|
||||
long tmp_long;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_long=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_long;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::CompareArray(const long &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::CompareArray(const CArrayLong *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayLong::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
long p_long,t_long;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_long=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_long)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_long)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_long=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_long;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::InsertSort(const long element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- search position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchLinear(const long element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]==element)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::QuickSearch(const long element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
long t_long;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_long=m_data[m];
|
||||
if(t_long==element)
|
||||
break;
|
||||
if(t_long>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::Search(const long element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchGreat(const long element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]<=element)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchLess(const long element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]>=element)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchGreatOrEqual(const long element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchLessOrEqual(const long element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchFirst(const long element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayLong::SearchLast(const long element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteLong(file_handle,m_data[i])!=sizeof(long))
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayLong::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=FileReadLong(file_handle);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,759 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayObj.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayObj. |
|
||||
//| Puprose: Class of dynamic array of pointers to instances |
|
||||
//| of the CObject class and its derivatives. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayObj : public CArray
|
||||
{
|
||||
protected:
|
||||
CObject *m_data[]; // data array
|
||||
bool m_free_mode; // flag of necessity of "physical" deletion of object
|
||||
|
||||
public:
|
||||
CArrayObj(void);
|
||||
~CArrayObj(void);
|
||||
//--- methods of access to protected data
|
||||
bool FreeMode(void) const { return(m_free_mode); }
|
||||
void FreeMode(const bool mode) { m_free_mode=mode; }
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(0x7778); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- method of creating an element of array
|
||||
virtual bool CreateElement(const int index) { return(false); }
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(CObject *element);
|
||||
bool AddArray(const CArrayObj *src);
|
||||
bool Insert(CObject *element,const int pos);
|
||||
bool InsertArray(const CArrayObj *src,const int pos);
|
||||
bool AssignArray(const CArrayObj *src);
|
||||
//--- method of access to thre array
|
||||
CObject *At(const int index) const;
|
||||
//--- methods of changing
|
||||
bool Update(const int index,CObject *element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
CObject *Detach(const int index);
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
void Clear(void);
|
||||
//--- method for comparing arrays
|
||||
bool CompareArray(const CArrayObj *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(CObject *element);
|
||||
int Search(const CObject *element) const;
|
||||
int SearchGreat(const CObject *element) const;
|
||||
int SearchLess(const CObject *element) const;
|
||||
int SearchGreatOrEqual(const CObject *element) const;
|
||||
int SearchLessOrEqual(const CObject *element) const;
|
||||
int SearchFirst(const CObject *element) const;
|
||||
int SearchLast(const CObject *element) const;
|
||||
|
||||
protected:
|
||||
void QuickSort(int beg,int end,const int mode);
|
||||
int QuickSearch(const CObject *element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayObj::CArrayObj(void) : m_free_mode(true)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayObj::~CArrayObj(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
{
|
||||
//--- "physical" removal of the object (if necessary and possible)
|
||||
if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC)
|
||||
delete m_data[dest+i];
|
||||
//---
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
m_data[src+i]=NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
{
|
||||
//--- "physical" removal of the object (if necessary and possible)
|
||||
if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC)
|
||||
delete m_data[dest+i];
|
||||
//---
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
m_data[src+i]=NULL;
|
||||
}
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
//--- explicitly zeroize all the loose items in the array
|
||||
for(int i=m_data_total;i<m_data_max;i++)
|
||||
m_data[i]=NULL;
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_total>size)
|
||||
{
|
||||
//--- "physical" removal of the object (if necessary and possible)
|
||||
if(m_free_mode)
|
||||
for(int i=size;i<m_data_total;i++)
|
||||
if(CheckPointer(m_data[i])==POINTER_DYNAMIC)
|
||||
delete m_data[i];
|
||||
m_data_total=size;
|
||||
}
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
Clear();
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Add(CObject *element)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(element))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::AddArray(const CArrayObj *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Insert(CObject *element,const int pos)
|
||||
{
|
||||
//--- check
|
||||
if(pos<0 || !CheckPointer(element))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::InsertArray(const CArrayObj *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num)) return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::AssignArray(const CArrayObj *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CArrayObj::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(NULL);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Update(const int index,CObject *element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || !CheckPointer(element) || index>=m_data_total)
|
||||
return(false);
|
||||
//--- "physical" removal of the object (if necessary and possible)
|
||||
if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC)
|
||||
delete m_data[index];
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Shift(const int index,const int shift)
|
||||
{
|
||||
CObject *tmp_node;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_node=m_data[index];
|
||||
m_data[index]=NULL;
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_node;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1)
|
||||
{
|
||||
if(index>=0 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC)
|
||||
delete m_data[index];
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detach element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CArrayObj::Detach(const int index)
|
||||
{
|
||||
CObject *result;
|
||||
//--- check
|
||||
if(index>=m_data_total)
|
||||
return(NULL);
|
||||
//--- detach
|
||||
result=m_data[index];
|
||||
//--- reset the array element, so as not remove the method MemMove
|
||||
m_data[index]=NULL;
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(NULL);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
for(int i=to-from+1;i>0;i--,m_data_total--)
|
||||
if(m_free_mode && CheckPointer(m_data[m_data_total-1])==POINTER_DYNAMIC)
|
||||
delete m_data[m_data_total-1];
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Clearing of array without the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayObj::Clear(void)
|
||||
{
|
||||
//--- "physical" removal of the object (if necessary and possible)
|
||||
if(m_free_mode)
|
||||
{
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
{
|
||||
if(CheckPointer(m_data[i])==POINTER_DYNAMIC)
|
||||
delete m_data[i];
|
||||
m_data[i]=NULL;
|
||||
}
|
||||
}
|
||||
m_data_total=0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::CompareArray(const CArrayObj *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i].Compare(array.m_data[i],0)!=0)
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayObj::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
CObject *p_node;
|
||||
CObject *t_node;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_node=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i].Compare(p_node,mode)<0)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j].Compare(p_node,mode)>0)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_node=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_node;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j,mode);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::InsertSort(CObject *element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!CheckPointer(element) || m_sort_mode==-1)
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- find position and insert
|
||||
int mode=m_sort_mode;
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos].Compare(element,m_sort_mode)>0)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=mode;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::QuickSearch(const CObject *element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
CObject *t_node;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m==m_data_total-1)
|
||||
break;
|
||||
t_node=m_data[m];
|
||||
if(t_node.Compare(element,m_sort_mode)==0)
|
||||
break;
|
||||
if(t_node.Compare(element,m_sort_mode)>0)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::Search(const CObject *element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos].Compare(element,m_sort_mode)==0)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchGreat(const CObject *element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos].Compare(element,m_sort_mode)<=0)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchLess(const CObject *element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos].Compare(element,m_sort_mode)>=0)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchGreatOrEqual(const CObject *element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos].Compare(element,m_sort_mode)>=0)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchLessOrEqual(const CObject *element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos].Compare(element,m_sort_mode)<=0)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchFirst(const CObject *element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos].Compare(element,m_sort_mode)==0)
|
||||
{
|
||||
while(m_data[pos].Compare(element,m_sort_mode)==0)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayObj::SearchLast(const CObject *element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1)
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos].Compare(element,m_sort_mode)==0)
|
||||
{
|
||||
while(m_data[pos].Compare(element,m_sort_mode)==0)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(m_data[i].Save(file_handle)!=true)
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayObj::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
//--- create new element
|
||||
if(!CreateElement(i))
|
||||
break;
|
||||
if(m_data[i].Load(file_handle)!=true)
|
||||
break;
|
||||
m_data_total++;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,770 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayShort.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayShort. |
|
||||
//| Pupose: Class of dynamic array of variables |
|
||||
//| of short or ushort type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayShort : public CArray
|
||||
{
|
||||
protected:
|
||||
short m_data[]; // data array
|
||||
|
||||
public:
|
||||
CArrayShort(void);
|
||||
~CArrayShort(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_SHORT); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const short element);
|
||||
bool AddArray(const short &src[]);
|
||||
bool AddArray(const CArrayShort *src);
|
||||
bool Insert(const short element,const int pos);
|
||||
bool InsertArray(const short &src[],const int pos);
|
||||
bool InsertArray(const CArrayShort *src,const int pos);
|
||||
bool AssignArray(const short &src[]);
|
||||
bool AssignArray(const CArrayShort *src);
|
||||
//--- method of access to the array
|
||||
short At(const int index) const;
|
||||
short operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of searching for minimum and maximum
|
||||
int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }
|
||||
int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const short element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const short &array[]) const;
|
||||
bool CompareArray(const CArrayShort *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const short element);
|
||||
int Search(const short element) const;
|
||||
int SearchGreat(const short element) const;
|
||||
int SearchLess(const short element) const;
|
||||
int SearchGreatOrEqual(const short element) const;
|
||||
int SearchLessOrEqual(const short element) const;
|
||||
int SearchFirst(const short element) const;
|
||||
int SearchLast(const short element) const;
|
||||
int SearchLinear(const short element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const short element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayShort::CArrayShort(void)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayShort::~CArrayShort(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Add(const short element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::AddArray(const short &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::AddArray(const CArrayShort *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Insert(const short element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::InsertArray(const short &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::InsertArray(const CArrayShort *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::AssignArray(const short &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::AssignArray(const CArrayShort *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
short CArrayShort::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(SHORT_MAX);
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Update(const int index,const short element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Shift(const int index,const int shift)
|
||||
{
|
||||
short tmp_short;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_short=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_short;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::CompareArray(const short &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::CompareArray(const CArrayShort *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayShort::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
short p_short,t_short;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_short=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_short)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_short)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_short=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_short;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::InsertSort(const short element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- find position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchLinear(const short element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]==element)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::QuickSearch(const short element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
short t_short;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_short=m_data[m];
|
||||
if(t_short==element)
|
||||
break;
|
||||
if(t_short>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::Search(const short element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchGreat(const short element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]<=element)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchLess(const short element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]>=element)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchGreatOrEqual(const short element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchLessOrEqual(const short element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchFirst(const short element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayShort::SearchLast(const short element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Save(const int file_handle)
|
||||
{
|
||||
int i=0;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
if(FileWriteInteger(file_handle,m_data[i],SHORT_VALUE)!=SHORT_VALUE)
|
||||
break;
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayShort::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=(short)FileReadInteger(file_handle,SHORT_VALUE);
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,780 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ArrayString.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Array.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CArrayString. |
|
||||
//| Purpose: Class of dynamic array of variables of string type. |
|
||||
//| Derives from class CArray. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CArrayString : public CArray
|
||||
{
|
||||
protected:
|
||||
string m_data[]; // data array
|
||||
|
||||
public:
|
||||
CArrayString(void);
|
||||
~CArrayString(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(TYPE_STRING); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- methods of managing dynamic memory
|
||||
bool Reserve(const int size);
|
||||
bool Resize(const int size);
|
||||
bool Shutdown(void);
|
||||
//--- methods of filling the array
|
||||
bool Add(const string element);
|
||||
bool AddArray(const string &src[]);
|
||||
bool AddArray(const CArrayString *src);
|
||||
bool Insert(const string element,const int pos);
|
||||
bool InsertArray(const string &src[],const int pos);
|
||||
bool InsertArray(const CArrayString *src,const int pos);
|
||||
bool AssignArray(const string &src[]);
|
||||
bool AssignArray(const CArrayString *src);
|
||||
//--- method of access to the array
|
||||
string At(const int index) const;
|
||||
string operator[](const int index) const { return(At(index)); }
|
||||
//--- methods of changing
|
||||
bool Update(const int index,const string element);
|
||||
bool Shift(const int index,const int shift);
|
||||
//--- methods of deleting
|
||||
bool Delete(const int index);
|
||||
bool DeleteRange(int from,int to);
|
||||
//--- methods for comparing arrays
|
||||
bool CompareArray(const string &array[]) const;
|
||||
bool CompareArray(const CArrayString *array) const;
|
||||
//--- methods for working with the sorted array
|
||||
bool InsertSort(const string element);
|
||||
int Search(const string element) const;
|
||||
int SearchGreat(const string element) const;
|
||||
int SearchLess(const string element) const;
|
||||
int SearchGreatOrEqual(const string element) const;
|
||||
int SearchLessOrEqual(const string element) const;
|
||||
int SearchFirst(const string element) const;
|
||||
int SearchLast(const string element) const;
|
||||
int SearchLinear(const string element) const;
|
||||
|
||||
protected:
|
||||
virtual void QuickSort(int beg,int end,const int mode=0);
|
||||
int QuickSearch(const string element) const;
|
||||
int MemMove(const int dest,const int src,int count);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayString::CArrayString(void)
|
||||
{
|
||||
//--- initialize protected data
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CArrayString::~CArrayString(void)
|
||||
{
|
||||
if(m_data_max!=0)
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving the memory within a single array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::MemMove(const int dest,const int src,int count)
|
||||
{
|
||||
int i;
|
||||
//--- check parameters
|
||||
if(dest<0 || src<0 || count<0)
|
||||
return(-1);
|
||||
//--- check count
|
||||
if(src+count>m_data_total)
|
||||
count=m_data_total-src;
|
||||
if(count<0)
|
||||
return(-1);
|
||||
//--- no need to copy
|
||||
if(dest==src || count==0)
|
||||
return(dest);
|
||||
//--- check data total
|
||||
if(dest+count>m_data_total)
|
||||
{
|
||||
if(m_data_max<dest+count)
|
||||
return(-1);
|
||||
m_data_total=dest+count;
|
||||
}
|
||||
//--- copy
|
||||
if(dest<src)
|
||||
{
|
||||
//--- copy from left to right
|
||||
for(i=0;i<count;i++)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- copy from right to left
|
||||
for(i=count-1;i>=0;i--)
|
||||
m_data[dest+i]=m_data[src+i];
|
||||
}
|
||||
//--- successful
|
||||
return(dest);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Request for more memory in an array. Checks if the requested |
|
||||
//| number of free elements already exists; allocates additional |
|
||||
//| memory with a given step |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Reserve(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<=0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
if(Available()<size)
|
||||
{
|
||||
new_size=m_data_max+m_step_resize*(1+(size-Available())/m_step_resize);
|
||||
if(new_size<0)
|
||||
//--- overflow occurred when calculating new_size
|
||||
return(false);
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
m_data_max=ArraySize(m_data);
|
||||
}
|
||||
//--- result
|
||||
return(Available()>=size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resizing (with removal of elements on the right) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Resize(const int size)
|
||||
{
|
||||
int new_size;
|
||||
//--- check
|
||||
if(size<0)
|
||||
return(false);
|
||||
//--- resize array
|
||||
new_size=m_step_resize*(1+size/m_step_resize);
|
||||
if(m_data_max!=new_size)
|
||||
{
|
||||
if((m_data_max=ArrayResize(m_data,new_size))==-1)
|
||||
{
|
||||
m_data_max=ArraySize(m_data);
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if(m_data_total>size)
|
||||
m_data_total=size;
|
||||
//--- result
|
||||
return(m_data_max==new_size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Complete cleaning of the array with the release of memory |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Shutdown(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_max==0)
|
||||
return(true);
|
||||
//--- clean
|
||||
if(ArrayResize(m_data,0)==-1)
|
||||
return(false);
|
||||
m_data_total=0;
|
||||
m_data_max=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Add(const string element)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- add
|
||||
m_data[m_data_total++]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::AddArray(const string &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding an element to the end of the array from another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::AddArray(const CArrayString *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- add
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[m_data_total++]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting an element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Insert(const string element,const int pos)
|
||||
{
|
||||
//--- check/reserve elements of array
|
||||
if(pos<0 || !Reserve(1))
|
||||
return(false);
|
||||
//--- insert
|
||||
m_data_total++;
|
||||
if(pos<m_data_total-1)
|
||||
{
|
||||
if(MemMove(pos+1,pos,m_data_total-pos-1)<0)
|
||||
return(false);
|
||||
m_data[pos]=element;
|
||||
}
|
||||
else
|
||||
m_data[m_data_total-1]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::InsertArray(const string &src[],const int pos)
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting elements in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::InsertArray(const CArrayString *src,const int pos)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.Total();
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(MemMove(num+pos,pos,m_data_total-pos)<0)
|
||||
return(false);
|
||||
for(int i=0;i<num;i++)
|
||||
m_data[i+pos]=src.m_data[i];
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::AssignArray(const string &src[])
|
||||
{
|
||||
int num=ArraySize(src);
|
||||
//--- check/reserve elements of array
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Assignment (copying) of another array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::AssignArray(const CArrayString *src)
|
||||
{
|
||||
int num;
|
||||
//--- check
|
||||
if(!CheckPointer(src))
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
num=src.m_data_total;
|
||||
Clear();
|
||||
if(m_data_max<num)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
Resize(num);
|
||||
//--- copy array
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
m_data[i]=src.m_data[i];
|
||||
m_data_total++;
|
||||
}
|
||||
m_sort_mode=src.SortMode();
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Access to data in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
string CArrayString::At(const int index) const
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return("");
|
||||
//--- result
|
||||
return(m_data[index]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updating element in the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Update(const int index,const string element)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- update
|
||||
m_data[index]=element;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Moving element from the specified position |
|
||||
//| on the specified shift |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Shift(const int index,const int shift)
|
||||
{
|
||||
string tmp_string;
|
||||
//--- check
|
||||
if(index<0 || index+shift<0 || index+shift>=m_data_total)
|
||||
return(false);
|
||||
if(shift==0)
|
||||
return(true);
|
||||
//--- move
|
||||
tmp_string=m_data[index];
|
||||
if(shift>0)
|
||||
{
|
||||
if(MemMove(index,index+1,shift)<0)
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(MemMove(index+shift+1,index+shift,-shift)<0)
|
||||
return(false);
|
||||
}
|
||||
m_data[index+shift]=tmp_string;
|
||||
m_sort_mode=-1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting element from the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Delete(const int index)
|
||||
{
|
||||
//--- check
|
||||
if(index<0 || index>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(index<m_data_total-1 && MemMove(index,index+1,m_data_total-index-1)<0)
|
||||
return(false);
|
||||
m_data_total--;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deleting range of elements |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::DeleteRange(int from,int to)
|
||||
{
|
||||
//--- check
|
||||
if(from<0 || to<0)
|
||||
return(false);
|
||||
if(from>to || from>=m_data_total)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(to>=m_data_total-1)
|
||||
to=m_data_total-1;
|
||||
if(MemMove(from,to+1,m_data_total-to-1)<0)
|
||||
return(false);
|
||||
m_data_total-=to-from+1;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::CompareArray(const string &array[]) const
|
||||
{
|
||||
//--- compare
|
||||
if(m_data_total!=ArraySize(array))
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparison of two arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::CompareArray(const CArrayString *array) const
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(array))
|
||||
return(false);
|
||||
//--- compare
|
||||
if(m_data_total!=array.m_data_total)
|
||||
return(false);
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]!=array.m_data[i])
|
||||
return(false);
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CArrayString::QuickSort(int beg,int end,const int mode)
|
||||
{
|
||||
int i,j;
|
||||
string p_string;
|
||||
string t_string;
|
||||
//--- check
|
||||
if(beg<0 || end<0)
|
||||
return;
|
||||
//--- sort
|
||||
i=beg;
|
||||
j=end;
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
p_string=m_data[(beg+end)>>1];
|
||||
while(i<j)
|
||||
{
|
||||
while(m_data[i]<p_string)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
while(m_data[j]>p_string)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
t_string=m_data[i];
|
||||
m_data[i++]=m_data[j];
|
||||
m_data[j]=t_string;
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j);
|
||||
beg=i;
|
||||
j=end;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::InsertSort(const string element)
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(!IsSorted())
|
||||
return(false);
|
||||
//--- check/reserve elements of array
|
||||
if(!Reserve(1))
|
||||
return(false);
|
||||
//--- if the array is empty, add an element
|
||||
if(m_data_total==0)
|
||||
{
|
||||
m_data[m_data_total++]=element;
|
||||
return(true);
|
||||
}
|
||||
//--- find position and insert
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]>element)
|
||||
Insert(element,pos);
|
||||
else
|
||||
Insert(element,pos+1);
|
||||
//--- restore the sorting flag after Insert(...)
|
||||
m_sort_mode=0;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchLinear(const string element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(-1);
|
||||
//---
|
||||
for(int i=0;i<m_data_total;i++)
|
||||
if(m_data[i]==element)
|
||||
return(i);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Quick search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::QuickSearch(const string element) const
|
||||
{
|
||||
int i,j,m=-1;
|
||||
string t_string;
|
||||
//--- search
|
||||
i=0;
|
||||
j=m_data_total-1;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_string=m_data[m];
|
||||
if(t_string==element)
|
||||
break;
|
||||
if(t_string>element)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
}
|
||||
//--- position
|
||||
return(m);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search of position of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::Search(const string element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than |
|
||||
//| specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchGreat(const string element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]<=element)
|
||||
if(++pos==m_data_total)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than |
|
||||
//| specified in the sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchLess(const string element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
while(m_data[pos]>=element)
|
||||
if(pos--==0)
|
||||
return(-1);
|
||||
//--- position
|
||||
return(pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is greater than or |
|
||||
//| equal to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchGreatOrEqual(const string element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos<m_data_total;pos++)
|
||||
if(m_data[pos]>=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of the first element which is less than or equal |
|
||||
//| to the specified in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchLessOrEqual(const string element) const
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
for(int pos=QuickSearch(element);pos>=0;pos--)
|
||||
if(m_data[pos]<=element)
|
||||
return(pos);
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of first appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchFirst(const string element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(pos--==0)
|
||||
break;
|
||||
return(pos+1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find position of last appearance of element in a sorted array |
|
||||
//+------------------------------------------------------------------+
|
||||
int CArrayString::SearchLast(const string element) const
|
||||
{
|
||||
int pos;
|
||||
//--- check
|
||||
if(m_data_total==0 || !IsSorted())
|
||||
return(-1);
|
||||
//--- search
|
||||
pos=QuickSearch(element);
|
||||
if(m_data[pos]==element)
|
||||
{
|
||||
while(m_data[pos]==element)
|
||||
if(++pos==m_data_total)
|
||||
break;
|
||||
return(pos-1);
|
||||
}
|
||||
//--- not found
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing array to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Save(const int file_handle)
|
||||
{
|
||||
int i=0,len;
|
||||
//--- check
|
||||
if(!CArray::Save(file_handle))
|
||||
return(false);
|
||||
//--- write array length
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write array
|
||||
for(i=0;i<m_data_total;i++)
|
||||
{
|
||||
len=StringLen(m_data[i]);
|
||||
//--- write string length
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write string
|
||||
if(len!=0) if(FileWriteString(file_handle,m_data[i],len)!=len)
|
||||
break;
|
||||
}
|
||||
//--- result
|
||||
return(i==m_data_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading array from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CArrayString::Load(const int file_handle)
|
||||
{
|
||||
int i=0,num,len;
|
||||
//--- check
|
||||
if(!CArray::Load(file_handle))
|
||||
return(false);
|
||||
//--- read array length
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read array
|
||||
Clear();
|
||||
if(num!=0)
|
||||
{
|
||||
if(!Reserve(num))
|
||||
return(false);
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
//--- read string length
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- read string
|
||||
if(len!=0)
|
||||
m_data[i]=FileReadString(file_handle,len);
|
||||
else
|
||||
m_data[i]="";
|
||||
m_data_total++;
|
||||
if(FileIsEnding(file_handle))
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_sort_mode=-1;
|
||||
//--- result
|
||||
return(m_data_total==num);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,657 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| List.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Object.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CList. |
|
||||
//| Purpose: Provides the possibility of working with the list of |
|
||||
//| CObject instances and its dervivatives |
|
||||
//| Derives from class CObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CList : public CObject
|
||||
{
|
||||
protected:
|
||||
CObject *m_first_node; // pointer to the first element of the list
|
||||
CObject *m_last_node; // pointer to the last element of the list
|
||||
CObject *m_curr_node; // pointer to the current element of the list
|
||||
int m_curr_idx; // index of the current list item
|
||||
int m_data_total; // number of elements
|
||||
bool m_free_mode; // flag of the necessity of "physical" deletion of object
|
||||
bool m_data_sort; // flag if the list is sorted or not
|
||||
int m_sort_mode; // mode of sorting of array
|
||||
|
||||
public:
|
||||
CList(void);
|
||||
~CList(void);
|
||||
//--- methods of access to protected data
|
||||
bool FreeMode(void) const { return(m_free_mode); }
|
||||
void FreeMode(bool mode) { m_free_mode=mode; }
|
||||
int Total(void) const { return(m_data_total); }
|
||||
bool IsSorted(void) const { return(m_data_sort); }
|
||||
int SortMode(void) const { return(m_sort_mode); }
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(0x7779); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
//--- method of creating an element of the list
|
||||
virtual CObject *CreateElement(void) { return(NULL); }
|
||||
//--- methods of filling the list
|
||||
int Add(CObject *new_node);
|
||||
int Insert(CObject *new_node,int index);
|
||||
//--- methods for navigating
|
||||
int IndexOf(CObject *node);
|
||||
CObject *GetNodeAtIndex(int index);
|
||||
CObject *GetFirstNode(void);
|
||||
CObject *GetPrevNode(void);
|
||||
CObject *GetCurrentNode(void);
|
||||
CObject *GetNextNode(void);
|
||||
CObject *GetLastNode(void);
|
||||
//--- methods for deleting
|
||||
CObject *DetachCurrent(void);
|
||||
bool DeleteCurrent(void);
|
||||
bool Delete(int index);
|
||||
void Clear(void);
|
||||
//--- method for comparing lists
|
||||
bool CompareList(CList *List);
|
||||
//--- methods for changing
|
||||
void Sort(int mode);
|
||||
bool MoveToIndex(int index);
|
||||
bool Exchange(CObject *node1,CObject *node2);
|
||||
//--- method for searching
|
||||
CObject *Search(CObject *element);
|
||||
protected:
|
||||
void QuickSort(int beg,int end,int mode);
|
||||
CObject *QuickSearch(CObject *element);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CList::CList(void) : m_first_node(NULL),
|
||||
m_last_node(NULL),
|
||||
m_curr_node(NULL),
|
||||
m_curr_idx(-1),
|
||||
m_data_total(0),
|
||||
m_free_mode(true),
|
||||
m_data_sort(false),
|
||||
m_sort_mode(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CList::~CList(void)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method QuickSort |
|
||||
//+------------------------------------------------------------------+
|
||||
void CList::QuickSort(int beg,int end,int mode)
|
||||
{
|
||||
int i,j,k;
|
||||
CObject *i_ptr,*j_ptr,*k_ptr;
|
||||
//---
|
||||
i_ptr=GetNodeAtIndex(i=beg);
|
||||
j_ptr=GetNodeAtIndex(j=end);
|
||||
while(i<end)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
k_ptr=GetNodeAtIndex(k=(beg+end)>>1);
|
||||
while(i<j)
|
||||
{
|
||||
while(i_ptr.Compare(k_ptr,mode)<0)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(i==m_data_total-1)
|
||||
break;
|
||||
i++;
|
||||
i_ptr=i_ptr.Next();
|
||||
}
|
||||
while(j_ptr.Compare(k_ptr,mode)>0)
|
||||
{
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
j--;
|
||||
j_ptr=j_ptr.Prev();
|
||||
}
|
||||
if(i<=j)
|
||||
{
|
||||
Exchange(i_ptr,j_ptr);
|
||||
i++;
|
||||
i_ptr=GetNodeAtIndex(i);
|
||||
//--- control the output of the array bounds
|
||||
if(j==0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
j--;
|
||||
j_ptr=GetNodeAtIndex(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(beg<j)
|
||||
QuickSort(beg,j,mode);
|
||||
beg=i;
|
||||
i_ptr=GetNodeAtIndex(i=beg);
|
||||
j_ptr=GetNodeAtIndex(j=end);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Index of element specified via the pointer to the list item |
|
||||
//+------------------------------------------------------------------+
|
||||
int CList::IndexOf(CObject *node)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(node) || !CheckPointer(m_curr_node))
|
||||
return(-1);
|
||||
//--- searching index
|
||||
if(node==m_curr_node)
|
||||
return(m_curr_idx);
|
||||
if(GetFirstNode()==node)
|
||||
return(0);
|
||||
for(int i=1;i<m_data_total;i++)
|
||||
if(GetNextNode()==node)
|
||||
return(i);
|
||||
//---
|
||||
return(-1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adding a new element to the end of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
int CList::Add(CObject *new_node)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(new_node))
|
||||
return(-1);
|
||||
//--- add
|
||||
if(m_first_node==NULL)
|
||||
m_first_node=new_node;
|
||||
else
|
||||
{
|
||||
m_last_node.Next(new_node);
|
||||
new_node.Prev(m_last_node);
|
||||
}
|
||||
m_curr_node=new_node;
|
||||
m_curr_idx=m_data_total;
|
||||
m_last_node=new_node;
|
||||
m_data_sort=false;
|
||||
//--- result
|
||||
return(m_data_total++);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserting a new element to the specified position in the list. |
|
||||
//| Inserting element to the current position of the list if index=-1|
|
||||
//+------------------------------------------------------------------+
|
||||
int CList::Insert(CObject *new_node,int index)
|
||||
{
|
||||
CObject *tmp_node;
|
||||
//--- check
|
||||
if(!CheckPointer(new_node))
|
||||
return(-1);
|
||||
if(index>m_data_total || index<0)
|
||||
return(-1);
|
||||
//--- adjust
|
||||
if(index==-1)
|
||||
{
|
||||
if(m_curr_node==NULL)
|
||||
return(Add(new_node));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(GetNodeAtIndex(index)==NULL)
|
||||
return(Add(new_node));
|
||||
}
|
||||
//--- no need to check m_curr_node
|
||||
tmp_node=m_curr_node.Prev();
|
||||
new_node.Prev(tmp_node);
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Next(new_node);
|
||||
else
|
||||
m_first_node=new_node;
|
||||
new_node.Next(m_curr_node);
|
||||
m_curr_node.Prev(new_node);
|
||||
m_data_total++;
|
||||
m_data_sort=false;
|
||||
m_curr_node=new_node;
|
||||
//--- result
|
||||
return(index);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the position of element in the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetNodeAtIndex(int index)
|
||||
{
|
||||
int i;
|
||||
bool revers;
|
||||
CObject *result;
|
||||
//--- check
|
||||
if(index>=m_data_total)
|
||||
return(NULL);
|
||||
if(index==m_curr_idx)
|
||||
return(m_curr_node);
|
||||
//--- optimize bust list
|
||||
if(index<m_curr_idx)
|
||||
{
|
||||
//--- index to the left of the current
|
||||
if(m_curr_idx-index<index)
|
||||
{
|
||||
//--- closer to the current index
|
||||
i=m_curr_idx;
|
||||
revers=true;
|
||||
result=m_curr_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- closer to the top of the list
|
||||
i=0;
|
||||
revers=false;
|
||||
result=m_first_node;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- index to the right of the current
|
||||
if(index-m_curr_idx<m_data_total-index-1)
|
||||
{
|
||||
//--- closer to the current index
|
||||
i=m_curr_idx;
|
||||
revers=false;
|
||||
result=m_curr_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- closer to the end of the list
|
||||
i=m_data_total-1;
|
||||
revers=true;
|
||||
result=m_last_node;
|
||||
}
|
||||
}
|
||||
if(!CheckPointer(result))
|
||||
return(NULL);
|
||||
//---
|
||||
if(revers)
|
||||
{
|
||||
//--- search from right to left
|
||||
for(;i>index;i--)
|
||||
{
|
||||
result=result.Prev();
|
||||
if(result==NULL)
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- search from left to right
|
||||
for(;i<index;i++)
|
||||
{
|
||||
result=result.Next();
|
||||
if(result==NULL)
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
m_curr_idx=index;
|
||||
//--- result
|
||||
return(m_curr_node=result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the first itme of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetFirstNode(void)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(m_first_node))
|
||||
return(NULL);
|
||||
//--- save
|
||||
m_curr_idx=0;
|
||||
//--- result
|
||||
return(m_curr_node=m_first_node);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the previous itme of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetPrevNode(void)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(m_curr_node) || m_curr_node.Prev()==NULL)
|
||||
return(NULL);
|
||||
//--- decrement
|
||||
m_curr_idx--;
|
||||
//--- result
|
||||
return(m_curr_node=m_curr_node.Prev());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the current item of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetCurrentNode(void)
|
||||
{
|
||||
return(m_curr_node);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the next item of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetNextNode(void)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(m_curr_node) || m_curr_node.Next()==NULL)
|
||||
return(NULL);
|
||||
//--- increment
|
||||
m_curr_idx++;
|
||||
//--- result
|
||||
return(m_curr_node=m_curr_node.Next());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get a pointer to the last itme of the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::GetLastNode(void)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(m_last_node))
|
||||
return(NULL);
|
||||
//---
|
||||
m_curr_idx=m_data_total-1;
|
||||
//--- result
|
||||
return(m_curr_node=m_last_node);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detach current item in the list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::DetachCurrent(void)
|
||||
{
|
||||
CObject *tmp_node,*result=NULL;
|
||||
//--- check
|
||||
if(!CheckPointer(m_curr_node))
|
||||
return(result);
|
||||
//--- "explode" list
|
||||
result=m_curr_node;
|
||||
m_curr_node=NULL;
|
||||
//--- if the deleted item was not the last one, pull up the "tail" of the list
|
||||
if((tmp_node=result.Next())!=NULL)
|
||||
{
|
||||
tmp_node.Prev(result.Prev());
|
||||
m_curr_node=tmp_node;
|
||||
}
|
||||
//--- if the deleted item was not the first one, pull up "head" list
|
||||
if((tmp_node=result.Prev())!=NULL)
|
||||
{
|
||||
tmp_node.Next(result.Next());
|
||||
//--- if "last_node" is removed, move the current pointer to the end of the list
|
||||
if(m_curr_node==NULL)
|
||||
{
|
||||
m_curr_node=tmp_node;
|
||||
m_curr_idx=m_data_total-2;
|
||||
}
|
||||
}
|
||||
m_data_total--;
|
||||
//--- if necessary, adjust the settings of the first and last elements
|
||||
if(m_first_node==result)
|
||||
m_first_node=result.Next();
|
||||
if(m_last_node==result)
|
||||
m_last_node=result.Prev();
|
||||
//--- complete the processing of element removed from the list
|
||||
//--- remove references to the list
|
||||
result.Prev(NULL);
|
||||
result.Next(NULL);
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete current item of list item |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::DeleteCurrent(void)
|
||||
{
|
||||
CObject *result=DetachCurrent();
|
||||
//--- check
|
||||
if(result==NULL)
|
||||
return(false);
|
||||
//--- complete the processing of element removed from the list
|
||||
if(m_free_mode)
|
||||
{
|
||||
//--- delete it "physically"
|
||||
if(CheckPointer(result)==POINTER_DYNAMIC)
|
||||
delete result;
|
||||
}
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete an item from a given position in the list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::Delete(int index)
|
||||
{
|
||||
if(GetNodeAtIndex(index)==NULL)
|
||||
return(false);
|
||||
//--- result
|
||||
return(DeleteCurrent());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Remove all items from the list |
|
||||
//+------------------------------------------------------------------+
|
||||
void CList::Clear(void)
|
||||
{
|
||||
GetFirstNode();
|
||||
while(m_data_total!=0)
|
||||
if(!DeleteCurrent())
|
||||
break;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Equality comparing of two lists |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::CompareList(CList *List)
|
||||
{
|
||||
CObject *node,*lnode;
|
||||
//--- check
|
||||
if(!CheckPointer(List))
|
||||
return(false);
|
||||
if((node=GetFirstNode())==NULL)
|
||||
return(false);
|
||||
if((lnode=List.GetFirstNode())==NULL)
|
||||
return(false);
|
||||
//--- compare
|
||||
if(node.Compare(lnode)!=0)
|
||||
return(false);
|
||||
while((node=GetNextNode())!=NULL)
|
||||
{
|
||||
if((lnode=List.GetNextNode())==NULL)
|
||||
return(false);
|
||||
if(node.Compare(lnode)!=0)
|
||||
return(false);
|
||||
}
|
||||
//--- equal
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sorting an array in ascending order |
|
||||
//+------------------------------------------------------------------+
|
||||
void CList::Sort(int mode)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return;
|
||||
if(m_data_sort && m_sort_mode==mode)
|
||||
return;
|
||||
//--- sort
|
||||
QuickSort(0,m_data_total-1,mode);
|
||||
m_sort_mode=mode;
|
||||
m_data_sort=true;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Move the current item of list to the specified position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::MoveToIndex(int index)
|
||||
{
|
||||
//--- check
|
||||
if(index>=m_data_total || !CheckPointer(m_curr_node))
|
||||
return(false);
|
||||
//--- tune
|
||||
if(m_curr_idx==index)
|
||||
return(true);
|
||||
if(m_curr_idx<index)
|
||||
index--;
|
||||
//--- move
|
||||
Insert(DetachCurrent(),index);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Move an item of the list from the specified position to the |
|
||||
//| current one |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::Exchange(CObject *node1,CObject *node2)
|
||||
{
|
||||
CObject *tmp_node,*node;
|
||||
//--- check
|
||||
if(!CheckPointer(node1) || !CheckPointer(node2))
|
||||
return(false);
|
||||
//---
|
||||
tmp_node=node1.Prev();
|
||||
node1.Prev(node2.Prev());
|
||||
if(node1.Prev()!=NULL)
|
||||
{
|
||||
node=node1.Prev();
|
||||
node.Next(node1);
|
||||
}
|
||||
else
|
||||
m_first_node=node1;
|
||||
node2.Prev(tmp_node);
|
||||
if(node2.Prev()!=NULL)
|
||||
{
|
||||
node=node2.Prev();
|
||||
node.Next(node2);
|
||||
}
|
||||
else
|
||||
m_first_node=node2;
|
||||
tmp_node=node1.Next();
|
||||
node1.Next(node2.Next());
|
||||
if(node1.Next()!=NULL)
|
||||
{
|
||||
node=node1.Next();
|
||||
node.Prev(node1);
|
||||
}
|
||||
else
|
||||
m_last_node=node1;
|
||||
node2.Next(tmp_node);
|
||||
if(node2.Next()!=NULL)
|
||||
{
|
||||
node=node2.Next();
|
||||
node.Prev(node2);
|
||||
}
|
||||
else
|
||||
m_last_node=node2;
|
||||
//---
|
||||
m_curr_idx=0;
|
||||
m_curr_node=m_first_node;
|
||||
m_data_sort=false;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of an element in a sorted list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::QuickSearch(CObject *element)
|
||||
{
|
||||
int i,j,m;
|
||||
CObject *t_node=NULL;
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return(NULL);
|
||||
//--- check the pointer is not needed
|
||||
i=0;
|
||||
j=m_data_total;
|
||||
while(j>=i)
|
||||
{
|
||||
//--- ">>1" is quick division by 2
|
||||
m=(j+i)>>1;
|
||||
if(m<0 || m>=m_data_total)
|
||||
break;
|
||||
t_node=GetNodeAtIndex(m);
|
||||
if(t_node.Compare(element,m_sort_mode)==0)
|
||||
break;
|
||||
if(t_node.Compare(element,m_sort_mode)>0)
|
||||
j=m-1;
|
||||
else
|
||||
i=m+1;
|
||||
t_node=NULL;
|
||||
}
|
||||
//--- result
|
||||
return(t_node);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Search position of an element in a sorted list |
|
||||
//+------------------------------------------------------------------+
|
||||
CObject *CList::Search(CObject *element)
|
||||
{
|
||||
CObject *result;
|
||||
//--- check
|
||||
if(!CheckPointer(element) || !m_data_sort)
|
||||
return(NULL);
|
||||
//--- search
|
||||
result=QuickSearch(element);
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing list to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::Save(const int file_handle)
|
||||
{
|
||||
CObject *node;
|
||||
bool result=true;
|
||||
//--- check
|
||||
if(!CheckPointer(m_curr_node) || file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- write start marker - 0xFFFFFFFFFFFFFFFF
|
||||
if(FileWriteLong(file_handle,-1)!=sizeof(long))
|
||||
return(false);
|
||||
//--- write type
|
||||
if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- write list size
|
||||
if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
//--- sequential scannning of elements in the list using the call of method Save()
|
||||
node=m_first_node;
|
||||
while(node!=NULL)
|
||||
{
|
||||
result&=node.Save(file_handle);
|
||||
node=node.Next();
|
||||
}
|
||||
//--- successful
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading list from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CList::Load(const int file_handle)
|
||||
{
|
||||
uint i,num;
|
||||
CObject *node;
|
||||
bool result=true;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- read and checking begin marker - 0xFFFFFFFFFFFFFFFF
|
||||
if(FileReadLong(file_handle)!=-1)
|
||||
return(false);
|
||||
//--- read and checking type
|
||||
if(FileReadInteger(file_handle,INT_VALUE)!=Type())
|
||||
return(false);
|
||||
//--- read list size
|
||||
num=FileReadInteger(file_handle,INT_VALUE);
|
||||
//--- sequential creation of list items using the call of method Load()
|
||||
Clear();
|
||||
for(i=0;i<num;i++)
|
||||
{
|
||||
node=CreateElement();
|
||||
if(node==NULL)
|
||||
return(false);
|
||||
Add(node);
|
||||
result&=node.Load(file_handle);
|
||||
}
|
||||
//--- successful
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,415 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Tree.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "TreeNode.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CTree. |
|
||||
//| Purpose: Building a binary tree of instances of CTreeNode class |
|
||||
//| and its derviatives. |
|
||||
//| Derives from class CTreeNode. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CTree : public CTreeNode
|
||||
{
|
||||
protected:
|
||||
CTreeNode *m_root_node; // root node of the tree
|
||||
|
||||
public:
|
||||
CTree(void);
|
||||
~CTree(void);
|
||||
//--- methods of access to protected data
|
||||
CTreeNode *Root(void) const { return(m_root_node); }
|
||||
//--- method of identifying the object
|
||||
virtual int Type() const { return(0x9999); }
|
||||
//--- method of filling the tree
|
||||
CTreeNode *Insert(CTreeNode *new_node);
|
||||
//--- methods of removing tree nodes
|
||||
bool Detach(CTreeNode *node);
|
||||
bool Delete(CTreeNode *node);
|
||||
void Clear(void);
|
||||
//--- method of searching data in the tree
|
||||
CTreeNode *Find(const CTreeNode *node);
|
||||
//--- method to create elements in the tree
|
||||
virtual CTreeNode *CreateElement() { return(NULL); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
void Balance(CTreeNode *node);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CTree::CTree(void) : m_root_node(NULL)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CTree::~CTree(void)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of adding a node to the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
CTreeNode *CTree::Insert(CTreeNode *new_node)
|
||||
{
|
||||
CTreeNode *p_node;
|
||||
CTreeNode *result=m_root_node;
|
||||
//--- check
|
||||
if(!CheckPointer(new_node))
|
||||
return(NULL);
|
||||
//--- add
|
||||
if(result!=NULL)
|
||||
{
|
||||
p_node=NULL;
|
||||
result=m_root_node;
|
||||
while(result!=NULL && result.Compare(new_node)!=0)
|
||||
{
|
||||
p_node=result;
|
||||
result=result.GetNext(new_node);
|
||||
}
|
||||
if(result!=NULL)
|
||||
return(result);
|
||||
if(p_node.Compare(new_node)>0)
|
||||
p_node.Left(new_node);
|
||||
else
|
||||
p_node.Right(new_node);
|
||||
new_node.Parent(p_node);
|
||||
Balance(p_node);
|
||||
}
|
||||
else
|
||||
m_root_node=new_node;
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of removing a node from the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTree::Delete(CTreeNode *node)
|
||||
{
|
||||
//--- check
|
||||
if(!CheckPointer(node))
|
||||
return(false);
|
||||
//--- delete
|
||||
if(Detach(node) && CheckPointer(node)==POINTER_DYNAMIC)
|
||||
delete node;
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of detaching node from the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTree::Detach(CTreeNode *node)
|
||||
{
|
||||
CTreeNode *curr_node,*tmp_node;
|
||||
CTreeNode *nodeA,*nodeB;
|
||||
//--- check
|
||||
curr_node=node;
|
||||
if(!CheckPointer(curr_node))
|
||||
return(false);
|
||||
//--- detach
|
||||
if(curr_node.BalanceL()>curr_node.BalanceR())
|
||||
{
|
||||
nodeA=curr_node.Left();
|
||||
while(nodeA.Right()!=NULL)
|
||||
nodeA=nodeA.Right();
|
||||
nodeB=nodeA.Parent();
|
||||
if(nodeB!=curr_node)
|
||||
{
|
||||
nodeB.Right(nodeA.Left());
|
||||
tmp_node=nodeB.Right();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeB);
|
||||
tmp_node=curr_node.Left();
|
||||
nodeA.Left(tmp_node);
|
||||
tmp_node.Parent(nodeA);
|
||||
}
|
||||
//--- left link of curr_node is already installed as it should be
|
||||
curr_node.Left(NULL);
|
||||
//--- transferring the right link of curr_node to nodeA
|
||||
nodeA.Right(curr_node.Right());
|
||||
tmp_node=curr_node.Right();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
curr_node.Right(NULL);
|
||||
//--- transferring the root link of curr_node to nodeA
|
||||
tmp_node=curr_node.Parent();
|
||||
nodeA.Parent(tmp_node);
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Left()==curr_node)
|
||||
tmp_node.Left(nodeA);
|
||||
else
|
||||
tmp_node.Right(nodeA);
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_node.Parent(NULL);
|
||||
m_root_node=nodeA;
|
||||
tmp_node=nodeA;
|
||||
}
|
||||
Balance(tmp_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(curr_node.BalanceR()>0)
|
||||
{
|
||||
nodeA=curr_node.Right();
|
||||
while(nodeA.Left()!=NULL)
|
||||
nodeA=nodeA.Left();
|
||||
nodeB=nodeA.Parent();
|
||||
if(nodeB!=curr_node)
|
||||
{
|
||||
nodeB.Left(nodeA.Right());
|
||||
tmp_node=nodeB.Left();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeB);
|
||||
tmp_node=curr_node.Right();
|
||||
nodeA.Right(tmp_node);
|
||||
tmp_node.Parent(nodeA);
|
||||
}
|
||||
//--- right link of curr_node is already installed as it should be
|
||||
curr_node.Right(NULL);
|
||||
//--- transferring the left link of curr_node to nodeA
|
||||
nodeA.Left(curr_node.Left());
|
||||
tmp_node=curr_node.Left();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
curr_node.Left(NULL);
|
||||
//--- transferring the root link of curr_node to nodeA
|
||||
tmp_node=curr_node.Parent();
|
||||
nodeA.Parent(tmp_node);
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Left()==curr_node)
|
||||
tmp_node.Left(nodeA);
|
||||
else
|
||||
tmp_node.Right(nodeA);
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_node.Parent(NULL);
|
||||
m_root_node=nodeA;
|
||||
tmp_node=nodeA;
|
||||
}
|
||||
Balance(tmp_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- node list
|
||||
if(curr_node.Parent()==NULL)
|
||||
m_root_node=NULL;
|
||||
else
|
||||
{
|
||||
tmp_node=curr_node.Parent();
|
||||
if(tmp_node.Left()==curr_node)
|
||||
tmp_node.Left(NULL);
|
||||
else
|
||||
tmp_node.Right(NULL);
|
||||
curr_node.Parent(NULL);
|
||||
}
|
||||
Balance(curr_node.Parent());
|
||||
}
|
||||
}
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of cleaning the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
void CTree::Clear(void)
|
||||
{
|
||||
if(CheckPointer(m_root_node)==POINTER_DYNAMIC)
|
||||
delete m_root_node;
|
||||
m_root_node=NULL;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of searching for a node in the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
CTreeNode *CTree::Find(const CTreeNode *node)
|
||||
{
|
||||
CTreeNode *result=m_root_node;
|
||||
//--- find
|
||||
while(result!=NULL && result.Compare(node)!=0)
|
||||
result=result.GetNext(node);
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method of balancing the tree |
|
||||
//+------------------------------------------------------------------+
|
||||
void CTree::Balance(CTreeNode *node)
|
||||
{
|
||||
CTreeNode *nodeA,*nodeB,*nodeC,*curr_node,*tmp_node;
|
||||
//---
|
||||
curr_node=node;
|
||||
while(curr_node!=NULL)
|
||||
{
|
||||
curr_node.RefreshBalance();
|
||||
if(MathAbs(curr_node.BalanceL()-curr_node.BalanceR())<=1)
|
||||
curr_node=curr_node.Parent();
|
||||
else
|
||||
{
|
||||
if(curr_node.BalanceR()>curr_node.BalanceL())
|
||||
{
|
||||
//--- rotation to the right
|
||||
tmp_node=curr_node.Right();
|
||||
if(tmp_node.BalanceL()>tmp_node.BalanceR())
|
||||
{
|
||||
//--- great rotation to the right
|
||||
nodeA=curr_node;
|
||||
nodeB=nodeA.Right();
|
||||
nodeC=nodeB.Left();
|
||||
nodeC.Parent(nodeA.Parent());
|
||||
tmp_node=nodeC.Parent();
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Right()==nodeA)
|
||||
tmp_node.Right(nodeC);
|
||||
else
|
||||
tmp_node.Left(nodeC);
|
||||
}
|
||||
else
|
||||
m_root_node=nodeC;
|
||||
nodeA.Parent(nodeC);
|
||||
nodeB.Parent(nodeC);
|
||||
nodeA.Right(nodeC.Left());
|
||||
tmp_node=nodeA.Right();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
nodeC.Left(nodeA);
|
||||
nodeB.Left(nodeC.Right());
|
||||
tmp_node=nodeB.Left();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeB);
|
||||
nodeC.Right(nodeB);
|
||||
if(m_root_node==nodeA)
|
||||
m_root_node=nodeC;
|
||||
curr_node=nodeC.Parent();
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- slight rotation to the right
|
||||
nodeA=curr_node;
|
||||
nodeB=nodeA.Right();
|
||||
nodeB.Parent(nodeA.Parent());
|
||||
tmp_node=nodeB.Parent();
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Right()==nodeA)
|
||||
tmp_node.Right(nodeB);
|
||||
else
|
||||
tmp_node.Left(nodeB);
|
||||
}
|
||||
else
|
||||
m_root_node=nodeB;
|
||||
nodeA.Parent(nodeB);
|
||||
nodeA.Right(nodeB.Left());
|
||||
tmp_node=nodeA.Right();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
nodeB.Left(nodeA);
|
||||
if(m_root_node==nodeA)
|
||||
m_root_node=nodeB;
|
||||
curr_node=nodeB.Parent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- rotation to the left
|
||||
tmp_node=curr_node.Left();
|
||||
if(tmp_node.BalanceR()>tmp_node.BalanceL())
|
||||
{
|
||||
//--- great rotation to the left
|
||||
nodeA=curr_node;
|
||||
nodeB=nodeA.Left();
|
||||
nodeC=nodeB.Right();
|
||||
nodeC.Parent(nodeA.Parent());
|
||||
tmp_node=nodeC.Parent();
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Right()==nodeA)
|
||||
tmp_node.Right(nodeC);
|
||||
else
|
||||
tmp_node.Left(nodeC);
|
||||
}
|
||||
else
|
||||
m_root_node=nodeC;
|
||||
nodeA.Parent(nodeC);
|
||||
nodeB.Parent(nodeC);
|
||||
nodeA.Left(nodeC.Right());
|
||||
tmp_node=nodeA.Left();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
nodeC.Right(nodeA);
|
||||
nodeB.Right(nodeC.Left());
|
||||
tmp_node=nodeB.Right();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeB);
|
||||
nodeC.Left(nodeB);
|
||||
if(m_root_node==nodeA)
|
||||
m_root_node=nodeC;
|
||||
curr_node=nodeC.Parent();
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- small rotation to the left
|
||||
nodeA=curr_node;
|
||||
nodeB=nodeA.Left();
|
||||
nodeB.Parent(nodeA.Parent());
|
||||
tmp_node=nodeB.Parent();
|
||||
if(tmp_node!=NULL)
|
||||
{
|
||||
if(tmp_node.Right()==nodeA)
|
||||
tmp_node.Right(nodeB);
|
||||
else
|
||||
tmp_node.Left(nodeB);
|
||||
}
|
||||
else
|
||||
m_root_node=nodeB;
|
||||
nodeA.Parent(nodeB);
|
||||
nodeA.Left(nodeB.Right());
|
||||
tmp_node=nodeA.Left();
|
||||
if(tmp_node!=NULL)
|
||||
tmp_node.Parent(nodeA);
|
||||
nodeB.Right(nodeA);
|
||||
if(m_root_node==nodeA)
|
||||
m_root_node=nodeB;
|
||||
curr_node=nodeB.Parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing tree to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTree::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
if(m_root_node==NULL)
|
||||
return(true);
|
||||
//--- result
|
||||
return(m_root_node.SaveNode(file_handle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading tree from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTree::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- create root node only
|
||||
Clear();
|
||||
Insert(CreateElement());
|
||||
//--- result
|
||||
return(m_root_node.LoadNode(file_handle,m_root_node));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,174 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| TreeNode.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <Object.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CTreeNode. |
|
||||
//| Purpose: Base class of node of binary tree CTree. |
|
||||
//| Derives from class CObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CTreeNode : public CObject
|
||||
{
|
||||
private:
|
||||
CTreeNode *m_p_node; // link to node up
|
||||
CTreeNode *m_l_node; // link to node left
|
||||
CTreeNode *m_r_node; // link to node right
|
||||
//--- variables
|
||||
int m_balance; // balance of node
|
||||
int m_l_balance; // balance of the left branch
|
||||
int m_r_balance; // balance of the right branch
|
||||
|
||||
public:
|
||||
CTreeNode(void);
|
||||
~CTreeNode(void);
|
||||
//--- methods of access to protected data
|
||||
CTreeNode* Parent(void) const { return(m_p_node); }
|
||||
void Parent(CTreeNode *node) { m_p_node=node; }
|
||||
CTreeNode* Left(void) const { return(m_l_node); }
|
||||
void Left(CTreeNode *node) { m_l_node=node; }
|
||||
CTreeNode* Right(void) const { return(m_r_node); }
|
||||
void Right(CTreeNode *node) { m_r_node=node; }
|
||||
int Balance(void) const { return(m_balance); }
|
||||
int BalanceL(void) const { return(m_l_balance); }
|
||||
int BalanceR(void) const { return(m_r_balance); }
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(0x8888); }
|
||||
//--- methods for controlling
|
||||
int RefreshBalance(void);
|
||||
CTreeNode *GetNext(const CTreeNode *node);
|
||||
//--- methods for working with files
|
||||
bool SaveNode(const int file_handle);
|
||||
bool LoadNode(const int file_handle,CTreeNode *main);
|
||||
|
||||
protected:
|
||||
//--- method for creating an instance of class
|
||||
virtual CTreeNode *CreateSample(void) { return(NULL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CTreeNode::CTreeNode(void) : m_p_node(NULL),
|
||||
m_l_node(NULL),
|
||||
m_r_node(NULL),
|
||||
m_balance(0),
|
||||
m_l_balance(0),
|
||||
m_r_balance(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CTreeNode::~CTreeNode(void)
|
||||
{
|
||||
//--- delete nodes of the next level
|
||||
if(m_l_node!=NULL)
|
||||
delete m_l_node;
|
||||
if(m_r_node!=NULL)
|
||||
delete m_r_node;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculating the balance of the node |
|
||||
//+------------------------------------------------------------------+
|
||||
int CTreeNode::RefreshBalance(void)
|
||||
{
|
||||
//--- calculate the balance of the left branch
|
||||
if(m_l_node==NULL)
|
||||
m_l_balance=0;
|
||||
else
|
||||
m_l_balance=m_l_node.RefreshBalance();
|
||||
//--- calculate the balance of the right branch
|
||||
if(m_r_node==NULL)
|
||||
m_r_balance=0;
|
||||
else
|
||||
m_r_balance=m_r_node.RefreshBalance();
|
||||
//--- calculate the balance of the node
|
||||
if(m_r_balance>m_l_balance)
|
||||
m_balance=m_r_balance+1;
|
||||
else
|
||||
m_balance=m_l_balance+1;
|
||||
//--- result
|
||||
return(m_balance);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Selecting next node |
|
||||
//+------------------------------------------------------------------+
|
||||
CTreeNode *CTreeNode::GetNext(const CTreeNode *node)
|
||||
{
|
||||
if(Compare(node)>0)
|
||||
return(m_l_node);
|
||||
//--- result
|
||||
return(m_r_node);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing node data to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTreeNode::SaveNode(const int file_handle)
|
||||
{
|
||||
bool result=true;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- write left node (if it is available)
|
||||
if(m_l_node!=NULL)
|
||||
{
|
||||
FileWriteInteger(file_handle,'L',SHORT_VALUE);
|
||||
result&=m_l_node.SaveNode(file_handle);
|
||||
}
|
||||
else
|
||||
FileWriteInteger(file_handle,'X',SHORT_VALUE);
|
||||
//--- write data of current node
|
||||
result&=Save(file_handle);
|
||||
//--- write right node (if it is available)
|
||||
if(m_r_node!=NULL)
|
||||
{
|
||||
FileWriteInteger(file_handle,'R',SHORT_VALUE);
|
||||
result&=m_r_node.SaveNode(file_handle);
|
||||
}
|
||||
else
|
||||
FileWriteInteger(file_handle,'X',SHORT_VALUE);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading node data from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CTreeNode::LoadNode(const int file_handle,CTreeNode *main)
|
||||
{
|
||||
bool result=true;
|
||||
short s_val;
|
||||
CTreeNode *node;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- read directions
|
||||
s_val=(short)FileReadInteger(file_handle,SHORT_VALUE);
|
||||
if(s_val=='L')
|
||||
{
|
||||
//--- read left node (if there is data)
|
||||
node=CreateSample();
|
||||
if(node==NULL)
|
||||
return(false);
|
||||
m_l_node=node;
|
||||
node.Parent(main);
|
||||
result&=node.LoadNode(file_handle,node);
|
||||
}
|
||||
//--- read data of current node
|
||||
result&=Load(file_handle);
|
||||
//--- read directions
|
||||
s_val=(short)FileReadInteger(file_handle,SHORT_VALUE);
|
||||
if(s_val=='R')
|
||||
{
|
||||
//--- read right node (if there is data)
|
||||
node=CreateSample();
|
||||
if(node==NULL)
|
||||
return(false);
|
||||
m_r_node=node;
|
||||
node.Parent(main);
|
||||
result&=node.LoadNode(file_handle,node);
|
||||
}
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,347 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| HistogramChart.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartCanvas.mqh"
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CHistogramChart |
|
||||
//| Usage: generates histogram chart |
|
||||
//+------------------------------------------------------------------+
|
||||
class CHistogramChart : public CChartCanvas
|
||||
{
|
||||
private:
|
||||
//--- colors
|
||||
uint m_fill_brush[];
|
||||
//--- adjusted parameters
|
||||
bool m_gradient;
|
||||
uint m_bar_gap;
|
||||
uint m_bar_min_size;
|
||||
uint m_bar_border;
|
||||
//--- data
|
||||
CArrayObj *m_values;
|
||||
|
||||
public:
|
||||
CHistogramChart(void);
|
||||
~CHistogramChart(void);
|
||||
//--- create
|
||||
virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE);
|
||||
//--- adjusted parameters
|
||||
void Gradient(const bool flag=true) { m_gradient=flag; }
|
||||
void BarGap(const uint value) { m_bar_gap=value; }
|
||||
void BarMinSize(const uint value) { m_bar_min_size=value; }
|
||||
void BarBorder(const uint value) { m_bar_border=value; }
|
||||
//--- data
|
||||
bool SeriesAdd(const double &value[],const string descr="",const uint clr=0);
|
||||
bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0);
|
||||
bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0);
|
||||
bool SeriesDelete(const uint pos);
|
||||
bool ValueUpdate(const uint series,const uint pos,double value);
|
||||
|
||||
protected:
|
||||
virtual void DrawData(const uint idx);
|
||||
void DrawBar(const int x,const int y,const int w,const int h,const uint clr);
|
||||
void GradientBrush(const int size,const uint fill_clr);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHistogramChart::CHistogramChart(void) : m_gradient(true),
|
||||
m_bar_gap(3),
|
||||
m_bar_min_size(5),
|
||||
m_bar_border(0)
|
||||
{
|
||||
ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CHistogramChart::~CHistogramChart(void)
|
||||
{
|
||||
if(ArraySize(m_fill_brush)!=0)
|
||||
ArrayFree(m_fill_brush);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create dynamic resource |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt)
|
||||
{
|
||||
//--- create object to store data
|
||||
if((m_values=new CArrayObj)==NULL)
|
||||
return(false);
|
||||
//--- pass responsibility for its destruction to the parent class
|
||||
m_data=m_values;
|
||||
//--- call method of parent class
|
||||
if(!CChartCanvas::Create(name,width,height,clrfmt))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adds data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::SeriesAdd(const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==m_max_data)
|
||||
return(false);
|
||||
//--- add
|
||||
CArrayDouble *arr=new CArrayDouble;
|
||||
if(!m_values.Add(arr))
|
||||
return(false);
|
||||
if(!arr.AssignArray(value))
|
||||
return(false);
|
||||
if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr))
|
||||
return(false);
|
||||
if(!m_descriptors.Add(descr))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserts data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==m_max_data)
|
||||
return(false);
|
||||
if(pos>=m_data_total)
|
||||
return(false);
|
||||
//--- insert
|
||||
CArrayDouble *arr=new CArrayDouble;
|
||||
if(!m_values.Insert(arr,pos))
|
||||
return(false);
|
||||
if(!arr.AssignArray(value))
|
||||
return(false);
|
||||
if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos))
|
||||
return(false);
|
||||
if(!m_descriptors.Insert(descr,pos))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updates data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(pos>=m_data_total)
|
||||
return(false);
|
||||
CArrayDouble *data=m_values.At(pos);
|
||||
if(data==NULL)
|
||||
return(false);
|
||||
//--- update
|
||||
if(!data.AssignArray(value))
|
||||
return(false);
|
||||
if(clr!=0 && !m_colors.Update(pos,clr))
|
||||
return(false);
|
||||
if(descr!=NULL && !m_descriptors.Update(pos,descr))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deletes data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::SeriesDelete(const uint pos)
|
||||
{
|
||||
//--- check
|
||||
if(pos>=m_data_total && m_data_total!=0)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(!m_values.Delete(pos))
|
||||
return(false);
|
||||
m_data_total--;
|
||||
if(!m_colors.Delete(pos))
|
||||
return(false);
|
||||
if(!m_descriptors.Delete(pos))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updates element in data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CHistogramChart::ValueUpdate(const uint series,const uint pos,double value)
|
||||
{
|
||||
CArrayDouble *data=m_values.At(series);
|
||||
//--- check
|
||||
if(data==NULL)
|
||||
return(false);
|
||||
//--- update
|
||||
if(!data.Update(pos,value))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws histogram |
|
||||
//+------------------------------------------------------------------+
|
||||
void CHistogramChart::DrawData(const uint idx)
|
||||
{
|
||||
double value=0.0;
|
||||
//--- check
|
||||
CArrayDouble *data=m_values.At(idx);
|
||||
if(data==NULL)
|
||||
return;
|
||||
int total=data.Total();
|
||||
if(total==0 || (int)idx>=total)
|
||||
return;
|
||||
//--- calculate
|
||||
int x1=m_data_area.left;
|
||||
int x2=m_data_area.right;
|
||||
int dx=(x2-x1)/total;
|
||||
uint clr=m_colors[idx];
|
||||
uint w=dx/m_data_total;
|
||||
if(w<m_bar_min_size)
|
||||
w=m_bar_min_size;
|
||||
int x=x1+(int)(m_bar_gap+w*idx);
|
||||
//--- set font
|
||||
string fontname;
|
||||
int fontsize=0;
|
||||
uint fontflags=0;
|
||||
uint fontangle=0;
|
||||
if(IS_SHOW_VALUE)
|
||||
{
|
||||
FontGet(fontname,fontsize,fontflags,fontangle);
|
||||
FontSet(fontname,-10*(w-3),fontflags,900);
|
||||
}
|
||||
//--- prepare gradient fill
|
||||
GradientBrush(w,clr);
|
||||
//--- draw
|
||||
for(int i=0;i<total;i++,x+=dx)
|
||||
{
|
||||
int y,h;
|
||||
double val=data[i];
|
||||
if(val==EMPTY_VALUE)
|
||||
continue;
|
||||
if(m_accumulative)
|
||||
value+=val;
|
||||
else
|
||||
value=val;
|
||||
// int val=(int)(value*m_scale_y);
|
||||
if(value>0)
|
||||
{
|
||||
y=(m_y_0-(int)(value*m_scale_y));
|
||||
h=m_y_0-y;
|
||||
}
|
||||
else
|
||||
{
|
||||
y=m_y_0;
|
||||
h=-(int)(value*m_scale_y);
|
||||
}
|
||||
DrawBar(x,y,w,h,clr);
|
||||
//--- draw text of value
|
||||
if(IS_SHOW_VALUE)
|
||||
{
|
||||
string text =DoubleToString(value,2);
|
||||
int width=(int)(TextWidth(text)+w);
|
||||
if(value>0)
|
||||
{
|
||||
if(width>y-m_y_max)
|
||||
TextOut(x+w/2,y+w,text,m_color_text,TA_RIGHT|TA_VCENTER);
|
||||
else
|
||||
TextOut(x+w/2,y-w,text,m_color_text,TA_LEFT|TA_VCENTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(width>m_y_min-y-h)
|
||||
TextOut(x+w/2,y+h-w,text,m_color_text,TA_LEFT|TA_VCENTER);
|
||||
else
|
||||
TextOut(x+w/2,y+h+w,text,m_color_text,TA_RIGHT|TA_VCENTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(IS_SHOW_VALUE)
|
||||
FontSet(fontname,fontsize,fontflags,fontangle);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws bar |
|
||||
//+------------------------------------------------------------------+
|
||||
void CHistogramChart::DrawBar(const int x,const int y,const int w,const int h,const uint clr)
|
||||
{
|
||||
//--- draw bar
|
||||
if(!m_gradient || ArraySize(m_fill_brush)<w)
|
||||
FillRectangle(x+1,y+1,w-x-2,h-y-2,clr);
|
||||
else
|
||||
{
|
||||
for(int i=1;i<h;i++)
|
||||
ArrayCopy(m_pixels,m_fill_brush,(y+i)*m_width+x+1,0,w);
|
||||
}
|
||||
//--- draw bar border
|
||||
if(m_bar_border!=0)
|
||||
Rectangle(x,y,x+w-1,y+h-1,m_color_border);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Creates brush for gradient fill |
|
||||
//+------------------------------------------------------------------+
|
||||
void CHistogramChart::GradientBrush(const int size,const uint fill_clr)
|
||||
{
|
||||
//--- to prepare gradient fill, we will use Bresenham's circle algorithm
|
||||
//--- X coordinate - size of the fill,
|
||||
//--- Y coordinate - color brightness
|
||||
if(m_gradient)
|
||||
{
|
||||
//--- adjust gradient radius if necessary
|
||||
int r=size;
|
||||
//--- check
|
||||
if(r<1)
|
||||
return;
|
||||
if(r!=ArrayResize(m_fill_brush,r))
|
||||
return;
|
||||
//--- initialize brush
|
||||
ArrayInitialize(m_fill_brush,m_color_background);
|
||||
//--- variables
|
||||
int f =1-r;
|
||||
int dd_x=1;
|
||||
int dd_y=-2*r;
|
||||
int dx =0;
|
||||
int dy =r;
|
||||
int i1,i2;
|
||||
uint clr,dclr;
|
||||
//---
|
||||
i1=i2=r>>1;
|
||||
if((r&1)==0)
|
||||
i1--;
|
||||
//--- calculate
|
||||
while(dy>=dx)
|
||||
{
|
||||
clr=fill_clr;
|
||||
dclr=GETRGB(XRGB((r-dy)*GETRGBR(clr)/r,(r-dy)*GETRGBG(clr)/r,(r-dy)*GETRGBB(clr)/r));
|
||||
clr-=dclr;
|
||||
m_fill_brush[i1]=clr;
|
||||
m_fill_brush[i2]=clr;
|
||||
//---
|
||||
if(f>=0)
|
||||
{
|
||||
dy--;
|
||||
dd_y+=2;
|
||||
f+=dd_y;
|
||||
}
|
||||
dx++;
|
||||
if(--i1<0)
|
||||
break;
|
||||
i2++;
|
||||
dd_x+=2;
|
||||
f+=dd_x;
|
||||
}
|
||||
}
|
||||
else
|
||||
ArrayFree(m_fill_brush);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,383 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| LineChart.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartCanvas.mqh"
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CLineChart |
|
||||
//| Usage: generates line chart |
|
||||
//+------------------------------------------------------------------+
|
||||
class CLineChart : public CChartCanvas
|
||||
{
|
||||
private:
|
||||
//--- data
|
||||
CArrayObj *m_values;
|
||||
//--- adjusted parameters
|
||||
bool m_filled;
|
||||
|
||||
public:
|
||||
CLineChart(void);
|
||||
~CLineChart(void);
|
||||
//--- create
|
||||
virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE);
|
||||
//--- adjusted parameters
|
||||
void Filled(const bool flag=true) { m_filled=flag; }
|
||||
//--- set up
|
||||
bool SeriesAdd(const double &value[],const string descr="",const uint clr=0);
|
||||
bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0);
|
||||
bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0);
|
||||
bool SeriesDelete(const uint pos);
|
||||
bool ValueUpdate(const uint series,const uint pos,double value);
|
||||
|
||||
protected:
|
||||
virtual void DrawChart(void);
|
||||
virtual void DrawData(const uint index=0);
|
||||
|
||||
private:
|
||||
double CalcArea(const uint index);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CLineChart::CLineChart(void) : m_filled(false)
|
||||
{
|
||||
ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CLineChart::~CLineChart(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create dynamic resource |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt)
|
||||
{
|
||||
//--- create object to store data
|
||||
if((m_values=new CArrayObj)==NULL)
|
||||
return(false);
|
||||
//--- pass responsibility for its destruction to the parent class
|
||||
m_data=m_values;
|
||||
//--- call method of parent class
|
||||
if(!CChartCanvas::Create(name,width,height,clrfmt))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adds data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::SeriesAdd(const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==m_max_data)
|
||||
return(false);
|
||||
//--- add
|
||||
CArrayDouble *arr=new CArrayDouble;
|
||||
if(!m_values.Add(arr))
|
||||
return(false);
|
||||
if(!arr.AssignArray(value))
|
||||
return(false);
|
||||
if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr))
|
||||
return(false);
|
||||
if(!m_descriptors.Add(descr))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserts data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==m_max_data)
|
||||
return(false);
|
||||
if(pos>=m_data_total)
|
||||
return(false);
|
||||
//--- insert
|
||||
CArrayDouble *arr=new CArrayDouble;
|
||||
if(!m_values.Insert(arr,pos))
|
||||
return(false);
|
||||
if(!arr.AssignArray(value))
|
||||
return(false);
|
||||
if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos))
|
||||
return(false);
|
||||
if(!m_descriptors.Insert(descr,pos))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updates data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if(pos>=m_data_total)
|
||||
return(false);
|
||||
CArrayDouble *data=m_values.At(pos);
|
||||
if(data==NULL)
|
||||
return(false);
|
||||
//--- update
|
||||
if(!data.AssignArray(value))
|
||||
return(false);
|
||||
if(clr!=0 && !m_colors.Update(pos,clr))
|
||||
return(false);
|
||||
if(descr!=NULL && !m_descriptors.Update(pos,descr))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deletes data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::SeriesDelete(const uint pos)
|
||||
{
|
||||
//--- check
|
||||
if(pos>=m_data_total && m_data_total!=0)
|
||||
return(false);
|
||||
//--- delete
|
||||
if(!m_values.Delete(pos))
|
||||
return(false);
|
||||
m_data_total--;
|
||||
if(!m_colors.Delete(pos))
|
||||
return(false);
|
||||
if(!m_descriptors.Delete(pos))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updates element in data series |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLineChart::ValueUpdate(const uint series,const uint pos,double value)
|
||||
{
|
||||
CArrayDouble *data=m_values.At(series);
|
||||
//--- check
|
||||
if(data==NULL)
|
||||
return(false);
|
||||
//--- update
|
||||
if(!data.Update(pos,value))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Redraws data |
|
||||
//+------------------------------------------------------------------+
|
||||
void CLineChart::DrawChart(void)
|
||||
{
|
||||
if(m_filled)
|
||||
{
|
||||
//--- calculate areas of filling
|
||||
double s[];
|
||||
ArrayResize(s,m_data_total);
|
||||
ArrayInitialize(s,0);
|
||||
for(uint i=0;i<m_data_total;i++)
|
||||
{
|
||||
CArrayDouble *data=m_values.At(i);
|
||||
if(data==NULL)
|
||||
continue;
|
||||
int total=data.Total();
|
||||
if(total<=1)
|
||||
continue;
|
||||
s[i]=CalcArea(i);
|
||||
}
|
||||
int index=ArrayMaximum(s);
|
||||
while(index!=-1 && s[index]!=0.0)
|
||||
{
|
||||
//--- draw in area descending order
|
||||
DrawData(index);
|
||||
s[index]=0.0;
|
||||
index=ArrayMaximum(s);
|
||||
}
|
||||
}
|
||||
else
|
||||
for(uint i=0;i<m_data_total;i++)
|
||||
DrawData(i);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws lines |
|
||||
//+------------------------------------------------------------------+
|
||||
void CLineChart::DrawData(const uint index)
|
||||
{
|
||||
double value=0.0;
|
||||
//--- check
|
||||
CArrayDouble *data=m_values.At(index);
|
||||
if(data==NULL)
|
||||
return;
|
||||
int total=data.Total();
|
||||
if(total<=1)
|
||||
return;
|
||||
//--- calculate
|
||||
int dx=m_data_area.Width()/(total-1);
|
||||
int x=m_data_area.left+1;
|
||||
int y1=0;
|
||||
int y2=(int)(m_y_0-data[0]*m_scale_y);
|
||||
//--- draw
|
||||
for(int i=1;i<total;i++,x+=dx)
|
||||
{
|
||||
y1=y2;
|
||||
double val=data[i];
|
||||
if(val==EMPTY_VALUE)
|
||||
continue;
|
||||
if(m_accumulative)
|
||||
value+=val;
|
||||
else
|
||||
value=val;
|
||||
y2=(int)(m_y_0-value*m_scale_y);
|
||||
if(m_filled)
|
||||
{
|
||||
if((y1>m_y_0 && y2<m_y_0) || (y1<m_y_0 && y2>m_y_0))
|
||||
{
|
||||
//--- draw two triangles
|
||||
int x3;
|
||||
if(y1>y2)
|
||||
{
|
||||
x3=x+dx*(y1-m_y_0)/(y1-y2);
|
||||
FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]);
|
||||
FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x3=x+dx*(m_y_0-y1)/(y2-y1);
|
||||
FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]);
|
||||
FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(y1<m_y_0 || y2<m_y_0)
|
||||
{
|
||||
if(y1>y2)
|
||||
FillTriangle(x,y1,x+dx,y2,x+dx,y1,(uint)m_colors[index]);
|
||||
if(y1<y2)
|
||||
{
|
||||
FillTriangle(x,y1,x+dx,y2,x,y2,(uint)m_colors[index]);
|
||||
y1=y2;
|
||||
}
|
||||
}
|
||||
if(y1>m_y_0 || y2>m_y_0)
|
||||
{
|
||||
if(y1<y2)
|
||||
FillTriangle(x,y1,x+dx,y2,x+dx,y1,(uint)m_colors[index]);
|
||||
if(y1>y2)
|
||||
{
|
||||
FillTriangle(x,y1,x+dx,y2,x,y2,(uint)m_colors[index]);
|
||||
y1=y2;
|
||||
}
|
||||
}
|
||||
FillRectangle(x,m_y_0,x+dx,y1,(uint)m_colors[index]);
|
||||
}
|
||||
else
|
||||
LineAA(x,y1,x+dx,y2,(uint)m_colors[index],STYLE_SOLID);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Area of filling |
|
||||
//+------------------------------------------------------------------+
|
||||
double CLineChart::CalcArea(const uint index)
|
||||
{
|
||||
double area =0;
|
||||
double value=0;
|
||||
int dx =100;
|
||||
//---
|
||||
CArrayDouble *data=m_values.At(index);
|
||||
if(data==NULL)
|
||||
return(0);
|
||||
int total=data.Total();
|
||||
if(total<=1)
|
||||
return(0);
|
||||
int y1=0;
|
||||
int y2=(int)(m_y_0-data[0]*m_scale_y);
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
y1=y2;
|
||||
double val=data[i];
|
||||
if(val==EMPTY_VALUE)
|
||||
continue;
|
||||
if(m_accumulative)
|
||||
value+=val;
|
||||
else
|
||||
value=val;
|
||||
y2=(int)(m_y_0-value*m_scale_y);
|
||||
if((y1>m_y_0 && y2<m_y_0) || (y1<m_y_0 && y2>m_y_0))
|
||||
{
|
||||
//--- line of values crosses the Y axis
|
||||
int x;
|
||||
if(y1>y2)
|
||||
{
|
||||
//--- from the bottom up
|
||||
x=dx*(y1-m_y_0)/(y1-y2);
|
||||
//--- add area of lower triangle
|
||||
area+=x*(y1-m_y_0)/2;
|
||||
//--- add area of upper triangle
|
||||
area+=(dx-x)*(m_y_0-y2)/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- from top down
|
||||
x=dx*(m_y_0-y1)/(y2-y1);
|
||||
//--- add area of upper triangle
|
||||
area+=x*(m_y_0-y1)/2;
|
||||
//--- add area of lower triangle
|
||||
area+=(dx-x)*(y2-m_y_0)/2;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(y1<m_y_0 || y2<m_y_0)
|
||||
{
|
||||
//--- both values are greater than zero
|
||||
if(y1>y2)
|
||||
{
|
||||
//--- add area of triangle
|
||||
area+=dx*(y1-y2)/2;
|
||||
//--- add area of rectangle
|
||||
area+=dx*(m_y_0-y2);
|
||||
}
|
||||
if(y1<y2)
|
||||
{
|
||||
//--- add area of triangle
|
||||
area+=dx*(y2-y1)/2;
|
||||
//--- add area of rectangle
|
||||
area+=dx*(m_y_0-y1);
|
||||
}
|
||||
}
|
||||
if(y1>m_y_0 || y2>m_y_0)
|
||||
{
|
||||
//--- both values are less than zero
|
||||
if(y1<y2)
|
||||
{
|
||||
//--- add area of triangle
|
||||
area+=dx*(y2-y1)/2;
|
||||
//--- add area of rectangle
|
||||
area+=dx*(y1-m_y_0);
|
||||
}
|
||||
if(y1>y2)
|
||||
{
|
||||
//--- add area of triangle
|
||||
area+=dx*(y1-y2)/2;
|
||||
//--- add area of rectangle
|
||||
area+=dx*(y2-m_y_0);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(area);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,414 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| PieChart.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartCanvas.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CPieChart |
|
||||
//| Usage: generates pie chart |
|
||||
//+------------------------------------------------------------------+
|
||||
class CPieChart : public CChartCanvas
|
||||
{
|
||||
private:
|
||||
//--- data
|
||||
CArrayDouble *m_values;
|
||||
//--- for draw
|
||||
int m_x0;
|
||||
int m_y0;
|
||||
int m_r;
|
||||
|
||||
public:
|
||||
CPieChart(void);
|
||||
~CPieChart(void);
|
||||
//--- create
|
||||
virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA);
|
||||
//--- data
|
||||
bool SeriesSet(const double &value[],const string &text[],const uint &clr[]);
|
||||
bool ValueAdd(const double value,const string descr="",const uint clr=0);
|
||||
bool ValueInsert(const uint pos,const double value,const string descr="",const uint clr=0);
|
||||
bool ValueUpdate(const uint pos,const double value,const string descr=NULL,const uint clr=0);
|
||||
bool ValueDelete(const uint pos);
|
||||
|
||||
protected:
|
||||
virtual void DrawChart(void);
|
||||
void DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr);
|
||||
string LabelMake(const string text,const double value,const bool to_left);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPieChart::CPieChart(void)
|
||||
{
|
||||
uint flags=FLAG_SHOW_LEGEND|FLAG_SHOW_DESCRIPTORS|FLAG_SHOW_VALUE|FLAG_SHOW_PERCENT;
|
||||
AllowedShowFlags(flags);
|
||||
ShowFlags(flags);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPieChart::~CPieChart(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create dynamic resource |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt)
|
||||
{
|
||||
//--- create object to store data
|
||||
if((m_values=new CArrayDouble)==NULL)
|
||||
return(false);
|
||||
//--- pass responsibility for its destruction to the parent class
|
||||
m_data=m_values;
|
||||
//--- call method of parent class
|
||||
if(!CChartCanvas::Create(name,width,height,clrfmt))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets displayed parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::SeriesSet(const double &value[],const string &text[],const uint &clr[])
|
||||
{
|
||||
//--- !!! user is responsible for correct filling of arrays !!!
|
||||
//--- check
|
||||
if(m_values==NULL)
|
||||
return(false);
|
||||
//--- set
|
||||
if(!m_values.AssignArray(value))
|
||||
return(false);
|
||||
if(!m_descriptors.AssignArray(text))
|
||||
return(false);
|
||||
if(!m_colors.AssignArray(clr))
|
||||
return(false);
|
||||
m_data_total=m_values.Total();
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adds displayed parameter (to the end) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::ValueAdd(const double value,const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if((value<=0))
|
||||
return(false);
|
||||
//--- add
|
||||
if(!m_values.Add(value))
|
||||
return(false);
|
||||
if(!m_descriptors.Add(descr))
|
||||
return(false);
|
||||
if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inserts displayed parameter (to specified position) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::ValueInsert(const uint pos,const double value,const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if((value<=0))
|
||||
return(false);
|
||||
//--- insert
|
||||
if(!m_values.Insert(value,pos))
|
||||
return(false);
|
||||
if(!m_descriptors.Insert(descr,pos))
|
||||
return(false);
|
||||
if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos))
|
||||
return(false);
|
||||
m_data_total++;
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Updates displayed parameter (in specified position) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::ValueUpdate(const uint pos,const double value,const string descr,const uint clr)
|
||||
{
|
||||
//--- check
|
||||
if((value<=0))
|
||||
return(false);
|
||||
//--- update
|
||||
if(!m_values.Update(pos,value))
|
||||
return(false);
|
||||
if(descr!=NULL && !m_descriptors.Update(pos,descr))
|
||||
return(false);
|
||||
if(clr!=0 && !m_colors.Update(pos,clr))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Deletes displayed parameter (from specified position) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPieChart::ValueDelete(const uint pos)
|
||||
{
|
||||
//--- delete
|
||||
if(!m_values.Delete(pos))
|
||||
return(false);
|
||||
m_data_total--;
|
||||
if(!m_descriptors.Delete(pos))
|
||||
return(false);
|
||||
if(!m_colors.Delete(pos))
|
||||
return(false);
|
||||
//--- redraw
|
||||
Redraw();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws |
|
||||
//+------------------------------------------------------------------+
|
||||
void CPieChart::DrawChart(void)
|
||||
{
|
||||
//--- check
|
||||
if(m_data_total==0)
|
||||
return;
|
||||
//--- variables
|
||||
string text="";
|
||||
double angle=M_PI*(m_data_offset%360)/180;
|
||||
int width,height;
|
||||
int dw=0;
|
||||
int dh=0;
|
||||
int index;
|
||||
CPoint p0[];
|
||||
CPoint p1[];
|
||||
//--- calculate geometry
|
||||
width =(m_data_area.Width()<<3)/10;
|
||||
height=(m_data_area.Height()<<3)/10;
|
||||
if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS)
|
||||
{
|
||||
if(IS_SHOW_VALUE)
|
||||
dw=(int)m_max_value_width;
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
dw=TextWidth("100.00%");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_DESCRIPTORS)
|
||||
{
|
||||
if(IS_SHOW_VALUE)
|
||||
dw=(int)m_max_value_width+TextWidth(" ()");
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
dw=TextWidth(" (100.00%)");
|
||||
}
|
||||
dw+=(int)m_max_descr_width;
|
||||
}
|
||||
}
|
||||
//--- pie chart will always be round
|
||||
width -=2*dw+10;
|
||||
height-=20;
|
||||
m_x0=m_data_area.left+(m_data_area.Width()>>1);
|
||||
m_y0=m_data_area.top+(m_data_area.Height()>>1);
|
||||
m_r =(((width>height) ? height : width)>>1);
|
||||
//--- draw pie chart
|
||||
if(ArrayResize(p0,m_data_total+1)==-1)
|
||||
return;
|
||||
if(m_data_total==1)
|
||||
{
|
||||
FillCircle(m_x0,m_y0,m_r,m_colors[0]);
|
||||
Circle(m_x0,m_y0,m_r,m_color_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
Circle(m_x0,m_y0,m_r,m_color_border);
|
||||
for(uint i=0;i<m_index_size;i++)
|
||||
{
|
||||
index=m_index[i];
|
||||
double val=m_values[index];
|
||||
double d_a=2*M_PI*val/m_sum;
|
||||
DrawPie(angle,angle+d_a,i,p0,m_colors[index]);
|
||||
angle+=d_a;
|
||||
angle=MathMod(angle,2*M_PI);
|
||||
}
|
||||
if(m_data_total!=m_index_size)
|
||||
DrawPie(angle,angle+2*M_PI*m_others/m_sum,m_index_size,p0,COLOR2RGB(clrBlack));
|
||||
for(uint i=0;i<=m_index_size;i++)
|
||||
Line(m_x0,m_y0,p0[i].x,p0[i].y,m_color_border);
|
||||
Circle(m_x0,m_y0,m_r,m_color_border);
|
||||
}
|
||||
//--- draw descriptors
|
||||
angle=M_PI*(m_data_offset%360)/180;
|
||||
int r1=(int)round(1.1*m_r);
|
||||
if(ArrayResize(p1,m_data_total)==-1)
|
||||
return;
|
||||
//--- calculations
|
||||
for(uint i=0;i<m_index_size;i++)
|
||||
{
|
||||
index=m_index[i];
|
||||
angle+=M_PI*m_values[index]/m_sum;
|
||||
//--- lines
|
||||
p0[i].x=m_x0+(int)round(m_r*cos(angle));
|
||||
p0[i].y=m_y0-(int)round(m_r*sin(angle));
|
||||
p1[i].x=m_x0+(int)round(r1*cos(angle));
|
||||
p1[i].y=m_y0-(int)round(r1*sin(angle));
|
||||
angle+=M_PI*m_values[index]/m_sum;
|
||||
}
|
||||
if(m_data_total!=m_index_size)
|
||||
{
|
||||
index=(int)m_data_total-1;
|
||||
angle+=M_PI*m_others/m_sum;
|
||||
p0[index].x=m_x0+(int)round(m_r*cos(angle));
|
||||
p0[index].y=m_y0-(int)round(m_r*sin(angle));
|
||||
p1[index].x=m_x0+(int)round(r1*cos(angle));
|
||||
p1[index].y=m_y0-(int)round(r1*sin(angle));
|
||||
}
|
||||
int x,y;
|
||||
//--- draw descriptors to the left
|
||||
for(uint i=0;i<m_index_size;i++)
|
||||
if(p0[i].x<m_x0)
|
||||
{
|
||||
x=p1[i].x-10;
|
||||
y=p1[i].y;
|
||||
index=m_index[i];
|
||||
text=LabelMake(m_descriptors[index],m_values[index],true);
|
||||
if(text!="")
|
||||
{
|
||||
Line(p0[i].x,p0[i].y,p1[i].x,p1[i].y,m_color_border);
|
||||
Line(p1[i].x,p1[i].y,x,y,m_color_border);
|
||||
TextOut(x-5,y,text,m_color_text,TA_RIGHT|TA_VCENTER);
|
||||
}
|
||||
}
|
||||
//--- draw descriptors to the right
|
||||
for(uint i=0;i<m_index_size;i++)
|
||||
if(p0[i].x>=m_x0)
|
||||
{
|
||||
x=p1[i].x+10;
|
||||
y=p1[i].y;
|
||||
index=m_index[i];
|
||||
text=LabelMake(m_descriptors[index],m_values[index],false);
|
||||
if(text!="")
|
||||
{
|
||||
Line(p0[i].x,p0[i].y,p1[i].x,p1[i].y,m_color_border);
|
||||
Line(p1[i].x,p1[i].y,x,y,m_color_border);
|
||||
TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER);
|
||||
}
|
||||
}
|
||||
if(m_data_total!=m_index_size)
|
||||
{
|
||||
index=(int)m_data_total-1;
|
||||
if(p0[index].x>=m_x0)
|
||||
{
|
||||
x=p1[index].x+10;
|
||||
y=p1[index].y;
|
||||
text=LabelMake("Others",m_others,true);
|
||||
TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
x=p1[index].x-10;
|
||||
y=p1[index].y;
|
||||
text=LabelMake("Others",m_others,false);
|
||||
TextOut(x-5,y,text,m_color_text,TA_RIGHT|TA_VCENTER);
|
||||
}
|
||||
if(text!="")
|
||||
{
|
||||
Line(p0[index].x,p0[index].y,p1[index].x,p1[index].y,m_color_border);
|
||||
Line(p1[index].x,p1[index].y,x,y,m_color_border);
|
||||
}
|
||||
}
|
||||
ArrayFree(p1);
|
||||
ArrayFree(p0);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draw pie |
|
||||
//+------------------------------------------------------------------+
|
||||
void CPieChart::DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr)
|
||||
{
|
||||
//--- draw arc
|
||||
Arc(m_x0,m_y0,m_r,m_r,fi3,fi4,p[idx].x,p[idx].y,p[idx+1].x,p[idx+1].y,clr);
|
||||
//--- variables
|
||||
int x3=p[idx].x;
|
||||
int y3=p[idx].y;
|
||||
int x4=p[idx+1].x;
|
||||
int y4=p[idx+1].y;
|
||||
//--- draw radii
|
||||
if(idx==0)
|
||||
Line(m_x0,m_y0,x3,y3,clr);
|
||||
if(idx!=m_data_total-1)
|
||||
Line(m_x0,m_y0,x4,y4,clr);
|
||||
//--- fill
|
||||
double fi=(fi3+fi4)/2;
|
||||
int xf=m_x0+(int)(0.99*m_r*cos(fi));
|
||||
int yf=m_y0-(int)(0.99*m_r*sin(fi));
|
||||
Fill(xf,yf,clr);
|
||||
//--- for small pie
|
||||
if(fi4-fi3<=M_PI_4)
|
||||
Line(m_x0,m_y0,xf,yf,clr);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Make label for pie |
|
||||
//+------------------------------------------------------------------+
|
||||
string CPieChart::LabelMake(const string text,const double value,const bool to_left)
|
||||
{
|
||||
string label="";
|
||||
//---
|
||||
if(to_left)
|
||||
{
|
||||
if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS)
|
||||
{
|
||||
if(IS_SHOW_VALUE)
|
||||
label=DoubleToString(value,2);
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
label=DoubleToString(100*value/m_sum,2)+"%";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label=text;
|
||||
if(IS_SHOW_VALUE)
|
||||
label+=" ("+DoubleToString(value,2)+")";
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
label+=" ("+DoubleToString(100*value/m_sum,2)+"%)";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS)
|
||||
{
|
||||
if(IS_SHOW_VALUE)
|
||||
label=DoubleToString(value,2);
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
label=DoubleToString(100*value/m_sum,2)+"%";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_VALUE)
|
||||
label="("+DoubleToString(value,2)+") ";
|
||||
else
|
||||
{
|
||||
if(IS_SHOW_PERCENT)
|
||||
label="("+DoubleToString(100*value/m_sum,2)+"%) ";
|
||||
}
|
||||
label+=text;
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(label);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,77 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXBox.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
//---
|
||||
#include "DXMesh.mqh"
|
||||
#include "DXMath.mqh"
|
||||
#include "DXUtils.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| 3D Box object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXBox : public CDXMesh
|
||||
{
|
||||
public:
|
||||
CDXBox();
|
||||
~CDXBox();
|
||||
//--- create bon in specified context
|
||||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to);
|
||||
//--- update box
|
||||
bool Update(const DXVector3 &from,const DXVector3 &to);
|
||||
|
||||
private:
|
||||
//---
|
||||
void PrepareVertices(const DXVector3 &from,const DXVector3 &to);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXBox::CDXBox() : CDXMesh()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXBox::~CDXBox(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create box in specified context |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXBox::Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to)
|
||||
{
|
||||
//--- release previous buffers
|
||||
Shutdown();
|
||||
//---
|
||||
DXVertex vertices[];
|
||||
uint indices[];
|
||||
//--- prepare box vertices and indices
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
if(!DXComputeBox(from,to,vertices,indices))
|
||||
return(false);
|
||||
for(int i=0; i<ArraySize(vertices); i++)
|
||||
vertices[i].vcolor=white;
|
||||
//--- create mesh
|
||||
return(CDXMesh::Create(dispatcher,buffer_scene,vertices,indices));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update box bounds |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXBox::Update(const DXVector3 &from,const DXVector3 &to)
|
||||
{
|
||||
//---
|
||||
DXVertex vertices[];
|
||||
uint indices[];
|
||||
//--- prepare box vertices and indices
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
if(!DXComputeBox(from,to,vertices,indices))
|
||||
return(false);
|
||||
for(int i=0; i<ArraySize(vertices); i++)
|
||||
vertices[i].vcolor=white;
|
||||
//--- update mesh vertices, indices are the same
|
||||
return(CDXMesh::VerticesSet(vertices));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,92 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXVertexBuffer.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
#include "DXHandle.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| DX vertex buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXVertexBuffer : public CDXHandleShared
|
||||
{
|
||||
public:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
virtual ~CDXVertexBuffer(void)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create vertex buffer in specified context |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TVertex>
|
||||
bool Create(int context_handle,const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
Shutdown();
|
||||
m_context=context_handle;
|
||||
m_handle=DXBufferCreate(m_context,DX_BUFFER_VERTEX,vertices,start,count);
|
||||
return(m_handle!=INVALID_HANDLE);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Render |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Render(uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
return(DXBufferSet(m_context,m_handle,start,count));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Shutdown |
|
||||
//+------------------------------------------------------------------+
|
||||
void Shutdown(void)
|
||||
{
|
||||
//--- relase handle
|
||||
if(m_handle!=INVALID_HANDLE)
|
||||
DXRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| DX index buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXIndexBuffer : public CDXHandleShared
|
||||
{
|
||||
public:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
virtual ~CDXIndexBuffer(void)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create index buffer in specified context |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Create(int context_handle,const uint &indices[],uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
Shutdown();
|
||||
m_context=context_handle;
|
||||
m_handle=DXBufferCreate(m_context,DX_BUFFER_INDEX,indices,start,count);
|
||||
return(m_handle!=INVALID_HANDLE);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Render |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Render(uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
return(DXBufferSet(m_context,m_handle,start,count));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Shutdown |
|
||||
//+------------------------------------------------------------------+
|
||||
void Shutdown(void)
|
||||
{
|
||||
//--- relase handle
|
||||
if(m_handle!=INVALID_HANDLE)
|
||||
DXRelease(m_handle);
|
||||
m_handle=INVALID_HANDLE;
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,373 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXDispatcher.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
//---
|
||||
#include "DXObjectBase.mqh"
|
||||
#include "DXData.mqh"
|
||||
#include "DXBuffers.mqh"
|
||||
#include "DXInput.mqh"
|
||||
#include "DXTexture.mqh"
|
||||
#include "DXShader.mqh"
|
||||
//--- default shaders
|
||||
#resource "Shaders/DefaultShaderVertex.hlsl" as string ExtDefaultShaderVertex;
|
||||
#resource "Shaders/DefaultShaderPixel.hlsl" as string ExtDefaultShaderPixel;
|
||||
//+------------------------------------------------------------------+
|
||||
//| DX dispatcher which holds all resources |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXDispatcher : public CDXObjectBase
|
||||
{
|
||||
protected:
|
||||
CDXObjectBase m_dx_resources; // DX resources list (Textures, Shaders, etc.)
|
||||
//--- default shaders
|
||||
CDXShader* m_default_vs;
|
||||
CDXShader* m_default_ps;
|
||||
|
||||
public:
|
||||
CDXDispatcher(void);
|
||||
~CDXDispatcher(void);
|
||||
//--- create/destroy
|
||||
bool Create(int context);
|
||||
void Destroy(void);
|
||||
//--- check resources
|
||||
void Check(void);
|
||||
//--- get DX Context Handle
|
||||
int DXContext(void) const { return(m_context); }
|
||||
//--- create shaders
|
||||
CDXShader* ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type);
|
||||
CDXShader* ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point);
|
||||
CDXShader* ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point);
|
||||
//--- create buffers
|
||||
template<typename TVertex>
|
||||
CDXVertexBuffer* VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY);
|
||||
CDXIndexBuffer* IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY);
|
||||
//--- create shader inputs
|
||||
template<typename TInput>
|
||||
CDXInput* InputCreate(void);
|
||||
CDXTexture* TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);
|
||||
CDXTexture* TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);
|
||||
|
||||
private:
|
||||
//--- add resource to list
|
||||
bool ResourceAdd(CDXObjectBase *resource);
|
||||
//--- check resources
|
||||
void ResourcesCheck(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXDispatcher::CDXDispatcher(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXDispatcher::~CDXDispatcher(void)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXDispatcher::Create(int context)
|
||||
{
|
||||
//--- check if context already exist
|
||||
if(m_context!=INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- save context
|
||||
m_context=context;
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destroy |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXDispatcher::Destroy(void)
|
||||
{
|
||||
//--- release default shaders
|
||||
if(m_default_ps)
|
||||
{
|
||||
m_default_ps.Release();
|
||||
m_default_ps=NULL;
|
||||
}
|
||||
if(m_default_vs)
|
||||
{
|
||||
m_default_vs.Release();
|
||||
m_default_vs=NULL;
|
||||
}
|
||||
//--- release and delete all DX resources
|
||||
while(m_dx_resources.Next())
|
||||
{
|
||||
CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next();
|
||||
resource.Release();
|
||||
}
|
||||
//--- forget context
|
||||
m_context=INVALID_HANDLE;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check resources |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXDispatcher::Check(void)
|
||||
{
|
||||
//---
|
||||
CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next();
|
||||
//--- release and delete all DX resources
|
||||
while(CheckPointer(resource)!=POINTER_INVALID)
|
||||
{
|
||||
CDXHandleShared* next=(CDXHandleShared*)resource.Next();
|
||||
//--- if references count 1 or less, then only we hold the resource
|
||||
if(resource.References()<=1)
|
||||
resource.Release();
|
||||
//---
|
||||
resource=next;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create default shader of specified type |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXShader* CDXDispatcher::ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type)
|
||||
{
|
||||
switch(shader_type)
|
||||
{
|
||||
//--- default pixel shader
|
||||
case DX_SHADER_PIXEL:
|
||||
{
|
||||
if(m_default_ps==NULL)
|
||||
m_default_ps=ShaderCreateFromSource(DX_SHADER_PIXEL,ExtDefaultShaderPixel,"PSMain");
|
||||
return(m_default_ps);
|
||||
}
|
||||
//--- default vertex shader
|
||||
case DX_SHADER_VERTEX:
|
||||
{
|
||||
if(m_default_vs==NULL)
|
||||
{
|
||||
m_default_vs=ShaderCreateFromSource(DX_SHADER_VERTEX,ExtDefaultShaderVertex,"VSMain");
|
||||
if(m_default_vs && !m_default_vs.LayoutSet<DXVertex>())
|
||||
{
|
||||
m_default_vs.Release();
|
||||
m_default_vs=NULL;
|
||||
}
|
||||
}
|
||||
return(m_default_vs);
|
||||
}
|
||||
}
|
||||
//--- return result
|
||||
return(NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create new shader of specified type from file |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXShader* CDXDispatcher::ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point)
|
||||
{
|
||||
//--- open source file
|
||||
int file=FileOpen(path,FILE_READ);
|
||||
if(file==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- check file size
|
||||
uint size=(uint)FileSize(file);
|
||||
FileClose(file);
|
||||
if(size>16*1024*1024)
|
||||
return(NULL);
|
||||
//--- prepare buffer
|
||||
char buffer[];
|
||||
ArrayResize(buffer,size);
|
||||
//--- read file into buffer
|
||||
int read=(int)FileLoad(path,buffer);
|
||||
if(read<=0)
|
||||
return(NULL);
|
||||
//--- convert vuffer to string
|
||||
string source=CharArrayToString(buffer,0,WHOLE_ARRAY,CP_UTF8);
|
||||
//--- add shader by source
|
||||
return(ShaderCreateFromSource(shader_type,source,entry_point));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create new shader of specified type from source code |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXShader* CDXDispatcher::ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new shader
|
||||
CDXShader* shader=new CDXShader();
|
||||
if(shader==NULL)
|
||||
return(NULL);
|
||||
//--- create shader
|
||||
if(!shader.Create(m_context,shader_type,source,entry_point))
|
||||
{
|
||||
shader.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add shader to resources list
|
||||
if(!ResourceAdd(shader))
|
||||
{
|
||||
shader.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return shader
|
||||
return(shader);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create vertex buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TVertex>
|
||||
CDXVertexBuffer* CDXDispatcher::VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new buffer
|
||||
CDXVertexBuffer* buffer=new CDXVertexBuffer();
|
||||
if(buffer==NULL)
|
||||
return(NULL);
|
||||
//--- create buffer
|
||||
if(!buffer.Create(m_context,vertices,start,count))
|
||||
{
|
||||
buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add buffer to resources list
|
||||
if(!ResourceAdd(buffer))
|
||||
{
|
||||
buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return buffer
|
||||
return(buffer);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create vertex buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXIndexBuffer* CDXDispatcher::IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new buffer
|
||||
CDXIndexBuffer* buffer=new CDXIndexBuffer();
|
||||
if(buffer==NULL)
|
||||
return(NULL);
|
||||
//--- create buffer
|
||||
if(!buffer.Create(m_context,indicies,start,count))
|
||||
{
|
||||
buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add buffer to resources list
|
||||
if(!ResourceAdd(buffer))
|
||||
{
|
||||
buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return input buffer
|
||||
return(buffer);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create shader input buffer |
|
||||
//+------------------------------------------------------------------+
|
||||
template<typename TInput>
|
||||
CDXInput* CDXDispatcher::InputCreate(void)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new input buffer
|
||||
CDXInput* input_buffer=new CDXInput();
|
||||
if(input_buffer==NULL)
|
||||
return(NULL);
|
||||
//--- create buffer
|
||||
if(!input_buffer.Create<TInput>(m_context))
|
||||
{
|
||||
input_buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add buffer to resources list
|
||||
if(!ResourceAdd(input_buffer))
|
||||
{
|
||||
input_buffer.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return shader
|
||||
return(input_buffer);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create texture from bitmap file |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXTexture* CDXDispatcher::TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new texture
|
||||
CDXTexture* texture=new CDXTexture();
|
||||
if(texture==NULL)
|
||||
return(NULL);
|
||||
//--- create texture
|
||||
if(!texture.Create(m_context,path,data_x,data_y,data_width,data_height))
|
||||
{
|
||||
texture.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add texture to resources list
|
||||
if(!ResourceAdd(texture))
|
||||
{
|
||||
texture.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return shader
|
||||
return(texture);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create texture from raw data, only 32-bit pixel formats supported|
|
||||
//+------------------------------------------------------------------+
|
||||
CDXTexture* CDXDispatcher::TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||||
{
|
||||
//--- check context
|
||||
if(m_context==INVALID_HANDLE)
|
||||
return(NULL);
|
||||
//--- allocate new texture
|
||||
CDXTexture* texture=new CDXTexture();
|
||||
if(texture==NULL)
|
||||
return(NULL);
|
||||
//--- create texture
|
||||
if(!texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height))
|
||||
{
|
||||
texture.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- add texture to resources list
|
||||
if(!ResourceAdd(texture))
|
||||
{
|
||||
texture.Release();
|
||||
return(NULL);
|
||||
}
|
||||
//--- return shader
|
||||
return(texture);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add DX resource |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXDispatcher::ResourceAdd(CDXObjectBase *resource)
|
||||
{
|
||||
//--- add resource
|
||||
if(!CheckPointer(resource))
|
||||
return(false);
|
||||
//---
|
||||
CDXObjectBase *last=&m_dx_resources;
|
||||
while(CheckPointer(last.Next())!=POINTER_INVALID)
|
||||
{
|
||||
if(last==resource)
|
||||
return(false);
|
||||
//---
|
||||
last=last.Next();
|
||||
}
|
||||
//---
|
||||
resource.Next(NULL);
|
||||
resource.Prev(last);
|
||||
last.Next(resource);
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,375 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXMesh.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
#include "DXObject.mqh"
|
||||
#include "DXDispatcher.mqh"
|
||||
#include "DXData.mqh"
|
||||
#include "DXUtils.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| DX simple mesh object with default shader |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXMesh : public CDXObject
|
||||
{
|
||||
protected:
|
||||
//--- DX resources
|
||||
CDXVertexBuffer* m_buffer_vertex;
|
||||
CDXIndexBuffer* m_buffer_index;
|
||||
CDXInput* m_buffer_object;
|
||||
CDXInput* m_buffer_scene;
|
||||
CDXShader* m_shader_vertex;
|
||||
CDXShader* m_shader_pixel;
|
||||
CDXTexture* m_texture;
|
||||
//--- object data
|
||||
DXMatrix m_transform_matrix;
|
||||
DXColor m_diffuse_color;
|
||||
DXColor m_emission_color;
|
||||
DXColor m_specular_color;
|
||||
float m_specular_power;
|
||||
|
||||
ENUM_DX_PRIMITIVE_TOPOLOGY m_topology;
|
||||
|
||||
public:
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDXMesh(void):m_buffer_vertex(NULL),m_buffer_index(NULL),m_buffer_object(NULL),m_buffer_scene(NULL),m_shader_vertex(NULL),m_shader_pixel(NULL),m_topology(WRONG_VALUE)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
~CDXMesh(void)
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create mesh object from vertices and indices list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVertex &vertices[],const uint &indices[],ENUM_DX_PRIMITIVE_TOPOLOGY topology=DX_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
|
||||
{
|
||||
Shutdown();
|
||||
//--- check data
|
||||
if(buffer_scene==NULL || buffer_scene.Handle()==INVALID_HANDLE ||
|
||||
ArraySize(vertices)<1 || ArraySize(indices)<1)
|
||||
return(false);
|
||||
//--- update context
|
||||
m_context=dispatcher.DXContext();
|
||||
//--- initialize default parameters
|
||||
DXMatrixIdentity(m_transform_matrix);
|
||||
m_diffuse_color =DXColor(1.0,1.0,1.0,1.0);
|
||||
m_emission_color=DXColor(0.0,0.0,0.0,0.0);
|
||||
m_specular_color=DXColor(0.0,0.0,0.0,0.0);
|
||||
m_specular_power=16.0f;
|
||||
//--- create object input
|
||||
m_buffer_object=dispatcher.InputCreate<DXInputObject>();
|
||||
if(m_buffer_object!=NULL)
|
||||
{
|
||||
m_buffer_object.AddRef();
|
||||
//--- use default vertex shader
|
||||
m_shader_vertex=dispatcher.ShaderCreateDefault(DX_SHADER_VERTEX);
|
||||
if(m_shader_vertex!=NULL)
|
||||
{
|
||||
m_shader_vertex.AddRef();
|
||||
//--- use default pixel shader
|
||||
m_shader_pixel=dispatcher.ShaderCreateDefault(DX_SHADER_PIXEL);
|
||||
if(m_shader_pixel!=NULL)
|
||||
{
|
||||
m_shader_pixel.AddRef();
|
||||
//--- create vertex buffer
|
||||
m_buffer_vertex=dispatcher.VertexBufferCreate(vertices);
|
||||
if(m_buffer_vertex!=NULL)
|
||||
{
|
||||
m_buffer_vertex.AddRef();
|
||||
//--- create index buffer
|
||||
m_buffer_index=dispatcher.IndexBufferCreate(indices);
|
||||
if(m_buffer_index!=NULL)
|
||||
m_buffer_index.AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- set object buffer to shaders
|
||||
if(m_buffer_object==NULL || m_shader_vertex==NULL || m_shader_pixel==NULL || m_buffer_vertex==NULL || m_buffer_index==NULL)
|
||||
{
|
||||
Shutdown();
|
||||
return(false);
|
||||
}
|
||||
//--- save scene buffer
|
||||
m_buffer_scene=buffer_scene;
|
||||
m_buffer_scene.AddRef();
|
||||
//--- save topology
|
||||
m_topology=topology;
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create mesh object from OBJ mesh file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,string obj_path,float scale=1.0f,bool inverse_winding=false)
|
||||
{
|
||||
DXVertex vertices[];
|
||||
uint indices[];
|
||||
//--- load model
|
||||
if(!DXLoadObjModel(obj_path,vertices,indices,scale))
|
||||
return(false);
|
||||
//--- set white vertices color
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
int count=ArraySize(vertices);
|
||||
for(int i=0; i<count; i++)
|
||||
vertices[i].vcolor=white;
|
||||
//--- inverse winding
|
||||
if(inverse_winding)
|
||||
DXInverseWinding(vertices,indices);
|
||||
//--- create mesh
|
||||
return(Create(dispatcher,buffer_scene,vertices,indices));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update vertices |
|
||||
//+------------------------------------------------------------------+
|
||||
bool VerticesSet(const DXVertex &vertices[])
|
||||
{
|
||||
//--- check size
|
||||
if(ArraySize(vertices)<1)
|
||||
return(false);
|
||||
//--- create new vertex buffer
|
||||
if(!m_buffer_vertex.Create(m_context,vertices))
|
||||
{
|
||||
Shutdown();
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update indices |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IndicesSet(const uint &indices[])
|
||||
{
|
||||
//--- check size
|
||||
if(ArraySize(indices)<1)
|
||||
return(false);
|
||||
//--- create new index buffer
|
||||
if(!m_buffer_index.Create(m_context,indices))
|
||||
{
|
||||
Shutdown();
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update indices |
|
||||
//+------------------------------------------------------------------+
|
||||
bool TopologySet(ENUM_DX_PRIMITIVE_TOPOLOGY topology)
|
||||
{
|
||||
m_topology=topology;
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get transform matrix |
|
||||
//+------------------------------------------------------------------+
|
||||
void TransformMatrixGet(DXMatrix &mat) const
|
||||
{
|
||||
mat=m_transform_matrix;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set transform matrix |
|
||||
//+------------------------------------------------------------------+
|
||||
void TransformMatrixSet(const DXMatrix &mat)
|
||||
{
|
||||
m_transform_matrix=mat;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get diffuse color |
|
||||
//+------------------------------------------------------------------+
|
||||
void DiffuseColorGet(DXColor &clr) const
|
||||
{
|
||||
clr=m_diffuse_color;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set diffuse color |
|
||||
//+------------------------------------------------------------------+
|
||||
void DiffuseColorSet(const DXColor &clr)
|
||||
{
|
||||
m_diffuse_color=clr;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get specular color |
|
||||
//+------------------------------------------------------------------+
|
||||
void SpecularColorGet(DXColor &clr) const
|
||||
{
|
||||
clr=m_specular_color;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set specular color |
|
||||
//+------------------------------------------------------------------+
|
||||
void SpecularColorSet(const DXColor &clr)
|
||||
{
|
||||
m_specular_color=clr;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get specular power |
|
||||
//+------------------------------------------------------------------+
|
||||
void SpecularPowerGet(float &power) const
|
||||
{
|
||||
power=m_specular_power;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set specular power |
|
||||
//+------------------------------------------------------------------+
|
||||
void SpecularPowerSet(float power)
|
||||
{
|
||||
m_specular_power=power;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get emission color |
|
||||
//+------------------------------------------------------------------+
|
||||
void EmissionColorGet(DXColor &clr) const
|
||||
{
|
||||
clr=m_emission_color;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set emission color |
|
||||
//+------------------------------------------------------------------+
|
||||
void EmissionColorSet(const DXColor &clr)
|
||||
{
|
||||
m_emission_color=clr;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Render mesh |
|
||||
//+------------------------------------------------------------------+
|
||||
virtual bool Render(void) override
|
||||
{
|
||||
//--- update object buffer
|
||||
DXInputObject input_data;
|
||||
DXMatrixTranspose(input_data.transform,m_transform_matrix);
|
||||
input_data.diffuse_color =m_diffuse_color;
|
||||
input_data.emission_color=m_emission_color;
|
||||
input_data.specular_color=m_specular_color;
|
||||
input_data.specular_power=m_specular_power;
|
||||
//--- clear shader textures
|
||||
m_shader_pixel.TexturesClear();
|
||||
//--- set buffers, shaders, topology and render
|
||||
if(m_buffer_object.InputSet(input_data))
|
||||
if(m_buffer_vertex.Render())
|
||||
if(m_buffer_index.Render())
|
||||
if(m_shader_vertex.InputSet(0,m_buffer_scene) && m_shader_vertex.InputSet(1,m_buffer_object))
|
||||
if(m_shader_pixel.InputSet(0,m_buffer_scene) && m_shader_pixel.InputSet(1,m_buffer_object))
|
||||
if(CheckPointer(m_texture)==POINTER_INVALID || m_shader_pixel.TextureSet(0,m_texture))
|
||||
if(m_shader_vertex.Render())
|
||||
if(m_shader_pixel.Render())
|
||||
if(DXPrimiveTopologySet(m_context,m_topology))
|
||||
return(DXDrawIndexed(m_context));
|
||||
//---
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set texture from image file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool TextureSet(CDXDispatcher &dispatcher,string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||||
{
|
||||
//--- check if texture already exist
|
||||
if(CheckPointer(m_texture)==POINTER_INVALID)
|
||||
{
|
||||
m_texture=dispatcher.TextureCreateFromFile(path,data_x,data_y,data_width,data_height);
|
||||
if(m_texture==NULL)
|
||||
return(false);
|
||||
m_texture.AddRef();
|
||||
return(true);
|
||||
}
|
||||
//--- update texture data
|
||||
if(!m_texture.Create(m_context,path,data_x,data_y,data_width,data_height))
|
||||
{
|
||||
m_texture.Release();
|
||||
m_texture=NULL;
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set texture from image data |
|
||||
//+------------------------------------------------------------------+
|
||||
bool TextureSet(CDXDispatcher &dispatcher,ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||||
{
|
||||
//--- check if texture already exist
|
||||
if(CheckPointer(m_texture)==POINTER_INVALID)
|
||||
{
|
||||
m_texture=dispatcher.TextureCreateFromData(format,width,height,data,data_x,data_y,data_width,data_height);
|
||||
if(m_texture==NULL)
|
||||
return(false);
|
||||
m_texture.AddRef();
|
||||
return(true);
|
||||
}
|
||||
//--- update texture data
|
||||
if(!m_texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height))
|
||||
{
|
||||
m_texture.Release();
|
||||
m_texture=NULL;
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete used texture |
|
||||
//+------------------------------------------------------------------+
|
||||
void TextureDelete()
|
||||
{
|
||||
//--- release texture
|
||||
if(CheckPointer(m_texture)!=POINTER_INVALID)
|
||||
{
|
||||
m_texture.Release();
|
||||
m_texture=NULL;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Shutdown |
|
||||
//+------------------------------------------------------------------+
|
||||
virtual void Shutdown(void)
|
||||
{
|
||||
//--- release all dx resources
|
||||
if(CheckPointer(m_buffer_vertex)!=POINTER_INVALID)
|
||||
{
|
||||
m_buffer_vertex.Release();
|
||||
m_buffer_vertex=NULL;
|
||||
}
|
||||
if(CheckPointer(m_buffer_index)!=POINTER_INVALID)
|
||||
{
|
||||
m_buffer_index.Release();
|
||||
m_buffer_index=NULL;
|
||||
}
|
||||
if(CheckPointer(m_buffer_object)!=POINTER_INVALID)
|
||||
{
|
||||
m_buffer_object.Release();
|
||||
m_buffer_object=NULL;
|
||||
}
|
||||
if(CheckPointer(m_texture)!=POINTER_INVALID)
|
||||
{
|
||||
m_texture.Release();
|
||||
m_texture=NULL;
|
||||
}
|
||||
if(CheckPointer(m_buffer_scene)!=POINTER_INVALID)
|
||||
{
|
||||
m_buffer_scene.Release();
|
||||
m_buffer_scene=NULL;
|
||||
}
|
||||
if(CheckPointer(m_shader_pixel)!=POINTER_INVALID)
|
||||
{
|
||||
m_shader_pixel.Release();
|
||||
m_shader_pixel=NULL;
|
||||
}
|
||||
if(CheckPointer(m_shader_vertex)!=POINTER_INVALID)
|
||||
{
|
||||
m_shader_vertex.Release();
|
||||
m_shader_vertex=NULL;
|
||||
}
|
||||
m_topology =WRONG_VALUE;
|
||||
}
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,162 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXSurface.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
//---
|
||||
#include "DXMesh.mqh"
|
||||
#include "DXMath.mqh"
|
||||
#include "DXUtils.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| 3D Box object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDXSurface : public CDXMesh
|
||||
{
|
||||
public:
|
||||
//--- surface creation flags
|
||||
enum EN_SURFACE_FLAGS
|
||||
{
|
||||
SF_NONE =0x0,
|
||||
SF_TWO_SIDED =0x1,
|
||||
SF_USE_NORMALS =0x2,
|
||||
};
|
||||
//--- surface color scheme
|
||||
enum EN_COLOR_SCHEME
|
||||
{
|
||||
CS_NONE =0,
|
||||
CS_JET =1,
|
||||
CS_COLD_TO_HOT =2,
|
||||
CS_RED_TO_GREEN=3
|
||||
};
|
||||
|
||||
protected:
|
||||
uint m_data_width;
|
||||
uint m_data_height;
|
||||
uint m_flags;
|
||||
EN_COLOR_SCHEME m_color_scheme;
|
||||
|
||||
public:
|
||||
CDXSurface();
|
||||
~CDXSurface();
|
||||
//--- create bon in specified context
|
||||
bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,double &data[],uint m_data_widht,uint m_data_height,float data_range,const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,uint flags=SF_NONE,EN_COLOR_SCHEME color_scheme=CS_NONE);
|
||||
//--- update box
|
||||
bool Update(double &data[],uint m_data_widht,uint m_data_height,float data_range,const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,uint flags=0,EN_COLOR_SCHEME color_scheme=CS_NONE);
|
||||
|
||||
private:
|
||||
//---
|
||||
void PrepareColors(DXVertex &vertices[],const DXVector3 &from,const DXVector3 &to);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXSurface::CDXSurface() : CDXMesh()
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXSurface::~CDXSurface(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create box in specified context |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXSurface::Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,
|
||||
double &data[],uint data_width,uint data_height,float data_range,
|
||||
const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,
|
||||
uint flags=SF_NONE,EN_COLOR_SCHEME color_scheme=CS_NONE)
|
||||
{
|
||||
//--- release previous buffers
|
||||
Shutdown();
|
||||
//--- save parameters
|
||||
m_data_width =data_width;
|
||||
m_data_height =data_height;
|
||||
m_flags =flags;
|
||||
m_color_scheme=color_scheme;
|
||||
//---
|
||||
DXVertex vertices[];
|
||||
uint indices[];
|
||||
//--- prepare surface vertices and indices
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
if(!DXComputeSurface(data,data_width,data_height,data_range,from,to,texture_size,flags&SF_TWO_SIDED,flags&SF_USE_NORMALS,vertices,indices))
|
||||
return(false);
|
||||
//--- calculate colors
|
||||
PrepareColors(vertices,from,to);
|
||||
//--- create mesh
|
||||
return(CDXMesh::Create(dispatcher,buffer_scene,vertices,indices));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update box bounds |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDXSurface::Update(double &data[],uint data_width,uint data_height,float data_range,
|
||||
const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,
|
||||
uint flags=0,EN_COLOR_SCHEME color_scheme=CS_NONE)
|
||||
{
|
||||
//---
|
||||
DXVertex vertices[];
|
||||
uint indices[];
|
||||
//--- prepare surface vertices and indices
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
if(!DXComputeSurface(data,data_width,data_height,data_range,from,to,texture_size,flags&SF_TWO_SIDED,flags&SF_USE_NORMALS,vertices,indices))
|
||||
return(false);
|
||||
//--- calculate colors
|
||||
m_color_scheme=color_scheme;
|
||||
PrepareColors(vertices,from,to);
|
||||
//--- update vertices
|
||||
bool res=CDXMesh::VerticesSet(vertices);
|
||||
//--- do not update indices if vertices relations are the same
|
||||
if(m_data_width!=data_width || m_data_height!=data_height || (m_flags&SF_TWO_SIDED)!=(flags&SF_TWO_SIDED))
|
||||
res=res && CDXMesh::IndicesSet(indices);
|
||||
//--- check result
|
||||
if(!res)
|
||||
{
|
||||
Shutdown();
|
||||
return(false);
|
||||
}
|
||||
//--- save parameters
|
||||
m_data_width =data_width;
|
||||
m_data_height =data_height;
|
||||
m_flags =flags;
|
||||
//--- success
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update box bounds |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDXSurface::PrepareColors(DXVertex &vertices[],const DXVector3 &from,const DXVector3 &to)
|
||||
{
|
||||
uint count=ArraySize(vertices);
|
||||
float scale=1.0f/(fmax(FLT_EPSILON,to.y-from.y));
|
||||
switch(m_color_scheme)
|
||||
{
|
||||
case CS_JET:
|
||||
{
|
||||
for(uint i=0; i<count; i++)
|
||||
DXComputeColorJet((vertices[i].position.y-from.y)*scale,vertices[i].vcolor);
|
||||
break;
|
||||
}
|
||||
case CS_COLD_TO_HOT:
|
||||
{
|
||||
for(uint i=0; i<count; i++)
|
||||
DXComputeColorColdToHot((vertices[i].position.y-from.y)*scale,vertices[i].vcolor);
|
||||
break;
|
||||
}
|
||||
case CS_RED_TO_GREEN:
|
||||
{
|
||||
for(uint i=0; i<count; i++)
|
||||
DXComputeColorRedToGreen((vertices[i].position.y-from.y)*scale,vertices[i].vcolor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f);
|
||||
for(uint i=0; i<count; i++)
|
||||
vertices[i].vcolor=white;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,942 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DXUtils.mqh |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2019, MetaQuotes Software Corp."
|
||||
#property link "https://www.mql5.com"
|
||||
//---
|
||||
#include "DXMath.mqh"
|
||||
#include "DXData.mqh"
|
||||
//--- data types in Wavefront OBJ file format
|
||||
#define OBJ_DATA_UNKNOWN 0
|
||||
#define OBJ_DATA_V 1
|
||||
#define OBJ_DATA_VT 2
|
||||
#define OBJ_DATA_VN 3
|
||||
#define OBJ_DATA_F 4
|
||||
//+------------------------------------------------------------------+
|
||||
//| OBJFaceType |
|
||||
//+------------------------------------------------------------------+
|
||||
struct OBJFaceType
|
||||
{
|
||||
int total;
|
||||
int v[4];
|
||||
int t[4];
|
||||
int n[4];
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Transforms right to left hand system, or backward |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 normal and DXVector2 tcoord members |
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
void DXInverseWinding(TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
//--- proccess vertices
|
||||
uint count=ArraySize(vertices);
|
||||
for(uint i=0; i<count; i++)
|
||||
{
|
||||
//--- invert normals
|
||||
vertices[i].normal.x=-vertices[i].normal.x;
|
||||
vertices[i].normal.y=-vertices[i].normal.y;
|
||||
vertices[i].normal.z=-vertices[i].normal.z;
|
||||
//--- flip texture coordinates
|
||||
vertices[i].tcoord.x=1.0f-vertices[i].tcoord.x;
|
||||
}
|
||||
//--- change indices order
|
||||
count=ArraySize(indices);
|
||||
for(uint i=2; i<count; i+=3)
|
||||
{
|
||||
uint tmp =indices[i];
|
||||
indices[i] =indices[i-2];
|
||||
indices[i-2]=tmp;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Load static 3D models from Maya 2011 |
|
||||
//| https://en.wikibooks.org/wiki/DirectX/10.0/Direct3D/Loading_Maya |
|
||||
//+------------------------------------------------------------------+
|
||||
bool DXLoadObjData(const string filename,DXVector4 &v_positions[],DXVector2 &v_tcoords[],DXVector4 &v_normals[],OBJFaceType &faces[],bool show_debug=false)
|
||||
{
|
||||
int total_positions=0;
|
||||
int total_tcoords=0;
|
||||
int total_normals=0;
|
||||
int total_faces=0;
|
||||
//---
|
||||
ResetLastError();
|
||||
int file_handle=FileOpen(filename,FILE_READ|FILE_TXT|FILE_ANSI);
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
{
|
||||
printf("FileOpen %s failed, error code=%d",filename,GetLastError());
|
||||
return(false);
|
||||
}
|
||||
int str_length=0;
|
||||
string str="";
|
||||
int total_lines=0;
|
||||
string str_parsed[];
|
||||
string str_parsed_faces[];
|
||||
//---
|
||||
while(!FileIsEnding(file_handle))
|
||||
{
|
||||
str=FileReadString(file_handle,str_length);
|
||||
total_lines++;
|
||||
//--- replace two spaces to one
|
||||
StringReplace(str,"\t"," ");
|
||||
while(StringFind(str," ",0)!=-1)
|
||||
StringReplace(str," "," ");
|
||||
//--- split string to tokens
|
||||
int total_items=StringSplit(str,' ',str_parsed);
|
||||
if(total_items<1)
|
||||
continue;
|
||||
//--- when examining the file you can ignore every line unless it starts with a "V", "VT", "VN", or "F".
|
||||
//--- the extra information in the file will not be needed for converting .obj to our file format.
|
||||
StringToUpper(str_parsed[0]);
|
||||
//--- parse data type
|
||||
int data_type=OBJ_DATA_UNKNOWN;
|
||||
if(str_parsed[0]=="V")
|
||||
data_type=OBJ_DATA_V;
|
||||
else
|
||||
if(str_parsed[0]=="VT")
|
||||
data_type=OBJ_DATA_VT;
|
||||
else
|
||||
if(str_parsed[0]=="VN")
|
||||
data_type=OBJ_DATA_VN;
|
||||
else
|
||||
if(str_parsed[0]=="F")
|
||||
data_type=OBJ_DATA_F;
|
||||
//--- proceed data type
|
||||
switch(data_type)
|
||||
{
|
||||
//--- 1. "V" lines are for the vertices, each is listed in X, Y, Z float format.
|
||||
case OBJ_DATA_V:
|
||||
{
|
||||
total_positions++;
|
||||
if(total_items<4)
|
||||
{
|
||||
PrintFormat("obj data error at line=%d: %s",total_lines,str);
|
||||
FileClose(file_handle);
|
||||
return(false);
|
||||
}
|
||||
ArrayResize(v_positions,total_positions,total_positions+1000);
|
||||
int idx=total_positions-1;
|
||||
v_positions[idx].x=(float)StringToDouble(str_parsed[1]);
|
||||
v_positions[idx].y=(float)StringToDouble(str_parsed[2]);
|
||||
v_positions[idx].z=(float)StringToDouble(str_parsed[3]);
|
||||
v_positions[idx].w=1.0f;
|
||||
//--- debug message
|
||||
if(show_debug)
|
||||
printf("posiiton %d: %f %f %f",idx,v_positions[idx].x,v_positions[idx].y,v_positions[idx].z);
|
||||
//---
|
||||
break;
|
||||
}
|
||||
//--- 2. "VT" lines are for the texture coordinates, they are listed in TU, TV float format.
|
||||
case OBJ_DATA_VT:
|
||||
{
|
||||
total_tcoords++;
|
||||
if(total_items<3)
|
||||
{
|
||||
PrintFormat("obj data error at line=%d: %s",total_lines,str);
|
||||
FileClose(file_handle);
|
||||
return(false);
|
||||
}
|
||||
ArrayResize(v_tcoords,total_tcoords,total_tcoords+1000);
|
||||
int idx=total_tcoords-1;
|
||||
v_tcoords[idx].x=(float)StringToDouble(str_parsed[1]);
|
||||
v_tcoords[idx].y=(float)StringToDouble(str_parsed[2]);
|
||||
//--- debug message
|
||||
if(show_debug)
|
||||
printf("tcoord %d: %f %f",idx,v_tcoords[idx].x,v_tcoords[idx].y);
|
||||
//---
|
||||
break;
|
||||
}
|
||||
//--- 3. "VN" lines are for the normal vectors, most of them are duplicated again
|
||||
//--- since it records them for every vertex in every triangle in the model, they are listed in NX, NY, NZ float format.
|
||||
case OBJ_DATA_VN:
|
||||
{
|
||||
total_normals++;
|
||||
if(total_items<4)
|
||||
{
|
||||
PrintFormat("obj data error at line=%d: %s",total_lines,str);
|
||||
FileClose(file_handle);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
ArrayResize(v_normals,total_normals,total_normals+1000);
|
||||
int idx=total_normals-1;
|
||||
v_normals[idx].x=(float)StringToDouble(str_parsed[1]);
|
||||
v_normals[idx].y=(float)StringToDouble(str_parsed[2]);
|
||||
v_normals[idx].z=(float)StringToDouble(str_parsed[3]);
|
||||
v_normals[idx].w=0.0f;
|
||||
//--- debug message
|
||||
if(show_debug)
|
||||
printf("normal %d: %f %f %f",idx,v_normals[idx].x,v_normals[idx].y,v_normals[idx].z);
|
||||
//---
|
||||
break;
|
||||
}
|
||||
//--- 4. "F" lines are for each face in the model.
|
||||
//--- the values listed are indexes into the vertices, texture coordinates, and normal vectors. The format of each face is:
|
||||
//--- f Vertex1/Texture1/Normal1 Vertex2/Texture2/Normal2 Vertex3/Texture3/Normal3
|
||||
//--- so a line that says "f 3/13/5 4/14/6 5/15/7" then translates to "Vertex3/Texture13/Normal5 Vertex4/Texture14/Normal6 Vertex5/Texture15/Normal7".
|
||||
case OBJ_DATA_F:
|
||||
{
|
||||
total_faces++;
|
||||
//--- check size
|
||||
if(total_items<4)
|
||||
{
|
||||
PrintFormat("obj data error at line=%d: %s",total_lines,str);
|
||||
FileClose(file_handle);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
ArrayResize(faces,total_faces,total_faces+1000);
|
||||
int idx=total_faces-1;
|
||||
//--- clear all face indices
|
||||
for(uint i=0; i<4; i++)
|
||||
{
|
||||
faces[idx].v[0]=0;
|
||||
faces[idx].t[0]=0;
|
||||
faces[idx].n[0]=0;
|
||||
}
|
||||
//--- read indices
|
||||
faces[idx].total=MathMin(total_items-1,4);
|
||||
for(int i=0; i<faces[idx].total; i++)
|
||||
{
|
||||
int elements=StringSplit(str_parsed[i+1],'/',str_parsed_faces);
|
||||
if(elements>0)
|
||||
faces[idx].v[i]=(int)StringToInteger(str_parsed_faces[0]);
|
||||
if(elements>1)
|
||||
faces[idx].t[i]=(int)StringToInteger(str_parsed_faces[1]);
|
||||
if(elements>2)
|
||||
faces[idx].n[i]=(int)StringToInteger(str_parsed_faces[2]);
|
||||
}
|
||||
//--- debug message
|
||||
if(show_debug)
|
||||
printf("%face d: %d vertex(%d,%d,%d,%d) texture(%d,%d,%d,%d) normal(%d,%d,%d,%d)",idx+1,
|
||||
faces[idx].v[0],faces[idx].v[1],faces[idx].v[2],faces[idx].v[3],
|
||||
faces[idx].t[0],faces[idx].t[1],faces[idx].t[2],faces[idx].t[3],
|
||||
faces[idx].n[0],faces[idx].n[1],faces[idx].n[2],faces[idx].n[3]);
|
||||
//---
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- close the file
|
||||
FileClose(file_handle);
|
||||
//---
|
||||
if(show_debug)
|
||||
{
|
||||
printf("File %s loaded successfully. Total lines: %d",filename,total_lines);
|
||||
printf("total v_positions=%d",total_positions);
|
||||
printf("total v_normals=%d",total_normals);
|
||||
printf("total v_tcoords=%d",total_tcoords);
|
||||
printf("total faces=%d",total_faces);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Load static 3D models from Maya 2011 |
|
||||
//| https://en.wikibooks.org/wiki/DirectX/10.0/Direct3D/Loading_Maya |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, normal and DXVector2 tcoord members |
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXLoadObjModel(const string filename,TVertex &vertices[],uint &indices[],float scale=1.0f)
|
||||
{
|
||||
//--- intermediate data arrays
|
||||
DXVector4 v_positions[];
|
||||
DXVector2 v_tcoords[];
|
||||
DXVector4 v_normals[];
|
||||
OBJFaceType faces[];
|
||||
//--- load data
|
||||
if(!DXLoadObjData(filename,v_positions,v_tcoords,v_normals,faces,false))
|
||||
{
|
||||
printf("Error loading model data from %s",filename);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
int total_v_positions=ArraySize(v_positions);
|
||||
int total_v_tcoords =ArraySize(v_tcoords);
|
||||
int total_v_normals =ArraySize(v_normals);
|
||||
int total_faces =ArraySize(faces);
|
||||
//--- check faces
|
||||
if(total_faces==0)
|
||||
{
|
||||
printf("No model data.");
|
||||
return(false);
|
||||
}
|
||||
//--- check consistency of the indices
|
||||
int vertices_count=0;
|
||||
int indices_count =0;
|
||||
bool split_vertices=false;
|
||||
for(int i=0; i<total_faces; i++)
|
||||
{
|
||||
//--- each face have to be 3 or 4 sided
|
||||
if(faces[i].total<3 || faces[i].total>4)
|
||||
{
|
||||
printf("Error in %d face, face vertices count is %d",i,faces[i].total);
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
for(int j=0; j<faces[i].total; j++)
|
||||
{
|
||||
if(faces[i].v[j]<=0 || faces[i].v[j]>total_v_positions)
|
||||
{
|
||||
printf("Error in %d face, %d vertext index is %d. Total posiitons=%d",i,j,faces[i].v[j],total_v_positions);
|
||||
return(false);
|
||||
}
|
||||
if(total_v_tcoords>0)
|
||||
{
|
||||
if(faces[i].t[j]<=0 || faces[i].t[j]>total_v_tcoords)
|
||||
{
|
||||
printf("Error in %d face, %d tcoord index is %d. Total tcoords=%d",i,j,faces[i].v[j],total_v_positions);
|
||||
return(false);
|
||||
}
|
||||
if(faces[i].t[j]!=faces[i].v[j])
|
||||
split_vertices=true;
|
||||
}
|
||||
if(total_v_normals>0)
|
||||
{
|
||||
if(faces[i].n[j]<=0 || faces[i].n[j]>total_v_normals)
|
||||
{
|
||||
printf("Error in %d face, %d normal index is %d. Total normals=%d",i,j,faces[i].v[j],total_v_positions);
|
||||
return(false);
|
||||
}
|
||||
if(faces[i].n[j]!=faces[i].v[j])
|
||||
split_vertices=true;
|
||||
}
|
||||
}
|
||||
//--- calc counts
|
||||
vertices_count+=faces[i].total;
|
||||
if(faces[i].total<4)
|
||||
indices_count+=3;
|
||||
else
|
||||
indices_count+=6;
|
||||
}
|
||||
printf("Data consistency checked.");
|
||||
//--- prepare arrays
|
||||
if(!split_vertices)
|
||||
vertices_count=total_v_positions;
|
||||
ArrayResize(vertices,vertices_count);
|
||||
ArrayResize(indices, indices_count);
|
||||
int v_idx=0,i_idx=0;
|
||||
for(int i=0; i<total_faces; i++)
|
||||
{
|
||||
for(int j=0; j<faces[i].total; j++)
|
||||
{
|
||||
if(!split_vertices)
|
||||
v_idx=faces[i].v[j]-1;
|
||||
//--- posiitons
|
||||
vertices[v_idx].position.x=v_positions[faces[i].v[j]-1].x*scale;
|
||||
vertices[v_idx].position.y=v_positions[faces[i].v[j]-1].y*scale;
|
||||
vertices[v_idx].position.z=v_positions[faces[i].v[j]-1].z*scale;
|
||||
vertices[v_idx].position.w=1.0f;
|
||||
//--- normal
|
||||
if(faces[i].n[j])
|
||||
DXVec4Normalize(vertices[v_idx].normal,v_normals[faces[i].n[j]-1]);
|
||||
//--- tcoord
|
||||
if(faces[i].t[j])
|
||||
vertices[v_idx].tcoord=v_tcoords[faces[i].t[j]-1];
|
||||
//--- indices
|
||||
indices[i_idx++]=v_idx;
|
||||
//--- increment indx
|
||||
if(split_vertices)
|
||||
v_idx++;
|
||||
}
|
||||
//--- the end of second triangle in 4-sided face
|
||||
if(faces[i].total==4)
|
||||
{
|
||||
indices[i_idx]=indices[i_idx-4];
|
||||
i_idx++;
|
||||
indices[i_idx]=indices[i_idx-3];
|
||||
i_idx++;
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Box |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeBox(const DXVector3 &from,const DXVector3 &to,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
//--- prepare arrays
|
||||
const int faces=6;
|
||||
if(ArrayResize(vertices,4*faces)!=4*faces)
|
||||
return(false);
|
||||
//--- set indices
|
||||
uint ind[]= {0,1,2, 2,3,0, 4,5,6, 6,7,4, 8,9,10, 10,11,8, 12,13,14, 14,15,12, 16,17,18, 18,19,16, 20,21,22, 22,23,20};
|
||||
ArrayResize(indices,0);
|
||||
if(ArrayCopy(indices,ind)!=ArraySize(ind))
|
||||
return(false);
|
||||
//--- prepare boundaries
|
||||
float left=from.x,right=to.x,bottom=from.y,top=to.y,near=from.z,far=to.z;
|
||||
if(from.x>to.x)
|
||||
{
|
||||
right=from.x;
|
||||
left= to.x;
|
||||
}
|
||||
if(from.y>to.y)
|
||||
{
|
||||
top= from.y;
|
||||
bottom=to.y;
|
||||
}
|
||||
if(from.z>to.z)
|
||||
{
|
||||
far=from.z;
|
||||
near=to.z;
|
||||
}
|
||||
//--- left face
|
||||
vertices[0].position=DXVector4(left,top, far, 1.0);
|
||||
vertices[1].position=DXVector4(left,top, near,1.0);
|
||||
vertices[2].position=DXVector4(left,bottom,near,1.0);
|
||||
vertices[3].position=DXVector4(left,bottom,far, 1.0);
|
||||
for(int i=0; i<4; i++)
|
||||
vertices[i].normal=DXVector4(-1.0,0.0,0.0,0.0);
|
||||
//--- right face
|
||||
vertices[4].position=DXVector4(right,top, near,1.0);
|
||||
vertices[5].position=DXVector4(right,top, far, 1.0);
|
||||
vertices[6].position=DXVector4(right,bottom,far, 1.0);
|
||||
vertices[7].position=DXVector4(right,bottom,near,1.0);
|
||||
for(int i=4; i<8; i++)
|
||||
vertices[i].normal=DXVector4(1.0,0.0,0.0,0.0);
|
||||
//--- front face
|
||||
vertices[8].position =DXVector4(left, top, near,1.0);
|
||||
vertices[9].position =DXVector4(right,top, near,1.0);
|
||||
vertices[10].position=DXVector4(right,bottom,near,1.0);
|
||||
vertices[11].position=DXVector4(left, bottom,near,1.0);
|
||||
for(int i=8; i<12; i++)
|
||||
vertices[i].normal=DXVector4(0.0,0.0,-1.0,0.0);
|
||||
//--- back face
|
||||
vertices[12].position=DXVector4(right,top, far,1.0);
|
||||
vertices[13].position=DXVector4(left, top, far,1.0);
|
||||
vertices[14].position=DXVector4(left, bottom,far,1.0);
|
||||
vertices[15].position=DXVector4(right,bottom,far,1.0);
|
||||
for(int i=12; i<16; i++)
|
||||
vertices[i].normal=DXVector4(0.0,0.0,1.0,0.0);
|
||||
//--- top face
|
||||
vertices[16].position=DXVector4(left, top,far, 1.0);
|
||||
vertices[17].position=DXVector4(right,top,far, 1.0);
|
||||
vertices[18].position=DXVector4(right,top,near,1.0);
|
||||
vertices[19].position=DXVector4(left, top,near,1.0);
|
||||
for(int i=16; i<20; i++)
|
||||
vertices[i].normal=DXVector4(0.0,1.0,0.0,0.0);
|
||||
//--- bottom face
|
||||
vertices[20].position=DXVector4(left, bottom,near,1.0);
|
||||
vertices[21].position=DXVector4(right,bottom,near,1.0);
|
||||
vertices[22].position=DXVector4(right,bottom,far, 1.0);
|
||||
vertices[23].position=DXVector4(left, bottom,far, 1.0);
|
||||
for(int i=20; i<24; i++)
|
||||
vertices[i].normal=DXVector4(0.0,-1.0,0.0,0.0);
|
||||
//--- texture coordinates
|
||||
for(int i=0; i<faces; i++)
|
||||
{
|
||||
vertices[i*4+0].tcoord=DXVector2(0.0f,0.0f);
|
||||
vertices[i*4+1].tcoord=DXVector2(1.0f,0.0f);
|
||||
vertices[i*4+2].tcoord=DXVector2(1.0f,1.0f);
|
||||
vertices[i*4+3].tcoord=DXVector2(0.0f,1.0f);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sphere |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeSphere(float radius,uint tessellation,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
if(tessellation<3)
|
||||
tessellation=3;
|
||||
uint segments_y =tessellation;
|
||||
uint segments_xz=tessellation*2;
|
||||
//--- prepare arrays
|
||||
uint count=(segments_y+1)*(segments_xz+1);
|
||||
if(ArrayResize(vertices,count)!=count)
|
||||
return(false);
|
||||
count=6*segments_y*(segments_xz);
|
||||
if(ArrayResize(indices,count)!=count)
|
||||
return(false);
|
||||
//--- create rings of vertices at progressively higher latitudes.
|
||||
for(uint i=0,idx=0; i<=segments_y; i++)
|
||||
{
|
||||
DXVector2 tcoord=DXVector2(0.0f,1.0f-(float)i/segments_y);
|
||||
float latitude=(i*DX_PI/segments_y)-DX_PI_DIV2;
|
||||
float dy =(float)sin(latitude);
|
||||
float dxz=(float)cos(latitude);
|
||||
//--- create a single ring of vertices at this latitude.
|
||||
for(uint j=0; j<=segments_xz; j++,idx++)
|
||||
{
|
||||
float longitude=(j%segments_xz)*DX_PI_MUL2/segments_xz;
|
||||
//--- normal
|
||||
DXVector3 normal=DXVector3((float)sin(longitude)*dxz,dy,(float)cos(longitude)*dxz);
|
||||
vertices[idx].normal =DXVector4(normal.x,normal.y,normal.z,0.0);
|
||||
//--- position
|
||||
DXVec3Scale(normal,normal,radius);
|
||||
vertices[idx].position=DXVector4(normal.x,normal.y,normal.z,1.0);
|
||||
//--- texture coords
|
||||
tcoord.x = float(j)/segments_xz;
|
||||
vertices[idx].tcoord =tcoord;
|
||||
}
|
||||
}
|
||||
//--- fill the index buffer with triangles joining each pair of latitude rings.
|
||||
uint stride=segments_xz+1;
|
||||
uint idx=0;
|
||||
for(uint i=0; i<segments_y; i++)
|
||||
{
|
||||
for(uint j=0; j<segments_xz; j++)
|
||||
{
|
||||
uint next_i=i+1;
|
||||
uint next_j=(j+1)%stride;
|
||||
|
||||
indices[idx++]=next_i*stride + next_j;
|
||||
indices[idx++]=next_i*stride + j;
|
||||
indices[idx++]= i*stride + j;
|
||||
|
||||
indices[idx++]= i*stride + j;
|
||||
indices[idx++]= i*stride + next_j;
|
||||
indices[idx++]=next_i*stride + next_j;
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Torus |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeTorus(float outer_radius,float inner_radius,uint tessellation,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
if(tessellation<3)
|
||||
tessellation=3;
|
||||
//--- prepare arrays
|
||||
uint count=(tessellation+1)*(tessellation+1);
|
||||
if(ArrayResize(vertices,count)!=count)
|
||||
return(false);
|
||||
count=6*tessellation*tessellation;
|
||||
if(ArrayResize(indices,count)!=count)
|
||||
return(false);
|
||||
//---
|
||||
uint v=0,idx=0;
|
||||
uint stride=tessellation+1;
|
||||
//--- first we loop around the main ring of the torus.
|
||||
for(uint i=0; i<=tessellation; i++)
|
||||
{
|
||||
DXVector2 tcoord=DXVector2(float(i)/tessellation,0.0f);
|
||||
//--- create a transform matrix that will align geometry to slice perpendicularly though the current ring position.
|
||||
DXMatrix rotation,transform;
|
||||
DXMatrixRotationY(rotation,-1.0f*(i%tessellation)*DX_PI_MUL2/tessellation-DX_PI_DIV2);
|
||||
DXMatrixTranslation(transform,outer_radius,0.0f,0.0f);
|
||||
DXMatrixMultiply(transform,transform,rotation);
|
||||
//--- now we loop along the other axis, around the side of the tube.
|
||||
for(uint j=0; j<=tessellation; j++)
|
||||
{
|
||||
//--- calc normal and position
|
||||
float angle=(j%tessellation)*DX_PI_MUL2/tessellation+DX_PI;
|
||||
vertices[v].normal=DXVector4((float)cos(angle),(float)sin(angle),0.0f,0.0f);
|
||||
vertices[v].position=DXVector4(vertices[v].normal.x*inner_radius,vertices[v].normal.y*inner_radius,0.0f,1.0f);
|
||||
DXVec4Transform(vertices[v].normal, vertices[v].normal, transform);
|
||||
DXVec4Transform(vertices[v].position,vertices[v].position,transform);
|
||||
//--- calc texture coord
|
||||
tcoord.y=1-float(j)/tessellation;
|
||||
vertices[v].tcoord=tcoord;
|
||||
v++;
|
||||
//--- create indices for two triangles.
|
||||
if(i<tessellation && j<tessellation)
|
||||
{
|
||||
uint next_i=i+1;
|
||||
uint next_j=j+1;
|
||||
|
||||
indices[idx++]=next_i*stride + next_j;
|
||||
indices[idx++]=next_i*stride + j;
|
||||
indices[idx++]= i*stride + j;
|
||||
|
||||
indices[idx++]= i*stride + j;
|
||||
indices[idx++]= i*stride + next_j;
|
||||
indices[idx++]=next_i*stride + next_j;
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cylinder |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeCylinder(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
return(DXComputeTruncatedCone(radius,radius,height,tessellation,vertices,indices));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Truncated Cone |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeTruncatedCone(float radius_top,float radius_bottom,float height,uint tessellation,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
if(tessellation<3)
|
||||
tessellation=3;
|
||||
//--- prepare arrays
|
||||
uint count=2*(tessellation+1)+2*tessellation;
|
||||
if(ArrayResize(vertices,count)!=count)
|
||||
return(false);
|
||||
count=6*tessellation+6*(tessellation-1);
|
||||
if(ArrayResize(indices,count)!=count)
|
||||
return(false);
|
||||
//--- prepare normal
|
||||
DXVector2 normal=DXVector2(height,radius_bottom-radius_top);
|
||||
DXVec2Normalize(normal,normal);
|
||||
float dy=height/2.0f;
|
||||
uint v=0,idx=0;
|
||||
uint stride=2;
|
||||
//--- create top and bottom rings of vertices
|
||||
for(uint i=0; i<=tessellation; i++)
|
||||
{
|
||||
float u=1.0f-(float)i/tessellation;
|
||||
float angle=(i*DX_PI_MUL2/tessellation);
|
||||
float dx=(float)sin(angle);
|
||||
float dz=(float)cos(angle);
|
||||
//---
|
||||
vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f);
|
||||
vertices[v].position=DXVector4(dx*radius_bottom,-dy,dz*radius_bottom,1.0f);
|
||||
vertices[v].tcoord =DXVector2(u,1.0f);
|
||||
v++;
|
||||
vertices[v].normal =vertices[v-1].normal;
|
||||
vertices[v].position=DXVector4(dx*radius_top,dy,dz*radius_top,1.0f);
|
||||
vertices[v].tcoord =DXVector2(u,0.0f);
|
||||
v++;
|
||||
//--- creater side surface
|
||||
if(i<tessellation)
|
||||
{
|
||||
uint next_i=i+1;
|
||||
|
||||
indices[idx++]=next_i*stride + 1;
|
||||
indices[idx++]= i*stride + 0;
|
||||
indices[idx++]=next_i*stride + 0;
|
||||
|
||||
|
||||
indices[idx++]= i*stride + 0;
|
||||
indices[idx++]=next_i*stride + 1;
|
||||
indices[idx++]= i*stride + 1;
|
||||
}
|
||||
}
|
||||
//--- first cap vertex
|
||||
uint cap_first=v;
|
||||
//--- create caps
|
||||
for(uint i=0; i<tessellation; i++)
|
||||
{
|
||||
float angle=(i*DX_PI_MUL2/tessellation);
|
||||
float dx=(float)sin(angle);
|
||||
float dz=(float)cos(angle);
|
||||
|
||||
vertices[v].normal =DXVector4(0.0f,-1.0f,0.0f,0.0f);
|
||||
vertices[v].position=DXVector4(dx*radius_bottom,-dy,dz*radius_bottom,1.0f);
|
||||
vertices[v].tcoord =DXVector2(0.5f+0.5f*dx,0.5f+0.5f*dz);
|
||||
v++;
|
||||
vertices[v].normal =DXVector4(0.0f,1.0f,0.0f,0.0f);
|
||||
vertices[v].position=DXVector4(dx*radius_top,dy,dz*radius_top,1.0f);
|
||||
vertices[v].tcoord =DXVector2(0.5f+0.5f*dx,0.5f-0.5f*dz);
|
||||
v++;
|
||||
//--- creater caps surface
|
||||
if(i>0 && i<tessellation-1)
|
||||
{
|
||||
uint next_i=i+1;
|
||||
|
||||
indices[idx++]=cap_first;
|
||||
indices[idx++]=cap_first+next_i*stride;
|
||||
indices[idx++]=cap_first+ i*stride;
|
||||
|
||||
indices[idx++]=cap_first+1;
|
||||
indices[idx++]=cap_first+ i*stride+1;
|
||||
indices[idx++]=cap_first+next_i*stride+1;
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Cone |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeCone(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
if(tessellation<3)
|
||||
tessellation=3;
|
||||
//--- prepare arrays
|
||||
uint count=2*(tessellation+1)+tessellation;
|
||||
if(ArrayResize(vertices,count)!=count)
|
||||
return(false);
|
||||
count=3*tessellation+3*(tessellation-1);
|
||||
if(ArrayResize(indices,count)!=count)
|
||||
return(false);
|
||||
//--- prepare normal
|
||||
DXVector2 normal=DXVector2(height,radius);
|
||||
DXVec2Normalize(normal,normal);
|
||||
float dy=height/2.0f;
|
||||
uint v=0,idx=0;
|
||||
uint stride=2;
|
||||
//--- create top and bottom rings of vertices
|
||||
for(uint i=0; i<=tessellation; i++)
|
||||
{
|
||||
float u=1.0f-(float)i/tessellation;
|
||||
float angle=(i*DX_PI_MUL2/tessellation);
|
||||
float dx=(float)sin(angle);
|
||||
float dz=(float)cos(angle);
|
||||
//---
|
||||
vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f);
|
||||
vertices[v].position=DXVector4(dx*radius,-dy,dz*radius,1.0f);
|
||||
vertices[v].tcoord =DXVector2(u,1.0f);
|
||||
v++;
|
||||
vertices[v].normal =vertices[v-1].normal;
|
||||
vertices[v].position=DXVector4(0.0f,dy,0.0f,1.0f);
|
||||
vertices[v].tcoord =DXVector2(u,0.0f);
|
||||
v++;
|
||||
//--- creater side surface
|
||||
if(i<tessellation)
|
||||
{
|
||||
uint next_i=i+1;
|
||||
|
||||
indices[idx++]=next_i*stride + 1;
|
||||
indices[idx++]= i*stride + 0;
|
||||
indices[idx++]=next_i*stride + 0;
|
||||
}
|
||||
}
|
||||
//--- first cap vertex
|
||||
uint cap_first=v;
|
||||
//--- create caps
|
||||
for(uint i=0; i<tessellation; i++)
|
||||
{
|
||||
float angle=(i*DX_PI_MUL2/tessellation);
|
||||
float dx=(float)sin(angle);
|
||||
float dz=(float)cos(angle);
|
||||
|
||||
vertices[v].normal =DXVector4(0.0f,-1.0f,0.0f,0.0f);
|
||||
vertices[v].position=DXVector4(dx*radius,-dy,dz*radius,1.0f);
|
||||
vertices[v].tcoord =DXVector2(0.5f+0.5f*dx,0.5f+0.5f*dz);
|
||||
v++;
|
||||
//--- creater caps surface
|
||||
if(i>0 && i<tessellation-1)
|
||||
{
|
||||
indices[idx++]=cap_first;
|
||||
indices[idx++]=cap_first+i+1;
|
||||
indices[idx++]=cap_first+i;
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Surface |
|
||||
//| TVertex must have |
|
||||
//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members|
|
||||
//+------------------------------------------------------------------+
|
||||
template <typename TVertex>
|
||||
bool DXComputeSurface(double &data[],uint data_width,uint data_height,double data_range,
|
||||
const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size,
|
||||
bool two_sided,bool use_normals,
|
||||
TVertex &vertices[],uint &indices[])
|
||||
{
|
||||
//---
|
||||
if(data_width<2 || data_height<2)
|
||||
return(false);
|
||||
//--- prepare arrays for vertices and triangles
|
||||
uint count=data_width*data_height*(two_sided?2:1);
|
||||
if(!ArrayResize(vertices,count))
|
||||
return(false);
|
||||
count=6*(data_width-1)*(data_height-1)*(two_sided?2:1);
|
||||
if(!ArrayResize(indices,count))
|
||||
return(false);
|
||||
//--- find min and max value
|
||||
float min_value=+FLT_MAX;
|
||||
float max_value=-FLT_MAX;
|
||||
for(uint j=0; j<data_height; j++)
|
||||
for(uint i=0; i<data_width; i++)
|
||||
{
|
||||
float value=(float)data[j*data_width+i];
|
||||
if(min_value>value)
|
||||
min_value=value;
|
||||
if(max_value<value)
|
||||
max_value=value;
|
||||
}
|
||||
//--- check and fix data range
|
||||
float avg_value=0.5f*(max_value+min_value);
|
||||
float range=(float)data_range;
|
||||
if(range<=0.0f)
|
||||
range=max_value-min_value;
|
||||
if(range<FLT_EPSILON)
|
||||
range=FLT_EPSILON;
|
||||
//---
|
||||
min_value=avg_value-0.5f*range;
|
||||
max_value=avg_value+0.5f*range;
|
||||
//---
|
||||
DXVector3 range_3d;
|
||||
DXVec3Subtract(range_3d,to,from);
|
||||
float step_x=range_3d.x/(data_width-1);
|
||||
float step_y=range_3d.y/range;
|
||||
float step_z=range_3d.z/(data_height-1);
|
||||
//--- calculate vertices positions and colors
|
||||
for(uint j=0; j<data_height; j++)
|
||||
{
|
||||
for(uint i=0; i<data_width; i++)
|
||||
{
|
||||
uint idx=j*data_width+i;
|
||||
//--- calc value
|
||||
float value=(float)data[idx]-min_value;
|
||||
//--- calc position
|
||||
vertices[idx].position.x = from.x+i *step_x;
|
||||
vertices[idx].position.y = from.y+value*step_y;
|
||||
vertices[idx].position.z = from.z+j *step_z;
|
||||
vertices[idx].position.w = 1.0f;
|
||||
//--- set texture coordinates
|
||||
vertices[idx].tcoord=DXVector2(i*step_x/texture_size.x,j*step_z/texture_size.y);
|
||||
}
|
||||
}
|
||||
//--- calculate normals
|
||||
if(use_normals)
|
||||
{
|
||||
for(uint j=0; j<data_height; j++)
|
||||
{
|
||||
for(uint i=0; i<data_width; i++)
|
||||
{
|
||||
DXVector4 v1,v2,normal;
|
||||
//--- v1
|
||||
if(i<=0)
|
||||
DXVec4Subtract(v1,vertices[j*data_width+i].position,vertices[j*data_width+i+1].position);
|
||||
else
|
||||
if(i>=data_width-1)
|
||||
DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i].position);
|
||||
else
|
||||
DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i+1].position);
|
||||
//--- v2
|
||||
if(j<=0)
|
||||
DXVec4Subtract(v2,vertices[j*data_width+i].position,vertices[(j+1)*data_width+i].position);
|
||||
else
|
||||
if(j>=data_height-1)
|
||||
DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[j*data_width+i].position);
|
||||
else
|
||||
DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[(j+1)*data_width+i].position);
|
||||
//--- normal
|
||||
DXVec4Cross(normal,v2,v1,DXVector4(0.0f,0.0f,0.0f,1.0f));
|
||||
float inv_len=(float)(1.0/sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z));
|
||||
vertices[j*data_width+i].normal.x=normal.x*inv_len;
|
||||
vertices[j*data_width+i].normal.y=normal.y*inv_len;
|
||||
vertices[j*data_width+i].normal.z=normal.z*inv_len;
|
||||
vertices[j*data_width+i].normal.w=0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DXVector4 n=DXVector4(0.0f,0.0f,0.0f,0.0f);
|
||||
for(int i=0; i<ArraySize(vertices); i++)
|
||||
vertices[i].normal=n;
|
||||
}
|
||||
//--- calculate triangles for every rectangle
|
||||
int n=0;
|
||||
for(uint i=0; i<data_width-1; i++)
|
||||
{
|
||||
for(uint j=0; j<data_height-1; j++)
|
||||
{
|
||||
//--- left triangle
|
||||
indices[n++]=j*data_width+(i+1);
|
||||
indices[n++]=j*data_width+i;
|
||||
indices[n++]=(j+1)*data_width+i;
|
||||
//--- right triangle
|
||||
indices[n++]=(j+1)*data_width+(i+1);
|
||||
indices[n++]=j*data_width+(i+1);
|
||||
indices[n++]=(j+1)*data_width+(i);
|
||||
}
|
||||
}
|
||||
//--- generate back side
|
||||
if(two_sided)
|
||||
{
|
||||
uint offset=data_height*data_width;
|
||||
for(uint j=0; j<data_height; j++)
|
||||
{
|
||||
for(uint i=0; i<data_width; i++)
|
||||
{
|
||||
uint idx=offset+j*data_width+i;
|
||||
//--- copy vertices in backward direction
|
||||
vertices[idx]=vertices[j*data_width+data_width-i-1];
|
||||
//--- inverse normals
|
||||
DXVec4Scale(vertices[idx].normal,vertices[idx].normal,-1.0f);
|
||||
}
|
||||
}
|
||||
//--- calculate triangles for opposit side
|
||||
for(uint i=0; i<data_width-1; i++)
|
||||
{
|
||||
for(uint j=0; j<data_height-1; j++)
|
||||
{
|
||||
//--- left triangle
|
||||
indices[n++]=offset+j*data_width+(i+1);
|
||||
indices[n++]=offset+j*data_width+i;
|
||||
indices[n++]=offset+(j+1)*data_width+i;
|
||||
//--- right triangle
|
||||
indices[n++]=offset+(j+1)*data_width+(i+1);
|
||||
indices[n++]=offset+j*data_width+(i+1);
|
||||
indices[n++]=offset+(j+1)*data_width+(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+---------------------------------------------------------------------+
|
||||
//| Computes Matlab jet color scheme colors on [0;1] range |
|
||||
//| dark blue > blue > light blue > green > yellow > red > dark red |
|
||||
//+---------------------------------------------------------------------+
|
||||
void DXComputeColorJet(const float value,DXColor &cout)
|
||||
{
|
||||
float v=value*1.1f-0.05f;
|
||||
cout.r = fmin(fmax(v<0.75f ? 4*v-1.5f : 4.5f-4*v,0.0f),1.0f);
|
||||
cout.g = fmin(fmax(v<0.5f ? 4*v-0.5f : 3.5f-4*v,0.0f),1.0f);
|
||||
cout.b = fmin(fmax(v<0.25f ? 4*v+0.5f : 2.5f-4*v,0.0f),1.0f);
|
||||
cout.a = 1.0;
|
||||
}
|
||||
//+---------------------------------------------------------------------+
|
||||
//| Computes hot to cold color scheme colors on [0;1] range |
|
||||
//| blue > light blue > green > yellow > red |
|
||||
//+---------------------------------------------------------------------+
|
||||
void DXComputeColorColdToHot(const float value,DXColor &cout)
|
||||
{
|
||||
float v=2*value-1.0f;
|
||||
cout.r = fmin(fmax(2*v,0.0f),1.0f);
|
||||
cout.g = fmin(fmax(2.0f-2*fabs(v),0.0f),1.0f);
|
||||
cout.b = fmin(fmax(-2*v,0.0f),1.0f);
|
||||
cout.a = 1.0;
|
||||
}
|
||||
//+---------------------------------------------------------------------+
|
||||
//| Computes red to green color scheme colors on [0;1] range |
|
||||
//| red > yellow > dark green |
|
||||
//+---------------------------------------------------------------------+
|
||||
void DXComputeColorRedToGreen(const float value,DXColor &cout)
|
||||
{
|
||||
if(value<=0.5)
|
||||
{
|
||||
cout.r=1.0f;
|
||||
cout.g=DXScalarLerp(0.01f,0.95f,fmin(fmax(2*value,0.0f),1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
cout.r=DXScalarLerp(0.1f,1.0f, fmin(fmax(2.0f-2*value,0.0f),1.0f));
|
||||
cout.g=DXScalarLerp(0.6f,0.95f,fmin(fmax(2.0f-2*value,0.0f),1.0f));
|
||||
}
|
||||
cout.b=0.0f;
|
||||
cout.a=1.0f;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,71 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Default Pixel Shader |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs for whole scene |
|
||||
//+------------------------------------------------------------------+
|
||||
cbuffer InputScene : register(b0)
|
||||
{
|
||||
matrix view;
|
||||
matrix projection;
|
||||
float4 light_direction;
|
||||
float4 light_color;
|
||||
float4 ambient_color;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs for single object |
|
||||
//+------------------------------------------------------------------+
|
||||
cbuffer InputObject : register(b1)
|
||||
{
|
||||
matrix transform;
|
||||
float4 diffuse_color;
|
||||
float4 emission_color;
|
||||
float4 specular_color;
|
||||
float specular_power;
|
||||
float dummy[3];
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Input texture |
|
||||
//+------------------------------------------------------------------+
|
||||
Texture2D<float4> diffuse_tex : register(t0);
|
||||
//+------------------------------------------------------------------+
|
||||
//| Texture sampler |
|
||||
//+------------------------------------------------------------------+
|
||||
SamplerState diffuse_samp
|
||||
{
|
||||
Filter =MIN_MAG_MIP_LINEAR;
|
||||
AddressU=Wrap;
|
||||
AddressV=Wrap;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Pixel shader input type |
|
||||
//+------------------------------------------------------------------+
|
||||
struct PSInput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float4 camera : CAMERA;
|
||||
float4 normal : NORMAL;
|
||||
float2 tcoord : TEXCOORD;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Pixel shader entry point |
|
||||
//+------------------------------------------------------------------+
|
||||
float4 PSMain(PSInput input) : SV_TARGET
|
||||
{
|
||||
float3 diffuse =saturate(-dot(light_direction.xyz,input.normal.xyz))*light_color.rgb*light_color.a;
|
||||
float3 ambient =ambient_color.rgb *ambient_color.a;
|
||||
float3 light =(diffuse+ambient)*diffuse_color.rgb*diffuse_color.a+emission_color.rgb*emission_color.a;
|
||||
float4 specular=float4(light_color.rgb*specular_color.rgb,pow(saturate(dot(reflect(normalize(light_direction.xyz),input.normal.xyz),normalize(input.camera.xyz))),specular_power)*light_color.a*specular_color.a);
|
||||
float4 clr=input.color;
|
||||
//--- use texture if it exist
|
||||
uint width,height;
|
||||
diffuse_tex.GetDimensions(width,height);
|
||||
if(width*height>0)
|
||||
clr*=diffuse_tex.Sample(diffuse_samp,frac(input.tcoord));
|
||||
//--- combine light with colors
|
||||
return(lerp(float4(light*clr.rgb,clr.a),float4(specular.rgb,1.0),specular.a));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,72 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Default Vertex Shader |
|
||||
//| Copyright 2019, MetaQuotes Software Corp. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs for whole scene |
|
||||
//+------------------------------------------------------------------+
|
||||
cbuffer InputScene : register(b0)
|
||||
{
|
||||
matrix view;
|
||||
matrix projection;
|
||||
float4 light_direction;
|
||||
float4 light_color;
|
||||
float4 ambient_color;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Inputs for single object |
|
||||
//+------------------------------------------------------------------+
|
||||
cbuffer InputObject : register(b1)
|
||||
{
|
||||
matrix transform;
|
||||
float4 diffuse_color;
|
||||
float4 emission_color;
|
||||
float4 specular_color;
|
||||
float specular_power;
|
||||
float dummy[3];
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Vertex shader input type |
|
||||
//+------------------------------------------------------------------+
|
||||
struct VSInput
|
||||
{
|
||||
float4 position : POSITION;
|
||||
float4 normal : NORMAL;
|
||||
float2 tcoord : TEXCOORD;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Pixel shader input type |
|
||||
//+------------------------------------------------------------------+
|
||||
struct PSInput
|
||||
{
|
||||
float4 position : SV_POSITION;
|
||||
float4 camera : CAMERA;
|
||||
float4 normal : NORMAL;
|
||||
float2 tcoord : TEXCOORD;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Vertex shader entry point |
|
||||
//+------------------------------------------------------------------+
|
||||
PSInput VSMain(VSInput input)
|
||||
{
|
||||
PSInput output;
|
||||
//--- posiiton and camera direction
|
||||
output.position=mul(input .position,transform);
|
||||
output.position=mul(output.position,view);
|
||||
output.camera =-output.position;
|
||||
output.position=mul(output.position,projection);
|
||||
//--- transform normals
|
||||
output.normal = mul(input.normal, transform);
|
||||
output.normal = mul(output.normal, view);
|
||||
output.normal = normalize(output.normal);
|
||||
//--- color and texture coordinates
|
||||
output.tcoord =input.tcoord;
|
||||
output.color =input.color;
|
||||
//---
|
||||
return(output);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,751 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| FlameCanvas.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Canvas.mqh"
|
||||
#include <Controls\Defines.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Gradient descriptors |
|
||||
//+------------------------------------------------------------------+
|
||||
struct GRADIENT_COLOR
|
||||
{
|
||||
uint clr; // color in ARGB format
|
||||
uint pos; // position of color in percentage of gradient range
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
struct GRADIENT_SIZE
|
||||
{
|
||||
uint size; // width of gradient fill in percentage of base fill
|
||||
uint pos; // position of color in percentage of gradient length
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CFlameCanvas |
|
||||
//| Usage: generates flame |
|
||||
//+------------------------------------------------------------------+
|
||||
class CFlameCanvas : public CCanvas
|
||||
{
|
||||
private:
|
||||
//--- parameters
|
||||
uint m_bar_gap;
|
||||
uint m_bar_width;
|
||||
uint m_chart_scale;
|
||||
double m_chart_price_min;
|
||||
double m_chart_price_max;
|
||||
ENUM_TIMEFRAMES m_timeframe;
|
||||
string m_symbol;
|
||||
int m_future_bars;
|
||||
int m_back_bars;
|
||||
int m_rates_total;
|
||||
uint m_palette[256]; // flame palette
|
||||
uchar m_flame[]; // buffer for calculation of flame
|
||||
uint m_time_redraw;
|
||||
uint m_delay;
|
||||
// bool m_resize_flag;
|
||||
// int m_tick_cnt;
|
||||
//--- flame parameters
|
||||
datetime m_tb1;
|
||||
double m_pb1;
|
||||
datetime m_te1;
|
||||
double m_pe1;
|
||||
datetime m_tb2;
|
||||
double m_pb2;
|
||||
datetime m_te2;
|
||||
double m_pe2;
|
||||
//--- equation parameters for flame
|
||||
int m_cloud_axis[100];
|
||||
double m_a1;
|
||||
double m_b1;
|
||||
double m_a2;
|
||||
double m_b2;
|
||||
int m_xb1;
|
||||
int m_yb1;
|
||||
int m_xe1;
|
||||
int m_ye1;
|
||||
int m_xb2;
|
||||
int m_yb2;
|
||||
int m_xe2;
|
||||
int m_ye2;
|
||||
|
||||
public:
|
||||
CFlameCanvas(void);
|
||||
~CFlameCanvas(void);
|
||||
//--- create
|
||||
bool FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars=0);
|
||||
void RatesTotal(const int value);
|
||||
//--- setting
|
||||
void PaletteSet(uint clr=0xFF0000);
|
||||
//--- draw
|
||||
void FlameDraw(const double &prices[],const int width,const int lenght);
|
||||
void FlameSet(datetime xb1,double yb1,datetime xe1,double ye1,datetime xb2,double yb2,datetime xe2,double ye2);
|
||||
//--- event handler
|
||||
void ChartEventHandler(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
|
||||
protected:
|
||||
bool Resize(void);
|
||||
void ChartScale(void);
|
||||
void FlameSet(void);
|
||||
void CloudDraw(const double &prices[],const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[],const uchar t_level=255,const bool custom_gradient=true);
|
||||
void FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[]);
|
||||
void GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[]);
|
||||
void GradientVerticalLine(int x,int y1,int y2,const GRADIENT_COLOR &gradient[]);
|
||||
void GradientVerticalLineMonochrome(int x,int y1,int y2,uint clr1,uint clr2);
|
||||
void FlameCreate(void);
|
||||
void FlameCalculate(void);
|
||||
void Delay(const uint value);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CFlameCanvas::CFlameCanvas(void) : m_bar_gap(16),
|
||||
m_bar_width(8),
|
||||
m_chart_scale(1),
|
||||
m_chart_price_min(0.0),
|
||||
m_chart_price_max(0.0),
|
||||
m_timeframe(PERIOD_CURRENT),
|
||||
m_symbol(NULL),
|
||||
m_future_bars(0),
|
||||
m_back_bars(0),
|
||||
m_rates_total(0),
|
||||
m_time_redraw(0),
|
||||
m_delay(50),
|
||||
m_tb1(0),
|
||||
m_pb1(0),
|
||||
m_te1(0),
|
||||
m_pe1(0),
|
||||
m_tb2(0),
|
||||
m_pb2(0),
|
||||
m_te2(0),
|
||||
m_pe2(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CFlameCanvas::~CFlameCanvas(void)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Creates dynamic resource with object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CFlameCanvas::FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars)
|
||||
{
|
||||
//--- get chart parameters
|
||||
ChartScale();
|
||||
//--- create
|
||||
int width =(int)m_bar_gap*(future_bars+back_bars);
|
||||
int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
|
||||
if(!CreateBitmap(0,0,name,time-back_bars*PeriodSeconds(),m_chart_price_max,width,height,COLOR_FORMAT_ARGB_NORMALIZE))
|
||||
return(false);
|
||||
ArrayResize(m_flame,width*height);
|
||||
//--- save parameters
|
||||
m_future_bars=future_bars;
|
||||
m_back_bars =back_bars;
|
||||
//--- settings
|
||||
PaletteSet();
|
||||
m_timeframe =Period();
|
||||
m_symbol =Symbol();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CFlameCanvas::Resize(void)
|
||||
{
|
||||
int x,y;
|
||||
//--- get limits
|
||||
double min=ChartGetDouble(0,CHART_PRICE_MIN);
|
||||
double max=ChartGetDouble(0,CHART_PRICE_MAX);
|
||||
if(m_chart_price_max!=max)
|
||||
{
|
||||
//--- move object
|
||||
ObjectSetDouble(0,m_objname,OBJPROP_PRICE,0,max);
|
||||
}
|
||||
//--- check
|
||||
if(m_chart_price_min==min && m_chart_price_max==max)
|
||||
return(false);
|
||||
m_chart_price_min=min;
|
||||
m_chart_price_max=max;
|
||||
//--- grt size
|
||||
ChartTimePriceToXY(0,0,m_tb1,min,x,y);
|
||||
int width =(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-x;
|
||||
int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
|
||||
//--- resize
|
||||
if(width<m_width)
|
||||
width=m_width;
|
||||
if(width<=0)
|
||||
return(false);
|
||||
CCanvas::Resize(width,height);
|
||||
//--- resize flame buffer
|
||||
ArrayResize(m_flame,width*height);
|
||||
ArrayInitialize(m_flame,0);
|
||||
ArrayInitialize(m_pixels,0);
|
||||
//--- restore parameters
|
||||
if(m_pb1!=0.0)
|
||||
FlameSet(m_tb1,m_pb1,m_te1,m_pe1,m_tb2,m_pb2,m_te2,m_pe2);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::RatesTotal(const int value)
|
||||
{
|
||||
if(value==0)
|
||||
return;
|
||||
if(m_rates_total==0)
|
||||
m_rates_total=value;
|
||||
else
|
||||
{
|
||||
if(m_rates_total!=value)
|
||||
{
|
||||
//--- move object
|
||||
ObjectSetInteger(0,m_objname,OBJPROP_TIME,0,
|
||||
ObjectGetInteger(0,m_objname,OBJPROP_TIME)+(value-m_rates_total)*PeriodSeconds());
|
||||
m_rates_total=value;
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Adjusts to the chart scale |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::ChartScale(void)
|
||||
{
|
||||
m_chart_scale=(uint)ChartGetInteger(0,CHART_SCALE);
|
||||
//--- set params
|
||||
switch(m_chart_scale)
|
||||
{
|
||||
case 0:
|
||||
m_bar_gap =1;
|
||||
m_bar_width=1;
|
||||
break;
|
||||
case 1:
|
||||
m_bar_gap =2;
|
||||
m_bar_width=1;
|
||||
break;
|
||||
case 2:
|
||||
m_bar_gap =4;
|
||||
m_bar_width=2;
|
||||
break;
|
||||
case 3:
|
||||
m_bar_gap =8;
|
||||
m_bar_width=4;
|
||||
break;
|
||||
case 4:
|
||||
m_bar_gap =16;
|
||||
m_bar_width=10;
|
||||
break;
|
||||
case 5:
|
||||
m_bar_gap =32;
|
||||
m_bar_width=22;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets palette |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::PaletteSet(uint clr)
|
||||
{
|
||||
//--- create palette
|
||||
double g=0,b=0,dg=1.45,db=0.63;
|
||||
//---
|
||||
for(uint a,i=0;i<256;i++)
|
||||
{
|
||||
//--- the first 32 values ??of flame are completely transparent
|
||||
a=uchar(i<32?0:i-32);
|
||||
//--- generate color for the i value of flame
|
||||
m_palette[i]=(a<<24)|(uint(255)<<16)|(uint(g+0.5)<<8)|uint(b+0.5);
|
||||
//--- increment the color components
|
||||
//--- the red color gets gradient due to transparency
|
||||
if(i>80) g+=dg;
|
||||
if(i>160) b+=db;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws the flame |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameDraw(const double &prices[],const int width,const int lenght)
|
||||
{
|
||||
static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}};
|
||||
static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}};
|
||||
//--- draw
|
||||
CloudDraw(prices,width,lenght,sword,flame);
|
||||
//--- copy flame buffer
|
||||
FlameCalculate();
|
||||
//--- start timer
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[])
|
||||
{
|
||||
//--- check
|
||||
int total=ArraySize(m_cloud_axis);
|
||||
if(total<2)
|
||||
return;
|
||||
if(total>lenght)
|
||||
total=lenght;
|
||||
//--- draw
|
||||
int xb,xe; // coordinates of the segment
|
||||
int ybm,yem; // coordinates of the center line
|
||||
int yb1,ye1; // coordinates of the first line
|
||||
int yb2,ye2; // coordinates of the second line
|
||||
//--- for implementation of variable width
|
||||
int w_total=ArraySize(size);
|
||||
if(w_total<2)
|
||||
return;
|
||||
int w_i =0;
|
||||
int w_is=(int)size[w_i].pos*total/100;
|
||||
int w_ie=(int)size[w_i+1].pos*total/100;
|
||||
double w =size[w_i].size*width/100;
|
||||
double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is);
|
||||
//--- draw from left to right
|
||||
xb=0;
|
||||
ybm=m_cloud_axis[0];
|
||||
yb1=ybm-(int)(w/2);
|
||||
yb2=ybm+(int)(w/2);
|
||||
//--- draw
|
||||
for(int i=1;i<total;i++)
|
||||
{
|
||||
xe=(int)(i*m_bar_gap);
|
||||
if(m_cloud_axis[i]==DBL_MAX)
|
||||
continue;
|
||||
yem=m_cloud_axis[i];
|
||||
w+=dw;
|
||||
ye1=yem-(int)(w/2);
|
||||
ye2=yem+(int)(w/2);
|
||||
//--- draw the segment of 'cloud'
|
||||
GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient);
|
||||
xb=xe;
|
||||
if(xb>=m_width)
|
||||
break;
|
||||
yb1=ye1;
|
||||
yb2=ye2;
|
||||
while(i>=w_ie-1 && i!=total-1)
|
||||
{
|
||||
w_i++;
|
||||
w_is=(int)size[w_i].pos*total/100;
|
||||
w_ie=(int)size[w_i+1].pos*total/100;
|
||||
w =size[w_i].size*width/100;
|
||||
if(w_ie==w_is)
|
||||
{
|
||||
//--- for "instant" resize
|
||||
dw=size[w_i+1].size*width/100-w;
|
||||
w+=dw;
|
||||
ye1=yem-(int)(w/2);
|
||||
ye2=yem+(int)(w/2);
|
||||
//--- draw the segment of 'cloud'
|
||||
GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient);
|
||||
yb1=ye1;
|
||||
yb2=ye2;
|
||||
}
|
||||
else
|
||||
{
|
||||
dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- copy flame buffer
|
||||
FlameCalculate();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets parameters of the flame and starts to draw |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameSet(void)
|
||||
{
|
||||
m_a1=m_bar_gap*((m_ye1-m_yb1)/((double)m_xe1-m_xb1));
|
||||
m_a2=m_bar_gap*((m_ye2-m_yb2)/((double)m_xe2-m_xb2));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sets parameters of the flame and starts to draw |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameSet(datetime tb1,double pb1,
|
||||
datetime te1,double pe1,
|
||||
datetime tb2,double pb2,
|
||||
datetime te2,double pe2)
|
||||
{
|
||||
datetime obj_time =(datetime)ObjectGetInteger(0,m_objname,OBJPROP_TIME);
|
||||
double obj_price=ObjectGetDouble(0,m_objname,OBJPROP_PRICE);
|
||||
int dx,dy;
|
||||
//--- save parameters
|
||||
m_tb1=tb1;
|
||||
m_pb1=pb1;
|
||||
m_te1=te1;
|
||||
m_pe1=pe1;
|
||||
m_tb2=tb2;
|
||||
m_pb2=pb2;
|
||||
m_te2=te2;
|
||||
m_pe2=pe2;
|
||||
//--- resize
|
||||
Resize();
|
||||
//--- convert
|
||||
if(ChartTimePriceToXY(0,0,obj_time,obj_price,dx,dy))
|
||||
{
|
||||
dy=m_yb1;
|
||||
if(ChartTimePriceToXY(0,0,tb1,pb1,m_xb1,m_yb1))
|
||||
if(ChartTimePriceToXY(0,0,te1,pe1,m_xe1,m_ye1))
|
||||
if(ChartTimePriceToXY(0,0,tb2,pb2,m_xb2,m_yb2))
|
||||
if(ChartTimePriceToXY(0,0,te2,pe2,m_xe2,m_ye2))
|
||||
{
|
||||
//--- convert to canvas coordinates
|
||||
m_xb1-=dx;
|
||||
m_xe1-=dx;
|
||||
m_xb2-=dx;
|
||||
m_xe2-=dx;
|
||||
//---
|
||||
FlameSet();
|
||||
}
|
||||
}
|
||||
//--- start timer
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generate array that describes the body of flame |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameCreate(void)
|
||||
{
|
||||
static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}};
|
||||
static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}};
|
||||
//---
|
||||
double a=rand(); // parameter of line a*x+b
|
||||
double b=rand(); // parameter of line a*x+b
|
||||
double c=rand(); // parameter of sine c*Sin(d*x)
|
||||
double d=rand(); // parameter of sine c*Sin(d*x)
|
||||
int w=rand(); // width at the base
|
||||
int l=rand(); // length
|
||||
//--- normalize
|
||||
a=fmod(a,(m_a2-m_a1))+m_a1;
|
||||
b=(m_yb1+m_yb2)/2;
|
||||
c=fmod(c,20);
|
||||
d=fmod(d,3*M_PI)+M_PI;
|
||||
//--- shape
|
||||
w%=150;
|
||||
if(w<10)
|
||||
w=10; // but no less than 10
|
||||
sword[1].size=w;
|
||||
w=rand();
|
||||
l%=50;
|
||||
sword[1].pos=l+30;
|
||||
l=rand();
|
||||
//--- sizes
|
||||
w=(m_yb2-m_yb1!=0) ? w%(m_yb2-m_yb1) : 10; // proportional to the starting width
|
||||
if(w<10)
|
||||
w=10; // but no less than 10
|
||||
l=l%((m_xe1-m_xb1)/(int)m_bar_gap-20)+20; // proportional to length
|
||||
//--- create
|
||||
int total=ArraySize(m_cloud_axis);
|
||||
for(int i=0;i<total;i++)
|
||||
m_cloud_axis[i]=int(a*i+b+c*sin(i/d));
|
||||
//--- draw
|
||||
FlameDraw(w,l,sword,flame);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculates and renders frame |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::FlameCalculate(void)
|
||||
{
|
||||
//--- calculate new frame
|
||||
int c;
|
||||
int idx;
|
||||
//--- draw body of flame to the right
|
||||
for(int x=0,x_tot=m_width-1;x<x_tot;x++)
|
||||
{
|
||||
//--- separately for y==0
|
||||
c=m_flame[x]+m_flame[x+m_width];
|
||||
c+=+m_flame[x]+m_flame[x+m_width];
|
||||
m_flame[x]=uchar(c/4);
|
||||
//---
|
||||
for(int y=1,y_tot=m_height-1;y<y_tot;y++)
|
||||
{
|
||||
idx=y*m_width+x;
|
||||
c=m_flame[idx-m_width]+m_flame[idx]+m_flame[idx+m_width];
|
||||
idx++;
|
||||
c+=m_flame[idx-m_width]+m_flame[idx]+m_flame[idx+m_width];
|
||||
m_flame[idx]=uchar(c/6);
|
||||
}
|
||||
//--- separately for y==m_height-1
|
||||
idx=(m_height-1)*m_width+x;
|
||||
c=m_flame[idx-m_width]+m_flame[idx];
|
||||
idx++;
|
||||
c+=m_flame[idx-m_width]+m_flame[idx];
|
||||
m_flame[idx]=uchar(c/4);
|
||||
}
|
||||
//--- move flame to the resource buffer
|
||||
for(int y=0;y<m_height;y++)
|
||||
{
|
||||
for(int x=0;x<m_width;x++)
|
||||
{
|
||||
idx=y*m_width+x;
|
||||
m_pixels[idx]=m_palette[m_flame[idx]];
|
||||
}
|
||||
}
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws "cloud" |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::CloudDraw(const double &prices[],const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[],const uchar t_level,const bool custom_gradient)
|
||||
{
|
||||
//--- check
|
||||
int total=ArraySize(prices);
|
||||
if(total<2)
|
||||
return;
|
||||
if(total>lenght)
|
||||
total=lenght;
|
||||
//--- draw
|
||||
int xb,xe; // coordinates of the segment
|
||||
int ybm,yem; // coordinates of the center line
|
||||
int yb1,ye1; // coordinates of the first line
|
||||
int yb2,ye2; // coordinates of the second line
|
||||
int xx;
|
||||
//--- for implementation of variable width
|
||||
int w_total=ArraySize(size);
|
||||
if(w_total<2)
|
||||
return;
|
||||
int w_i =0;
|
||||
int w_is=(int)size[w_i].pos*total/100;
|
||||
int w_ie=(int)size[w_i+1].pos*total/100;
|
||||
double w =size[w_i].size*width/100;
|
||||
double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is);
|
||||
//--- draw from left to right
|
||||
xb=0;
|
||||
ChartTimePriceToXY(0,0,0,prices[0],xx,ybm);
|
||||
yb1=ybm-(int)(w/2);
|
||||
yb2=ybm+(int)(w/2);
|
||||
//--- draw
|
||||
for(int i=1;i<total;i++)
|
||||
{
|
||||
xe=(int)(i*m_bar_gap);
|
||||
if(prices[i]==DBL_MAX)
|
||||
continue;
|
||||
ChartTimePriceToXY(0,0,0,prices[i],xx,yem);
|
||||
w+=dw;
|
||||
ye1=yem-(int)(w/2);
|
||||
ye2=yem+(int)(w/2);
|
||||
//--- draw the segment of 'cloud'
|
||||
GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient);
|
||||
xb=xe;
|
||||
if(xb>=m_width)
|
||||
break;
|
||||
yb1=ye1;
|
||||
yb2=ye2;
|
||||
while(i>=w_ie-1 && i!=total-1)
|
||||
{
|
||||
w_i++;
|
||||
w_is=(int)size[w_i].pos*total/100;
|
||||
w_ie=(int)size[w_i+1].pos*total/100;
|
||||
w =size[w_i].size*width/100;
|
||||
if(w_ie==w_is)
|
||||
{
|
||||
//--- for "instant" resize
|
||||
dw=size[w_i+1].size*width/100-w;
|
||||
w+=dw;
|
||||
ye1=yem-(int)(w/2);
|
||||
ye2=yem+(int)(w/2);
|
||||
//--- draw the segment of 'cloud'
|
||||
GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient);
|
||||
yb1=ye1;
|
||||
yb2=ye2;
|
||||
}
|
||||
else
|
||||
{
|
||||
dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws area with vertical fill using specified gradient |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[])
|
||||
{
|
||||
//--- it is assumed that the colors array has sufficient size and positions are already sorted in ascending order
|
||||
//--- get length by X and Y
|
||||
int x1 =xb;
|
||||
int y1 =yb1;
|
||||
int x2 =xb;
|
||||
int y2 =yb2;
|
||||
int dx =(xe>xb)? xe-xb : xb-xe;
|
||||
int dy1=(ye1>yb1)? ye1-yb1 : yb1-ye1;
|
||||
int dy2=(ye2>yb2)? ye2-yb2 : yb2-ye2;
|
||||
//--- get direction by X and Y
|
||||
int sx =(xb<xe)? 1 : -1;
|
||||
int sy1=(yb1<ye1)? 1 : -1;
|
||||
int sy2=(yb2<ye2)? 1 : -1;
|
||||
int er1=dx-dy1;
|
||||
int er2=dx-dy2;
|
||||
//--- extreme colors
|
||||
uint clr_first=gradient[0].clr;
|
||||
uint clr_last =gradient[ArraySize(gradient)-1].clr;
|
||||
//--- draw the first line
|
||||
while(x1!=xe || y1!=ye1)
|
||||
{
|
||||
//--- calculate coordinates of next pixel of the first line
|
||||
if((er1<<1)>-dy1)
|
||||
{
|
||||
//--- try to change X coordinate of the first line
|
||||
//--- draw the second line
|
||||
while(x2!=xe || y2!=ye2)
|
||||
{
|
||||
//--- calculate coordinates of next pixel of the second line
|
||||
if((er2<<1)>-dy2)
|
||||
{
|
||||
//--- try to change X coordinate of the second line
|
||||
//--- gradient fill
|
||||
GradientVerticalLine(x1,y1,y2,gradient);
|
||||
er2-=dy2;
|
||||
if(x2!=xe)
|
||||
x2+=sx;
|
||||
}
|
||||
if((er2<<1)<dx)
|
||||
{
|
||||
er2+=dx;
|
||||
if(y2!=ye2)
|
||||
y2+=sy2;
|
||||
}
|
||||
//--- draw the first line
|
||||
if(x1!=x2)
|
||||
break;
|
||||
}
|
||||
er1-=dy1;
|
||||
if(x1!=xe)
|
||||
x1+=sx;
|
||||
}
|
||||
if((er1<<1)<dx)
|
||||
{
|
||||
er1+=dx;
|
||||
if(y1!=ye1)
|
||||
y1+=sy1;
|
||||
}
|
||||
}
|
||||
//--- gradient fill
|
||||
GradientVerticalLine(x1,ye1,ye2,gradient);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws gradient vertical line |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::GradientVerticalLineMonochrome(int x,int y1,int y2,uint clr1,uint clr2)
|
||||
{
|
||||
//---
|
||||
double dc;
|
||||
int dd,dy=y2-y1;
|
||||
//--- check
|
||||
if(dy==0)
|
||||
return;
|
||||
//--- extract components from the first color
|
||||
uchar clr=(uchar)clr1;
|
||||
//--- parameters of pixels iteration
|
||||
if(dy>0)
|
||||
{
|
||||
dd=dy;
|
||||
dy=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dd=-dy;
|
||||
dy=-1;
|
||||
}
|
||||
//--- increments for the color components
|
||||
dc=(double)((uchar)clr2-clr)/dd;
|
||||
//--- draw
|
||||
for(int i=0;y1!=y2;i++,y1+=dy)
|
||||
{
|
||||
int idx=y1*m_width+x;
|
||||
//--- check range
|
||||
if(idx<0 || idx>=ArraySize(m_flame))
|
||||
continue;
|
||||
if(x>=0 && x<m_width && y1>=0 && y1<m_height)
|
||||
if(m_flame[idx]<(uchar)(clr+dc*i))
|
||||
m_flame[idx]=(uchar)(clr+dc*i);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draws vertical line with specified gradient |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::GradientVerticalLine(int x,int y1,int y2,const GRADIENT_COLOR &gradient[])
|
||||
{
|
||||
//--- it is assumed that the colors array has sufficient size and positions are already sorted in ascending order
|
||||
int total=ArraySize(gradient);
|
||||
int dy=y2-y1;
|
||||
//--- draw segments
|
||||
for(int i=0;i<total-1;i++)
|
||||
GradientVerticalLineMonochrome(x,y1+dy*gradient[i].pos/100,y1+dy*gradient[i+1].pos/100,gradient[i].clr,gradient[i+1].clr);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Event handler |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::ChartEventHandler(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
//--- events filter
|
||||
switch(id)
|
||||
{
|
||||
case CHARTEVENT_CHART_CHANGE:
|
||||
//--- handle only chart modification events
|
||||
if(m_chart_scale!=(uint)ChartGetInteger(0,CHART_SCALE))
|
||||
{
|
||||
Delay(20);
|
||||
//--- changed horizontal scale
|
||||
ChartScale();
|
||||
if(m_pb1!=0.0)
|
||||
FlameSet(m_tb1,m_pb1,m_te1,m_pe1,m_tb2,m_pb2,m_te2,m_pe2);
|
||||
return;
|
||||
}
|
||||
if(m_height!=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS))
|
||||
{
|
||||
//--- changed vertical size
|
||||
Delay(20);
|
||||
if(m_pb1!=0.0)
|
||||
FlameSet(m_tb1,m_pb1,m_te1,m_pe1,m_tb2,m_pb2,m_te2,m_pe2);
|
||||
return;
|
||||
}
|
||||
if(m_chart_price_min!=ChartGetDouble(0,CHART_PRICE_MIN) ||
|
||||
m_chart_price_max!=ChartGetDouble(0,CHART_PRICE_MAX))
|
||||
{
|
||||
//--- changed vertical scale
|
||||
Delay(20);
|
||||
if(m_pb1!=0.0)
|
||||
FlameSet(m_tb1,m_pb1,m_te1,m_pe1,m_tb2,m_pb2,m_te2,m_pe2);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
//--- organize custom timer
|
||||
case CHARTEVENT_CUSTOM+1302:
|
||||
//--- time to draw the new frame?
|
||||
if(GetTickCount()>m_time_redraw)
|
||||
{
|
||||
//--- add the body of flame
|
||||
FlameCreate();
|
||||
//--- draw frame
|
||||
FlameCalculate();
|
||||
Update();
|
||||
//--- calculate time for the next frame
|
||||
m_time_redraw=GetTickCount()+m_delay;
|
||||
}
|
||||
//--- generate next event for custom timer
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delay |
|
||||
//+------------------------------------------------------------------+
|
||||
void CFlameCanvas::Delay(const uint value)
|
||||
{
|
||||
//--- too small
|
||||
if(value<10)
|
||||
return;
|
||||
//--- start delay
|
||||
uint cnt=GetTickCount()+value;
|
||||
//--- delay
|
||||
while(cnt>=GetTickCount());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,205 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectPanel.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
#include <Arrays\ArrayInt.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectPanel. |
|
||||
//| Purpose: Class for grouping objects for managing a chart |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectPanel : public CChartObjectButton
|
||||
{
|
||||
protected:
|
||||
CArrayObj m_attachment; // array of attached objects
|
||||
CArrayInt m_dX; // array of dX attached objects
|
||||
CArrayInt m_dY; // array of dY attached objects
|
||||
bool m_expanded; // collapsed/expanded flag
|
||||
|
||||
public:
|
||||
CChartObjectPanel();
|
||||
~CChartObjectPanel();
|
||||
//--- method for attaching objects
|
||||
bool Attach(CChartObjectLabel *chart_object);
|
||||
bool X_Distance(const int X);
|
||||
int X_Distance(void) const { return(CChartObjectButton::X_Distance()); }
|
||||
bool Y_Distance(const int Y);
|
||||
int Y_Distance(void) const { return(CChartObjectButton::Y_Distance()); }
|
||||
int X_Size() const;
|
||||
int X_Size(const int Y) const { return(CChartObjectButton::X_Size()); }
|
||||
int Y_Size() const;
|
||||
int Y_Size(const int Y) const { return(CChartObjectButton::Y_Size()); }
|
||||
|
||||
int Timeframes(void) const { return(CChartObjectButton::Timeframes()); }
|
||||
virtual bool Timeframes(const int timeframes);
|
||||
bool State(const bool state);
|
||||
bool State(void) const { return(CChartObjectButton::State()); }
|
||||
bool CheckState();
|
||||
|
||||
protected:
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
void CChartObjectPanel::CChartObjectPanel(void) : m_expanded(true)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor. |
|
||||
//+------------------------------------------------------------------+
|
||||
void CChartObjectPanel::~CChartObjectPanel(void)
|
||||
{
|
||||
//--- All objects added by the method Add(), deleted automatically
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method Attach |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::Attach(CChartObjectLabel *chart_object)
|
||||
{
|
||||
if(m_attachment.Add(chart_object))
|
||||
{
|
||||
int x,y;
|
||||
x=chart_object.X_Distance();
|
||||
m_dX.Add(chart_object.X_Distance());
|
||||
x+=X_Distance();
|
||||
chart_object.X_Distance(X_Distance()+chart_object.X_Distance());
|
||||
y=CChartObjectButton::Y_Size();
|
||||
y+=chart_object.Y_Distance();
|
||||
m_dY.Add(chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2);
|
||||
chart_object.Y_Distance(Y_Distance()+chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2);
|
||||
return(true);
|
||||
}
|
||||
//---
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method X_Distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::X_Distance(const int X)
|
||||
{
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
for(int i=0;i<m_attachment.Total();i++)
|
||||
{
|
||||
chart_object=m_attachment.At(i);
|
||||
chart_object.X_Distance(X+m_dX.At(i));
|
||||
}
|
||||
//---
|
||||
return(CChartObjectButton::X_Distance(X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method Y_Distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::Y_Distance(const int Y)
|
||||
{
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
for(int i=0;i<m_attachment.Total();i++)
|
||||
{
|
||||
chart_object=m_attachment.At(i);
|
||||
chart_object.Y_Distance(Y+m_dY.At(i));
|
||||
}
|
||||
//---
|
||||
return(CChartObjectButton::Y_Distance(Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method X_Size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectPanel::X_Size() const
|
||||
{
|
||||
int max_x=CChartObjectButton::X_Size()+X_Distance();
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
if(m_expanded)
|
||||
{
|
||||
for(int i=0;i<m_attachment.Total();i++)
|
||||
if((chart_object=m_attachment.At(i))!=NULL)
|
||||
if(max_x<chart_object.X_Distance()+chart_object.X_Size())
|
||||
max_x=chart_object.X_Distance()+chart_object.X_Size();
|
||||
return(max_x-X_Distance()+2);
|
||||
}
|
||||
//---
|
||||
return(CChartObjectButton::X_Size()+2);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method Y_Size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectPanel::Y_Size() const
|
||||
{
|
||||
int max_y=CChartObjectButton::Y_Size()+Y_Distance();
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
if(m_expanded)
|
||||
{
|
||||
for(int i=0;i<m_attachment.Total();i++)
|
||||
if((chart_object=m_attachment.At(i))!=NULL)
|
||||
if(max_y<chart_object.Y_Distance()+chart_object.Y_Size())
|
||||
max_y=chart_object.Y_Distance()+chart_object.Y_Size();
|
||||
return(max_y-Y_Distance()+2);
|
||||
}
|
||||
//---
|
||||
return(CChartObjectButton::Y_Size()+2);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method Timeframes |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::Timeframes(const int timeframes)
|
||||
{
|
||||
int i;
|
||||
bool res=CChartObject::Timeframes(timeframes);
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
if(m_expanded)
|
||||
for(i=0;i<m_attachment.Total();i++)
|
||||
{
|
||||
chart_object=m_attachment.At(i);
|
||||
res&=chart_object.Timeframes(timeframes);
|
||||
}
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method State |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::State(const bool state)
|
||||
{
|
||||
if(CChartObjectButton::State(state))
|
||||
{
|
||||
m_expanded=state;
|
||||
return(true);
|
||||
}
|
||||
//---
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Method CheckState |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPanel::CheckState(void)
|
||||
{
|
||||
int i;
|
||||
CChartObjectLabel *chart_object;
|
||||
//---
|
||||
if(m_expanded!=State())
|
||||
{
|
||||
if(m_expanded=State())
|
||||
//--- make all objects visible
|
||||
for(i=0;i<m_attachment.Total();i++)
|
||||
{
|
||||
chart_object=m_attachment.At(i);
|
||||
chart_object.Timeframes(-1);
|
||||
}
|
||||
else
|
||||
//--- make all objects invisible
|
||||
for(i=0;i<m_attachment.Total();i++)
|
||||
{
|
||||
chart_object=m_attachment.At(i);
|
||||
chart_object.Timeframes(0x100000);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//---
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,398 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectSubChart.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectSubChart. |
|
||||
//| Purpose: Class of the "SubChart" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectSubChart : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectSubChart(void);
|
||||
~CChartObjectSubChart(void);
|
||||
//--- method of creating object
|
||||
bool Create(long chart_id,const string name,const int window,const int X,const int Y,const int sizeX,const int sizeY);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_CHART); }
|
||||
//--- methods of access to properties of the object
|
||||
int X_Distance(void) const;
|
||||
bool X_Distance(const int X) const;
|
||||
int Y_Distance(void) const;
|
||||
bool Y_Distance(const int Y) const;
|
||||
ENUM_BASE_CORNER Corner(void) const;
|
||||
bool Corner(const ENUM_BASE_CORNER corner) const;
|
||||
int X_Size(void) const;
|
||||
bool X_Size(const int size) const;
|
||||
int Y_Size(void) const;
|
||||
bool Y_Size(const int size) const;
|
||||
string Symbol(void) const;
|
||||
bool Symbol(const string symbol) const;
|
||||
int Period(void) const;
|
||||
bool Period(const int period) const;
|
||||
int Scale(void) const;
|
||||
bool Scale(const int scale) const;
|
||||
bool DateScale(void) const;
|
||||
bool DateScale(const bool scale) const;
|
||||
bool PriceScale(void) const;
|
||||
bool PriceScale(const bool scale) const;
|
||||
//--- change of time/price coordinates is blocked
|
||||
datetime Time(const int point) const { return(CChartObject::Time(point)); }
|
||||
bool Time(const int point,const datetime time) const { return(false); }
|
||||
double Price(const int point) const { return(CChartObject::Price(point)); }
|
||||
bool Price(const int point,const double price) const { return(false); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectSubChart::CChartObjectSubChart(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectSubChart::~CChartObjectSubChart(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "SubChart" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Create(long chart_id,const string name,const int window,
|
||||
const int X,const int Y,const int sizeX,const int sizeY)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_CHART,window,0,0,0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!X_Distance(X) || !Y_Distance(Y))
|
||||
return(false);
|
||||
if(!X_Size(sizeX) || !Y_Size(sizeY))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::X_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the X-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::X_Distance(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::Y_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the Y-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Y_Distance(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get base corner |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_BASE_CORNER CChartObjectSubChart::Corner(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(WRONG_VALUE);
|
||||
//--- result
|
||||
return((ENUM_BASE_CORNER)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set base corner |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Corner(const ENUM_BASE_CORNER corner) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,corner));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::X_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::X_Size(const int size) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,size));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::Y_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Y_Size(const int size) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,size));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get chart symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
string CChartObjectSubChart::Symbol(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return("");
|
||||
//--- result
|
||||
return(ObjectGetString(m_chart_id,m_name,OBJPROP_SYMBOL));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set chart symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Symbol(const string symbol) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetString(m_chart_id,m_name,OBJPROP_SYMBOL,symbol));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get chart period |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::Period(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_PERIOD));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set chart period |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Period(const int period) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_PERIOD,period));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get chart scale |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectSubChart::Scale(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(-1);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CHART_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set chart scale |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Scale(const int scale) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_CHART_SCALE,scale));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "time scale" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::DateScale(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DATE_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "time scale" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::DateScale(const bool scale) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_DATE_SCALE,scale));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "price scale" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::PriceScale(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_PRICE_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "price scale" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::PriceScale(const bool scale) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_PRICE_SCALE,scale));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Save(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "X-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "corner" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "X-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "symbol" property
|
||||
str=ObjectGetString(m_chart_id,m_name,OBJPROP_SYMBOL);
|
||||
len=StringLen(str);
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
if(len!=0 && FileWriteString(file_handle,str,len)!=len)
|
||||
return(false);
|
||||
//--- write value of the "period" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_PERIOD),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "scale" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- write value of the "time scale" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DATE_SCALE),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- write value of the "price scale" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_PRICE_SCALE),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectSubChart::Load(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "X-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "corner" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "X-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "symbol" property
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
str=(len!=0) ? FileReadString(file_handle,len) : "";
|
||||
if(!ObjectSetString(m_chart_id,m_name,OBJPROP_SYMBOL,str))
|
||||
return(false);
|
||||
//--- read value of the "period" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_PERIOD,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "scale" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,FileReadDatetime(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "time scale" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_DATE_SCALE,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "price scale" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_PRICE_SCALE,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,479 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsArrows.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All arrows. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrow. |
|
||||
//| Purpose: Class of the "Arrow" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrow : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectArrow(void);
|
||||
~CChartObjectArrow(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price,const char code);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_ARROW); }
|
||||
//--- methods of access to properties of the object
|
||||
char ArrowCode(void) const;
|
||||
virtual bool ArrowCode(const char code) const;
|
||||
ENUM_ARROW_ANCHOR Anchor(void) const;
|
||||
virtual bool Anchor(const ENUM_ARROW_ANCHOR anchor) const;
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrow::CChartObjectArrow(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrow::~CChartObjectArrow(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Arrow" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrow::Create(long chart_id,const string name,const int window,const datetime time,const double price,const char code)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!ArrowCode(code))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get code of "arrow" symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
char CChartObjectArrow::ArrowCode(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((char)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ARROWCODE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set code of "arrow" symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrow::ArrowCode(const char code) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ARROWCODE,code));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get anchor type |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_ARROW_ANCHOR CChartObjectArrow::Anchor(void) const
|
||||
{
|
||||
//--- result
|
||||
return((ENUM_ARROW_ANCHOR)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ANCHOR));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set anchor type |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrow::Anchor(const ENUM_ARROW_ANCHOR anchor) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ANCHOR,anchor));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrow::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- writing
|
||||
if(!CObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write code of "arrow" symbol
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ARROWCODE),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- write anchor type
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ANCHOR),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrow::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- reading
|
||||
if(!CObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read code of "arrow" symbol
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_ARROWCODE,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- read anchor type
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_ANCHOR,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowThumbUp. |
|
||||
//| Purpose: Class of the "Thumbs Up" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowThumbUp : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowThumbUp(void);
|
||||
~CChartObjectArrowThumbUp(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_THUMB_UP); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowThumbUp::CChartObjectArrowThumbUp(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowThumbUp::~CChartObjectArrowThumbUp(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Thumbs Up" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowThumbUp::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_THUMB_UP,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowThumbDown. |
|
||||
//| Purpose: Class of the "Thumbs Down" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowThumbDown : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowThumbDown(void);
|
||||
~CChartObjectArrowThumbDown(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_THUMB_DOWN); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowThumbDown::CChartObjectArrowThumbDown(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowThumbDown::~CChartObjectArrowThumbDown(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "ThumbsDown" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowThumbDown::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_THUMB_DOWN,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowUp. |
|
||||
//| Purpose: Class of the "Arrow Up" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowUp : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowUp(void);
|
||||
~CChartObjectArrowUp(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_UP); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowUp::CChartObjectArrowUp(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowUp::~CChartObjectArrowUp(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Arrow Up" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowUp::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_UP,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowDown. |
|
||||
//| Purpose: Class of the "Arrow Down" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowDown : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowDown(void);
|
||||
~CChartObjectArrowDown(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_DOWN); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowDown::CChartObjectArrowDown(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowDown::~CChartObjectArrowDown(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Arrow Down" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowDown::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_DOWN,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowStop. |
|
||||
//| Purpose: Class of the "Stop Sign" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowStop : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowStop(void);
|
||||
~CChartObjectArrowStop(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_STOP); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowStop::CChartObjectArrowStop(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowStop::~CChartObjectArrowStop(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Stop Sign" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowStop::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_STOP,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowCheck. |
|
||||
//| Purpose: Class of the "Check Sign" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowCheck : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowCheck(void);
|
||||
~CChartObjectArrowCheck(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_CHECK); }
|
||||
//--- change of arrow code is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowCheck::CChartObjectArrowCheck(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowCheck::~CChartObjectArrowCheck(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Check Sign" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowCheck::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_CHECK,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowLeftPrice. |
|
||||
//| Purpose: Class of the "Left Price Label" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowLeftPrice : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowLeftPrice(void);
|
||||
~CChartObjectArrowLeftPrice(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_LEFT_PRICE); }
|
||||
//--- change of arrow code and anchor point is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
virtual bool Anchor(const ENUM_ARROW_ANCHOR anchor) const override { return(false); }
|
||||
ENUM_ARROW_ANCHOR Anchor(void) const { return(CChartObjectArrow::Anchor()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowLeftPrice::CChartObjectArrowLeftPrice(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowLeftPrice::~CChartObjectArrowLeftPrice(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Left Price Label" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowLeftPrice::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_LEFT_PRICE,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectArrowRightPrice. |
|
||||
//| Purpose: Class of the "Right Price Label" object of chart. |
|
||||
//| Derives from class CChartObjectArrow. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectArrowRightPrice : public CChartObjectArrow
|
||||
{
|
||||
public:
|
||||
CChartObjectArrowRightPrice(void);
|
||||
~CChartObjectArrowRightPrice(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_ARROW_RIGHT_PRICE); }
|
||||
//--- change of arrow code and anchor point is blocked
|
||||
virtual bool ArrowCode(const char code) const override { return(false); }
|
||||
char ArrowCode(void) const { return(CChartObjectArrow::ArrowCode()); }
|
||||
virtual bool Anchor(const ENUM_ARROW_ANCHOR anchor) const override { return(false); }
|
||||
ENUM_ARROW_ANCHOR Anchor(void) const { return(CChartObjectArrow::Anchor()); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowRightPrice::CChartObjectArrowRightPrice(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectArrowRightPrice::~CChartObjectArrowRightPrice(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Right Price Label" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectArrowRightPrice::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ARROW_RIGHT_PRICE,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,512 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsBmpControls.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All objects with "bmp" pictures. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectBitmap. |
|
||||
//| Purpose: Class of the "Bitmap" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectBitmap : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectBitmap(void);
|
||||
~CChartObjectBitmap(void);
|
||||
//--- methods of access to properties of the object
|
||||
string BmpFile(void) const;
|
||||
bool BmpFile(const string name) const;
|
||||
int X_Offset(void) const;
|
||||
bool X_Offset(const int X) const;
|
||||
int Y_Offset(void) const;
|
||||
bool Y_Offset(const int Y) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_BITMAP); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectBitmap::CChartObjectBitmap(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectBitmap::~CChartObjectBitmap(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Bitmapp" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::Create(long chart_id,const string name,const int window,const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_BITMAP,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get name of bmp-file |
|
||||
//+------------------------------------------------------------------+
|
||||
string CChartObjectBitmap::BmpFile(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return("");
|
||||
//--- result
|
||||
return(ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set name of bmp-file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::BmpFile(const string name) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the XOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBitmap::X_Offset(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XOFFSET));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the XOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::X_Offset(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XOFFSET,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the YOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBitmap::Y_Offset(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YOFFSET));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the YOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::Y_Offset(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YOFFSET,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::Save(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "name of bmp-file" property
|
||||
str=ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE);
|
||||
len=StringLen(str);
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
if(len!=0 && FileWriteString(file_handle,str,len)!=len)
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBitmap::Load(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "name of bmp-file" property
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
str=(len!=0) ? FileReadString(file_handle,len) : "";
|
||||
if(!ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,str))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectBmpLabel. |
|
||||
//| Purpose: Class of the "Bitmap label" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectBmpLabel : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectBmpLabel(void);
|
||||
~CChartObjectBmpLabel(void);
|
||||
//--- methods of access to properties of the object
|
||||
int X_Distance(void) const;
|
||||
bool X_Distance(const int X) const;
|
||||
int Y_Distance(void) const;
|
||||
bool Y_Distance(const int Y) const;
|
||||
int X_Size(void) const;
|
||||
int Y_Size(void) const;
|
||||
ENUM_BASE_CORNER Corner(void) const;
|
||||
bool Corner(const ENUM_BASE_CORNER corner) const;
|
||||
string BmpFileOn(void) const;
|
||||
bool BmpFileOn(const string name) const;
|
||||
string BmpFileOff(void) const;
|
||||
bool BmpFileOff(const string name) const;
|
||||
bool State(void) const;
|
||||
bool State(const bool state) const;
|
||||
int X_Offset(void) const;
|
||||
bool X_Offset(const int X) const;
|
||||
int Y_Offset(void) const;
|
||||
bool Y_Offset(const int Y) const;
|
||||
//--- change of time/price coordinates is blocked
|
||||
bool Time(const datetime time) const { return(false); }
|
||||
bool Price(const double price) const { return(false); }
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const int X,const int Y);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_BITMAP_LABEL); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectBmpLabel::CChartObjectBmpLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectBmpLabel::~CChartObjectBmpLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Bitmap label" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Create(long chart_id,const string name,const int window,const int X,const int Y)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_BITMAP_LABEL,window,0,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!X_Distance(X) || !Y_Distance(Y))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-distance property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::X_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the X-distance property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::X_Distance(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-distance property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::Y_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the Y-distance property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Y_Distance(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::X_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::Y_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Corner property |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_BASE_CORNER CChartObjectBmpLabel::Corner(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(WRONG_VALUE);
|
||||
//--- result
|
||||
return((ENUM_BASE_CORNER)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the Corner property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Corner(const ENUM_BASE_CORNER corner) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,corner));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get filename of the "bmp-ON" property |
|
||||
//+------------------------------------------------------------------+
|
||||
string CChartObjectBmpLabel::BmpFileOn(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return("");
|
||||
//--- result
|
||||
return(ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE,0));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set filename for the "bmp-ON" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::BmpFileOn(const string name) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,0,name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get filename of the "bmp-OFF" property |
|
||||
//+------------------------------------------------------------------+
|
||||
string CChartObjectBmpLabel::BmpFileOff(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return("");
|
||||
//--- result
|
||||
return(ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE,1));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set filename for the "bmp-OFF" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::BmpFileOff(const string name) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,1,name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the State property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::State(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STATE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the State property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::State(const bool state) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_STATE,state));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the XOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::X_Offset(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XOFFSET));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the XOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::X_Offset(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XOFFSET,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the YOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectBmpLabel::Y_Offset(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YOFFSET));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the YOffset property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Y_Offset(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YOFFSET,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Save(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "X-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Corner" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "filename bmp-ON" property
|
||||
str=ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE,0);
|
||||
len=StringLen(str);
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
if(len!=0 && FileWriteString(file_handle,str,len)!=len)
|
||||
return(false);
|
||||
//--- write value of the "filename bmp-OFF" property
|
||||
str=ObjectGetString(m_chart_id,m_name,OBJPROP_BMPFILE,1);
|
||||
len=StringLen(str);
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
if(len!=0 && FileWriteString(file_handle,str,len)!=len)
|
||||
return(false);
|
||||
//--- write state
|
||||
if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_STATE))!=sizeof(long))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading object parameters from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectBmpLabel::Load(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "X-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of "Corner" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "filename bmp-ON" property
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
str=(len!=0) ? FileReadString(file_handle,len) : "";
|
||||
if(!ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,0,str))
|
||||
return(false);
|
||||
//--- read value of the "filename bmp-OFF" property
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
str=(len!=0) ? FileReadString(file_handle,len) : "";
|
||||
if(!ObjectSetString(m_chart_id,m_name,OBJPROP_BMPFILE,1,str))
|
||||
return(false);
|
||||
//--- read state
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_STATE,FileReadLong(file_handle)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,246 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsChannels.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All channels. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObjectsLines.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectChannel. |
|
||||
//| Purpose: Class of the "Equidistant channel" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectChannel : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectChannel(void);
|
||||
~CChartObjectChannel(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_CHANNEL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectChannel::CChartObjectChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectChannel::~CChartObjectChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Equidistant channel" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectChannel::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_CHANNEL,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectStdDevChannel. |
|
||||
//| Purpose: Class of the "Standrad deviation channel" |
|
||||
//| object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectStdDevChannel : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectStdDevChannel(void);
|
||||
~CChartObjectStdDevChannel(void);
|
||||
//--- methods of access to properties of the object
|
||||
double Deviations(void) const;
|
||||
bool Deviations(const double deviation) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const datetime time2,const double deviation);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_STDDEVCHANNEL); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectStdDevChannel::CChartObjectStdDevChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectStdDevChannel::~CChartObjectStdDevChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Standard deviation channel" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectStdDevChannel::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const datetime time2,const double deviation)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_STDDEVCHANNEL,window,time1,0.0,time2,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
if(!Deviations(deviation))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Deviations" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectStdDevChannel::Deviations(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_DEVIATION));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Deviations" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectStdDevChannel::Deviations(const double deviation) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_DEVIATION,deviation));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectStdDevChannel::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectTrend::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "Deviations" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_DEVIATION))!=sizeof(double))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectStdDevChannel::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectTrend::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "Deviations" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_DEVIATION,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectRegression. |
|
||||
//| Purpose: Class of the "Regression channel" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectRegression : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectRegression(void);
|
||||
~CChartObjectRegression(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const datetime time2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_REGRESSION); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRegression::CChartObjectRegression(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRegression::~CChartObjectRegression(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Regression channel" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRegression::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const datetime time2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_REGRESSION,window,time1,0.0,time2,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectPitchfork. |
|
||||
//| Purpose: Class of the "Andrews pitchfork" object of chart |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectPitchfork : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectPitchfork(void);
|
||||
~CChartObjectPitchfork(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_CHANNEL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectPitchfork::CChartObjectPitchfork(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectPitchfork::~CChartObjectPitchfork(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Andrews pitchfork" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectPitchfork::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_PITCHFORK,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,201 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsElliott.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All Elliott tools. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectElliottWave3. |
|
||||
//| Purpose: Class of the "ElliottCorrectiveWave" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectElliottWave3 : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectElliottWave3(void);
|
||||
~CChartObjectElliottWave3(void);
|
||||
//--- methods of access to properties of the object
|
||||
ENUM_ELLIOT_WAVE_DEGREE Degree(void) const;
|
||||
bool Degree(const ENUM_ELLIOT_WAVE_DEGREE degree) const;
|
||||
bool Lines(void) const;
|
||||
bool Lines(const bool lines) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_ELLIOTWAVE3); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectElliottWave3::CChartObjectElliottWave3(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectElliottWave3::~CChartObjectElliottWave3(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "ElliottCorrectiveWave" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ELLIOTWAVE3,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Degree" property |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_ELLIOT_WAVE_DEGREE CChartObjectElliottWave3::Degree(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(WRONG_VALUE);
|
||||
//--- result
|
||||
return((ENUM_ELLIOT_WAVE_DEGREE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DEGREE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Degree" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Degree(const ENUM_ELLIOT_WAVE_DEGREE degree) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_DEGREE,degree));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Lines" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Lines(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DRAWLINES));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Lines" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Lines(const bool lines) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_DRAWLINES,lines));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Save(const int file_handle)
|
||||
{
|
||||
bool result;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
result=CChartObject::Save(file_handle);
|
||||
if(result)
|
||||
{
|
||||
//--- write value of the "Degree" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DEGREE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Lines" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DRAWLINES),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
}
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave3::Load(const int file_handle)
|
||||
{
|
||||
bool result;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
result=CChartObject::Load(file_handle);
|
||||
if(result)
|
||||
{
|
||||
//--- read value of the "Degree" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_DEGREE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Lines" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_DRAWLINES,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
}
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectElliottWave5. |
|
||||
//| Purpose: Class of the "ElliottMotiveWave" object of chart. |
|
||||
//| Derives from class CChartObjectElliottWave3. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectElliottWave5 : public CChartObjectElliottWave3
|
||||
{
|
||||
public:
|
||||
CChartObjectElliottWave5(void);
|
||||
~CChartObjectElliottWave5(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3,
|
||||
const datetime time4,const double price4,
|
||||
const datetime time5,const double price5);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_ELLIOTWAVE5); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectElliottWave5::CChartObjectElliottWave5(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectElliottWave5::~CChartObjectElliottWave5(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "ElliottMotiveWave" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectElliottWave5::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3,
|
||||
const datetime time4,const double price4,
|
||||
const datetime time5,const double price5)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ELLIOTWAVE5,window,time1,price1,time2,price2,time3,price3,time4,price4,time5,price5))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,5))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,365 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsFibo.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All Fibonacci tools. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObjectsLines.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFibo. |
|
||||
//| Purpose: Class of the "Fibonacci Lines" object. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFibo : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectFibo(void);
|
||||
~CChartObjectFibo(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_FIBO); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFibo::CChartObjectFibo(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFibo::~CChartObjectFibo(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Lines" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFibo::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_FIBO,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFiboTimes. |
|
||||
//| Purpose: Class of the "Fibonacci Time Zones" object of chart |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFiboTimes : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectFiboTimes(void);
|
||||
~CChartObjectFiboTimes(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_FIBOTIMES); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboTimes::CChartObjectFiboTimes(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboTimes::~CChartObjectFiboTimes(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Time Zones" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboTimes::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_FIBOTIMES,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFiboFan. |
|
||||
//| Purpose: Class of the "Fibonacci Fan" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFiboFan : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectFiboFan(void);
|
||||
~CChartObjectFiboFan(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_FIBOFAN); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboFan::CChartObjectFiboFan(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboFan::~CChartObjectFiboFan(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Fan" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboFan::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_FIBOFAN,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFiboArc. |
|
||||
//| Purpose: Class of the "Fibonacci Arcs" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFiboArc : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectFiboArc(void);
|
||||
~CChartObjectFiboArc(void);
|
||||
//--- methods of access to properties of the object
|
||||
double Scale(void) const;
|
||||
bool Scale(const double scale) const;
|
||||
bool Ellipse(void) const;
|
||||
bool Ellipse(const bool ellipse) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,const double scale);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_FIBOARC); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboArc::CChartObjectFiboArc(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboArc::~CChartObjectFiboArc(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Arcs" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,const double scale)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_FIBOARC,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
if(!Scale(scale))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Scale" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectFiboArc::Scale(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Scale" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Scale(const double scale) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,scale));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Ellipse" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Ellipse(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ELLIPSE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Ellipse" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Ellipse(const bool ellipse) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ELLIPSE,ellipse));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameter of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "Scale" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- write value of the "Ellipse" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ELLIPSE),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboArc::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "Scale" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "Ellipse" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_ELLIPSE,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFiboChannel. |
|
||||
//| Purpose: Class of the "Fibonacci Channel" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFiboChannel : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectFiboChannel(void);
|
||||
~CChartObjectFiboChannel(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_FIBOCHANNEL); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboChannel::CChartObjectFiboChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboChannel::~CChartObjectFiboChannel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Channel" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboChannel::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_FIBOCHANNEL,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectFiboExpansion. |
|
||||
//| Purpose: Class of the "Fibonacci Expansion" object. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectFiboExpansion : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectFiboExpansion(void);
|
||||
~CChartObjectFiboExpansion(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_EXPANSION); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboExpansion::CChartObjectFiboExpansion(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectFiboExpansion::~CChartObjectFiboExpansion(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Fibonacci Expansion" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectFiboExpansion::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_EXPANSION,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,390 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsGann.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All Gann tools. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObjectsLines.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectGannLine. |
|
||||
//| Purpose: Class of the "Gann Line" object of chart. |
|
||||
//| Derives from class CChartObjectTrendByAngle. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectGannLine : public CChartObjectTrendByAngle
|
||||
{
|
||||
public:
|
||||
CChartObjectGannLine(void);
|
||||
~CChartObjectGannLine(void);
|
||||
//--- methods of access to properties of the object
|
||||
double PipsPerBar(void) const;
|
||||
bool PipsPerBar(const double ppb) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_GANNLINE); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannLine::CChartObjectGannLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannLine::~CChartObjectGannLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Gann Line" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannLine::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_GANNLINE,window,time1,price1,time2,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
if(!PipsPerBar(ppb))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectGannLine::PipsPerBar(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannLine::PipsPerBar(const double ppb) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,ppb));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannLine::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectTrend::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "PipsPerBar"
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannLine::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectTrend::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "PipsPerBar" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectGannFan. |
|
||||
//| Purpose: Class of the "Gann Fan" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectGannFan : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectGannFan(void);
|
||||
~CChartObjectGannFan(void);
|
||||
//--- methods of access to properties of the object
|
||||
double PipsPerBar(void) const;
|
||||
bool PipsPerBar(const double ppb) const;
|
||||
bool Downtrend(void) const;
|
||||
bool Downtrend(const bool downtrend) const;
|
||||
//--- method of create the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_GANNFAN); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannFan::CChartObjectGannFan(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannFan::~CChartObjectGannFan(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Gann Fan" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_GANNFAN,window,time1,price1,time2,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
if(!PipsPerBar(ppb))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectGannFan::PipsPerBar(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::PipsPerBar(const double ppb) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,ppb));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Downtrend" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::Downtrend(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DIRECTION));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "Downtrend" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::Downtrend(const bool downtrend) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_DIRECTION,downtrend));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectTrend::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "PipsPerBar" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- write value of the "Downtrend" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DIRECTION),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading object parameters from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannFan::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectTrend::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "PipsPerBar" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "Downtrend" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_DIRECTION,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectGannGrid. |
|
||||
//| Purpose: Class of the "Gann Grid" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectGannGrid : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectGannGrid(void);
|
||||
~CChartObjectGannGrid(void);
|
||||
//--- methods of access to properties of the object
|
||||
double PipsPerBar(void) const;
|
||||
bool PipsPerBar(const double ppb) const;
|
||||
bool Downtrend(void) const;
|
||||
bool Downtrend(const bool downtrend) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_GANNGRID); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannGrid::CChartObjectGannGrid(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectGannGrid::~CChartObjectGannGrid(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Gann Grid" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double ppb)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_GANNGRID,window,time1,price1,time2,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
if(!PipsPerBar(ppb))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the"PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectGannGrid::PipsPerBar(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value for the "PipsPerBar" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::PipsPerBar(const double ppb) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,ppb));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the property value "Downtrend" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::Downtrend(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DIRECTION));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the property value "Downtrend" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::Downtrend(const bool downtrend) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_DIRECTION,downtrend));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectTrend::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "PipsPerBar" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_SCALE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- write value of the "Downtrend" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_DIRECTION),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading paprameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectGannGrid::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectTrend::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "PipsPerBar" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_SCALE,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "Downtrend" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_DIRECTION,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,335 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsLines.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All lines. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectVLine. |
|
||||
//| Purpose: Class of the "Vertical line" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectVLine : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectVLine(void);
|
||||
~CChartObjectVLine(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_VLINE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectVLine::CChartObjectVLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectVLine::~CChartObjectVLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Vertical line" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectVLine::Create(long chart_id,const string name,const int window,const datetime time)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_VLINE,window,time,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectHLine. |
|
||||
//| Purpose: Class of the "Horizontal line" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectHLine : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectHLine(void);
|
||||
~CChartObjectHLine(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_HLINE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectHLine::CChartObjectHLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectHLine::~CChartObjectHLine(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Horizontal line" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectHLine::Create(long chart_id,const string name,const int window,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_HLINE,window,0,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectTrend. |
|
||||
//| Purpose: Class of the "Trendline" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//| It is the parent class for all objects that have properties |
|
||||
//| RAY_LEFT and RAY_RIGHT. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectTrend : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectTrend(void);
|
||||
~CChartObjectTrend(void);
|
||||
//--- methods of access to properties of the object
|
||||
bool RayLeft(void) const;
|
||||
bool RayLeft(const bool new_sel) const;
|
||||
bool RayRight(void) const;
|
||||
bool RayRight(const bool new_sel) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_TREND); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTrend::CChartObjectTrend(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTrend::~CChartObjectTrend(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Trendline" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_TREND,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Ray left" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::RayLeft(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Ray left" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::RayLeft(const bool new_ray) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,new_ray));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Ray right" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::RayRight(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Ray right" flag |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::RayRight(const bool new_ray) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT,new_ray));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "Ray left" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- write value of the "Ray right" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT),CHAR_VALUE)!=sizeof(char))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrend::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "Ray left" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_LEFT,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Ray right" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_RAY_RIGHT,FileReadInteger(file_handle,CHAR_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectTrendByAngle. |
|
||||
//| Puprose: Class of the "Trendline by angle" object of chart. |
|
||||
//| Derives from class CChartObjectTrend. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectTrendByAngle : public CChartObjectTrend
|
||||
{
|
||||
public:
|
||||
CChartObjectTrendByAngle(void);
|
||||
~CChartObjectTrendByAngle(void);
|
||||
//--- methods of access to properties of the object
|
||||
double Angle(void) const;
|
||||
bool Angle(const double angle) const;
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_TRENDBYANGLE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTrendByAngle::CChartObjectTrendByAngle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTrendByAngle::~CChartObjectTrendByAngle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Trendline by angle" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrendByAngle::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_TRENDBYANGLE,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Angle" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectTrendByAngle::Angle(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//---
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_ANGLE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Angle" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTrendByAngle::Angle(const double angle) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_ANGLE,angle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectCycles. |
|
||||
//| Purpose: Class of the "Cycle lines" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectCycles : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectCycles(void);
|
||||
~CChartObjectCycles(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_CYCLES); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectCycles::CChartObjectCycles(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectCycles::~CChartObjectCycles(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Cycle lines" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectCycles::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_CYCLES,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,142 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsShapes.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All shapes. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectRectangle. |
|
||||
//| Purpose: Class of the "Rectangle" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectRectangle : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectRectangle(void);
|
||||
~CChartObjectRectangle(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_RECTANGLE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRectangle::CChartObjectRectangle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRectangle::~CChartObjectRectangle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Rectangle" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectangle::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_RECTANGLE,window,time1,price1,time2,price2))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,2))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectTriangle. |
|
||||
//| Purpose: Class of the "Triangle" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectTriangle : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectTriangle(void);
|
||||
~CChartObjectTriangle(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_TRIANGLE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTriangle::CChartObjectTriangle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectTriangle::~CChartObjectTriangle(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Triangle" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectTriangle::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_TRIANGLE,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectEllipse. |
|
||||
//| Purpose: Class of the "Ellipse" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectEllipse : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectEllipse(void);
|
||||
~CChartObjectEllipse(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_ELLIPSE); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectEllipse::CChartObjectEllipse(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectEllipse::~CChartObjectEllipse(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Ellipse" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEllipse::Create(long chart_id,const string name,const int window,
|
||||
const datetime time1,const double price1,
|
||||
const datetime time2,const double price2,
|
||||
const datetime time3,const double price3)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_ELLIPSE,window,time1,price1,time2,price2,time3,price3))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,3))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,895 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ChartObjectsTxtControls.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//| All text objects. |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "ChartObject.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectText. |
|
||||
//| Purpose: Class of the "Text" object of chart. |
|
||||
//| Derives from class CChartObject. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectText : public CChartObject
|
||||
{
|
||||
public:
|
||||
CChartObjectText(void);
|
||||
~CChartObjectText(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const datetime time,const double price);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_TEXT); }
|
||||
//--- methods of access to properties of the object
|
||||
double Angle(void) const;
|
||||
bool Angle(const double angle) const;
|
||||
string Font(void) const;
|
||||
bool Font(const string font) const;
|
||||
int FontSize(void) const;
|
||||
bool FontSize(const int size) const;
|
||||
ENUM_ANCHOR_POINT Anchor(void) const;
|
||||
bool Anchor(const ENUM_ANCHOR_POINT anchor) const;
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectText::CChartObjectText(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectText::~CChartObjectText(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Text" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Create(long chart_id,const string name,const int window,
|
||||
const datetime time,const double price)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_TEXT,window,time,price))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get value of the "Angle" property |
|
||||
//+------------------------------------------------------------------+
|
||||
double CChartObjectText::Angle(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(EMPTY_VALUE);
|
||||
//--- result
|
||||
return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_ANGLE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set value of the "Angle" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Angle(const double angle) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_ANGLE,angle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get font name |
|
||||
//+------------------------------------------------------------------+
|
||||
string CChartObjectText::Font(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return("");
|
||||
//--- result
|
||||
return(ObjectGetString(m_chart_id,m_name,OBJPROP_FONT));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set font name |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Font(const string font) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetString(m_chart_id,m_name,OBJPROP_FONT,font));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get font size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectText::FontSize(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_FONTSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set font size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::FontSize(const int size) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_FONTSIZE,size));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get anchor point |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_ANCHOR_POINT CChartObjectText::Anchor(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(WRONG_VALUE);
|
||||
//--- result
|
||||
return((ENUM_ANCHOR_POINT)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ANCHOR));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set anchor point |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Anchor(const ENUM_ANCHOR_POINT anchor) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ANCHOR,anchor));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Save(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObject::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "Angle" property
|
||||
if(FileWriteDouble(file_handle,ObjectGetDouble(m_chart_id,m_name,OBJPROP_ANGLE))!=sizeof(double))
|
||||
return(false);
|
||||
//--- write value of the "Font Name" property
|
||||
str=ObjectGetString(m_chart_id,m_name,OBJPROP_FONT);
|
||||
len=StringLen(str);
|
||||
if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE)
|
||||
return(false);
|
||||
if(len!=0 && FileWriteString(file_handle,str,len)!=len)
|
||||
return(false);
|
||||
//--- write value of the "Font Size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_FONTSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Anchor Point" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ANCHOR),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectText::Load(const int file_handle)
|
||||
{
|
||||
int len;
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObject::Load(file_handle))
|
||||
return(false);
|
||||
//--- reading value of the "Angle" property
|
||||
if(!ObjectSetDouble(m_chart_id,m_name,OBJPROP_ANGLE,0,FileReadDouble(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "Font Name" property
|
||||
len=FileReadInteger(file_handle,INT_VALUE);
|
||||
str=(len!=0) ? FileReadString(file_handle,len) : "";
|
||||
if(!ObjectSetString(m_chart_id,m_name,OBJPROP_FONT,str))
|
||||
return(false);
|
||||
//--- read value of the "Font Size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_FONTSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Anchor Point" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_ANCHOR,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectLabel. |
|
||||
//| Purpose: Class of the "Label" object of chart. |
|
||||
//| Derives from class CChartObjectText. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectLabel : public CChartObjectText
|
||||
{
|
||||
public:
|
||||
CChartObjectLabel(void);
|
||||
~CChartObjectLabel(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const int X,const int Y);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_LABEL); }
|
||||
//--- methods of access to properties of the object
|
||||
int X_Distance(void) const;
|
||||
bool X_Distance(const int X) const;
|
||||
int Y_Distance(void) const;
|
||||
bool Y_Distance(const int Y) const;
|
||||
int X_Size(void) const;
|
||||
int Y_Size(void) const;
|
||||
|
||||
ENUM_BASE_CORNER Corner(void) const;
|
||||
bool Corner(const ENUM_BASE_CORNER corner) const;
|
||||
//--- change of time/price coordinates is blocked
|
||||
datetime Time(const int point) const { return(CChartObjectText::Time(point)); }
|
||||
bool Time(const int point,const datetime time) const { return(false); }
|
||||
double Price(const int point) const { return(CChartObjectText::Price(point)); }
|
||||
bool Price(const int point,const double price) const { return(false); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectLabel::CChartObjectLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectLabel::~CChartObjectLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Label" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::Create(long chart_id,const string name,const int window,const int X,const int Y)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,OBJ_LABEL,window,0,0.0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!Description(name))
|
||||
return(false);
|
||||
if(!X_Distance(X) || !Y_Distance(Y))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectLabel::X_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the X-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::X_Distance(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectLabel::Y_Distance(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the Y-distance |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::Y_Distance(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectLabel::X_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
int CChartObjectLabel::Y_Size(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(0);
|
||||
//--- result
|
||||
return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get base corner |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_BASE_CORNER CChartObjectLabel::Corner(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(WRONG_VALUE);
|
||||
//--- result
|
||||
return((ENUM_BASE_CORNER)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set base corner |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::Corner(const ENUM_BASE_CORNER corner) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,corner));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::Save(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectText::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "X-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-distance" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Corner" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CORNER),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectLabel::Load(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectText::Load(file_handle))
|
||||
return(false);
|
||||
//--- reading value of the "X-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-distance" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YDISTANCE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Corner" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_CORNER,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectEdit. |
|
||||
//| Purpose: Class of the "Edit" object of chart. |
|
||||
//| Derives from class CChartObjectLabel. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectEdit : public CChartObjectLabel
|
||||
{
|
||||
public:
|
||||
CChartObjectEdit(void);
|
||||
~CChartObjectEdit(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const int X,const int Y,const int sizeX,const int sizeY);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_EDIT); }
|
||||
//--- methods of access to properties of the object
|
||||
bool X_Size(const int X) const;
|
||||
int X_Size(void) const { return(CChartObjectLabel::X_Size()); }
|
||||
bool Y_Size(const int Y) const;
|
||||
int Y_Size(void) const { return(CChartObjectLabel::Y_Size()); }
|
||||
color BackColor(void) const;
|
||||
bool BackColor(const color new_color) const;
|
||||
color BorderColor(void) const;
|
||||
bool BorderColor(const color new_color) const;
|
||||
bool ReadOnly(void) const;
|
||||
bool ReadOnly(const bool flag) const;
|
||||
ENUM_ALIGN_MODE TextAlign(void) const;
|
||||
bool TextAlign(const ENUM_ALIGN_MODE align) const;
|
||||
//--- change of angle is blocked
|
||||
bool Angle(const double angle) const { return(false); }
|
||||
double Angle(void) const { return(CChartObjectLabel::Angle()); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectEdit::CChartObjectEdit(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectEdit::~CChartObjectEdit(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Edit" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::Create(long chart_id,const string name,const int window,const int X,const int Y,const int sizeX,const int sizeY)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!X_Distance(X) || !Y_Distance(Y))
|
||||
return(false);
|
||||
if(!X_Size(sizeX) || !Y_Size(sizeY))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::X_Size(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::Y_Size(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get background color |
|
||||
//+------------------------------------------------------------------+
|
||||
color CChartObjectEdit::BackColor(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(CLR_NONE);
|
||||
//--- result
|
||||
return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set background color |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::BackColor(const color new_color) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR,new_color));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get border color |
|
||||
//+------------------------------------------------------------------+
|
||||
color CChartObjectEdit::BorderColor(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(CLR_NONE);
|
||||
//--- result
|
||||
return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BORDER_COLOR));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set border color |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::BorderColor(const color new_color) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BORDER_COLOR,new_color));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Read only" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::ReadOnly(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_READONLY));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Read only" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::ReadOnly(const bool flag) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_READONLY,flag));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Align" property |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_ALIGN_MODE CChartObjectEdit::TextAlign(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((ENUM_ALIGN_MODE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_ALIGN));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Align" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::TextAlign(const ENUM_ALIGN_MODE align) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ALIGN,align));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::Save(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectLabel::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "X-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write background color
|
||||
if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR))!=sizeof(long))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectEdit::Load(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectLabel::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "X-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read background color
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR,FileReadLong(file_handle)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectButton. |
|
||||
//| Purpose: Class of the "Button" object of chart. |
|
||||
//| Derives from class CChartObjectEdit. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectButton : public CChartObjectEdit
|
||||
{
|
||||
public:
|
||||
CChartObjectButton(void);
|
||||
~CChartObjectButton(void);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const override { return(OBJ_BUTTON); }
|
||||
//--- methods of access to properties of the object
|
||||
bool State(void) const;
|
||||
bool State(const bool state) const;
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectButton::CChartObjectButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectButton::~CChartObjectButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectButton::State(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STATE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectButton::State(const bool state) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_STATE,state));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectButton::Save(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectEdit::Save(file_handle))
|
||||
return(false);
|
||||
//--- write state
|
||||
if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_STATE))!=sizeof(long))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectButton::Load(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectEdit::Load(file_handle))
|
||||
return(false);
|
||||
//--- read state
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_STATE,FileReadLong(file_handle)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CChartObjectRectLabel. |
|
||||
//| Purpose: Class of the "Rectangle Label" object of chart. |
|
||||
//| Derives from class CChartObjectLabel. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CChartObjectRectLabel : public CChartObjectLabel
|
||||
{
|
||||
public:
|
||||
CChartObjectRectLabel(void);
|
||||
~CChartObjectRectLabel(void);
|
||||
//--- method of creating the object
|
||||
bool Create(long chart_id,const string name,const int window,const int X,const int Y,const int sizeX,const int sizeY);
|
||||
//--- method of identifying the object
|
||||
virtual int Type(void) const { return(OBJ_RECTANGLE_LABEL); }
|
||||
//--- methods of access to properties of the object
|
||||
bool X_Size(const int X) const;
|
||||
int X_Size(void)const { return(CChartObjectLabel::X_Size()); }
|
||||
bool Y_Size(const int Y) const;
|
||||
int Y_Size(void)const { return(CChartObjectLabel::Y_Size()); }
|
||||
color BackColor(void) const;
|
||||
bool BackColor(const color new_color) const;
|
||||
ENUM_BORDER_TYPE BorderType(void) const;
|
||||
bool BorderType(const ENUM_BORDER_TYPE flag) const;
|
||||
//--- change of angle is blocked
|
||||
bool Angle(const double angle) const { return(false); }
|
||||
double Angle(void) const { return(CChartObjectLabel::Angle()); }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRectLabel::CChartObjectRectLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CChartObjectRectLabel::~CChartObjectRectLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object "Ractangle Label" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::Create(long chart_id,const string name,const int window,const int X,const int Y,const int sizeX,const int sizeY)
|
||||
{
|
||||
if(!ObjectCreate(chart_id,name,(ENUM_OBJECT)Type(),window,0,0,0))
|
||||
return(false);
|
||||
if(!Attach(chart_id,name,window,1))
|
||||
return(false);
|
||||
if(!X_Distance(X) || !Y_Distance(Y))
|
||||
return(false);
|
||||
if(!X_Size(sizeX) || !Y_Size(sizeY))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set X-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::X_Size(const int X) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,X));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set Y-size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::Y_Size(const int Y) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,Y));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get background color |
|
||||
//+------------------------------------------------------------------+
|
||||
color CChartObjectRectLabel::BackColor(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(CLR_NONE);
|
||||
//--- result
|
||||
return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set background color |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::BackColor(const color new_color) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR,new_color));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get the "Border type" property |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_BORDER_TYPE CChartObjectRectLabel::BorderType(void) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return((ENUM_BORDER_TYPE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BORDER_TYPE));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Border type" property |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::BorderType(const ENUM_BORDER_TYPE type) const
|
||||
{
|
||||
//--- check
|
||||
if(m_chart_id==-1)
|
||||
return(false);
|
||||
//--- result
|
||||
return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BORDER_TYPE,type));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Writing parameters of object to file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::Save(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- write
|
||||
if(!CChartObjectLabel::Save(file_handle))
|
||||
return(false);
|
||||
//--- write value of the "X-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_XSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write value of the "Y-size" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_YSIZE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- write background color
|
||||
if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR))!=sizeof(long))
|
||||
return(false);
|
||||
//--- write value of the "Border type" property
|
||||
if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BORDER_TYPE),INT_VALUE)!=sizeof(int))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reading parameters of object from file |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CChartObjectRectLabel::Load(const int file_handle)
|
||||
{
|
||||
string str;
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE || m_chart_id==-1)
|
||||
return(false);
|
||||
//--- read
|
||||
if(!CChartObjectLabel::Load(file_handle))
|
||||
return(false);
|
||||
//--- read value of the "X-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_XSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read value of the "Y-size" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_YSIZE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- read background color
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_BGCOLOR,FileReadLong(file_handle)))
|
||||
return(false);
|
||||
//--- read value of the "Border type" property
|
||||
if(!ObjectSetInteger(m_chart_id,m_name,OBJPROP_BORDER_TYPE,FileReadInteger(file_handle,INT_VALUE)))
|
||||
return(false);
|
||||
//--- successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,268 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| BmpButton.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsBmpControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CBmpButton |
|
||||
//| Usage: control that is displayed by |
|
||||
//| the CChartObjectBmpLabel object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CBmpButton : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectBmpLabel m_button; // chart object
|
||||
//--- parameters of the chart object
|
||||
int m_border; // border width
|
||||
string m_bmp_off_name; // name of BMP file for the "OFF" state (default state)
|
||||
string m_bmp_on_name; // name of BMP file for the "ON" state
|
||||
string m_bmp_passive_name;
|
||||
string m_bmp_active_name;
|
||||
|
||||
public:
|
||||
CBmpButton(void);
|
||||
~CBmpButton(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- parameters of the chart object
|
||||
int Border(void) const { return(m_border); }
|
||||
bool Border(const int value);
|
||||
bool BmpNames(const string off="",const string on="");
|
||||
string BmpOffName(void) const { return(m_bmp_off_name); }
|
||||
bool BmpOffName(const string name);
|
||||
string BmpOnName(void) const { return(m_bmp_on_name); }
|
||||
bool BmpOnName(const string name);
|
||||
string BmpPassiveName(void) const { return(m_bmp_passive_name); }
|
||||
bool BmpPassiveName(const string name);
|
||||
string BmpActiveName(void) const { return(m_bmp_active_name); }
|
||||
bool BmpActiveName(const string name);
|
||||
//--- state
|
||||
bool Pressed(void) const { return(m_button.State()); }
|
||||
bool Pressed(const bool pressed) { return(m_button.State(pressed)); }
|
||||
//--- properties
|
||||
bool Locking(void) const { return(IS_CAN_LOCK); }
|
||||
void Locking(const bool locking);
|
||||
|
||||
protected:
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetZOrder(void) { return(m_button.Z_Order(m_zorder)); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
virtual bool OnChange(void);
|
||||
//--- íîâûå îáðàáîò÷èêè
|
||||
virtual bool OnActivate(void);
|
||||
virtual bool OnDeactivate(void);
|
||||
virtual bool OnMouseDown(void);
|
||||
virtual bool OnMouseUp(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CBmpButton::CBmpButton(void) : m_border(0),
|
||||
m_bmp_off_name(NULL),
|
||||
m_bmp_on_name(NULL),
|
||||
m_bmp_passive_name(NULL),
|
||||
m_bmp_active_name(NULL)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CBmpButton::~CBmpButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_button.Create(chart,name,subwin,x1,y1))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set border width |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::Border(const int value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_border=value;
|
||||
//--- set up the chart object
|
||||
return(m_button.Width(value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set two images at once |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::BmpNames(const string off,const string on)
|
||||
{
|
||||
//--- save new values of parameters
|
||||
m_bmp_off_name=off;
|
||||
m_bmp_on_name =on;
|
||||
//--- set up the chart object
|
||||
if(!m_button.BmpFileOff(off))
|
||||
return(false);
|
||||
if(!m_button.BmpFileOn(on))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set image for the "OFF" state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::BmpOffName(const string name)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_bmp_off_name=name;
|
||||
//--- set up the chart object
|
||||
if(!m_button.BmpFileOff(name))
|
||||
return(false);
|
||||
//--- set size by image dimensions
|
||||
Width(m_button.X_Size());
|
||||
Height(m_button.Y_Size());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set image for the "ON" state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::BmpOnName(const string name)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_bmp_on_name=name;
|
||||
//--- set up the chart object
|
||||
if(!m_button.BmpFileOn(name))
|
||||
return(false);
|
||||
//--- set size by image dimensions
|
||||
Width(m_button.X_Size());
|
||||
Height(m_button.Y_Size());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set image for the "OFF" state (passive) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::BmpPassiveName(const string name)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_bmp_passive_name=name;
|
||||
//--- set up the chart object
|
||||
if(!IS_ACTIVE)
|
||||
return(BmpOffName(name));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set image for the "OFF" state (active) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::BmpActiveName(const string name)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_bmp_active_name=name;
|
||||
//--- set up the chart object
|
||||
if(IS_ACTIVE)
|
||||
return(BmpOffName(name));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Locking flag |
|
||||
//+------------------------------------------------------------------+
|
||||
void CBmpButton::Locking(const bool flag)
|
||||
{
|
||||
if(flag)
|
||||
PropFlagsSet(WND_PROP_FLAG_CAN_LOCK);
|
||||
else
|
||||
PropFlagsReset(WND_PROP_FLAG_CAN_LOCK);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnShow(void)
|
||||
{
|
||||
return(m_button.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnHide(void)
|
||||
{
|
||||
return(m_button.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnChange(void)
|
||||
{
|
||||
//--- set up the chart object
|
||||
return(m_button.Width(m_border) && m_button.BmpFileOff(m_bmp_off_name) && m_button.BmpFileOn(m_bmp_on_name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of activating the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnActivate(void)
|
||||
{
|
||||
if(m_bmp_active_name!=NULL)
|
||||
BmpOffName(m_bmp_active_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of deactivating the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnDeactivate(void)
|
||||
{
|
||||
if(m_bmp_passive_name!=NULL)
|
||||
BmpOffName(m_bmp_passive_name);
|
||||
if(!IS_CAN_LOCK)
|
||||
Pressed(false);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnMouseDown(void)
|
||||
{
|
||||
if(!IS_CAN_LOCK)
|
||||
Pressed(!Pressed());
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::OnMouseDown());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CBmpButton::OnMouseUp(void)
|
||||
{
|
||||
//--- depress the button if it is not fixed
|
||||
if(m_button.State() && !IS_CAN_LOCK)
|
||||
m_button.State(false);
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::OnMouseUp());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,146 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Button.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CButton |
|
||||
//| Usage: control that is displayed by |
|
||||
//| the CChartObjectButton object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CButton : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectButton m_button; // chart object
|
||||
|
||||
public:
|
||||
CButton(void);
|
||||
~CButton(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- state
|
||||
bool Pressed(void) const { return(m_button.State()); }
|
||||
bool Pressed(const bool pressed) { return(m_button.State(pressed)); }
|
||||
//--- properties
|
||||
bool Locking(void) const { return(IS_CAN_LOCK); }
|
||||
void Locking(const bool flag);
|
||||
|
||||
protected:
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetText(void) { return(m_button.Description(m_text)); }
|
||||
virtual bool OnSetColor(void) { return(m_button.Color(m_color)); }
|
||||
virtual bool OnSetColorBackground(void) { return(m_button.BackColor(m_color_background)); }
|
||||
virtual bool OnSetColorBorder(void) { return(m_button.BorderColor(m_color_border)); }
|
||||
virtual bool OnSetFont(void) { return(m_button.Font(m_font)); }
|
||||
virtual bool OnSetFontSize(void) { return(m_button.FontSize(m_font_size)); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
virtual bool OnResize(void);
|
||||
//--- íîâûå îáðàáîò÷èêè
|
||||
virtual bool OnMouseDown(void);
|
||||
virtual bool OnMouseUp(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CButton::CButton(void)
|
||||
{
|
||||
m_color =CONTROLS_BUTTON_COLOR;
|
||||
m_color_background=CONTROLS_BUTTON_COLOR_BG;
|
||||
m_color_border =CONTROLS_BUTTON_COLOR_BORDER;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CButton::~CButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height()))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Locking flag |
|
||||
//+------------------------------------------------------------------+
|
||||
void CButton::Locking(const bool flag)
|
||||
{
|
||||
if(flag)
|
||||
PropFlagsSet(WND_PROP_FLAG_CAN_LOCK);
|
||||
else
|
||||
PropFlagsReset(WND_PROP_FLAG_CAN_LOCK);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnShow(void)
|
||||
{
|
||||
return(m_button.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnHide(void)
|
||||
{
|
||||
return(m_button.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnResize(void)
|
||||
{
|
||||
//--- resize the chart object
|
||||
return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnMouseDown(void)
|
||||
{
|
||||
if(!IS_CAN_LOCK)
|
||||
Pressed(!Pressed());
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::OnMouseDown());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CButton::OnMouseUp(void)
|
||||
{
|
||||
//--- depress the button if it is not fixed
|
||||
if(m_button.State() && !IS_CAN_LOCK)
|
||||
m_button.State(false);
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::OnMouseUp());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,183 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| CheckBox.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include "Edit.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
#resource "res\\CheckBoxOn.bmp"
|
||||
#resource "res\\CheckBoxOff.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CCheckBox |
|
||||
//| Usage: class that implements the "CheckBox" control |
|
||||
//+------------------------------------------------------------------+
|
||||
class CCheckBox : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CBmpButton m_button; // button object
|
||||
CEdit m_label; // label object
|
||||
//--- data
|
||||
int m_value; // value
|
||||
|
||||
public:
|
||||
CCheckBox(void);
|
||||
~CCheckBox(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- settings
|
||||
string Text(void) const { return(m_label.Text()); }
|
||||
bool Text(const string value) { return(m_label.Text(value)); }
|
||||
color Color(void) const { return(m_label.Color()); }
|
||||
bool Color(const color value) { return(m_label.Color(value)); }
|
||||
//--- state
|
||||
bool Checked(void) const { return(m_button.Pressed()); }
|
||||
bool Checked(const bool flag) { return(m_button.Pressed(flag)); }
|
||||
//--- data
|
||||
int Value(void) const { return(m_value); }
|
||||
void Value(const int value) { m_value=value; }
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateButton(void);
|
||||
virtual bool CreateLabel(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickButton(void);
|
||||
virtual bool OnClickLabel(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CCheckBox)
|
||||
ON_EVENT(ON_CLICK,m_button,OnClickButton)
|
||||
ON_EVENT(ON_CLICK,m_label,OnClickLabel)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CCheckBox::CCheckBox(void) : m_value(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CCheckBox::~CCheckBox(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateButton())
|
||||
return(false);
|
||||
if(!CreateLabel())
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::CreateButton(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_CHECK_BUTTON_X_OFF;
|
||||
int y1=CONTROLS_CHECK_BUTTON_Y_OFF;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
//--- create
|
||||
if(!m_button.Create(m_chart_id,m_name+"Button",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button.BmpNames("::res\\CheckBoxOff.bmp","::res\\CheckBoxOn.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_button))
|
||||
return(false);
|
||||
m_button.Locking(true);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create label |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::CreateLabel(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_CHECK_LABEL_X_OFF;
|
||||
int y1=CONTROLS_CHECK_LABEL_Y_OFF;
|
||||
int x2=Width();
|
||||
int y2=Height();
|
||||
//--- create
|
||||
if(!m_label.Create(m_chart_id,m_name+"Label",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_label.Text(m_name))
|
||||
return(false);
|
||||
if(!Add(m_label))
|
||||
return(false);
|
||||
m_label.ReadOnly(true);
|
||||
m_label.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG);
|
||||
m_label.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BG);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
FileWriteInteger(file_handle,Checked());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
if(!FileIsEnding(file_handle))
|
||||
Checked(FileReadInteger(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::OnClickButton(void)
|
||||
{
|
||||
//--- send the "changed state" event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on label |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckBox::OnClickLabel(void)
|
||||
{
|
||||
//--- change button state
|
||||
m_button.Pressed(!m_button.Pressed());
|
||||
//--- return the result of the button click handler
|
||||
return(OnClickButton());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,377 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| CheckGroup.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndClient.mqh"
|
||||
#include "CheckBox.mqh"
|
||||
#include <Arrays\ArrayString.mqh>
|
||||
#include <Arrays\ArrayLong.mqh>
|
||||
#include <Arrays\ArrayInt.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CCheckGroup |
|
||||
//| Usage: view and edit group of flags |
|
||||
//+------------------------------------------------------------------+
|
||||
class CCheckGroup : public CWndClient
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CCheckBox m_rows[]; // array of the row objects
|
||||
//--- set up
|
||||
int m_offset; // index of first visible row in array of rows
|
||||
int m_total_view; // number of visible rows
|
||||
int m_item_height; // height of visible row
|
||||
//--- data
|
||||
CArrayString m_strings; // array of rows
|
||||
CArrayLong m_values; // array of values
|
||||
CArrayInt m_states; // array of states
|
||||
long m_value; // current value
|
||||
int m_current; // index of current row in array of rows
|
||||
|
||||
public:
|
||||
CCheckGroup(void);
|
||||
~CCheckGroup(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
virtual void Destroy(const int reason=0);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- fill
|
||||
virtual bool AddItem(const string item,const long value=0);
|
||||
//--- data
|
||||
long Value(void) const;
|
||||
bool Value(const long value);
|
||||
int Check(const int idx) const;
|
||||
bool Check(const int idx,const int value);
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
bool CreateButton(int index);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnVScrollShow(void);
|
||||
virtual bool OnVScrollHide(void);
|
||||
virtual bool OnScrollLineDown(void);
|
||||
virtual bool OnScrollLineUp(void);
|
||||
virtual bool OnChangeItem(const int row_index);
|
||||
//--- redraw
|
||||
bool Redraw(void);
|
||||
bool RowState(const int index,const bool select);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CCheckGroup)
|
||||
ON_INDEXED_EVENT(ON_CHANGE,m_rows,OnChangeItem)
|
||||
EVENT_MAP_END(CWndClient)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CCheckGroup::CCheckGroup(void) : m_offset(0),
|
||||
m_total_view(0),
|
||||
m_item_height(CONTROLS_LIST_ITEM_HEIGHT),
|
||||
m_current(CONTROLS_INVALID_INDEX),
|
||||
m_value(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CCheckGroup::~CCheckGroup(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- determine the number of visible rows
|
||||
m_total_view=(y2-y1)/m_item_height;
|
||||
//--- check the number of visible rows
|
||||
if(m_total_view<1)
|
||||
return(false);
|
||||
//--- call method of the parent class
|
||||
if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- set up
|
||||
if(!m_background.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_background.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BORDER))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
ArrayResize(m_rows,m_total_view);
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
if(!CreateButton(i))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
void CCheckGroup::Destroy(const int reason)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
CWndClient::Destroy(reason);
|
||||
//--- clear items
|
||||
m_strings.Clear();
|
||||
m_values.Clear();
|
||||
m_states.Clear();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create "row" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::CreateButton(int index)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH+m_item_height*index;
|
||||
int x2=Width()-CONTROLS_BORDER_WIDTH;
|
||||
int y2=y1+m_item_height;
|
||||
//--- create
|
||||
if(!m_rows[index].Create(m_chart_id,m_name+"Item"+IntegerToString(index),m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_rows[index].Text(""))
|
||||
return(false);
|
||||
if(!Add(m_rows[index]))
|
||||
return(false);
|
||||
m_rows[index].Hide();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::AddItem(const string item,const long value)
|
||||
{
|
||||
//--- add
|
||||
if(!m_strings.Add(item))
|
||||
return(false);
|
||||
if(!m_values.Add(value))
|
||||
return(false);
|
||||
if(!m_states.Add(0))
|
||||
return(false);
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//--- exit if number of items does not exceed the size of visible area
|
||||
if(total<m_total_view+1)
|
||||
{
|
||||
if(IS_VISIBLE && total!=0)
|
||||
m_rows[total-1].Show();
|
||||
return(Redraw());
|
||||
}
|
||||
//--- if number of items exceeded the size of visible area
|
||||
if(total==m_total_view+1)
|
||||
{
|
||||
//--- enable vertical scrollbar
|
||||
if(!VScrolled(true))
|
||||
return(false);
|
||||
//--- and immediately make it invisible (if needed)
|
||||
if(!IS_VISIBLE)
|
||||
m_scroll_v.Visible(false);
|
||||
}
|
||||
//--- set up the scrollbar
|
||||
m_scroll_v.MaxPos(m_strings.Total()-m_total_view);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
long CCheckGroup::Value(void) const
|
||||
{
|
||||
return(m_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Value(const long value)
|
||||
{
|
||||
m_value=value;
|
||||
//---
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
int CCheckGroup::Check(const int idx) const
|
||||
{
|
||||
//--- check
|
||||
if(idx>=m_values.Total())
|
||||
return(0);
|
||||
//---
|
||||
return(m_states[idx]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Check(const int idx,const int value)
|
||||
{
|
||||
//--- check
|
||||
if(idx>=m_values.Total())
|
||||
return(false);
|
||||
//---
|
||||
bool res=(m_states.Update(idx,value) && Redraw());
|
||||
//--- change value
|
||||
if(res && idx<64)
|
||||
{
|
||||
if(m_rows[idx].Checked())
|
||||
Value(m_value|m_values.At(idx));
|
||||
else
|
||||
Value(m_value&(~m_values.At(idx)));
|
||||
}
|
||||
//---
|
||||
return(res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the group visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Show(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWndClient::Show())
|
||||
return(false);
|
||||
//--- loop by rows
|
||||
int total=m_values.Total();
|
||||
for(int i=total;i<m_total_view;i++)
|
||||
m_rows[i].Hide();
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
FileWriteLong(file_handle,Value());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
if(!FileIsEnding(file_handle))
|
||||
Value(FileReadLong(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Redraw |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::Redraw(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- copy text
|
||||
if(!m_rows[i].Text(m_strings[i+m_offset]))
|
||||
return(false);
|
||||
//--- select
|
||||
if(!RowState(i,m_states[i+m_offset]!=0))
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Change state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::RowState(const int index,const bool select)
|
||||
{
|
||||
//--- check index
|
||||
if(index<0 || index>=ArraySize(m_rows))
|
||||
return(true);
|
||||
//--- change state
|
||||
return(m_rows[index].Checked(select));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Show vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::OnVScrollShow(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to shown vertical scrollbar
|
||||
m_rows[i].Width(Width()-(CONTROLS_SCROLL_SIZE+CONTROLS_BORDER_WIDTH));
|
||||
}
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
{
|
||||
m_scroll_v.Visible(false);
|
||||
return(true);
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Hide vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::OnVScrollHide(void)
|
||||
{
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
return(true);
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to hidden vertical scroll bar
|
||||
m_rows[i].Width(Width()-CONTROLS_BORDER_WIDTH);
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll up for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::OnScrollLineUp(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll down for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::OnScrollLineDown(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of changing a "row" state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CCheckGroup::OnChangeItem(const int row_index)
|
||||
{
|
||||
//--- change value
|
||||
m_states.Update(row_index+m_offset,m_rows[row_index].Checked());
|
||||
if(row_index+m_offset<64)
|
||||
{
|
||||
if(m_rows[row_index].Checked())
|
||||
Value(m_value|m_values.At(row_index+m_offset));
|
||||
else
|
||||
Value(m_value&(~m_values.At(row_index+m_offset)));
|
||||
}
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,324 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ComboBox.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "Edit.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include "ListView.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Can not place the same file into resource twice
|
||||
#resource "res\\DropOn.bmp" // image file
|
||||
#resource "res\\DropOff.bmp" // image file
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CComboBox |
|
||||
//| Usage: drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
class CComboBox : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CEdit m_edit; // the entry field object
|
||||
CBmpButton m_drop; // the button object
|
||||
CListView m_list; // the drop-down list object
|
||||
//--- set up
|
||||
int m_item_height; // height of visible row
|
||||
int m_view_items; // number of visible rows in the drop-down list
|
||||
|
||||
public:
|
||||
CComboBox(void);
|
||||
~CComboBox(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- fill
|
||||
bool AddItem(const string item,const long value=0);
|
||||
//--- set up
|
||||
void ListViewItems(const int value) { m_view_items=value; }
|
||||
//--- data
|
||||
virtual bool ItemAdd(const string item,const long value=0) { return(m_list.ItemAdd(item,value)); }
|
||||
virtual bool ItemInsert(const int index,const string item,const long value=0) { return(m_list.ItemInsert(index,item,value)); }
|
||||
virtual bool ItemUpdate(const int index,const string item,const long value=0) { return(m_list.ItemUpdate(index,item,value)); }
|
||||
virtual bool ItemDelete(const int index) { return(m_list.ItemDelete(index)); }
|
||||
virtual bool ItemsClear(void) { return(m_list.ItemsClear()); }
|
||||
//--- data
|
||||
string Select(void) { return(m_edit.Text()); }
|
||||
bool Select(const int index);
|
||||
bool SelectByText(const string text);
|
||||
bool SelectByValue(const long value);
|
||||
//--- data (read only)
|
||||
long Value(void) { return(m_list.Value()); }
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateEdit(void);
|
||||
virtual bool CreateButton(void);
|
||||
virtual bool CreateList(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickEdit(void);
|
||||
virtual bool OnClickButton(void);
|
||||
virtual bool OnChangeList(void);
|
||||
//--- show drop-down list
|
||||
bool ListShow(void);
|
||||
bool ListHide(void);
|
||||
void CheckListHide(const int id,int x,int y);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CComboBox)
|
||||
ON_EVENT(ON_CLICK,m_edit,OnClickEdit)
|
||||
ON_EVENT(ON_CLICK,m_drop,OnClickButton)
|
||||
ON_EVENT(ON_CHANGE,m_list,OnChangeList)
|
||||
CheckListHide(id,(int)lparam,(int)dparam);
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CComboBox::CComboBox(void) : m_item_height(CONTROLS_COMBO_ITEM_HEIGHT),
|
||||
m_view_items(CONTROLS_COMBO_ITEMS_VIEW)
|
||||
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CComboBox::~CComboBox(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- check height
|
||||
if(y2-y1<CONTROLS_COMBO_MIN_HEIGHT)
|
||||
return(false);
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateEdit())
|
||||
return(false);
|
||||
if(!CreateButton())
|
||||
return(false);
|
||||
if(!CreateList())
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create main entry field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::CreateEdit(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_edit.Create(m_chart_id,m_name+"Edit",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!m_edit.Text(""))
|
||||
return(false);
|
||||
if(!m_edit.ReadOnly(true))
|
||||
return(false);
|
||||
if(!Add(m_edit))
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::CreateButton(void)
|
||||
{
|
||||
//--- right align button (try to make equal offsets from top and bottom)
|
||||
int x1=Width()-(CONTROLS_BUTTON_SIZE+CONTROLS_COMBO_BUTTON_X_OFF);
|
||||
int y1=(Height()-CONTROLS_BUTTON_SIZE)/2;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_drop.Create(m_chart_id,m_name+"Drop",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_drop.BmpNames("::res\\DropOff.bmp","::res\\DropOn.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_drop))
|
||||
return(false);
|
||||
m_drop.Locking(true);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::CreateList(void)
|
||||
{
|
||||
//--- create
|
||||
if(m_list.TotalView(m_view_items))
|
||||
{
|
||||
if(!m_list.Create(m_chart_id,m_name+"List",m_subwin,0,Height(),Width(),0))
|
||||
return(false);
|
||||
if(!Add(m_list))
|
||||
return(false);
|
||||
m_list.Hide();
|
||||
}
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::AddItem(const string item,const long value)
|
||||
{
|
||||
//--- add item to list
|
||||
return(m_list.AddItem(item,value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select item |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::Select(const int index)
|
||||
{
|
||||
if(!m_list.Select(index))
|
||||
return(false);
|
||||
//--- call the handler
|
||||
return(OnChangeList());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select item (by text) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::SelectByText(const string text)
|
||||
{
|
||||
if(!m_list.SelectByText(text))
|
||||
return(false);
|
||||
//--- call the handler
|
||||
return(OnChangeList());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select item (by value) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::SelectByValue(const long value)
|
||||
{
|
||||
if(!m_list.SelectByValue(value))
|
||||
return(false);
|
||||
//--- call the handler
|
||||
return(OnChangeList());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::Show(void)
|
||||
{
|
||||
m_edit.Show();
|
||||
m_drop.Show();
|
||||
m_list.Hide();
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
FileWriteLong(file_handle,Value());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
if(!FileIsEnding(file_handle))
|
||||
SelectByValue(FileReadLong(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on main entry field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::OnClickEdit(void)
|
||||
{
|
||||
//--- change button state
|
||||
if(!m_drop.Pressed(!m_drop.Pressed()))
|
||||
return(false);
|
||||
//--- call the click on button handler
|
||||
return(OnClickButton());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::OnClickButton(void)
|
||||
{
|
||||
//--- show or hide the drop-down list depending on the button state
|
||||
return((m_drop.Pressed()) ? ListShow() : ListHide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::OnChangeList(void)
|
||||
{
|
||||
string text=m_list.Select();
|
||||
//--- hide the list, depress the button
|
||||
ListHide();
|
||||
m_drop.Pressed(false);
|
||||
//--- set text in the main entry field
|
||||
m_edit.Text(text);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Show the drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::ListShow(void)
|
||||
{
|
||||
BringToTop();
|
||||
//--- show the list
|
||||
return(m_list.Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CComboBox::ListHide(void)
|
||||
{
|
||||
//--- hide the list
|
||||
return(m_list.Hide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide the drop-down element if necessary |
|
||||
//+------------------------------------------------------------------+
|
||||
void CComboBox::CheckListHide(const int id,int x,int y)
|
||||
{
|
||||
//--- check event ID
|
||||
if(id!=CHARTEVENT_CLICK)
|
||||
return;
|
||||
//--- check visibility of the drop-down element
|
||||
if(!m_list.IsVisible())
|
||||
return;
|
||||
//--- check mouse cursor's position
|
||||
y-=(int)ChartGetInteger(m_chart_id,CHART_WINDOW_YDISTANCE,m_subwin);
|
||||
if(!m_edit.Contains(x,y) && !m_list.Contains(x,y))
|
||||
{
|
||||
m_drop.Pressed(false);
|
||||
m_list.Hide();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,413 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DateDropList.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include "Picture.mqh"
|
||||
#include <Canvas\Canvas.mqh>
|
||||
#include <Tools\DateTime.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Enumerations |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- date modes
|
||||
enum ENUM_DATE_MODES
|
||||
{
|
||||
DATE_MODE_MON, // month mode
|
||||
DATE_MODE_YEAR // year mode
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Can not place the same file into resource twice
|
||||
#resource "res\\LeftTransp.bmp"
|
||||
#resource "res\\RightTransp.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDateDropList |
|
||||
//| Usage: drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDateDropList : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CBmpButton m_dec; // the button object
|
||||
CBmpButton m_inc; // the button object
|
||||
CPicture m_list; // the drop-down list object
|
||||
CCanvas m_canvas; // and its canvas
|
||||
//--- data
|
||||
CDateTime m_value; // current value
|
||||
//--- variable
|
||||
ENUM_DATE_MODES m_mode; // operation mode
|
||||
CRect m_click_rect[32]; // array of click sensibility areas on canvas
|
||||
|
||||
public:
|
||||
CDateDropList(void);
|
||||
~CDateDropList(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- data
|
||||
datetime Value(void) { return(StructToTime(m_value)); }
|
||||
void Value(datetime value) { m_value.Date(value); }
|
||||
void Value(MqlDateTime& value) { m_value=value; }
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
|
||||
protected:
|
||||
//--- internal event handlers
|
||||
virtual bool OnClick(void);
|
||||
//--- create dependent controls
|
||||
virtual bool CreateButtons(void);
|
||||
virtual bool CreateList(void);
|
||||
//--- draw
|
||||
void DrawCanvas(void);
|
||||
void DrawClickRect(const int idx,int x,int y,string text,const uint clr,uint alignment=0);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickDec(void);
|
||||
virtual bool OnClickInc(void);
|
||||
virtual bool OnClickList(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CDateDropList)
|
||||
ON_EVENT(ON_CLICK,m_dec,OnClickDec)
|
||||
ON_EVENT(ON_CLICK,m_inc,OnClickInc)
|
||||
ON_EVENT(ON_CLICK,m_list,OnClickList)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDateDropList::CDateDropList(void) : m_mode(DATE_MODE_MON)
|
||||
{
|
||||
ZeroMemory(m_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDateDropList::~CDateDropList(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- need to find dimensions depending on font size
|
||||
//--- width 7 columns + 2 offsets
|
||||
int w=7*(2*CONTROLS_FONT_SIZE)+2*CONTROLS_FONT_SIZE;
|
||||
//--- header height + 7 rows
|
||||
int h=(CONTROLS_BUTTON_SIZE+4*CONTROLS_BORDER_WIDTH)+7*(2*CONTROLS_FONT_SIZE);
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x1+w,y1+h))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateList())
|
||||
return(false);
|
||||
if(!CreateButtons())
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::CreateList(void)
|
||||
{
|
||||
//--- create object
|
||||
if(!m_list.Create(m_chart_id,m_name+"List",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!Add(m_list))
|
||||
return(false);
|
||||
//--- create canvas
|
||||
if(!m_canvas.Create(m_name,Width(),Height()))
|
||||
return(false);
|
||||
m_canvas.FontSet(CONTROLS_FONT_NAME,CONTROLS_FONT_SIZE*(-10));
|
||||
m_list.BmpName(m_canvas.ResourceName());
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create buttons |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::CreateButtons(void)
|
||||
{
|
||||
//--- right align button (try to make equal offsets from top and bottom)
|
||||
int x1=2*CONTROLS_BORDER_WIDTH;
|
||||
int y1=2*CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create "Dec" button
|
||||
if(!m_dec.Create(m_chart_id,m_name+"Dec",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_dec.BmpNames("::res\\LeftTransp.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_dec))
|
||||
return(false);
|
||||
//---
|
||||
x2=Width()-2*CONTROLS_BORDER_WIDTH;
|
||||
x1=x2-CONTROLS_BUTTON_SIZE;
|
||||
//--- create "Inc" button
|
||||
if(!m_inc.Create(m_chart_id,m_name+"Inc",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_inc.BmpNames("::res\\RightTransp.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_inc))
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::Show(void)
|
||||
{
|
||||
//--- draw canvas
|
||||
DrawCanvas();
|
||||
//--- call method of the parent class
|
||||
return(CWndContainer::Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::OnClickDec(void)
|
||||
{
|
||||
switch(m_mode)
|
||||
{
|
||||
//--- within the month
|
||||
case DATE_MODE_MON:
|
||||
m_value.MonDec();
|
||||
break;
|
||||
//--- within the year
|
||||
case DATE_MODE_YEAR:
|
||||
m_value.YearDec();
|
||||
break;
|
||||
}
|
||||
DrawCanvas();
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::OnClickInc(void)
|
||||
{
|
||||
switch(m_mode)
|
||||
{
|
||||
//--- within the month
|
||||
case DATE_MODE_MON:
|
||||
m_value.MonInc();
|
||||
break;
|
||||
//--- within the year
|
||||
case DATE_MODE_YEAR:
|
||||
m_value.YearInc();
|
||||
break;
|
||||
}
|
||||
DrawCanvas();
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on picture |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::OnClickList(void)
|
||||
{
|
||||
m_mouse_x=m_list.MouseX();
|
||||
m_mouse_y=m_list.MouseY();
|
||||
//---
|
||||
OnClick();
|
||||
//---
|
||||
m_mouse_x=0;
|
||||
m_mouse_y=0;
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "click" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDateDropList::OnClick(void)
|
||||
{
|
||||
for(int i=0;i<32;i++)
|
||||
{
|
||||
if(m_click_rect[i].Contains(m_mouse_x,m_mouse_y))
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
//--- clicked on the header
|
||||
switch(m_mode)
|
||||
{
|
||||
//--- within the month
|
||||
case DATE_MODE_MON:
|
||||
//--- switch to the "within the year" mode
|
||||
m_mode=DATE_MODE_YEAR;
|
||||
DrawCanvas();
|
||||
break;
|
||||
//--- within the year
|
||||
case DATE_MODE_YEAR:
|
||||
//--- do nothing for now
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- selected
|
||||
switch(m_mode)
|
||||
{
|
||||
//--- within the month
|
||||
case DATE_MODE_MON:
|
||||
m_value.Day(i);
|
||||
Hide();
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
break;
|
||||
//--- within the year
|
||||
case DATE_MODE_YEAR:
|
||||
m_value.Mon(i);
|
||||
m_mode=DATE_MODE_MON;
|
||||
DrawCanvas();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Draw canvas |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDateDropList::DrawCanvas(void)
|
||||
{
|
||||
int x,y;
|
||||
int dx,dy;
|
||||
string text;
|
||||
uint text_al=TA_CENTER|TA_VCENTER;
|
||||
CDateTime tmp_date;
|
||||
int rows,cols;
|
||||
int idx;
|
||||
//--- zero out array of areas
|
||||
for(int i=0;i<32;i++)
|
||||
ZeroMemory(m_click_rect[i]);
|
||||
//---
|
||||
m_canvas.Erase(COLOR2RGB(CONTROLS_EDIT_COLOR_BG));
|
||||
m_canvas.Rectangle(0,0,Width()-1,Height()-1,COLOR2RGB(CONTROLS_EDIT_COLOR_BORDER));
|
||||
x=Width()/2;
|
||||
y=CONTROLS_BUTTON_SIZE/2+2*CONTROLS_BORDER_WIDTH;
|
||||
switch(m_mode)
|
||||
{
|
||||
//--- within the month
|
||||
case DATE_MODE_MON:
|
||||
text=m_value.MonthName()+" "+IntegerToString(m_value.year);
|
||||
DrawClickRect(0,x,y,text,COLOR2RGB(CONTROLS_EDIT_COLOR),text_al);
|
||||
rows=6;
|
||||
cols=7;
|
||||
x=dx=Width()/(cols+1);
|
||||
y+=y;
|
||||
dy=(Height()-y-2*CONTROLS_BORDER_WIDTH)/(rows+1);
|
||||
y+=dy/2;
|
||||
for(int i=0;i<cols;i++,x+=dx)
|
||||
m_canvas.TextOut(x,y,m_value.ShortDayName(i),COLOR2RGB(CONTROLS_EDIT_COLOR),text_al);
|
||||
//--- backup data
|
||||
tmp_date=m_value;
|
||||
//--- find the beginning of the first displayed week
|
||||
tmp_date.DayDec(tmp_date.day_of_week);
|
||||
while(tmp_date.mon==m_value.mon && tmp_date.day!=1)
|
||||
tmp_date.DayDec(cols);
|
||||
//--- draw
|
||||
idx=1;
|
||||
y+=dy;
|
||||
for(int i=0;i<rows;i++,y+=dy)
|
||||
{
|
||||
x=dx;
|
||||
for(int j=0;j<cols;j++,x+=dx)
|
||||
{
|
||||
text=IntegerToString(tmp_date.day);
|
||||
if(tmp_date.mon==m_value.mon)
|
||||
{
|
||||
if(tmp_date.day==m_value.day)
|
||||
m_canvas.FillRectangle(x-dx/2,y-dy/2,x+dx/2,y+dy/2,COLOR2RGB(CONTROLS_COLOR_BG_SEL));
|
||||
DrawClickRect(idx++,x,y,text,COLOR2RGB(CONTROLS_EDIT_COLOR),text_al);
|
||||
}
|
||||
else
|
||||
m_canvas.TextOut(x,y,text,COLOR2RGB(CONTROLS_BUTTON_COLOR_BORDER),text_al);
|
||||
tmp_date.DayInc();
|
||||
}
|
||||
}
|
||||
break;
|
||||
//--- within the year
|
||||
case DATE_MODE_YEAR:
|
||||
text=IntegerToString(m_value.year);
|
||||
DrawClickRect(0,x,y,text,COLOR2RGB(CONTROLS_EDIT_COLOR),text_al);
|
||||
rows=3;
|
||||
cols=4;
|
||||
x=dx=Width()/(cols+1);
|
||||
y+=y;
|
||||
dy=(Height()-y)/rows;
|
||||
y+=dy/2;
|
||||
for(int i=0;i<rows*cols;i++)
|
||||
{
|
||||
if(i+1==m_value.mon)
|
||||
m_canvas.FillRectangle(x-dx/2,y-dy/4,x+dx/2,y+dy/4,COLOR2RGB(CONTROLS_COLOR_BG_SEL));
|
||||
DrawClickRect(i+1,x,y,m_value.ShortMonthName(i+1),COLOR2RGB(CONTROLS_EDIT_COLOR),text_al);
|
||||
if(i%cols==cols-1)
|
||||
{
|
||||
x=dx;
|
||||
y+=dy;
|
||||
}
|
||||
else
|
||||
x+=dx;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_canvas.Update();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDateDropList::DrawClickRect(const int idx,int x,int y,string text,const uint clr,uint alignment)
|
||||
{
|
||||
int text_w,text_h;
|
||||
//--- display the text
|
||||
m_canvas.TextOut(x,y,text,clr,alignment);
|
||||
//--- determine area occupied by text
|
||||
m_canvas.TextSize(text,text_w,text_h);
|
||||
//--- convert relative coordinated to absolute ones
|
||||
x+=Left();
|
||||
y+=Top();
|
||||
//--- check flags of horizontal alignment
|
||||
switch(alignment&(TA_LEFT|TA_CENTER|TA_RIGHT))
|
||||
{
|
||||
case TA_LEFT:
|
||||
m_click_rect[idx].left=x;
|
||||
break;
|
||||
case TA_CENTER:
|
||||
m_click_rect[idx].left=x-text_w/2;
|
||||
break;
|
||||
case TA_RIGHT:
|
||||
m_click_rect[idx].left=x-text_w;
|
||||
break;
|
||||
}
|
||||
m_click_rect[idx].Width(text_w);
|
||||
//--- check flags of vertical alignment
|
||||
switch(alignment&(TA_TOP|TA_VCENTER|TA_BOTTOM))
|
||||
{
|
||||
case TA_TOP:
|
||||
m_click_rect[idx].top=y;
|
||||
break;
|
||||
case TA_VCENTER:
|
||||
m_click_rect[idx].top=y-text_h/2;
|
||||
break;
|
||||
case TA_BOTTOM:
|
||||
m_click_rect[idx].top=y-text_h;
|
||||
break;
|
||||
}
|
||||
m_click_rect[idx].Height(text_h);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,264 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DatePicker.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "Edit.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include "DateDropList.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- Can not place the same file into resource twice
|
||||
#resource "res\\DateDropOn.bmp" // image file
|
||||
#resource "res\\DateDropOff.bmp" // image file
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDatePicker |
|
||||
//| Usage: date picker |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDatePicker : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CEdit m_edit; // the entry field object
|
||||
CBmpButton m_drop; // the button object
|
||||
CDateDropList m_list; // the drop-down list object
|
||||
//--- data
|
||||
datetime m_value; // current value
|
||||
|
||||
public:
|
||||
CDatePicker(void);
|
||||
~CDatePicker(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- data
|
||||
datetime Value(void) const { return(m_value); }
|
||||
void Value(datetime value) { m_edit.Text(TimeToString(m_value=value,TIME_DATE)); }
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateEdit(void);
|
||||
virtual bool CreateButton(void);
|
||||
virtual bool CreateList(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickEdit(void);
|
||||
virtual bool OnClickButton(void);
|
||||
virtual bool OnChangeList(void);
|
||||
//--- show drop-down list
|
||||
bool ListShow(void);
|
||||
bool ListHide(void);
|
||||
void CheckListHide(const int id,int x,int y);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CDatePicker)
|
||||
ON_EVENT(ON_CLICK,m_edit,OnClickEdit)
|
||||
ON_EVENT(ON_CLICK,m_drop,OnClickButton)
|
||||
ON_EVENT(ON_CHANGE,m_list,OnChangeList)
|
||||
CheckListHide(id,(int)lparam,(int)dparam);
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDatePicker::CDatePicker(void) : m_value(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDatePicker::~CDatePicker(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateEdit())
|
||||
return(false);
|
||||
if(!CreateButton())
|
||||
return(false);
|
||||
if(!CreateList())
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create main entry field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::CreateEdit(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_edit.Create(m_chart_id,m_name+"Edit",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!m_edit.Text(""))
|
||||
return(false);
|
||||
if(!m_edit.ReadOnly(true))
|
||||
return(false);
|
||||
if(!Add(m_edit))
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::CreateButton(void)
|
||||
{
|
||||
//--- right align button (try to make equal offsets from top and bottom)
|
||||
int x1=Width()-(2*CONTROLS_BUTTON_SIZE+CONTROLS_COMBO_BUTTON_X_OFF);
|
||||
int y1=(Height()-CONTROLS_BUTTON_SIZE)/2;
|
||||
int x2=x1+2*CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_drop.Create(m_chart_id,m_name+"Drop",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_drop.BmpNames("::res\\DateDropOff.bmp","::res\\DateDropOn.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_drop))
|
||||
return(false);
|
||||
m_drop.Locking(true);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::CreateList(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_list.Create(m_chart_id,m_name+"List",m_subwin,0,Height()-1,Width(),0))
|
||||
return(false);
|
||||
if(!Add(m_list))
|
||||
return(false);
|
||||
m_list.Hide();
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::Show(void)
|
||||
{
|
||||
m_edit.Show();
|
||||
m_drop.Show();
|
||||
m_list.Hide();
|
||||
//--- call method of the parent class
|
||||
return(CWnd::Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| save |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- write
|
||||
FileWriteLong(file_handle,Value());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| load |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- load
|
||||
if(!FileIsEnding(file_handle))
|
||||
Value(FileReadLong(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on main entry field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::OnClickEdit(void)
|
||||
{
|
||||
//--- change button state
|
||||
if(!m_drop.Pressed(!m_drop.Pressed()))
|
||||
return(false);
|
||||
//--- call the click on button handler
|
||||
return(OnClickButton());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::OnClickButton(void)
|
||||
{
|
||||
//--- show or hide the drop-down list depending on the button state
|
||||
return((m_drop.Pressed()) ? ListShow():ListHide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of change on drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::OnChangeList(void)
|
||||
{
|
||||
string text=TimeToString(m_value=m_list.Value(),TIME_DATE);
|
||||
//--- hide the list, depress the button
|
||||
ListHide();
|
||||
m_drop.Pressed(false);
|
||||
//--- set text in the main entry field
|
||||
m_edit.Text(text);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Show the drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::ListShow(void)
|
||||
{
|
||||
//--- set value
|
||||
m_list.Value(m_value);
|
||||
//--- show the list
|
||||
return(m_list.Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide drop-down list |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDatePicker::ListHide(void)
|
||||
{
|
||||
//--- hide the list
|
||||
return(m_list.Hide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide the drop-down element if necessary |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDatePicker::CheckListHide(const int id,int x,int y)
|
||||
{
|
||||
//--- check event ID
|
||||
if(id!=CHARTEVENT_CLICK)
|
||||
return;
|
||||
//--- check visibility of the drop-down element
|
||||
if(!m_list.IsVisible())
|
||||
return;
|
||||
//--- check mouse cursor's position
|
||||
y-=(int)ChartGetInteger(m_chart_id,CHART_WINDOW_YDISTANCE,m_subwin);
|
||||
if(!m_edit.Contains(x,y) && !m_list.Contains(x,y))
|
||||
{
|
||||
m_drop.Pressed(false);
|
||||
m_list.Hide();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,190 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Defines.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Enumerations |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- properties flags
|
||||
enum ENUM_WND_PROP_FLAGS
|
||||
{
|
||||
WND_PROP_FLAG_CAN_DBL_CLICK = 1, // can be double clicked by mouse
|
||||
WND_PROP_FLAG_CAN_DRAG = 2, // can be dragged by mouse
|
||||
WND_PROP_FLAG_CLICKS_BY_PRESS= 4, // generates the "click" event series on pressing left mouse button
|
||||
WND_PROP_FLAG_CAN_LOCK = 8, // control with fixed state (usually it is a button)
|
||||
WND_PROP_FLAG_READ_ONLY =16 // read only (usually it is a edit)
|
||||
};
|
||||
//--- state flags
|
||||
enum ENUM_WND_STATE_FLAGS
|
||||
{
|
||||
WND_STATE_FLAG_ENABLE = 1, // "object is enabled" flag
|
||||
WND_STATE_FLAG_VISIBLE = 2, // "object is visible" flag
|
||||
WND_STATE_FLAG_ACTIVE = 4, // "object is active" flag
|
||||
};
|
||||
//--- mouse flags
|
||||
enum ENUM_MOUSE_FLAGS
|
||||
{
|
||||
MOUSE_INVALID_FLAGS =-1, // no buttons state
|
||||
MOUSE_EMPTY = 0, // buttons are not pressed
|
||||
MOUSE_LEFT = 1, // left button pressed
|
||||
MOUSE_RIGHT = 2 // right button pressed
|
||||
};
|
||||
//--- alignment flags
|
||||
enum ENUM_WND_ALIGN_FLAGS
|
||||
{
|
||||
WND_ALIGN_NONE = 0, // no alignment
|
||||
WND_ALIGN_LEFT = 1, // align by left border
|
||||
WND_ALIGN_TOP = 2, // align by top border
|
||||
WND_ALIGN_RIGHT = 4, // align by right border
|
||||
WND_ALIGN_BOTTOM = 8, // align by bottom border
|
||||
WND_ALIGN_WIDTH = WND_ALIGN_LEFT|WND_ALIGN_RIGHT, // justify
|
||||
WND_ALIGN_HEIGHT = WND_ALIGN_TOP|WND_ALIGN_BOTTOM, // align by top and bottom border
|
||||
WND_ALIGN_CLIENT = WND_ALIGN_WIDTH|WND_ALIGN_HEIGHT // align by all sides
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Drawing styles and colors |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- common
|
||||
#define CONTROLS_FONT_NAME "Trebuchet MS"
|
||||
#define CONTROLS_FONT_SIZE (10)
|
||||
//--- Text
|
||||
#define CONTROLS_COLOR_TEXT C'0x3B,0x29,0x28'
|
||||
#define CONTROLS_COLOR_TEXT_SEL White
|
||||
#define CONTROLS_COLOR_BG White
|
||||
#define CONTROLS_COLOR_BG_SEL C'0x33,0x99,0xFF'
|
||||
//--- Button
|
||||
#define CONTROLS_BUTTON_COLOR C'0x3B,0x29,0x28'
|
||||
#define CONTROLS_BUTTON_COLOR_BG C'0xDD,0xE2,0xEB'
|
||||
#define CONTROLS_BUTTON_COLOR_BORDER C'0xB2,0xC3,0xCF'
|
||||
//--- Label
|
||||
#define CONTROLS_LABEL_COLOR C'0x3B,0x29,0x28'
|
||||
//--- Edit
|
||||
#define CONTROLS_EDIT_COLOR C'0x3B,0x29,0x28'
|
||||
#define CONTROLS_EDIT_COLOR_BG White
|
||||
#define CONTROLS_EDIT_COLOR_BORDER C'0xB2,0xC3,0xCF'
|
||||
//--- Scrolls
|
||||
#define CONTROLS_SCROLL_COLOR_BG C'0xEC,0xEC,0xEC'
|
||||
#define CONTROLS_SCROLL_COLOR_BORDER C'0xD3,0xD3,0xD3'
|
||||
//--- Client
|
||||
#define CONTROLS_CLIENT_COLOR_BG C'0xDE,0xDE,0xDE'
|
||||
#define CONTROLS_CLIENT_COLOR_BORDER C'0x2C,0x2C,0x2C'
|
||||
//--- ListView
|
||||
#define CONTROLS_LISTITEM_COLOR_TEXT C'0x3B,0x29,0x28'
|
||||
#define CONTROLS_LISTITEM_COLOR_TEXT_SEL White
|
||||
#define CONTROLS_LISTITEM_COLOR_BG White
|
||||
#define CONTROLS_LISTITEM_COLOR_BG_SEL C'0x33,0x99,0xFF'
|
||||
#define CONTROLS_LIST_COLOR_BG White
|
||||
#define CONTROLS_LIST_COLOR_BORDER C'0xB2,0xC3,0xCF'
|
||||
//--- CheckGroup
|
||||
#define CONTROLS_CHECKGROUP_COLOR_BG C'0xF7,0xF7,0xF7'
|
||||
#define CONTROLS_CHECKGROUP_COLOR_BORDER C'0xB2,0xC3,0xCF'
|
||||
//--- RadioGroup
|
||||
#define CONTROLS_RADIOGROUP_COLOR_BG C'0xF7,0xF7,0xF7'
|
||||
#define CONTROLS_RADIOGROUP_COLOR_BORDER C'0xB2,0xC3,0xCF'
|
||||
//--- Dialog
|
||||
#define CONTROLS_DIALOG_COLOR_BORDER_LIGHT White
|
||||
#define CONTROLS_DIALOG_COLOR_BORDER_DARK C'0xB6,0xB6,0xB6'
|
||||
#define CONTROLS_DIALOG_COLOR_BG C'0xF0,0xF0,0xF0'
|
||||
#define CONTROLS_DIALOG_COLOR_CAPTION_TEXT C'0x28,0x29,0x3B'
|
||||
#define CONTROLS_DIALOG_COLOR_CLIENT_BG C'0xF7,0xF7,0xF7'
|
||||
#define CONTROLS_DIALOG_COLOR_CLIENT_BORDER C'0xC8,0xC8,0xC8'
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constants for the controls |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- common
|
||||
#define CONTROLS_INVALID_ID (-1) // invalid ID
|
||||
#define CONTROLS_INVALID_INDEX (-1) // invalid index of array
|
||||
#define CONTROLS_SELF_MESSAGE (-1) // message to oneself
|
||||
#define CONTROLS_MAXIMUM_ID (10000) // maximum number of IDs in application
|
||||
#define CONTROLS_BORDER_WIDTH (1) // border width
|
||||
#define CONTROLS_SUBWINDOW_GAP (3) // gap between sub-windows along the Y axis
|
||||
#define CONTROLS_DRAG_SPACING (50) // sensitivity threshold for dragging
|
||||
#define CONTROLS_DBL_CLICK_TIME (100) // double click interval
|
||||
//--- BmpButton
|
||||
#define CONTROLS_BUTTON_SIZE (16) // default size of button (16 x 16)
|
||||
//--- Scrolls
|
||||
#define CONTROLS_SCROLL_SIZE (18) // default lateral size of scrollbar
|
||||
#define CONTROLS_SCROLL_THUMB_SIZE (22) // default length of scroll box
|
||||
//--- RadioButton
|
||||
#define CONTROLS_RADIO_BUTTON_X_OFF (3) // X offset of radio button (for RadioButton)
|
||||
#define CONTROLS_RADIO_BUTTON_Y_OFF (3) // Y offset of radio button (for RadioButton)
|
||||
#define CONTROLS_RADIO_LABEL_X_OFF (20) // X offset of label (for RadioButton)
|
||||
#define CONTROLS_RADIO_LABEL_Y_OFF (0) // Y offset of label (for RadioButton)
|
||||
//--- CheckBox
|
||||
#define CONTROLS_CHECK_BUTTON_X_OFF (3) // X offset of check button (for CheckBox)
|
||||
#define CONTROLS_CHECK_BUTTON_Y_OFF (3) // Y offset of check button (for CheckBox)
|
||||
#define CONTROLS_CHECK_LABEL_X_OFF (20) // X offset of label (for CheckBox)
|
||||
#define CONTROLS_CHECK_LABEL_Y_OFF (0) // Y offset of label (for CheckBox)
|
||||
//--- Spin
|
||||
#define CONTROLS_SPIN_BUTTON_X_OFF (2) // X offset of button from right (for SpinEdit)
|
||||
#define CONTROLS_SPIN_MIN_HEIGHT (18) // minimal height (for SpinEdit)
|
||||
#define CONTROLS_SPIN_BUTTON_SIZE (8) // default size of button (16 x 8) (for SpinEdit)
|
||||
//--- Combo
|
||||
#define CONTROLS_COMBO_BUTTON_X_OFF (2) // X offset of button from right (for ComboBox)
|
||||
#define CONTROLS_COMBO_MIN_HEIGHT (18) // minimal height (for ComboBox)
|
||||
#define CONTROLS_COMBO_ITEM_HEIGHT (18) // height of combo box item (for ComboBox)
|
||||
#define CONTROLS_COMBO_ITEMS_VIEW (8) // number of items in combo box (for ComboBox)
|
||||
//--- ListView
|
||||
#define CONTROLS_LIST_ITEM_HEIGHT (18) // height of list item (for ListView)
|
||||
//--- Dialog
|
||||
#define CONTROLS_DIALOG_CAPTION_HEIGHT (22) // height of dialog header
|
||||
#define CONTROLS_DIALOG_BUTTON_OFF (3) // offset of dialog buttons
|
||||
#define CONTROLS_DIALOG_CLIENT_OFF (2) // offset of dialog client area
|
||||
#define CONTROLS_DIALOG_MINIMIZE_LEFT (10) // left coordinate of dialog in minimized state
|
||||
#define CONTROLS_DIALOG_MINIMIZE_TOP (10) // top coordinate of dialog in minimized state
|
||||
#define CONTROLS_DIALOG_MINIMIZE_WIDTH (100) // width of dialog in minimized state
|
||||
#define CONTROLS_DIALOG_MINIMIZE_HEIGHT (4*CONTROLS_BORDER_WIDTH+CONTROLS_DIALOG_CAPTION_HEIGHT) // height of dialog in minimized state
|
||||
//+------------------------------------------------------------------+
|
||||
//| Macro |
|
||||
//+------------------------------------------------------------------+
|
||||
//--- check properties
|
||||
#define IS_CAN_DBL_CLICK ((m_prop_flags&WND_PROP_FLAG_CAN_DBL_CLICK)!=0)
|
||||
#define IS_CAN_DRAG ((m_prop_flags&WND_PROP_FLAG_CAN_DRAG)!=0)
|
||||
#define IS_CLICKS_BY_PRESS ((m_prop_flags&WND_PROP_FLAG_CLICKS_BY_PRESS)!=0)
|
||||
#define IS_CAN_LOCK ((m_prop_flags&WND_PROP_FLAG_CAN_LOCK)!=0)
|
||||
#define IS_READ_ONLY ((m_prop_flags&WND_PROP_FLAG_READ_ONLY)!=0)
|
||||
//--- check state
|
||||
#define IS_ENABLED ((m_state_flags&WND_STATE_FLAG_ENABLE)!=0)
|
||||
#define IS_VISIBLE ((m_state_flags&WND_STATE_FLAG_VISIBLE)!=0)
|
||||
#define IS_ACTIVE ((m_state_flags&WND_STATE_FLAG_ACTIVE)!=0)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Macro of event handling map |
|
||||
//+------------------------------------------------------------------+
|
||||
#define INTERNAL_EVENT (-1)
|
||||
//--- beginning of map
|
||||
#define EVENT_MAP_BEGIN(class_name) bool class_name::OnEvent(const int id,const long& lparam,const double& dparam,const string& sparam) {
|
||||
//--- end of map
|
||||
#define EVENT_MAP_END(parent_class_name) return(parent_class_name::OnEvent(id,lparam,dparam,sparam)); }
|
||||
//--- event handling by numeric ID
|
||||
#define ON_EVENT(event,control,handler) if(id==(event+CHARTEVENT_CUSTOM) && lparam==control.Id()) { handler(); return(true); }
|
||||
//--- event handling by numeric ID by pointer of control
|
||||
#define ON_EVENT_PTR(event,control,handler) if(control!=NULL && id==(event+CHARTEVENT_CUSTOM) && lparam==control.Id()) { handler(); return(true); }
|
||||
//--- event handling without ID analysis
|
||||
#define ON_NO_ID_EVENT(event,handler) if(id==(event+CHARTEVENT_CUSTOM)) { return(handler()); }
|
||||
//--- event handling by row ID
|
||||
#define ON_NAMED_EVENT(event,control,handler) if(id==(event+CHARTEVENT_CUSTOM) && sparam==control.Name()) { handler(); return(true); }
|
||||
//--- handling of indexed event
|
||||
#define ON_INDEXED_EVENT(event,controls,handler) { int total=ArraySize(controls); for(int i=0;i<total;i++) if(id==(event+CHARTEVENT_CUSTOM) && lparam==controls[i].Id()) return(handler(i)); }
|
||||
//--- handling of external event
|
||||
#define ON_EXTERNAL_EVENT(event,handler) if(id==(event+CHARTEVENT_CUSTOM)) { handler(lparam,dparam,sparam); return(true); }
|
||||
//+------------------------------------------------------------------+
|
||||
//| Events |
|
||||
//+------------------------------------------------------------------+
|
||||
#define ON_CLICK (0) // clicking on control event
|
||||
#define ON_DBL_CLICK (1) // double clicking on control event
|
||||
#define ON_SHOW (2) // showing control event
|
||||
#define ON_HIDE (3) // hiding control event
|
||||
#define ON_CHANGE (4) // changing control event
|
||||
#define ON_START_EDIT (5) // start of editing event
|
||||
#define ON_END_EDIT (6) // end of editing event
|
||||
#define ON_SCROLL_INC (7) // increment of scrollbar event
|
||||
#define ON_SCROLL_DEC (8) // decrement of scrollbar event
|
||||
#define ON_MOUSE_FOCUS_SET (9) // the "mouse cursor entered the control" event
|
||||
#define ON_MOUSE_FOCUS_KILL (10) // the "mouse cursor exited the control" event
|
||||
#define ON_DRAG_START (11) // the "control dragging start" event
|
||||
#define ON_DRAG_PROCESS (12) // the "control is being dragged" event
|
||||
#define ON_DRAG_END (13) // the "control dragging end" event
|
||||
#define ON_BRING_TO_TOP (14) // the "mouse events priority increase" event
|
||||
#define ON_APP_CLOSE (100) // "closing the application" event
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,971 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dialog.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "WndClient.mqh"
|
||||
#include "Panel.mqh"
|
||||
#include "Edit.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include <Charts\Chart.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
#resource "res\\Close.bmp"
|
||||
#resource "res\\Restore.bmp"
|
||||
#resource "res\\Turn.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDialog |
|
||||
//| Usage: base class to create dialog boxes |
|
||||
//| and indicator panels |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDialog : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CPanel m_white_border; // the "white border" object
|
||||
CPanel m_background; // the background object
|
||||
CEdit m_caption; // the window title object
|
||||
CBmpButton m_button_close; // the "Close" button object
|
||||
CWndClient m_client_area; // the client area object
|
||||
|
||||
protected:
|
||||
//--- flags
|
||||
bool m_panel_flag; // the "panel in a separate window" flag
|
||||
//--- flags
|
||||
bool m_minimized; // "create in minimized state" flag
|
||||
//--- additional areas
|
||||
CRect m_min_rect; // minimal area coordinates
|
||||
CRect m_norm_rect; // normal area coordinates
|
||||
|
||||
public:
|
||||
CDialog(void);
|
||||
~CDialog(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up
|
||||
string Caption(void) const { return(m_caption.Text()); }
|
||||
bool Caption(const string text) { return(m_caption.Text(text)); }
|
||||
//--- fill
|
||||
bool Add(CWnd *control);
|
||||
bool Add(CWnd &control);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateWhiteBorder(void);
|
||||
virtual bool CreateBackground(void);
|
||||
virtual bool CreateCaption(void);
|
||||
virtual bool CreateButtonClose(void);
|
||||
virtual bool CreateClientArea(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual void OnClickCaption(void);
|
||||
virtual void OnClickButtonClose(void);
|
||||
//--- access properties of caption
|
||||
void CaptionAlignment(const int flags,const int left,const int top,const int right,const int bottom)
|
||||
{ m_caption.Alignment(flags,left,top,right,bottom); }
|
||||
//--- access properties of client area
|
||||
bool ClientAreaVisible(const bool visible) { return(m_client_area.Visible(visible)); }
|
||||
int ClientAreaLeft(void) const { return(m_client_area.Left()); }
|
||||
int ClientAreaTop(void) const { return(m_client_area.Top()); }
|
||||
int ClientAreaRight(void) const { return(m_client_area.Right()); }
|
||||
int ClientAreaBottom(void) const { return(m_client_area.Bottom()); }
|
||||
int ClientAreaWidth(void) const { return(m_client_area.Width()); }
|
||||
int ClientAreaHeight(void) const { return(m_client_area.Height()); }
|
||||
//--- handlers of drag
|
||||
virtual bool OnDialogDragStart(void);
|
||||
virtual bool OnDialogDragProcess(void);
|
||||
virtual bool OnDialogDragEnd(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CDialog)
|
||||
ON_EVENT(ON_CLICK,m_button_close,OnClickButtonClose)
|
||||
ON_EVENT(ON_CLICK,m_caption,OnClickCaption)
|
||||
ON_EVENT(ON_DRAG_START,m_caption,OnDialogDragStart)
|
||||
ON_EVENT_PTR(ON_DRAG_PROCESS,m_drag_object,OnDialogDragProcess)
|
||||
ON_EVENT_PTR(ON_DRAG_END,m_drag_object,OnDialogDragEnd)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDialog::CDialog(void) : m_panel_flag(false),
|
||||
m_minimized(false)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDialog::~CDialog(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!m_panel_flag && !CreateWhiteBorder())
|
||||
return(false);
|
||||
if(!CreateBackground())
|
||||
return(false);
|
||||
if(!CreateCaption())
|
||||
return(false);
|
||||
if(!CreateButtonClose())
|
||||
return(false);
|
||||
if(!CreateClientArea())
|
||||
return(false);
|
||||
//--- set up additional areas
|
||||
m_norm_rect.SetBound(m_rect);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add control to the client area (by pointer) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::Add(CWnd *control)
|
||||
{
|
||||
return(m_client_area.Add(control));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add control to the client area (by reference) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::Add(CWnd &control)
|
||||
{
|
||||
return(m_client_area.Add(control));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Save |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- save
|
||||
FileWriteStruct(file_handle,m_norm_rect);
|
||||
FileWriteInteger(file_handle,m_min_rect.left);
|
||||
FileWriteInteger(file_handle,m_min_rect.top);
|
||||
FileWriteInteger(file_handle,m_minimized);
|
||||
//--- result
|
||||
return(CWndContainer::Save(file_handle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Load |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::Load(const int file_handle)
|
||||
{
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//--- load
|
||||
if(!FileIsEnding(file_handle))
|
||||
{
|
||||
FileReadStruct(file_handle,m_norm_rect);
|
||||
int left=FileReadInteger(file_handle);
|
||||
int top=FileReadInteger(file_handle);
|
||||
m_min_rect.Move(left,top);
|
||||
m_minimized=FileReadInteger(file_handle);
|
||||
}
|
||||
//--- result
|
||||
return(CWndContainer::Load(file_handle));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create "white border" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::CreateWhiteBorder(void)
|
||||
{
|
||||
//--- coordinates
|
||||
int x1=0;
|
||||
int y1=0;
|
||||
int x2=Width();
|
||||
int y2=Height();
|
||||
//--- create
|
||||
if(!m_white_border.Create(m_chart_id,m_name+"Border",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_white_border.ColorBackground(CONTROLS_DIALOG_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_white_border.ColorBorder(CONTROLS_DIALOG_COLOR_BORDER_LIGHT))
|
||||
return(false);
|
||||
if(!CWndContainer::Add(m_white_border))
|
||||
return(false);
|
||||
m_white_border.Alignment(WND_ALIGN_CLIENT,0,0,0,0);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create background |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::CreateBackground(void)
|
||||
{
|
||||
int off=(m_panel_flag) ? 0:CONTROLS_BORDER_WIDTH;
|
||||
//--- coordinates
|
||||
int x1=off;
|
||||
int y1=off;
|
||||
int x2=Width()-off;
|
||||
int y2=Height()-off;
|
||||
//--- create
|
||||
if(!m_background.Create(m_chart_id,m_name+"Back",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_background.ColorBackground(CONTROLS_DIALOG_COLOR_BG))
|
||||
return(false);
|
||||
color border=(m_panel_flag) ? CONTROLS_DIALOG_COLOR_BG : CONTROLS_DIALOG_COLOR_BORDER_DARK;
|
||||
if(!m_background.ColorBorder(border))
|
||||
return(false);
|
||||
if(!CWndContainer::Add(m_background))
|
||||
return(false);
|
||||
m_background.Alignment(WND_ALIGN_CLIENT,off,off,off,off);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create window title |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::CreateCaption(void)
|
||||
{
|
||||
int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH;
|
||||
//--- coordinates
|
||||
int x1=off;
|
||||
int y1=off;
|
||||
int x2=Width()-off;
|
||||
int y2=y1+CONTROLS_DIALOG_CAPTION_HEIGHT;
|
||||
//--- create
|
||||
if(!m_caption.Create(m_chart_id,m_name+"Caption",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_caption.Color(CONTROLS_DIALOG_COLOR_CAPTION_TEXT))
|
||||
return(false);
|
||||
if(!m_caption.ColorBackground(CONTROLS_DIALOG_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_caption.ColorBorder(CONTROLS_DIALOG_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_caption.ReadOnly(true))
|
||||
return(false);
|
||||
if(!m_caption.Text(m_name))
|
||||
return(false);
|
||||
if(!CWndContainer::Add(m_caption))
|
||||
return(false);
|
||||
m_caption.Alignment(WND_ALIGN_WIDTH,off,0,off,0);
|
||||
if(!m_panel_flag)
|
||||
m_caption.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Close" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::CreateButtonClose(void)
|
||||
{
|
||||
int off=(m_panel_flag) ? 0 : 2*CONTROLS_BORDER_WIDTH;
|
||||
//--- coordinates
|
||||
int x1=Width()-off-(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF);
|
||||
int y1=off+CONTROLS_DIALOG_BUTTON_OFF;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_button_close.Create(m_chart_id,m_name+"Close",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button_close.BmpNames("::res\\Close.bmp"))
|
||||
return(false);
|
||||
if(!CWndContainer::Add(m_button_close))
|
||||
return(false);
|
||||
m_button_close.Alignment(WND_ALIGN_RIGHT,0,0,off+CONTROLS_DIALOG_BUTTON_OFF,0);
|
||||
//--- change caption
|
||||
CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF),0);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create client area |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::CreateClientArea(void)
|
||||
{
|
||||
int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH;
|
||||
//--- coordinates
|
||||
int x1=off+CONTROLS_DIALOG_CLIENT_OFF;
|
||||
int y1=off+CONTROLS_DIALOG_CAPTION_HEIGHT;
|
||||
int x2=Width()-(off+CONTROLS_DIALOG_CLIENT_OFF);
|
||||
int y2=Height()-(off+CONTROLS_DIALOG_CLIENT_OFF);
|
||||
//--- create
|
||||
if(!m_client_area.Create(m_chart_id,m_name+"Client",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_client_area.ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG))
|
||||
return(false);
|
||||
if(!m_client_area.ColorBorder(CONTROLS_DIALOG_COLOR_CLIENT_BORDER))
|
||||
return(false);
|
||||
CWndContainer::Add(m_client_area);
|
||||
m_client_area.Alignment(WND_ALIGN_CLIENT,x1,y1,x1,x1);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the window title |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDialog::OnClickCaption(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "Close" button |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDialog::OnClickButtonClose(void)
|
||||
{
|
||||
Visible(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Start dragging the dialog box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::OnDialogDragStart(void)
|
||||
{
|
||||
if(m_drag_object==NULL)
|
||||
{
|
||||
m_drag_object=new CDragWnd;
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
}
|
||||
//--- calculate coordinates
|
||||
int x1=Left()-CONTROLS_DRAG_SPACING;
|
||||
int y1=Top()-CONTROLS_DRAG_SPACING;
|
||||
int x2=Right()+CONTROLS_DRAG_SPACING;
|
||||
int y2=Bottom()+CONTROLS_DRAG_SPACING;
|
||||
//--- create
|
||||
m_drag_object.Create(m_chart_id,"",m_subwin,x1,y1,x2,y2);
|
||||
m_drag_object.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- constraints
|
||||
CChart chart;
|
||||
chart.Attach(m_chart_id);
|
||||
m_drag_object.Limits(-CONTROLS_DRAG_SPACING,-CONTROLS_DRAG_SPACING,
|
||||
chart.WidthInPixels()+CONTROLS_DRAG_SPACING,
|
||||
chart.HeightInPixels(m_subwin)+CONTROLS_DRAG_SPACING);
|
||||
chart.Detach();
|
||||
//--- set mouse params
|
||||
m_drag_object.MouseX(m_caption.MouseX());
|
||||
m_drag_object.MouseY(m_caption.MouseY());
|
||||
m_drag_object.MouseFlags(m_caption.MouseFlags());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Continue dragging the dialog box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::OnDialogDragProcess(void)
|
||||
{
|
||||
//--- checking
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
//--- calculate coordinates
|
||||
int x=m_drag_object.Left()+50;
|
||||
int y=m_drag_object.Top()+50;
|
||||
//--- move dialog
|
||||
Move(x,y);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| End dragging the dialog box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDialog::OnDialogDragEnd(void)
|
||||
{
|
||||
if(m_drag_object!=NULL)
|
||||
{
|
||||
m_caption.MouseFlags(m_drag_object.MouseFlags());
|
||||
delete m_drag_object;
|
||||
m_drag_object=NULL;
|
||||
}
|
||||
//--- set up additional areas
|
||||
if(m_minimized)
|
||||
m_min_rect.SetBound(m_rect);
|
||||
else
|
||||
m_norm_rect.SetBound(m_rect);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CAppDialog |
|
||||
//| Usage: main dialog box of MQL5 application |
|
||||
//+------------------------------------------------------------------+
|
||||
class CAppDialog : public CDialog
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CBmpButton m_button_minmax; // the "Minimize/Maximize" button object
|
||||
//--- variables
|
||||
string m_program_name; // name of program
|
||||
string m_instance_id; // unique string ID
|
||||
ENUM_PROGRAM_TYPE m_program_type; // type of program
|
||||
string m_indicator_name;
|
||||
int m_deinit_reason;
|
||||
//--- for mouse
|
||||
int m_subwin_Yoff; // subwindow Y offset
|
||||
CWnd* m_focused_wnd; // pointer to object that has mouse focus
|
||||
CWnd* m_top_wnd; // pointer to object that has priority over mouse events handling
|
||||
|
||||
protected:
|
||||
CChart m_chart; // object to access chart
|
||||
|
||||
public:
|
||||
CAppDialog(void);
|
||||
~CAppDialog(void);
|
||||
//--- main application dialog creation and destroy
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
virtual void Destroy(const int reason=REASON_PROGRAM);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- dialog run
|
||||
bool Run(void);
|
||||
//--- chart events processing
|
||||
void ChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up
|
||||
void Minimized(const bool flag) { m_minimized=flag; }
|
||||
//--- to save/restore state
|
||||
void IniFileSave(void);
|
||||
void IniFileLoad(void);
|
||||
virtual string IniFileName(void) const;
|
||||
virtual string IniFileExt(void) const { return(".dat"); }
|
||||
virtual bool Load(const int file_handle);
|
||||
virtual bool Save(const int file_handle);
|
||||
|
||||
private:
|
||||
bool CreateCommon(const long chart,const string name,const int subwin);
|
||||
bool CreateExpert(const int x1,const int y1,const int x2,const int y2);
|
||||
bool CreateIndicator(const int x1,const int y1,const int x2,const int y2);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateButtonMinMax(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual void OnClickButtonClose(void);
|
||||
virtual void OnClickButtonMinMax(void);
|
||||
//--- external event handlers
|
||||
virtual void OnAnotherApplicationClose(const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- methods
|
||||
virtual bool Rebound(const CRect &rect);
|
||||
virtual void Minimize(void);
|
||||
virtual void Maximize(void);
|
||||
string CreateInstanceId(void);
|
||||
string ProgramName(void) const { return(m_program_name); }
|
||||
void SubwinOff(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CAppDialog)
|
||||
ON_EVENT(ON_CLICK,m_button_minmax,OnClickButtonMinMax)
|
||||
ON_EXTERNAL_EVENT(ON_APP_CLOSE,OnAnotherApplicationClose)
|
||||
EVENT_MAP_END(CDialog)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CAppDialog::CAppDialog(void) : m_program_type(WRONG_VALUE),
|
||||
m_deinit_reason(WRONG_VALUE),
|
||||
m_subwin_Yoff(0),
|
||||
m_focused_wnd(NULL),
|
||||
m_top_wnd(NULL)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CAppDialog::~CAppDialog(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Application dialog initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
if(!CreateCommon(chart,name,subwin))
|
||||
return(false);
|
||||
//---
|
||||
switch(m_program_type)
|
||||
{
|
||||
case PROGRAM_EXPERT:
|
||||
if(!CreateExpert(x1,y1,x2,y2))
|
||||
return(false);
|
||||
break;
|
||||
case PROGRAM_INDICATOR:
|
||||
if(!CreateIndicator(x1,y1,x2,y2))
|
||||
return(false);
|
||||
break;
|
||||
default:
|
||||
Print("CAppDialog: invalid program type");
|
||||
return(false);
|
||||
}
|
||||
//--- Title of dialog window
|
||||
if(!Caption(m_program_name))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateButtonMinMax())
|
||||
return(false);
|
||||
//--- get subwindow offset
|
||||
SubwinOff();
|
||||
//--- if flag is set, minimize the dialog
|
||||
if(m_minimized)
|
||||
Minimize();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize common area |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::CreateCommon(const long chart,const string name,const int subwin)
|
||||
{
|
||||
//--- save parameters
|
||||
m_chart_id =chart;
|
||||
m_name =name;
|
||||
m_subwin =subwin;
|
||||
m_program_name =name;
|
||||
m_deinit_reason=WRONG_VALUE;
|
||||
//--- get unique ID
|
||||
m_instance_id=CreateInstanceId();
|
||||
//--- initialize chart object
|
||||
m_chart.Attach(chart);
|
||||
//--- determine type of program
|
||||
m_program_type=(ENUM_PROGRAM_TYPE)MQL5InfoInteger(MQL5_PROGRAM_TYPE);
|
||||
//--- specify object and mouse events
|
||||
if(!m_chart.EventObjectCreate() || !m_chart.EventObjectDelete() || !m_chart.EventMouseMove())
|
||||
{
|
||||
Print("CAppDialog: object events specify error");
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize in Expert Advisor |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::CreateExpert(const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- EA works only in main window
|
||||
m_subwin=0;
|
||||
//--- geometry for the minimized state
|
||||
m_min_rect.SetBound(CONTROLS_DIALOG_MINIMIZE_LEFT,
|
||||
CONTROLS_DIALOG_MINIMIZE_TOP,
|
||||
CONTROLS_DIALOG_MINIMIZE_LEFT+CONTROLS_DIALOG_MINIMIZE_WIDTH,
|
||||
CONTROLS_DIALOG_MINIMIZE_TOP+CONTROLS_DIALOG_MINIMIZE_HEIGHT);
|
||||
//--- call method of the parent class
|
||||
if(!CDialog::Create(m_chart.ChartId(),m_instance_id,m_subwin,x1,y1,x2,y2))
|
||||
{
|
||||
Print("CAppDialog: expert dialog create error");
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize in Indicator |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::CreateIndicator(const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
int width=m_chart.WidthInPixels();
|
||||
//--- geometry for the minimized state
|
||||
m_min_rect.LeftTop(0,0);
|
||||
m_min_rect.Width(width);
|
||||
m_min_rect.Height(CONTROLS_DIALOG_MINIMIZE_HEIGHT-2*CONTROLS_BORDER_WIDTH);
|
||||
//--- determine subwindow
|
||||
m_subwin=ChartWindowFind();
|
||||
if(m_subwin==-1)
|
||||
{
|
||||
Print("CAppDialog: find subwindow error");
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//---
|
||||
int total=ChartIndicatorsTotal(m_chart.ChartId(),m_subwin);
|
||||
m_indicator_name=ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1);
|
||||
//--- if subwindow number is 0 (main window), then our program is
|
||||
//--- not an indicator panel, but is an indicator with built-in settings dialog
|
||||
//--- dialog of such an indicator should behave as an Expert Advisor dialog
|
||||
if(m_subwin==0)
|
||||
return(CreateExpert(x1,y1,x2,y2));
|
||||
//--- if subwindow number is not 0, then our program is an indicator panel
|
||||
//--- check if subwindow is not occupied by other indicators
|
||||
if(total!=1)
|
||||
{
|
||||
Print("CAppDialog: subwindow busy");
|
||||
ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1));
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- resize subwindow by dialog height
|
||||
if(!IndicatorSetInteger(INDICATOR_HEIGHT,(y2-y1)+1))
|
||||
{
|
||||
Print("CAppDialog: subwindow resize error");
|
||||
ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1));
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- indicator short name
|
||||
m_indicator_name=m_program_name+IntegerToString(m_subwin);
|
||||
if(!IndicatorSetString(INDICATOR_SHORTNAME,m_indicator_name))
|
||||
{
|
||||
Print("CAppDialog: shortname error");
|
||||
ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1));
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- set flag
|
||||
m_panel_flag=true;
|
||||
//--- call method of the parent class
|
||||
if(!CDialog::Create(m_chart.ChartId(),m_instance_id,m_subwin,0,0,width,y2-y1))
|
||||
{
|
||||
Print("CAppDialog: indicator dialog create error");
|
||||
ChartIndicatorDelete(m_chart.ChartId(),m_subwin,ChartIndicatorName(m_chart.ChartId(),m_subwin,total-1));
|
||||
m_chart.Detach();
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Application dialog deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::Destroy(const int reason)
|
||||
{
|
||||
//--- destroyed already?
|
||||
if(m_deinit_reason!=WRONG_VALUE)
|
||||
return;
|
||||
//---
|
||||
m_deinit_reason=reason;
|
||||
IniFileSave();
|
||||
//--- detach chart object from chart
|
||||
m_chart.Detach();
|
||||
//--- call parent destroy
|
||||
CDialog::Destroy();
|
||||
//---
|
||||
if(reason==REASON_PROGRAM)
|
||||
{
|
||||
if(m_program_type==PROGRAM_EXPERT)
|
||||
ExpertRemove();
|
||||
if(m_program_type==PROGRAM_INDICATOR)
|
||||
ChartIndicatorDelete(m_chart_id,m_subwin,m_indicator_name);
|
||||
}
|
||||
//--- send message
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_APP_CLOSE,m_subwin,0.0,m_program_name);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate subwindow offset |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::SubwinOff(void)
|
||||
{
|
||||
m_subwin_Yoff=m_chart.SubwindowY(m_subwin);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Minimize/Maximize" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::CreateButtonMinMax(void)
|
||||
{
|
||||
int off=(m_panel_flag) ? 0:2*CONTROLS_BORDER_WIDTH;
|
||||
//--- coordinates
|
||||
int x1=Width()-off-2*(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF);
|
||||
int y1=off+CONTROLS_DIALOG_BUTTON_OFF;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_button_minmax.Create(m_chart_id,m_name+"MinMax",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button_minmax.BmpNames("::res\\Turn.bmp","::res\\Restore.bmp"))
|
||||
return(false);
|
||||
if(!CWndContainer::Add(m_button_minmax))
|
||||
return(false);
|
||||
m_button_minmax.Locking(true);
|
||||
m_button_minmax.Alignment(WND_ALIGN_RIGHT,0,0,off+CONTROLS_BUTTON_SIZE+2*CONTROLS_DIALOG_BUTTON_OFF,0);
|
||||
//--- change caption
|
||||
CaptionAlignment(WND_ALIGN_WIDTH,off,0,off+2*(CONTROLS_BUTTON_SIZE+CONTROLS_DIALOG_BUTTON_OFF),0);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Charts event processing |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::ChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
int mouse_x=(int)lparam;
|
||||
int mouse_y=(int)dparam-m_subwin_Yoff;
|
||||
//--- separate mouse events from others
|
||||
switch(id)
|
||||
{
|
||||
case CHARTEVENT_CHART_CHANGE:
|
||||
//--- assumed that the CHARTEVENT_CHART_CHANGE event can handle only the application dialog
|
||||
break;
|
||||
case CHARTEVENT_OBJECT_CLICK:
|
||||
//--- we won't handle the CHARTEVENT_OBJECT_CLICK event, as we are working with the CHARTEVENT_MOUSE_MOVE events
|
||||
return;
|
||||
case CHARTEVENT_CUSTOM+ON_MOUSE_FOCUS_SET:
|
||||
//--- the CHARTEVENT_CUSTOM + ON_MOUSE_FOCUS_SET event
|
||||
if(CheckPointer(m_focused_wnd)!=POINTER_INVALID)
|
||||
{
|
||||
//--- if there is an element with focus, try to take its focus away
|
||||
if(!m_focused_wnd.MouseFocusKill(lparam))
|
||||
return;
|
||||
}
|
||||
m_focused_wnd=ControlFind(lparam);
|
||||
return;
|
||||
case CHARTEVENT_CUSTOM+ON_BRING_TO_TOP:
|
||||
m_top_wnd=ControlFind(lparam);
|
||||
return;
|
||||
case CHARTEVENT_MOUSE_MOVE:
|
||||
//--- the CHARTEVENT_MOUSE_MOVE event
|
||||
if(CheckPointer(m_top_wnd)!=POINTER_INVALID)
|
||||
{
|
||||
//--- if a priority element already exists, pass control to it
|
||||
if(m_top_wnd.OnMouseEvent(mouse_x,mouse_y,(int)StringToInteger(sparam)))
|
||||
{
|
||||
//--- event handled
|
||||
m_chart.Redraw();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(OnMouseEvent(mouse_x,mouse_y,(int)StringToInteger(sparam)))
|
||||
m_chart.Redraw();
|
||||
return;
|
||||
default:
|
||||
//--- call event processing and redraw chart if event handled
|
||||
if(OnEvent(id,lparam,dparam,sparam))
|
||||
m_chart.Redraw();
|
||||
return;
|
||||
}
|
||||
//--- if event was not handled, try to handle the CHARTEVENT_CHART_CHANGE event
|
||||
if(id==CHARTEVENT_CHART_CHANGE)
|
||||
{
|
||||
//--- if subwindow number is not 0, and dialog subwindow has changed its number, then restart
|
||||
if(m_subwin!=0 && m_subwin!=ChartWindowFind())
|
||||
{
|
||||
long fiction=1;
|
||||
OnAnotherApplicationClose(fiction,dparam,sparam);
|
||||
}
|
||||
//--- if subwindow height is less that dialog height, minimize application window (always)
|
||||
if(m_chart.HeightInPixels(m_subwin)<Height()+CONTROLS_BORDER_WIDTH)
|
||||
{
|
||||
m_button_minmax.Pressed(true);
|
||||
Minimize();
|
||||
m_chart.Redraw();
|
||||
}
|
||||
//--- if chart width is less that dialog width, and subwindow number is not 0, try to modify dialog width
|
||||
if(m_chart.WidthInPixels()!=Width() && m_subwin!=0)
|
||||
{
|
||||
Width(m_chart.WidthInPixels());
|
||||
m_chart.Redraw();
|
||||
}
|
||||
//--- get subwindow offset
|
||||
SubwinOff();
|
||||
return;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Run application |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::Run(void)
|
||||
{
|
||||
//--- redraw chart for dialog invalidate
|
||||
m_chart.Redraw();
|
||||
//--- here we begin to assign IDs to controls
|
||||
if(Id(m_subwin*CONTROLS_MAXIMUM_ID)>CONTROLS_MAXIMUM_ID)
|
||||
{
|
||||
Print("CAppDialog: too many objects");
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stop application |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::OnClickButtonClose(void)
|
||||
{
|
||||
//--- destroy application
|
||||
Destroy();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "Minimize/Maximize" button |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::OnClickButtonMinMax(void)
|
||||
{
|
||||
if(m_button_minmax.Pressed())
|
||||
Minimize();
|
||||
else
|
||||
Maximize();
|
||||
//--- get subwindow offset
|
||||
SubwinOff();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::Rebound(const CRect &rect)
|
||||
{
|
||||
if(!Move(rect.LeftTop()))
|
||||
return(false);
|
||||
if(!Size(rect.Size()))
|
||||
return(false);
|
||||
//--- resize subwindow
|
||||
if(m_program_type==PROGRAM_INDICATOR && !IndicatorSetInteger(INDICATOR_HEIGHT,rect.Height()+1))
|
||||
{
|
||||
Print("CAppDialog: subwindow resize error");
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Minimize dialog window |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::Minimize(void)
|
||||
{
|
||||
//--- set flag
|
||||
m_minimized=true;
|
||||
//--- resize
|
||||
Rebound(m_min_rect);
|
||||
//--- hide client area
|
||||
ClientAreaVisible(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Restore dialog window |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::Maximize(void)
|
||||
{
|
||||
//--- reset flag
|
||||
m_minimized=false;
|
||||
//--- resize
|
||||
Rebound(m_norm_rect);
|
||||
//--- show client area
|
||||
ClientAreaVisible(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create unique prefix for object names |
|
||||
//+------------------------------------------------------------------+
|
||||
string CAppDialog::CreateInstanceId(void)
|
||||
{
|
||||
return(IntegerToString(rand(),5,'0'));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the ON_APP_CLOSE external event |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::OnAnotherApplicationClose(const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
//--- exit if we are in the main window
|
||||
if(m_subwin==0)
|
||||
return;
|
||||
//--- exit if external program was closed in main window
|
||||
if(lparam==0)
|
||||
return;
|
||||
//--- get subwindow offset
|
||||
SubwinOff();
|
||||
//--- exit if external program was closed in subwindow with greater number
|
||||
if(lparam>=m_subwin)
|
||||
return;
|
||||
//--- after all the checks we must change the subwindow
|
||||
//--- get the new number of subwindow
|
||||
m_subwin=ChartWindowFind();
|
||||
//--- change short name
|
||||
m_indicator_name=m_program_name+IntegerToString(m_subwin);
|
||||
IndicatorSetString(INDICATOR_SHORTNAME,m_indicator_name);
|
||||
//--- change dialog title
|
||||
Caption(m_program_name);
|
||||
//--- reassign IDs
|
||||
Run();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Save the current state of the program |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::IniFileSave(void)
|
||||
{
|
||||
string filename=IniFileName()+IniFileExt();
|
||||
int handle=FileOpen(filename,FILE_WRITE|FILE_BIN|FILE_ANSI);
|
||||
//---
|
||||
if(handle!=INVALID_HANDLE)
|
||||
{
|
||||
Save(handle);
|
||||
FileClose(handle);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Read the previous state of the program |
|
||||
//+------------------------------------------------------------------+
|
||||
void CAppDialog::IniFileLoad(void)
|
||||
{
|
||||
string filename=IniFileName()+IniFileExt();
|
||||
int handle=FileOpen(filename,FILE_READ|FILE_BIN|FILE_ANSI);
|
||||
//---
|
||||
if(handle!=INVALID_HANDLE)
|
||||
{
|
||||
Load(handle);
|
||||
FileClose(handle);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generate the filename |
|
||||
//+------------------------------------------------------------------+
|
||||
string CAppDialog::IniFileName(void) const
|
||||
{
|
||||
string name;
|
||||
//---
|
||||
name=(m_indicator_name!=NULL) ? m_indicator_name : m_program_name;
|
||||
//---
|
||||
name+="_"+Symbol();
|
||||
name+="_Ini";
|
||||
//---
|
||||
return(name);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Load data |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::Load(const int file_handle)
|
||||
{
|
||||
if(CDialog::Load(file_handle))
|
||||
{
|
||||
if(m_minimized)
|
||||
{
|
||||
m_button_minmax.Pressed(true);
|
||||
Minimize();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_button_minmax.Pressed(false);
|
||||
Maximize();
|
||||
}
|
||||
int prev_deinit_reason=FileReadInteger(file_handle);
|
||||
if(prev_deinit_reason==REASON_CHARTCLOSE || prev_deinit_reason==REASON_CLOSE)
|
||||
{
|
||||
//--- if the previous time program ended after closing the chart window,
|
||||
//--- delete object left since the last start of the program
|
||||
string prev_instance_id=IntegerToString(FileReadInteger(file_handle),5,'0');
|
||||
if(prev_instance_id!=m_instance_id)
|
||||
{
|
||||
long chart_id=m_chart.ChartId();
|
||||
int total=ObjectsTotal(chart_id,m_subwin);
|
||||
for(int i=total-1;i>=0;i--)
|
||||
{
|
||||
string obj_name=ObjectName(chart_id,i,m_subwin);
|
||||
if(StringFind(obj_name,prev_instance_id)==0)
|
||||
ObjectDelete(chart_id,obj_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Save data |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CAppDialog::Save(const int file_handle)
|
||||
{
|
||||
if(CDialog::Save(file_handle))
|
||||
{
|
||||
FileWriteInteger(file_handle,m_deinit_reason);
|
||||
FileWriteInteger(file_handle,(int)StringToInteger(m_instance_id));
|
||||
return(true);
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,188 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Edit.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CEdit |
|
||||
//| Usage: control that is displayed by |
|
||||
//| the CChartObjectEdit object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CEdit : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectEdit m_edit; // chart object
|
||||
//--- parameters of the chart object
|
||||
bool m_read_only; // "read-only" mode flag
|
||||
ENUM_ALIGN_MODE m_align_mode; // align mode
|
||||
|
||||
public:
|
||||
CEdit(void);
|
||||
~CEdit(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- parameters of the chart object
|
||||
bool ReadOnly(void) const { return(m_read_only); }
|
||||
bool ReadOnly(const bool flag);
|
||||
ENUM_ALIGN_MODE TextAlign(void) const { return(m_align_mode); }
|
||||
bool TextAlign(const ENUM_ALIGN_MODE align);
|
||||
//--- data access
|
||||
string Text(void) const { return(m_edit.Description()); }
|
||||
bool Text(const string value) { return(CWndObj::Text(value)); }
|
||||
|
||||
protected:
|
||||
//--- handlers of object events
|
||||
virtual bool OnObjectEndEdit(void);
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetText(void) { return(m_edit.Description(m_text)); }
|
||||
virtual bool OnSetColor(void) { return(m_edit.Color(m_color)); }
|
||||
virtual bool OnSetColorBackground(void) { return(m_edit.BackColor(m_color_background)); }
|
||||
virtual bool OnSetColorBorder(void) { return(m_edit.BorderColor(m_color_border)); }
|
||||
virtual bool OnSetFont(void) { return(m_edit.Font(m_font)); }
|
||||
virtual bool OnSetFontSize(void) { return(m_edit.FontSize(m_font_size)); }
|
||||
virtual bool OnSetZOrder(void) { return(m_edit.Z_Order(m_zorder)); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
virtual bool OnResize(void);
|
||||
virtual bool OnChange(void);
|
||||
virtual bool OnClick(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
if(m_name==sparam && id==CHARTEVENT_OBJECT_ENDEDIT)
|
||||
return(OnObjectEndEdit());
|
||||
//--- event was not handled
|
||||
return(CWndObj::OnEvent(id,lparam,dparam,sparam));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CEdit::CEdit(void) : m_read_only(false),
|
||||
m_align_mode(ALIGN_LEFT)
|
||||
{
|
||||
m_color =CONTROLS_EDIT_COLOR;
|
||||
m_color_background=CONTROLS_EDIT_COLOR_BG;
|
||||
m_color_border =CONTROLS_EDIT_COLOR_BORDER;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CEdit::~CEdit(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_edit.Create(chart,name,subwin,x1,y1,Width(),Height()))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::ReadOnly(const bool flag)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_read_only=flag;
|
||||
//--- set up the chart object
|
||||
return(m_edit.ReadOnly(flag));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::TextAlign(const ENUM_ALIGN_MODE align)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_align_mode=align;
|
||||
//--- set up the chart object
|
||||
return(m_edit.TextAlign(align));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_edit.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnShow(void)
|
||||
{
|
||||
return(m_edit.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnHide(void)
|
||||
{
|
||||
return(m_edit.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_edit.X_Distance(m_rect.left) && m_edit.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnResize(void)
|
||||
{
|
||||
//--- resize the chart object
|
||||
return(m_edit.X_Size(m_rect.Width()) && m_edit.Y_Size(m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnChange(void)
|
||||
{
|
||||
//--- set up the chart object
|
||||
return(CWndObj::OnChange() && ReadOnly(m_read_only) && TextAlign(m_align_mode));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "End of editing" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnObjectEndEdit(void)
|
||||
{
|
||||
//--- send the ON_END_EDIT notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_END_EDIT,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "click" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CEdit::OnClick(void)
|
||||
{
|
||||
//--- if editing is enabled, send the ON_START_EDIT notification
|
||||
if(!m_read_only)
|
||||
{
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_START_EDIT,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//--- else send the ON_CLICK notification
|
||||
return(CWnd::OnClick());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,93 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Label.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CLabel |
|
||||
//| Usage: control that is displayed by |
|
||||
//| the CChartObjectLabel object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CLabel : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectLabel m_label; // chart object
|
||||
|
||||
public:
|
||||
CLabel(void);
|
||||
~CLabel(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
|
||||
protected:
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetText(void) { return(m_label.Description(m_text)); }
|
||||
virtual bool OnSetColor(void) { return(m_label.Color(m_color)); }
|
||||
virtual bool OnSetFont(void) { return(m_label.Font(m_font)); }
|
||||
virtual bool OnSetFontSize(void) { return(m_label.FontSize(m_font_size)); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CLabel::CLabel(void)
|
||||
{
|
||||
m_color=CONTROLS_LABEL_COLOR;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CLabel::~CLabel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLabel::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_label.Create(chart,name,subwin,x1,y1))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLabel::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_label.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLabel::OnShow(void)
|
||||
{
|
||||
return(m_label.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLabel::OnHide(void)
|
||||
{
|
||||
return(m_label.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CLabel::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_label.X_Distance(m_rect.left) && m_label.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,544 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ListView.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndClient.mqh"
|
||||
#include "Edit.mqh"
|
||||
#include <Arrays\ArrayString.mqh>
|
||||
#include <Arrays\ArrayLong.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CListView |
|
||||
//| Usage: display lists |
|
||||
//+------------------------------------------------------------------+
|
||||
class CListView : public CWndClient
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CEdit m_rows[]; // array of the row objects
|
||||
//--- set up
|
||||
int m_offset; // index of first visible row in array of rows
|
||||
int m_total_view; // number of visible rows
|
||||
int m_item_height; // height of visible row
|
||||
bool m_height_variable; // ïðèçíàê ïåðåìåííîé âûñîòû ñïèñêà
|
||||
//--- data
|
||||
CArrayString m_strings; // array of rows
|
||||
CArrayLong m_values; // array of values
|
||||
int m_current; // index of current row in array of rows
|
||||
|
||||
public:
|
||||
CListView(void);
|
||||
~CListView(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
virtual void Destroy(const int reason=0);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up
|
||||
bool TotalView(const int value);
|
||||
//--- fill
|
||||
virtual bool AddItem(const string item,const long value=0);
|
||||
//--- data
|
||||
virtual bool ItemAdd(const string item,const long value=0);
|
||||
virtual bool ItemInsert(const int index,const string item,const long value=0);
|
||||
virtual bool ItemUpdate(const int index,const string item,const long value=0);
|
||||
virtual bool ItemDelete(const int index);
|
||||
virtual bool ItemsClear(void);
|
||||
//--- data
|
||||
int Current(void) { return(m_current); }
|
||||
string Select(void) { return(m_strings.At(m_current)); }
|
||||
bool Select(const int index);
|
||||
bool SelectByText(const string text);
|
||||
bool SelectByValue(const long value);
|
||||
//--- data (read only)
|
||||
long Value(void) { return(m_values.At(m_current)); }
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
bool CreateRow(const int index);
|
||||
//--- event handlers
|
||||
virtual bool OnResize(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnVScrollShow(void);
|
||||
virtual bool OnVScrollHide(void);
|
||||
virtual bool OnScrollLineDown(void);
|
||||
virtual bool OnScrollLineUp(void);
|
||||
virtual bool OnItemClick(const int index);
|
||||
//--- redraw
|
||||
bool Redraw(void);
|
||||
bool RowState(const int index,const bool select);
|
||||
bool CheckView(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CListView)
|
||||
ON_INDEXED_EVENT(ON_CLICK,m_rows,OnItemClick)
|
||||
EVENT_MAP_END(CWndClient)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CListView::CListView(void) : m_offset(0),
|
||||
m_total_view(0),
|
||||
m_item_height(CONTROLS_LIST_ITEM_HEIGHT),
|
||||
m_current(CONTROLS_INVALID_INDEX),
|
||||
m_height_variable(false)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CListView::~CListView(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
int y=y2;
|
||||
//--- if the number of visible rows is previously determined, adjust the vertical size
|
||||
if(!TotalView((y2-y1)/m_item_height))
|
||||
y=m_item_height+y1+2*CONTROLS_BORDER_WIDTH;
|
||||
//--- check the number of visible rows
|
||||
if(m_total_view<1)
|
||||
return(false);
|
||||
//--- call method of the parent class
|
||||
if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y))
|
||||
return(false);
|
||||
//--- set up
|
||||
if(!m_background.ColorBackground(CONTROLS_LIST_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_background.ColorBorder(CONTROLS_LIST_COLOR_BORDER))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
ArrayResize(m_rows,m_total_view);
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
if(!CreateRow(i))
|
||||
return(false);
|
||||
if(m_height_variable && i>0)
|
||||
m_rows[i].Hide();
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
void CListView::Destroy(const int reason)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
CWndClient::Destroy(reason);
|
||||
//--- clear items
|
||||
m_strings.Clear();
|
||||
m_values.Clear();
|
||||
//---
|
||||
m_offset =0;
|
||||
m_total_view=0;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::TotalView(const int value)
|
||||
{
|
||||
//--- if parameter is not equal to 0, modifications are not possible
|
||||
if(m_total_view!=0)
|
||||
{
|
||||
m_height_variable=true;
|
||||
return(false);
|
||||
}
|
||||
//--- save value
|
||||
m_total_view=value;
|
||||
//--- parameter has been changed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::Show(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
CWndClient::Show();
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//---
|
||||
if(total==0)
|
||||
total=1;
|
||||
//---
|
||||
if(m_height_variable && total<m_total_view)
|
||||
for(int i=total;i<m_total_view;i++)
|
||||
m_rows[i].Hide();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create "row" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::CreateRow(const int index)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH+m_item_height*index;
|
||||
int x2=Width()-2*CONTROLS_BORDER_WIDTH;
|
||||
int y2=y1+m_item_height;
|
||||
//--- create
|
||||
if(!m_rows[index].Create(m_chart_id,m_name+"Item"+IntegerToString(index),m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_rows[index].Text(""))
|
||||
return(false);
|
||||
if(!m_rows[index].ReadOnly(true))
|
||||
return(false);
|
||||
if(!RowState(index,false))
|
||||
return(false);
|
||||
if(!Add(m_rows[index]))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::AddItem(const string item,const long value)
|
||||
{
|
||||
//--- method left for compatibility with previous version
|
||||
return(ItemAdd(item,value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::ItemAdd(const string item,const long value)
|
||||
{
|
||||
//--- add
|
||||
if(!m_strings.Add(item))
|
||||
return(false);
|
||||
if(!m_values.Add((value)?value:m_values.Total()))
|
||||
return(false);
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//--- exit if number of items does not exceed the size of visible area
|
||||
if(total<m_total_view+1)
|
||||
{
|
||||
if(m_height_variable && total!=1)
|
||||
{
|
||||
Height(total*m_item_height+2*CONTROLS_BORDER_WIDTH);
|
||||
if(IS_VISIBLE)
|
||||
m_rows[total-1].Show();
|
||||
}
|
||||
return(Redraw());
|
||||
}
|
||||
//--- if number of items exceeded the size of visible area
|
||||
if(total==m_total_view+1)
|
||||
{
|
||||
//--- enable vertical scrollbar
|
||||
if(!VScrolled(true))
|
||||
return(false);
|
||||
//--- and immediately make it invisible (if needed)
|
||||
if(IS_VISIBLE && !OnVScrollShow())
|
||||
return(false);
|
||||
}
|
||||
//--- set up the scrollbar
|
||||
m_scroll_v.MaxPos(m_strings.Total()-m_total_view);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Insert item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::ItemInsert(const int index,const string item,const long value)
|
||||
{
|
||||
//--- insert
|
||||
if(!m_strings.Insert(item,index))
|
||||
return(false);
|
||||
if(!m_values.Insert(value,index))
|
||||
return(false);
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//--- exit if number of items does not exceed the size of visible area
|
||||
if(total<m_total_view+1)
|
||||
{
|
||||
if(m_height_variable && total!=1)
|
||||
{
|
||||
Height(total*m_item_height+2*CONTROLS_BORDER_WIDTH);
|
||||
if(IS_VISIBLE)
|
||||
m_rows[total-1].Show();
|
||||
}
|
||||
return(Redraw());
|
||||
}
|
||||
//--- if number of items exceeded the size of visible area
|
||||
if(total==m_total_view+1)
|
||||
{
|
||||
//--- enable vertical scrollbar
|
||||
if(!VScrolled(true))
|
||||
return(false);
|
||||
//--- and immediately make it invisible (if needed)
|
||||
if(IS_VISIBLE && !OnVScrollShow())
|
||||
return(false);
|
||||
}
|
||||
//--- set up the scrollbar
|
||||
m_scroll_v.MaxPos(m_strings.Total()-m_total_view);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::ItemUpdate(const int index,const string item,const long value)
|
||||
{
|
||||
//--- update
|
||||
if(!m_strings.Update(index,item))
|
||||
return(false);
|
||||
if(!m_values.Update(index,value))
|
||||
return(false);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::ItemDelete(const int index)
|
||||
{
|
||||
//--- delete
|
||||
if(!m_strings.Delete(index))
|
||||
return(false);
|
||||
if(!m_values.Delete(index))
|
||||
return(false);
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//--- exit if number of items does not exceed the size of visible area
|
||||
if(total<m_total_view)
|
||||
{
|
||||
if(m_height_variable && total!=0)
|
||||
{
|
||||
Height(total*m_item_height+2*CONTROLS_BORDER_WIDTH);
|
||||
m_rows[total].Hide();
|
||||
}
|
||||
return(Redraw());
|
||||
}
|
||||
//--- if number of items exceeded the size of visible area
|
||||
if(total==m_total_view)
|
||||
{
|
||||
//--- disable vertical scrollbar
|
||||
if(!VScrolled(false))
|
||||
return(false);
|
||||
//--- and immediately make it unvisible
|
||||
if(!OnVScrollHide())
|
||||
return(false);
|
||||
}
|
||||
//--- set up the scrollbar
|
||||
m_scroll_v.MaxPos(m_strings.Total()-m_total_view);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete all items |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::ItemsClear(void)
|
||||
{
|
||||
m_offset=0;
|
||||
//--- clear
|
||||
if(!m_strings.Shutdown())
|
||||
return(false);
|
||||
if(!m_values.Shutdown())
|
||||
return(false);
|
||||
//---
|
||||
if(m_height_variable)
|
||||
{
|
||||
Height(m_item_height+2*CONTROLS_BORDER_WIDTH);
|
||||
for(int i=1;i<m_total_view;i++)
|
||||
m_rows[i].Hide();
|
||||
}
|
||||
//--- disable vertical scrollbar
|
||||
if(!VScrolled(false))
|
||||
return(false);
|
||||
//--- and immediately make it unvisible (if needed)
|
||||
if(!OnVScrollHide())
|
||||
return(false);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sett current item |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::Select(const int index)
|
||||
{
|
||||
//--- check index
|
||||
if(index>=m_strings.Total())
|
||||
return(false);
|
||||
if(index<0 && index!=CONTROLS_INVALID_INDEX)
|
||||
return(false);
|
||||
//--- unselect
|
||||
if(m_current!=CONTROLS_INVALID_INDEX)
|
||||
RowState(m_current-m_offset,false);
|
||||
//--- select
|
||||
if(index!=CONTROLS_INVALID_INDEX)
|
||||
RowState(index-m_offset,true);
|
||||
//--- save value
|
||||
m_current=index;
|
||||
//--- succeed
|
||||
return(CheckView());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set current item (by text) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::SelectByText(const string text)
|
||||
{
|
||||
//--- find text
|
||||
int index=m_strings.SearchLinear(text);
|
||||
//--- if text is not found, exit without changing the selection
|
||||
if(index==CONTROLS_INVALID_INDEX)
|
||||
return(false);
|
||||
//--- change selection
|
||||
return(Select(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set current item (by value) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::SelectByValue(const long value)
|
||||
{
|
||||
//--- find value
|
||||
int index=m_values.SearchLinear(value);
|
||||
//--- if value is not found, exit without changing the selection
|
||||
if(index==CONTROLS_INVALID_INDEX)
|
||||
return(false);
|
||||
//--- change selection
|
||||
return(Select(index));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Redraw |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::Redraw(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- copy text
|
||||
if(!m_rows[i].Text(m_strings.At(i+m_offset)))
|
||||
return(false);
|
||||
//--- select
|
||||
if(!RowState(i,(m_current==i+m_offset)))
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Change state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::RowState(const int index,const bool select)
|
||||
{
|
||||
//--- check index
|
||||
if(index<0 || index>=ArraySize(m_rows))
|
||||
return(true);
|
||||
//--- determine colors
|
||||
color text_color=(select) ? CONTROLS_LISTITEM_COLOR_TEXT_SEL : CONTROLS_LISTITEM_COLOR_TEXT;
|
||||
color back_color=(select) ? CONTROLS_LISTITEM_COLOR_BG_SEL : CONTROLS_LISTITEM_COLOR_BG;
|
||||
//--- get pointer
|
||||
CEdit *item=GetPointer(m_rows[index]);
|
||||
//--- recolor the "row"
|
||||
return(item.Color(text_color) && item.ColorBackground(back_color) && item.ColorBorder(back_color));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check visibility of selected row |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::CheckView(void)
|
||||
{
|
||||
//--- check visibility
|
||||
if(m_current>=m_offset && m_current<m_offset+m_total_view)
|
||||
return(true);
|
||||
//--- selected row is not visible
|
||||
int total=m_strings.Total();
|
||||
m_offset=(total-m_current>m_total_view) ? m_current : total-m_total_view;
|
||||
//--- adjust the scrollbar
|
||||
m_scroll_v.CurrPos(m_offset);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of resizing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnResize(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWndClient::OnResize())
|
||||
return(false);
|
||||
//--- set up the size of "row"
|
||||
if(VScrolled())
|
||||
OnVScrollShow();
|
||||
else
|
||||
OnVScrollHide();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Show vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnVScrollShow(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to shown vertical scrollbar
|
||||
m_rows[i].Width(Width()-(CONTROLS_SCROLL_SIZE+CONTROLS_BORDER_WIDTH));
|
||||
}
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
{
|
||||
m_scroll_v.Visible(false);
|
||||
return(true);
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Hide vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnVScrollHide(void)
|
||||
{
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
return(true);
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to hidden vertical scroll bar
|
||||
m_rows[i].Width(Width()-2*CONTROLS_BORDER_WIDTH);
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll up for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnScrollLineUp(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll down for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnScrollLineDown(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on row |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CListView::OnItemClick(const int index)
|
||||
{
|
||||
//--- select "row"
|
||||
Select(index+m_offset);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,124 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Panel.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CPanel |
|
||||
//| Usage: control that is displayed by |
|
||||
//| the CChartObjectRectLabel object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CPanel : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectRectLabel m_rectangle; // chart object
|
||||
//--- parameters of the chart object
|
||||
ENUM_BORDER_TYPE m_border; // border type
|
||||
|
||||
public:
|
||||
CPanel(void);
|
||||
~CPanel(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- parameters of the chart object
|
||||
ENUM_BORDER_TYPE BorderType(void) const { return(m_border); }
|
||||
bool BorderType(const ENUM_BORDER_TYPE type);
|
||||
|
||||
protected:
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetText(void) { return(m_rectangle.Description(m_text)); }
|
||||
virtual bool OnSetColorBackground(void) { return(m_rectangle.BackColor(m_color_background)); }
|
||||
virtual bool OnSetColorBorder(void) { return(m_rectangle.Color(m_color_border)); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
virtual bool OnResize(void);
|
||||
virtual bool OnChange(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPanel::CPanel(void) : m_border(BORDER_FLAT)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPanel::~CPanel(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_rectangle.Create(chart,name,subwin,x1,y1,Width(),Height()))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set border type |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::BorderType(const ENUM_BORDER_TYPE type)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_border=type;
|
||||
//--- set up the chart object
|
||||
return(m_rectangle.BorderType(type));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_rectangle.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnShow(void)
|
||||
{
|
||||
return(m_rectangle.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnHide(void)
|
||||
{
|
||||
return(m_rectangle.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_rectangle.X_Distance(m_rect.left) && m_rectangle.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnResize(void)
|
||||
{
|
||||
//--- resize the chart object
|
||||
return(m_rectangle.X_Size(m_rect.Width()) && m_rectangle.Y_Size(m_rect.Height()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPanel::OnChange(void)
|
||||
{
|
||||
//--- set up the chart object
|
||||
return(CWndObj::OnChange() && m_rectangle.BorderType(m_border));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,125 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Picture.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndObj.mqh"
|
||||
#include <ChartObjects\ChartObjectsBmpControls.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CPicture |
|
||||
//| Note: image displayed by |
|
||||
//| the CChartObjectBmpLabel object |
|
||||
//+------------------------------------------------------------------+
|
||||
class CPicture : public CWndObj
|
||||
{
|
||||
private:
|
||||
CChartObjectBmpLabel m_picture; // chart object
|
||||
//--- parameters of the chart object
|
||||
int m_border; // border width
|
||||
string m_bmp_name; // filename
|
||||
|
||||
public:
|
||||
CPicture(void);
|
||||
~CPicture(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- parameters of the chart object
|
||||
int Border(void) const { return(m_border); }
|
||||
bool Border(const int value);
|
||||
string BmpName(void) const { return(m_bmp_name); }
|
||||
bool BmpName(const string name);
|
||||
|
||||
protected:
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void);
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnMove(void);
|
||||
virtual bool OnChange(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPicture::CPicture(void) : m_border(0),
|
||||
m_bmp_name(NULL)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CPicture::~CPicture(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create the chart object
|
||||
if(!m_picture.Create(chart,name,subwin,x1,y1))
|
||||
return(false);
|
||||
//--- call the settings handler
|
||||
return(OnChange());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set border width |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::Border(const int value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_border=value;
|
||||
//--- set up the chart object
|
||||
return(m_picture.Width(value));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set image |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::BmpName(const string name)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_bmp_name=name;
|
||||
//--- set up the chart object
|
||||
return(m_picture.BmpFileOn(name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::OnCreate(void)
|
||||
{
|
||||
//--- create the chart object by previously set parameters
|
||||
return(m_picture.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display object on chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::OnShow(void)
|
||||
{
|
||||
return(m_picture.Timeframes(OBJ_ALL_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Hide object from chart |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::OnHide(void)
|
||||
{
|
||||
return(m_picture.Timeframes(OBJ_NO_PERIODS));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::OnMove(void)
|
||||
{
|
||||
//--- position the chart object
|
||||
return(m_picture.X_Distance(m_rect.left) && m_picture.Y_Distance(m_rect.top));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up the chart object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CPicture::OnChange(void)
|
||||
{
|
||||
//--- set up the chart object
|
||||
return(m_picture.Width(m_border) && m_picture.BmpFileOn(m_bmp_name));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,160 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RadioButton.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
#include "Edit.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
#resource "res\\RadioButtonOn.bmp"
|
||||
#resource "res\\RadioButtonOff.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CRadioButton |
|
||||
//| Usage: class that implements the "RadioButton" control |
|
||||
//+------------------------------------------------------------------+
|
||||
class CRadioButton : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CBmpButton m_button; // button object
|
||||
CEdit m_label; // label object
|
||||
|
||||
public:
|
||||
CRadioButton(void);
|
||||
~CRadioButton(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- settings
|
||||
string Text(void) const { return(m_label.Text()); }
|
||||
bool Text(const string value) { return(m_label.Text(value)); }
|
||||
color Color(void) const { return(m_label.Color()); }
|
||||
bool Color(const color value) { return(m_label.Color(value)); }
|
||||
//--- state
|
||||
bool State(void) const { return(m_button.Pressed()); }
|
||||
bool State(const bool flag) { return(m_button.Pressed(flag)); }
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateButton(void);
|
||||
virtual bool CreateLabel(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickButton(void);
|
||||
virtual bool OnClickLabel(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CRadioButton)
|
||||
ON_EVENT(ON_CLICK,m_button,OnClickButton)
|
||||
ON_EVENT(ON_CLICK,m_label,OnClickLabel)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRadioButton::CRadioButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRadioButton::~CRadioButton(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateButton())
|
||||
return(false);
|
||||
if(!CreateLabel())
|
||||
return(false);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioButton::CreateButton(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_RADIO_BUTTON_X_OFF;
|
||||
int y1=CONTROLS_RADIO_BUTTON_Y_OFF;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
//--- create
|
||||
if(!m_button.Create(m_chart_id,m_name+"Button",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_button.BmpNames("::res\\RadioButtonOff.bmp","::res\\RadioButtonOn.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_button))
|
||||
return(false);
|
||||
m_button.Locking(true);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create label |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioButton::CreateLabel(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_RADIO_LABEL_X_OFF;
|
||||
int y1=CONTROLS_RADIO_LABEL_Y_OFF;
|
||||
int x2=Width();
|
||||
int y2=Height();
|
||||
//--- create
|
||||
if(!m_label.Create(m_chart_id,m_name+"Label",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_label.Text(m_name))
|
||||
return(false);
|
||||
if(!Add(m_label))
|
||||
return(false);
|
||||
m_label.ReadOnly(true);
|
||||
m_label.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG);
|
||||
m_label.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BG);
|
||||
//--- succeeded
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioButton::OnClickButton(void)
|
||||
{
|
||||
//--- if button is in the "turned off" state, turn it on again and complete the handling
|
||||
//--- this is due to that radio button can not be turned off by clicking on it (it can be only turned on)
|
||||
if(!m_button.Pressed())
|
||||
{
|
||||
//--- turn on the radio button
|
||||
if(!m_button.Pressed(true))
|
||||
return(false);
|
||||
}
|
||||
//--- send the "changed state" event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on label |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioButton::OnClickLabel(void)
|
||||
{
|
||||
//--- if button is in the "turned on" state, simply complete the handling
|
||||
//--- this is due to that radio button can not be turned off by clicking on it (it can be only turned on)
|
||||
if(m_button.Pressed())
|
||||
return(true);
|
||||
//--- turn on the radio button
|
||||
m_button.Pressed(true);
|
||||
//--- return the result of the button click handler
|
||||
return(OnClickButton());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,361 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RadioGroup.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndClient.mqh"
|
||||
#include "RadioButton.mqh"
|
||||
#include <Arrays\ArrayString.mqh>
|
||||
#include <Arrays\ArrayLong.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CRadioGroup |
|
||||
//| Usage: view and edit radio buttons |
|
||||
//+------------------------------------------------------------------+
|
||||
class CRadioGroup : public CWndClient
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CRadioButton m_rows[]; // array of the row objects
|
||||
//--- set up
|
||||
int m_offset; // index of first visible row in array of rows
|
||||
int m_total_view; // number of visible rows
|
||||
int m_item_height; // height of visible row
|
||||
//--- data
|
||||
CArrayString m_strings; // array of rows
|
||||
CArrayLong m_values; // array of values
|
||||
int m_current; // index of current row in array of rows
|
||||
|
||||
public:
|
||||
CRadioGroup(void);
|
||||
~CRadioGroup(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
virtual void Destroy(const int reason=0);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- fill
|
||||
virtual bool AddItem(const string item,const long value=0);
|
||||
//--- data
|
||||
long Value(void) const { return(m_values.At(m_current)); }
|
||||
bool Value(const long value);
|
||||
bool ValueCheck(long value) const;
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
bool CreateButton(const int index);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnVScrollShow(void);
|
||||
virtual bool OnVScrollHide(void);
|
||||
virtual bool OnScrollLineDown(void);
|
||||
virtual bool OnScrollLineUp(void);
|
||||
virtual bool OnChangeItem(const int row_index);
|
||||
//--- redraw
|
||||
bool Redraw(void);
|
||||
bool RowState(const int index,const bool select);
|
||||
void Select(const int index);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CRadioGroup)
|
||||
ON_INDEXED_EVENT(ON_CHANGE,m_rows,OnChangeItem)
|
||||
EVENT_MAP_END(CWndClient)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRadioGroup::CRadioGroup(void) : m_offset(0),
|
||||
m_total_view(0),
|
||||
m_item_height(CONTROLS_LIST_ITEM_HEIGHT),
|
||||
m_current(CONTROLS_INVALID_INDEX)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CRadioGroup::~CRadioGroup(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- determine the number of visible rows
|
||||
m_total_view=(y2-y1)/m_item_height;
|
||||
//--- check the number of visible rows
|
||||
if(m_total_view<1)
|
||||
return(false);
|
||||
//--- call method of the parent class
|
||||
if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- set up
|
||||
if(!m_background.ColorBackground(CONTROLS_RADIOGROUP_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_background.ColorBorder(CONTROLS_RADIOGROUP_COLOR_BORDER))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
ArrayResize(m_rows,m_total_view);
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
if(!CreateButton(i))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRadioGroup::Destroy(const int reason)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
CWndClient::Destroy(reason);
|
||||
//--- clear items
|
||||
m_strings.Clear();
|
||||
m_values.Clear();
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create "row" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::CreateButton(const int index)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH+m_item_height*index;
|
||||
int x2=Width()-CONTROLS_BORDER_WIDTH;
|
||||
int y2=y1+m_item_height;
|
||||
//--- create
|
||||
if(!m_rows[index].Create(m_chart_id,m_name+"Item"+IntegerToString(index),m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_rows[index].Text(""))
|
||||
return(false);
|
||||
if(!Add(m_rows[index]))
|
||||
return(false);
|
||||
m_rows[index].Hide();
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add item (row) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::AddItem(const string item,const long value)
|
||||
{
|
||||
//--- check value
|
||||
if(value!=0 && !ValueCheck(value))
|
||||
return(false);
|
||||
//--- add
|
||||
if(!m_strings.Add(item))
|
||||
return(false);
|
||||
if(!m_values.Add(value))
|
||||
return(false);
|
||||
//--- number of items
|
||||
int total=m_strings.Total();
|
||||
//--- exit if number of items does not exceed the size of visible area
|
||||
if(total<m_total_view+1)
|
||||
{
|
||||
if(IS_VISIBLE && total!=0)
|
||||
m_rows[total-1].Show();
|
||||
return(Redraw());
|
||||
}
|
||||
//--- if number of items exceeded the size of visible area
|
||||
if(total==m_total_view+1)
|
||||
{
|
||||
//--- enable vertical scrollbar
|
||||
if(!VScrolled(true))
|
||||
return(false);
|
||||
//--- and immediately make it invisible (if needed)
|
||||
if(!IS_VISIBLE)
|
||||
m_scroll_v.Visible(false);
|
||||
|
||||
}
|
||||
//--- set up the scrollbar
|
||||
m_scroll_v.MaxPos(m_strings.Total()-m_total_view);
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Value(const long value)
|
||||
{
|
||||
//--- çíà÷åíèå äîëæíî ïðèñóòñòâîâàòü â íàáîðå
|
||||
int total=m_values.Total();
|
||||
//---
|
||||
for(int i=0;i<total;i++)
|
||||
if(m_values.At(i)==value)
|
||||
Select(i+m_offset);
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::ValueCheck(long value) const
|
||||
{
|
||||
//--- ïðîâåðÿåìîå çíà÷åíèå íå äîëæíî äóáëèðîâàòü óæå ñóùåñòâóþùåå
|
||||
int total=m_values.Total();
|
||||
//---
|
||||
for(int i=0;i<total;i++)
|
||||
if(m_values.At(i)==value)
|
||||
return(false);
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the group visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Show(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWndClient::Show())
|
||||
return(false);
|
||||
//--- loop by rows
|
||||
int total=m_values.Total();
|
||||
for(int i=total;i<m_total_view;i++)
|
||||
m_rows[i].Hide();
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
FileWriteLong(file_handle,Value());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
if(!FileIsEnding(file_handle))
|
||||
Value(FileReadLong(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sett current item |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRadioGroup::Select(const int index)
|
||||
{
|
||||
//--- disable the "ON" state
|
||||
if(m_current!=-1)
|
||||
RowState(m_current-m_offset,false);
|
||||
//--- enable the "ON" state
|
||||
if(index!=-1)
|
||||
RowState(index-m_offset,true);
|
||||
//--- save value
|
||||
m_current=index;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Redraw |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::Redraw(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- copy text
|
||||
if(!m_rows[i].Text(m_strings.At(i+m_offset)))
|
||||
return(false);
|
||||
//--- select
|
||||
if(!RowState(i,(m_current==i+m_offset)))
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Change state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::RowState(const int index,const bool select)
|
||||
{
|
||||
//--- check index
|
||||
if(index<0 || index>=ArraySize(m_rows))
|
||||
return(true);
|
||||
//--- change state
|
||||
return(m_rows[index].State(select));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Show vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::OnVScrollShow(void)
|
||||
{
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to shown vertical scrollbar
|
||||
m_rows[i].Width(Width()-(CONTROLS_SCROLL_SIZE+CONTROLS_BORDER_WIDTH));
|
||||
}
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
{
|
||||
m_scroll_v.Visible(false);
|
||||
return(true);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Hide vertical scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::OnVScrollHide(void)
|
||||
{
|
||||
//--- check visibility
|
||||
if(!IS_VISIBLE)
|
||||
return(true);
|
||||
//--- loop by "rows"
|
||||
for(int i=0;i<m_total_view;i++)
|
||||
{
|
||||
//--- resize "rows" according to hidden vertical scroll bar
|
||||
m_rows[i].Width(Width()-CONTROLS_BORDER_WIDTH);
|
||||
}
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll up for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::OnScrollLineUp(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Scroll down for one row" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::OnScrollLineDown(void)
|
||||
{
|
||||
//--- get new offset
|
||||
m_offset=m_scroll_v.CurrPos();
|
||||
//--- redraw
|
||||
return(Redraw());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of changing a "row" state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRadioGroup::OnChangeItem(const int row_index)
|
||||
{
|
||||
//--- select "row"
|
||||
Select(row_index+m_offset);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,279 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Rect.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
//+------------------------------------------------------------------+
|
||||
//| Structure CPoint |
|
||||
//| Usage: point of chart in Cartesian coordinates |
|
||||
//+------------------------------------------------------------------+
|
||||
struct CPoint
|
||||
{
|
||||
int x; // horizontal coordinate
|
||||
int y; // vertical coordinate
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Structure CSize |
|
||||
//| Usage: size of area of chart in Cartesian coordinates |
|
||||
//+------------------------------------------------------------------+
|
||||
struct CSize
|
||||
{
|
||||
int cx; // horizontal size
|
||||
int cy; // vertical size
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Structure CRect |
|
||||
//| Usage: area of chart in Cartesian coordinates |
|
||||
//+------------------------------------------------------------------+
|
||||
struct CRect
|
||||
{
|
||||
int left; // left coordinate
|
||||
int top; // top coordinate
|
||||
int right; // right coordinate
|
||||
int bottom; // bottom coordinate
|
||||
|
||||
//--- methods
|
||||
CPoint LeftTop(void) const;
|
||||
void LeftTop(const int x,const int y);
|
||||
void LeftTop(const CPoint& point);
|
||||
CPoint RightBottom(void) const;
|
||||
void RightBottom(const int x,const int y);
|
||||
void RightBottom(const CPoint& point);
|
||||
CPoint CenterPoint(void) const;
|
||||
int Width(void) const { return(right-left); }
|
||||
void Width(const int w) { right=left+w; }
|
||||
int Height(void) const { return(bottom-top); }
|
||||
void Height(const int h) { bottom=top+h; }
|
||||
CSize Size(void) const;
|
||||
void Size(const int cx,const int cy);
|
||||
void Size(const CSize& size);
|
||||
void SetBound(const int l,const int t,const int r,const int b);
|
||||
void SetBound(const CRect& rect);
|
||||
void SetBound(const CPoint& point,const CSize& size);
|
||||
void SetBound(const CPoint& left_top,const CPoint& right_bottom);
|
||||
void Move(const int x,const int y);
|
||||
void Move(const CPoint& point);
|
||||
void Shift(const int dx,const int dy);
|
||||
void Shift(const CPoint& point);
|
||||
void Shift(const CSize& size);
|
||||
bool Contains(const int x,const int y) const;
|
||||
bool Contains(const CPoint& point) const;
|
||||
void Normalize(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
CPoint CRect::LeftTop(void) const
|
||||
{
|
||||
CPoint point;
|
||||
//--- action
|
||||
point.x=left;
|
||||
point.y=top;
|
||||
//--- result
|
||||
return(point);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::LeftTop(const int x,const int y)
|
||||
{
|
||||
left=x;
|
||||
top =y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::LeftTop(const CPoint& point)
|
||||
{
|
||||
left=point.x;
|
||||
top =point.y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
CPoint CRect::RightBottom(void) const
|
||||
{
|
||||
CPoint point;
|
||||
//--- action
|
||||
point.x=right;
|
||||
point.y=bottom;
|
||||
//--- result
|
||||
return(point);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::RightBottom(const int x,const int y)
|
||||
{
|
||||
right =x;
|
||||
bottom=y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::RightBottom(const CPoint& point)
|
||||
{
|
||||
right =point.x;
|
||||
bottom=point.y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
CPoint CRect::CenterPoint(void) const
|
||||
{
|
||||
CPoint point;
|
||||
//--- action
|
||||
point.x=left+Width()/2;
|
||||
point.y=top+Height()/2;
|
||||
//--- result
|
||||
return(point);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
CSize CRect::Size(void) const
|
||||
{
|
||||
CSize size;
|
||||
//--- action
|
||||
size.cx=right-left;
|
||||
size.cy=bottom-top;
|
||||
//--- result
|
||||
return(size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Size(const int cx,const int cy)
|
||||
{
|
||||
right =left+cx;
|
||||
bottom=top+cy;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Size(const CSize& size)
|
||||
{
|
||||
right =left+size.cx;
|
||||
bottom=top+size.cy;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::SetBound(const int l,const int t,const int r,const int b)
|
||||
{
|
||||
left =l;
|
||||
top =t;
|
||||
right =r;
|
||||
bottom=b;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::SetBound(const CRect& rect)
|
||||
{
|
||||
left =rect.left;
|
||||
top =rect.top;
|
||||
right =rect.right;
|
||||
bottom=rect.bottom;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::SetBound(const CPoint& point,const CSize& size)
|
||||
{
|
||||
LeftTop(point);
|
||||
Size(size);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::SetBound(const CPoint& left_top,const CPoint& right_bottom)
|
||||
{
|
||||
LeftTop(left_top);
|
||||
RightBottom(right_bottom);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Move(const int x,const int y)
|
||||
{
|
||||
right +=x-left;
|
||||
bottom+=y-top;
|
||||
left =x;
|
||||
top =y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Move(const CPoint& point)
|
||||
{
|
||||
right +=point.x-left;
|
||||
bottom+=point.y-top;
|
||||
left =point.x;
|
||||
top =point.y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Relative movement of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Shift(const int dx,const int dy)
|
||||
{
|
||||
left +=dx;
|
||||
top +=dy;
|
||||
right +=dx;
|
||||
bottom+=dy;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Relative movement of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Shift(const CPoint& point)
|
||||
{
|
||||
left +=point.x;
|
||||
top +=point.y;
|
||||
right +=point.x;
|
||||
bottom+=point.y;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Relative movement of area |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Shift(const CSize& size)
|
||||
{
|
||||
left +=size.cx;
|
||||
top +=size.cy;
|
||||
right +=size.cx;
|
||||
bottom+=size.cy;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if a point is within the area |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRect::Contains(const int x,const int y) const
|
||||
{
|
||||
//--- check and return the result
|
||||
return(x>=left && x<=right && y>=top && y<=bottom);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if a point is within the area |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CRect::Contains(const CPoint& point) const
|
||||
{
|
||||
//--- check and return the result
|
||||
return(point.x>=left && point.x<=right && point.y>=top && point.y<=bottom);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Standardizes the height and width |
|
||||
//+------------------------------------------------------------------+
|
||||
void CRect::Normalize(void)
|
||||
{
|
||||
if(left>right)
|
||||
{
|
||||
int tmp1=left;
|
||||
left=right;
|
||||
right=tmp1;
|
||||
}
|
||||
if(top>bottom)
|
||||
{
|
||||
int tmp2=top;
|
||||
top=bottom;
|
||||
bottom=tmp2;
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,675 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Scrolls.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "Panel.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
#resource "res\\Up.bmp"
|
||||
#resource "res\\ThumbVert.bmp"
|
||||
#resource "res\\Down.bmp"
|
||||
#resource "res\\Left.bmp"
|
||||
#resource "res\\ThumbHor.bmp"
|
||||
#resource "res\\Right.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CScroll |
|
||||
//| Usage: base class for scrollbars |
|
||||
//+------------------------------------------------------------------+
|
||||
class CScroll : public CWndContainer
|
||||
{
|
||||
protected:
|
||||
//--- dependent controls
|
||||
CPanel m_back; // the "scrollbar background" object
|
||||
CBmpButton m_inc; // the "increment button" object ("down" for vertical scrollbar, "right" for horizontal scrollbar)
|
||||
CBmpButton m_dec; // the "decrement button" object ("up" for vertical scrollbar, "left" for horizontal scrollbar)
|
||||
CBmpButton m_thumb; // the "scroll box" object
|
||||
//--- set up
|
||||
int m_min_pos; // minimum value
|
||||
int m_max_pos; // maximum value
|
||||
//--- state
|
||||
int m_curr_pos; // current value
|
||||
|
||||
public:
|
||||
CScroll(void);
|
||||
~CScroll(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up
|
||||
int MinPos(void) const { return(m_min_pos); }
|
||||
void MinPos(const int value);
|
||||
int MaxPos(void) const { return(m_max_pos); }
|
||||
void MaxPos(const int value);
|
||||
//--- state
|
||||
int CurrPos(void) const { return(m_curr_pos); }
|
||||
bool CurrPos(int value);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateBack(void);
|
||||
virtual bool CreateInc(void) { return(true); }
|
||||
virtual bool CreateDec(void) { return(true); }
|
||||
virtual bool CreateThumb(void) { return(true); }
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickInc(void);
|
||||
virtual bool OnClickDec(void);
|
||||
//--- internal event handlers
|
||||
virtual bool OnShow(void);
|
||||
virtual bool OnHide(void);
|
||||
virtual bool OnChangePos(void) { return(true); }
|
||||
//--- handlers of dragging
|
||||
virtual bool OnThumbDragStart(void) { return(true); }
|
||||
virtual bool OnThumbDragProcess(void) { return(true); }
|
||||
virtual bool OnThumbDragEnd(void) { return(true); }
|
||||
//--- calculate position by coordinate
|
||||
virtual int CalcPos(const int coord) { return(0); }
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CScroll)
|
||||
ON_EVENT(ON_CLICK,m_inc,OnClickInc)
|
||||
ON_EVENT(ON_CLICK,m_dec,OnClickDec)
|
||||
ON_EVENT(ON_DRAG_START,m_thumb,OnThumbDragStart)
|
||||
ON_EVENT_PTR(ON_DRAG_PROCESS,m_drag_object,OnThumbDragProcess)
|
||||
ON_EVENT_PTR(ON_DRAG_END,m_drag_object,OnThumbDragEnd)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScroll::CScroll(void) : m_curr_pos(0),
|
||||
m_min_pos(0),
|
||||
m_max_pos(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScroll::~CScroll(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateBack())
|
||||
return(false);
|
||||
if(!CreateInc())
|
||||
return(false);
|
||||
if(!CreateDec())
|
||||
return(false);
|
||||
if(!CreateThumb())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create scrollbar background |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::CreateBack(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_back.Create(m_chart_id,m_name+"Back",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!m_back.ColorBackground(CONTROLS_SCROLL_COLOR_BG))
|
||||
return(false);
|
||||
if(!m_back.ColorBorder(CONTROLS_SCROLL_COLOR_BORDER))
|
||||
return(false);
|
||||
if(!Add(m_back))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set current value |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::CurrPos(int value)
|
||||
{
|
||||
//--- check value
|
||||
if(value<m_min_pos)
|
||||
value=m_min_pos;
|
||||
if(value>m_max_pos)
|
||||
value=m_max_pos;
|
||||
//--- if value was changed
|
||||
if(m_curr_pos!=value)
|
||||
{
|
||||
m_curr_pos=value;
|
||||
//--- call virtual handler
|
||||
return(OnChangePos());
|
||||
}
|
||||
//--- value has not been changed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set minimum value |
|
||||
//+------------------------------------------------------------------+
|
||||
void CScroll::MinPos(const int value)
|
||||
{
|
||||
//--- if value was changed
|
||||
if(m_min_pos!=value)
|
||||
{
|
||||
m_min_pos=value;
|
||||
//--- adjust the scroll box position
|
||||
CurrPos(m_curr_pos);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set maximum value |
|
||||
//+------------------------------------------------------------------+
|
||||
void CScroll::MaxPos(const int value)
|
||||
{
|
||||
//--- if value was changed
|
||||
if(m_max_pos!=value)
|
||||
{
|
||||
m_max_pos=value;
|
||||
//--- adjust the scroll box position
|
||||
CurrPos(m_curr_pos);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Show scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::OnShow(void)
|
||||
{
|
||||
if(m_id==CONTROLS_INVALID_ID)
|
||||
return(true);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_SHOW,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Hide scrollbar" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::OnHide(void)
|
||||
{
|
||||
if(m_id==CONTROLS_INVALID_ID)
|
||||
return(true);
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_HIDE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "increment" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::OnClickInc(void)
|
||||
{
|
||||
//--- try to increment current value
|
||||
if(!CurrPos(m_curr_pos+1))
|
||||
return(true);
|
||||
//--- if value was changed, send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_SCROLL_INC,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "decrement" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScroll::OnClickDec(void)
|
||||
{
|
||||
//--- try to decrement current value
|
||||
if(!CurrPos(m_curr_pos-1))
|
||||
return(true);
|
||||
//--- if value was changed, send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_SCROLL_DEC,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CScrollV |
|
||||
//| Usage: class of vertical scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
class CScrollV : public CScroll
|
||||
{
|
||||
public:
|
||||
CScrollV(void);
|
||||
~CScrollV(void);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateInc(void);
|
||||
virtual bool CreateDec(void);
|
||||
virtual bool CreateThumb(void);
|
||||
//--- internal event handlers
|
||||
virtual bool OnResize(void);
|
||||
virtual bool OnChangePos(void);
|
||||
//--- handlers of dragging
|
||||
virtual bool OnThumbDragStart(void);
|
||||
virtual bool OnThumbDragProcess(void);
|
||||
virtual bool OnThumbDragEnd(void);
|
||||
//--- calculate position by coordinate
|
||||
virtual int CalcPos(const int coord);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScrollV::CScrollV(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScrollV::~CScrollV(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Increment" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::CreateInc(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=Height()-CONTROLS_SCROLL_SIZE+CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_inc.Create(m_chart_id,m_name+"Inc",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_inc.BmpNames("::res\\Down.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_inc))
|
||||
return(false);
|
||||
//--- property
|
||||
m_inc.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Decrement" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::CreateDec(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_dec.Create(m_chart_id,m_name+"Dec",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_dec.BmpNames("::res\\Up.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_dec))
|
||||
return(false);
|
||||
//--- property
|
||||
m_dec.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create scroll box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::CreateThumb(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_SCROLL_THUMB_SIZE;
|
||||
//--- create
|
||||
if(!m_thumb.Create(m_chart_id,m_name+"Thumb",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_thumb.BmpNames("::res\\ThumbVert.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_thumb))
|
||||
return(false);
|
||||
m_thumb.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of changing current state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::OnChangePos(void)
|
||||
{
|
||||
//--- check if scrolling is possible
|
||||
if(m_max_pos-m_min_pos<=0)
|
||||
return(Visible(false));
|
||||
else
|
||||
if(!Visible(true))
|
||||
return(false);
|
||||
//--- calculate new coordinated of the scrollbar
|
||||
int steps =m_max_pos-m_min_pos; // number of steps to change position
|
||||
int min_coord=m_dec.Bottom(); // minimum possible coordinate (corresponds to the m_min_pos value)
|
||||
int max_coord=m_inc.Top()-m_thumb.Height(); // maximum possible coordinate (corresponds to the m_max_pos value)
|
||||
int new_coord=min_coord+(max_coord-min_coord)*m_curr_pos/steps; // new coordinate
|
||||
//--- adjust the scroll box position
|
||||
return(m_thumb.Move(m_thumb.Left(),new_coord));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of resizing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::OnResize(void)
|
||||
{
|
||||
//--- can not change the lateral size
|
||||
if(Width()!=CONTROLS_SCROLL_SIZE)
|
||||
m_rect.Width(CONTROLS_SCROLL_SIZE);
|
||||
//--- resize the scrollbar background
|
||||
if(!m_back.Size(Size()))
|
||||
return(false);
|
||||
//--- move the "Increment" button
|
||||
if(!m_inc.Move(m_inc.Left(),Bottom()-CONTROLS_SCROLL_SIZE))
|
||||
return(false);
|
||||
//--- adjust the scroll box position
|
||||
return(OnChangePos());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Start dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::OnThumbDragStart(void)
|
||||
{
|
||||
if(m_drag_object==NULL)
|
||||
{
|
||||
m_drag_object=new CDragWnd;
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
}
|
||||
//--- calculate coordinates
|
||||
int x1=m_thumb.Left()-CONTROLS_DRAG_SPACING;
|
||||
int y1=m_thumb.Top()-CONTROLS_DRAG_SPACING;
|
||||
int x2=m_thumb.Right()+CONTROLS_DRAG_SPACING;
|
||||
int y2=m_thumb.Bottom()+CONTROLS_DRAG_SPACING;
|
||||
//--- create
|
||||
m_drag_object.Create(m_chart_id,"",m_subwin,x1,y1,x2,y2);
|
||||
m_drag_object.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- îãðàíè÷åíèÿ
|
||||
m_drag_object.Limits(x1,m_dec.Bottom()-CONTROLS_DRAG_SPACING,x2,m_inc.Top()+CONTROLS_DRAG_SPACING);
|
||||
//--- set mouse params
|
||||
m_drag_object.MouseX(m_thumb.MouseX());
|
||||
m_drag_object.MouseY(m_thumb.MouseY());
|
||||
m_drag_object.MouseFlags(m_thumb.MouseFlags());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Continue dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::OnThumbDragProcess(void)
|
||||
{
|
||||
//--- checking
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
//--- calculate coordinates
|
||||
int x=m_drag_object.Left()+CONTROLS_DRAG_SPACING;
|
||||
int y=m_drag_object.Top()+CONTROLS_DRAG_SPACING;
|
||||
//--- calculate new position
|
||||
int new_pos=CalcPos(y);
|
||||
if(new_pos!=m_curr_pos)
|
||||
{
|
||||
ushort event_id=(m_curr_pos<new_pos) ? ON_SCROLL_INC : ON_SCROLL_DEC;
|
||||
m_curr_pos=new_pos;
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,event_id,m_id,0.0,m_name);
|
||||
}
|
||||
//--- move thumb
|
||||
m_thumb.Move(x,y);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| End dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollV::OnThumbDragEnd(void)
|
||||
{
|
||||
if(m_drag_object!=NULL)
|
||||
{
|
||||
m_thumb.MouseFlags(m_drag_object.MouseFlags());
|
||||
delete m_drag_object;
|
||||
m_drag_object=NULL;
|
||||
}
|
||||
//--- succeed
|
||||
return(m_thumb.Pressed(false));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate position by coordinate |
|
||||
//+------------------------------------------------------------------+
|
||||
int CScrollV::CalcPos(const int coord)
|
||||
{
|
||||
//--- calculate new position of the scrollbar
|
||||
int steps =m_max_pos-m_min_pos; // number of steps to change position
|
||||
int min_coord=m_dec.Bottom(); // minimum possible coordinate (corresponds to the m_min_pos value)
|
||||
int max_coord=m_inc.Top()-m_thumb.Height(); // maximum possible coordinate (corresponds to the m_max_pos value)
|
||||
//--- checkeng
|
||||
if(max_coord==min_coord)
|
||||
return(0);
|
||||
if(coord<min_coord || coord>max_coord)
|
||||
return(m_curr_pos);
|
||||
//---
|
||||
int new_pos=(int)MathRound((((double)(coord-min_coord))/(max_coord-min_coord))*steps); // new position
|
||||
//---
|
||||
return(new_pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CScrollH |
|
||||
//| Usage: class of horizontal scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
class CScrollH : public CScroll
|
||||
{
|
||||
public:
|
||||
CScrollH(void);
|
||||
~CScrollH(void);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateInc(void);
|
||||
virtual bool CreateDec(void);
|
||||
virtual bool CreateThumb(void);
|
||||
//--- internal event handlers
|
||||
virtual bool OnResize(void);
|
||||
virtual bool OnChangePos(void);
|
||||
//--- handlers of dragging
|
||||
virtual bool OnThumbDragStart(void);
|
||||
virtual bool OnThumbDragProcess(void);
|
||||
virtual bool OnThumbDragEnd(void);
|
||||
//--- calculate position by coordinate
|
||||
virtual int CalcPos(const int coord);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScrollH::CScrollH(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CScrollH::~CScrollH(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Increment" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::CreateInc(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=Width()-CONTROLS_SCROLL_SIZE+CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_inc.Create(m_chart_id,m_name+"Inc",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_inc.BmpNames("::res\\Right.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_inc))
|
||||
return(false);
|
||||
//--- property
|
||||
m_inc.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Decrement" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::CreateDec(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_dec.Create(m_chart_id,m_name+"Dec",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_dec.BmpNames("::res\\Left.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_dec))
|
||||
return(false);
|
||||
//--- property
|
||||
m_dec.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create scroll box |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::CreateThumb(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH;
|
||||
int x2=x1+CONTROLS_SCROLL_THUMB_SIZE;
|
||||
int y2=y1+CONTROLS_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_thumb.Create(m_chart_id,m_name+"Thumb",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_thumb.BmpNames("::res\\ThumbHor.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_thumb))
|
||||
return(false);
|
||||
m_thumb.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of changing current state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::OnChangePos(void)
|
||||
{
|
||||
//--- check if scrolling is possible
|
||||
if(m_max_pos-m_min_pos<=0)
|
||||
return(Visible(false));
|
||||
else
|
||||
if(!Visible(true))
|
||||
return(false);
|
||||
//--- calculate new coordinated of the scrollbar
|
||||
int steps=m_max_pos-m_min_pos; // number of steps to change position
|
||||
int min_coord=m_dec.Right(); // minimum possible coordinate (corresponds to the m_min_pos value)
|
||||
int max_coord=m_inc.Left()-m_thumb.Width(); // maximum possible coordinate (corresponds to the m_max_pos value)
|
||||
int new_coord=min_coord+(max_coord-min_coord)*m_curr_pos/steps; // new coordinate
|
||||
//--- adjust the scroll box position
|
||||
return(m_thumb.Move(new_coord,m_thumb.Top()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of resizing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::OnResize(void)
|
||||
{
|
||||
//--- can not change the lateral size
|
||||
if(Height()!=CONTROLS_SCROLL_SIZE)
|
||||
m_rect.Height(CONTROLS_SCROLL_SIZE);
|
||||
//--- resize the scrollbar background
|
||||
if(!m_back.Size(Size()))
|
||||
return(false);
|
||||
//--- move the "Increment" button
|
||||
if(!m_inc.Move(Right()-CONTROLS_SCROLL_SIZE,m_inc.Top()))
|
||||
return(false);
|
||||
//--- adjust the scroll box position
|
||||
return(OnChangePos());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Start dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::OnThumbDragStart(void)
|
||||
{
|
||||
if(m_drag_object==NULL)
|
||||
{
|
||||
m_drag_object=new CDragWnd;
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
}
|
||||
//--- calculate coordinates
|
||||
int x1=m_thumb.Left()-CONTROLS_DRAG_SPACING;
|
||||
int y1=m_thumb.Top()-CONTROLS_DRAG_SPACING;
|
||||
int x2=m_thumb.Right()+CONTROLS_DRAG_SPACING;
|
||||
int y2=m_thumb.Bottom()+CONTROLS_DRAG_SPACING;
|
||||
//--- create
|
||||
m_drag_object.Create(m_chart_id,"",m_subwin,x1,y1,x2,y2);
|
||||
m_drag_object.PropFlags(WND_PROP_FLAG_CAN_DRAG);
|
||||
//--- îãðàíè÷åíèÿ
|
||||
m_drag_object.Limits(m_dec.Right()-CONTROLS_DRAG_SPACING,y1,m_inc.Left()+CONTROLS_DRAG_SPACING,y2);
|
||||
//--- set mouse params
|
||||
m_drag_object.MouseX(m_thumb.MouseX());
|
||||
m_drag_object.MouseY(m_thumb.MouseY());
|
||||
m_drag_object.MouseFlags(m_thumb.MouseFlags());
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Continue dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::OnThumbDragProcess(void)
|
||||
{
|
||||
//--- checking
|
||||
if(m_drag_object==NULL)
|
||||
return(false);
|
||||
//--- calculate coordinates
|
||||
int x=m_drag_object.Left()+CONTROLS_DRAG_SPACING;
|
||||
int y=m_drag_object.Top()+CONTROLS_DRAG_SPACING;
|
||||
//--- calculate new position
|
||||
int new_pos=CalcPos(x);
|
||||
if(new_pos!=m_curr_pos)
|
||||
{
|
||||
ushort event_id=(m_curr_pos<new_pos)?ON_SCROLL_INC:ON_SCROLL_DEC;
|
||||
m_curr_pos=new_pos;
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,event_id,m_id,0.0,m_name);
|
||||
}
|
||||
//--- move thumb
|
||||
m_thumb.Move(x,y);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| End dragging the "slider" |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CScrollH::OnThumbDragEnd(void)
|
||||
{
|
||||
if(m_drag_object!=NULL)
|
||||
{
|
||||
m_thumb.MouseFlags(m_drag_object.MouseFlags());
|
||||
delete m_drag_object;
|
||||
m_drag_object=NULL;
|
||||
}
|
||||
//--- succeed
|
||||
return(m_thumb.Pressed(false));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate position by coordinate |
|
||||
//+------------------------------------------------------------------+
|
||||
int CScrollH::CalcPos(const int coord)
|
||||
{
|
||||
//--- calculate new position of the scrollbar
|
||||
int steps =m_max_pos-m_min_pos; // number of steps to change position
|
||||
int min_coord=m_dec.Right(); // minimum possible coordinate (corresponds to the m_min_pos value)
|
||||
int max_coord=m_inc.Left()-m_thumb.Width(); // maximum possible coordinate (corresponds to the m_max_pos value)
|
||||
//--- checkeng
|
||||
if(max_coord==min_coord)
|
||||
return(0);
|
||||
if(coord<min_coord || coord>max_coord)
|
||||
return(m_curr_pos);
|
||||
//---
|
||||
int new_pos=(int)MathRound((((double)(coord-min_coord))/(max_coord-min_coord))*steps); // new position
|
||||
//---
|
||||
return(new_pos);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,265 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SpinEdit.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "Edit.mqh"
|
||||
#include "BmpButton.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resources |
|
||||
//+------------------------------------------------------------------+
|
||||
#resource "res\\SpinInc.bmp"
|
||||
#resource "res\\SpinDec.bmp"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CSpinEdit |
|
||||
//| Usage: class that implements the "Up-Down" control |
|
||||
//+------------------------------------------------------------------+
|
||||
class CSpinEdit : public CWndContainer
|
||||
{
|
||||
private:
|
||||
//--- dependent controls
|
||||
CEdit m_edit; // the entry field object
|
||||
CBmpButton m_inc; // the "Increment button" object
|
||||
CBmpButton m_dec; // the "Decrement button" object
|
||||
//--- adjusted parameters
|
||||
int m_min_value; // minimum value
|
||||
int m_max_value; // maximum value
|
||||
//--- state
|
||||
int m_value; // current value
|
||||
|
||||
public:
|
||||
CSpinEdit(void);
|
||||
~CSpinEdit(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up
|
||||
int MinValue(void) const { return(m_min_value); }
|
||||
void MinValue(const int value);
|
||||
int MaxValue(void) const { return(m_max_value); }
|
||||
void MaxValue(const int value);
|
||||
//--- state
|
||||
int Value(void) const { return(m_value); }
|
||||
bool Value(int value);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateEdit(void);
|
||||
virtual bool CreateInc(void);
|
||||
virtual bool CreateDec(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnClickInc(void);
|
||||
virtual bool OnClickDec(void);
|
||||
//--- internal event handlers
|
||||
virtual bool OnChangeValue(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CSpinEdit)
|
||||
ON_EVENT(ON_CLICK,m_inc,OnClickInc)
|
||||
ON_EVENT(ON_CLICK,m_dec,OnClickDec)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSpinEdit::CSpinEdit(void) : m_min_value(0),
|
||||
m_max_value(0),
|
||||
m_value(0)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CSpinEdit::~CSpinEdit(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- check height
|
||||
if(y2-y1<CONTROLS_SPIN_MIN_HEIGHT)
|
||||
return(false);
|
||||
//--- call method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateEdit())
|
||||
return(false);
|
||||
if(!CreateInc())
|
||||
return(false);
|
||||
if(!CreateDec())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set current value |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::Value(int value)
|
||||
{
|
||||
//--- check value
|
||||
if(value<m_min_value)
|
||||
value=m_min_value;
|
||||
if(value>m_max_value)
|
||||
value=m_max_value;
|
||||
//--- if value was changed
|
||||
if(m_value!=value)
|
||||
{
|
||||
m_value=value;
|
||||
//--- call virtual handler
|
||||
return(OnChangeValue());
|
||||
}
|
||||
//--- value has not been changed
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::Save(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
FileWriteInteger(file_handle,m_value);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::Load(const int file_handle)
|
||||
{
|
||||
//--- check
|
||||
if(file_handle==INVALID_HANDLE)
|
||||
return(false);
|
||||
//---
|
||||
if(!FileIsEnding(file_handle))
|
||||
Value(FileReadInteger(file_handle));
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set minimum value |
|
||||
//+------------------------------------------------------------------+
|
||||
void CSpinEdit::MinValue(const int value)
|
||||
{
|
||||
//--- if value was changed
|
||||
if(m_min_value!=value)
|
||||
{
|
||||
m_min_value=value;
|
||||
//--- adjust the edit value
|
||||
Value(m_value);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set maximum value |
|
||||
//+------------------------------------------------------------------+
|
||||
void CSpinEdit::MaxValue(const int value)
|
||||
{
|
||||
//--- if value was changed
|
||||
if(m_max_value!=value)
|
||||
{
|
||||
m_max_value=value;
|
||||
//--- adjust the edit value
|
||||
Value(m_value);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the edit field |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::CreateEdit(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_edit.Create(m_chart_id,m_name+"Edit",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!m_edit.Text(""))
|
||||
return(false);
|
||||
if(!m_edit.ReadOnly(true))
|
||||
return(false);
|
||||
if(!Add(m_edit))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Increment" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::CreateInc(void)
|
||||
{
|
||||
//--- right align button (try to make equal offsets from top and bottom)
|
||||
int x1=Width()-(CONTROLS_BUTTON_SIZE+CONTROLS_SPIN_BUTTON_X_OFF);
|
||||
int y1=(Height()-2*CONTROLS_SPIN_BUTTON_SIZE)/2;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_SPIN_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_inc.Create(m_chart_id,m_name+"Inc",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_inc.BmpNames("::res\\SpinInc.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_inc))
|
||||
return(false);
|
||||
//--- property
|
||||
m_inc.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the "Decrement" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::CreateDec(void)
|
||||
{
|
||||
//--- right align button (try to make equal offsets from top and bottom)
|
||||
int x1=Width()-(CONTROLS_BUTTON_SIZE+CONTROLS_SPIN_BUTTON_X_OFF);
|
||||
int y1=(Height()-2*CONTROLS_SPIN_BUTTON_SIZE)/2+CONTROLS_SPIN_BUTTON_SIZE;
|
||||
int x2=x1+CONTROLS_BUTTON_SIZE;
|
||||
int y2=y1+CONTROLS_SPIN_BUTTON_SIZE;
|
||||
//--- create
|
||||
if(!m_dec.Create(m_chart_id,m_name+"Dec",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!m_dec.BmpNames("::res\\SpinDec.bmp"))
|
||||
return(false);
|
||||
if(!Add(m_dec))
|
||||
return(false);
|
||||
//--- property
|
||||
m_dec.PropFlags(WND_PROP_FLAG_CLICKS_BY_PRESS);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "increment" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::OnClickInc(void)
|
||||
{
|
||||
//--- try to increment current value
|
||||
return(Value(m_value+1));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the "decrement" button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::OnClickDec(void)
|
||||
{
|
||||
//--- try to decrement current value
|
||||
return(Value(m_value-1));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of changing current state |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CSpinEdit::OnChangeValue(void)
|
||||
{
|
||||
//--- copy text to the edit field edit
|
||||
m_edit.Text(IntegerToString(m_value));
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,755 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| Wnd.mqh |
|
||||
//| Copyright 2009-2018, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Rect.mqh"
|
||||
#include "Defines.mqh"
|
||||
#include <Object.mqh>
|
||||
class CDragWnd;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CWnd |
|
||||
//| Usage: base class of the control object that creates |
|
||||
//| control panels and indicator panels |
|
||||
//+------------------------------------------------------------------+
|
||||
class CWnd : public CObject
|
||||
{
|
||||
protected:
|
||||
//--- parameters of creation
|
||||
long m_chart_id; // chart ID
|
||||
int m_subwin; // chart subwindow
|
||||
string m_name; // object name
|
||||
//--- geometry
|
||||
CRect m_rect; // chart area
|
||||
//--- ID
|
||||
long m_id; // object ID
|
||||
//--- state flags
|
||||
int m_state_flags;
|
||||
//--- properties flags
|
||||
int m_prop_flags;
|
||||
//--- alignment
|
||||
int m_align_flags; // alignment flags
|
||||
int m_align_left; // fixed offset from left border
|
||||
int m_align_top; // fixed offset from top border
|
||||
int m_align_right; // fixed offset from right border
|
||||
int m_align_bottom; // fixed offset from bottom border
|
||||
//--- the last saved state of mouse
|
||||
int m_mouse_x; // X coordinate
|
||||
int m_mouse_y; // Y coordinate
|
||||
int m_mouse_flags; // state of buttons
|
||||
uint m_last_click; // last click time
|
||||
//--- drag object
|
||||
CDragWnd *m_drag_object; // pointer to the dragged object
|
||||
|
||||
public:
|
||||
CWnd(void);
|
||||
~CWnd(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- release memory
|
||||
virtual void Destroy(const int reason=0);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
virtual bool OnMouseEvent(const int x,const int y,const int flags);
|
||||
//--- naming (read only)
|
||||
string Name(void) const { return(m_name); }
|
||||
//--- access the contents of container
|
||||
int ControlsTotal(void) const { return(0); }
|
||||
CWnd* Control(const int ind) const { return(NULL); }
|
||||
virtual CWnd* ControlFind(const long id);
|
||||
//--- geometry
|
||||
const CRect Rect(void) const { return(m_rect); }
|
||||
int Left(void) const { return(m_rect.left); }
|
||||
virtual void Left(const int x) { m_rect.left=x; }
|
||||
int Top(void) const { return(m_rect.top); }
|
||||
virtual void Top(const int y) { m_rect.top=y; }
|
||||
int Right(void) const { return(m_rect.right); }
|
||||
virtual void Right(const int x) { m_rect.right=x; }
|
||||
int Bottom(void) const { return(m_rect.bottom); }
|
||||
virtual void Bottom(const int y) { m_rect.bottom=y; }
|
||||
int Width(void) const { return(m_rect.Width()); }
|
||||
virtual bool Width(const int w);
|
||||
int Height(void) const { return(m_rect.Height()); }
|
||||
virtual bool Height(const int h);
|
||||
CSize Size(void) const { return(m_rect.Size()); }
|
||||
virtual bool Size(const int w,const int h);
|
||||
virtual bool Size(const CSize &size);
|
||||
virtual bool Move(const int x,const int y);
|
||||
virtual bool Move(const CPoint &point);
|
||||
virtual bool Shift(const int dx,const int dy);
|
||||
bool Contains(const int x,const int y) const { return(m_rect.Contains(x,y)); }
|
||||
bool Contains(CWnd *control) const;
|
||||
//--- alignment
|
||||
void Alignment(const int flags,const int left,const int top,const int right,const int bottom);
|
||||
virtual bool Align(const CRect &rect);
|
||||
//--- ID
|
||||
virtual long Id(const long id);
|
||||
long Id(void) const { return(m_id); }
|
||||
//--- state
|
||||
bool IsEnabled(void) const { return(IS_ENABLED); }
|
||||
virtual bool Enable(void);
|
||||
virtual bool Disable(void);
|
||||
bool IsVisible(void) const { return(IS_VISIBLE); }
|
||||
virtual bool Visible(const bool flag);
|
||||
virtual bool Show(void);
|
||||
virtual bool Hide(void);
|
||||
bool IsActive(void) const { return(IS_ACTIVE); }
|
||||
virtual bool Activate(void);
|
||||
virtual bool Deactivate(void);
|
||||
//--- state flags
|
||||
int StateFlags(void) const { return(m_state_flags); }
|
||||
void StateFlags(const int flags) { m_state_flags=flags; }
|
||||
void StateFlagsSet(const int flags) { m_state_flags|=flags; }
|
||||
void StateFlagsReset(const int flags) { m_state_flags&=~flags; }
|
||||
//--- properties flags
|
||||
int PropFlags(void) const { return(m_prop_flags); }
|
||||
void PropFlags(const int flags) { m_prop_flags=flags; }
|
||||
void PropFlagsSet(const int flags) { m_prop_flags|=flags; }
|
||||
void PropFlagsReset(const int flags) { m_prop_flags&=~flags; }
|
||||
//--- for mouse operations
|
||||
int MouseX(void) const { return(m_mouse_x); }
|
||||
void MouseX(const int value) { m_mouse_x=value; }
|
||||
int MouseY(void) const { return(m_mouse_y); }
|
||||
void MouseY(const int value) { m_mouse_y=value; }
|
||||
int MouseFlags(void) const { return(m_mouse_flags); }
|
||||
virtual void MouseFlags(const int value) { m_mouse_flags=value; }
|
||||
bool MouseFocusKill(const long id=CONTROLS_INVALID_ID);
|
||||
bool BringToTop(void);
|
||||
|
||||
protected:
|
||||
//--- internal event handlers
|
||||
virtual bool OnCreate(void) { return(true); }
|
||||
virtual bool OnDestroy(void) { return(true); }
|
||||
virtual bool OnMove(void) { return(true); }
|
||||
virtual bool OnResize(void) { return(true); }
|
||||
virtual bool OnEnable(void) { return(true); }
|
||||
virtual bool OnDisable(void) { return(true); }
|
||||
virtual bool OnShow(void) { return(true); }
|
||||
virtual bool OnHide(void) { return(true); }
|
||||
virtual bool OnActivate(void) { return(true); }
|
||||
virtual bool OnDeactivate(void) { return(true); }
|
||||
virtual bool OnClick(void);
|
||||
virtual bool OnDblClick(void);
|
||||
virtual bool OnChange(void) { return(true); }
|
||||
//--- mouse event handlers
|
||||
virtual bool OnMouseDown(void);
|
||||
virtual bool OnMouseUp(void);
|
||||
//--- handlers of dragging
|
||||
virtual bool OnDragStart(void);
|
||||
virtual bool OnDragProcess(const int x,const int y);
|
||||
virtual bool OnDragEnd(void);
|
||||
//--- methods for drag-object
|
||||
virtual bool DragObjectCreate(void) { return(false); }
|
||||
virtual bool DragObjectDestroy(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
if((id!=CHARTEVENT_MOUSE_MOVE))
|
||||
return(false);
|
||||
if(!IS_VISIBLE)
|
||||
return(false);
|
||||
int x=(int)lparam;
|
||||
int y=(int)dparam;
|
||||
int flags=(int)StringToInteger(sparam);
|
||||
//---
|
||||
if(m_drag_object!=NULL)
|
||||
return(m_drag_object.OnMouseEvent(x,y,flags));
|
||||
//---
|
||||
return(OnMouseEvent(x,y,flags));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of mouse events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnMouseEvent(const int x,const int y,const int flags)
|
||||
{
|
||||
if(!Contains(x,y))
|
||||
{
|
||||
//--- if cursor is not inside the element and this element is active - deactivate
|
||||
if(IS_ACTIVE)
|
||||
{
|
||||
//--- reset state and coordinates
|
||||
m_mouse_x =0;
|
||||
m_mouse_y =0;
|
||||
m_mouse_flags=MOUSE_INVALID_FLAGS;
|
||||
//--- deactivate
|
||||
Deactivate();
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
//--- check the state of the left mouse button
|
||||
if((flags&MOUSE_LEFT)!=0)
|
||||
{
|
||||
//--- left mouse button is pressed
|
||||
if(m_mouse_flags==MOUSE_INVALID_FLAGS)
|
||||
{
|
||||
//--- but not in this control (i.e., cursor entered the element with mouse button pressed)
|
||||
//--- activate the control, but there will be no click
|
||||
if(!IS_ACTIVE)
|
||||
{
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_MOUSE_FOCUS_SET,m_id,0.0,m_name);
|
||||
//--- activate
|
||||
return(Activate());
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
if((m_mouse_flags&MOUSE_LEFT)!=0)
|
||||
{
|
||||
//--- mouse button has already been pressed
|
||||
if(IS_CAN_DRAG)
|
||||
return(OnDragProcess(x,y));
|
||||
if(IS_CLICKS_BY_PRESS)
|
||||
{
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CLICK,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- mouse button has been released (pressing)
|
||||
//--- save the state and coordinates
|
||||
m_mouse_flags=flags;
|
||||
m_mouse_x =x;
|
||||
m_mouse_y =y;
|
||||
//--- call the handler
|
||||
return(OnMouseDown());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- left mouse button is released
|
||||
if(m_mouse_flags==MOUSE_INVALID_FLAGS)
|
||||
{
|
||||
//--- cursor entered the control with mouse button released
|
||||
//--- activate control and save state to the member
|
||||
m_mouse_flags=flags;
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_MOUSE_FOCUS_SET,m_id,0.0,m_name);
|
||||
//--- activate
|
||||
return(Activate());
|
||||
}
|
||||
if((m_mouse_flags&MOUSE_LEFT)!=0)
|
||||
{
|
||||
//--- mouse button has been pressed (clicking)
|
||||
//--- save the state and coordinates
|
||||
m_mouse_flags=flags;
|
||||
m_mouse_x =x;
|
||||
m_mouse_y =y;
|
||||
//--- call the handler
|
||||
return(OnMouseUp());
|
||||
}
|
||||
}
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWnd::CWnd(void) : m_chart_id(CONTROLS_INVALID_ID),
|
||||
m_subwin(CONTROLS_INVALID_ID),
|
||||
m_name(NULL),
|
||||
m_id(CONTROLS_INVALID_ID),
|
||||
m_state_flags(WND_STATE_FLAG_ENABLE+WND_STATE_FLAG_VISIBLE),
|
||||
m_prop_flags(0),
|
||||
m_align_flags(WND_ALIGN_NONE),
|
||||
m_align_left(0),
|
||||
m_align_top(0),
|
||||
m_align_right(0),
|
||||
m_align_bottom(0),
|
||||
m_mouse_x(0),
|
||||
m_mouse_y(0),
|
||||
m_mouse_flags(MOUSE_INVALID_FLAGS),
|
||||
m_last_click(0),
|
||||
m_drag_object(NULL)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWnd::~CWnd(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- attach to chart
|
||||
m_chart_id=chart;
|
||||
m_name =name;
|
||||
m_subwin =subwin;
|
||||
//--- set coordinates of area
|
||||
Left(x1);
|
||||
Top(y1);
|
||||
Right(x2);
|
||||
Bottom(y2);
|
||||
//--- always successful
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destruction of the control |
|
||||
//+------------------------------------------------------------------+
|
||||
void CWnd::Destroy(const int reason)
|
||||
{
|
||||
//--- call virtual event handler
|
||||
if(OnDestroy())
|
||||
m_name="";
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find control by specified ID |
|
||||
//+------------------------------------------------------------------+
|
||||
CWnd* CWnd::ControlFind(const long id)
|
||||
{
|
||||
CWnd *result=NULL;
|
||||
//--- check
|
||||
if(id==m_id)
|
||||
result=GetPointer(this);
|
||||
//--- return the result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Change width of control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Width(const int w)
|
||||
{
|
||||
//--- change width
|
||||
m_rect.Width(w);
|
||||
//--- call virtual event handler
|
||||
return(OnResize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Change height of control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Height(const int h)
|
||||
{
|
||||
//--- change height
|
||||
m_rect.Height(h);
|
||||
//--- call virtual event handler
|
||||
return(OnResize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Size(const int w,const int h)
|
||||
{
|
||||
//--- change size
|
||||
m_rect.Size(w,h);
|
||||
//--- call virtual event handler
|
||||
return(OnResize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Size(const CSize &size)
|
||||
{
|
||||
//--- change size
|
||||
m_rect.Size(size);
|
||||
//--- call virtual event handler
|
||||
return(OnResize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Move(const int x,const int y)
|
||||
{
|
||||
//--- moving
|
||||
m_rect.Move(x,y);
|
||||
//--- call virtual event handler
|
||||
return(OnMove());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Move(const CPoint &point)
|
||||
{
|
||||
//--- moving
|
||||
m_rect.Move(point);
|
||||
//--- call virtual event handler
|
||||
return(OnMove());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Relative movement of the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Shift(const int dx,const int dy)
|
||||
{
|
||||
//--- moving
|
||||
m_rect.Shift(dx,dy);
|
||||
//--- call virtual event handler
|
||||
return(OnMove());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check contains |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Contains(CWnd *control) const
|
||||
{
|
||||
//--- check
|
||||
if(control==NULL)
|
||||
return(false);
|
||||
//--- result
|
||||
return(Contains(control.Left(),control.Top()) && Contains(control.Right(),control.Bottom()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Enables event handling by the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Enable(void)
|
||||
{
|
||||
//--- if there are now changes, then succeed
|
||||
if(IS_ENABLED)
|
||||
return(true);
|
||||
//--- change flag
|
||||
StateFlagsSet(WND_STATE_FLAG_ENABLE);
|
||||
//--- call virtual event handler
|
||||
return(OnEnable());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Disables event handling by the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Disable(void)
|
||||
{
|
||||
//--- if there are now changes, then succeed
|
||||
if(!IS_ENABLED)
|
||||
return(true);
|
||||
//--- change flag
|
||||
StateFlagsReset(WND_STATE_FLAG_ENABLE);
|
||||
//--- call virtual event handler
|
||||
return(OnDisable());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "object is visible" flag for the control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Visible(const bool flag)
|
||||
{
|
||||
//--- if there are now changes, then succeed
|
||||
if(IS_VISIBLE==flag)
|
||||
return(true);
|
||||
//--- call virtual event handler
|
||||
return(flag ? Show() : Hide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Show(void)
|
||||
{
|
||||
//--- change flag
|
||||
StateFlagsSet(WND_STATE_FLAG_VISIBLE);
|
||||
//--- call virtual event handler
|
||||
return(OnShow());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control hidden |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Hide(void)
|
||||
{
|
||||
//--- change flag
|
||||
StateFlagsReset(WND_STATE_FLAG_VISIBLE);
|
||||
//--- call virtual event handler
|
||||
return(OnHide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control active |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Activate(void)
|
||||
{
|
||||
//--- if there are now changes, then succeed
|
||||
if(IS_ACTIVE)
|
||||
return(true);
|
||||
//--- change flag
|
||||
StateFlagsSet(WND_STATE_FLAG_ACTIVE);
|
||||
//--- call virtual event handler
|
||||
return(OnActivate());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control inactive |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Deactivate(void)
|
||||
{
|
||||
//--- if there are now changes, then succeed
|
||||
if(!IS_ACTIVE)
|
||||
return(true);
|
||||
//--- change flag
|
||||
StateFlagsReset(WND_STATE_FLAG_ACTIVE);
|
||||
//--- call virtual event handler
|
||||
return(OnDeactivate());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set ID of control |
|
||||
//+------------------------------------------------------------------+
|
||||
long CWnd::Id(const long id)
|
||||
{
|
||||
m_id=id;
|
||||
//--- always use only one ID
|
||||
return(1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set parameters of alignment |
|
||||
//+------------------------------------------------------------------+
|
||||
void CWnd::Alignment(const int flags,const int left,const int top,const int right,const int bottom)
|
||||
{
|
||||
m_align_flags =flags;
|
||||
m_align_left =left;
|
||||
m_align_top =top;
|
||||
m_align_right =right;
|
||||
m_align_bottom=bottom;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Align element in specified chart area |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::Align(const CRect &rect)
|
||||
{
|
||||
int new_value=0;
|
||||
//--- check
|
||||
if(m_align_flags==WND_ALIGN_NONE)
|
||||
return(true);
|
||||
//--- we are interested only in alignment by right and bottom borders,
|
||||
//--- as left and right borders are processed in the OnMove()
|
||||
if((m_align_flags&WND_ALIGN_RIGHT)!=0)
|
||||
{
|
||||
//--- there is alignment by right border,
|
||||
if((m_align_flags&WND_ALIGN_LEFT)!=0)
|
||||
{
|
||||
//--- and by left border (change size)
|
||||
new_value=rect.Width()-m_align_left-m_align_right;
|
||||
if(!Size(new_value,Height()))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- no alignment by left border (move)
|
||||
new_value=rect.right-Width()-m_align_right;
|
||||
if(!Move(new_value,Top()))
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
if((m_align_flags&WND_ALIGN_BOTTOM)!=0)
|
||||
{
|
||||
//--- there is alignment by bottom border,
|
||||
if((m_align_flags&WND_ALIGN_TOP)!=0)
|
||||
{
|
||||
//--- and by top border (change size)
|
||||
new_value=rect.Height()-m_align_top-m_align_bottom;
|
||||
if(!Size(Width(),new_value))
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- no alignment by top border (move)
|
||||
new_value=rect.bottom-Height()-m_align_bottom;
|
||||
if(!Move(Left(),new_value))
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Remove the mouse focus from control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::MouseFocusKill(const long id)
|
||||
{
|
||||
//--- check
|
||||
if(id==m_id)
|
||||
return(false);
|
||||
//--- reset flag
|
||||
Deactivate();
|
||||
//--- clean
|
||||
m_mouse_x =0;
|
||||
m_mouse_y =0;
|
||||
m_mouse_flags=MOUSE_INVALID_FLAGS;
|
||||
//--- call the handler
|
||||
return(OnDeactivate());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Increases the priority of an element |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::BringToTop(void)
|
||||
{
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_BRING_TO_TOP,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "click" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnClick(void)
|
||||
{
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CLICK,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "doubl click" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnDblClick(void)
|
||||
{
|
||||
//--- send notification
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_DBL_CLICK,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of click on the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnMouseDown(void)
|
||||
{
|
||||
if(IS_CAN_DRAG)
|
||||
return(OnDragStart());
|
||||
if(IS_CLICKS_BY_PRESS)
|
||||
return(OnClick());
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of releasing the left mouse button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnMouseUp(void)
|
||||
{
|
||||
if(IS_CAN_DBL_CLICK)
|
||||
{
|
||||
uint last_time=GetTickCount();
|
||||
if(m_last_click==0 || last_time-m_last_click>CONTROLS_DBL_CLICK_TIME)
|
||||
{
|
||||
m_last_click=(last_time==0) ? 1 : last_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_last_click=0;
|
||||
return(OnDblClick());
|
||||
}
|
||||
}
|
||||
if(IS_CAN_DRAG)
|
||||
return(OnDragEnd());
|
||||
if(!IS_CLICKS_BY_PRESS)
|
||||
return(OnClick());
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the control dragging start |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnDragStart(void)
|
||||
{
|
||||
if(!IS_CAN_DRAG)
|
||||
return(true);
|
||||
//--- disable scrolling of chart with mouse
|
||||
ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,false);
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_DRAG_START,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of control dragging process |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnDragProcess(const int x,const int y)
|
||||
{
|
||||
Shift(x-m_mouse_x,y-m_mouse_y);
|
||||
//--- save
|
||||
m_mouse_x=x;
|
||||
m_mouse_y=y;
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the control dragging end |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::OnDragEnd(void)
|
||||
{
|
||||
if(!IS_CAN_DRAG)
|
||||
return(true);
|
||||
//--- enable scrolling of chart with mouse
|
||||
ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,true);
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_DRAG_END,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destroy the dragged object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWnd::DragObjectDestroy(void)
|
||||
{
|
||||
if(m_drag_object!=NULL)
|
||||
{
|
||||
delete m_drag_object;
|
||||
m_drag_object=NULL;
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CDragWnd |
|
||||
//| Usage: base class for drag |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDragWnd : public CWnd
|
||||
{
|
||||
protected:
|
||||
int m_limit_left; // left constraint
|
||||
int m_limit_top; // top constraint
|
||||
int m_limit_right; // right constraint
|
||||
int m_limit_bottom; // bottom constraint
|
||||
|
||||
public:
|
||||
CDragWnd(void);
|
||||
~CDragWnd(void);
|
||||
//--- constraints
|
||||
void Limits(const int l,const int t,const int r,const int b);
|
||||
|
||||
protected:
|
||||
virtual bool OnDragProcess(const int x,const int y);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDragWnd::CDragWnd(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CDragWnd::~CDragWnd(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constrain the control dragging |
|
||||
//+------------------------------------------------------------------+
|
||||
void CDragWnd::Limits(const int l,const int t,const int r,const int b)
|
||||
{
|
||||
//--- save
|
||||
m_limit_left =l;
|
||||
m_limit_top =t;
|
||||
m_limit_right =r;
|
||||
m_limit_bottom=b;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of control dragging process |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CDragWnd::OnDragProcess(const int x,const int y)
|
||||
{
|
||||
int dx=x-m_mouse_x;
|
||||
int dy=y-m_mouse_y;
|
||||
//--- check shift
|
||||
if(Right()+dx>m_limit_right)
|
||||
dx=m_limit_right-Right();
|
||||
if(Left()+dx<m_limit_left)
|
||||
dx=m_limit_left-Left();
|
||||
if(Bottom()+dy>m_limit_bottom)
|
||||
dy=m_limit_bottom-Bottom();
|
||||
if(Top()+dy<m_limit_top)
|
||||
dy=m_limit_top-Top();
|
||||
//--- shift
|
||||
Shift(dx,dy);
|
||||
//--- save
|
||||
m_mouse_x=x;
|
||||
m_mouse_y=y;
|
||||
//--- generate event
|
||||
EventChartCustom(CONTROLS_SELF_MESSAGE,ON_DRAG_PROCESS,m_id,0.0,m_name);
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,308 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| WndClient.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "WndContainer.mqh"
|
||||
#include "Panel.mqh"
|
||||
#include "Scrolls.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CWndClient |
|
||||
//| Usage: base class to create areas with |
|
||||
//| the scrollbars |
|
||||
//+------------------------------------------------------------------+
|
||||
class CWndClient : public CWndContainer
|
||||
{
|
||||
protected:
|
||||
//--- flags
|
||||
bool m_v_scrolled; // "vertical scrolling is possible" flag
|
||||
bool m_h_scrolled; // "horizontal scrolling is possible" flag
|
||||
//--- dependent controls
|
||||
CPanel m_background; // the "scrollbar background" object
|
||||
CScrollV m_scroll_v; // the vertical scrollbar object
|
||||
CScrollH m_scroll_h; // the horizontal scrollbar object
|
||||
|
||||
public:
|
||||
CWndClient(void);
|
||||
~CWndClient(void);
|
||||
//--- create
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- parameters
|
||||
virtual bool ColorBackground(const color value) { return(m_background.ColorBackground(value)); }
|
||||
virtual bool ColorBorder(const color value) { return(m_background.ColorBorder(value)); }
|
||||
virtual bool BorderType(const ENUM_BORDER_TYPE flag) { return(m_background.BorderType(flag)); }
|
||||
//--- settings
|
||||
virtual bool VScrolled(void) { return(m_v_scrolled); }
|
||||
virtual bool VScrolled(const bool flag);
|
||||
virtual bool HScrolled(void) { return(m_h_scrolled); }
|
||||
virtual bool HScrolled(const bool flag);
|
||||
//--- ID
|
||||
virtual long Id(const long id);
|
||||
virtual long Id(void) const { return(CWnd::Id()); }
|
||||
//--- state
|
||||
virtual bool Show(void);
|
||||
|
||||
protected:
|
||||
//--- create dependent controls
|
||||
virtual bool CreateBack(void);
|
||||
virtual bool CreateScrollV(void);
|
||||
virtual bool CreateScrollH(void);
|
||||
//--- internal event handlers
|
||||
virtual bool OnResize(void);
|
||||
//--- handlers of the dependent controls events
|
||||
virtual bool OnVScrollShow(void) { return(true); }
|
||||
virtual bool OnVScrollHide(void) { return(true); }
|
||||
virtual bool OnHScrollShow(void) { return(true); }
|
||||
virtual bool OnHScrollHide(void) { return(true); }
|
||||
virtual bool OnScrollLineDown(void) { return(true); }
|
||||
virtual bool OnScrollLineUp(void) { return(true); }
|
||||
virtual bool OnScrollLineLeft(void) { return(true); }
|
||||
virtual bool OnScrollLineRight(void) { return(true); }
|
||||
//--- resize
|
||||
virtual bool Rebound(const CRect &rect);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CWndClient)
|
||||
ON_NAMED_EVENT(ON_SHOW,m_scroll_v,OnVScrollShow)
|
||||
ON_NAMED_EVENT(ON_HIDE,m_scroll_v,OnVScrollHide)
|
||||
ON_EVENT(ON_SCROLL_DEC,m_scroll_v,OnScrollLineUp)
|
||||
ON_EVENT(ON_SCROLL_INC,m_scroll_v,OnScrollLineDown)
|
||||
ON_NAMED_EVENT(ON_SHOW,m_scroll_h,OnHScrollShow)
|
||||
ON_NAMED_EVENT(ON_HIDE,m_scroll_h,OnHScrollHide)
|
||||
ON_EVENT(ON_SCROLL_DEC,m_scroll_h,OnScrollLineLeft)
|
||||
ON_EVENT(ON_SCROLL_INC,m_scroll_h,OnScrollLineRight)
|
||||
EVENT_MAP_END(CWndContainer)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndClient::CWndClient(void) : m_v_scrolled(false),
|
||||
m_h_scrolled(false)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndClient::~CWndClient(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- create dependent controls
|
||||
if(!CreateBack())
|
||||
return(false);
|
||||
if(m_v_scrolled && !CreateScrollV())
|
||||
return(false);
|
||||
if(m_h_scrolled && !CreateScrollH())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create scrollbar background |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::CreateBack(void)
|
||||
{
|
||||
//--- create
|
||||
if(!m_background.Create(m_chart_id,m_name+"Back",m_subwin,0,0,Width(),Height()))
|
||||
return(false);
|
||||
if(!m_background.ColorBorder(CONTROLS_CLIENT_COLOR_BORDER))
|
||||
return(false);
|
||||
if(!m_background.ColorBackground(CONTROLS_CLIENT_COLOR_BG))
|
||||
return(false);
|
||||
if(!Add(m_background))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create vertical scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::CreateScrollV(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=Width()-CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
int y1=CONTROLS_BORDER_WIDTH;
|
||||
int x2=Width()-CONTROLS_BORDER_WIDTH;
|
||||
int y2=Height()-CONTROLS_BORDER_WIDTH;
|
||||
if(m_h_scrolled) y2-=CONTROLS_SCROLL_SIZE;
|
||||
//--- create
|
||||
if(!m_scroll_v.Create(m_chart_id,m_name+"VScroll",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_scroll_v))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create horizontal scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::CreateScrollH(void)
|
||||
{
|
||||
//--- calculate coordinates
|
||||
int x1=CONTROLS_BORDER_WIDTH;
|
||||
int y1=Height()-CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
|
||||
int x2=Width()-CONTROLS_BORDER_WIDTH;
|
||||
int y2=Height()-CONTROLS_BORDER_WIDTH;
|
||||
if(m_v_scrolled) x2-=CONTROLS_SCROLL_SIZE;
|
||||
//--- create
|
||||
if(!m_scroll_h.Create(m_chart_id,m_name+"HScroll",m_subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
if(!Add(m_scroll_h))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up vertical scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::VScrolled(const bool flag)
|
||||
{
|
||||
if(m_v_scrolled==flag)
|
||||
return(true);
|
||||
//--- there are changes
|
||||
int d_size=0;
|
||||
if(flag)
|
||||
{
|
||||
//--- create vertical scrollbar
|
||||
if(!CreateScrollV())
|
||||
return(false);
|
||||
//--- need to shorten horizontal scrollbar (if there is one)
|
||||
d_size=-CONTROLS_SCROLL_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- delete vertical scrollbar
|
||||
m_scroll_v.Destroy();
|
||||
if(!Delete(m_scroll_v))
|
||||
return(false);
|
||||
//--- need to lengthen horizontal scrollbar (if there is one)
|
||||
d_size=CONTROLS_SCROLL_SIZE;
|
||||
}
|
||||
m_v_scrolled=flag;
|
||||
//--- change width of horizontal scrollbar (if there is one)
|
||||
if(m_h_scrolled)
|
||||
{
|
||||
if(!m_scroll_h.Width(m_scroll_h.Width()+d_size))
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up horizontal scrollbar |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::HScrolled(const bool flag)
|
||||
{
|
||||
if(m_h_scrolled==flag)
|
||||
return(true);
|
||||
//--- there are changes
|
||||
int d_size=0;
|
||||
if(flag)
|
||||
{
|
||||
//--- create horizontal scrollbar
|
||||
if(!CreateScrollH())
|
||||
return(false);
|
||||
//--- need to shorten vertical scrollbar (if there is one)
|
||||
d_size=-CONTROLS_SCROLL_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- delete horizontal scrollbar
|
||||
m_scroll_h.Destroy();
|
||||
if(!Delete(m_scroll_h))
|
||||
return(false);
|
||||
//--- need to lengthen vertical scrollbar (if there is one)
|
||||
d_size=CONTROLS_SCROLL_SIZE;
|
||||
}
|
||||
m_h_scrolled=flag;
|
||||
//--- change width of vertical scrollbar (if there is one)
|
||||
if(m_v_scrolled)
|
||||
{
|
||||
if(!m_scroll_v.Height(m_scroll_v.Height()+d_size))
|
||||
return(false);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set ID of control |
|
||||
//+------------------------------------------------------------------+
|
||||
long CWndClient::Id(const long id)
|
||||
{
|
||||
//--- reserve ID for container
|
||||
long id_used=CWndContainer::Id(id);
|
||||
//---
|
||||
if(!m_v_scrolled)
|
||||
id_used+=m_scroll_v.Id(id+id_used);
|
||||
if(!m_h_scrolled)
|
||||
id_used+=m_scroll_h.Id(id+id_used);
|
||||
//--- return number of used IDs
|
||||
return(id_used);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the control visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::Show(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
CWndContainer::Show();
|
||||
//---
|
||||
if(!m_v_scrolled)
|
||||
m_scroll_v.Hide();
|
||||
if(!m_h_scrolled)
|
||||
m_scroll_h.Hide();
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of resizing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::OnResize(void)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWndContainer::OnResize())
|
||||
return(false);
|
||||
//--- resize background
|
||||
int d_size=0;
|
||||
m_background.Width(Width());
|
||||
m_background.Height(Height());
|
||||
//---
|
||||
if(m_v_scrolled)
|
||||
{
|
||||
//--- move vertical scrollbar
|
||||
m_scroll_v.Move(Right()-CONTROLS_SCROLL_SIZE,Top());
|
||||
//--- modify vertical scrollbar
|
||||
d_size=(m_h_scrolled) ? CONTROLS_SCROLL_SIZE : 0;
|
||||
m_scroll_v.Height(Height()-d_size);
|
||||
}
|
||||
if(m_h_scrolled)
|
||||
{
|
||||
//--- move horizontal scrollbar
|
||||
m_scroll_h.Move(Left(),Bottom()-CONTROLS_SCROLL_SIZE);
|
||||
//--- modify horizontal scrollbar
|
||||
d_size=(m_v_scrolled) ? CONTROLS_SCROLL_SIZE : 0;
|
||||
m_scroll_h.Width(Width()-d_size);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Resize |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndClient::Rebound(const CRect &rect)
|
||||
{
|
||||
m_rect.SetBound(rect);
|
||||
//--- call virtual event handler
|
||||
return(OnResize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,473 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| WndContainer.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Wnd.mqh"
|
||||
#include <Arrays\ArrayObj.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CWndContainer |
|
||||
//| Usage: base class of the combined control |
|
||||
//+------------------------------------------------------------------+
|
||||
class CWndContainer : public CWnd
|
||||
{
|
||||
private:
|
||||
CArrayObj m_controls; // container of the control
|
||||
|
||||
public:
|
||||
CWndContainer(void);
|
||||
~CWndContainer(void);
|
||||
//--- release memory
|
||||
virtual void Destroy(const int reason=0);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
virtual bool OnMouseEvent(const int x,const int y,const int flags);
|
||||
//--- access the contents of container
|
||||
int ControlsTotal(void) const { return(m_controls.Total()); }
|
||||
CWnd* Control(const int ind) const { return(dynamic_cast<CWnd *>(m_controls.At(ind))); }
|
||||
virtual CWnd* ControlFind(const long id);
|
||||
//--- for mouse cursor focus
|
||||
virtual bool MouseFocusKill(const long id=-1);
|
||||
//--- fill
|
||||
bool Add(CWnd *control);
|
||||
bool Add(CWnd &control);
|
||||
//--- underflowing
|
||||
bool Delete(CWnd *control);
|
||||
bool Delete(CWnd &control);
|
||||
//--- geometry
|
||||
virtual bool Move(const int x,const int y);
|
||||
virtual bool Move(const CPoint &point);
|
||||
virtual bool Shift(const int dx,const int dy);
|
||||
//--- ID
|
||||
virtual long Id(const long id);
|
||||
long Id(void) const { return(CWnd::Id()); }
|
||||
//--- state
|
||||
virtual bool Enable(void);
|
||||
virtual bool Disable(void);
|
||||
virtual bool Show(void);
|
||||
virtual bool Hide(void);
|
||||
//--- methods for working with files
|
||||
virtual bool Save(const int file_handle);
|
||||
virtual bool Load(const int file_handle);
|
||||
|
||||
protected:
|
||||
//--- internal event handlers
|
||||
virtual bool OnResize(void);
|
||||
virtual bool OnActivate(void);
|
||||
virtual bool OnDeactivate(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
//--- if an object is being dragged, pass control to the special drag object
|
||||
if(m_drag_object!=NULL && m_drag_object.OnEvent(id,lparam,dparam,sparam))
|
||||
return(true);
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=total-1;i>=0;i--)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
if(control.OnEvent(id,lparam,dparam,sparam))
|
||||
return(true);
|
||||
}
|
||||
//--- not handled
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of mouse events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::OnMouseEvent(const int x,const int y,const int flags)
|
||||
{
|
||||
if(!IS_VISIBLE)
|
||||
return(false);
|
||||
//--- if an object is being dragged, pass control to the special drag object
|
||||
if(m_drag_object!=NULL && m_drag_object.OnMouseEvent(x,y,flags))
|
||||
return(true);
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=total-1;i>=0;i--)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
if(control.OnMouseEvent(x,y,flags))
|
||||
return(true);
|
||||
}
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::OnMouseEvent(x,y,flags));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndContainer::CWndContainer(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndContainer::~CWndContainer(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
void CWndContainer::Destroy(const int reason)
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(0);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Destroy();
|
||||
m_controls.Delete(0);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Find control by specified ID |
|
||||
//+------------------------------------------------------------------+
|
||||
CWnd* CWndContainer::ControlFind(const long id)
|
||||
{
|
||||
CWnd *result=CWnd::ControlFind(id);
|
||||
//---
|
||||
if(result!=NULL)
|
||||
return(result);
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
result=control.ControlFind(id);
|
||||
if(result!=NULL)
|
||||
break;
|
||||
}
|
||||
//--- return the result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Remove the mouse focus from control |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::MouseFocusKill(const long id=-1)
|
||||
{
|
||||
if(!IS_ACTIVE)
|
||||
return(false);
|
||||
Deactivate();
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.MouseFocusKill();
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add control to the group (by pointer) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Add(CWnd *control)
|
||||
{
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
return(false);
|
||||
//--- correct the coordinates of added control
|
||||
control.Shift(Left(),Top());
|
||||
//--- "projecting" the group flag "visibility" to the added element
|
||||
if(IS_VISIBLE && control.IsVisible())
|
||||
{
|
||||
//--- element will be "visible" only if the group is "visible" and the element is completely "within" this group
|
||||
control.Visible(Contains(control));
|
||||
}
|
||||
else
|
||||
control.Hide();
|
||||
//--- "projecting" the group flag "enabled" to the added element
|
||||
if(IS_ENABLED)
|
||||
control.Enable();
|
||||
else
|
||||
control.Disable();
|
||||
//--- adding
|
||||
return(m_controls.Add(control));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Add control to the group (by reference) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Add(CWnd &control)
|
||||
{
|
||||
//--- add by pointer
|
||||
return(Add((CWnd*)GetPointer(control)));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete control from the group (by pointer) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Delete(CWnd *control)
|
||||
{
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
return(false);
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *pointer=Control(i);
|
||||
//--- check of pointer
|
||||
if(pointer==NULL)
|
||||
continue;
|
||||
//--- delete item from group
|
||||
if(pointer==control)
|
||||
return(m_controls.Delete(i));
|
||||
}
|
||||
//--- failure
|
||||
return(false);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Delete control from the group (by reference) |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Delete(CWnd &control)
|
||||
{
|
||||
//--- delete by pointer
|
||||
return(Delete((CWnd*)GetPointer(control)));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the controls group |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Move(const int x,const int y)
|
||||
{
|
||||
//--- relative movement
|
||||
return(Shift(x-Left(),y-Top()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Absolute movement of the controls group |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Move(const CPoint &point)
|
||||
{
|
||||
//--- relative movement
|
||||
return(Shift(point.x-Left(),point.y-Top()));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Relative movement of the controls group |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Shift(const int dx,const int dy)
|
||||
{
|
||||
//--- call of the method of the parent class
|
||||
if(!CWnd::Shift(dx,dy)) return(false);
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
//--- move the group item
|
||||
control.Shift(dx,dy);
|
||||
}
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set ID of control |
|
||||
//+------------------------------------------------------------------+
|
||||
long CWndContainer::Id(const long id)
|
||||
{
|
||||
//--- reserve ID for container
|
||||
long id_used=1;
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
id_used+=control.Id(id+id_used);
|
||||
}
|
||||
m_id=id;
|
||||
//--- return number of used IDs
|
||||
return(id_used);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Enables event handling by the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Enable(void)
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Enable();
|
||||
}
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::Enable());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Disables event handling by the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Disable(void)
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Disable();
|
||||
}
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::Disable());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the group of controls visible |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Show(void)
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Show();
|
||||
}
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::Show());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Makes the group of controls hidden |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Hide(void)
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Hide();
|
||||
}
|
||||
//--- call of the method of the parent class
|
||||
return(CWnd::Hide());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of resizing |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::OnResize()
|
||||
{
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
if(!control.Align(Rect()))
|
||||
return(false);
|
||||
}
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of activating the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::OnActivate(void)
|
||||
{
|
||||
if(IS_ACTIVE)
|
||||
return(false);
|
||||
Activate();
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Activate();
|
||||
}
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of deactivating the group of controls |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::OnDeactivate(void)
|
||||
{
|
||||
if(!IS_ACTIVE)
|
||||
return(false);
|
||||
Deactivate();
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
control.Deactivate();
|
||||
}
|
||||
//--- handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Save |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Save(const int file_handle)
|
||||
{
|
||||
bool result=true;
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
result&=control.Save(file_handle);
|
||||
}
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Load |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndContainer::Load(const int file_handle)
|
||||
{
|
||||
bool result=true;
|
||||
//--- loop by elements of group
|
||||
int total=m_controls.Total();
|
||||
for(int i=0;i<total;i++)
|
||||
{
|
||||
CWnd *control=Control(i);
|
||||
//--- check of pointer
|
||||
if(control==NULL)
|
||||
continue;
|
||||
result&=control.Load(file_handle);
|
||||
}
|
||||
//--- result
|
||||
return(result);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,262 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| WndObj.mqh |
|
||||
//| Copyright 2009-2017, MetaQuotes Software Corp. |
|
||||
//| http://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Wnd.mqh"
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class CWndObj |
|
||||
//| Usage: base class to work with chart objects |
|
||||
//+------------------------------------------------------------------+
|
||||
class CWndObj : public CWnd
|
||||
{
|
||||
private:
|
||||
//--- flags of object
|
||||
bool m_undeletable; // "object is not deletable" flag
|
||||
bool m_unchangeable; // "object is not changeable" flag
|
||||
bool m_unmoveable; // "object is not movable" flag
|
||||
|
||||
protected:
|
||||
//--- parameters of the chart object
|
||||
string m_text; // object text
|
||||
color m_color; // object color
|
||||
color m_color_background; // object background color
|
||||
color m_color_border; // object border color
|
||||
string m_font; // object font
|
||||
int m_font_size; // object font size
|
||||
long m_zorder; // Z order
|
||||
|
||||
public:
|
||||
CWndObj(void);
|
||||
~CWndObj(void);
|
||||
//--- chart event handler
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
//--- set up the object
|
||||
string Text(void) const { return(m_text); }
|
||||
bool Text(const string value);
|
||||
color Color(void) const { return(m_color); }
|
||||
bool Color(const color value);
|
||||
color ColorBackground(void) const { return(m_color_background); }
|
||||
bool ColorBackground(const color value);
|
||||
color ColorBorder(void) const { return(m_color_border); }
|
||||
bool ColorBorder(const color value);
|
||||
string Font(void) const { return(m_font); }
|
||||
bool Font(const string value);
|
||||
int FontSize(void) const { return(m_font_size); }
|
||||
bool FontSize(const int value);
|
||||
long ZOrder(void) const { return(m_zorder); }
|
||||
bool ZOrder(const long value);
|
||||
|
||||
protected:
|
||||
//--- handlers of object events
|
||||
virtual bool OnObjectCreate(void);
|
||||
virtual bool OnObjectChange(void);
|
||||
virtual bool OnObjectDelete(void);
|
||||
virtual bool OnObjectDrag(void);
|
||||
//--- handlers of object settings
|
||||
virtual bool OnSetText(void) { return(true); }
|
||||
virtual bool OnSetColor(void) { return(true); }
|
||||
virtual bool OnSetColorBackground(void) { return(true); }
|
||||
virtual bool OnSetColorBorder(void) { return(true); }
|
||||
virtual bool OnSetFont(void) { return(true); }
|
||||
virtual bool OnSetFontSize(void) { return(true); }
|
||||
virtual bool OnSetZOrder(void) { return(true); }
|
||||
//--- internal event handlers
|
||||
virtual bool OnDestroy(void) { return(ObjectDelete(m_chart_id,m_name)); }
|
||||
virtual bool OnChange(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Common handler of chart events |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
||||
{
|
||||
if(m_name==sparam)
|
||||
{
|
||||
//--- object name and string parameters are equal
|
||||
//--- this means that event should be handled
|
||||
switch(id)
|
||||
{
|
||||
case CHARTEVENT_OBJECT_CREATE: return(OnObjectCreate());
|
||||
case CHARTEVENT_OBJECT_CHANGE: return(OnObjectChange());
|
||||
case CHARTEVENT_OBJECT_DELETE: return(OnObjectDelete());
|
||||
case CHARTEVENT_OBJECT_DRAG : return(OnObjectDrag());
|
||||
}
|
||||
}
|
||||
//--- event was not handled
|
||||
return(CWnd::OnEvent(id,lparam,dparam,sparam));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndObj::CWndObj(void) : m_color(clrNONE),
|
||||
m_color_background(clrNONE),
|
||||
m_color_border(clrNONE),
|
||||
m_font(CONTROLS_FONT_NAME),
|
||||
m_font_size(CONTROLS_FONT_SIZE),
|
||||
m_zorder(0),
|
||||
m_undeletable(true),
|
||||
m_unchangeable(true),
|
||||
m_unmoveable(true)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CWndObj::~CWndObj(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Text" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::Text(const string value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_text=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetText());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Color" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::Color(const color value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_color=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetColor());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Setting the "Background color" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::ColorBackground(const color value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_color_background=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetColorBackground());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Border color" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::ColorBorder(const color value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_color_border=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetColorBorder());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Font" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::Font(const string value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_font=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetFont());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Font size" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::FontSize(const int value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_font_size=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetFontSize());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set the "Z order" parameter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::ZOrder(const long value)
|
||||
{
|
||||
//--- save new value of parameter
|
||||
m_zorder=value;
|
||||
//--- call virtual event handler
|
||||
return(OnSetZOrder());
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Object creation" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnObjectCreate(void)
|
||||
{
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Object modification" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnObjectChange(void)
|
||||
{
|
||||
//--- if object is not changeable
|
||||
if(m_unchangeable)
|
||||
{
|
||||
//--- restore position
|
||||
if(!OnMove())
|
||||
return(false);
|
||||
//--- restore size
|
||||
if(!OnResize())
|
||||
return(false);
|
||||
//--- restore settings
|
||||
if(!OnChange())
|
||||
return(false);
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Object deletion" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnObjectDelete(void)
|
||||
{
|
||||
//--- if object is not deletable
|
||||
if(m_undeletable)
|
||||
{
|
||||
//--- restore the object
|
||||
if(!OnCreate())
|
||||
return(false);
|
||||
//--- restore settings
|
||||
if(!OnChange())
|
||||
return(false);
|
||||
//--- restore visibility
|
||||
return(IS_VISIBLE ? OnShow():OnHide());
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the "Object dragging" event |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnObjectDrag(void)
|
||||
{
|
||||
//--- if object is not movable
|
||||
if(m_unmoveable)
|
||||
{
|
||||
//--- restore position
|
||||
return(OnMove());
|
||||
}
|
||||
//--- event is handled
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Set up the object |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CWndObj::OnChange(void)
|
||||
{
|
||||
//--- set up the chart object according to previously set parameters
|
||||
if(!OnSetText())
|
||||
return(false);
|
||||
if(!OnSetFont())
|
||||
return(false);
|
||||
if(!OnSetFontSize())
|
||||
return(false);
|
||||
if(!OnSetColor())
|
||||
return(false);
|
||||
if(!OnSetColorBackground())
|
||||
return(false);
|
||||
if(!OnSetColorBorder())
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 568 B |
|
After Width: | Height: | Size: 568 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 824 B |