297 lines
7.5 KiB
C++
297 lines
7.5 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#include "neovision/crt.h"
|
|
|
|
namespace neovision {
|
|
|
|
class Application;
|
|
|
|
/**
|
|
* @brief Buffer used by views.
|
|
*/
|
|
typedef std::vector<std::vector<wchar_t>> ViewBuffer;
|
|
|
|
/**
|
|
* @brief Represents a renderable view area.
|
|
*
|
|
* This is the base class for anything within neovision that can be drawn onto
|
|
* the screen.
|
|
*
|
|
* Each view holds it's own buffer - all writes to a view go to it's internal
|
|
* buffer. The buffer is only drawn to the screen when the Draw event is called
|
|
* (typically by the Application instance, which is also a view in itself).
|
|
*
|
|
*/
|
|
class View
|
|
{
|
|
|
|
ViewBuffer m_buffer;
|
|
std::mutex m_bufferMutex;
|
|
|
|
Vector2D m_cursorPosition;
|
|
bool m_dirty{true};
|
|
bool m_initialized{false};
|
|
std::optional<std::reference_wrapper<View>> m_parent{};
|
|
Vector2D m_position;
|
|
std::mutex m_positionMutex;
|
|
ViewBuffer m_previousBuffer;
|
|
std::mutex m_previousBufferMutex;
|
|
Vector2D m_size;
|
|
std::vector<std::unique_ptr<View>> m_views;
|
|
std::atomic<std::int32_t> m_zOrder{0};
|
|
|
|
void DoRender(
|
|
std::function<void(const std::wstring&, const Vector2D&)> outputFunc
|
|
);
|
|
|
|
public:
|
|
|
|
/**
|
|
* @brief Default constructor.
|
|
*/
|
|
View() = default;
|
|
|
|
/**
|
|
* @brief Destructor.
|
|
*/
|
|
virtual ~View();
|
|
|
|
/**
|
|
* @brief Adds a child view.
|
|
*
|
|
* This view will take ownership of the child and render it when
|
|
* appropriate etc,...
|
|
*
|
|
* @param view View to add.
|
|
*/
|
|
virtual void Add(std::unique_ptr<View> view);
|
|
|
|
/**
|
|
* @brief Recalculates the z-order of child views.
|
|
*
|
|
* Called automatically by views when their z-order changes, or when new
|
|
* views are added.
|
|
*/
|
|
void CalculateZOrders();
|
|
|
|
/**
|
|
* @brief Get cursor position.
|
|
*
|
|
* Gets the current cursor position within the view area.
|
|
*
|
|
* @note Coordinates are relative to the view area, not the screen. In fact,
|
|
* a view's cursor has no relation to the terminal's cursor at all. It just
|
|
* determines where text will go when the Write-family functions are called
|
|
* without an explicit position.
|
|
*
|
|
* @return Returns the current cursor position.
|
|
*/
|
|
Vector2D CursorPosition() const;
|
|
|
|
/**
|
|
* @brief Set cursor position.
|
|
*
|
|
* Sets the current position witin the view area.
|
|
*
|
|
* @note As with the CursorPosition() getter, coordinates are relative, and
|
|
* there is no relation to the terminal cursor.
|
|
*
|
|
* @param pos New cursor position.
|
|
*/
|
|
void CursorPosition(const Vector2D& pos);
|
|
|
|
/**
|
|
* @brief Get dirty flag.
|
|
*
|
|
* Indicates whether the view buffer has been updated since last
|
|
* render.
|
|
*
|
|
* @return Returns true if buffer is dirty.
|
|
*/
|
|
bool Dirty() const;
|
|
|
|
/**
|
|
* @brief Check initialized.
|
|
*
|
|
* @return Returns true if the view has been initialized.
|
|
*/
|
|
bool Initialized() const;
|
|
|
|
/**
|
|
* @brief Get parent.
|
|
*
|
|
* @return Returns an observing pointer to the parent view if there is one.
|
|
*/
|
|
std::optional<std::reference_wrapper<View>> Parent();
|
|
|
|
/**
|
|
* @brief Set position.
|
|
*
|
|
* @param p New area position.
|
|
*/
|
|
void Position(const Vector2D& p);
|
|
|
|
/**
|
|
* @brief Get position.
|
|
*
|
|
* @return Returns the area's position.
|
|
*/
|
|
Vector2D Position() const;
|
|
|
|
/**
|
|
* @brief Render buffer to IO.
|
|
*
|
|
* Writes the buffer to the current IO stream.
|
|
*/
|
|
void Render();
|
|
|
|
/**
|
|
* @brief Render buffer to another view.
|
|
*
|
|
* Writes the buffer to the given view.
|
|
*
|
|
* @param[out] view View to render to.
|
|
*/
|
|
void Render(View& view);
|
|
|
|
/**
|
|
* @brief Set dirty flag true.
|
|
*
|
|
* Forces the view to render next render event.
|
|
*
|
|
* @param[in] propagateChildren Marks all child views as dirty as well if
|
|
* true.
|
|
* @param[in] propagateParent Marks parent as dirty as well if true.
|
|
*/
|
|
void SetDirty(bool propagateChildren = true, bool propagateParent = true);
|
|
|
|
/**
|
|
* @brief Set size.
|
|
*
|
|
* @param s New area size.
|
|
* @param fill Fill character for newly created blank space (if growing).
|
|
* (optional - defaults to spaces.)
|
|
*/
|
|
void Size(const Vector2D& s, wchar_t fill = 0);
|
|
|
|
/**
|
|
* @brief Get size.
|
|
*
|
|
* @return Returns the area size.
|
|
*/
|
|
Vector2D Size() const;
|
|
|
|
/**
|
|
* @brief Write text.
|
|
*
|
|
* Writes a wide string to the view buffer at the current cursor
|
|
* position.
|
|
*
|
|
* @param s String to write.
|
|
*/
|
|
void Write(const std::wstring& s);
|
|
|
|
/**
|
|
* @brief Write text at specific position.
|
|
*
|
|
* Writes a wide string to the view buffer at the specified position. The
|
|
* cursor position will be updated to wherever the last character of the
|
|
* string ends up.
|
|
*
|
|
* @param p Position to write string at.
|
|
* @param s String to write.
|
|
*/
|
|
void WriteAt(const Vector2D& p, const std::wstring& s);
|
|
|
|
/**
|
|
* @brief Write text line.
|
|
*
|
|
* Writes a wide string to the view buffer at the current cursor position
|
|
* and moves to the cursor to the beginning of the next line.
|
|
*
|
|
* @param s String to write.
|
|
*/
|
|
void WriteLn(const std::wstring& s);
|
|
|
|
/**
|
|
* @brief Get the view z-order.
|
|
*
|
|
* The z order indicates the order in which views are rendered.
|
|
* Views with a higher z-order are drawn last, which means they appear on
|
|
* top of windows with a lower z-order. As such it can also be thought of as
|
|
* the z axis position of a window, where positive points towards the viewer
|
|
* and negative points away from the viewer.
|
|
*
|
|
* @return Returns the view's z-order.
|
|
*/
|
|
std::int32_t Zorder() const;
|
|
|
|
/**
|
|
* @brief Set the view z-order.
|
|
*
|
|
* The z order indicates the order in which views are rendered.
|
|
* Views with a higher z-order are drawn last, which means they appear on
|
|
* top of windows with a lower z-order. As such it can also be thought of as
|
|
* the z axis position of a window, where positive points towards the viewer
|
|
* and negative points away from the viewer.
|
|
*
|
|
* @param z The new z-order.
|
|
*/
|
|
void Zorder(std::int32_t z);
|
|
|
|
protected:
|
|
|
|
/**
|
|
* @brief Initialize event.
|
|
*
|
|
* This runs when the application initializes the view.
|
|
*/
|
|
virtual void Initialize();
|
|
|
|
/**
|
|
* @brief Draw event.
|
|
*
|
|
* This runs when the application wants the view to draw itself.
|
|
* This is where you'd draw stuff into the view's buffer.
|
|
* (As opposed to Render(), which renders the buffer to a desination like
|
|
* the screen or another view).
|
|
*
|
|
* Must be implemented when creating a view.
|
|
*/
|
|
virtual void OnDraw();
|
|
|
|
/**
|
|
* @brief Key event.
|
|
*
|
|
* Triggers when a keyboard event happens.
|
|
*/
|
|
virtual void OnKey(const std::wstring&){};
|
|
|
|
/**
|
|
* @brief Mouse event.
|
|
*
|
|
* Triggers when a mouse event happens.
|
|
*/
|
|
virtual void OnMouse(const MouseEventData&){};
|
|
|
|
/**
|
|
* @brief Write to the internal view buffer.
|
|
*
|
|
* All the various Write() functions ultimately call this.
|
|
* Override this if you want to make a custom view writer.
|
|
*
|
|
* @param p Position in buffer to write to.
|
|
* @param s String to be written into the buffer.
|
|
*/
|
|
virtual void WriteToBuffer(const Vector2D& p, const std::wstring s);
|
|
|
|
friend class Application;
|
|
|
|
};
|
|
|
|
} // namespace neovision
|