OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4Gui.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // generic user interface
17 // all generic classes that do not fit into other C4Gui*-files
18 
19 #include "C4Include.h"
20 #include "gui/C4Gui.h"
21 
22 #include "game/C4FullScreen.h"
23 #include "gui/C4LoaderScreen.h"
24 #include "game/C4Application.h"
25 #include "game/C4Viewport.h"
26 #include "lib/C4Log.h"
27 #include "platform/C4GamePadCon.h"
28 #include "gui/C4MouseControl.h"
30 #include "graphics/C4Draw.h"
31 #include "game/C4GraphicsSystem.h"
32 
33 namespace C4GUI
34 {
35 
36 // --------------------------------------------------
37 // Generic helpers
38 
39  bool ExpandHotkeyMarkup(StdStrBuf &sText, uint32_t &rcHotkey, bool for_tooltip)
40  {
41  const char *HotkeyMarkup = (for_tooltip ? "<c ff800000>%s</c>" : "<c ffffff7f>%s</c>");
42 
43  StdStrBuf output;
44 
45  const char *input = sText.getData();
46  rcHotkey = 0;
47 
48  // Iterate over all input characters
49  while (input && *input)
50  {
51  if (*input != '&')
52  {
53  // This will correctly copy UTF-8 chars too
54  output.AppendChar(*input++);
55  }
56  else
57  {
58  ++input;
59  if (*input == '\0' || *input == '&')
60  {
61  // If the ampersand is followed by another ampersand, or it is the last character, copy it verbatimly
62  // Note: This means you can't use an ampersand as an accelerator key.
63  output.AppendChar(*input);
64  }
65  else
66  {
67  // Store the start of the hotkey so we can copy it later
68  const char *accel_start = input;
69  rcHotkey = GetNextCharacter(&input);
70  // Using std::string because StdStrBuf doesn't have a ctor from two iterators
71  std::string accel(accel_start, input);
72  output.AppendFormat(HotkeyMarkup, accel.c_str());
73 
74  // Converting a char code to upper case isn't trivial for unicode. (This should really just use ICU.)
75  if (Inside(rcHotkey, static_cast<uint32_t>('a'), static_cast<uint32_t>('z')))
76  {
77  rcHotkey += static_cast<uint32_t>('A') - 'a';
78  }
79  else if (!Inside(rcHotkey, static_cast<uint32_t>('A'), static_cast<uint32_t>('Z')))
80  {
81  // Warn about accelerator keys outside the basic latin alphabet.
82  LogF(LoadResStr("IDS_ERR_UNSUPPORTED_ACCELERATOR"), accel.c_str(), sText.getData());
83  }
84  }
85  }
86  }
87 
88  if (rcHotkey == 0)
89  {
90  // No accelerator found
91  return false;
92  }
93 
94  sText.Take(output);
95  // done, success
96  return true;
97  }
98 
100  {
101  // max alpha
102  DWORD dwAlpha = std::max<DWORD>(rdwClr>>24&255, 0xff)<<24;
103  rdwClr &= 0xffffff;
104  // determine brightness
105  // 50% red, 87% green, 27% blue (max 164 * 255)
106  DWORD r=(rdwClr>>16&255), g=(rdwClr>>8&255), b=(rdwClr&255);
107  int32_t iLightness = r*50 + g*87 + b*27;
108  // above 65/164 (*255) is OK
109  if (iLightness < 16575)
110  {
111  int32_t iInc = (16575-iLightness) / 164;
112  // otherwise, lighten
113  rdwClr = (std::min<DWORD>(r+iInc, 255)<<16) | (std::min<DWORD>(g+iInc, 255)<<8) | std::min<DWORD>(b+iInc, 255);
114  }
115  // return color and alpha
116  rdwClr |= dwAlpha;
117  return rdwClr;
118  }
119 
120  void DynBarFacet::SetHorizontal(C4Surface &rBySfc, int iHeight, int iBorderWidth)
121  {
122  if (!iHeight) iHeight = rBySfc.Hgt;
123  if (!iBorderWidth) iBorderWidth = iHeight;
124  fctBegin.Set(&rBySfc,0,0,iBorderWidth,iHeight);
125  fctMiddle.Set(&rBySfc,iBorderWidth,0,rBySfc.Wdt-2*iBorderWidth,iHeight);
126  fctEnd.Set(&rBySfc,rBySfc.Wdt-iBorderWidth,0,iBorderWidth,iHeight);
127  }
128 
129  void DynBarFacet::SetHorizontal(C4Facet &rByFct, int32_t iBorderWidth)
130  {
131  if (!iBorderWidth) iBorderWidth = rByFct.Hgt;
132  fctBegin.Set(rByFct.Surface,rByFct.X,rByFct.Y,iBorderWidth,rByFct.Hgt);
133  fctMiddle.Set(rByFct.Surface,rByFct.Hgt,rByFct.X,rByFct.Y+rByFct.Wdt-2*iBorderWidth,rByFct.Hgt);
134  fctEnd.Set(rByFct.Surface,rByFct.X+rByFct.Wdt-iBorderWidth,rByFct.Y,iBorderWidth,rByFct.Hgt);
135  }
136 
137  void ScrollBarFacets::Set(const C4Facet &rByFct, int32_t iPinIndex)
138  {
139  // set by hardcoded size
140  barScroll.fctBegin.Set(rByFct.Surface,0,0,16,16);
141  barScroll.fctMiddle.Set(rByFct.Surface,0,16,16,16);
142  barScroll.fctEnd.Set(rByFct.Surface,0,32,16,16);
143  fctScrollDTop.Set(rByFct.Surface,16,0,16,16);
144  if (iPinIndex)
145  fctScrollPin.Set(rByFct.Surface,32,16*(iPinIndex-1),16,16);
146  else
147  fctScrollPin.Set(rByFct.Surface,16,16,16,16);
148  fctScrollDBottom.Set(rByFct.Surface,16,32,16,16);
149  }
150 
151 // --------------------------------------------------
152 // Element
153 
154  Element::Element() : pParent(nullptr), pDragTarget(nullptr), fDragging(false), pContextHandler(nullptr), fVisible(true), is_immediate_tooltip(false)
155  {
156  // pParent=nullptr invalidates pPrev/pNext
157  // fDragging=false invalidates iDragX/Y
158  // zero fields
159  rcBounds.Set(0,0,0,0);
160  }
161 
163  {
164  // delete context handler
166  // remove from any container
167  if (pParent)
168  pParent->RemoveElement(this);
169  else if (this != Screen::GetScreenS() && Screen::GetScreenS())
170  // always ensure removal from screen!
172  }
173 
175  {
176  // child removed: forward to parent
177  if (pParent)
178  pParent->RemoveElement(pChild);
179  else if (this != Screen::GetScreenS())
180  // always ensure removal from screen!
181  // but not if this is the context menu, to avoid endless flip-flop!
182  if (!IsMenu())
184  }
185 
187  {
188  // update own fields
189  UpdateOwnPos();
190  // notify container
191  if (pParent) pParent->ElementSizeChanged(this);
192  }
193 
195  {
196  // update own fields
197  UpdateOwnPos();
198  // notify container
199  if (pParent) pParent->ElementPosChanged(this);
200  }
201 
203  {
204  // self and parent must be visible
205  return fVisible && (!pParent || pParent->IsVisible());
206  }
207 
208  void Element::SetVisibility(bool fToValue)
209  {
210  fVisible = fToValue;
211  // stop mouseover for invisible
212  if (!fVisible)
213  {
214  Screen *pScreen = GetScreen();
215  if (pScreen) pScreen->Mouse.OnElementGetsInvisible(this);
216  }
217  }
218 
219  void Element::ScreenPos2ClientPos(int32_t &riX, int32_t &riY)
220  {
221  // apply all parent offsets
222  Container *pCont = pParent;
223  while (pCont)
224  {
225  pCont->ApplyElementOffset(riX, riY);
226  pCont = pCont->GetParent();
227  }
228  // apply own offset
229  riX -= rcBounds.x; riY -= rcBounds.y;
230  }
231 
232  void Element::ClientPos2ScreenPos(int32_t &riX, int32_t &riY)
233  {
234  // apply all parent offsets
235  Container *pCont = pParent;
236  while (pCont)
237  {
238  pCont->ApplyInvElementOffset(riX, riY);
239  pCont = pCont->GetParent();
240  }
241  // apply own offset
242  riX += rcBounds.x; riY += rcBounds.y;
243  }
244 
245  void Element::MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
246  {
247  // store self as mouse-over-component
248  rMouse.pMouseOverElement = this;
249  // evaluate dragging
250  if (pDragTarget && iButton == C4MC_Button_LeftDown && !rMouse.pDragElement)
251  StartDragging(rMouse, iX, iY, dwKeyParam);
252  // right button down: open context menu
253  if (iButton == C4MC_Button_RightDown)
254  {
256  if (pCtx) pCtx->OnContext(this, iX, iY);
257  }
258  }
259 
260  void Element::StartDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
261  {
262  // set flag
263  fDragging = true;
264  // set drag start pos
265  iDragX = iX; iDragY = iY;
266  // mark drag in mouse
267  rMouse.pDragElement = this;
268  }
269 
270  void Element::DoDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
271  {
272  // check if anything moved
273  if (pDragTarget && (iX != iDragX || iY != iDragY))
274  {
275  // move position, then
276  pDragTarget->rcBounds.x += iX-iDragX;
277  pDragTarget->rcBounds.y += iY-iDragY;
278  // drag X/Y is up-to-date if this is a child element of the drag target
280  }
281  }
282 
283  void Element::StopDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
284  {
285  // move element pos
286  DoDragging(rMouse, iX, iY, dwKeyParam);
287  }
288 
289  Dialog *Element::GetDlg () { if (pParent) return pParent->GetDlg (); return nullptr; }
290  Screen *Element::GetScreen() { if (pParent) return pParent->GetScreen(); return nullptr; }
291 
292  void Element::Draw3DFrame(C4TargetFacet &cgo, bool fUp, int32_t iIndent, BYTE byAlpha, bool fDrawTop, int32_t iTopOff, bool fDrawLeft, int32_t iLeftOff)
293  {
294  DWORD dwAlpha = byAlpha<<24;
295  int32_t x0 = cgo.TargetX + rcBounds.x + iLeftOff,
296  y0 = cgo.TargetY + rcBounds.y + iTopOff,
297  x1 = cgo.TargetX + rcBounds.x + rcBounds.Wdt - 1,
298  y1 = cgo.TargetY + rcBounds.y + rcBounds.Hgt - 1;
299  if (fDrawTop) pDraw->DrawLineDw(cgo.Surface, (float)x0,(float)y0,(float)x1,(float)y0, C4GUI_BorderColor1 | dwAlpha);
300  if (fDrawLeft) pDraw->DrawLineDw(cgo.Surface, (float)x0,(float)y0,(float)x0,(float)y1, C4GUI_BorderColor1 | dwAlpha);
301  if (fDrawTop) pDraw->DrawLineDw(cgo.Surface, (float)(x0+1),(float)(y0+1),(float)(x1-1),(float)(y0+1), C4GUI_BorderColor2 | dwAlpha);
302  if (fDrawLeft) pDraw->DrawLineDw(cgo.Surface, (float)(x0+1),(float)(y0+1),(float)(x0+1),(float)(y1-1), C4GUI_BorderColor2 | dwAlpha);
303  pDraw->DrawLineDw(cgo.Surface, (float)x0,(float)y1,(float)x1,(float)y1, C4GUI_BorderColor3 | dwAlpha);
304  pDraw->DrawLineDw(cgo.Surface, (float)x1,(float)y0,(float)x1,(float)y1, C4GUI_BorderColor3 | dwAlpha);
305  pDraw->DrawLineDw(cgo.Surface, (float)(x0+1),(float)(y1-1),(float)(x1-1),(float)(y1-1), C4GUI_BorderColor1 | dwAlpha);
306  pDraw->DrawLineDw(cgo.Surface, (float)(x1-1),(float)(y0+1),(float)(x1-1),(float)(y1-1), C4GUI_BorderColor1 | dwAlpha);
307  }
308 
310  {
311  if (rcBounds.Hgt == rFacets.fctMiddle.Hgt)
312  {
313  // exact bar
314  int32_t x0=cgo.TargetX+rcBounds.x, y0=cgo.TargetY+rcBounds.y;
315  int32_t iX = rFacets.fctBegin.Wdt, w=rFacets.fctMiddle.Wdt, wLeft=rFacets.fctBegin.Wdt, wRight=rFacets.fctEnd.Wdt;
316  int32_t iRightShowLength = wRight/3;
317  bool fOverflow = (wLeft > rcBounds.Wdt);
318  if (fOverflow) rFacets.fctBegin.Wdt = rcBounds.Wdt;
319  rFacets.fctBegin.Draw(cgo.Surface, x0,y0);
320  if (fOverflow) rFacets.fctBegin.Wdt = wLeft;
321  while (iX < rcBounds.Wdt-iRightShowLength)
322  {
323  int32_t w2=std::min(w, rcBounds.Wdt-iRightShowLength-iX); rFacets.fctMiddle.Wdt=w2;
324  rFacets.fctMiddle.Draw(cgo.Surface, x0+iX, y0);
325  iX += w;
326  }
327  rFacets.fctMiddle.Wdt=w;
328  fOverflow = (wRight > rcBounds.Wdt);
329  if (fOverflow)
330  {
331  rFacets.fctEnd.X += wRight - rcBounds.Wdt;
332  rFacets.fctEnd.Wdt = rcBounds.Wdt;
333  }
334  rFacets.fctEnd.Draw(cgo.Surface, x0+rcBounds.Wdt-rFacets.fctEnd.Wdt, y0);
335  if (fOverflow)
336  {
337  rFacets.fctEnd.X -= wRight - rcBounds.Wdt;
338  rFacets.fctEnd.Wdt = wRight;
339  }
340  }
341  else
342  {
343  // zoomed bar
344  float fZoom = (float) rcBounds.Hgt / rFacets.fctMiddle.Hgt;
345  int32_t x0=cgo.TargetX+rcBounds.x, y0=cgo.TargetY+rcBounds.y;
346  int32_t iX = int32_t(fZoom*rFacets.fctBegin.Wdt), w=int32_t(fZoom*rFacets.fctMiddle.Wdt), wOld=rFacets.fctMiddle.Wdt;
347  int32_t iRightShowLength = rFacets.fctEnd.Wdt/3;
348  rFacets.fctBegin.DrawX(cgo.Surface, x0,y0,int32_t(fZoom*rFacets.fctBegin.Wdt),rcBounds.Hgt);
349  while (iX < rcBounds.Wdt-(fZoom*iRightShowLength))
350  {
351  int32_t w2=std::min<int32_t>(w, rcBounds.Wdt-int32_t(fZoom*iRightShowLength)-iX); rFacets.fctMiddle.Wdt=long(float(w2)/fZoom);
352  rFacets.fctMiddle.DrawX(cgo.Surface, x0+iX, y0, w2,rcBounds.Hgt);
353  iX += w;
354  }
355  rFacets.fctMiddle.Wdt=wOld;
356  rFacets.fctEnd.DrawX(cgo.Surface, x0+rcBounds.Wdt-int32_t(fZoom*rFacets.fctEnd.Wdt), y0,int32_t(fZoom*rFacets.fctEnd.Wdt),rcBounds.Hgt);
357  }
358  }
359 
361  {
362  C4DrawTransform trf(1);
363  DrawHVBar(cgo, rFacets, trf, rcBounds.Hgt);
364  }
365 
367  {
368  C4DrawTransform trf;
369  float fOffX = cgo.TargetX + rcBounds.x + rcBounds.Hgt/2;
370  float fOffY = cgo.TargetY + rcBounds.y + rcBounds.Hgt/2;
371  trf.SetRotate(-90.0f, fOffX, fOffY);
372 
373  DrawHVBar(cgo, rFacets, trf, rcBounds.Wdt);
374  }
375 
376  void Element::DrawHVBar(C4TargetFacet &cgo, DynBarFacet &rFacets, C4DrawTransform &trf, int32_t iMiddleLength)
377  {
378  int32_t y0 = cgo.TargetY + rcBounds.y;
379  int32_t x0 = cgo.TargetX + rcBounds.x;
380 
381  // draw up arrow
382  rFacets.fctBegin.DrawT(cgo.Surface, x0, y0, 0, 0, &trf);
383 
384  // draw middle part
385  int32_t h = rFacets.fctMiddle.Hgt;
386  int32_t barHeight = iMiddleLength - (rFacets.fctBegin.Hgt + rFacets.fctEnd.Hgt);
387 
388  for (int32_t iY = 0; iY <= barHeight; iY += h)
389  {
390  int32_t h2 = std::min(h, barHeight - iY);
391  rFacets.fctMiddle.Hgt = h2;
392  rFacets.fctMiddle.DrawT(cgo.Surface, x0, y0 + rFacets.fctBegin.Hgt + iY, 0, 0, &trf);
393  }
394  rFacets.fctMiddle.Hgt = h;
395 
396  // draw lower arrow
397  rFacets.fctEnd.DrawT(cgo.Surface, x0, y0 + iMiddleLength - rFacets.fctEnd.Hgt, 0, 0, &trf);
398  }
399 
400  C4Rect Element::GetToprightCornerRect(int32_t iWidth, int32_t iHeight, int32_t iHIndent, int32_t iVIndent, int32_t iIndexX)
401  {
402  // bounds by topright corner of element
403  C4Rect rtBounds = (GetContainer() != this) ? GetClientRect() : GetContainedClientRect();
404  rtBounds.x += rtBounds.Wdt - (iWidth + iHIndent) * (iIndexX + 1);
405  rtBounds.y += iVIndent;
406  rtBounds.Wdt = rtBounds.Hgt = iHeight;
407  return rtBounds;
408  }
409 
410  void Element::SetToolTip(const char *szNewTooltip, bool is_immediate)
411  {
412  // store tooltip
413  if (szNewTooltip) ToolTip.Copy(szNewTooltip); else ToolTip.Clear();
414  // store immediate flag
415  is_immediate_tooltip = is_immediate;
416  }
417 
419  {
420  if (!pContextHandler) return false;
421  return pContextHandler->OnContext(this, rcBounds.Wdt/2, rcBounds.Hgt/2);
422  }
423 
424  const char *Element::GetToolTip()
425  {
426  // fallback to parent tooltip, if own is not assigned
427  return (!pParent || !ToolTip.isNull()) ? ToolTip.getData() : pParent->GetToolTip();
428  }
429 
431  {
432  // fallback to parent context, if own is not assigned
434  }
435 
436  bool Element::IsInActiveDlg(bool fForKeyboard)
437  {
438  // get dlg
439  Dialog *pDlg=GetDlg();
440  if (!pDlg) return false;
441  // check if dlg is active
442  return pDlg->IsActive(fForKeyboard);
443  }
444 
445 
446 // --------------------------------------------------
447 // CMouse
448 
449  CMouse::CMouse(int32_t iX, int32_t iY) : fActive(true), fActiveInput(false)
450  {
451  // set pos
452  x=iX; y=iY;
453  // reset fields
454  LDown=MDown=RDown=false;
455  dwKeys=0;
457  pDragElement = nullptr;
459  // LDownX/Y initialized upon need
460  }
461 
463  {
464  }
465 
466  void CMouse::Input(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
467  {
468  // pos changed or click issued?
469  if (iButton || iX!=x || iY!=y)
470  {
471  // then hide tooltips for a while
473  // and mark as active input device
474  fActiveInput = true;
475  }
476  // copy fields
477  x=iX; y=iY; dwKeys=dwKeyParam;
478  // update buttons
479  switch (iButton)
480  {
481  case C4MC_Button_LeftDown: LDown=true; LDownX=x; LDownY=y; break;
482  case C4MC_Button_LeftUp: LDown=false; break;
483  case C4MC_Button_RightDown: RDown=true; break;
484  case C4MC_Button_RightUp: RDown=false; break;
485  }
486  }
487 
488  void CMouse::Draw(C4TargetFacet &cgo, TooltipShowState draw_tool_tips)
489  {
490  // only if owned
491  if (!fActive) return;
492 
493  // Make sure to draw the cursor without zoom.
494  ZoomData GuiZoom;
495  pDraw->GetZoom(&GuiZoom);
496  const float oldZoom = GuiZoom.Zoom;
497  GuiZoom.Zoom = 1.0;
498  pDraw->SetZoom(GuiZoom);
499 
500  int32_t iOffsetX = -GfxR->fctMouseCursor.Wdt/2;
501  int32_t iOffsetY = -GfxR->fctMouseCursor.Hgt/2;
502  GfxR->fctMouseCursor.Draw(cgo.Surface,x+iOffsetX,y+iOffsetY,0);
503  // ToolTip
504  if (pMouseOverElement && draw_tool_tips != TTST_None)
505  {
506  if (draw_tool_tips == TTST_All || pMouseOverElement->IsImmediateToolTip())
507  {
508  const char *szTip = pMouseOverElement->GetToolTip();
509  if (szTip && *szTip)
510  {
511  C4TargetFacet cgoTip; cgoTip.Set(cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt);
512  Screen::DrawToolTip(szTip, cgoTip, x, y);
513  }
514  }
515  }
516 
517  // And restore old zoom settings.
518  GuiZoom.Zoom = oldZoom;
519  pDraw->SetZoom(GuiZoom);
520  }
521 
523  {
524  // release MouseOver
526  // release drag
527  if (pDragElement)
528  {
529  int32_t iX, iY; DWORD dwKeys;
530  GetLastXY(iX, iY, dwKeys);
532  pDragElement->StopDragging(*this, iX, iY, dwKeys);
533  }
535  }
536 
538  {
539  // clear ptr
540  if (pMouseOverElement == pChild)
541  {
542  pMouseOverElement->MouseLeave(*this); // do leave callback so any tooltip is cleared!
543  pMouseOverElement = nullptr;
544  }
545  if (pPrevMouseOverElement == pChild) pPrevMouseOverElement = nullptr;
546  if (pDragElement == pChild) pDragElement = nullptr;
547  }
548 
550  {
551  // clear ptr
552  RemoveElement(pChild);
553  }
554 
555 
556 // --------------------------------------------------
557 // Screen
558 
560  {
561  // inherited
562  Window::RemoveElement(pChild);
563  // clear ptrs
564  if (pActiveDlg == pChild) { pActiveDlg = nullptr; Mouse.ResetElements(); }
565  Mouse.RemoveElement(pChild);
566  if (pContext)
567  {
568  if (pContext == pChild) pContext=nullptr;
569  else pContext->RemoveElement(pChild);
570  }
571  }
572 
573  Screen::Screen() : Window(), Mouse(0, 0), pContext(nullptr), fExclusive(true), fZoom(1.0f)
574  {
575  // no dialog active
576  pActiveDlg = nullptr;
577  // set static var
578  pScreen = this;
579  }
580 
581  void Screen::Init(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt)
582  {
583  Mouse.x = tx+twdt/2;
584  Mouse.y = ty+thgt/2;
585  fZoom = 1.0f;
586  // set size - calcs client area as well
587  SetBounds(C4Rect(tx,ty,twdt,thgt));
588  SetPreferredDlgRect(C4Rect(0,0,twdt,thgt));
589  }
590 
592  {
594  // dtor: Close context menu
595  AbortContext(false);
596  // fields reset
597  fExclusive = true;
598  fZoom = 1.0f;
599  }
600 
602  {
603  // clear singleton
604  if (this == pScreen) pScreen = nullptr;
605  }
606 
608  {
609  // redraw fullscreen BG if dlgs are dragged around in shared mode
610  if (!IsExclusive())
612  }
613 
614  void Screen::ShowDialog(Dialog *pDlg, bool fFade)
615  {
616  assert(pDlg);
617  // do place console mode dialogs
618  if (!Application.isEditor || pDlg->IsViewportDialog())
619  // exclusive or free dlg: center pos
620  // evaluate own placement proc first
621  if (!pDlg->DoPlacement(this, PreferredDlgRect))
622  {
623  if (pDlg->IsFreePlaceDialog())
624  pDlg->SetPos((GetWidth() - pDlg->GetWidth()) / 2, (GetHeight() - pDlg->GetHeight()) / 2 + pDlg->IsBottomPlacementDialog()*GetHeight()/3);
625  else if (IsExclusive())
626  pDlg->SetPos((GetWidth() - pDlg->GetWidth()) / 2, (GetHeight() - pDlg->GetHeight()) / 2);
627  else
628  // non-exclusive mode at preferred viewport pos
630  }
631  // add to local component list at correct ordering
632  int32_t iNewZ = pDlg->GetZOrdering(); Element *pEl; Dialog *pOtherDlg;
633  for (pEl = GetFirst(); pEl; pEl = pEl->GetNext())
634  if ((pOtherDlg = pEl->GetDlg()))
635  if (pOtherDlg->GetZOrdering() > iNewZ)
636  break;
637  InsertElement(pDlg, pEl);
638  // set as active, if not fading and on top
639  if (!fFade && !pEl)
640  // but not viewport dialogs!
641  if (!pDlg->IsExternalDrawDialog())
642  pActiveDlg = pDlg;
643  // show it
644  pDlg->fOK = false;
645  pDlg->fShow = true;
646  // mouse focus might have changed
648  }
649 
651  {
652  // no change?
653  if (pActiveDlg == pDlg) return;
654  // in single-mode: release any MouseOver/Drag of previous dlg
655  if (IsExclusive())
657  // close any context menu
658  AbortContext(false);
659  // set as active dlg
660  pActiveDlg = pDlg;
661  // ensure it's last in the list, if it's not a specially ordered dlg
662  if (!pDlg->GetZOrdering() && pDlg->GetNext())
663  MakeLastElement(pDlg);
664  }
665 
666  void Screen::CloseDialog(Dialog *pDlg, bool fFade)
667  {
668  // hide dlg
669  if (!fFade) pDlg->fShow = false;
670  // kill from active
671  if (pActiveDlg == pDlg)
672  {
673  // release any MouseOver/Drag of previous dlg
675  // close context menu: probably belonging to closed dlg anyway
676  AbortContext(false);
677  // set new active dlg
679  // do not set yet if it's fading
680  if (pActiveDlg && pActiveDlg->IsFading()) pActiveDlg = nullptr;
681  }
682  // redraw background; clip update
684  }
685 
687  {
688  Dialog *pNewTop = GetTopDialog();
689  if (pActiveDlg == pNewTop) return;
691  // do not set yet if it's fading
692  if (pActiveDlg && pActiveDlg->IsFading()) pActiveDlg = nullptr;
693  }
694 
696  {
697  // search backwards in component list
698  Dialog *pDlg;
699  for (Element *pEl = pLast; pEl; pEl = pEl->GetPrev())
700  if ((pDlg = pEl->GetDlg()))
701  if (pDlg->IsShown())
702  return pDlg;
703  // no dlg found
704  return nullptr;
705  }
706 
707  void Screen::CloseAllDialogs(bool fWithOK)
708  {
709  while (pActiveDlg) pActiveDlg->Close(fWithOK);
710  }
711 #ifdef USE_WIN32_WINDOWS
712  Dialog *Screen::GetDialog(HWND hWindow)
713  {
714  // get dialog with matching handle
715  Dialog *pDlg;
716  for (Element *pEl = pLast; pEl; pEl = pEl->GetPrev())
717  if ((pDlg = pEl->GetDlg()))
718  if (pDlg->pWindow && pDlg->pWindow->hWindow == hWindow)
719  return pDlg;
720  return nullptr;
721  }
722 #endif
724  {
725  // get dialog with matching window
726  Dialog *pDlg;
727  for (Element *pEl = pLast; pEl; pEl = pEl->GetPrev())
728  if ( (pDlg = pEl->GetDlg()) != nullptr)
729  if (pDlg->pWindow == pWindow)
730  return pDlg;
731  return nullptr;
732  }
733  void Screen::Render(bool fDoBG)
734  {
735  // get output cgo
736  C4TargetFacet cgo;
738  // draw to it
739  Draw(cgo, fDoBG);
740  }
741 
743  {
744  // draw mouse cursor
745  // All tool tips hidden during keyboard input. Immediate tooltips hidden if mouse was moving recently.
747  }
748 
749  void Screen::Draw(C4TargetFacet &cgo, bool fDoBG)
750  {
751  // draw bg, if this won't be done by a fullscreen dialog
752  if (fDoBG)
753  {
754  Dialog *pFSDlg = GetFullscreenDialog(false);
755  if (!pFSDlg || !pFSDlg->HasBackground())
756  {
759  else
760  // loader not yet loaded: black BG
761  pDraw->DrawBoxDw(cgo.Surface, 0,0, cgo.Wdt+1, cgo.Hgt+1, 0x00000000);
762  }
763  }
764  // draw contents (if GUI-gfx are loaded, which is assumed in GUI-drawing-functions)
766  {
767  Window::Draw(cgo);
768  if (pContext) pContext->Draw(cgo);
769  }
770  // draw mouse cursor
771  if (!Application.isEditor) RenderMouse(cgo);
772  }
773 
775  {
776  // mark keystroke in mouse
778  // key not yet processed
779  return false;
780  }
781 
782  bool Screen::CharIn(const char * c)
783  {
784  // Special: Tab chars are ignored, because they are always handled as focus advance
785  if (c[0] == 0x09) return false;
786  // mark in mouse
788  // no processing if focus is not set
789  if (!HasKeyboardFocus()) return false;
790  // always return true in exclusive mode (which means: key processed)
791  bool fResult = IsExclusive();
792  // context menu: forward to context
793  if (pContext) return pContext->CharIn(c) || fResult;
794  // no active dlg?
795  if (!pActiveDlg || !pActiveDlg->IsVisible()) return fResult;
796  // forward to dialog
797  return pActiveDlg->CharIn(c) || fResult;
798  }
799 
800  void Screen::MouseMove(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, class C4Viewport *pVP)
801  {
802  // Special: Pass to MouseControl if dragging and button is not upped
803  if (IsActive() && !::MouseControl.IsDragging())
804  {
805  bool fResult = MouseInput(iButton, iX, iY, dwKeyParam, nullptr, pVP);
806  if (HasMouseFocus()) { SetMouseInGUI(true, true); return; }
807  // non-exclusive GUI: inform mouse-control about GUI-result
808  SetMouseInGUI(fResult, true);
809  // abort if GUI processed it
810  if (fResult) return;
811  }
812  else
813  // no GUI: mouse is not in GUI
814  SetMouseInGUI(false, true);
815  // mouse control enabled?
816  if (!::MouseControl.IsActive())
817  {
818  // enable mouse in GUI, if a mouse-only-dlg is displayed
820  SetMouseInGUI(true, true);
821  return;
822  }
823  // Pass on to mouse controlled viewport
824  ::Viewports.MouseMoveToViewport(iButton, iX, iY, dwKeyParam);
825  }
826 
827  void Screen::SetMouseInGUI(bool fInGUI, bool fByMouse)
828  {
829  // inform mouse control and GUI
830  Mouse.SetOwnedMouse(fInGUI);
831  // initial movement to ensure mouse control pos is correct
832  if (!::MouseControl.IsMouseOwned() && !fInGUI && !fByMouse)
833  {
836  }
837  ::MouseControl.SetOwnedMouse(!fInGUI);
838  }
839 
840  bool Screen::MouseInput(int32_t iButton, int32_t iPxX, int32_t iPxY, DWORD dwKeyParam, Dialog *pForDlg, class C4Viewport *pForVP)
841  {
842  // convert from screen pixel coordinates to GUI coordinates
843  float fZoom = pForDlg ? 1.0f : GetZoom(); // Developer mode dialogs are currently drawn unzoomed
844  float fX = float(iPxX) / fZoom;
845  float fY = float(iPxY) / fZoom;
846  // forward to mouse
847  Mouse.Input(iButton, fX, fY, dwKeyParam);
848 
849  // dragging
850  if (Mouse.pDragElement)
851  {
852  int32_t iX2=fX, iY2=fY;
854  if (!Mouse.IsLDown())
855  {
856  // stop dragging
857  Mouse.pDragElement->StopDragging(Mouse, iX2, iY2, dwKeyParam);
858  Mouse.pDragElement = nullptr;
859  }
860  else
861  {
862  // continue dragging
863  Mouse.pDragElement->DoDragging(Mouse, iX2, iY2, dwKeyParam);
864  }
865  }
866  // backup previous MouseOver-element
868  Mouse.pMouseOverElement = nullptr;
869  bool fProcessed = false;
870  // active context menu?
871  if (!pForVP && pContext && pContext->CtxMouseInput(Mouse, iButton, fX, fY, dwKeyParam))
872  {
873  // processed by context menu: OK!
874  }
875  // otherwise: active dlg and inside screen? (or direct forward to specific dlg/viewport dlg)
876  else if (rcBounds.Contains(fX, fY) || pForDlg || pForVP)
877  {
878  // context menu open but mouse down command issued? close context then
879  if (pContext && (iButton == C4MC_Button_LeftDown || iButton == C4MC_Button_RightDown))
880  AbortContext(true);
881  // get client pos
882  if (!pForDlg && !pForVP)
883  {
884  C4Rect &rcClientArea = GetClientRect();
885  fX -= rcClientArea.x; fY -= rcClientArea.y;
886  }
887  // exclusive mode: process active dialog only
888  if (IsExclusive() && !pForDlg && !pForVP)
889  {
891  {
892  // bounds check to dlg: only if not dragging
893  C4Rect &rcDlgBounds = pActiveDlg->GetBounds();
894  if (Mouse.IsLDown() || rcDlgBounds.Contains(fX, fY))
895  // forward to active dialog
896  pActiveDlg->MouseInput(Mouse, iButton, fX - rcDlgBounds.x, fY - rcDlgBounds.y, dwKeyParam);
897  else
898  Mouse.pMouseOverElement = nullptr;
899  }
900  else
901  // outside dialog: own handling (for screen context menu)
902  Window::MouseInput(Mouse, iButton, fX, fY, dwKeyParam);
903  }
904  else
905  {
906  // non-exclusive mode: process all dialogs; make them active on left-click
907  Dialog *pDlg;
908  for (Element *pEl = pLast; pEl; pEl = pEl->GetPrev())
909  if ((pDlg = pEl->GetDlg()))
910  if (pDlg->IsShown())
911  {
912  // if specified: process specified dlg only
913  if (pForDlg && pDlg != pForDlg) continue;
914  // if specified: process specified viewport only
915  bool fIsExternalDrawDialog = pDlg->IsExternalDrawDialog();
916  C4Viewport *pVP = fIsExternalDrawDialog ? pDlg->GetViewport() : nullptr;
917  if (pForVP && pForVP != pVP) continue;
918  // calc offset
919  C4Rect &rcDlgBounds = pDlg->GetBounds();
920  int32_t iOffX=0, iOffY=0;
921  // special handling for viewport dialogs
922  if (fIsExternalDrawDialog)
923  {
924  // ignore external drawing dialogs without a viepwort assigned
925  if (!pVP) continue;
926  // always clip to viewport bounds
927  C4Rect rcOut(pVP->GetOutputRect());
928  if (!rcOut.Contains(fX + rcBounds.x, fY + rcBounds.y)) continue;
929  // viewport dialogs: Offset determined by viewport position
930  iOffX = rcOut.x; iOffY = rcOut.y;
931  }
932  // hit test; or special: dragging possible outside active dialog
933  if (rcDlgBounds.Contains(fX-iOffX, fY-iOffY) || (pDlg == pActiveDlg && Mouse.pDragElement && Mouse.pDragElement->GetDlg() == pDlg))
934  {
935  // Okay; do input
936  pDlg->MouseInput(Mouse, iButton, fX - rcDlgBounds.x - iOffX, fY - rcDlgBounds.y - iOffY, dwKeyParam);
937  // CAUTION: pDlg may be invalid now!
938  // set processed-flag manually
939  fProcessed = true;
940  // inactive dialogs get activated by clicks
941  if (Mouse.IsLDown() && pDlg != pActiveDlg)
942  // but not viewport dialogs!
943  if (!pDlg->IsExternalDrawDialog())
944  ActivateDialog(pDlg);
945  // one dlg only; break loop here
946  break;
947  }
948  }
949  }
950  }
951 
952  // check if MouseOver has changed
954  {
955  // send events
958  }
959  // return whether anything processed it
960  return fProcessed || Mouse.pDragElement || (Mouse.pMouseOverElement && Mouse.pMouseOverElement!=this) || pContext;
961  }
962 
964  {
965  return MouseInput(C4MC_Button_None, Mouse.x, Mouse.y, Mouse.dwKeys, nullptr, nullptr);
966  }
967 
969  {
970  // when exclusive mode has changed: Make sure mouse clip is correct
972  }
973 
974  void Screen::DoContext(ContextMenu *pNewCtx, Element *pAtElement, int32_t iX, int32_t iY)
975  {
976  assert(pNewCtx); assert(pNewCtx != pContext);
977  // close previous context menu
978  AbortContext(false);
979  // element offset
980  if (pAtElement) pAtElement->ClientPos2ScreenPos(iX, iY);
981  // usually open bottom right
982  // check bottom bounds
983  if (iY + pNewCtx->GetBounds().Hgt >= GetBounds().Hgt)
984  {
985  // bottom too narrow: open to top, if height is sufficient
986  // otherwise, open to top from bottom screen pos
987  if (iY < pNewCtx->GetBounds().Hgt) iY = GetBounds().Hgt;
988  iY -= pNewCtx->GetBounds().Hgt;
989  }
990  // check right bounds likewise
991  if (iX + pNewCtx->GetBounds().Wdt >= GetBounds().Wdt)
992  {
993  // bottom too narrow: open to top, if height is sufficient
994  // otherwise, open to top from bottom screen pos
995  if (iX < pNewCtx->GetBounds().Wdt) iX = GetBounds().Wdt;
996  iX -= pNewCtx->GetBounds().Wdt;
997  }
998  // open new
999  (pContext = pNewCtx)->Open(pAtElement, iX, iY);
1000  }
1001 
1003  {
1004  Dialog *pDlg; int32_t iResult=0;
1005  for (Element *pEl = GetFirst(); pEl; pEl = pEl->GetNext())
1006  if ((pDlg = pEl->GetDlg()))
1007  if (pDlg->IsShown() && pDlg->IsMouseControlled())
1008  ++iResult;
1009  return iResult;
1010  }
1011 
1012  void Screen::DrawToolTip(const char *szTip, C4TargetFacet &cgo, float x, float y)
1013  {
1014  CStdFont *pUseFont = &(::GraphicsResource.TooltipFont);
1015  StdStrBuf sText;
1016  pUseFont->BreakMessage(szTip, std::min<int32_t>(C4GUI_MaxToolTipWdt, std::max<int32_t>(cgo.Wdt, 50)), &sText, true);
1017  // get tooltip rect
1018  int32_t tWdt,tHgt;
1019  if (pUseFont->GetTextExtent(sText.getData(), tWdt, tHgt, true))
1020  {
1021  tWdt+=6; tHgt+=4;
1022  int32_t tX, tY;
1023  if (y < cgo.Y+cgo.TargetY+tHgt+5) tY = std::min<int32_t>(y+5, cgo.TargetY+cgo.Hgt-tHgt); else tY = y-tHgt-5;
1024  tX = Clamp<int32_t>(x-tWdt/2, cgo.TargetX+cgo.X, cgo.TargetX+cgo.Wdt-tWdt);
1025  // draw tooltip box
1026  pDraw->DrawBoxDw(cgo.Surface, tX,tY,tX+tWdt-1,tY+tHgt-2, C4GUI_ToolTipBGColor);
1027  pDraw->DrawFrameDw(cgo.Surface, tX,tY,tX+tWdt-1,tY+tHgt-1, C4GUI_ToolTipFrameColor);
1028  // draw tooltip
1029  pDraw->TextOut(sText.getData(), *pUseFont, 1.0f, cgo.Surface, tX+3,tY+1, C4GUI_ToolTipColor, ALeft);
1030  // while there's a tooltip, redraw the bg, because it might overlap
1032  }
1033  }
1034 
1035  bool Screen::HasFullscreenDialog(bool fIncludeFading)
1036  {
1037  return !!GetFullscreenDialog(fIncludeFading);
1038  }
1039 
1040  Dialog *Screen::GetFullscreenDialog(bool fIncludeFading)
1041  {
1042  Dialog *pDlg;
1043  for (Element *pEl = GetFirst(); pEl; pEl = pEl->GetNext())
1044  if ((pDlg = pEl->GetDlg()))
1045  if (pDlg->IsVisible())
1046  if (pDlg->IsFullscreenDialog())
1047  if (fIncludeFading || !pDlg->IsFading())
1048  return pDlg;
1049  return nullptr;
1050  }
1051 
1053  {
1054  // Gamepad is always kept open now.
1055  }
1056 
1058 
1059 // --------------------------------------------------
1060 // ComponentAligner
1061 
1062  bool ComponentAligner::GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
1063  {
1064  rcOut.x = rcClientArea.x + iMarginX;
1065  rcOut.y = rcClientArea.y + iMarginY;
1066  rcOut.Wdt = rcClientArea.Wdt - iMarginX * 2;
1067  rcOut.Hgt = iHgt;
1068  int32_t d = iHgt + iMarginY * 2;
1069  rcClientArea.y += d; rcClientArea.Hgt -= d;
1070  // get centered in width as specified
1071  if (iWdt >= 0)
1072  {
1073  rcOut.x += (rcOut.Wdt - iWdt) / 2;
1074  rcOut.Wdt = iWdt;
1075  }
1076  return rcClientArea.Hgt >= 0;
1077  }
1078 
1079  bool ComponentAligner::GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
1080  {
1081  rcOut.x = rcClientArea.x + iMarginX;
1082  rcOut.y = rcClientArea.y + iMarginY;
1083  rcOut.Wdt = iWdt;
1084  rcOut.Hgt = rcClientArea.Hgt - iMarginY * 2;
1085  int32_t d = iWdt + iMarginX * 2;
1086  rcClientArea.x += d; rcClientArea.Wdt -= d;
1087  // get centered in height as specified
1088  if (iHgt >= 0)
1089  {
1090  rcOut.y += (rcOut.Hgt - iHgt) / 2;
1091  rcOut.Hgt = iHgt;
1092  }
1093  return rcClientArea.Wdt >= 0;
1094  }
1095 
1096  bool ComponentAligner::GetFromRight(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
1097  {
1098  rcOut.x = rcClientArea.x + rcClientArea.Wdt - iWdt - iMarginX;
1099  rcOut.y = rcClientArea.y + iMarginY;
1100  rcOut.Wdt = iWdt;
1101  rcOut.Hgt = rcClientArea.Hgt - iMarginY * 2;
1102  rcClientArea.Wdt -= iWdt + iMarginX * 2;
1103  // get centered in height as specified
1104  if (iHgt >= 0)
1105  {
1106  rcOut.y += (rcOut.Hgt - iHgt) / 2;
1107  rcOut.Hgt = iHgt;
1108  }
1109  return rcClientArea.Wdt >= 0;
1110  }
1111 
1112  bool ComponentAligner::GetFromBottom(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
1113  {
1114  rcOut.x = rcClientArea.x + iMarginX;
1115  rcOut.y = rcClientArea.y + rcClientArea.Hgt - iHgt - iMarginY;
1116  rcOut.Wdt = rcClientArea.Wdt - iMarginX * 2;
1117  rcOut.Hgt = iHgt;
1118  rcClientArea.Hgt -= iHgt + iMarginY * 2;
1119  // get centered in width as specified
1120  if (iWdt >= 0)
1121  {
1122  rcOut.x += (rcOut.Wdt - iWdt) / 2;
1123  rcOut.Wdt = iWdt;
1124  }
1125  return rcClientArea.Hgt >= 0;
1126  }
1127 
1129  {
1130  rcOut.x = rcClientArea.x + iMarginX;
1131  rcOut.y = rcClientArea.y + iMarginY;
1132  rcOut.Wdt = rcClientArea.Wdt - iMarginX * 2;
1133  rcOut.Hgt = rcClientArea.Hgt - iMarginY * 2;
1134  }
1135 
1136  bool ComponentAligner::GetCentered(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
1137  {
1138  rcOut.x = rcClientArea.GetMiddleX() - iWdt/2;
1139  rcOut.y = rcClientArea.GetMiddleY() - iHgt/2;
1140  rcOut.Wdt = iWdt;
1141  rcOut.Hgt = iHgt;
1142  // range check
1143  return rcOut.Wdt+iMarginX*2 <= rcClientArea.Wdt && rcOut.Hgt+iMarginY*2 <= rcClientArea.Hgt;
1144  }
1145 
1146  void ComponentAligner::LogIt(const char *szName)
1147  {
1148  LogF("ComponentAligner %s: (%d,%d)+(%d,%d), Margin (%d,%d)", szName, rcClientArea.x, rcClientArea.y, rcClientArea.Wdt, rcClientArea.Hgt, iMarginX, iMarginY);
1149  }
1150 
1151  C4Rect &ComponentAligner::GetGridCell(int32_t iSectX, int32_t iSectXMax, int32_t iSectY, int32_t iSectYMax, int32_t iSectSizeX, int32_t iSectSizeY, bool fCenterPos, int32_t iSectNumX, int32_t iSectNumY)
1152  {
1153  int32_t iSectSizeXO = iSectSizeX, iSectSizeYO = iSectSizeY;
1154  int32_t iSectSizeXMax = (rcClientArea.Wdt-iMarginX) / iSectXMax - iMarginX;
1155  int32_t iSectSizeYMax = (rcClientArea.Hgt-iMarginY) / iSectYMax - iMarginY;
1156  if (iSectSizeX<0 || fCenterPos) iSectSizeX=iSectSizeXMax; else iSectSizeX=std::min<int32_t>(iSectSizeX, iSectSizeXMax);
1157  if (iSectSizeY<0 || fCenterPos) iSectSizeY=iSectSizeYMax; else iSectSizeY=std::min<int32_t>(iSectSizeY, iSectSizeYMax);
1158  rcTemp.x = iSectX * (iSectSizeX+iMarginX) + iMarginX + rcClientArea.x;
1159  rcTemp.y = iSectY * (iSectSizeY+iMarginY) + iMarginY + rcClientArea.y;
1160  rcTemp.Wdt = iSectSizeX * iSectNumX + iMarginX*(iSectNumX-1); rcTemp.Hgt = iSectSizeY * iSectNumY + iMarginY*(iSectNumY-1);
1161  if (iSectSizeXO>=0 && fCenterPos)
1162  {
1163  rcTemp.x += (iSectSizeX - iSectSizeXO)/2;
1164  rcTemp.Wdt = iSectSizeXO;
1165  }
1166  if (iSectSizeYO>=0 && fCenterPos)
1167  {
1168  rcTemp.y += (iSectSizeY - iSectSizeYO)/2;
1169  rcTemp.Hgt = iSectSizeYO;
1170  }
1171  return rcTemp;
1172  }
1173 
1174 
1175 // --------------------------------------------------
1176 // Global stuff
1177 
1178  void GUISound(const char *szSound)
1179  {
1180  if (Config.Sound.FESamples)
1181  StartSoundEffect(szSound);
1182  }
1183 
1184 
1185 // --------------------------------------------------
1186 // Static vars
1187 
1189  Screen *Screen::pScreen;
1190 
1191 
1192 } // end of namespace
1193 
const char * getData() const
Definition: StdBuf.h:450
#define C4GUI_ToolTipColor
Definition: C4Gui.h:74
bool HasKeyboardFocus()
Definition: C4Gui.h:2668
virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
bool Contains(int32_t iX, int32_t iY) const
Definition: C4Rect.h:42
C4Config Config
Definition: C4Config.cpp:837
const int32_t C4MC_Button_LeftDown
void GUISound(const char *szSound)
Definition: C4Gui.cpp:1178
virtual void StartDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:260
float Y
Definition: C4Facet.h:120
void DrawHVBar(C4TargetFacet &cgo, DynBarFacet &rFacets, C4DrawTransform &trf, int32_t iMiddleLength)
Definition: C4Gui.cpp:376
C4FacetSurface fctBackground
bool fShow
Definition: C4Gui.h:2081
Dialog * GetTopDialog()
Definition: C4Gui.cpp:695
void AbortContext(bool fByUser)
Definition: C4Gui.h:2654
Element * pDragElement
Definition: C4Gui.h:2553
#define GfxR
float fZoom
Definition: C4Gui.h:2594
void SetPos(int32_t iXPos, int32_t iYPos)
Definition: C4Gui.h:860
int Wdt
Definition: C4Surface.h:67
virtual void RemoveElement(Element *pChild)
Definition: C4GuiMenu.cpp:366
virtual void RemoveElement(Element *pChild)
Definition: C4Gui.cpp:559
uint32_t GetNextCharacter(const char **pszString)
Definition: Standard.h:88
virtual Container * GetContainer()
Definition: C4Gui.h:410
void UpdateMouseFocus()
Definition: C4Gui.cpp:968
void Clear()
Definition: StdBuf.h:474
#define b
C4Facet fctScrollDTop
Definition: C4Gui.h:362
virtual bool IsBottomPlacementDialog()
Definition: C4Gui.h:2161
ContextHandler * pContextHandler
Definition: C4Gui.h:381
void ResetActiveInput()
Definition: C4Gui.h:2577
bool IsVisible()
Definition: C4Gui.cpp:202
bool DoContext()
Definition: C4Gui.cpp:418
C4Surface * pSurface
Definition: C4Window.h:279
C4Facet fctScrollDBottom
Definition: C4Gui.h:362
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:410
int32_t y
Definition: C4Gui.h:2532
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:570
bool RDown
Definition: C4Gui.h:2533
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
const int32_t C4MC_Button_RightUp
#define C4GUI_ToolTipFrameColor
Definition: C4Gui.h:73
void Close(bool fOK)
Element * pLast
Definition: C4Gui.h:750
Definition: C4Rect.h:29
DWORD MakeColorReadableOnBlack(DWORD &rdwClr)
Definition: C4Gui.cpp:99
uint8_t BYTE
DialogWindow * pWindow
Definition: C4Gui.h:2088
void Draw3DFrame(C4TargetFacet &cgo, bool fUp=false, int32_t iIndent=1, BYTE byAlpha=C4GUI_BorderAlpha, bool fDrawTop=true, int32_t iTopOff=0, bool fDrawLeft=true, int32_t iLeftOff=0)
Definition: C4Gui.cpp:292
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
void MouseMoveToViewport(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
static Screen * GetScreenS()
Definition: C4Gui.h:2626
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:864
bool IsImmediateToolTip() const
Definition: C4Gui.h:441
virtual void StopDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:283
bool IsViewportDialog()
Definition: C4Gui.h:2172
void Draw(C4TargetFacet &cgo, TooltipShowState draw_tool_tips)
Definition: C4Gui.cpp:488
int32_t iDragY
Definition: C4Gui.h:379
void SetPreferredDlgRect(const C4Rect &rtNewPref)
Definition: C4Gui.h:2648
virtual void UpdateSize()
Definition: C4Gui.cpp:186
#define C4GUI_ToolTipBGColor
Definition: C4Gui.h:72
bool IsActive()
Definition: C4Gui.h:2630
C4MouseControl MouseControl
Definition: C4Globals.cpp:47
C4Rect GetContainedClientRect()
Definition: C4Gui.h:448
virtual ~Element()
Definition: C4Gui.cpp:162
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
static void DrawToolTip(const char *szTip, C4TargetFacet &cgo, float guix, float guiy)
Definition: C4Gui.cpp:1012
int Hgt
Definition: C4Surface.h:67
C4GraphicsResource GraphicsResource
void SetOwnedMouse(bool fToVal)
#define C4GUI_BorderColor2
Definition: C4Gui.h:86
void DrawLineDw(C4Surface *sfcTarget, float x1, float y1, float x2, float y2, DWORD dwClr, float width=1.0f)
Definition: C4Draw.cpp:617
virtual bool IsFreePlaceDialog()
Definition: C4Gui.h:2158
DynBarFacet barScroll
Definition: C4Gui.h:361
void RecheckActiveDialog()
Definition: C4Gui.cpp:686
void GetLastXY(int32_t &rX, int32_t &rY, DWORD &rdwKeys)
Definition: C4Gui.h:2564
bool IsShown()
Definition: C4Gui.h:2147
const char * GetToolTip()
Definition: C4Gui.cpp:424
bool fOK
Definition: C4Gui.h:2082
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool IsMouseStill()
Definition: C4Gui.h:2576
static C4Rect rcTemp
Definition: C4Gui.h:2777
void AppendFormat(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:197
virtual void RemoveElement(Element *pChild)
float GetZoom()
Definition: C4Gui.h:2828
void AppendChar(char cChar)
Definition: StdBuf.h:596
C4SoundInstance * StartSoundEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
int32_t GetMiddleX() const
Definition: C4Rect.h:58
int32_t Wdt
Definition: C4Rect.h:32
void DrawFrameDw(C4Surface *sfcDest, int x1, int y1, int x2, int y2, DWORD dwClr, float width=1.0f)
Definition: C4Draw.cpp:644
bool IsExclusive()
Definition: C4Gui.h:2667
bool LDown
Definition: C4Gui.h:2533
C4Rect & GetAll()
Definition: C4Gui.h:2795
bool ExpandHotkeyMarkup(StdStrBuf &sText, uint32_t &rcHotkey, bool for_tooltip)
Definition: C4Gui.cpp:39
bool IsLDown()
Definition: C4Gui.h:2562
#define C4GUI_BorderColor1
Definition: C4Gui.h:85
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1194
int iResult
Definition: C4GroupMain.cpp:39
void ReleaseElements()
Definition: C4Gui.cpp:522
int32_t GetHeight()
Definition: C4Gui.h:444
bool IsFading()
Definition: C4Gui.h:2151
virtual void SetVisibility(bool fToValue)
Definition: C4Gui.cpp:208
bool MouseInput(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, Dialog *pDlg, class C4Viewport *pVP)
Definition: C4Gui.cpp:840
virtual bool CharIn(const char *c)
Definition: C4GuiMenu.cpp:455
void DrawBar(C4TargetFacet &cgo, DynBarFacet &rFacets)
Definition: C4Gui.cpp:309
const int32_t C4MC_Button_LeftUp
void Clear()
Definition: C4Gui.cpp:591
bool GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1062
int32_t y
Definition: C4Rect.h:32
bool fDragging
Definition: C4Gui.h:380
virtual C4Viewport * GetViewport()
Definition: C4Gui.h:2171
Element * GetFirst()
Definition: C4Gui.h:829
void DrawT(C4Surface *sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform)
Definition: C4Facet.cpp:76
C4Facet fctMiddle
Definition: C4Gui.h:351
Element * pPrevMouseOverElement
Definition: C4Gui.h:2552
void DrawX(C4Surface *sfcTarget, float iX, float iY, float iWdt, float iHgt, int32_t iPhaseX=0, int32_t iPhaseY=0) const
Definition: C4Facet.cpp:358
bool fActive
Definition: C4Gui.h:2536
void Init(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt)
Definition: C4Gui.cpp:581
bool RecheckMouseInput()
Definition: C4Gui.cpp:963
virtual void ApplyElementOffset(int32_t &riX, int32_t &riY)
Definition: C4Gui.h:840
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
void LogIt(const char *szName)
Definition: C4Gui.cpp:1146
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:849
C4Rect GetToprightCornerRect(int32_t iWidth=16, int32_t iHeight=16, int32_t iHIndent=4, int32_t iVIndent=4, int32_t iIndexX=0)
Definition: C4Gui.cpp:400
C4Rect rcBounds
Definition: C4Gui.h:385
void RenderMouse(C4TargetFacet &cgo)
Definition: C4Gui.cpp:742
void Set(const C4Facet &cpy)
Definition: C4Facet.h:184
void Take(char *pnData)
Definition: StdBuf.h:465
void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true)
Definition: C4Facet.cpp:154
Container * GetParent()
Definition: C4Gui.h:429
void InsertElement(Element *pChild, Element *pInsertBefore)
virtual bool IsMenu()
Definition: C4Gui.h:403
virtual void ElementSizeChanged(Element *pOfElement)
Definition: C4Gui.h:753
virtual ContextHandler * GetContextHandler()
Definition: C4Gui.cpp:430
C4Rect GetOutputRect()
Definition: C4Viewport.h:64
C4Draw * pDraw
Definition: C4Draw.cpp:45
virtual bool HasBackground()
Definition: C4Gui.h:2154
int32_t LDownX
Definition: C4Gui.h:2534
int32_t GetMouseControlledDialogCount()
Definition: C4Gui.cpp:1002
virtual void RemoveElement(Element *pChild)
Definition: C4Gui.cpp:174
bool HasFullscreenDialog(bool fIncludeFading)
Definition: C4Gui.cpp:1035
DWORD dwKeys
Definition: C4Gui.h:2535
Container * pParent
Definition: C4Gui.h:376
virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:245
C4LoaderScreen * pLoaderScreen
virtual Dialog * GetDlg()
Definition: C4Gui.h:2116
float GetZoom() const
Definition: C4Gui.h:2628
void Set(const C4Facet &rByFct, int32_t iPinIndex=0)
Definition: C4Gui.cpp:137
int32_t GetMiddleY() const
Definition: C4Rect.h:59
ContextMenu * pContext
Definition: C4Gui.h:2591
void DrawFullScreen(C4Facet &cgo)
Definition: C4Facet.cpp:184
void MakeLastElement(Element *pChild)
virtual void ElementPosChanged(Element *pOfElement)
Definition: C4Gui.cpp:607
virtual bool IsExternalDrawDialog()
Definition: C4Gui.h:2178
int32_t LDownY
Definition: C4Gui.h:2534
#define C4GUI_MaxToolTipWdt
Definition: C4Gui.h:140
C4Rect & GetBounds()
Definition: C4Gui.h:445
int32_t GetWidth()
Definition: C4Gui.h:443
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
const int32_t C4MC_Button_RightDown
virtual class Dialog * GetDlg()
Definition: C4Gui.cpp:289
void SetOwnedMouse(bool fToVal)
Definition: C4Gui.h:2573
void CloseDialog(Dialog *pDlg, bool fFade)
Definition: C4Gui.cpp:666
void SetHorizontal(C4Surface &rBySfc, int iHeight=0, int iBorderWidth=0)
Definition: C4Gui.cpp:120
virtual int32_t GetZOrdering()
Definition: C4Gui.h:2181
int32_t x
Definition: C4Rect.h:32
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
Definition: C4Rect.cpp:86
virtual bool CharIn(const char *c)
Definition: C4Gui.cpp:782
void Input(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:466
static Screen * pScreen
Definition: C4Gui.h:2596
void CloseAllDialogs(bool fWithOK)
Definition: C4Gui.cpp:707
C4Facet fctBegin
Definition: C4Gui.h:351
Element * GetNext() const
Definition: C4Gui.h:449
float TargetX
Definition: C4Facet.h:167
C4ViewportList Viewports
Definition: C4Viewport.cpp:841
bool HasMouseFocus()
Definition: C4Gui.h:2675
void ResetElements()
Definition: C4Gui.h:2566
void Render(bool fDoBG)
Definition: C4Gui.cpp:733
void DrawHBarByVGfx(C4TargetFacet &cgo, DynBarFacet &rFacets)
Definition: C4Gui.cpp:366
void GetZoom(ZoomData *r)
Definition: C4Draw.h:197
float Hgt
Definition: C4Facet.h:120
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
virtual bool IsFullscreenDialog()
Definition: C4Gui.h:2153
void MouseMove(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam, class C4Viewport *pVP)
Definition: C4Gui.cpp:800
Dialog * GetFullscreenDialog(bool fIncludeFading)
Definition: C4Gui.cpp:1040
void ClientPos2ScreenPos(int32_t &riX, int32_t &riY)
Definition: C4Gui.cpp:232
virtual void Draw(C4TargetFacet &cgo, bool fDoBG)
Definition: C4Gui.cpp:749
void ShowDialog(Dialog *pDlg, bool fFade)
Definition: C4Gui.cpp:614
Dialog * GetDialog(C4Window *pWindow)
Definition: C4Gui.cpp:723
void SetRotate(float iAngle, float fOffX, float fOffY)
C4Rect & GetGridCell(int32_t iSectX, int32_t iSectXMax, int32_t iSectY, int32_t iSectYMax, int32_t iSectSizeX=-1, int32_t iSectSizeY=-1, bool fCenterPos=false, int32_t iSectNumX=1, int32_t iSectNumY=1)
Definition: C4Gui.cpp:1151
bool isNull() const
Definition: StdBuf.h:449
virtual C4Rect & GetClientRect()
Definition: C4Gui.h:447
const int ALeft
Definition: C4Surface.h:43
virtual void ElementPosChanged(Element *pOfElement)
Definition: C4Gui.h:754
const int32_t C4MC_Button_None
bool fVisible
Definition: C4Gui.h:383
void ScreenPos2ClientPos(int32_t &riX, int32_t &riY)
Definition: C4Gui.cpp:219
int32_t x
Definition: C4Gui.h:2532
Window * pDragTarget
Definition: C4Gui.h:378
void DrawVBar(C4TargetFacet &cgo, DynBarFacet &rFacets)
Definition: C4Gui.cpp:360
virtual void ApplyInvElementOffset(int32_t &riX, int32_t &riY)
Definition: C4Gui.h:841
virtual void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
virtual void Draw(C4TargetFacet &cgo)
#define C4GUI_BorderColor3
Definition: C4Gui.h:87
bool GetFromRight(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1096
Element * GetPrev() const
Definition: C4Gui.h:450
int32_t FESamples
Definition: C4Config.h:130
C4Rect PreferredDlgRect
Definition: C4Gui.h:2593
void ResetToolTipTime()
Definition: C4Gui.h:2575
virtual void UpdateOwnPos()
Definition: C4Gui.h:434
virtual void UpdatePos()
Definition: C4Gui.cpp:194
virtual void DoDragging(CMouse &rMouse, int32_t iX, int32_t iY, DWORD dwKeyParam)
Definition: C4Gui.cpp:270
void RemoveElement(Element *pChild)
Definition: C4Gui.cpp:537
C4Facet fctScrollPin
Definition: C4Gui.h:362
virtual Screen * GetScreen()
Definition: C4Gui.cpp:290
virtual bool OnContext(Element *pOnElement, int32_t iX, int32_t iY)=0
int32_t Hgt
Definition: C4Rect.h:32
CMouse Mouse
Definition: C4Gui.h:2587
void OnElementGetsInvisible(Element *pChild)
Definition: C4Gui.cpp:549
virtual bool IsMouseControlled()
Definition: C4Gui.h:2168
CMouse(int32_t iX, int32_t iY)
Definition: C4Gui.cpp:449
bool fActiveInput
Definition: C4Gui.h:2542
C4Surface * Surface
Definition: C4Facet.h:119
bool GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1079
float TargetY
Definition: C4Facet.h:167
Dialog * pActiveDlg
Definition: C4Gui.h:2590
bool IsActiveInput()
Definition: C4Gui.h:2578
int32_t iDragX
Definition: C4Gui.h:379
Screen TheScreen
Definition: C4Gui.cpp:1057
uint32_t DWORD
C4ConfigSound Sound
Definition: C4Config.h:255
void SetMouseInGUI(bool fInGUI, bool fByMouse)
Definition: C4Gui.cpp:827
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
void Copy()
Definition: StdBuf.h:475
float Wdt
Definition: C4Facet.h:120
void SetZoom(float X, float Y, float Zoom)
Definition: C4Draw.cpp:782
Element * pMouseOverElement
Definition: C4Gui.h:2552
bool Inside(T ival, U lbound, V rbound)
Definition: Standard.h:45
bool IsActive(bool fForKeyboard)
float X
Definition: C4Facet.h:120
float Zoom
Definition: C4Draw.h:70
bool CtxMouseInput(CMouse &rMouse, int32_t iButton, int32_t iScreenX, int32_t iScreenY, DWORD dwKeyParam)
Definition: C4GuiMenu.cpp:443
virtual bool DoPlacement(Screen *pOnScreen, const C4Rect &rPreferredDlgRect)
Definition: C4Gui.h:2175
virtual void Draw(C4TargetFacet &cgo)
Definition: C4GuiMenu.cpp:462
C4Application Application
Definition: C4Globals.cpp:44
bool GetCentered(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1136
virtual void MouseEnter(CMouse &rMouse)
Definition: C4Gui.h:413
bool GetFromBottom(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1112
C4Facet fctEnd
Definition: C4Gui.h:351
bool IsInActiveDlg(bool fForKeyboard)
Definition: C4Gui.cpp:436
virtual bool CharIn(const char *c)
virtual void MouseLeave(CMouse &rMouse)
Definition: C4Gui.h:414
void ActivateDialog(Dialog *pDlg)
Definition: C4Gui.cpp:650
bool fExclusive
Definition: C4Gui.h:2592
bool KeyAny()
Definition: C4Gui.cpp:774
void UpdateGamepadGUIControlEnabled()
Definition: C4Gui.cpp:1052
bool MDown
Definition: C4Gui.h:2533