//! \~\file piscreentiles.h
//! \~\ingroup Console
//! \brief
//! \~english Various tiles for PIScreen
//! \~russian Различные тайлы для PIScreen
//! \details
//! \~english Provides ready-to-use tile implementations for common UI elements.
//! \~russian Обеспечивает готовые к использованию реализации тайлов для общих элементов UI.
/*
    PIP - Platform Independent Primitives
    Various tiles for PIScreen
    Ivan Pelipenko peri4ko@yandex.ru

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PISCREENTILES_H
#define PISCREENTILES_H

#include "pip_console_export.h"
#include "piscreentile.h"


//! \~\ingroup Console
//! \~\brief
//! \~english Simple text tile with per-row formatting.
//! \~russian Простой текстовый тайл с форматированием по строкам.
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);

public:
	//! \~english Row text with cell format.
	//! \~russian Текст строки с форматом ячеек.
	typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;

	//! \~english Constructs an empty text tile.
	//! \~russian Создает пустой текстовый тайл.
	TileSimple(const PIString & n = PIString());

	//! \~english Constructs a text tile with one row.
	//! \~russian Создает текстовый тайл с одной строкой.
	TileSimple(const Row & r);

	//! \~english Destroys the text tile.
	//! \~russian Уничтожает текстовый тайл.
	virtual ~TileSimple() {}

	//! \~english Rows displayed by the tile.
	//! \~russian Строки, отображаемые тайлом.
	PIVector<Row> content;

	//! \~english Horizontal text alignment inside the tile.
	//! \~russian Горизонтальное выравнивание текста внутри тайла.
	PIScreenTypes::Alignment alignment;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
};


class TileList;

//! \~\ingroup Console
//! \~\brief
//! \~english Scroll bar tile used by list-like widgets.
//! \~russian Тайловая полоса прокрутки для списковых виджетов.
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
	friend class TileList;

public:
	//! \~english Constructs a scroll bar tile.
	//! \~russian Создает тайл полосы прокрутки.
	TileScrollBar(const PIString & n = PIString());

	//! \~english Destroys the scroll bar tile.
	//! \~russian Уничтожает тайл полосы прокрутки.
	virtual ~TileScrollBar() {}

	//! \~english Sets the minimum scroll value.
	//! \~russian Устанавливает минимальное значение прокрутки.
	void setMinimum(int v);

	//! \~english Sets the maximum scroll value.
	//! \~russian Устанавливает максимальное значение прокрутки.
	void setMaximum(int v);

	//! \~english Sets the current scroll value.
	//! \~russian Устанавливает текущее значение прокрутки.
	void setValue(int v);

	//! \~english Returns the minimum scroll value.
	//! \~russian Возвращает минимальное значение прокрутки.
	int minimum() const { return minimum_; }

	//! \~english Returns the maximum scroll value.
	//! \~russian Возвращает максимальное значение прокрутки.
	int maximum() const { return maximum_; }

	//! \~english Returns the current scroll value.
	//! \~russian Возвращает текущее значение прокрутки.
	int value() const { return value_; }

	//! \~english Thickness of the drawn bar in cells, perpendicular to the scroll direction.
	//! \~russian Толщина отрисовываемой полосы в ячейках поперек направления прокрутки.
	int thickness;

protected:
	void _check();
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
	bool mouseEvent(PIKbdListener::MouseEvent me) override;
	int minimum_, maximum_, value_;
	PIChar line_char;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Scrollable list tile with optional row selection.
//! \~russian Прокручиваемый тайл списка с необязательным выбором строк.
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileList, PIScreenTile);

public:
	//! \~english Selection policy for list rows.
	//! \~russian Режим выбора строк списка.
	enum SelectionMode {
		NoSelection /** \~english Rows are not selectable. \~russian Выбор строк отключен. */,
		SingleSelection /** \~english At most one row can be selected. \~russian Можно выбрать не более одной строки. */,
		MultiSelection /** \~english Multiple rows can be selected. \~russian Можно выбрать несколько строк. */
	};

	//! \~english Events emitted by the list tile.
	//! \~russian События, генерируемые тайлом списка.
	enum EventType {
		SelectionChanged /** \~english Selection set changed. \~russian Изменился набор выбранных строк. */,
		RowPressed /** \~english Current row was activated; event data stores the row index. \~russian Текущая строка была активирована; данные события содержат индекс строки. */
	};

	//! \~english Constructs a list tile with the specified selection mode.
	//! \~russian Создает тайл списка с указанным режимом выбора.
	TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection);

	//! \~english Destroys the list tile.
	//! \~russian Уничтожает тайл списка.
	virtual ~TileList() {}

	//! \~english Row text with cell format.
	//! \~russian Текст строки с форматом ячеек.
	typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;

	//! \~english Rows displayed by the list.
	//! \~russian Строки, отображаемые списком.
	PIDeque<Row> content;

	//! \~english Alignment used to draw row text.
	//! \~russian Выравнивание, используемое при рисовании текста строк.
	PIScreenTypes::Alignment alignment;

	//! \~english Active row selection mode.
	//! \~russian Текущий режим выбора строк.
	SelectionMode selection_mode;

	//! \~english Indexes of selected rows.
	//! \~russian Индексы выбранных строк.
	PISet<int> selected;

	//! \~english Cached count of visible content rows between the top and bottom scroll markers.
	//! \~russian Кэшированное количество видимых строк содержимого между верхней и нижней метками прокрутки.
	int lhei;

	//! \~english Index of the current row used for focus and activation.
	//! \~russian Индекс текущей строки, используемой для фокуса и активации.
	int cur;

	//! \~english Index of the first row currently visible in the viewport.
	//! \~russian Индекс первой строки, видимой в текущей области просмотра.
	int offset;

protected:
	void sizeHint(int & w, int & h) const override;
	void resizeEvent(int w, int h) override;
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
	bool mouseEvent(PIKbdListener::MouseEvent me) override;
	bool wheelEvent(PIKbdListener::WheelEvent we) override;
	TileScrollBar * scroll;
	bool mouse_sel;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Push button tile.
//! \~russian Тайл кнопки.
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileButton, PIScreenTile);

public:
	//! \~english Constructs a button tile.
	//! \~russian Создает тайл кнопки.
	TileButton(const PIString & n = PIString());

	//! \~english Destroys the button tile.
	//! \~russian Уничтожает тайл кнопки.
	virtual ~TileButton() {}

	//! \~english Events emitted by the button.
	//! \~russian События, генерируемые кнопкой.
	enum EventType {
		ButtonClicked /** \~english Button was activated. \~russian Кнопка была активирована. */
	};

	//! \~english Text format of the button label.
	//! \~russian Формат текста надписи кнопки.
	PIScreenTypes::CellFormat format;

	//! \~english Button caption.
	//! \~russian Подпись кнопки.
	PIString text;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
	bool mouseEvent(PIKbdListener::MouseEvent me) override;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Group of selectable buttons arranged in one tile.
//! \~russian Группа выбираемых кнопок, размещенных в одном тайле.
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);

public:
	//! \~english Constructs a button group tile.
	//! \~russian Создает тайл группы кнопок.
	TileButtons(const PIString & n = PIString());

	//! \~english Destroys the button group tile.
	//! \~russian Уничтожает тайл группы кнопок.
	virtual ~TileButtons() {}

	//! \~english Events emitted by the button group.
	//! \~russian События, генерируемые группой кнопок.
	enum EventType {
		ButtonSelected /** \~english A button was selected; event data stores the button index. \~russian Кнопка была выбрана; данные события содержат индекс кнопки. */
	};

	//! \~english Button caption with cell format.
	//! \~russian Подпись кнопки с форматом ячеек.
	typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;

	//! \~english Alignment of the whole button group inside the tile bounds.
	//! \~russian Выравнивание всей группы кнопок внутри границ тайла.
	PIScreenTypes::Alignment alignment;

	//! \~english Button definitions shown by the tile.
	//! \~russian Описания кнопок, отображаемых тайлом.
	PIVector<Button> content;

	//! \~english Index of the currently highlighted button.
	//! \~russian Индекс текущей подсвеченной кнопки.
	int cur;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
	bool mouseEvent(PIKbdListener::MouseEvent me) override;
	struct Rect {
		Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {}
		int x0, y0, x1, y1;
	};
	PIVector<Rect> btn_rects;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Check box tile.
//! \~russian Тайл флажка.
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);

public:
	//! \~english Constructs a check box tile.
	//! \~russian Создает тайл флажка.
	TileCheck(const PIString & n = PIString());

	//! \~english Destroys the check box tile.
	//! \~russian Уничтожает тайл флажка.
	virtual ~TileCheck() {}

	//! \~english Events emitted by the check box.
	//! \~russian События, генерируемые флажком.
	enum EventType {
		Toggled /** \~english Check state changed; event data stores the new boolean value. \~russian Состояние флажка изменилось; данные события содержат новое логическое значение. */
	};

	//! \~english Text format of the caption.
	//! \~russian Формат текста подписи.
	PIScreenTypes::CellFormat format;

	//! \~english Caption displayed after the check mark.
	//! \~russian Подпись, отображаемая после флажка.
	PIString text;

	//! \~english Current check state.
	//! \~russian Текущее состояние флажка.
	bool toggled;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
	bool mouseEvent(PIKbdListener::MouseEvent me) override;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Progress indicator tile.
//! \~russian Тайл индикатора прогресса.
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);

public:
	//! \~english Constructs a progress tile.
	//! \~russian Создает тайл прогресса.
	TileProgress(const PIString & n = PIString());

	//! \~english Destroys the progress tile.
	//! \~russian Уничтожает тайл прогресса.
	virtual ~TileProgress() {}

	//! \~english Text format used for the overlaid label.
	//! \~russian Формат текста, используемый для наложенной подписи.
	PIScreenTypes::CellFormat format;

	//! \~english Text shown before the numeric value.
	//! \~russian Текст, отображаемый перед числовым значением.
	PIString prefix;

	//! \~english Text shown after the numeric value.
	//! \~russian Текст, отображаемый после числового значения.
	PIString suffix;

	//! \~english Value treated as 100 percent.
	//! \~russian Значение, принимаемое за 100 процентов.
	double maximum;

	//! \~english Current progress value.
	//! \~russian Текущее значение прогресса.
	double value;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Log view tile backed by the global %PICout buffer.
//! \~russian Тайл журнала, использующий глобальный буфер %PICout.
class PIP_CONSOLE_EXPORT TilePICout: public TileList {
	PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);

public:
	//! \~english Constructs a %PICout viewer tile.
	//! \~russian Создает тайл просмотра %PICout.
	TilePICout(const PIString & n = PIString());

	//! \~english Destroys the %PICout viewer tile.
	//! \~russian Уничтожает тайл просмотра %PICout.
	virtual ~TilePICout() {}

	//! \~english Format applied to appended log lines.
	//! \~russian Формат, применяемый к добавляемым строкам журнала.
	PIScreenTypes::CellFormat format;

	//! \~english Maximum number of lines retained from the %PICout buffer.
	//! \~russian Максимальное количество строк, сохраняемых из буфера %PICout.
	int max_lines;

protected:
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
};


//! \~\ingroup Console
//! \~\brief
//! \~english Single-line editable text input tile.
//! \~russian Однострочный тайл редактируемого текстового ввода.
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
	PIOBJECT_SUBCLASS(TileInput, PIScreenTile);

public:
	//! \~english Constructs an input tile.
	//! \~russian Создает тайл ввода.
	TileInput(const PIString & n = PIString());

	//! \~english Destroys the input tile.
	//! \~russian Уничтожает тайл ввода.
	virtual ~TileInput() {}

	//! \~english Format of the entered text.
	//! \~russian Формат вводимого текста.
	PIScreenTypes::CellFormat format;

	//! \~english Current input text.
	//! \~russian Текущий введенный текст.
	PIString text;

	//! \~english Maximum input length setting reserved for the tile logic.
	//! \~russian Параметр максимальной длины ввода, зарезервированный для логики тайла.
	int max_length;

protected:
	void sizeHint(int & w, int & h) const override;
	void drawEvent(PIScreenDrawer * d) override;
	bool keyEvent(PIKbdListener::KeyEvent key) override;
	void reserCursor();
	int cur, offset;
	bool inv;
	PITimeMeasurer tm_blink;
};


#endif // PISCREENTILES_H
