swift
Loading...
Searching...
No Matches
messages.cpp
1// SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3
5
6#ifndef NOMINMAX
7# define NOMINMAX
8#endif
9#include "messages.h"
10
11#include <XPLMGraphics.h>
12#include <XPUIGraphics.h>
13
14namespace XSwiftBus
15{
17 {
18 static const int lh = [] {
19 int lineHeight = 0;
20 XPLMGetFontDimensions(xplmFont_Basic, nullptr, &lineHeight, nullptr);
21 return lineHeight;
22 }();
23 return lh;
24 }
25
27 {
28 static const int fixedLineHeight = CMessageBox::lineHeight();
29 static const int lineSpace = fixedLineHeight / 3;
30
31 const int messageCount = static_cast<int>(m_messages.size());
32
33 const int screenHeight = m_screenHeight.get();
34 const int boxRight = m_screenWidth.get() - m_boxRight;
35 const int boxLeft = m_boxLeft;
36 int boxTop;
37 int boxBottom;
38
39 if (m_boxTop >= 0)
40 {
41 boxTop = screenHeight - m_boxTop;
42 boxBottom = boxTop - lineSpace * 2 - (fixedLineHeight + lineSpace) * messageCount;
43 }
44 else
45 {
46 boxBottom = m_boxBottom >= 0 ? m_boxBottom : 20;
47 boxTop = boxBottom + lineSpace * 2 + (fixedLineHeight + lineSpace) * messageCount;
48 }
49
50 if (boxTop > screenHeight)
51 {
52 boxTop = screenHeight;
53 }
54 if (boxBottom <= 0)
55 {
56 boxBottom = 0;
57 }
58
59 XPLMDrawTranslucentDarkBox(boxLeft, boxTop, boxRight, boxBottom);
60
61 static int arrowWidth = 0, arrowHeight = 0;
62 if (!arrowHeight)
63 {
64 XPGetElementDefaultDimensions(xpElement_LittleUpArrow, &arrowWidth, &arrowHeight, nullptr);
65 }
66
67 static const int x = boxLeft + lineSpace;
68 if (m_upArrow)
69 {
70 const int y = boxTop - lineSpace - arrowHeight;
71 XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleUpArrow, 0);
72 }
73 if (m_downArrow)
74 {
75 const int y = boxTop - (fixedLineHeight + lineSpace) * messageCount;
76 XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleDownArrow, 0);
77 }
78 for (int i = 0; i < messageCount; ++i)
79 {
80 const int y = boxTop - (fixedLineHeight + lineSpace) * (i + 1);
81 const size_t ii = static_cast<size_t>(i);
82 XPLMDrawString(m_messages[ii].m_rgb.data(), x + arrowWidth + arrowWidth / 2, y,
83 const_cast<char *>(reinterpret_cast<const char *>(m_messages[ii].m_text.c_str())), nullptr,
84 xplmFont_Basic);
85 }
86 }
87
88 void CMessageBox::setValues(int leftPx, int topPx, int rightPx, int bottomPx, int lines, int durationMs)
89 {
90 m_boxBottom = bottomPx;
91 m_boxLeft = leftPx;
92 m_boxRight = rightPx;
93 m_boxTop = topPx;
94 m_lines = lines;
95 m_durationMs = durationMs;
96 }
97
99 {
100 static int len = 0;
101 if (!len)
102 {
103 int charWidth;
104 XPLMGetFontDimensions(xplmFont_Basic, &charWidth, nullptr, nullptr);
105 const int boxRight = m_screenWidth.get() - m_boxRight;
106 const int boxLeft = m_boxLeft;
107 len = (boxRight - boxLeft - 20) / charWidth;
108 }
109 return len;
110 }
111
112 CMessageBoxControl::CMessageBoxControl(int left, int right, int top)
113 : m_messageBox(left, right, top), m_showCommand("org/swift-project/xswiftbus/show_messages",
114 "Show xswiftbus text messages", [this] { show(); }),
115 m_hideCommand("org/swift-project/xswiftbus/hide_messages", "Hide xswiftbus text messages",
116 [this] { hide(); }),
117 m_toggleCommand("org/swift-project/xswiftbus/toggle_messages", "Toggle xswiftbus text messages",
118 [this] { toggle(); }),
119 m_scrollUpCommand("org/swift-project/xswiftbus/scroll_up", "Scroll up xswiftbus text messages",
120 [this] { scrollUp(); }),
121 m_scrollDownCommand("org/swift-project/xswiftbus/scroll_down", "Scroll down xswiftbus text messages",
122 [this] { scrollDown(); }),
123 m_scrollToTopCommand("org/swift-project/xswiftbus/scroll_top", "Scroll to top of xswiftbus text messages",
124 [this] { scrollToTop(); }),
125 m_scrollToBottomCommand("org/swift-project/xswiftbus/scroll_bottom",
126 "Scroll to bottom of xswiftbus text messages", [this] { scrollToBottom(); })
127 {
128 show();
129 }
130
131 void CMessageBoxControl::addMessage(const CMessage &message)
132 {
133 if (m_messages.size() >= c_maxTotalLines)
134 {
135 m_messages.erase(m_messages.begin());
136 }
137 m_messages.push_back(message);
138 if (m_position + 1 >= m_messages.size() || !m_visible)
139 {
140 scrollToBottom();
141 }
142 }
143
144 void CMessageBoxControl::scrollUp()
145 {
146 if (!m_visible)
147 {
148 return;
149 }
150
151 if (m_position - 1 >= std::min(m_messages.size(), m_maxVisibleLines))
152 {
153 m_position--;
154 }
155 updateVisibleLines();
156 }
157
158 void CMessageBoxControl::scrollDown()
159 {
160 if (!m_visible)
161 {
162 return;
163 }
164
165 if (m_position + 1 <= m_messages.size())
166 {
167 m_position++;
168 }
169 updateVisibleLines();
170 }
171
172 void CMessageBoxControl::scrollToTop()
173 {
174 if (!m_visible)
175 {
176 return;
177 }
178
179 m_position = std::min(m_messages.size(), m_maxVisibleLines);
180 updateVisibleLines();
181 }
182
183 void CMessageBoxControl::scrollToBottom()
184 {
185 m_position = m_messages.size();
186 updateVisibleLines();
187 }
188
189 void CMessageBoxControl::updateVisibleLines()
190 {
191 const size_t lines = std::min(m_messages.size(), m_maxVisibleLines);
192 // const auto end = m_messages.cbegin() + m_position;
193 // m_messageBox.setMessages(end - lines, end);
194 auto end = m_messages.begin();
195 std::advance(end, m_position);
196 auto start = end;
197 std::advance(start, -1 * static_cast<int>(lines));
198
199 m_messageBox.setMessages(start, end);
200 m_messageBox.enableArrows(m_position > lines, m_position < m_messages.size());
201 }
202} // namespace XSwiftBus
203
CMessageBoxControl(int left, int right, int top)
Constructor.
virtual void draw()
Callback to draw the thing.
void setValues(int leftPx, int topPx, int rightPx, int bottomPx, int lines, int durationMs)
Set margin values.
int maxLineLength() const
Returns the maximum number of characters per line.
static int lineHeight()
Line height based on font.
Plugin loaded by X-Plane which publishes a DBus service.
Definition command.h:14
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition lockfree.h:264
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)