Chatterino
MessageLayoutContainer.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <QPoint>
4 #include <QRect>
5 #include <memory>
6 #include <vector>
7 
8 #include "common/Common.hpp"
9 #include "common/FlagsEnum.hpp"
10 #include "messages/Selection.hpp"
12 
13 class QPainter;
14 
15 namespace chatterino {
16 
17 enum class MessageFlag : int64_t;
18 enum class FirstWord { Neutral, RTL, LTR };
20 
21 struct Margin {
22  int top;
23  int right;
24  int bottom;
25  int left;
26 
28  : Margin(0)
29  {
30  }
31 
32  Margin(int value)
33  : Margin(value, value, value, value)
34  {
35  }
36 
37  Margin(int _top, int _right, int _bottom, int _left)
38  : top(_top)
39  , right(_right)
40  , bottom(_bottom)
41  , left(_left)
42  {
43  }
44 };
45 
47  MessageLayoutContainer() = default;
48 
50  bool containsRTL = false;
51 
52  int getHeight() const;
53  int getWidth() const;
54  float getScale() const;
55 
56  // methods
57  void begin(int width_, float scale_, MessageFlags flags_);
58  void end();
59 
60  void clear();
61  bool canAddElements() const;
62  void addElement(MessageLayoutElement *element);
63  void addElementNoLineBreak(MessageLayoutElement *element);
64  void breakLine();
65  bool atStartOfLine();
66  bool fitsInLine(int width_);
67  // this method is called when a message has an RTL word
68  // we need to reorder the words to be shown properly
69  // however we don't we to reorder non-text elements like badges, timestamps, username
70  // firstTextIndex is the index of the first text element that we need to start the reordering from
71  void reorderRTL(int firstTextIndex);
72  MessageLayoutElement *getElementAt(QPoint point);
73 
74  // painting
75  void paintElements(QPainter &painter);
76  void paintAnimatedElements(QPainter &painter, int yOffset);
77  void paintSelection(QPainter &painter, int messageIndex,
78  Selection &selection, int yOffset);
79 
80  // selection
81  int getSelectionIndex(QPoint point);
82  int getLastCharacterIndex() const;
83  int getFirstMessageCharacterIndex() const;
84  void addSelectionText(QString &str, uint32_t from, uint32_t to,
85  CopyMode copymode);
86 
87  bool isCollapsed();
88 
89 private:
90  struct Line {
91  int startIndex;
92  int endIndex;
93  int startCharIndex;
94  int endCharIndex;
95  QRect rect;
96  };
97 
98  // helpers
99  /*
100  _addElement is called at two stages. first stage is the normal one where we want to add message layout elements to the container.
101  If we detect an RTL word in the message, reorderRTL will be called, which is the second stage, where we call _addElement
102  again for each layout element, but in the correct order this time, without adding the elemnt to the this->element_ vector.
103  Due to compact emote logic, we need the previous element to check if we should change the spacing or not.
104  in stage one, this is simply elements_.back(), but in stage 2 that's not the case due to the reordering, and we need to pass the
105  index of the reordered previous element.
106  In stage one we don't need that and we pass -2 to indicate stage one (i.e. adding mode)
107  In stage two, we pass -1 for the first element, and the index of the oredered privous element for the rest.
108  */
109  void _addElement(MessageLayoutElement *element, bool forceAdd = false,
110  int prevIndex = -2);
111  bool canCollapse();
112 
113  const Margin margin = {4, 8, 4, 8};
114 
115  // variables
116  float scale_ = 1.f;
117  int width_ = 0;
118  MessageFlags flags_{};
119  int line_ = 0;
120  int height_ = 0;
121  int currentX_ = 0;
122  int currentY_ = 0;
123  int charIndex_ = 0;
124  size_t lineStart_ = 0;
125  int lineHeight_ = 0;
126  int spaceWidth_ = 4;
127  int textLineHeight_ = 0;
128  int dotdotdotWidth_ = 0;
129  bool canAddMessages_ = true;
130  bool isCollapsed_ = false;
131 
132  std::vector<std::unique_ptr<MessageLayoutElement>> elements_;
133  std::vector<Line> lines_;
134 };
135 
136 } // namespace chatterino
Definition: MessageLayoutElement.hpp:26
Definition: Selection.hpp:44
int right
Definition: MessageLayoutContainer.hpp:23
Definition: Application.cpp:48
int bottom
Definition: MessageLayoutContainer.hpp:24
Definition: MessageLayoutContainer.hpp:21
CopyMode
Definition: Common.hpp:52
MessageFlag
Definition: Message.hpp:18
int64_t FlagsEnum< MessageFlag > MessageFlags
Definition: Channel.hpp:20
Margin(int _top, int _right, int _bottom, int _left)
Definition: MessageLayoutContainer.hpp:37
Definition: MessageLayoutContainer.hpp:46
int left
Definition: MessageLayoutContainer.hpp:25
FirstWord
Definition: MessageLayoutContainer.hpp:18
Margin(int value)
Definition: MessageLayoutContainer.hpp:32
int top
Definition: MessageLayoutContainer.hpp:22
Margin()
Definition: MessageLayoutContainer.hpp:27