3568 lines
305 KiB
MQL5
3568 lines
305 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TextBox.mqh |
|
|
//| Copyright 2016, MetaQuotes Software Corp. |
|
|
//| http://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#include "Scrolls.mqh"
|
|
#include "..\Keys.mqh"
|
|
#include "..\Element.mqh"
|
|
#include "..\TimeCounter.mqh"
|
|
#include <Charts\Chart.mqh>
|
|
//+------------------------------------------------------------------+
|
|
//| Класс для создания многострочного текстового поля |
|
|
//+------------------------------------------------------------------+
|
|
class CTextBox : public CElement
|
|
{
|
|
private:
|
|
//--- Экземпляр класса для работы с клавиатурой
|
|
CKeys m_keys;
|
|
//--- Объект для работы со счётчиком таймера
|
|
CTimeCounter m_counter;
|
|
//--- Объекты для создания элемента
|
|
CRectCanvas m_textbox;
|
|
CScrollV m_scrollv;
|
|
CScrollH m_scrollh;
|
|
//--- Символы и их свойства
|
|
struct StringOptions
|
|
{
|
|
string m_symbol[]; // Символы
|
|
int m_width[]; // Ширина символов
|
|
bool m_end_of_line; // Признак окончания строки
|
|
};
|
|
StringOptions m_lines[];
|
|
//--- Общий размер и размер видимой части элемента
|
|
int m_area_x_size;
|
|
int m_area_y_size;
|
|
int m_area_visible_x_size;
|
|
int m_area_visible_y_size;
|
|
//--- Цвет фона и символов выделенного текста
|
|
color m_selected_back_color;
|
|
color m_selected_text_color;
|
|
//--- Начальные и конечные индексы строк и символов (выделенного текста)
|
|
int m_selected_line_from;
|
|
int m_selected_line_to;
|
|
int m_selected_symbol_from;
|
|
int m_selected_symbol_to;
|
|
//--- Цвет текста по умолчанию
|
|
color m_default_text_color;
|
|
//--- Текст по умолчанию
|
|
string m_default_text;
|
|
//--- Переменная для работы со строкой
|
|
string m_temp_input_string;
|
|
//--- Отступы для текста от краёв поля ввода
|
|
int m_text_x_offset;
|
|
int m_text_y_offset;
|
|
//--- Текущие координаты текстового курсора
|
|
int m_text_cursor_x;
|
|
int m_text_cursor_y;
|
|
//--- Текущая позиция текстового курсора
|
|
uint m_text_cursor_x_pos;
|
|
uint m_text_cursor_y_pos;
|
|
//--- Для расчёта границ видимой части поля ввода
|
|
int m_x_limit;
|
|
int m_y_limit;
|
|
int m_x2_limit;
|
|
int m_y2_limit;
|
|
//--- Размер шага для смещения по горизонтали
|
|
int m_shift_x_step;
|
|
//--- Ограничения на смещение
|
|
int m_shift_x2_limit;
|
|
int m_shift_y2_limit;
|
|
//--- Многострочный режим
|
|
bool m_multi_line_mode;
|
|
//--- Режим "Перенос по словам"
|
|
bool m_word_wrap_mode;
|
|
//--- Режим "Только для чтения"
|
|
bool m_read_only_mode;
|
|
//--- Режим авто выделения текста
|
|
bool m_auto_selection_mode;
|
|
//--- Состояние поля ввода
|
|
bool m_text_edit_state;
|
|
//--- Счётчик таймера для перемотки списка
|
|
int m_timer_counter;
|
|
//---
|
|
public:
|
|
CTextBox(void);
|
|
~CTextBox(void);
|
|
//--- Методы для создания элемента
|
|
bool CreateTextBox(const int x_gap,const int y_gap);
|
|
//---
|
|
private:
|
|
void InitializeProperties(const int x_gap,const int y_gap);
|
|
bool CreateCanvas(void);
|
|
bool CreateTextBox(void);
|
|
bool CreateScrollV(void);
|
|
bool CreateScrollH(void);
|
|
//---
|
|
public:
|
|
//--- Возвращает указатели на полосы прокрутки
|
|
CScrollV *GetScrollVPointer(void) { return(::GetPointer(m_scrollv)); }
|
|
CScrollH *GetScrollHPointer(void) { return(::GetPointer(m_scrollh)); }
|
|
//--- Цвет фона и символов выделенного текста
|
|
void SelectedBackColor(const color clr) { m_selected_back_color=clr; }
|
|
void SelectedTextColor(const color clr) { m_selected_text_color=clr; }
|
|
//--- (1) Текст по умолчанию и (2) цвет текста по умолчанию
|
|
void DefaultText(const string text) { m_default_text=text; }
|
|
void DefaultTextColor(const color clr) { m_default_text_color=clr; }
|
|
//--- (1) Многострочный режим, (2) режим "Перенос по словам"
|
|
void MultiLineMode(const bool mode) { m_multi_line_mode=mode; }
|
|
bool MultiLineMode(void) const { return(m_multi_line_mode); }
|
|
void WordWrapMode(const bool mode) { m_word_wrap_mode=mode; }
|
|
//--- (1) Режим "Только для чтения", (2) состояние поля ввода, (3) режим для автоматического выделения текста
|
|
bool ReadOnlyMode(void) const { return(m_read_only_mode); }
|
|
void ReadOnlyMode(const bool mode) { m_read_only_mode=mode; }
|
|
bool TextEditState(void) const { return(m_text_edit_state); }
|
|
void AutoSelectionMode(const bool state) { m_auto_selection_mode=state; }
|
|
//--- (1) Отступы для текста от краёв поля ввода, (2) режим выравнивания текста
|
|
void TextXOffset(const int x_offset) { m_text_x_offset=x_offset; }
|
|
void TextYOffset(const int y_offset) { m_text_y_offset=y_offset; }
|
|
//--- Возвращает индекс (1) строки, (2) символа, на котором находится текстовый курсор,
|
|
// (3) количество строк, (4) количество видимых строк
|
|
uint TextCursorLine(void) { return(m_text_cursor_y_pos); }
|
|
uint TextCursorColumn(void) { return(m_text_cursor_x_pos); }
|
|
uint LinesTotal(void) { return(::ArraySize(m_lines)); }
|
|
uint VisibleLinesTotal(void);
|
|
//--- Количество символов в указанной строке
|
|
uint ColumnsTotal(const uint line_index);
|
|
//--- Информация текстового курсора (строка/количество строк, столбец/количество столбцов)
|
|
string TextCursorInfo(void);
|
|
//--- Добавляет строку
|
|
void AddLine(const string added_text="");
|
|
//--- Добавляет текст в указанную строку
|
|
void AddText(const uint line_index,const string added_text);
|
|
//--- Возвращает текст из указанной строки
|
|
string GetValue(const uint line_index=0);
|
|
//--- Очищает текстовое поле ввода
|
|
void ClearTextBox(void);
|
|
//--- Прокрутка таблицы: (1) вертикальная и (2) горизонтальная
|
|
void VerticalScrolling(const int pos=WRONG_VALUE);
|
|
void HorizontalScrolling(const int pos=WRONG_VALUE);
|
|
//--- Смещение данных относительно позиций полос прокрутки
|
|
void ShiftData(void);
|
|
//--- Корректировка размеров поля ввода
|
|
void CorrectSize(void);
|
|
//--- Активация поля ввода
|
|
void ActivateTextBox(void);
|
|
//--- Дезактивирует поле ввода
|
|
void DeactivateTextBox(void);
|
|
//--- Изменение размеров
|
|
void ChangeSize(const uint x_size,const uint y_size);
|
|
//---
|
|
public:
|
|
//--- Обработчик событий графика
|
|
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
|
//--- Таймер
|
|
virtual void OnEventTimer(void);
|
|
//--- Перемещение элемента
|
|
virtual void Moving(const bool only_visible=true);
|
|
//--- Управление
|
|
virtual void Show(void);
|
|
virtual void Hide(void);
|
|
virtual void Delete(void);
|
|
//--- (1) Установка, (2) сброс приоритетов на нажатие левой кнопки мыши
|
|
virtual void SetZorders(void);
|
|
virtual void ResetZorders(void);
|
|
//--- Рисует элемент
|
|
virtual void Draw(void);
|
|
//--- Обновление элемента
|
|
virtual void Update(const bool redraw=false);
|
|
//---
|
|
private:
|
|
//--- Обработка нажатия на элемент
|
|
bool OnClickTextBox(const string clicked_object);
|
|
|
|
//--- Обработка нажатия на клавише
|
|
bool OnPressedKey(const long key_code);
|
|
//--- Обработка нажатия на клавише "Backspace"
|
|
bool OnPressedKeyBackspace(const long key_code);
|
|
//--- Обработка нажатия на клавише "Enter"
|
|
bool OnPressedKeyEnter(const long key_code);
|
|
//--- Обработка нажатия на клавише "Left"
|
|
bool OnPressedKeyLeft(const long key_code);
|
|
//--- Обработка нажатия на клавише "Right"
|
|
bool OnPressedKeyRight(const long key_code);
|
|
//--- Обработка нажатия на клавише "Up"
|
|
bool OnPressedKeyUp(const long key_code);
|
|
//--- Обработка нажатия на клавише "Down"
|
|
bool OnPressedKeyDown(const long key_code);
|
|
//--- Обработка нажатия на клавише "Home"
|
|
bool OnPressedKeyHome(const long key_code);
|
|
//--- Обработка нажатия на клавише "End"
|
|
bool OnPressedKeyEnd(const long key_code);
|
|
|
|
//--- Обработка нажатия на клавише Ctrl + Left
|
|
bool OnPressedKeyCtrlAndLeft(const long key_code);
|
|
//--- Обработка нажатия на клавише Ctrl + Right
|
|
bool OnPressedKeyCtrlAndRight(const long key_code);
|
|
//--- Обработка одновременного нажатия клавиш Ctrl + Home
|
|
bool OnPressedKeyCtrlAndHome(const long key_code);
|
|
//--- Обработка одновременного нажатия клавиш Ctrl + End
|
|
bool OnPressedKeyCtrlAndEnd(const long key_code);
|
|
|
|
//--- Обработка нажатия на клавише Shift + Left
|
|
bool OnPressedKeyShiftAndLeft(const long key_code);
|
|
//--- Обработка нажатия на клавише Shift + Right
|
|
bool OnPressedKeyShiftAndRight(const long key_code);
|
|
//--- Обработка нажатия на клавише Shift + Up
|
|
bool OnPressedKeyShiftAndUp(const long key_code);
|
|
//--- Обработка нажатия на клавише Shift + Down
|
|
bool OnPressedKeyShiftAndDown(const long key_code);
|
|
//--- Обработка нажатия на клавише Shift + Home
|
|
bool OnPressedKeyShiftAndHome(const long key_code);
|
|
//--- Обработка нажатия на клавише Shift + End
|
|
bool OnPressedKeyShiftAndEnd(const long key_code);
|
|
|
|
//--- Обработка нажатия на клавише Ctrl + Shift + Left
|
|
bool OnPressedKeyCtrlShiftAndLeft(const long key_code);
|
|
//--- Обработка нажатия на клавише Ctrl + Shift + Right
|
|
bool OnPressedKeyCtrlShiftAndRight(const long key_code);
|
|
//--- Обработка нажатия на клавише Ctrl + Shift + Home
|
|
bool OnPressedKeyCtrlShiftAndHome(const long key_code);
|
|
//--- Обработка нажатия на клавише Ctrl + Shift + End
|
|
bool OnPressedKeyCtrlShiftAndEnd(const long key_code);
|
|
//---
|
|
private:
|
|
//--- Устанавливает (1) начальные и (2) конечные индексы для выделения текста
|
|
void SetStartSelectedTextIndexes(void);
|
|
void SetEndSelectedTextIndexes(void);
|
|
//--- Выделить весь текст
|
|
void SelectAllText(void);
|
|
//--- Сбросить выделенный текст
|
|
void ResetSelectedText(void);
|
|
//--- Ускоренная перемотка поля ввода
|
|
void FastSwitching(void);
|
|
|
|
//--- Вывод текста на холст
|
|
void TextOut(void);
|
|
//--- Рисует рамку
|
|
virtual void DrawBorder(void);
|
|
//--- Рисует текстовый курсор
|
|
void DrawCursor(void);
|
|
//--- Отображает текст и мигающий курсор
|
|
void DrawTextAndCursor(const bool show_state=false);
|
|
|
|
//--- Возвращает текущий цвет фона
|
|
uint AreaColorCurrent(void);
|
|
//--- Возвращает текущий цвет текста
|
|
uint TextColorCurrent(void);
|
|
//--- Возвращает текущий цвет рамки
|
|
uint BorderColorCurrent(void);
|
|
//--- Изменение цвета объектов
|
|
void ChangeObjectsColor(void);
|
|
|
|
//--- Собирает строку из символов
|
|
string CollectString(const uint line_index,const uint symbols_total=0);
|
|
//--- Добавляет символ и его свойства в массивы структуры
|
|
void AddSymbol(const string key_symbol);
|
|
//--- Удаляет символ
|
|
void DeleteSymbol(void);
|
|
//--- Удаляет (1) выделенный текст, (2) на одной строке, (3) на нескольких строках
|
|
bool DeleteSelectedText(void);
|
|
void DeleteTextOnOneLine(void);
|
|
void DeleteTextOnMultipleLines(void);
|
|
|
|
//
|
|
void InsertToString(const uint line_index, const uint start_pos, const string text);
|
|
|
|
//--- Возвращает высоту строки
|
|
uint LineHeight(void);
|
|
//--- Возвращает ширину строки от указанного символа в пикселях
|
|
uint LineWidth(const uint symbol_index,const uint line_index);
|
|
//--- Возвращает максимальную ширину строки
|
|
uint MaxLineWidth(void);
|
|
|
|
//--- Смещает строки на одну позицию вверх
|
|
void ShiftOnePositionUp(void);
|
|
//--- Смещает строки на одну позицию вниз
|
|
void ShiftOnePositionDown(void);
|
|
|
|
//--- Проверка наличия выделенного текста
|
|
bool CheckSelectedText(const uint line_index,const uint symbol_index);
|
|
//--- Проверка на наличие обязательной первой строки
|
|
uint CheckFirstLine(void);
|
|
|
|
//--- Устанавливает новый размер массивам свойств указанной строки
|
|
void ArraysResize(const uint line_index,const uint new_size);
|
|
//--- Делает копию указанной (source) строки в новое место (destination)
|
|
void LineCopy(const uint destination,const uint source);
|
|
//--- Очищает указанную строку
|
|
void ClearLine(const uint line_index);
|
|
|
|
//--- Перемещение текстового курсора в указанном направлении
|
|
void MoveTextCursor(const ENUM_MOVE_TEXT_CURSOR direction);
|
|
void MoveTextCursor(const ENUM_MOVE_TEXT_CURSOR direction,const bool with_highlighted_text);
|
|
//--- Перемещение текстового курсора влево
|
|
void MoveTextCursorToLeft(const bool to_next_word=false);
|
|
//--- Перемещение текстового курсора вправо
|
|
void MoveTextCursorToRight(const bool to_next_word=false);
|
|
//--- Перемещение текстового курсора на одну строку вверх
|
|
void MoveTextCursorToUp(void);
|
|
//--- Перемещение текстового курсора на одну строку вниз
|
|
void MoveTextCursorToDown(void);
|
|
|
|
//--- Устанавливает курсор по указанным позициям
|
|
void SetTextCursor(const uint x_pos,const uint y_pos);
|
|
//--- Устанавливает курсор по указанным позициям по курсору мыши
|
|
void SetTextCursorByMouseCursor(void);
|
|
//--- Корректировка текстового курсора по оси X
|
|
void CorrectingTextCursorXPos(const int x_pos=WRONG_VALUE);
|
|
|
|
//--- Расчёт координат для текстового курсора
|
|
void CalculateTextCursorX(void);
|
|
void CalculateTextCursorY(void);
|
|
|
|
//--- Расчёт границ поля ввода
|
|
void CalculateBoundaries(void);
|
|
void CalculateXBoundaries(void);
|
|
void CalculateYBoundaries(void);
|
|
//--- Расчёт X-позиции ползунка полосы прокрутки в левой границе поля ввода
|
|
int CalculateScrollThumbX(void);
|
|
//--- Расчёт X-позиции ползунка полосы прокрутки в правой границе поля ввода
|
|
int CalculateScrollThumbX2(void);
|
|
//--- Расчёт X-позиции ползунка полосы прокрутки
|
|
int CalculateScrollPosX(const bool to_right=false);
|
|
//--- Расчёт Y-позиции ползунка полосы прокрутки в верхней границе поля ввода
|
|
int CalculateScrollThumbY(void);
|
|
//--- Расчёт Y-позиции ползунка полосы прокрутки в нижней границе поля ввода
|
|
int CalculateScrollThumbY2(void);
|
|
//--- Расчёт Y-позиции ползунка полосы прокрутки
|
|
int CalculateScrollPosY(const bool to_down=false);
|
|
//--- Корректировка горизонтальной полосы прокрутки
|
|
void CorrectingHorizontalScrollThumb(void);
|
|
//--- Корректировка вертикальной полосы прокрутки
|
|
void CorrectingVerticalScrollThumb(void);
|
|
|
|
//--- Рассчитывает размеры текстого поля ввода
|
|
void CalculateTextBoxSize(void);
|
|
bool CalculateTextBoxXSize(void);
|
|
bool CalculateTextBoxYSize(void);
|
|
//--- Изменить основные размеры элемента
|
|
void ChangeMainSize(const int x_size,const int y_size);
|
|
//--- Изменить размеры поля ввода
|
|
void ChangeTextBoxSize(const bool x_offset=false,const bool y_offset=false);
|
|
//--- Изменить размеры полос прокрутки
|
|
void ChangeScrollsSize(void);
|
|
|
|
//--- Перенос по словам
|
|
void WordWrap(void);
|
|
//--- Возвращает индексы первых видимых символа и пробела
|
|
bool CheckForOverflow(const uint line_index,int &symbol_index,int &space_index);
|
|
//--- Количество слов в указанной строке
|
|
uint WordsTotal(const uint line_index);
|
|
//--- Возвращает количество переносимых символов
|
|
bool WrapSymbolsTotal(const uint line_index,uint &wrap_symbols_total);
|
|
//--- Возвращает индекс символа пробела по его номеру
|
|
uint SymbolIndexBySpaceNumber(const uint line_index,const uint space_index);
|
|
//--- Перемещает строки
|
|
void MoveLines(const uint from_index,const uint to_index,const uint count,const bool to_down=true);
|
|
//--- Перемещение символов в указанной строке
|
|
void MoveSymbols(const uint line_index,const uint from_pos,const uint to_pos,const bool to_left=true);
|
|
//--- Добавление текста в указанную строку
|
|
void AddToString(const uint line_index,const string text);
|
|
//--- Копирует в переданный массив символы для переноса на другую строку
|
|
void CopyWrapSymbols(const uint line_index,const uint start_pos,const uint symbols_total,string &array[]);
|
|
//--- Вставляет символы из переданного массива в указанную строку
|
|
void PasteWrapSymbols(const uint line_index,const uint start_pos,string &array[]);
|
|
//--- Перенос текста на следующую строку
|
|
void WrapTextToNewLine(const uint curr_line_index,const uint symbol_index,const bool by_pressed_enter=false);
|
|
//--- Перенос текста из указанной строки в предыдущую
|
|
void WrapTextToPrevLine(const uint next_line_index,const uint wrap_symbols_total,const bool is_all_text=false);
|
|
|
|
//--- Изменить ширину по правому краю окна
|
|
virtual void ChangeWidthByRightWindowSide(void);
|
|
//--- Изменить высоту по нижнему краю окна
|
|
virtual void ChangeHeightByBottomWindowSide(void);
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CTextBox::CTextBox(void) : m_selected_text_color(clrWhite),
|
|
m_selected_back_color(C'51,153,255'),
|
|
m_selected_line_from(WRONG_VALUE),
|
|
m_selected_line_to(WRONG_VALUE),
|
|
m_selected_symbol_from(WRONG_VALUE),
|
|
m_selected_symbol_to(WRONG_VALUE),
|
|
m_default_text_color(clrTomato),
|
|
m_default_text(""),
|
|
m_temp_input_string(""),
|
|
m_text_x_offset(5),
|
|
m_text_y_offset(4),
|
|
m_multi_line_mode(false),
|
|
m_word_wrap_mode(false),
|
|
m_read_only_mode(false),
|
|
m_auto_selection_mode(false),
|
|
m_text_edit_state(false),
|
|
m_text_cursor_x_pos(0),
|
|
m_text_cursor_y_pos(0),
|
|
m_shift_x_step(10),
|
|
m_shift_x2_limit(0),
|
|
m_shift_y2_limit(0)
|
|
{
|
|
//--- Сохраним имя класса элемента в базовом классе
|
|
CElementBase::ClassName(CLASS_NAME);
|
|
//--- Исходные координаты текстового курсора
|
|
m_text_cursor_x=m_text_x_offset;
|
|
m_text_cursor_y=m_text_y_offset;
|
|
//--- Установка параметров для счётчика таймера
|
|
m_counter.SetParameters(16,200);
|
|
//--- Обязательная первая строка многострочного поля ввода
|
|
::ArrayResize(m_lines,1);
|
|
//--- Установим признак окончания строки
|
|
m_lines[0].m_end_of_line=true;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CTextBox::~CTextBox(void)
|
|
{
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработчик событий графика |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
|
|
{
|
|
//--- Обработка события перемещения курсора
|
|
if(id==CHARTEVENT_MOUSE_MOVE)
|
|
{
|
|
//--- Проверка статуса полос прокрутки
|
|
bool is_scroll_state=m_scrollv.ScrollBarControl() || ((m_multi_line_mode)? m_scrollh.ScrollBarControl() : false);
|
|
//---
|
|
if(m_text_edit_state)
|
|
{
|
|
//--- Если (1) не в фокусе и (2) левая кнопка мыши нажата и (3) не в режиме перемещения полос прокрутки
|
|
if(!CElementBase::MouseFocus() && m_mouse.LeftButtonState() && !is_scroll_state)
|
|
{
|
|
//--- Отправим сообщение об окончании ввода строки в поле ввода, если поле было активно
|
|
string str=(m_multi_line_mode)? TextCursorInfo() : "";
|
|
::EventChartCustom(m_chart_id,ON_END_EDIT,CElementBase::Id(),CElementBase::Index(),str);
|
|
//--- Дезактивируем поле ввода
|
|
DeactivateTextBox();
|
|
//--- Обновить
|
|
Update(true);
|
|
}
|
|
}
|
|
//--- Изменение цвета объектов
|
|
ChangeObjectsColor();
|
|
//--- Выйти, если многострочный режим отключен
|
|
if(!m_multi_line_mode)
|
|
return;
|
|
//--- Если полоса прокрутки в действии
|
|
if(is_scroll_state)
|
|
{
|
|
//--- Сдвинуть данные относительно полос прокрутки
|
|
ShiftData();
|
|
//--- Дезактивируем поле ввода
|
|
DeactivateTextBox();
|
|
//--- Обновить
|
|
Update(true);
|
|
//--- Обновить полосу прокрутки в действии
|
|
if(m_scrollh.State()) m_scrollh.Update(true);
|
|
if(m_scrollv.State()) m_scrollv.Update(true);
|
|
}
|
|
//--- Если одна из кнопок полос прокрутки нажата
|
|
if(m_mouse.LeftButtonState() &&
|
|
(m_scrollv.ScrollIncState() || m_scrollv.ScrollDecState() ||
|
|
m_scrollh.ScrollIncState() || m_scrollh.ScrollDecState()))
|
|
{
|
|
//--- Дезактивируем поле ввода
|
|
DeactivateTextBox();
|
|
//--- Обновить
|
|
Update(true);
|
|
}
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка события нажатия левой кнопки мыши на объекте
|
|
if(id==CHARTEVENT_OBJECT_CLICK)
|
|
{
|
|
//--- Нажатие на поле ввода
|
|
if(OnClickTextBox(sparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
//--- Обработка события нажатия на кнопках полосы прокрутки
|
|
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
|
|
{
|
|
//--- Если было нажатие на кнопках полосы прокрутки списка
|
|
if(m_scrollv.OnClickScrollInc((uint)lparam,(uint)dparam) ||
|
|
m_scrollv.OnClickScrollDec((uint)lparam,(uint)dparam))
|
|
{
|
|
//--- Сдвигает данные
|
|
ShiftData();
|
|
m_scrollv.Update(true);
|
|
return;
|
|
}
|
|
//--- Если было нажатие на кнопках полосы прокрутки списка
|
|
if(m_scrollh.OnClickScrollInc((uint)lparam,(uint)dparam) ||
|
|
m_scrollh.OnClickScrollDec((uint)lparam,(uint)dparam))
|
|
{
|
|
//--- Сдвигает данные
|
|
ShiftData();
|
|
m_scrollh.Update(true);
|
|
return;
|
|
}
|
|
}
|
|
//--- Обработка нажатия кнопки на клавиатуре
|
|
if(id==CHARTEVENT_KEYDOWN)
|
|
{
|
|
//--- Выйти, если поле ввода не активировано
|
|
if(!m_text_edit_state)
|
|
return;
|
|
//--- Нажатие на символьной клавише
|
|
if(OnPressedKey(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Backspace"
|
|
if(OnPressedKeyBackspace(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Enter"
|
|
if(OnPressedKeyEnter(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Left"
|
|
if(OnPressedKeyLeft(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Right"
|
|
if(OnPressedKeyRight(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Up"
|
|
if(OnPressedKeyUp(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Down"
|
|
if(OnPressedKeyDown(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "Home"
|
|
if(OnPressedKeyHome(lparam))
|
|
return;
|
|
//--- Нажатие на клавише "End"
|
|
if(OnPressedKeyEnd(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Left
|
|
if(OnPressedKeyCtrlAndLeft(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Right
|
|
if(OnPressedKeyCtrlAndRight(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Home
|
|
if(OnPressedKeyCtrlAndHome(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + End
|
|
if(OnPressedKeyCtrlAndEnd(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + Left
|
|
if(OnPressedKeyShiftAndLeft(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + Right
|
|
if(OnPressedKeyShiftAndRight(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + Up
|
|
if(OnPressedKeyShiftAndUp(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + Down
|
|
if(OnPressedKeyShiftAndDown(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + Home
|
|
if(OnPressedKeyShiftAndHome(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Shift + End
|
|
if(OnPressedKeyShiftAndEnd(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Shift + Left
|
|
if(OnPressedKeyCtrlShiftAndLeft(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Shift + Right
|
|
if(OnPressedKeyCtrlShiftAndRight(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Shift + Home
|
|
if(OnPressedKeyCtrlShiftAndHome(lparam))
|
|
return;
|
|
//--- Одновременное нажатие клавиш Ctrl + Shift + End
|
|
if(OnPressedKeyCtrlShiftAndEnd(lparam))
|
|
return;
|
|
//---
|
|
return;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Таймер |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::OnEventTimer(void)
|
|
{
|
|
//--- Ускоренная перемотка значений
|
|
FastSwitching();
|
|
//--- Пауза между обновлением текстового курсора
|
|
if(m_counter.CheckTimeCounter())
|
|
{
|
|
//--- Обновим текстовый курсор, если элемент видим и поле ввода активировано
|
|
if(CElementBase::IsVisible() && m_text_edit_state)
|
|
DrawTextAndCursor();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт элемент "Текстовое поле ввода" |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CreateTextBox(const int x_gap,const int y_gap)
|
|
{
|
|
//--- Выйти, если нет указателя на главный элемент
|
|
if(!CElement::CheckMainPointer())
|
|
return(false);
|
|
//--- Инициализация свойств
|
|
InitializeProperties(x_gap,y_gap);
|
|
//--- Рассчитаем размеры текстового поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Создание элемента
|
|
if(!CreateCanvas())
|
|
return(false);
|
|
if(!CreateTextBox())
|
|
return(false);
|
|
if(!CreateScrollV())
|
|
return(false);
|
|
if(!CreateScrollH())
|
|
return(false);
|
|
//--- Изменить размеры текстового поля ввода
|
|
ChangeTextBoxSize();
|
|
//--- В режиме переноса слов нужно повторно пересчитать и установить размеры
|
|
if(m_word_wrap_mode)
|
|
{
|
|
CalculateTextBoxSize();
|
|
ChangeTextBoxSize();
|
|
}
|
|
//---
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Инициализация свойств |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::InitializeProperties(const int x_gap,const int y_gap)
|
|
{
|
|
m_x =CElement::CalculateX(x_gap);
|
|
m_y =CElement::CalculateY(y_gap);
|
|
m_x_size =(m_x_size<0 || m_auto_xresize_mode)? m_main.X2()-CElementBase::X()-m_auto_xresize_right_offset : m_x_size;
|
|
m_y_size =(m_y_size<0 || m_auto_yresize_mode)? m_main.Y2()-CElementBase::Y()-m_auto_yresize_bottom_offset : m_y_size;
|
|
//--- Цвета по умолчанию
|
|
m_back_color =(m_back_color!=clrNONE)? m_back_color : clrWhite;
|
|
m_back_color_locked =(m_back_color_locked!=clrNONE)? m_back_color_locked : clrWhiteSmoke;
|
|
m_border_color =(m_border_color!=clrNONE)? m_border_color : clrGray;
|
|
m_border_color_hover =(m_border_color_hover!=clrNONE)? m_border_color_hover : clrBlack;
|
|
m_border_color_locked =(m_border_color_locked!=clrNONE)? m_border_color_locked : clrSilver;
|
|
m_border_color_pressed =(m_border_color_pressed!=clrNONE)? m_border_color_pressed : clrCornflowerBlue;
|
|
m_label_color =(m_label_color!=clrNONE)? m_label_color : clrBlack;
|
|
m_label_color_locked =(m_label_color_locked!=clrNONE)? m_label_color_locked : clrSilver;
|
|
//--- Отступы от крайней точки
|
|
CElementBase::XGap(x_gap);
|
|
CElementBase::YGap(y_gap);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт холст для рисования фона |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CreateCanvas(void)
|
|
{
|
|
//--- Формирование имени объекта
|
|
string name=CElementBase::ElementName("textbox");
|
|
//--- Создание объекта
|
|
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
|
|
return(false);
|
|
//--- Проверка на наличие обязательной первой строки
|
|
CheckFirstLine();
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт холст для рисования поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CreateTextBox(void)
|
|
{
|
|
//--- Формирование имени объекта
|
|
string name="";
|
|
if(m_index==WRONG_VALUE)
|
|
name=m_program_name+"_"+"textbox_edit"+"_"+(string)m_id;
|
|
else
|
|
name=m_program_name+"_"+"textbox_edit"+"_"+(string)m_index+"__"+(string)m_id;
|
|
//--- Координаты
|
|
int x =m_x+1;
|
|
int y =m_y+1;
|
|
//--- Размер
|
|
int x_size =m_area_x_size-2;
|
|
int y_size =m_area_y_size-2;
|
|
//--- Создание объекта
|
|
::ResetLastError();
|
|
if(!m_textbox.CreateBitmapLabel(m_chart_id,m_subwin,name,x,y,x_size,y_size,COLOR_FORMAT_ARGB_NORMALIZE))
|
|
{
|
|
::Print(__FUNCTION__," > Не удалось создать холст для рисования поля ввода: ",::GetLastError());
|
|
return(false);
|
|
}
|
|
//--- Получим указатель на базовый класс
|
|
if(!m_textbox.Attach(m_chart_id,name,COLOR_FORMAT_ARGB_NORMALIZE))
|
|
{
|
|
::Print(__FUNCTION__," > Не удалось присоединить холст для рисования к графику: ",::GetLastError());
|
|
return(false);
|
|
}
|
|
//--- Свойства
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_ZORDER,m_zorder+1);
|
|
::ObjectSetString(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_TOOLTIP,"\n");
|
|
//--- Координаты
|
|
m_textbox.X(x);
|
|
m_textbox.Y(y);
|
|
//--- Отступы от крайней точки панели
|
|
m_textbox.XGap(CElement::CalculateXGap(x));
|
|
m_textbox.YGap(CElement::CalculateYGap(y));
|
|
//--- Установим размеры видимой области
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XSIZE,m_area_visible_x_size);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YSIZE,m_area_visible_y_size);
|
|
//--- Зададим смещение фрейма внутри изображения по осям X и Y
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET,0);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YOFFSET,0);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт вертикальный скролл |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CreateScrollV(void)
|
|
{
|
|
//--- Сохранить указатель родительского элемента
|
|
m_scrollv.MainPointer(this);
|
|
//--- Если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
{
|
|
//--- Инициализация вертикальной полосы прокрутки
|
|
m_scrollv.Reinit(m_area_y_size,m_area_visible_y_size);
|
|
//--- Сохранить указатель родительского элемента
|
|
m_scrollv.GetIncButtonPointer().MainPointer(m_scrollv);
|
|
m_scrollv.GetDecButtonPointer().MainPointer(m_scrollv);
|
|
return(true);
|
|
}
|
|
//--- Координаты
|
|
int x =m_scrollv.ScrollWidth()+1;
|
|
int y =1;
|
|
//--- Установим свойства
|
|
m_scrollv.Index(0);
|
|
m_scrollv.IsDropdown(CElementBase::IsDropdown());
|
|
m_scrollv.XSize(m_scrollv.ScrollWidth());
|
|
m_scrollv.YSize(m_y_size-m_scrollv.ScrollWidth()-1);
|
|
m_scrollv.AnchorRightWindowSide(true);
|
|
//--- Расчёт количества шагов для смещения
|
|
uint lines_total =LinesTotal()+1;
|
|
uint visible_lines_total =VisibleLinesTotal();
|
|
//--- Создание полосы прокрутки
|
|
if(!m_scrollv.CreateScroll(x,y,lines_total,visible_lines_total))
|
|
return(false);
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_scrollv);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Создаёт горизонтальный скролл |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CreateScrollH(void)
|
|
{
|
|
//--- Сохранить указатель родительского элемента
|
|
m_scrollh.MainPointer(this);
|
|
//--- Если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
{
|
|
//--- Инициализация горизонтальной полосы прокрутки
|
|
m_scrollh.Reinit(m_area_x_size,m_area_visible_x_size);
|
|
//--- Сохранить указатель главного элемента
|
|
m_scrollh.GetIncButtonPointer().MainPointer(m_scrollh);
|
|
m_scrollh.GetDecButtonPointer().MainPointer(m_scrollh);
|
|
return(true);
|
|
}
|
|
//--- Координаты
|
|
int x =1;
|
|
int y =m_scrollh.ScrollWidth()+1;
|
|
//--- Установим свойства
|
|
m_scrollh.Index(1);
|
|
m_scrollh.IsDropdown(CElementBase::IsDropdown());
|
|
m_scrollh.XSize(CElementBase::XSize()-m_scrollv.ScrollWidth()-1);
|
|
m_scrollh.YSize(m_scrollv.ScrollWidth());
|
|
m_scrollh.AnchorBottomWindowSide(true);
|
|
//--- Расчёт количества шагов для смещения
|
|
uint x_size_total =m_area_x_size/m_shift_x_step;
|
|
uint visible_x_size_total =m_area_visible_x_size/m_shift_x_step;
|
|
//--- Создание полосы прокрутки
|
|
if(!m_scrollh.CreateScroll(x,y,x_size_total,visible_x_size_total))
|
|
return(false);
|
|
//--- Добавить элемент в массив
|
|
CElement::AddToArray(m_scrollh);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает количество видимых строк |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::VisibleLinesTotal(void)
|
|
{
|
|
return((m_area_visible_y_size-(m_text_y_offset*2))/LineHeight());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает количество символов в указанной строке |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::ColumnsTotal(const uint line_index)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint check_index=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Получим размер массива символов в строке
|
|
uint symbols_total=::ArraySize(m_lines[check_index].m_symbol);
|
|
//--- Вернуть количество символов
|
|
return(symbols_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Информация текстового курсора |
|
|
//+------------------------------------------------------------------+
|
|
string CTextBox::TextCursorInfo(void)
|
|
{
|
|
//--- Компоненты для строки
|
|
string lines_total =(string)LinesTotal();
|
|
string columns_total =(string)ColumnsTotal(TextCursorLine());
|
|
string text_cursor_line =string(TextCursorLine()+1);
|
|
string text_cursor_column =string(TextCursorColumn()+1);
|
|
//--- Сформируем строку
|
|
string text_box_info="Ln "+text_cursor_line+"/"+lines_total+", "+"Col "+text_cursor_column+"/"+columns_total;
|
|
//--- Вернуть строку
|
|
return(text_box_info);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::AddLine(const string added_text="")
|
|
{
|
|
//--- Выйти, если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
return;
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Резервный размер массива
|
|
int reserve_size=10000;
|
|
//--- Устанавливаем размер массивам структуры
|
|
::ArrayResize(m_lines,lines_total+1,reserve_size);
|
|
//--- Установим признак окончания строки
|
|
m_lines[lines_total].m_end_of_line=true;
|
|
//--- Установим шрифт
|
|
m_textbox.FontSet(CElement::Font(),-CElement::FontSize()*10,FW_NORMAL);
|
|
//--- Добавим текст в строку
|
|
AddToString(lines_total,added_text);
|
|
//--- Выйти, если у составного элемента указатель на главный элемент невалиден
|
|
if(::CheckPointer(m_scrollh.MainPointer())==POINTER_INVALID)
|
|
return;
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
//--- В режиме переноса слов нужно повторно пересчитать и установить размеры
|
|
if(m_word_wrap_mode)
|
|
{
|
|
CalculateTextBoxSize();
|
|
ChangeTextBoxSize();
|
|
}
|
|
//--- Перерисовать полосы прокрутки
|
|
//if(m_scrollh.IsScroll())
|
|
// m_scrollh.Update(true);
|
|
//if(m_scrollv.IsScroll())
|
|
// m_scrollv.Update(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет текст в указанную строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::AddText(const uint line_index,const string added_text)
|
|
{
|
|
//--- Выйти, если передана пустая строка
|
|
if(added_text=="")
|
|
return;
|
|
//--- Получим размер массива строк, с проверкой на наличие обязательной первой строки
|
|
uint lines_total=CheckFirstLine();
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Корректировка индекса с учётом режима переноса по словам
|
|
if(m_word_wrap_mode)
|
|
{
|
|
for(uint i=0,j=0; i<lines_total; i++)
|
|
{
|
|
//--- Считаем строки по признаку окончания
|
|
if(m_lines[i].m_end_of_line)
|
|
{
|
|
//---
|
|
if(l==j || i+1>=lines_total)
|
|
{
|
|
l=i;
|
|
break;
|
|
}
|
|
//---
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//---
|
|
uint insert_pos = (l == m_text_cursor_y_pos) ? m_text_cursor_x_pos : ::ArraySize(m_lines[l].m_symbol);
|
|
|
|
//--- Установим шрифт
|
|
m_textbox.FontSet(CElement::Font(),-CElement::FontSize()*10,FW_NORMAL);
|
|
//--- Добавим текст в строку
|
|
InsertToString(l,insert_pos,added_text);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает текст из указанной строки |
|
|
//+------------------------------------------------------------------+
|
|
string CTextBox::GetValue(const uint line_index=0)
|
|
{
|
|
//--- Получим размер массива строк, с проверкой на наличие обязательной первой строки
|
|
uint lines_total=CheckFirstLine();
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Вернуть текст
|
|
return(CollectString(l));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Очищает текстовое поле ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ClearTextBox(void)
|
|
{
|
|
//--- Удаляем все строки кроме первой
|
|
::ArrayResize(m_lines,1);
|
|
//--- Очищаем первую строку
|
|
ClearLine(0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Горизонтальная прокрутка поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::HorizontalScrolling(const int pos=WRONG_VALUE)
|
|
{
|
|
//--- Для определения позиции ползунка
|
|
int index=0;
|
|
//--- Индекс последней позиции
|
|
int last_pos_index=int(m_area_x_size-m_area_visible_x_size);
|
|
//--- Корректировка в случае выхода из диапазона
|
|
if(pos<0)
|
|
index=last_pos_index;
|
|
else
|
|
index=(pos>last_pos_index)? last_pos_index : pos;
|
|
//--- Сдвигаем ползунок полосы прокрутки
|
|
m_scrollh.MovingThumb(index);
|
|
//--- Сдвигаем поле ввода
|
|
ShiftData();
|
|
//--- Обновить полосу прокрутки
|
|
m_scrollh.Update();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Вертикальная прокрутка поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::VerticalScrolling(const int pos=WRONG_VALUE)
|
|
{
|
|
//--- Для определения позиции ползунка
|
|
int index=0;
|
|
//--- Индекс последней позиции
|
|
int last_pos_index=int((m_area_y_size-m_area_visible_y_size)/(double)LineHeight());
|
|
//--- Корректировка в случае выхода из диапазона
|
|
if(pos<0)
|
|
index=last_pos_index;
|
|
else
|
|
index=(pos>last_pos_index)? last_pos_index : pos;
|
|
//--- Сдвигаем ползунок полосы прокрутки
|
|
m_scrollv.MovingThumb(index);
|
|
//--- Сдвигаем поле ввода
|
|
ShiftData();
|
|
//--- Обновить полосу прокрутки
|
|
m_scrollv.Update(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сдвигает данные относительно полос прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ShiftData(void)
|
|
{
|
|
//--- Получим текущие позиции ползунков горизонтальной и вертикальной полос прокрутки
|
|
int h_offset =m_scrollh.CurrentPos()*m_shift_x_step;
|
|
int v_offset =m_text_y_offset+(m_scrollv.CurrentPos()*(int)LineHeight())-2;
|
|
//--- Рассчитаем отступы для смещения
|
|
int x_offset =(h_offset<1)? 0 : (h_offset>=m_shift_x2_limit)? m_shift_x2_limit : h_offset;
|
|
int y_offset =(v_offset<1)? 0 : (v_offset>=m_shift_y2_limit)? m_shift_y2_limit : v_offset;
|
|
//--- Расчёт положения данных относительно ползунков полос прокрутки
|
|
long x =(m_area_x_size>m_area_visible_x_size && !m_word_wrap_mode)? x_offset : 0;
|
|
long y =(m_area_y_size>m_area_visible_y_size)? y_offset : 0;
|
|
//--- Смещение данных
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET,x);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YOFFSET,y);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Корректировка размеров поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CorrectSize(void)
|
|
{
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize(true,true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Активация поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ActivateTextBox(void)
|
|
{
|
|
OnClickTextBox(m_textbox.ChartObjectName());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменение размеров |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeSize(const uint x_size,const uint y_size)
|
|
{
|
|
//--- Установить новый размер
|
|
ChangeMainSize(x_size,y_size);
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение элемента |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Moving(const bool only_visible=true)
|
|
{
|
|
//--- Выйти, если элемент скрыт
|
|
if(only_visible)
|
|
if(!CElementBase::IsVisible())
|
|
return;
|
|
//--- Если привязка справа
|
|
if(m_anchor_right_window_side)
|
|
{
|
|
//--- Сохранение координат в полях элемента
|
|
CElementBase::X(m_main.X2()-XGap());
|
|
//--- Сохранение координат в полях объектов
|
|
m_textbox.X(m_main.X2()-m_textbox.XGap());
|
|
}
|
|
else
|
|
{
|
|
CElementBase::X(m_main.X()+XGap());
|
|
m_textbox.X(m_main.X()+m_textbox.XGap());
|
|
}
|
|
//--- Если привязка снизу
|
|
if(m_anchor_bottom_window_side)
|
|
{
|
|
CElementBase::Y(m_main.Y2()-YGap());
|
|
m_textbox.Y(m_main.Y2()-m_textbox.YGap());
|
|
}
|
|
else
|
|
{
|
|
CElementBase::Y(m_main.Y()+YGap());
|
|
m_textbox.Y(m_main.Y()+m_textbox.YGap());
|
|
}
|
|
//--- Обновление координат
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XDISTANCE,m_textbox.X());
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YDISTANCE,m_textbox.Y());
|
|
//--- Обновить положение объектов
|
|
CElement::Moving(only_visible);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Показывает элемент |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Show(void)
|
|
{
|
|
//--- Выйти, если элемент уже видим
|
|
if(CElementBase::IsVisible())
|
|
return;
|
|
//--- Сделать видимыми все объекты
|
|
::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
|
|
//--- Состояние видимости
|
|
CElementBase::IsVisible(true);
|
|
//--- Обновить положение элемента
|
|
Moving();
|
|
//--- Показать полосы прокрутки
|
|
if(m_scrollv.IsScroll())
|
|
m_scrollv.Show();
|
|
if(m_scrollh.IsScroll())
|
|
m_scrollh.Show();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Скрывает элемент |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Hide(void)
|
|
{
|
|
//--- Выйти, если элемент скрыт
|
|
if(!CElementBase::IsVisible())
|
|
return;
|
|
//--- Скрыть все объекты
|
|
::ObjectSetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
|
|
m_scrollv.Hide();
|
|
m_scrollh.Hide();
|
|
//--- Состояние видимости
|
|
CElementBase::IsVisible(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаление |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Delete(void)
|
|
{
|
|
//--- Удаление объектов
|
|
m_canvas.Destroy();
|
|
m_textbox.Destroy();
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Освобождение массивов элемента
|
|
for(uint i=0; i<lines_total; i++)
|
|
{
|
|
::ArrayFree(m_lines[i].m_width);
|
|
::ArrayFree(m_lines[i].m_symbol);
|
|
}
|
|
//---
|
|
::ArrayFree(m_lines);
|
|
//--- Инициализация переменных значениями по умолчанию
|
|
m_text_edit_state=false;
|
|
CElementBase::IsVisible(true);
|
|
CElementBase::MouseFocus(false);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Установка приоритетов |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SetZorders(void)
|
|
{
|
|
CElement::SetZorders();
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_ZORDER,m_zorder+1);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сброс приоритетов |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ResetZorders(void)
|
|
{
|
|
CElement::ResetZorders();
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_ZORDER,WRONG_VALUE);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на элемент |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnClickTextBox(const string clicked_object)
|
|
{
|
|
//--- Выйдем, если чужое имя объекта
|
|
if(m_textbox.ChartObjectName()!=clicked_object)
|
|
{
|
|
//--- Отправим сообщение об окончании ввода строки в поле ввода, если поле было активно
|
|
if(m_text_edit_state)
|
|
{
|
|
string str=(m_multi_line_mode)? TextCursorInfo() : "";
|
|
::EventChartCustom(m_chart_id,ON_END_EDIT,CElementBase::Id(),CElementBase::Index(),str);
|
|
}
|
|
//--- Дезактивировать поле ввода
|
|
DeactivateTextBox();
|
|
//--- Обновить
|
|
Update(true);
|
|
return(false);
|
|
}
|
|
//--- Выйти, если (1) включен режим "Только для чтения" или (2) элемент заблокирован
|
|
if(m_read_only_mode || CElementBase::IsLocked())
|
|
return(true);
|
|
//--- Выйдем, если полоса прокрутки в активном режиме
|
|
if(m_scrollv.State() || m_scrollh.State())
|
|
return(true);
|
|
//--- Если (1) включен режим авто выделения текста и (2) поле ввода было активировано только что
|
|
if(m_auto_selection_mode && !m_text_edit_state)
|
|
SelectAllText();
|
|
//--- Сброс выделения
|
|
else
|
|
ResetSelectedText();
|
|
//--- Отключим управление графиком
|
|
m_chart.SetInteger(CHART_KEYBOARD_CONTROL,false);
|
|
//--- Если (1) включен режим авто выделения текста и (2) поле ввода активировано
|
|
if(!m_auto_selection_mode || (m_auto_selection_mode && m_text_edit_state))
|
|
{
|
|
//--- Установить текстовый курсор по курсору мыши
|
|
SetTextCursorByMouseCursor();
|
|
}
|
|
//--- Если включен режим многострочного поля ввода, корректируем вертикальную полосу прокрутки
|
|
if(m_multi_line_mode)
|
|
CorrectingVerticalScrollThumb();
|
|
//--- Активировать поле ввода
|
|
m_text_edit_state=true;
|
|
//--- Обновить текст и курсор
|
|
DrawTextAndCursor(true);
|
|
//--- Изменить цвет рамки
|
|
DrawBorder();
|
|
m_canvas.Update();
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_CLICK_TEXT_BOX,CElementBase::Id(),CElementBase::Index(),TextCursorInfo());
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Procesamiento de tecla presionada |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKey(const long key_code)
|
|
{
|
|
//--- Obtener el símbolo de la tecla
|
|
string pressed_key=m_keys.KeySymbol(key_code);
|
|
//--- Salir si no hay símbolo
|
|
if(pressed_key=="")
|
|
return(false);
|
|
//--- Si hay texto seleccionado, eliminarlo
|
|
DeleteSelectedText();
|
|
//--- Agregar el símbolo y sus propiedades
|
|
AddSymbol(pressed_key);
|
|
//--- Determinar si se necesita recálculo completo de dimensiones
|
|
bool needs_full_recalc=false;
|
|
//--- Obtener tamaño del array de símbolos y ancho de línea actual
|
|
int symbols_total =::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
int line_width = (int)LineWidth(symbols_total,m_text_cursor_y_pos);
|
|
const int xscrrol = m_scrollv.ScrollWidth();
|
|
//--- Si el modo de ajuste de palabras está activado
|
|
if(m_word_wrap_mode)
|
|
{
|
|
//--- Se necesita recálculo si la línea supera el área visible (causará wrap)
|
|
if((line_width+m_text_x_offset*2+xscrrol)>m_area_visible_x_size)
|
|
needs_full_recalc=true;
|
|
}
|
|
//--- Si el modo de ajuste de palabras está desactivado
|
|
else
|
|
{
|
|
//--- Se necesita recálculo si la línea supera el área total actual
|
|
// (necesitará expandir el canvas o ajustar scroll)
|
|
if((line_width+m_text_x_offset*2+xscrrol)>m_area_x_size)
|
|
needs_full_recalc=true;
|
|
}
|
|
//--- Si se necesita recálculo completo
|
|
if(needs_full_recalc)
|
|
{
|
|
//--- Calcular dimensiones del campo de entrada
|
|
CalculateTextBoxSize();
|
|
//--- Establecer nuevo tamaño al campo de entrada
|
|
ChangeTextBoxSize(true,true);
|
|
//--- Corregir barra de desplazamiento horizontal
|
|
CorrectingHorizontalScrollThumb();
|
|
//--- Si el modo de ajuste de palabras está activado, corregir barra vertical
|
|
if(m_word_wrap_mode)
|
|
CorrectingVerticalScrollThumb();
|
|
}
|
|
//--- Si no se necesita recálculo completo
|
|
else
|
|
{
|
|
//--- Obtener coordenada X del cursor
|
|
CalculateTextCursorX();
|
|
//--- Corregir barra de desplazamiento horizontal si el cursor salió del área visible
|
|
int x_offset=(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET);
|
|
if(m_text_cursor_x-x_offset>=m_area_visible_x_size-m_text_x_offset)
|
|
CorrectingHorizontalScrollThumb();
|
|
}
|
|
//--- Actualizar texto en el campo de entrada
|
|
DrawTextAndCursor(true);
|
|
//--- Enviar mensaje sobre esto
|
|
::EventChartCustom(m_chart_id,ON_MODIFY_TEXTBOX,CElementBase::Id(),CElementBase::Index(),pressed_key);
|
|
return(true);
|
|
}
|
|
/*
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия специальных символов с Shift/Alt |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeySpecial(const long key_code)
|
|
{
|
|
//--- Obtener estado de modificadores
|
|
if(!m_keys.KeyShiftState())
|
|
return(false);
|
|
|
|
//--- Mapa de caracteres especiales
|
|
string special_char = "";
|
|
|
|
//--- Con Shift
|
|
if(is_shift && !is_alt)
|
|
{
|
|
switch((int)key_code)
|
|
{
|
|
case 188: special_char = "<"; break; // Shift + ,
|
|
case 190: special_char = ">"; break; // Shift + .
|
|
case 191: special_char = "?"; break; // Shift + /
|
|
case 186: special_char = ":"; break; // Shift + ;
|
|
case 222: special_char = "\""; break; // Shift + '
|
|
case 219: special_char = "{"; break; // Shift + [
|
|
case 221: special_char = "}"; break; // Shift + ]
|
|
case 220: special_char = "|"; break; // Shift + \
|
|
case 49: special_char = "!"; break; // Shift + 1
|
|
case 50: special_char = "@"; break; // Shift + 2
|
|
case 51: special_char = "#"; break; // Shift + 3
|
|
case 52: special_char = "$"; break; // Shift + 4
|
|
case 53: special_char = "%"; break; // Shift + 5
|
|
case 54: special_char = "^"; break; // Shift + 6
|
|
case 55: special_char = "&"; break; // Shift + 7
|
|
case 56: special_char = "*"; break; // Shift + 8
|
|
case 57: special_char = "("; break; // Shift + 9
|
|
case 48: special_char = ")"; break; // Shift + 0
|
|
case 189: special_char = "_"; break; // Shift + -
|
|
case 187: special_char = "+"; break; // Shift + =
|
|
case 192: special_char = "~"; break; // Shift + `
|
|
}
|
|
}
|
|
//--- Sin Shift (caracteres normales que Keys.mqh no captura)
|
|
else if(!is_shift && !is_alt)
|
|
{
|
|
switch((int)key_code)
|
|
{
|
|
case 188: special_char = ","; break;
|
|
case 190: special_char = "."; break;
|
|
case 191: special_char = "/"; break;
|
|
case 186: special_char = ";"; break;
|
|
case 222: special_char = "'"; break;
|
|
case 219: special_char = "["; break;
|
|
case 221: special_char = "]"; break;
|
|
case 220: special_char = "\\"; break;
|
|
case 189: special_char = "-"; break;
|
|
case 187: special_char = "="; break;
|
|
case 192: special_char = "`"; break;
|
|
}
|
|
}
|
|
|
|
//--- Si no encontramos carácter especial, salir
|
|
if(special_char == "")
|
|
return(false);
|
|
|
|
//--- Si hay texto seleccionado, eliminarlo
|
|
DeleteSelectedText();
|
|
|
|
//--- Agregar el carácter especial
|
|
AddSymbol(special_char);
|
|
|
|
//--- Recalcular dimensiones
|
|
CalculateTextBoxSize();
|
|
ChangeTextBoxSize(true, true);
|
|
|
|
//--- Corregir scrollbars
|
|
CorrectingHorizontalScrollThumb();
|
|
if(m_word_wrap_mode)
|
|
CorrectingVerticalScrollThumb();
|
|
|
|
//--- Redibujar
|
|
DrawTextAndCursor(true);
|
|
|
|
//--- Enviar evento de modificación
|
|
::EventChartCustom(m_chart_id, ON_MODIFY_TEXTBOX, CElementBase::Id(), CElementBase::Index(), special_char);
|
|
return(true);
|
|
} */
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Backspace' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyBackspace(const long key_code)
|
|
{
|
|
//--- Выйти, если это не клавиша 'Backspace'
|
|
if(key_code!=KEY_BACKSPACE)
|
|
return(false);
|
|
//--- Если есть выделенный текст, удалим его и выйдем
|
|
if(DeleteSelectedText())
|
|
return(true);
|
|
//--- Удалить символ, если позиция больше нуля
|
|
if(m_text_cursor_x_pos>0)
|
|
DeleteSymbol();
|
|
//--- Если нулевая позиция и не первая строка,
|
|
// удалить строку и сместить строки на одну позицию вверх
|
|
else if(m_text_cursor_y_pos>0)
|
|
ShiftOnePositionUp();
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize(true,true);
|
|
//--- Корректируем полосы прокрутки
|
|
CorrectingHorizontalScrollThumb();
|
|
CorrectingVerticalScrollThumb();
|
|
//--- Обновить текст в поле ввода
|
|
DrawTextAndCursor(true);
|
|
//--- Отправим сообщение об этом
|
|
//::EventChartCustom(m_chart_id,ON_MOVE_TEXT_CURSOR,CElementBase::Id(),CElementBase::Index(),TextCursorInfo());
|
|
// Modifuqe esto agrege un nuevo evento
|
|
::EventChartCustom(m_chart_id,ON_MODIFY_TEXTBOX,CElementBase::Id(),CElementBase::Index(),"backspace");
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише "Enter" |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyEnter(const long key_code)
|
|
{
|
|
//--- Выйти, если это не клавиша 'Enter'
|
|
if(key_code!=KEY_ENTER)
|
|
return(false);
|
|
//--- Если есть выделенный текст, удалим его
|
|
DeleteSelectedText();
|
|
//--- Если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
{
|
|
//--- Дезактивировать поле ввода
|
|
DeactivateTextBox();
|
|
//--- Обновить
|
|
Update(true);
|
|
//--- Отправим сообщение об этом
|
|
string str=(m_multi_line_mode)? TextCursorInfo() : "";
|
|
::EventChartCustom(m_chart_id,ON_END_EDIT,CElementBase::Id(),CElementBase::Index(),str);
|
|
return(false);
|
|
}
|
|
//--- Сместим строки на одну позицию вниз
|
|
ShiftOnePositionDown();
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
//--- Корректируем вертикальную полосу прокрутки
|
|
CorrectingVerticalScrollThumb();
|
|
//--- Переместить курсор в начало строки
|
|
SetTextCursor(0,m_text_cursor_y_pos);
|
|
//--- Переместить полосу прокрутки в начало
|
|
HorizontalScrolling(0);
|
|
//--- Обновить текст в поле ввода
|
|
DrawTextAndCursor(true);
|
|
//--- Отправим сообщение об этом
|
|
//::EventChartCustom(m_chart_id,ON_MOVE_TEXT_CURSOR,CElementBase::Id(),CElementBase::Index(),TextCursorInfo());
|
|
// Modifuqe esto agrege un nuevo evento
|
|
::EventChartCustom(m_chart_id,ON_MODIFY_TEXTBOX,CElementBase::Id(),CElementBase::Index(),"\n");
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Left' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyLeft(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Left' или (2) нажата клавиша 'Ctrl' или (3) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_LEFT || m_keys.KeyCtrlState() || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор влево на один символ
|
|
MoveTextCursor(TO_NEXT_LEFT_SYMBOL,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Right' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyRight(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Right' или (2) нажата клавиша 'Ctrl' или (3) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_RIGHT || m_keys.KeyCtrlState() || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вправо на один символ
|
|
MoveTextCursor(TO_NEXT_RIGHT_SYMBOL,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Up' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyUp(const long key_code)
|
|
{
|
|
//--- Выйти, если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
return(false);
|
|
//--- Выйти, если (1) это не клавиша 'Up' или (2) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_UP || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вверх на одну строку
|
|
MoveTextCursor(TO_NEXT_UP_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Down' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyDown(const long key_code)
|
|
{
|
|
//--- Выйти, если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
return(false);
|
|
//--- Выйти, если (1) это не клавиша 'Down' или (2) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_DOWN || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вниз на одну строку
|
|
MoveTextCursor(TO_NEXT_DOWN_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'Home' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyHome(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Home' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_HOME || m_keys.KeyCtrlState() || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в начало текущей строки
|
|
MoveTextCursor(TO_BEGIN_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише 'End' |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyEnd(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'End' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' нажата
|
|
if(key_code!=KEY_END || m_keys.KeyCtrlState() || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в конец текущей строки
|
|
MoveTextCursor(TO_END_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка одновременного нажатия клавиш Ctrl + Left |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlAndLeft(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Left' и (2) клавиша 'Ctrl' не нажата или (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_LEFT && m_keys.KeyCtrlState()) || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор влево на одно слово
|
|
MoveTextCursor(TO_NEXT_LEFT_WORD,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка одновременного нажатия клавиш Ctrl + Right |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlAndRight(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Right' и (2) клавиша 'Ctrl' не нажата или (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_RIGHT && m_keys.KeyCtrlState()) || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вправо на одно слово
|
|
MoveTextCursor(TO_NEXT_RIGHT_WORD,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка одновременного нажатия клавиш Ctrl + Home |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlAndHome(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Home' и (2) клавиша 'Ctrl' не нажата или (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_HOME && m_keys.KeyCtrlState()) || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в начало первой строки
|
|
MoveTextCursor(TO_BEGIN_FIRST_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка одновременного нажатия клавиш Ctrl + End |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlAndEnd(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'End' и (2) клавиша 'Ctrl' не нажата или (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_END && m_keys.KeyCtrlState()) || m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в конец последней строки
|
|
MoveTextCursor(TO_END_LAST_LINE,false);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + Left |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndLeft(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Left' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_LEFT || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор влево на один символ
|
|
MoveTextCursor(TO_NEXT_LEFT_SYMBOL,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + Right |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndRight(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Right' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_RIGHT || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вправо на один символ
|
|
MoveTextCursor(TO_NEXT_RIGHT_SYMBOL,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + Up |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndUp(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Up' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_UP || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вверх на одну строку
|
|
MoveTextCursor(TO_NEXT_UP_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + Down |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndDown(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Down' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_DOWN || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Сместить текстовый курсор вниз на одну строку
|
|
MoveTextCursor(TO_NEXT_DOWN_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + Home |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndHome(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Home' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_HOME || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в начало текущей строки
|
|
MoveTextCursor(TO_BEGIN_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Shift + End |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyShiftAndEnd(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'End' или (2) клавиша 'Ctrl' нажата или (3) клавиша 'Shift' не нажата
|
|
if(key_code!=KEY_END || m_keys.KeyCtrlState() || !m_keys.KeyShiftState())
|
|
return(false);
|
|
//--- Переместить курсор в конец текущей строки
|
|
MoveTextCursor(TO_END_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Ctrl + Shift + Left |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlShiftAndLeft(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Left' и (2) клавиша 'Ctrl' не нажата и (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_LEFT && m_keys.KeyCtrlState() && m_keys.KeyShiftState()))
|
|
return(false);
|
|
//--- Сместить текстовый курсор влево на одно слово
|
|
MoveTextCursor(TO_NEXT_LEFT_WORD,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Ctrl + Shift + Right |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlShiftAndRight(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Right' и (2) клавиша 'Ctrl' не нажата и (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_RIGHT && m_keys.KeyCtrlState() && m_keys.KeyShiftState()))
|
|
return(false);
|
|
//--- Сместить текстовый курсор вправо на одно слово
|
|
MoveTextCursor(TO_NEXT_RIGHT_WORD,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Ctrl + Shift + Home |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlShiftAndHome(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'Home' и (2) клавиша 'Ctrl' не нажата и (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_HOME && m_keys.KeyCtrlState() && m_keys.KeyShiftState()))
|
|
return(false);
|
|
//--- Переместить курсор в начало первой строки
|
|
MoveTextCursor(TO_BEGIN_FIRST_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обработка нажатия на клавише Ctrl + Shift + End |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::OnPressedKeyCtrlShiftAndEnd(const long key_code)
|
|
{
|
|
//--- Выйти, если (1) это не клавиша 'End' и (2) клавиша 'Ctrl' не нажата и (3) клавиша 'Shift' нажата
|
|
if(!(key_code==KEY_END && m_keys.KeyCtrlState() && m_keys.KeyShiftState()))
|
|
return(false);
|
|
//--- Переместить курсор в конец последней строки
|
|
MoveTextCursor(TO_END_LAST_LINE,true);
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Установить начальные индексы для выделенния текста |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SetStartSelectedTextIndexes(void)
|
|
{
|
|
//--- Если начальные индексы для выделения текста ещё не установлены
|
|
if(m_selected_line_from==WRONG_VALUE)
|
|
{
|
|
m_selected_line_from =(int)m_text_cursor_y_pos;
|
|
m_selected_symbol_from =(int)m_text_cursor_x_pos;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Установить конечные индексы для выделенния текста |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SetEndSelectedTextIndexes(void)
|
|
{
|
|
//--- Установить конечные индексы для выделения текста
|
|
m_selected_line_to =(int)m_text_cursor_y_pos;
|
|
m_selected_symbol_to =(int)m_text_cursor_x_pos;
|
|
//--- Если все индексы равны, то сбросить выделение
|
|
if(m_selected_line_from==m_selected_line_to && m_selected_symbol_from==m_selected_symbol_to)
|
|
ResetSelectedText();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Выделить весь текст |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SelectAllText(void)
|
|
{
|
|
//--- Получим размер массива символов
|
|
int symbols_total=::ArraySize(m_lines[0].m_symbol);
|
|
//--- Установить индексы для выделения текста
|
|
m_selected_line_from =0;
|
|
m_selected_line_to =0;
|
|
m_selected_symbol_from =0;
|
|
m_selected_symbol_to =symbols_total;
|
|
//--- Переместить ползунок горизонтальной полосы прокрутки на последнюю позицию
|
|
HorizontalScrolling();
|
|
//--- Переместить курсор в конец строки
|
|
SetTextCursor(symbols_total,0);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Сбросить выделенный текст |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ResetSelectedText(void)
|
|
{
|
|
m_selected_line_from =WRONG_VALUE;
|
|
m_selected_line_to =WRONG_VALUE;
|
|
m_selected_symbol_from =WRONG_VALUE;
|
|
m_selected_symbol_to =WRONG_VALUE;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Дезактивация поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DeactivateTextBox(void)
|
|
{
|
|
//--- Выйти, если уже дезактивировано
|
|
if(!m_text_edit_state)
|
|
return;
|
|
//--- Дезактивировать
|
|
m_text_edit_state=false;
|
|
//--- Включим управление графиком
|
|
m_chart.SetInteger(CHART_KEYBOARD_CONTROL,true);
|
|
//--- Сброс выделения
|
|
ResetSelectedText();
|
|
//--- Если многострочный режим отключен
|
|
if(!m_multi_line_mode)
|
|
{
|
|
//--- Переместить курсор в начало строки
|
|
SetTextCursor(0,0);
|
|
//--- Сместить полосу прокрутки в начало строки
|
|
HorizontalScrolling(0);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Ускоренная промотка полосы прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::FastSwitching(void)
|
|
{
|
|
//--- Выйдем, если нет фокуса на элементе
|
|
if(!CElementBase::MouseFocus())
|
|
return;
|
|
//--- Вернём счётчик к первоначальному значению, если кнопка мыши отжата
|
|
if(!m_mouse.LeftButtonState() || m_scrollv.State() || m_scrollh.State())
|
|
m_timer_counter=SPIN_DELAY_MSC;
|
|
//--- Если же кнопка мыши нажата
|
|
else
|
|
{
|
|
//--- Увеличим счётчик на установленный интервал
|
|
m_timer_counter+=TIMER_STEP_MSC;
|
|
//--- Выйдем, если меньше нуля
|
|
if(m_timer_counter<0)
|
|
return;
|
|
//---
|
|
bool scroll_v=false,scroll_h=false;
|
|
//--- Если прокрутка вверх
|
|
if(m_scrollv.GetIncButtonPointer().MouseFocus())
|
|
{
|
|
m_scrollv.OnClickScrollInc((uint)Id(),0);
|
|
scroll_v=true;
|
|
}
|
|
//--- Если прокрутка вниз
|
|
else if(m_scrollv.GetDecButtonPointer().MouseFocus())
|
|
{
|
|
m_scrollv.OnClickScrollDec((uint)Id(),1);
|
|
scroll_v=true;
|
|
}
|
|
//--- Если прокрутка влево
|
|
else if(m_scrollh.GetIncButtonPointer().MouseFocus())
|
|
{
|
|
m_scrollh.OnClickScrollInc((uint)Id(),2);
|
|
scroll_h=true;
|
|
}
|
|
//--- Если прокрутка вправо
|
|
else if(m_scrollh.GetDecButtonPointer().MouseFocus())
|
|
{
|
|
m_scrollh.OnClickScrollDec((uint)Id(),3);
|
|
scroll_h=true;
|
|
}
|
|
//--- Выйти, если ни одна кнопка не нажата
|
|
if(!scroll_v && !scroll_h)
|
|
return;
|
|
//--- Смещает поле ввода
|
|
ShiftData();
|
|
//--- Обновить полосы прокрутки
|
|
if(scroll_v) m_scrollv.Update(true);
|
|
if(scroll_h) m_scrollh.Update(true);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует текст |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Draw(void)
|
|
{
|
|
//--- Выводим текст
|
|
CTextBox::TextOut();
|
|
//--- Рисуем рамку
|
|
DrawBorder();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Обновление элемента |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::Update(const bool redraw=false)
|
|
{
|
|
//--- Перерисовать таблицу, если указано
|
|
if(redraw)
|
|
{
|
|
//--- Нарисовать
|
|
Draw();
|
|
//--- Применить
|
|
m_canvas.Update();
|
|
m_textbox.Update();
|
|
return;
|
|
}
|
|
//--- Применить
|
|
m_canvas.Update();
|
|
m_textbox.Update();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Вывод текста на холст |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::TextOut(void)
|
|
{
|
|
//--- Очистить холст
|
|
m_textbox.Erase(AreaColorCurrent());
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Корректировка в случае выхода из диапазона
|
|
m_text_cursor_y_pos=(m_text_cursor_y_pos>=lines_total)? lines_total-1 : m_text_cursor_y_pos;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Если включен многострочный режим или количество символов больше нуля
|
|
if(m_multi_line_mode || symbols_total>0)
|
|
{
|
|
//--- Цвет текста
|
|
uint text_color=TextColorCurrent();
|
|
//--- Получим ширину строки
|
|
int line_width=(int)LineWidth(m_text_cursor_x_pos,m_text_cursor_y_pos);
|
|
//--- Получим высоту строки и пройдёмся по всем строкам в цикле
|
|
int line_height=(int)LineHeight();
|
|
|
|
m_textbox.FontSet();
|
|
|
|
for(uint i=0; i<lines_total; i++)
|
|
{
|
|
//--- Получим координаты для текста
|
|
int x=m_text_x_offset;
|
|
int y=m_text_y_offset+((int)i*line_height);
|
|
//--- Получим размер строки
|
|
uint string_length=::ArraySize(m_lines[i].m_symbol);
|
|
//--- Рисуем текст
|
|
for(uint s=0; s<string_length; s++)
|
|
{
|
|
//--- Если есть выделенный текст, определим его цвет, а также цвет фона текущего символа
|
|
if(CheckSelectedText(i,s))
|
|
{
|
|
//--- Цвет выделенного текста
|
|
text_color=::ColorToARGB(m_selected_text_color);
|
|
//--- Рассчитаем координаты для рисования фона
|
|
int x2 =x+m_lines[i].m_width[s];
|
|
int y2 =y+line_height-1;
|
|
//--- Рисуем цвет фона символа
|
|
m_textbox.FillRectangle(x,y,x2,y2,::ColorToARGB(m_selected_back_color,m_alpha));
|
|
}
|
|
else
|
|
text_color=TextColorCurrent();
|
|
//--- Нарисовать символ
|
|
m_textbox.TextOutFast(x,y,m_lines[i].m_symbol[s],text_color,TA_LEFT);
|
|
//--- X-координата для следующего символа
|
|
x+=m_lines[i].m_width[s];
|
|
}
|
|
}
|
|
}
|
|
//--- Если же многострочный режим отключен и нет ни одного символа, то будет отображаться текст по умолчанию (если указан)
|
|
else
|
|
{
|
|
if(m_default_text!="")
|
|
m_textbox.TextOut(m_area_x_size/2,m_area_y_size/2,m_default_text,::ColorToARGB(m_default_text_color),TA_CENTER|TA_VCENTER);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует рамку поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DrawBorder(void)
|
|
{
|
|
//--- Получим смещение по оси X
|
|
int xo=(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_XOFFSET);
|
|
int yo=(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_YOFFSET);
|
|
//--- Границы
|
|
int x_size =(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_XSIZE)-1;
|
|
int y_size =(int)::ObjectGetInteger(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_YSIZE)-1;
|
|
//--- Координаты
|
|
int x1=xo,y1=yo;
|
|
int x2=xo+x_size;
|
|
int y2=yo+y_size;
|
|
//--- Рисуем прямоугольник без заливки
|
|
m_canvas.Rectangle(x1,y1,x2,y2,BorderColorCurrent());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рисует текстовый курсор |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DrawCursor(void)
|
|
{
|
|
//--- Получим высоту строки
|
|
int line_height=(int)LineHeight();
|
|
//--- Получим X-координату курсора
|
|
CalculateTextCursorX();
|
|
//--- Нарисуем текстовый курсор
|
|
for(int i=0; i<line_height; i++)
|
|
{
|
|
//--- Получим Y-координату для пикселя
|
|
int y=m_text_y_offset+((int)m_text_cursor_y_pos*line_height)+i;
|
|
//--- Получим текущий цвет пикселя
|
|
uint pixel_color=m_textbox.PixelGet(m_text_cursor_x,y);
|
|
//--- Инвертируем цвет для курсора
|
|
pixel_color=::ColorToARGB(m_clr.Negative((color)pixel_color));
|
|
m_textbox.PixelSet(m_text_cursor_x,y,::ColorToARGB(pixel_color));
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Отображает текст и мигающий курсор |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DrawTextAndCursor(const bool show_state=false)
|
|
{
|
|
//--- Определим состояние для текстового курсора (показать/скрыть)
|
|
static bool state=false;
|
|
state=(!show_state)? !state : show_state;
|
|
//--- Выводим текст
|
|
CTextBox::TextOut();
|
|
//--- Нарисовать текстовый курсор
|
|
if(state)
|
|
DrawCursor();
|
|
//--- Обновить поле ввода
|
|
m_canvas.Update();
|
|
m_textbox.Update();
|
|
m_scrollh.Update(true);
|
|
m_scrollv.Update(true);
|
|
//--- Сброс счётчика
|
|
m_counter.ZeroTimeCounter();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает цвет фона относительно текущего состояния элемента |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::AreaColorCurrent(void)
|
|
{
|
|
uint clr=(!CElementBase::IsLocked())? m_back_color : m_back_color_locked;
|
|
//--- Вернуть цвет
|
|
return(::ColorToARGB(clr,m_alpha));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает цвет текста относительно текущего состояния элемента |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::TextColorCurrent(void)
|
|
{
|
|
uint clr=(!CElementBase::IsLocked())? m_label_color : m_label_color_locked;
|
|
//--- Вернуть цвет
|
|
return(::ColorToARGB(clr));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает цвет рамки относительно текущего состояния элемента |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::BorderColorCurrent(void)
|
|
{
|
|
uint clr=clrBlack;
|
|
//--- Если элемент не заблокирован
|
|
if(!CElementBase::IsLocked())
|
|
{
|
|
//--- Если поле ввода активировано
|
|
if(m_text_edit_state)
|
|
clr=m_border_color_pressed;
|
|
//--- Если неактивировано, то проверяем фокус элемента
|
|
else
|
|
clr=(CElementBase::MouseFocus())? m_border_color_hover : m_border_color;
|
|
}
|
|
//--- Если элемент заблокирован
|
|
else
|
|
clr=m_border_color_locked;
|
|
//--- Вернуть цвет
|
|
return(::ColorToARGB(clr));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменение цвета объектов |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeObjectsColor(void)
|
|
{
|
|
//--- Отслеживаем изменение цвета, только если доступен сам и родитель
|
|
if(m_main.CElementBase::IsLocked() || !CElementBase::IsAvailable())
|
|
return;
|
|
//--- Если это момент пересечения границ элемента
|
|
if(CElementBase::CheckCrossingBorder())
|
|
{
|
|
//--- Изменить цвет
|
|
DrawBorder();
|
|
m_canvas.Update();
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Собирает строку из символов |
|
|
//+------------------------------------------------------------------+
|
|
string CTextBox::CollectString(const uint line_index,const uint symbols_total=0)
|
|
{
|
|
m_temp_input_string="";
|
|
//--- Получим размер строки
|
|
uint string_length=::ArraySize(m_lines[line_index].m_symbol);
|
|
//---
|
|
for(uint i=0; i<string_length; i++)
|
|
{
|
|
if(symbols_total>0)
|
|
{
|
|
if(i==symbols_total)
|
|
break;
|
|
}
|
|
//---
|
|
::StringAdd(m_temp_input_string,m_lines[line_index].m_symbol[i]);
|
|
}
|
|
//--- Вернуть собранную строку
|
|
return(m_temp_input_string);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет символ и его свойства в массивы структуры |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::AddSymbol(const string key_symbol)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Установим новый размер массивам
|
|
ArraysResize(m_text_cursor_y_pos,symbols_total+1);
|
|
//--- Сместить все символы от конца массива к индексу добавляемого символа
|
|
MoveSymbols(m_text_cursor_y_pos,0,m_text_cursor_x_pos,false);
|
|
//--- Получим ширину символа
|
|
int width=m_textbox.TextWidth(key_symbol);
|
|
//--- Добавить символ в освободившийся элемент
|
|
m_lines[m_text_cursor_y_pos].m_symbol[m_text_cursor_x_pos] =key_symbol;
|
|
m_lines[m_text_cursor_y_pos].m_width[m_text_cursor_x_pos] =width;
|
|
//--- Увеличить счётчик позиции курсора
|
|
m_text_cursor_x_pos++;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаляет символ |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DeleteSymbol(void)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Если массив пустой
|
|
if(symbols_total<1)
|
|
{
|
|
//--- Установим курсор на нулевую позицию текщей строки
|
|
SetTextCursor(0,m_text_cursor_y_pos);
|
|
return;
|
|
}
|
|
//--- Получим позицию предыдущего символа
|
|
int check_pos=(int)m_text_cursor_x_pos-1;
|
|
//--- Выйти, если выход из диапазона
|
|
if(check_pos<0)
|
|
return;
|
|
//--- Сместить все символы на один элемент влево от индекса удаляемого символа
|
|
MoveSymbols(m_text_cursor_y_pos,m_text_cursor_x_pos,check_pos);
|
|
//--- Уменьшить счётчик позиции курсора
|
|
m_text_cursor_x_pos--;
|
|
//--- Установим новый размер массивам
|
|
ArraysResize(m_text_cursor_y_pos,symbols_total-1);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаляет выделенный текст |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::DeleteSelectedText(void)
|
|
{
|
|
//--- Выйти, если текст не выделен
|
|
if(m_selected_line_from==WRONG_VALUE)
|
|
return(false);
|
|
//--- Если удаляются символы на одной строке
|
|
if(m_selected_line_from==m_selected_line_to)
|
|
DeleteTextOnOneLine();
|
|
//--- Если удаляются символы с нескольких строк
|
|
else
|
|
DeleteTextOnMultipleLines();
|
|
//--- Сброс выделенного текста
|
|
ResetSelectedText();
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
//--- Корректируем полосы прокрутки
|
|
CorrectingHorizontalScrollThumb();
|
|
CorrectingVerticalScrollThumb();
|
|
//--- Обновить текст в поле ввода
|
|
DrawTextAndCursor(true);
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_MOVE_TEXT_CURSOR,CElementBase::Id(),CElementBase::Index(),TextCursorInfo());
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаляет выделенный на одной строке текст |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DeleteTextOnOneLine(void)
|
|
{
|
|
int symbols_total =::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
int symbols_to_delete =::fabs(m_selected_symbol_from-m_selected_symbol_to);
|
|
//--- Если начальный индекс символа справа
|
|
if(m_selected_symbol_to<m_selected_symbol_from)
|
|
{
|
|
//--- Сместим символы на освободившееся место в текущей строке
|
|
MoveSymbols(m_text_cursor_y_pos,m_selected_symbol_from,m_selected_symbol_to);
|
|
}
|
|
//--- Если начальный индекс символа слева
|
|
else
|
|
{
|
|
//--- Сместим текстовый курсор влево на количество удаляемых символов
|
|
m_text_cursor_x_pos-=symbols_to_delete;
|
|
//--- Сместим символы на освободившееся место в текущей строке
|
|
MoveSymbols(m_text_cursor_y_pos,m_selected_symbol_to,m_selected_symbol_from);
|
|
}
|
|
//--- Уменьшим размер массива текущей строки на извлечённое из неё количество символов
|
|
ArraysResize(m_text_cursor_y_pos,symbols_total-symbols_to_delete);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Удаляет выделенный текст на нескольких строках |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::DeleteTextOnMultipleLines(void)
|
|
{
|
|
//--- Общее количество символов на начальной и конечной строках
|
|
uint symbols_total_line_from =::ArraySize(m_lines[m_selected_line_from].m_symbol);
|
|
uint symbols_total_line_to =::ArraySize(m_lines[m_selected_line_to].m_symbol);
|
|
//--- Количество промежуточных строк для удаления
|
|
uint lines_to_delete=::fabs(m_selected_line_from-m_selected_line_to);
|
|
//--- Количество символов для удаления на начальной и конечной строках
|
|
uint symbols_to_delete_in_line_from =::fabs(symbols_total_line_from-m_selected_symbol_from);
|
|
uint symbols_to_delete_in_line_to =::fabs(symbols_total_line_to-m_selected_symbol_to);
|
|
//--- Если начальная строка ниже конечной
|
|
if(m_selected_line_from>m_selected_line_to)
|
|
{
|
|
//--- Скопируем в массив символы, которые нужно перенести
|
|
string array[];
|
|
CopyWrapSymbols(m_selected_line_from,m_selected_symbol_from,symbols_to_delete_in_line_from,array);
|
|
//--- Установим новый размер строке-приёмнику
|
|
uint new_size=m_selected_symbol_to+symbols_to_delete_in_line_from;
|
|
ArraysResize(m_selected_line_to,new_size);
|
|
//--- Добавить данные в массивы структуры строки-приёмника
|
|
PasteWrapSymbols(m_selected_line_to,m_selected_symbol_to,array);
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Сместим строки вверх на количество удаляемых строк
|
|
MoveLines(m_selected_line_to+1,lines_total-lines_to_delete,lines_to_delete,false);
|
|
//--- Установим новый размер массиву строк
|
|
::ArrayResize(m_lines,lines_total-lines_to_delete);
|
|
}
|
|
//--- Если начальная строка выше конечной
|
|
else
|
|
{
|
|
//--- Скопируем в массив символы, которые нужно перенести
|
|
string array[];
|
|
CopyWrapSymbols(m_selected_line_to,m_selected_symbol_to,symbols_to_delete_in_line_to,array);
|
|
//--- Установим новый размер строке-приёмнику
|
|
uint new_size=m_selected_symbol_from+symbols_to_delete_in_line_to;
|
|
ArraysResize(m_selected_line_from,new_size);
|
|
//--- Добавить данные в массивы структуры строки-приёмника
|
|
PasteWrapSymbols(m_selected_line_from,m_selected_symbol_from,array);
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Сместим строки вверх на количество удаляемых строк
|
|
MoveLines(m_selected_line_from+1,lines_total-lines_to_delete,lines_to_delete,false);
|
|
//--- Установим новый размер массиву строк
|
|
::ArrayResize(m_lines,lines_total-lines_to_delete);
|
|
//--- Переместить курсор на начальную позицию в выделении
|
|
SetTextCursor(m_selected_symbol_from,m_selected_line_from);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает высоту строки |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::LineHeight(void)
|
|
{
|
|
//--- Установим шрифт для отображения на холсте (нужно, чтобы получить высоту строки)
|
|
m_textbox.FontSet(CElement::Font(),-CElement::FontSize()*10,FW_NORMAL);
|
|
//--- Вернём высоту строки
|
|
return(m_textbox.TextHeight("|"));
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает ширину строки от начала до указанной позиции |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::LineWidth(const uint symbol_index,const uint line_index)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Получим размер массива символов указанной строки
|
|
uint symbols_total=::ArraySize(m_lines[l].m_symbol);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint s=(symbol_index<symbols_total)? symbol_index : symbols_total;
|
|
//--- Суммируем ширину всех символов
|
|
uint width=0;
|
|
for(uint i=0; i<s; i++)
|
|
width+=m_lines[l].m_width[i];
|
|
//--- Вернуть ширину строки
|
|
return(width);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает максимальную ширину строки |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::MaxLineWidth(void)
|
|
{
|
|
uint max_line_width=0;
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
for(uint i=0; i<lines_total; i++)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[i].m_symbol);
|
|
//--- Получим ширину строки
|
|
uint line_width=LineWidth(symbols_total,i);
|
|
//--- Сохраним максимальную ширину
|
|
if(line_width>max_line_width)
|
|
max_line_width=line_width;
|
|
}
|
|
//--- Вернуть максимальную ширину строки
|
|
return(max_line_width);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Смещает строки на одну позицию вверх |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ShiftOnePositionUp(void)
|
|
{
|
|
//--- Если включен перенос слов
|
|
if(m_word_wrap_mode)
|
|
{
|
|
//--- Индекс предыдущей строки
|
|
uint prev_line_index=m_text_cursor_y_pos-1;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[prev_line_index].m_symbol);
|
|
//--- Если предыдущая строка имеет признак окончания
|
|
if(m_lines[prev_line_index].m_end_of_line)
|
|
{
|
|
//--- (1) Уберём признак окончания и (2) переместим текстовый курсор в конец строки
|
|
m_lines[prev_line_index].m_end_of_line=false;
|
|
SetTextCursor(symbols_total,prev_line_index);
|
|
}
|
|
else
|
|
{
|
|
//--- (1) Переместим текстовый курсор в конец строки и (2) удалим символ
|
|
SetTextCursor(symbols_total,prev_line_index);
|
|
DeleteSymbol();
|
|
}
|
|
return;
|
|
}
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Если есть символы в этой строке, запомним их, чтобы добавить к предыдущей строке
|
|
m_temp_input_string=(symbols_total>0)? CollectString(m_text_cursor_y_pos) : "";
|
|
//--- Сместим строки от следующего элемента на одну строку вверх
|
|
MoveLines(m_text_cursor_y_pos,lines_total-1,1,false);
|
|
//--- Установим новый размер массиву строк
|
|
::ArrayResize(m_lines,lines_total-1);
|
|
//--- Уменьшим счётчик строк
|
|
m_text_cursor_y_pos--;
|
|
//--- Получим размер массива символов
|
|
symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Переместим курсор в конец
|
|
m_text_cursor_x_pos=symbols_total;
|
|
//--- Получим X-координату курсора
|
|
CalculateTextCursorX();
|
|
//--- Если есть строка, которую нужно добавить к предыдущей
|
|
if(m_temp_input_string!="")
|
|
AddToString(m_text_cursor_y_pos,m_temp_input_string);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Смещает строки на одну позицию вниз |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ShiftOnePositionDown(void)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Увеличим массив на один элемент
|
|
uint new_size=lines_total+1;
|
|
::ArrayResize(m_lines,new_size);
|
|
//--- Сместим строки от текущей позиции на один пункт вниз (начиная с конца массива)
|
|
MoveLines(lines_total,m_text_cursor_y_pos+1,1);
|
|
//--- Перенесём текст на новую строку
|
|
WrapTextToNewLine(m_text_cursor_y_pos,m_text_cursor_x_pos,true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Проверка наличия выделенного текста |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CheckSelectedText(const uint line_index,const uint symbol_index)
|
|
{
|
|
bool is_selected_text=false;
|
|
//--- Выйти, если нет выделенного текста
|
|
if(m_selected_line_from==WRONG_VALUE)
|
|
return(false);
|
|
//--- Если начальный индекс на строке ниже
|
|
if(m_selected_line_from>m_selected_line_to)
|
|
{
|
|
//--- Конечная строка и символ справа от конечного выделенного
|
|
if((int)line_index==m_selected_line_to && (int)symbol_index>=m_selected_symbol_to)
|
|
{ is_selected_text=true; }
|
|
//--- Начальная строка и символ слева от начального выделенного
|
|
else if((int)line_index==m_selected_line_from && (int)symbol_index<m_selected_symbol_from)
|
|
{ is_selected_text=true; }
|
|
//--- Промежуточная строка (выделяются все символы)
|
|
else if((int)line_index>m_selected_line_to && (int)line_index<m_selected_line_from)
|
|
{ is_selected_text=true; }
|
|
}
|
|
//--- Если начальный индекс на строке выше
|
|
else if(m_selected_line_from<m_selected_line_to)
|
|
{
|
|
//--- Конечная строка и символ слева от конечного выделенного
|
|
if((int)line_index==m_selected_line_to && (int)symbol_index<m_selected_symbol_to)
|
|
{ is_selected_text=true; }
|
|
//--- Начальная строка и символ справа от начального выделенного
|
|
else if((int)line_index==m_selected_line_from && (int)symbol_index>=m_selected_symbol_from)
|
|
{ is_selected_text=true; }
|
|
//--- Промежуточная строка (выделяются все символы)
|
|
else if((int)line_index<m_selected_line_to && (int)line_index>m_selected_line_from)
|
|
{ is_selected_text=true; }
|
|
}
|
|
//--- Если начальный и конечный индекс на одной строке
|
|
else
|
|
{
|
|
//--- Нашли проверяемую строку
|
|
if((int)line_index>=m_selected_line_to && (int)line_index<=m_selected_line_from)
|
|
{
|
|
//--- Если смещение курсора вправо и символ в выделенном диапазоне
|
|
if(m_selected_symbol_from>m_selected_symbol_to)
|
|
{
|
|
if((int)symbol_index>=m_selected_symbol_to && (int)symbol_index<m_selected_symbol_from)
|
|
is_selected_text=true;
|
|
}
|
|
//--- Если смещение курсора влево и символ в выделенном диапазоне
|
|
else
|
|
{
|
|
if((int)symbol_index>=m_selected_symbol_from && (int)symbol_index<m_selected_symbol_to)
|
|
is_selected_text=true;
|
|
}
|
|
}
|
|
}
|
|
//--- Вернуть результат
|
|
return(is_selected_text);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Проверка на наличие обязательной первой строки |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::CheckFirstLine(void)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Если нет ни одной строки, устанавливаем размер массивам структуры
|
|
if(lines_total<1)
|
|
::ArrayResize(m_lines,++lines_total);
|
|
//--- Вернуть количество строк
|
|
return(lines_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Устанавливает новый размер массивам свойств указанной строки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ArraysResize(const uint line_index,const uint new_size)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Резервный размер массива
|
|
int reserve_size=100;
|
|
//--- Устанавливаем размер массивам структуры
|
|
::ArrayResize(m_lines[line_index].m_symbol,new_size,reserve_size);
|
|
::ArrayResize(m_lines[line_index].m_width,new_size,reserve_size);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Делает копию указанной (source) строки в новое место (dest.) |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::LineCopy(const uint destination,const uint source)
|
|
{
|
|
::ArrayCopy(m_lines[destination].m_width,m_lines[source].m_width);
|
|
::ArrayCopy(m_lines[destination].m_symbol,m_lines[source].m_symbol);
|
|
m_lines[destination].m_end_of_line=m_lines[source].m_end_of_line;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Очищает указанную строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ClearLine(const uint line_index)
|
|
{
|
|
::ArrayFree(m_lines[line_index].m_symbol);
|
|
::ArrayFree(m_lines[line_index].m_width);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора в указанном направлении |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursor(const ENUM_MOVE_TEXT_CURSOR direction)
|
|
{
|
|
switch(direction)
|
|
{
|
|
//--- Переместить курсор на один символ влево
|
|
case TO_NEXT_LEFT_SYMBOL : MoveTextCursorToLeft(); break;
|
|
//--- Переместить курсор на один символ вправо
|
|
case TO_NEXT_RIGHT_SYMBOL : MoveTextCursorToRight(); break;
|
|
//--- Переместить курсор на одно слово влево
|
|
case TO_NEXT_LEFT_WORD : MoveTextCursorToLeft(true); break;
|
|
//--- Переместить курсор на одно слово вправо
|
|
case TO_NEXT_RIGHT_WORD : MoveTextCursorToRight(true); break;
|
|
//--- Переместить курсор на одну строку вверх
|
|
case TO_NEXT_UP_LINE : MoveTextCursorToUp(); break;
|
|
//--- Переместить курсор на одну строку вниз
|
|
case TO_NEXT_DOWN_LINE : MoveTextCursorToDown(); break;
|
|
//--- Переместить курсор в начало текущей строки
|
|
case TO_BEGIN_LINE : SetTextCursor(0,m_text_cursor_y_pos); break;
|
|
//--- Переместить курсор в конец текущей строки
|
|
case TO_END_LINE :
|
|
{
|
|
//--- Получим количество символов в текущей строке
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Переместить курсор
|
|
SetTextCursor(symbols_total,m_text_cursor_y_pos);
|
|
break;
|
|
}
|
|
//--- Переместить курсор в начало первой строки
|
|
case TO_BEGIN_FIRST_LINE : SetTextCursor(0,0); break;
|
|
//--- Переместить курсор в конец последней строки
|
|
case TO_END_LAST_LINE :
|
|
{
|
|
//--- Получим количество строк и символов в последней строке
|
|
uint lines_total =::ArraySize(m_lines);
|
|
uint symbols_total =::ArraySize(m_lines[lines_total-1].m_symbol);
|
|
//--- Переместить курсор
|
|
SetTextCursor(symbols_total,lines_total-1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора в указанном направлении и |
|
|
//| с условием |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursor(const ENUM_MOVE_TEXT_CURSOR direction,const bool with_highlighted_text)
|
|
{
|
|
//--- Если только перемещение текстового курсора
|
|
if(!with_highlighted_text)
|
|
{
|
|
//--- Сброс выделения
|
|
ResetSelectedText();
|
|
//--- Переместить курсор в начало первой строки
|
|
MoveTextCursor(direction);
|
|
}
|
|
//--- Если с выделением текста
|
|
else
|
|
{
|
|
//--- Установить начальные индексы для выделенния текста
|
|
SetStartSelectedTextIndexes();
|
|
//--- Сместить текстовый курсор на один символ
|
|
MoveTextCursor(direction);
|
|
//--- Установить конечные индексы для выделения текста
|
|
SetEndSelectedTextIndexes();
|
|
}
|
|
//--- Корректируем полосы прокрутки
|
|
CorrectingHorizontalScrollThumb();
|
|
CorrectingVerticalScrollThumb();
|
|
//--- Обновить текст в поле ввода
|
|
DrawTextAndCursor(true);
|
|
//--- Отправим сообщение об этом
|
|
::EventChartCustom(m_chart_id,ON_MOVE_TEXT_CURSOR,CElementBase::Id(),CElementBase::Index(),TextCursorInfo());
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора влево |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursorToLeft(const bool to_next_word=false)
|
|
{
|
|
//--- Если перейти к следующему символу
|
|
if(!to_next_word)
|
|
{
|
|
//--- Если позиция текстового курсора больше нуля
|
|
if(m_text_cursor_x_pos>0)
|
|
{
|
|
//--- Сместим его на предыдущий символ
|
|
m_text_cursor_x-=m_lines[m_text_cursor_y_pos].m_width[m_text_cursor_x_pos-1];
|
|
//--- Уменьшим счётчик символов
|
|
m_text_cursor_x_pos--;
|
|
}
|
|
else
|
|
{
|
|
//--- Если это не первая строка
|
|
if(m_text_cursor_y_pos>0)
|
|
{
|
|
//--- Перейдём в конец предыдущей строки
|
|
m_text_cursor_y_pos--;
|
|
CorrectingTextCursorXPos();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Получим количество символов в текущей строке
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Если курсор в начале текущей строки и это не первая строка,
|
|
// переместим курсор в конец предыдущей строки
|
|
if(m_text_cursor_x_pos==0 && m_text_cursor_y_pos>0)
|
|
{
|
|
//--- Получим индекс предыдущей строки
|
|
uint prev_line_index=m_text_cursor_y_pos-1;
|
|
//--- Получим количество символов предыдущей строки
|
|
symbols_total=::ArraySize(m_lines[prev_line_index].m_symbol);
|
|
//--- Переместим курсор в конец предыдущей строки
|
|
SetTextCursor(symbols_total,prev_line_index);
|
|
}
|
|
//--- Если курсор не в начале текущей строки или курсор на первой строке
|
|
else
|
|
{
|
|
//--- Найдём начало непрерывной последовательности символов (справа налево)
|
|
for(uint i=m_text_cursor_x_pos; i<=symbols_total; i--)
|
|
{
|
|
//--- Перейти к следующему, если курсор в конце строки
|
|
if(i==symbols_total)
|
|
continue;
|
|
//--- Если это первый символ строки
|
|
if(i==0)
|
|
{
|
|
//--- Установим курсор в начало строки
|
|
SetTextCursor(0,m_text_cursor_y_pos);
|
|
break;
|
|
}
|
|
//--- Если это не первый символ строки
|
|
else
|
|
{
|
|
//--- Если нашли начало непрерывной последовательности, на которой впервые.
|
|
// Началом считается пробел на следующем индексе.
|
|
if(i!=m_text_cursor_x_pos &&
|
|
m_lines[m_text_cursor_y_pos].m_symbol[i]!=SPACE &&
|
|
m_lines[m_text_cursor_y_pos].m_symbol[i-1]==SPACE)
|
|
{
|
|
//--- Установим курсор в начало новой непрерывной последовательности
|
|
SetTextCursor(i,m_text_cursor_y_pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора на один символ вправо |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursorToRight(const bool to_next_word=false)
|
|
{
|
|
//--- Если перейти к следующему символу
|
|
if(!to_next_word)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_width);
|
|
//--- Если это не конец строки
|
|
if(m_text_cursor_x_pos<symbols_total)
|
|
{
|
|
//--- Сместим позицию текстового курсора на следующий символ
|
|
m_text_cursor_x+=m_lines[m_text_cursor_y_pos].m_width[m_text_cursor_x_pos];
|
|
//--- Увеличим счётчик символов
|
|
m_text_cursor_x_pos++;
|
|
}
|
|
else
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Если это не последняя строка
|
|
if(m_text_cursor_y_pos<lines_total-1)
|
|
{
|
|
//--- Переместить курсор в начало следующей строки
|
|
m_text_cursor_x=m_text_x_offset;
|
|
SetTextCursor(0,++m_text_cursor_y_pos);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Получим количество символов в текущей строке
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_symbol);
|
|
//--- Если курсор в конце строки и это не последняя строка, переместим курсор в начало следующей строки
|
|
if(m_text_cursor_x_pos==symbols_total && m_text_cursor_y_pos<lines_total-1)
|
|
{
|
|
SetTextCursor(0,m_text_cursor_y_pos+1);
|
|
}
|
|
//--- Если курсор не в конце строки или это последняя строка
|
|
else
|
|
{
|
|
//--- Найдём начало непрерывной последовательности символов (слева направо)
|
|
for(uint i=m_text_cursor_x_pos; i<=symbols_total; i++)
|
|
{
|
|
//--- Если это первый символ, перейти к следующему
|
|
if(i==0)
|
|
continue;
|
|
//--- Если дошли до конца строки, переместить курсор в конец
|
|
if(i>=symbols_total-1)
|
|
{
|
|
SetTextCursor(symbols_total,m_text_cursor_y_pos);
|
|
break;
|
|
}
|
|
//--- Если нашли начало непрерывной последовательности, на которой впервые.
|
|
// Началом считается пробел на предыдущем индексе.
|
|
if(i!=m_text_cursor_x_pos &&
|
|
m_lines[m_text_cursor_y_pos].m_symbol[i]!=SPACE &&
|
|
m_lines[m_text_cursor_y_pos].m_symbol[i-1]==SPACE)
|
|
{
|
|
//--- Установим курсор в конец новой непрерывной последовательности
|
|
SetTextCursor(i,m_text_cursor_y_pos);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора на одну строку вверх |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursorToUp(void)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Если не выходим за пределы массива
|
|
if(m_text_cursor_y_pos-1<lines_total)
|
|
{
|
|
//--- Переход на предыдущую строку
|
|
m_text_cursor_y_pos--;
|
|
//--- Корректировка текстового курсора по оси X
|
|
CorrectingTextCursorXPos(m_text_cursor_x_pos);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение текстового курсора на одну строку вниз |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveTextCursorToDown(void)
|
|
{
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Если не выходим за пределы массива
|
|
if(m_text_cursor_y_pos+1<lines_total)
|
|
{
|
|
//--- Переход на следующую строку
|
|
m_text_cursor_y_pos++;
|
|
//--- Корректировка текстового курсора по оси X
|
|
CorrectingTextCursorXPos(m_text_cursor_x_pos);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Устанавливает курсор по указанным позициям |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SetTextCursor(const uint x_pos,const uint y_pos)
|
|
{
|
|
m_text_cursor_x_pos=x_pos;
|
|
m_text_cursor_y_pos=(!m_multi_line_mode)? 0 : y_pos;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Устанавливает курсор по указанным позициям по курсору мыши |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::SetTextCursorByMouseCursor(void)
|
|
{
|
|
//--- Определим координаты на поле ввода под курсором мыши
|
|
int x =m_mouse.RelativeX(m_textbox);
|
|
int y =m_mouse.RelativeY(m_textbox);
|
|
//--- Получим высоту строки
|
|
int line_height=(int)LineHeight();
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Определим символ нажатия
|
|
for(uint l=0; l<lines_total; l++)
|
|
{
|
|
//--- Зададим начальные координаты для проверки условия
|
|
int x_offset=m_text_x_offset;
|
|
int y_offset=m_text_y_offset+((int)l*line_height);
|
|
//--- Проверка условия по оси Y
|
|
bool y_pos_check=(l<lines_total-1)?(y>=y_offset && y<y_offset+line_height) : y>=y_offset;
|
|
//--- Если нажатие было не на этой строке, перейти к следующей
|
|
if(!y_pos_check)
|
|
continue;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[l].m_width);
|
|
//--- Если это пустая строка, переместить курсор на указанную позицию и выйти из цикла
|
|
if(symbols_total<1)
|
|
{
|
|
SetTextCursor(0,l);
|
|
HorizontalScrolling(0);
|
|
break;
|
|
}
|
|
//--- Найдём символ, на который нажали
|
|
for(uint s=0; s<symbols_total; s++)
|
|
{
|
|
//--- Если нашли символ, переместить курсор на указанную позицию и выйти из цикла
|
|
if(x>=x_offset && x<x_offset+m_lines[l].m_width[s])
|
|
{
|
|
SetTextCursor(s,l);
|
|
l=lines_total;
|
|
break;
|
|
}
|
|
//--- Прибавить ширину текущего символа для следующей проверки
|
|
x_offset+=m_lines[l].m_width[s];
|
|
//--- Если это последний символ, переместим курсор в конец строки и выйдем из цикла
|
|
if(s==symbols_total-1 && x>x_offset)
|
|
{
|
|
SetTextCursor(s+1,l);
|
|
l=lines_total;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Корректировка текстового курсора по оси X |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CorrectingTextCursorXPos(const int x_pos=WRONG_VALUE)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[m_text_cursor_y_pos].m_width);
|
|
//--- Опеределим позицию курсора
|
|
uint text_cursor_x_pos=0;
|
|
//--- Если позиция указана
|
|
if(x_pos!=WRONG_VALUE)
|
|
text_cursor_x_pos=(x_pos>(int)symbols_total-1)? symbols_total : x_pos;
|
|
//--- Если позиция не указана, то установим курсор в конец строки
|
|
else
|
|
text_cursor_x_pos=symbols_total;
|
|
//--- Нулевая позиция, если в строке нет символов
|
|
m_text_cursor_x_pos=(symbols_total<1)? 0 : text_cursor_x_pos;
|
|
//--- Получим X-координату курсора
|
|
CalculateTextCursorX();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт X-координаты для текстового курсора |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateTextCursorX(void)
|
|
{
|
|
//--- Получим ширину строки
|
|
int line_width=(int)LineWidth(m_text_cursor_x_pos,m_text_cursor_y_pos);
|
|
//--- Рассчитать и сохранить X-координату курсора
|
|
m_text_cursor_x=m_text_x_offset+line_width;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт Y-координаты для текстового курсора |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateTextCursorY(void)
|
|
{
|
|
//--- Получим высоту строки
|
|
int line_height=(int)LineHeight();
|
|
//--- Получим Y-координату курсора
|
|
m_text_cursor_y=m_text_y_offset+int(line_height*m_text_cursor_y_pos);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт границ поля ввода по двум осям |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateBoundaries(void)
|
|
{
|
|
CalculateXBoundaries();
|
|
CalculateYBoundaries();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт границ поля ввода по оси X |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateXBoundaries(void)
|
|
{
|
|
//--- Получим X-координату и смещение по оси X
|
|
int x =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XDISTANCE);
|
|
int xoffset =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET);
|
|
//--- Рассчитаем границы видимой части поля ввода
|
|
m_x_limit =(x+xoffset)-x;
|
|
m_x2_limit =(m_multi_line_mode)? (x+xoffset+m_x_size-m_scrollv.ScrollWidth()-m_text_x_offset)-x : (x+xoffset+m_x_size-m_text_x_offset)-x;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт границ поля ввода по оси Y |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateYBoundaries(void)
|
|
{
|
|
//--- Выйти, если отключен многострочный режим
|
|
if(!m_multi_line_mode)
|
|
return;
|
|
//--- Получим Y-координату и смещение по оси Y
|
|
int y =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YDISTANCE);
|
|
int yoffset =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YOFFSET);
|
|
//--- Рассчитаем границы видимой части поля ввода
|
|
m_y_limit =(y+yoffset)-y;
|
|
m_y2_limit =(y+yoffset+m_y_size-m_scrollh.ScrollWidth())-y;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт X-координаты полосы прокрутки в левой границе поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollThumbX(void)
|
|
{
|
|
return(m_text_cursor_x-m_text_x_offset);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт X-координаты полосы прокрутки в правой границе поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollThumbX2(void)
|
|
{
|
|
return((m_multi_line_mode)? m_text_cursor_x-m_x_size+m_scrollv.ScrollWidth()+m_text_x_offset : m_text_cursor_x-m_x_size+m_text_x_offset*2);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт X-позиции ползунка полосы прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollPosX(const bool to_right=false)
|
|
{
|
|
int calc_x =(!to_right)? CalculateScrollThumbX() : CalculateScrollThumbX2();
|
|
double pos_x_value =(calc_x-::fmod((double)calc_x,(double)m_shift_x_step))/m_shift_x_step+((!to_right)? 0 : 1);
|
|
//---
|
|
return((int)pos_x_value);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт Y-координаты полосы прокрутки в верхней границе поля ввода|
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollThumbY(void)
|
|
{
|
|
return(m_text_cursor_y-m_text_y_offset);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт Y-координаты полосы прокрутки в нижней границе поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollThumbY2(void)
|
|
{
|
|
//--- Установим шрифт для отображения на холсте (нужно, чтобы получить высоту строки)
|
|
m_textbox.FontSet(CElement::Font(),-CElement::FontSize()*10,FW_NORMAL);
|
|
//--- Получим высоту строки
|
|
int line_height=m_textbox.TextHeight("|");
|
|
//--- Рассчитать и вернуть значение
|
|
return(m_text_cursor_y-m_y_size+m_scrollh.ScrollWidth()+m_text_y_offset+line_height);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Расчёт Y-позиции ползунка полосы прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
int CTextBox::CalculateScrollPosY(const bool to_down=false)
|
|
{
|
|
int calc_y =(!to_down)? CalculateScrollThumbY() : CalculateScrollThumbY2();
|
|
double pos_y_value =(calc_y-::fmod((double)calc_y,(double)LineHeight()))/LineHeight()+((!to_down)? 0 : 1);
|
|
//---
|
|
return((int)pos_y_value);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Корректировка горизонтальной полосы прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CorrectingHorizontalScrollThumb(void)
|
|
{
|
|
//--- Получим границы видимой части поля ввода
|
|
CalculateXBoundaries();
|
|
//--- Получим X-координату курсора
|
|
CalculateTextCursorX();
|
|
//--- Если текстовый курсор вышел из поля видимости влево
|
|
if(m_text_cursor_x<=m_x_limit)
|
|
{
|
|
HorizontalScrolling(CalculateScrollPosX());
|
|
}
|
|
//--- Если текстовый курсор вышел из поля видимости вправо
|
|
else if(m_text_cursor_x>=m_x2_limit)
|
|
{
|
|
HorizontalScrolling(CalculateScrollPosX(true));
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Корректировка вертикальной полосы прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CorrectingVerticalScrollThumb(void)
|
|
{
|
|
//--- Получим границы видимой части поля ввода
|
|
CalculateYBoundaries();
|
|
//--- Получим Y-координату курсора
|
|
CalculateTextCursorY();
|
|
//--- Если текстовый курсор вышел из поля видимости вверх
|
|
if(m_text_cursor_y<=m_y_limit)
|
|
{
|
|
VerticalScrolling(CalculateScrollPosY());
|
|
}
|
|
//--- Если текстовый курсор вышел из поля видимости вниз
|
|
else if(m_text_cursor_y+(int)LineHeight()>=m_y2_limit)
|
|
{
|
|
VerticalScrolling(CalculateScrollPosY(true));
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рассчитывает размеры текстового поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CalculateTextBoxSize(void)
|
|
{
|
|
CalculateTextBoxXSize();
|
|
CalculateTextBoxYSize();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рассчитывает ширину текстового поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CalculateTextBoxXSize(void)
|
|
{
|
|
//--- Запомним текущие размеры
|
|
int area_x_size_curr=m_area_x_size;
|
|
//--- Получим максимальную ширину строки из текстового поля ввода
|
|
int max_line_width=int((m_text_x_offset*2)+MaxLineWidth()+m_scrollv.ScrollWidth());
|
|
//--- Определим общую ширину
|
|
m_area_x_size=(max_line_width>m_x_size)? max_line_width : m_x_size;
|
|
//--- Определим видимую ширину
|
|
m_area_visible_x_size=m_x_size-2;
|
|
//--- Сохраним ограничение по смещению
|
|
m_shift_x2_limit=m_area_x_size-m_area_visible_x_size;
|
|
//--- Признак того, что размеры не изменились
|
|
if(area_x_size_curr==m_area_x_size)
|
|
return(false);
|
|
//--- Признак того, что размеры были изменились
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Рассчитывает высоту текстового поля ввода |4
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CalculateTextBoxYSize(void)
|
|
{
|
|
//--- Запомним текущие размеры
|
|
int area_y_size_curr=m_area_y_size;
|
|
//--- Получим высоту строки
|
|
int line_height=(int)LineHeight();
|
|
//--- Получим размер массива строк
|
|
int lines_total=::ArraySize(m_lines);
|
|
//--- Рассчитаем общую высоту элемента
|
|
int lines_height=int((m_text_y_offset*2)+(line_height*lines_total)+m_scrollh.ScrollWidth());//*2);
|
|
//--- Определим общую высоту
|
|
m_area_y_size=(m_multi_line_mode && lines_height>m_y_size)? lines_height : m_y_size;
|
|
//--- Определим видимую высоту
|
|
m_area_visible_y_size=m_y_size-2;
|
|
//--- Сохраним ограничение по смещению
|
|
m_shift_y2_limit=m_area_y_size-m_area_visible_y_size;
|
|
//--- Признак того, что размеры не изменились
|
|
if(area_y_size_curr==m_area_y_size)
|
|
return(false);
|
|
//--- Признак того, что размеры были изменились
|
|
return(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменить основные размеры элемента |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeMainSize(const int x_size,const int y_size)
|
|
{
|
|
//--- Установить новый размер
|
|
CElementBase::XSize(x_size);
|
|
CElementBase::YSize(y_size);
|
|
m_canvas.XSize(m_x_size);
|
|
m_canvas.YSize(m_y_size);
|
|
m_canvas.Resize(m_x_size,m_y_size);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменить размеры поля ввода |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeTextBoxSize(const bool is_x_offset=false,const bool is_y_offset=false)
|
|
{
|
|
//--- Установить новый размер таблице
|
|
m_textbox.XSize(m_area_x_size);
|
|
m_textbox.YSize(m_area_y_size);
|
|
m_textbox.Resize(m_area_x_size,m_area_y_size);
|
|
//--- Установим размеры видимой области
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XSIZE,m_area_visible_x_size);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YSIZE,m_area_visible_y_size);
|
|
//--- Разница между общей шириной и видимой частью
|
|
int x_different =m_area_x_size-m_area_visible_x_size;
|
|
int y_different =m_area_y_size-m_area_visible_y_size;
|
|
//--- Зададим смещение фрейма внутри изображения по осям X и Y
|
|
int x_offset =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET);
|
|
int y_offset =(int)::ObjectGetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YOFFSET);
|
|
int x_offset2 =(!is_x_offset)? 0 : (x_offset<=x_different)? x_offset : x_different;
|
|
int y_offset2 =(!is_y_offset)? 0 : (y_offset<=y_different)? y_offset : y_different;
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_XOFFSET,x_offset2);
|
|
::ObjectSetInteger(m_chart_id,m_textbox.ChartObjectName(),OBJPROP_YOFFSET,y_offset2);
|
|
//--- Изменить размеры полос прокрутки
|
|
ChangeScrollsSize();
|
|
//--- Перенос по словам
|
|
WordWrap();
|
|
//--- Корректировка данных
|
|
ShiftData();
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменить размеры полос прокрутки |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeScrollsSize(void)
|
|
{
|
|
//--- Расчёт количества шагов для смещения
|
|
uint x_size_total =m_area_x_size/m_shift_x_step;
|
|
uint visible_x_size_total =m_area_visible_x_size/m_shift_x_step;
|
|
uint y_size_total =LinesTotal()+1;
|
|
uint visible_y_size_total =VisibleLinesTotal();
|
|
//--- Рассчитать размеры полос прокрутки
|
|
m_scrollh.Reinit(x_size_total,visible_x_size_total);
|
|
m_scrollv.Reinit(y_size_total,visible_y_size_total);
|
|
//--- Выйти, если это однострочное поле ввода
|
|
if(!m_multi_line_mode)
|
|
return;
|
|
//--- Если (1) горизонтальная полоса прокрутки не нужна или (2) включен перенос по словам
|
|
if(!m_scrollh.IsScroll() || m_word_wrap_mode)
|
|
{
|
|
HorizontalScrolling(0);
|
|
//--- Скрыть горизонтальную полосу прокрутки
|
|
m_scrollh.Hide();
|
|
//--- Изменить высоту вертикальной полосы прокрутки
|
|
if(m_multi_line_mode)
|
|
m_scrollv.ChangeYSize(CElementBase::YSize()-2);
|
|
}
|
|
else
|
|
{
|
|
//--- Показать горизонтальную полосу прокрутки
|
|
if(CElementBase::IsVisible())
|
|
{
|
|
m_scrollh.Show();
|
|
m_scrollh.GetIncButtonPointer().Show();
|
|
m_scrollh.GetDecButtonPointer().Show();
|
|
//--- Отправим сообщение об изменении в графическом интерфейсе
|
|
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
|
|
}
|
|
//--- Рассчитать и изменить высоту вертикальной полосы прокрутки
|
|
if(m_multi_line_mode)
|
|
m_scrollv.ChangeYSize(CElementBase::YSize()-m_scrollh.ScrollWidth()-2);
|
|
}
|
|
//--- Если вертикальная полоса прокрутки не нужна
|
|
if(!m_scrollv.IsScroll())
|
|
{
|
|
VerticalScrolling(0);
|
|
//--- Скрыть вертикальную полосу прокрутки
|
|
m_scrollv.Hide();
|
|
//--- Изменить ширину горизонтальной полосы прокрутки, если отключен перенос по словам
|
|
if(!m_word_wrap_mode)
|
|
m_scrollh.ChangeXSize(CElementBase::XSize()-1);
|
|
}
|
|
else
|
|
{
|
|
//--- Показать вертикальную полосу прокрутки
|
|
if(CElementBase::IsVisible())
|
|
{
|
|
m_scrollv.Show();
|
|
m_scrollv.GetIncButtonPointer().Show();
|
|
m_scrollv.GetDecButtonPointer().Show();
|
|
//--- Отправим сообщение об изменении в графическом интерфейсе
|
|
::EventChartCustom(m_chart_id,ON_CHANGE_GUI,CElementBase::Id(),0,"");
|
|
}
|
|
//--- Изменить ширину горизонтальной полосы прокрутки, если отключен перенос по словам
|
|
if(!m_word_wrap_mode)
|
|
m_scrollh.ChangeXSize(CElementBase::XSize()-m_scrollh.ScrollWidth()-1);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перенос по словам |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::WordWrap(void)
|
|
{
|
|
//--- Выйти, если режимы (1) многострочного поля ввода или (2) переноса по словам отключены
|
|
if(!m_multi_line_mode || !m_word_wrap_mode)
|
|
return;
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Проверим, нужно ли выровнять текст по ширине поля ввода
|
|
for(uint i=0; i<lines_total; i++)
|
|
{
|
|
//--- Для определения первых видимых индексов (1) символа и (2) пробела
|
|
int symbol_index =WRONG_VALUE;
|
|
int space_index =WRONG_VALUE;
|
|
//--- Индекс следующей строки
|
|
uint next_line_index=i+1;
|
|
//--- Если строка не помещается, то перенесём часть текущей строки на новую строку
|
|
if(CheckForOverflow(i,symbol_index,space_index))
|
|
{
|
|
//--- Если пробел найден, то он переносится не будет
|
|
if(space_index!=WRONG_VALUE)
|
|
space_index++;
|
|
//--- Увеличим массив строк на один элемент
|
|
::ArrayResize(m_lines,++lines_total);
|
|
//--- Сместим строки от текущей позиции на один пункт вниз
|
|
MoveLines(lines_total-1,next_line_index,1);
|
|
//--- Проверим индекс символа, от которого будет перенос текста
|
|
int check_index=(space_index==WRONG_VALUE && symbol_index!=WRONG_VALUE)? symbol_index : space_index;
|
|
//--- Перенесём текст на новую строку
|
|
WrapTextToNewLine(i,check_index);
|
|
}
|
|
//--- Если строка помещается, то проверим, не нужно ли осуществить обратный перенос
|
|
else
|
|
{
|
|
//--- Пропускаем, если (1) это строка с окончанием или (2) это последняя строка
|
|
if(m_lines[i].m_end_of_line || next_line_index>=lines_total)
|
|
continue;
|
|
//--- Определим количество символов для переноса
|
|
uint wrap_symbols_total=0;
|
|
//--- Если нужно перенести оставшийся текст следующей строки на текущую
|
|
if(WrapSymbolsTotal(i,wrap_symbols_total))
|
|
{
|
|
WrapTextToPrevLine(next_line_index,wrap_symbols_total,true);
|
|
//--- Обновить размер массива для дальнейшего использования в цикле
|
|
lines_total=::ArraySize(m_lines);
|
|
//--- Шаг назад, чтобы избежать пропуск строки для следующей проверки
|
|
i--;
|
|
}
|
|
//--- Перенести только то, что помещается
|
|
else
|
|
WrapTextToPrevLine(next_line_index,wrap_symbols_total);
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Проверка на переполнение строки |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::CheckForOverflow(const uint line_index,int &symbol_index,int &space_index)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//--- Отступы
|
|
uint x_offset_plus=m_text_x_offset+m_scrollv.XSize();
|
|
//--- Получим полную ширину строки
|
|
uint full_line_width=LineWidth(symbols_total,line_index)+x_offset_plus;
|
|
//--- Если ширина этой строки помещается в поле
|
|
if(full_line_width<(uint)m_area_visible_x_size)
|
|
return(false);
|
|
//--- Определим индексы символов переполнения
|
|
for(uint s=symbols_total-1; s>0; s--)
|
|
{
|
|
//--- Получим (1) ширину подстроки от начала до текущего символа и (2) символ
|
|
uint line_width =LineWidth(s,line_index)+x_offset_plus;
|
|
string symbol =m_lines[line_index].m_symbol[s];
|
|
//--- Если ещё не нашли видимый символ
|
|
if(symbol_index==WRONG_VALUE)
|
|
{
|
|
//--- Если ширина подстроки помещается в область поля ввода, запомним индекс символа
|
|
if(line_width<(uint)m_area_visible_x_size)
|
|
symbol_index=(int)s;
|
|
//--- Перейти к следующему символу
|
|
continue;
|
|
}
|
|
//--- Если это пробел, запомним его индекс и остановим цикл
|
|
if(symbol==SPACE)
|
|
{
|
|
space_index=(int)s;
|
|
break;
|
|
}
|
|
}
|
|
//--- Выполнение условия означает, что строка не помещается
|
|
bool is_overflow=(symbol_index!=WRONG_VALUE || space_index!=WRONG_VALUE);
|
|
//--- Вернуть результат
|
|
return(is_overflow);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает количество слов в указанной строке |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::WordsTotal(const uint line_index)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Получим размер массива символов указанной строки
|
|
uint symbols_total=::ArraySize(m_lines[l].m_symbol);
|
|
//--- Счётчик слов
|
|
uint words_counter=0;
|
|
//--- Ищем пробел по указанному индексу
|
|
for(uint s=1; s<symbols_total; s++)
|
|
{
|
|
//--- Считаем, если (2) дошли до конца строки или (2) нашли пробел (конец слова)
|
|
if(s+1==symbols_total || (m_lines[l].m_symbol[s]!=SPACE && m_lines[l].m_symbol[s-1]==SPACE))
|
|
words_counter++;
|
|
}
|
|
//--- Вернуть количество слов
|
|
return((words_counter<1)? 1 : words_counter);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает количество переносимых символов с признаком объёма |
|
|
//+------------------------------------------------------------------+
|
|
bool CTextBox::WrapSymbolsTotal(const uint line_index,uint &wrap_symbols_total)
|
|
{
|
|
//--- Признаки (1) количества символов для переноса и (2) строки без пробелов
|
|
bool is_all_text=false,is_solid_row=false;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//--- Отступы
|
|
uint x_offset_plus=m_text_x_offset+m_scrollv.XSize();
|
|
//--- Получим полную ширину строки
|
|
uint full_line_width=LineWidth(symbols_total,line_index)+x_offset_plus;
|
|
//--- Получим ширину свободного пространства
|
|
uint free_space=m_area_visible_x_size-full_line_width;
|
|
//--- Получим количество слов в следующей строке
|
|
uint next_line_index =line_index+1;
|
|
uint words_total =WordsTotal(next_line_index);
|
|
//--- Получим размер массива символов
|
|
uint next_line_symbols_total=::ArraySize(m_lines[next_line_index].m_symbol);
|
|
//--- Определить количество слов, которые можно перенести со следующей строки (поиск по пробелу)
|
|
for(uint w=0; w<words_total; w++)
|
|
{
|
|
//--- Получим (1) индекс пробела и (2) ширину подстроки от начала до пробела
|
|
uint ss_index =SymbolIndexBySpaceNumber(next_line_index,w);
|
|
uint substring_width =LineWidth(ss_index,next_line_index);
|
|
//--- Если подстрока помещается в свободное пространство текущей строки
|
|
if(substring_width<free_space)
|
|
{
|
|
//--- ...проверим, можно ли добавить ещё одно слово
|
|
wrap_symbols_total=ss_index;
|
|
//--- Остановиться, если это вся строка
|
|
if(next_line_symbols_total==wrap_symbols_total)
|
|
{
|
|
is_all_text=true;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//--- Если это сплошная строка без пробела
|
|
if(ss_index==next_line_symbols_total)
|
|
is_solid_row=true;
|
|
//---
|
|
break;
|
|
}
|
|
}
|
|
//--- Сразу вернуть результат, если (1) это строка с пробелом или (2) нет свободного места
|
|
if(!is_solid_row || free_space<1)
|
|
return(is_all_text);
|
|
//--- Получим полную ширину следующей строки
|
|
full_line_width=LineWidth(next_line_symbols_total,next_line_index)+x_offset_plus;
|
|
//--- Если (1) строка не помещается и нет пробелов в конце (2) текущей и (3) предыдущей строках
|
|
if(full_line_width>free_space &&
|
|
m_lines[line_index].m_symbol[symbols_total-1]!=SPACE &&
|
|
m_lines[next_line_index].m_symbol[next_line_symbols_total-1]!=SPACE)
|
|
{
|
|
//--- Определить количество символов, которые можно перенести со следующей строки
|
|
for(uint s=next_line_symbols_total-1; s>=0; s--)
|
|
{
|
|
//--- Получим ширину подстроки от начала до указанного символа
|
|
uint substring_width=LineWidth(s,next_line_index);
|
|
//--- Если подстрока не помещается в свободное пространство указанного контейнера, перейти к следующему символу
|
|
if(substring_width>=free_space)
|
|
continue;
|
|
//--- Если подстрока помещается, запомним значение и остановимся
|
|
wrap_symbols_total=s;
|
|
break;
|
|
}
|
|
}
|
|
//--- Вернуть истину, если нужно перенести весь текст
|
|
return(is_all_text);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Возвращает индекс символа пробела по его номеру |
|
|
//+------------------------------------------------------------------+
|
|
uint CTextBox::SymbolIndexBySpaceNumber(const uint line_index,const uint space_index)
|
|
{
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Предотвращение выхода из диапазона
|
|
uint l=(line_index<lines_total)? line_index : lines_total-1;
|
|
//--- Получим размер массива символов указанной строки
|
|
uint symbols_total=::ArraySize(m_lines[l].m_symbol);
|
|
//--- (1) Для определения индекса символа пробела и (2) счётчик пробелов
|
|
uint symbol_index =0;
|
|
uint space_counter =0;
|
|
//--- Ищем пробел по указанному индексу
|
|
for(uint s=1; s<symbols_total; s++)
|
|
{
|
|
//--- Если нашли пробел
|
|
if(m_lines[l].m_symbol[s]!=SPACE && m_lines[l].m_symbol[s-1]==SPACE)
|
|
{
|
|
//--- Если счётчик равен указанному индексу пробела, запомним его и остановим цикл
|
|
if(space_counter==space_index)
|
|
{
|
|
symbol_index=s;
|
|
break;
|
|
}
|
|
//--- Увеличим счётчик пробелов
|
|
space_counter++;
|
|
}
|
|
}
|
|
//--- Вернуть размер строки, если не нашли индекс пробела
|
|
return((symbol_index<1)? symbols_total : symbol_index);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение строк на указанное количество позиций |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveLines(const uint from_index,const uint to_index,const uint count,const bool to_down=true)
|
|
{
|
|
//--- Смещение строк по направлению вниз
|
|
if(to_down)
|
|
{
|
|
for(uint i=from_index; i>to_index; i--)
|
|
{
|
|
//--- Индекс предыдущего элемента массива строк
|
|
uint prev_index=i-count;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[prev_index].m_symbol);
|
|
//--- Установим новый размер массивам
|
|
ArraysResize(i,symbols_total);
|
|
//--- Сделать копию строки
|
|
LineCopy(i,prev_index);
|
|
//--- Если это последняя итерация
|
|
if(prev_index==to_index)
|
|
{
|
|
//--- Выйти, если это первая строка
|
|
if(to_index<1)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//--- Смещение строк по направлению вверх
|
|
else
|
|
{
|
|
for(uint i=from_index; i<to_index; i++)
|
|
{
|
|
//--- Индекс следующего элемента массива строк
|
|
uint next_index=i+count;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[next_index].m_symbol);
|
|
//--- Установим новый размер массивам
|
|
ArraysResize(i,symbols_total);
|
|
//--- Сделать копию строки
|
|
LineCopy(i,next_index);
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перемещение символов в указанной строке |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::MoveSymbols(const uint line_index,const uint from_pos,const uint to_pos,const bool to_left=true)
|
|
{
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//--- Разница
|
|
uint offset=from_pos-to_pos;
|
|
//--- Если нужно сместить символы влево
|
|
if(to_left)
|
|
{
|
|
for(uint s=to_pos; s<symbols_total-offset; s++)
|
|
{
|
|
uint i=s+offset;
|
|
m_lines[line_index].m_symbol[s] =m_lines[line_index].m_symbol[i];
|
|
m_lines[line_index].m_width[s] =m_lines[line_index].m_width[i];
|
|
}
|
|
}
|
|
//--- Если нужно сместить символы вправо
|
|
else
|
|
{
|
|
for(uint s=symbols_total-1; s>to_pos; s--)
|
|
{
|
|
uint i=s-1;
|
|
m_lines[line_index].m_symbol[s] =m_lines[line_index].m_symbol[i];
|
|
m_lines[line_index].m_width[s] =m_lines[line_index].m_width[i];
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Добавляет текст в указанную строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::AddToString(const uint line_index,const string text)
|
|
{
|
|
//--- Переносим строку в массив
|
|
uchar array[];
|
|
int total=::StringToCharArray(text,array)-1;
|
|
if(total<0)
|
|
return;
|
|
//--- Получим размер массива символов
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//--- Установим новый размер массивам
|
|
uint new_size=symbols_total+total;
|
|
ArraysResize(line_index,new_size);
|
|
//--- Добавить данные в массивы структуры
|
|
for(uint i=symbols_total; i<new_size; i++)
|
|
{
|
|
m_lines[line_index].m_symbol[i] =::CharToString(array[i-symbols_total]);
|
|
m_lines[line_index].m_width[i] =m_textbox.TextWidth(m_lines[line_index].m_symbol[i]);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// Agregado
|
|
void CTextBox::InsertToString(const uint line_index, const uint start_pos, const string text)
|
|
{
|
|
//---
|
|
uchar array[];
|
|
int total=::StringToCharArray(text,array)-1;
|
|
if(total<0)
|
|
return;
|
|
//---
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//---
|
|
uint new_size=symbols_total+total;
|
|
ArraysResize(line_index,new_size);
|
|
//---
|
|
for(int i = (int)new_size - 1; i >= (int)(start_pos + total); i--)
|
|
{
|
|
uint source_index = i - total;
|
|
m_lines[line_index].m_symbol[i] = m_lines[line_index].m_symbol[source_index];
|
|
m_lines[line_index].m_width[i] = m_lines[line_index].m_width[source_index];
|
|
}
|
|
//---
|
|
for(uint i = 0; i < uint(total); i++)
|
|
{
|
|
uint target_index = start_pos + i;
|
|
m_lines[line_index].m_symbol[target_index] = ::CharToString(array[i]);
|
|
m_lines[line_index].m_width[target_index] = m_textbox.TextWidth(m_lines[line_index].m_symbol[target_index]);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Копирует в переданный массив символы для переноса |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::CopyWrapSymbols(const uint line_index,const uint start_pos,const uint symbols_total,string &array[])
|
|
{
|
|
//--- Установим размер массиву
|
|
::ArrayResize(array,symbols_total);
|
|
//--- Скопируем в массив символы, которые нужно перенести
|
|
for(uint i=0; i<symbols_total; i++)
|
|
array[i]=m_lines[line_index].m_symbol[start_pos+i];
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Вставляет символы в указанную строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::PasteWrapSymbols(const uint line_index,const uint start_pos,string &array[])
|
|
{
|
|
uint array_size=::ArraySize(array);
|
|
//--- Добавить данные в массивы структуры новой строки
|
|
for(uint i=0; i<array_size; i++)
|
|
{
|
|
uint s=start_pos+i;
|
|
m_lines[line_index].m_symbol[s] =array[i];
|
|
m_lines[line_index].m_width[s] =m_textbox.TextWidth(array[i]);
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перенос текста на новую строку |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::WrapTextToNewLine(const uint line_index,const uint symbol_index,const bool by_pressed_enter=false)
|
|
{
|
|
//--- Получим размер массива символов из строки
|
|
uint symbols_total=::ArraySize(m_lines[line_index].m_symbol);
|
|
//--- Последний индекс символа
|
|
uint last_symbol_index=symbols_total-1;
|
|
//--- Корректировка в случае пустой строки
|
|
uint check_symbol_index=(symbol_index>last_symbol_index && symbol_index!=symbols_total)? last_symbol_index : symbol_index;
|
|
//--- Индекс следующей строки
|
|
uint next_line_index=line_index+1;
|
|
//--- Количество символов, которые нужно перенести на новую строку
|
|
uint new_line_size=symbols_total-check_symbol_index;
|
|
//--- Скопируем в массив символы, которые нужно перенести
|
|
string array[];
|
|
CopyWrapSymbols(line_index,check_symbol_index,new_line_size,array);
|
|
//--- Установим новый размер массивам структуры в строке
|
|
ArraysResize(line_index,symbols_total-new_line_size);
|
|
//--- Установим новый размер массивам структуры в новой строке
|
|
ArraysResize(next_line_index,new_line_size);
|
|
//--- Добавить данные в массивы структуры новой строки
|
|
PasteWrapSymbols(next_line_index,0,array);
|
|
//--- Определим новое положение текстового курсора
|
|
int x_pos=int(new_line_size-(symbols_total-m_text_cursor_x_pos));
|
|
m_text_cursor_x_pos =(x_pos<0)? (int)m_text_cursor_x_pos : x_pos;
|
|
m_text_cursor_y_pos =(x_pos<0)? (int)line_index : (int)next_line_index;
|
|
//--- Если указано, что вызов по нажатию на клавише Enter
|
|
if(by_pressed_enter)
|
|
{
|
|
//--- Если строка имела признак окончания, то ставим признак окончания текущей и следующей
|
|
if(m_lines[line_index].m_end_of_line)
|
|
{
|
|
m_lines[line_index].m_end_of_line =true;
|
|
m_lines[next_line_index].m_end_of_line =true;
|
|
}
|
|
//--- Если нет, то только текущей
|
|
else
|
|
{
|
|
m_lines[line_index].m_end_of_line =true;
|
|
m_lines[next_line_index].m_end_of_line =false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//--- Если строка имела признак окончания, то продолжаем и устанавливаем признак на следующей строке
|
|
if(m_lines[line_index].m_end_of_line)
|
|
{
|
|
m_lines[line_index].m_end_of_line =false;
|
|
m_lines[next_line_index].m_end_of_line =true;
|
|
}
|
|
//--- Если строка не имела признак окончания, то продолжаем в обеих строках
|
|
else
|
|
{
|
|
m_lines[line_index].m_end_of_line =false;
|
|
m_lines[next_line_index].m_end_of_line =false;
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Перенос текста из следующей строки в текущую |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::WrapTextToPrevLine(const uint next_line_index,const uint wrap_symbols_total,const bool is_all_text=false)
|
|
{
|
|
//--- Получим размер массива символов из строки
|
|
uint symbols_total=::ArraySize(m_lines[next_line_index].m_symbol);
|
|
//--- Индекс предыдущей строки
|
|
uint prev_line_index=next_line_index-1;
|
|
//--- Скопируем в массив символы, которые нужно перенести
|
|
string array[];
|
|
CopyWrapSymbols(next_line_index,0,wrap_symbols_total,array);
|
|
//--- Получим размер массива символов из предыдущей строки
|
|
uint prev_line_symbols_total=::ArraySize(m_lines[prev_line_index].m_symbol);
|
|
//--- Увеличим размер массива предыдущей строки на добавляемое количество символов
|
|
uint new_prev_line_size=prev_line_symbols_total+wrap_symbols_total;
|
|
ArraysResize(prev_line_index,new_prev_line_size);
|
|
//--- Добавить данные в массивы структуры новой строки
|
|
PasteWrapSymbols(prev_line_index,new_prev_line_size-wrap_symbols_total,array);
|
|
//--- Сместим символы на освободившееся место в текущей строке
|
|
MoveSymbols(next_line_index,wrap_symbols_total,0);
|
|
//--- Уменьшим размер массива текущей строки на извлечённое из неё количество символов
|
|
ArraysResize(next_line_index,symbols_total-wrap_symbols_total);
|
|
//--- Скорректировать текстовый курсор
|
|
if((is_all_text && next_line_index==m_text_cursor_y_pos) ||
|
|
(!is_all_text && next_line_index==m_text_cursor_y_pos && wrap_symbols_total>0))
|
|
{
|
|
m_text_cursor_x_pos=new_prev_line_size-(wrap_symbols_total-m_text_cursor_x_pos);
|
|
m_text_cursor_y_pos--;
|
|
}
|
|
//--- Выйти, если это не весь оставшийся текст строки
|
|
if(!is_all_text)
|
|
return;
|
|
//--- Добавить признак оконачания для предыдущей строки, если у текущей строки он тоже есть
|
|
if(m_lines[next_line_index].m_end_of_line)
|
|
m_lines[next_line_index-1].m_end_of_line=true;
|
|
//--- Получим размер массива строк
|
|
uint lines_total=::ArraySize(m_lines);
|
|
//--- Сместим строки на одну вверх
|
|
MoveLines(next_line_index,lines_total-1,1,false);
|
|
//--- Установим новый размер массиву строк
|
|
::ArrayResize(m_lines,lines_total-1);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменить ширину по правому краю формы |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeWidthByRightWindowSide(void)
|
|
{
|
|
//--- Выйти, если включен режим фиксации к правому краю формы
|
|
if(m_anchor_right_window_side)
|
|
return;
|
|
//--- Координаты
|
|
int x=0;
|
|
//--- Размеры
|
|
int x_size =m_main.X2()-CElementBase::X()-m_auto_xresize_right_offset;
|
|
int y_size =(m_auto_yresize_mode)? m_main.Y2()-CElementBase::Y()-m_auto_yresize_bottom_offset : m_y_size;
|
|
//--- Установить новый размер
|
|
ChangeMainSize(x_size,y_size);
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
//--- В режиме переноса слов нужно повторно пересчитать и установить размеры
|
|
if(m_word_wrap_mode)
|
|
{
|
|
CalculateTextBoxSize();
|
|
ChangeTextBoxSize();
|
|
}
|
|
//--- Нарисовать текст и дезактивировать поле ввода
|
|
DeactivateTextBox();
|
|
//--- Перерисовать элемент
|
|
Draw();
|
|
if(m_scrollh.IsScroll())
|
|
m_scrollh.Update(true);
|
|
if(m_scrollv.IsScroll())
|
|
m_scrollv.Update(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Изменить высоту по нижнему краю окна |
|
|
//+------------------------------------------------------------------+
|
|
void CTextBox::ChangeHeightByBottomWindowSide(void)
|
|
{
|
|
//--- Выйти, если включен режим фиксации к нижнему краю формы
|
|
if(m_anchor_bottom_window_side)
|
|
return;
|
|
//--- Координаты
|
|
int y=0;
|
|
//--- Размеры
|
|
int x_size =(m_auto_xresize_mode)? m_main.X2()-CElementBase::X()-m_auto_xresize_right_offset : m_x_size;
|
|
int y_size =m_main.Y2()-CElementBase::Y()-m_auto_yresize_bottom_offset;
|
|
//--- Установить новый размер
|
|
ChangeMainSize(x_size,y_size);
|
|
//--- Рассчитать размеры поля ввода
|
|
CalculateTextBoxSize();
|
|
//--- Установить новый размер полю ввода
|
|
ChangeTextBoxSize();
|
|
//--- Нарисовать текст и дезактивировать поле ввода
|
|
DeactivateTextBox();
|
|
//--- Перерисовать элемент
|
|
Draw();
|
|
if(m_scrollh.IsScroll())
|
|
m_scrollh.Update(true);
|
|
if(m_scrollv.IsScroll())
|
|
m_scrollv.Update(true);
|
|
}
|
|
//+------------------------------------------------------------------+
|