minetest/src/gui/guiHyperText.h
DS 0ac999ded7
Add scroll_container formspec element (redo) (#9101)
New formspec elements:

 - `scroll_container[<X>,<Y>;<W>,<H>;<scrollbar name>;<orientation>;<scroll factor>]`
 - `scroll_container_end[]`

Other elements can be embedded in this element. Scrollbar must be placed manually.
2020-04-13 10:50:07 +02:00

230 lines
4.9 KiB
C++

/*
Minetest
Copyright (C) 2019 EvicenceBKidscode / Pierre-Yves Rollo <dev@pyrollo.com>
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 2.1 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include "config.h" // for USE_FREETYPE
using namespace irr;
class ISimpleTextureSource;
class Client;
#if USE_FREETYPE
#include "irrlicht_changes/CGUITTFont.h"
#endif
class ParsedText
{
public:
ParsedText(const wchar_t *text);
~ParsedText();
enum ElementType
{
ELEMENT_TEXT,
ELEMENT_SEPARATOR,
ELEMENT_IMAGE,
ELEMENT_ITEM
};
enum BackgroundType
{
BACKGROUND_NONE,
BACKGROUND_COLOR
};
enum FloatType
{
FLOAT_NONE,
FLOAT_RIGHT,
FLOAT_LEFT
};
enum HalignType
{
HALIGN_CENTER,
HALIGN_LEFT,
HALIGN_RIGHT,
HALIGN_JUSTIFY
};
enum ValignType
{
VALIGN_MIDDLE,
VALIGN_TOP,
VALIGN_BOTTOM
};
typedef std::unordered_map<std::string, std::string> StyleList;
typedef std::unordered_map<std::string, std::string> AttrsList;
struct Tag
{
std::string name;
AttrsList attrs;
StyleList style;
};
struct Element
{
std::list<Tag *> tags;
ElementType type;
core::stringw text = "";
core::dimension2d<u32> dim;
core::position2d<s32> pos;
s32 drawwidth;
FloatType floating = FLOAT_NONE;
ValignType valign;
gui::IGUIFont *font;
irr::video::SColor color;
irr::video::SColor hovercolor;
bool underline;
s32 baseline = 0;
// img & item specific attributes
std::string name;
v3s16 angle{0, 0, 0};
v3s16 rotation{0, 0, 0};
s32 margin = 10;
void setStyle(StyleList &style);
};
struct Paragraph
{
std::vector<Element> elements;
HalignType halign;
s32 margin = 10;
void setStyle(StyleList &style);
};
std::vector<Paragraph> m_paragraphs;
// Element style
s32 margin = 3;
ValignType valign = VALIGN_TOP;
BackgroundType background_type = BACKGROUND_NONE;
irr::video::SColor background_color;
Tag m_root_tag;
protected:
typedef enum { ER_NONE, ER_TAG, ER_NEWLINE } EndReason;
// Parser functions
void enterElement(ElementType type);
void endElement();
void enterParagraph();
void endParagraph(EndReason reason);
void pushChar(wchar_t c);
ParsedText::Tag *newTag(const std::string &name, const AttrsList &attrs);
ParsedText::Tag *openTag(const std::string &name, const AttrsList &attrs);
bool closeTag(const std::string &name);
void parseGenericStyleAttr(const std::string &name, const std::string &value,
StyleList &style);
void parseStyles(const AttrsList &attrs, StyleList &style);
void globalTag(const ParsedText::AttrsList &attrs);
u32 parseTag(const wchar_t *text, u32 cursor);
void parse(const wchar_t *text);
std::unordered_map<std::string, StyleList> m_elementtags;
std::unordered_map<std::string, StyleList> m_paragraphtags;
std::vector<Tag *> m_not_root_tags;
std::list<Tag *> m_active_tags;
// Current values
StyleList m_style;
Element *m_element;
Paragraph *m_paragraph;
bool m_empty_paragraph;
EndReason m_end_paragraph_reason;
};
class TextDrawer
{
public:
TextDrawer(const wchar_t *text, Client *client, gui::IGUIEnvironment *environment,
ISimpleTextureSource *tsrc);
void place(const core::rect<s32> &dest_rect);
inline s32 getHeight() { return m_height; };
void draw(const core::rect<s32> &clip_rect,
const core::position2d<s32> &dest_offset);
ParsedText::Element *getElementAt(core::position2d<s32> pos);
ParsedText::Tag *m_hovertag;
protected:
struct RectWithMargin
{
core::rect<s32> rect;
s32 margin;
};
ParsedText m_text;
Client *m_client;
gui::IGUIEnvironment *m_environment;
s32 m_height;
s32 m_voffset;
std::vector<RectWithMargin> m_floating;
};
class GUIHyperText : public gui::IGUIElement
{
public:
//! constructor
GUIHyperText(const wchar_t *text, gui::IGUIEnvironment *environment,
gui::IGUIElement *parent, s32 id,
const core::rect<s32> &rectangle, Client *client,
ISimpleTextureSource *tsrc);
//! destructor
virtual ~GUIHyperText();
//! draws the element and its children
virtual void draw();
core::dimension2du getTextDimension();
bool OnEvent(const SEvent &event);
protected:
// GUI members
Client *m_client;
GUIScrollBar *m_vscrollbar;
TextDrawer m_drawer;
// Positioning
u32 m_scrollbar_width;
core::rect<s32> m_display_text_rect;
core::position2d<s32> m_text_scrollpos;
ParsedText::Element *getElementAt(s32 X, s32 Y);
void checkHover(s32 X, s32 Y);
};