X-Plane Remote Access Plugin and Client Library
MessageWindow.cc
1 // Copyright (c) 2013 by István Váradi
2 
3 // This file is part of XPLRA, a remote-access plugin for X-Plane
4 
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 
8 // 1. Redistributions of source code must retain the above copyright notice, this
9 // list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 
14 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 
25 // The views and conclusions contained in the software and documentation are those
26 // of the authors and should not be interpreted as representing official policies,
27 // either expressed or implied, of the FreeBSD Project.
28 
29 //------------------------------------------------------------------------------
30 
31 #include "MessageWindow.h"
32 
33 #include <hu/varadiistvan/xplcommon/Util.h>
34 
35 #include <XPLMProcessing.h>
36 #include <XPLMGraphics.h>
37 
38 //------------------------------------------------------------------------------
39 
41 
42 using hu::varadiistvan::xplcommon::Util;
43 
44 using std::string;
45 using std::min;
46 using std::max;
47 
48 //------------------------------------------------------------------------------
49 
50 void MessageWindow::drawWindowCallback(XPLMWindowID /*windowID*/, void* refCon)
51 {
52  MessageWindow* messageWindow = reinterpret_cast<MessageWindow*>(refCon);
53  messageWindow->drawWindow();
54 }
55 
56 //------------------------------------------------------------------------------
57 
58 void MessageWindow::handleKeyCallback(XPLMWindowID /*windowID*/, char key,
59  XPLMKeyFlags flags, char virtualKey,
60  void* refCon, int losingFocus)
61 {
62  MessageWindow* messageWindow = reinterpret_cast<MessageWindow*>(refCon);
63  messageWindow->handleKey(key, flags, virtualKey, losingFocus!=0);
64 }
65 
66 //------------------------------------------------------------------------------
67 
68 int MessageWindow::handleMouseClickCallback(XPLMWindowID /*windowID*/,
69  int x, int y,
70  XPLMMouseStatus mouse, void* refCon)
71 {
72  MessageWindow* messageWindow = reinterpret_cast<MessageWindow*>(refCon);
73  return messageWindow->handleMouseClick(x, y, mouse) ? 1 : 0;
74 }
75 
76 //------------------------------------------------------------------------------
77 
79  maxMessageLength(0),
80  showForced(false),
81  showTime(0.0),
82  hideTime(0.0),
83  clickedX(-1),
84  clickedY(-1),
85  clickedLeft(-1),
86  clickedTop(-1),
87  clickedRight(-1),
88  clickedBottom(-1),
89  duration(0.0)
90 {
91  widthDataRef = XPLMFindDataRef("sim/graphics/view/window_width");
92  heightDataRef = XPLMFindDataRef("sim/graphics/view/window_height");
93 
94  int digitsOnly = 0;
95  XPLMGetFontDimensions(xplmFont_Basic, &fontWidth, &fontHeight, &digitsOnly);
96 
97  Util::debug("hu.varadiistvan.xplra.MessageWindow: fontWidth=%d, fontHeight=%d\n",
99 
100  resetLocation();
101 
102  windowID = XPLMCreateWindow(left, top, right, bottom, 0,
105  &handleMouseClickCallback, this);
106 }
107 
108 //------------------------------------------------------------------------------
109 
111 {
112  XPLMSetWindowIsVisible(windowID, 0);
113  XPLMDestroyWindow(windowID);
114 }
115 
116 //------------------------------------------------------------------------------
117 
119 {
120  showForced = true;
121  XPLMSetWindowIsVisible(windowID, 1);
122 }
123 
124 //------------------------------------------------------------------------------
125 
127 {
128  showForced = false;
129 }
130 
131 //------------------------------------------------------------------------------
132 
134 {
135  resetLocation();
136  XPLMSetWindowGeometry(windowID, left, top, right, bottom);
137 }
138 
139 //------------------------------------------------------------------------------
140 
142 {
143  static float colour[3] = { 0.2, 1.0, 0.65 };
144 
145  float now = XPLMGetElapsedTime();
146 
147  float d = getNewMessage(displayedMessage);
148  if (d>0.0) {
149  showTime = now;
150  hideTime = now + d;
151  }
152 
153  if (now>=hideTime) hideTime = 0.0;
154 
155  if (hideTime==0.0 && !showForced) {
156  XPLMSetWindowIsVisible(windowID, 0);
157  } else {
158  XPLMDrawTranslucentDarkBox(left, top, right, bottom);
159  if (hideTime!=0.0) {
160  size_t offset = 0;
161  if (displayedMessage.size()>maxMessageLength &&
162  now > (showTime + scrollTimeout) )
163  {
164  offset = (now - showTime - scrollTimeout) /
166  offset = min(offset,
168  }
169 
170  string dm(displayedMessage, offset, maxMessageLength);
171 
172  XPLMDrawString(colour,
175  const_cast<char*>(dm.c_str()), 0,
176  xplmFont_Basic);
177  }
178  }
179 }
180 
181 //------------------------------------------------------------------------------
182 
183 void MessageWindow::handleKey(char key, XPLMKeyFlags flags, char virtualKey,
184  bool losingFocus)
185 {
186  Util::debug("hu.varadiistvan.xplra.MessageWindow.handleKey: key=0x%02d (%c), flags=0x%04x, virtualKey=0x%02d (%c), losingFocus=%d\n",
187  key, key, flags, virtualKey, virtualKey, losingFocus);
188 }
189 
190 //------------------------------------------------------------------------------
191 
192 bool MessageWindow::handleMouseClick(int x, int y, XPLMMouseStatus mouse)
193 {
194  if (mouse==xplm_MouseDown) {
195  if (x <= (left + resizeArea) ) {
196  mouseMode = MOUSE_RESIZE_LEFT;
197  } else if (x > (right-resizeArea) ) {
198  mouseMode = MOUSE_RESIZE_RIGHT;
199  } else {
200  mouseMode = MOUSE_MOVE;
201  }
202  clickedX = x;
203  clickedY = y;
204  clickedLeft = left;
205  clickedTop = top;
208  } else if (mouse==xplm_MouseDrag) {
209  int xDiff = x - clickedX;
210 
211  if (mouseMode==MOUSE_MOVE) {
212  int newLeft = clickedLeft + xDiff;
213  int newRight = clickedRight + xDiff;
214 
215  int screenWidth = XPLMGetDatai(widthDataRef);
216  if (newLeft>=0 && newRight<screenWidth) {
217  left = newLeft;
218  right = newRight;
219  }
220 
221  int yDiff = y - clickedY;
222  int newTop = clickedTop + yDiff;
223  int newBottom = clickedBottom + yDiff;
224 
225  int screenHeight = XPLMGetDatai(heightDataRef);
226  if (newTop<screenHeight && newBottom>=0) {
227  top = newTop;
228  bottom = newBottom;
229  }
230  } else if (mouseMode==MOUSE_RESIZE_LEFT) {
231  int newLeft = clickedLeft + xDiff;
232  if (newLeft>=0 && (right-newLeft)>=minimalWidth) {
233  left = newLeft;
235  }
236  } else if (mouseMode==MOUSE_RESIZE_RIGHT) {
237  int newRight = clickedRight + xDiff;
238  int screenWidth = XPLMGetDatai(widthDataRef);
239  if (newRight<screenWidth && (newRight-left)>=minimalWidth) {
240  right = newRight;
242  }
243  }
244 
245  XPLMSetWindowGeometry(windowID, left, top, right, bottom);
246  }
247 
248  return true;
249 }
250 
251 //------------------------------------------------------------------------------
252 
253 float MessageWindow::getNewMessage(std::string& dest)
254 {
255  mutex.lock();
256 
257  float d = duration;
258  if (d>0.0) {
259  dest = message;
260 
261  message.clear();
262  duration = 0.0;
263  }
264 
265  mutex.unlock();
266 
267  return d;
268 }
269 
270 //------------------------------------------------------------------------------
271 
272 void MessageWindow::setNewMessage(const std::string& msg, float d)
273 {
274  mutex.lock();
275  message = msg;
276  duration = d;
277  mutex.unlock();
278 
279  XPLMSetWindowIsVisible(windowID, 1);
280 }
281 
282 //------------------------------------------------------------------------------
283 
285 {
286  int screenWidth = XPLMGetDatai(widthDataRef);
287  int screenHeight = XPLMGetDatai(heightDataRef);
288 
289  // Util::debug("hu.varadiistvan.xplra.MessageWindow: screenWidth=%d, screenHeight=%d\n",
290  // screenWidth, screenHeight);
291 
292  left = 50;
293  right = screenWidth - left;
294 
295  top = screenHeight * 9 / 10;
297 
299 }
300 
301 //------------------------------------------------------------------------------
302 
304 {
307 }
308 
309 //------------------------------------------------------------------------------
310 
311 // Local Variables:
312 // mode: C++
313 // c-basic-offset: 4
314 // indent-tabs-mode: nil
315 // End:
void setNewMessage(const std::string &msg, float d)
XPLMDataRef widthDataRef
static const int resizeArea
Definition: MessageWindow.h:79
static void handleKeyCallback(XPLMWindowID windowID, char key, XPLMKeyFlags flags, char virtualKey, void *refCon, int losingFocus)
static constexpr float scrollTimeout
static void drawWindowCallback(XPLMWindowID windowID, void *refCon)
void handleKey(char key, XPLMKeyFlags flags, char virtualKey, bool losingFocus)
static const int verticalMarginSize
Definition: MessageWindow.h:89
enum xplra::MessageWindow::@0 mouseMode
XPLMWindowID windowID
bool handleMouseClick(int x, int y, XPLMMouseStatus mouse)
hu::varadiistvan::scpl::Mutex mutex
std::string displayedMessage
void recalculateMaxMessageLength()
float getNewMessage(std::string &dest)
static const int horizontalMarginSize
Definition: MessageWindow.h:84
static const int baseLineSize
Definition: MessageWindow.h:94
static int handleMouseClickCallback(XPLMWindowID windowID, int x, int y, XPLMMouseStatus mouse, void *refCon)
static const int minimalWidth
Definition: MessageWindow.h:74
XPLMDataRef heightDataRef
static constexpr float scrollInterval