swift
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 
14 namespace 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 
26  void CMessageBox::draw()
27  {
28  static const int lineHeight = CMessageBox::lineHeight();
29  static const int lineSpace = lineHeight / 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 - (lineHeight + lineSpace) * messageCount;
43  }
44  else
45  {
46  boxBottom = m_boxBottom >= 0 ? m_boxBottom : 20;
47  boxTop = boxBottom + lineSpace * 2 + (lineHeight + lineSpace) * messageCount;
48  }
49 
50  if (boxTop > screenHeight) { boxTop = screenHeight; }
51  if (boxBottom <= 0) { boxBottom = 0; }
52 
53  XPLMDrawTranslucentDarkBox(boxLeft, boxTop, boxRight, boxBottom);
54 
55  static int arrowWidth = 0, arrowHeight = 0;
56  if (!arrowHeight)
57  {
58  XPGetElementDefaultDimensions(xpElement_LittleUpArrow, &arrowWidth, &arrowHeight, nullptr);
59  }
60 
61  static const int x = boxLeft + lineSpace;
62  if (m_upArrow)
63  {
64  const int y = boxTop - lineSpace - arrowHeight;
65  XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleUpArrow, 0);
66  }
67  if (m_downArrow)
68  {
69  const int y = boxTop - (lineHeight + lineSpace) * messageCount;
70  XPDrawElement(x, y, x + arrowWidth, y + arrowHeight, xpElement_LittleDownArrow, 0);
71  }
72  for (int i = 0; i < messageCount; ++i)
73  {
74  const int y = boxTop - (lineHeight + lineSpace) * (i + 1);
75  const size_t ii = static_cast<size_t>(i);
76  XPLMDrawString(m_messages[ii].m_rgb.data(), x + arrowWidth + arrowWidth / 2, y,
77  const_cast<char *>(reinterpret_cast<const char *>(m_messages[ii].m_text.c_str())), nullptr,
78  xplmFont_Basic);
79  }
80  }
81 
82  void CMessageBox::setValues(int leftPx, int topPx, int rightPx, int bottomPx, int lines, int durationMs)
83  {
84  m_boxBottom = bottomPx;
85  m_boxLeft = leftPx;
86  m_boxRight = rightPx;
87  m_boxTop = topPx;
88  m_lines = lines;
89  m_durationMs = durationMs;
90  }
91 
92  int CMessageBox::maxLineLength() const
93  {
94  static int len = 0;
95  if (!len)
96  {
97  int charWidth;
98  XPLMGetFontDimensions(xplmFont_Basic, &charWidth, nullptr, nullptr);
99  const int boxRight = m_screenWidth.get() - m_boxRight;
100  const int boxLeft = m_boxLeft;
101  len = (boxRight - boxLeft - 20) / charWidth;
102  }
103  return len;
104  }
105 
106  CMessageBoxControl::CMessageBoxControl(int left, int right, int top)
107  : m_messageBox(left, right, top), m_showCommand("org/swift-project/xswiftbus/show_messages",
108  "Show xswiftbus text messages", [this] { show(); }),
109  m_hideCommand("org/swift-project/xswiftbus/hide_messages", "Hide xswiftbus text messages",
110  [this] { hide(); }),
111  m_toggleCommand("org/swift-project/xswiftbus/toggle_messages", "Toggle xswiftbus text messages",
112  [this] { toggle(); }),
113  m_scrollUpCommand("org/swift-project/xswiftbus/scroll_up", "Scroll up xswiftbus text messages",
114  [this] { scrollUp(); }),
115  m_scrollDownCommand("org/swift-project/xswiftbus/scroll_down", "Scroll down xswiftbus text messages",
116  [this] { scrollDown(); }),
117  m_scrollToTopCommand("org/swift-project/xswiftbus/scroll_top", "Scroll to top of xswiftbus text messages",
118  [this] { scrollToTop(); }),
119  m_scrollToBottomCommand("org/swift-project/xswiftbus/scroll_bottom",
120  "Scroll to bottom of xswiftbus text messages", [this] { scrollToBottom(); })
121  {
122  show();
123  }
124 
125  void CMessageBoxControl::addMessage(const CMessage &message)
126  {
127  if (m_messages.size() >= c_maxTotalLines) { m_messages.erase(m_messages.begin()); }
128  m_messages.push_back(message);
129  if (m_position + 1 >= m_messages.size() || !m_visible) { scrollToBottom(); }
130  }
131 
132  void CMessageBoxControl::scrollUp()
133  {
134  if (!m_visible) { return; }
135 
136  if (m_position - 1 >= std::min(m_messages.size(), m_maxVisibleLines)) { m_position--; }
137  updateVisibleLines();
138  }
139 
140  void CMessageBoxControl::scrollDown()
141  {
142  if (!m_visible) { return; }
143 
144  if (m_position + 1 <= m_messages.size()) { m_position++; }
145  updateVisibleLines();
146  }
147 
148  void CMessageBoxControl::scrollToTop()
149  {
150  if (!m_visible) { return; }
151 
152  m_position = std::min(m_messages.size(), m_maxVisibleLines);
153  updateVisibleLines();
154  }
155 
156  void CMessageBoxControl::scrollToBottom()
157  {
158  m_position = m_messages.size();
159  updateVisibleLines();
160  }
161 
162  void CMessageBoxControl::updateVisibleLines()
163  {
164  const size_t lines = std::min(m_messages.size(), m_maxVisibleLines);
165  // const auto end = m_messages.cbegin() + m_position;
166  // m_messageBox.setMessages(end - lines, end);
167  auto end = m_messages.begin();
168  std::advance(end, m_position);
169  auto start = end;
170  std::advance(start, -1 * static_cast<int>(lines));
171 
172  m_messageBox.setMessages(start, end);
173  m_messageBox.enableArrows(m_position > lines, m_position < m_messages.size());
174  }
175 } // namespace XSwiftBus
176 
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.
DataRefType get() const
Get the value of the dataref.
Definition: datarefs.h:117
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:338