OpenClonk
C4GuiDialogs.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 // generic user interface
18 // dialog base classes and some user dialogs
19 
20 #include "C4Include.h"
22 #include "gui/C4Gui.h"
23 
24 #include "game/C4Application.h"
25 #include "game/C4GameScript.h"
26 #include "game/C4Viewport.h"
27 #include "graphics/C4Draw.h"
29 #include "object/C4DefList.h"
30 #include "object/C4Def.h"
31 
32 #include "graphics/C4DrawGL.h"
33 #include "platform/StdRegistry.h"
34 
35 namespace C4GUI
36 {
37 
38 // --------------------------------------------------
39 // FrameDecoration
40 
42  {
43  pSourceDef = nullptr;
48  fctTop.Default();
50  fctRight.Default();
54  fctLeft.Default();
56  }
57 
58  bool FrameDecoration::SetFacetByAction(C4Def *pOfDef, C4TargetFacet &rfctTarget, const char *szFacetName)
59  {
60  // get action
61  StdStrBuf sActName;
62  sActName.Format("FrameDeco%s", szFacetName);
63  C4PropList *act = pOfDef->GetActionByName(sActName.getData());
64  if (!act) return false;
65  // set facet by it
66  int32_t x = act->GetPropertyInt(P_X);
67  int32_t y = act->GetPropertyInt(P_Y);
68  int32_t wdt = act->GetPropertyInt(P_Wdt);
69  int32_t hgt = act->GetPropertyInt(P_Hgt);
70  int32_t tx = act->GetPropertyInt(P_OffX);
71  int32_t ty = act->GetPropertyInt(P_OffY);
72  if (!wdt || !hgt) return false;
73  rfctTarget.Set(pOfDef->Graphics.GetBitmap(), x, y, wdt, hgt, tx, ty);
74  return true;
75  }
76 
77  bool FrameDecoration::SetByDef(C4ID idSourceDef)
78  {
79  return SetByDef(C4Id2Def(idSourceDef));
80  }
81 
83  {
84  if (!pSrcDef) return false;
85  // script compiled?
86  if (!pSrcDef->Script.IsReady()) return false;
87  // reset old
88  Clear();
89  this->pSourceDef = pSrcDef;
90  this->idSourceDef = pSrcDef->id;
91  // query values
92  dwBackClr = pSrcDef->Call(FormatString(PSF_FrameDecoration, "BackClr" ).getData()).getInt();
93  iBorderTop = pSrcDef->Call(FormatString(PSF_FrameDecoration, "BorderTop" ).getData()).getInt();
94  iBorderLeft = pSrcDef->Call(FormatString(PSF_FrameDecoration, "BorderLeft" ).getData()).getInt();
95  iBorderRight = pSrcDef->Call(FormatString(PSF_FrameDecoration, "BorderRight" ).getData()).getInt();
96  iBorderBottom = pSrcDef->Call(FormatString(PSF_FrameDecoration, "BorderBottom").getData()).getInt();
97  // get gfx
98  SetFacetByAction(pSrcDef, fctTop , "Top" );
99  SetFacetByAction(pSrcDef, fctTopRight , "TopRight" );
100  SetFacetByAction(pSrcDef, fctRight , "Right" );
101  SetFacetByAction(pSrcDef, fctBottomRight, "BottomRight");
102  SetFacetByAction(pSrcDef, fctBottom , "Bottom" );
103  SetFacetByAction(pSrcDef, fctBottomLeft , "BottomLeft" );
104  SetFacetByAction(pSrcDef, fctLeft , "Left" );
105  SetFacetByAction(pSrcDef, fctTopLeft , "TopLeft" );
106  // check for gfx outside main area
108  || (fctTopLeft.TargetX < 0) || (fctLeft.TargetX < 0) || (fctBottomLeft.TargetX < 0)
111  // k, done
112  return true;
113  }
114 
116  {
117  // simply re-set by def
118  return SetByDef(idSourceDef);
119  }
120 
122  {
123  // draw BG
124  int ox = cgo.TargetX+rcBounds.x, oy = cgo.TargetY+rcBounds.y;
125  pDraw->DrawBoxDw(cgo.Surface, ox,oy,ox+rcBounds.Wdt-1,oy+rcBounds.Hgt-1,dwBackClr);
126  // draw borders
127  int x,y,Q;
128  // top
129  if ((Q=fctTop.Wdt))
130  {
131  for (x = iBorderLeft; x < rcBounds.Wdt-iBorderRight; x += fctTop.Wdt)
132  {
133  int w = std::min<int>(fctTop.Wdt, rcBounds.Wdt-iBorderRight-x);
134  fctTop.Wdt = w;
135  fctTop.Draw(cgo.Surface, ox+x, oy+fctTop.TargetY);
136  }
137  fctTop.Wdt = Q;
138  }
139  // left
140  if ((Q=fctLeft.Hgt))
141  {
142  for (y = iBorderTop; y < rcBounds.Hgt-iBorderBottom; y += fctLeft.Hgt)
143  {
144  int h = std::min<int>(fctLeft.Hgt, rcBounds.Hgt-iBorderBottom-y);
145  fctLeft.Hgt = h;
146  fctLeft.Draw(cgo.Surface, ox+fctLeft.TargetX, oy+y);
147  }
148  fctLeft.Hgt = Q;
149  }
150  // right
151  if ((Q=fctRight.Hgt))
152  {
153  for (y = iBorderTop; y < rcBounds.Hgt-iBorderBottom; y += fctRight.Hgt)
154  {
155  int h = std::min<int>(fctRight.Hgt, rcBounds.Hgt-iBorderBottom-y);
156  fctRight.Hgt = h;
157  fctRight.Draw(cgo.Surface, ox+rcBounds.Wdt-iBorderRight+fctRight.TargetX, oy+y);
158  }
159  fctRight.Hgt = Q;
160  }
161  // bottom
162  if ((Q=fctBottom.Wdt))
163  {
164  for (x = iBorderLeft; x < rcBounds.Wdt-iBorderRight; x += fctBottom.Wdt)
165  {
166  int w = std::min<int>(fctBottom.Wdt, rcBounds.Wdt-iBorderRight-x);
167  fctBottom.Wdt = w;
168  fctBottom.Draw(cgo.Surface, ox+x, oy+rcBounds.Hgt-iBorderBottom+fctBottom.TargetY);
169  }
170  fctBottom.Wdt = Q;
171  }
172  // draw edges
177  }
178 
179 // --------------------------------------------------
180 // DialogWindow
181 
182 #ifdef USE_WIN32_WINDOWS
183 
184  C4Window * DialogWindow::Init(C4AbstractApp * pApp, const char * Title, const C4Rect &rcBounds, const char *szID)
185  {
186  C4Window * result = C4Window::Init(C4Window::W_GuiWindow, pApp, Title, &rcBounds);
187  if (result)
188  {
189  // update pos
190  if (szID && *szID)
191  RestoreWindowPosition(hWindow, FormatString("ConsoleGUI_%s", szID).getData(), Config.GetSubkeyPath("Console"), false);
192  // and show
193  ::ShowWindow(hWindow, SW_SHOW);
194  }
195  return result;
196  }
197 
198 #else
199  C4Window * DialogWindow::Init(C4AbstractApp * pApp, const char * Title, const C4Rect &rcBounds, const char *szID)
200  {
201  C4Window * result = C4Window::Init(C4Window::W_GuiWindow, pApp, Title, &rcBounds);
202  if (result)
203  {
204  // update pos
205  if (szID && *szID)
206  RestorePosition(FormatString("ConsoleGUI_%s", szID).getData(), Config.GetSubkeyPath("Console"), false);
207  else
208  SetSize(rcBounds.Wdt, rcBounds.Hgt);
209  }
210  return result;
211  }
212 #endif // _WIN32
213 
215  {
216  if (!pDialog)
217  return; // safety
218  C4Rect r;
219  GetSize(&r);
220  if (pSurface)
221  {
222  pSurface->Wdt = r.Wdt;
223  pSurface->Hgt = r.Hgt;
224 #ifndef USE_CONSOLE
226  glClear(GL_COLOR_BUFFER_BIT);
227 #endif
228  }
229  C4TargetFacet cgo;
230  cgo.Set(nullptr, 0, 0, r.Wdt, r.Hgt, 0, 0);
231  pDialog->Draw(cgo);
232  }
233 
235  {
236  // FIXME: Close the dialog of this window
237  }
238 
240  {
241 #ifdef WITH_QT_EDITOR
242  // TODO: Implement these as Qt editor windows.
243  // This currently creates an empty window in Windows and a segfault in Linux.
244  return false;
245 #endif
246  // already created?
247  if (pWindow) return true;
248  // create it!
249  pWindow = new DialogWindow();
251  {
252  delete pWindow;
253  pWindow = nullptr;
254  return false;
255  }
256  // create rendering context
258  pWindow->pDialog = this;
259  return true;
260  }
261 
263  {
264  if (pWindow)
265  {
266  delete pWindow->pSurface;
267  pWindow->Clear();
268  delete pWindow;
269  pWindow = nullptr;
270  }
271  }
272 
273  Dialog::Dialog(int32_t iWdt, int32_t iHgt, const char *szTitle, bool fViewportDlg):
274  Window(), pTitle(nullptr), pCloseBtn(nullptr), fDelOnClose(false), fViewportDlg(fViewportDlg), pWindow(nullptr), pFrameDeco(nullptr)
275  {
276  // zero fields
277  pActiveCtrl = nullptr;
278  fShow = fOK = false;
279  iFade = 100; eFade = eFadeNone;
280  // add title
281  rcBounds.Wdt = iWdt;
282  SetTitle(szTitle);
283  // set size - calcs client rect as well
284  SetBounds(C4Rect(0,0,iWdt,iHgt));
285  // create key callbacks
287  Keys.emplace_back(K_TAB);
289  {
290  ControllerKeys::Right(Keys);
291  }
292  pKeyAdvanceControl = new C4KeyBinding(Keys, "GUIAdvanceFocus", KEYSCOPE_Gui,
294  Keys.clear();
295  Keys.emplace_back(K_TAB, KEYS_Shift);
297  {
298  ControllerKeys::Left(Keys);
299  }
300  pKeyAdvanceControlB = new C4KeyBinding(Keys, "GUIAdvanceFocusBack", KEYSCOPE_Gui,
302  Keys.clear();
303  Keys.emplace_back(KEY_Any, KEYS_Alt);
304  Keys.emplace_back(KEY_Any, C4KeyShiftState(KEYS_Alt | KEYS_Shift));
305  pKeyHotkey = new C4KeyBinding(Keys, "GUIHotkey", KEYSCOPE_Gui,
306  new DlgKeyCBPassKey<Dialog>(*this, &Dialog::KeyHotkey), C4CustomKey::PRIO_Ctrl);
307  Keys.clear();
308  Keys.emplace_back(K_RETURN);
310  {
311  ControllerKeys::Ok(Keys);
312  }
313  pKeyEnter = new C4KeyBinding(Keys, "GUIDialogOkay", KEYSCOPE_Gui,
315  Keys.clear();
316  Keys.emplace_back(K_ESCAPE);
318  {
320  }
321  pKeyEscape = new C4KeyBinding(Keys, "GUIDialogAbort", KEYSCOPE_Gui,
323  Keys.clear();
324  Keys.emplace_back(KEY_Any);
325  Keys.emplace_back(KEY_Any, KEYS_Shift);
326  pKeyFocusDefControl = new C4KeyBinding(Keys, "GUIFocusDefault", KEYSCOPE_Gui,
327  new DlgKeyCB<Dialog>(*this, &Dialog::KeyFocusDefault), C4CustomKey::PRIO_Dlg);
328  }
329 
331  {
332  // default title font
333  return std::min<int32_t>(::GraphicsResource.TextFont.GetLineHeight(), C4GUI_MinWoodBarHgt);
334  }
335 
336  void Dialog::SetTitle(const char *szTitle, bool fShowCloseButton)
337  {
338  // always keep local copy of title
339  TitleString.Copy(szTitle);
340  // console mode dialogs: Use window bar
342  {
343  if (pWindow) pWindow->SetTitle(szTitle ? szTitle : "");
344  return;
345  }
346  // set new
347  if (szTitle && *szTitle)
348  {
350  if (pTitle)
351  {
352  pTitle->GetBounds() = C4Rect(-GetMarginLeft(), -iTextHgt, rcBounds.Wdt, iTextHgt);
353  // noupdate if title is same - this is necessary to prevent scrolling reset when refilling internal menus
354  if (SEqual(pTitle->GetText(), szTitle)) return;
355  pTitle->SetText(szTitle);
356  }
357  else
358  AddElement(pTitle = new WoodenLabel(szTitle, C4Rect(-GetMarginLeft(), -iTextHgt, rcBounds.Wdt, iTextHgt), C4GUI_CaptionFontClr, &::GraphicsResource.TextFont, ALeft, false));
359  pTitle->SetToolTip(szTitle);
360  pTitle->SetDragTarget(this);
362  if (fShowCloseButton)
363  {
364  pTitle->SetRightIndent(20); // for close button
365  if (!pCloseBtn)
366  {
368  pCloseBtn->SetToolTip(LoadResStr("IDS_MNU_CLOSE"));
369  }
370  else
371  pCloseBtn->GetBounds() = pTitle->GetToprightCornerRect(16,16,4,4,0);
372  }
373  }
374  else
375  {
376  if (pTitle) { delete pTitle; pTitle=nullptr; }
377  if (pCloseBtn) { delete pCloseBtn; pCloseBtn = nullptr; }
378  }
379  }
380 
382  {
383  // kill key bindings
384  delete pKeyAdvanceControl;
385  delete pKeyAdvanceControlB;
386  delete pKeyHotkey;
387  delete pKeyEscape;
388  delete pKeyEnter;
389  delete pKeyFocusDefControl;
390  // clear window
392  // avoid endless delete/close-recursion
393  fDelOnClose = false;
394  // free deco
395  if (pFrameDeco) pFrameDeco->Deref();
396  }
397 
399  {
400  // update title bar position
401  if (pTitle)
402  {
404  pTitle->SetBounds(C4Rect(-GetMarginLeft(), -iTextHgt, rcBounds.Wdt, iTextHgt));
405  if (pCloseBtn) pCloseBtn->SetBounds(pTitle->GetToprightCornerRect(16,16,4,4,0));
406  }
407  // inherited
409  // update assigned window
410  if (pWindow)
411  {
413  }
414  }
415 
417  {
418  // Dialogs with their own windows can only be at 0/0
419  if (pWindow)
420  {
421  rcBounds.x = 0;
422  rcBounds.y = 0;
423  }
425  }
426 
428  {
429  // inherited
430  Window::RemoveElement(pChild);
431  // clear ptr
432  if (pChild == pActiveCtrl) pActiveCtrl = nullptr;
433  }
434 
436  {
437  C4TargetFacet cgo; cgo.Set(cgo0);
438  // Dialogs with a window just ignore the cgo.
439  if (pWindow)
440  {
441  cgo.Surface = pWindow->pSurface;
442  cgo.X = 0; cgo.Y = 0; cgo.Wdt = rcBounds.Wdt; cgo.Hgt = rcBounds.Hgt;
443  }
444  Screen *pScreen;
445  // evaluate fading
446  switch (eFade)
447  {
448  case eFadeNone: break; // no fading
449  case eFadeIn:
450  // fade in
451  if ((iFade+=10) >= 100)
452  {
453  if ((pScreen = GetScreen()))
454  {
455  if (pScreen->GetTopDialog() == this)
456  pScreen->ActivateDialog(this);
457  }
458  eFade = eFadeNone;
459  }
460  break;
461  case eFadeOut:
462  // fade out
463  if ((iFade-=10) <= 0)
464  {
465  fVisible = fShow = false;
466  if ((pScreen = GetScreen()))
467  pScreen->RecheckActiveDialog();
468  eFade = eFadeNone;
469  }
470  }
471  // set fade
472  if (iFade < 100)
473  {
474  if (iFade <= 0) return;
475  pDraw->ActivateBlitModulation((iFade*255/100)<<24 | 0xffffff);
476  }
477  // separate window: Clear background
478  if (pWindow)
479  pDraw->DrawBoxDw(cgo.Surface, rcBounds.x, rcBounds.y, rcBounds.Wdt-1, rcBounds.Hgt-1, (0xff << 24) | (C4GUI_StandardBGColor & 0xffffff) );
480  // draw window + contents (evaluates IsVisible)
481  Window::Draw(cgo);
482  // reset blit modulation
484  // blit output to own window
485  if (pWindow)
486  {
487  // Draw context menu on editor window
488  ContextMenu *menu;
489  if ((menu = GetScreen()->pContext))
490  {
491  if (menu->GetTargetDialog() == this)
492  {
493  menu->Draw(cgo);
494  }
495  }
496  // Editor window: Blit to output
497  C4Rect rtSrc,rtDst;
498  rtSrc.x=rcBounds.x; rtSrc.y=rcBounds.y; rtSrc.Wdt=rcBounds.Wdt; rtSrc.Hgt=rcBounds.Hgt;
499  rtDst.x=0; rtDst.y=0; rtDst.Wdt=rcBounds.Wdt; rtDst.Hgt=rcBounds.Hgt;
500  pWindow->pSurface->PageFlip(&rtSrc, &rtDst);
501  }
502  }
503 
505  {
506  // custom border?
507  if (pFrameDeco)
508  pFrameDeco->Draw(cgo, rcBounds);
509  else
510  {
511  // standard border/bg then
512  // draw background
514  // draw frame
515  Draw3DFrame(cgo);
516  }
517  }
518 
519  bool Dialog::CharIn(const char * c)
520  {
521  // reroute to active control
522  if (pActiveCtrl && pActiveCtrl->CharIn(c)) return true;
523  // unprocessed: Focus default control
524  // Except for space, which may have been processed as a key already
525  // (changing focus here would render buttons unusable, because they switch on KeyUp)
526  Control *pDefCtrl = GetDefaultControl();
527  if (pDefCtrl && pDefCtrl != pActiveCtrl && (!c || *c != 0x20))
528  {
529  SetFocus(pDefCtrl, false);
530  if (pActiveCtrl && pActiveCtrl->CharIn(c))
531  return true;
532  }
533  return false;
534  }
535 
536  bool Dialog::KeyHotkey(const C4KeyCodeEx &key)
537  {
538  StdStrBuf sKey = C4KeyCodeEx::KeyCode2String(key.Key, true, true);
539  // do hotkey procs for standard alphanumerics only
540  if (sKey.getLength() != 1) return false;
541  WORD wKey = WORD(*sKey.getData());
542  if (Inside<WORD>(TOUPPERIFX11(wKey), 'A', 'Z')) if (OnHotkey(char(TOUPPERIFX11(wKey)))) return true;
543  if (Inside<WORD>(TOUPPERIFX11(wKey), '0', '9')) if (OnHotkey(char(TOUPPERIFX11(wKey)))) return true;
544  return false;
545  }
546 
547  bool Dialog::KeyFocusDefault()
548  {
549  // unprocessed key: Focus default control
550  Control *pDefCtrl = GetDefaultControl();
551  if (pDefCtrl && pDefCtrl != pActiveCtrl)
552  SetFocus(pDefCtrl, false);
553  // never mark this as processed, so a later char message to the control may be sent (for deselected chat)
554  return false;
555  }
556 
557  void Dialog::MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam)
558  {
559  // inherited will do...
560  Window::MouseInput(rMouse, iButton, iX, iY, dwKeyParam);
561  }
562 
563  void Dialog::SetFocus(Control *pCtrl, bool fByMouse)
564  {
565  // no change?
566  if (pCtrl == pActiveCtrl) return;
567  // leave old focus
568  if (pActiveCtrl)
569  {
570  Control *pC = pActiveCtrl;
571  pActiveCtrl = nullptr;
572  pC->OnLooseFocus();
573  // if leaving the old focus set a new one, abort here because it looks like the control didn't want to lose focus
574  if (pActiveCtrl) return;
575  }
576  // set new
577  if ((pActiveCtrl = pCtrl)) pCtrl->OnGetFocus(fByMouse);
578  }
579 
580  void Dialog::AdvanceFocus(bool fBackwards)
581  {
582  // get element to start from
583  Element *pCurrElement = pActiveCtrl;
584  // find new control
585  for (;;)
586  {
587  // get next element
588  pCurrElement = GetNextNestedElement(pCurrElement, fBackwards);
589  // end reached: start from beginning
590  if (!pCurrElement && pActiveCtrl) if (!(pCurrElement = GetNextNestedElement(nullptr, fBackwards))) return;
591  // cycled?
592  if (pCurrElement == pActiveCtrl)
593  {
594  // but current is no longer a focus element? Then defocus it and return
595  if (pCurrElement && !pCurrElement->IsFocusElement())
596  SetFocus(nullptr, false);
597  return;
598  }
599  // for list elements, check whether the child can be selected
600  if (pCurrElement->GetParent() && !pCurrElement->GetParent()->IsSelectedChild(pCurrElement)) continue;
601  // check if this is a new control
602  Control *pFocusCtrl = pCurrElement->IsFocusElement();
603  if (pFocusCtrl && pFocusCtrl != pActiveCtrl && pFocusCtrl->IsVisible())
604  {
605  // set focus here...
606  SetFocus(pFocusCtrl, false);
607  // ...done!
608  return;
609  }
610  }
611  // never reached
612  }
613 
614  bool Dialog::Show(Screen *pOnScreen, bool fCB)
615  {
616  // already shown?
617  if (fShow) return false;
618  // default screen
619  if (!pOnScreen) if (!(pOnScreen = Screen::GetScreenS())) return false;
620  // show there
621  pOnScreen->ShowDialog(this, false);
622  fVisible = true;
623  // developer mode: Create window
625  if (!CreateConsoleWindow()) return false;
626  // CB
627  if (fCB) OnShown();
628  return true;
629  }
630 
631  void Dialog::Close(bool fOK)
632  {
633  // already closed?
634  if (!fShow) return;
635  // set OK flag
636  this->fOK = fOK;
637  // get screen
638  Screen *pScreen = GetScreen();
639  if (pScreen) pScreen->CloseDialog(this, false); else fShow = false;
640  // developer mode: Remove window
642  // do callback - last call, because it might do perilous things
643  OnClosed(fOK);
644  }
645 
646  void Dialog::OnClosed(bool fOK)
647  {
648  // developer mode: Remove window
650  // delete when closing?
651  if (fDelOnClose)
652  {
653  fDelOnClose=false;
654  delete this;
655  }
656  }
657 
659  {
660  // Cancel all dialogues if game is left (including e.g. league dialogues)
661  if (::Application.IsQuittingGame()) return false;
662  // main message loop
663  while (fShow)
664  {
665  // dialog idle proc
666  OnIdle();
667  // Modal dialogue during running game is tricky. Do not execute game!
668  bool fGameWasRunning = ::Game.IsRunning;
669  ::Game.IsRunning = false;
670  // handle messages - this may block until the next timer
671  if (!Application.ScheduleProcs())
672  return false; // game GUI and lobby will deleted in Game::Clear()
673  // reset game run state
674  if (fGameWasRunning) ::Game.IsRunning = true;
675  }
676  // return whether dlg was OK
677  return fOK;
678  }
679 
681  {
682  // process messages
683  if (!Application.ScheduleProcs(0))
684  return false;
685  // check status
686  if (!fShow) return false;
687  return true;
688  }
689 
691  {
692  // execute
693  if (Execute()) return true;
694  // delete self if closed
695  delete this;
696  return false;
697  }
698 
699  bool Dialog::IsActive(bool fForKeyboard)
700  {
701  // must be fully visible
702  if (!IsShown() || IsFading()) return false;
703  // screen-less dialogs are always inactive (not yet added)
704  Screen *pScreen = GetScreen();
705  if (!pScreen) return false;
706  // no keyboard focus if screen is in context mode
707  if (fForKeyboard && pScreen->HasContext()) return false;
708  // always okay in shared mode: all dlgs accessible by mouse
709  if (!pScreen->IsExclusive() && !fForKeyboard) return true;
710  // exclusive mode or keyboard input: Only one dlg active
711  return pScreen->pActiveDlg == this;
712  }
713 
714  bool Dialog::FadeIn(Screen *pOnScreen)
715  {
716  // default screen
717  if (!pOnScreen) pOnScreen = Screen::GetScreenS();
718  // fade in there
719  pOnScreen->ShowDialog(this, true);
720  iFade = 0;
721  eFade = eFadeIn;
722  fVisible = true;
723  OnShown();
724  // done, success
725  return true;
726  }
727 
728  void Dialog::FadeOut(bool fCloseWithOK)
729  {
730  // only if shown, or being faded in
731  if (!IsShown() && (!fVisible || eFade!=eFadeIn)) return;
732  // set OK flag
733  this->fOK = fCloseWithOK;
734  // fade out
735  Screen *pOnScreen = GetScreen();
736  if (!pOnScreen) return;
737  pOnScreen->CloseDialog(this, true);
738  eFade = eFadeOut;
739  // do callback - last call, because it might do perilous things
740  OnClosed(fCloseWithOK);
741  }
742 
743  void Dialog::ApplyElementOffset(int32_t &riX, int32_t &riY)
744  {
745  // inherited
746  Window::ApplyElementOffset(riX, riY);
747  // apply viewport offset, if a viewport is assigned
748  C4Viewport *pVP = GetViewport();
749  if (pVP)
750  {
751  C4Rect rcVP(pVP->GetOutputRect());
752  riX -= rcVP.x; riY -= rcVP.y;
753  }
754  }
755 
756  void Dialog::ApplyInvElementOffset(int32_t &riX, int32_t &riY)
757  {
758  // inherited
760  // apply viewport offset, if a viewport is assigned
761  C4Viewport *pVP = GetViewport();
762  if (pVP)
763  {
764  C4Rect rcVP(pVP->GetOutputRect());
765  riX += rcVP.x; riY += rcVP.y;
766  }
767  }
768 
769  void Dialog::SetClientSize(int32_t iToWdt, int32_t iToHgt)
770  {
771  // calc new bounds
772  iToWdt += GetMarginLeft()+GetMarginRight();
773  iToHgt += GetMarginTop()+GetMarginBottom();
774  rcBounds.x += (rcBounds.Wdt - iToWdt)/2;
775  rcBounds.y += (rcBounds.Hgt - iToHgt)/2;
776  rcBounds.Wdt = iToWdt; rcBounds.Hgt = iToHgt;
777  // reflect changes
778  UpdatePos();
779  }
780 
781 
782 // --------------------------------------------------
783 // FullscreenDialog
784 
785  FullscreenDialog::FullscreenDialog(const char *szTitle, const char *szSubtitle)
786  : Dialog(Screen::GetScreenS()->GetClientRect().Wdt, Screen::GetScreenS()->GetClientRect().Hgt, nullptr /* create own title */, false), pFullscreenTitle(nullptr)
787  {
788  // set margins
789  int32_t iScreenX = Screen::GetScreenS()->GetClientRect().Wdt;
790  int32_t iScreenY = Screen::GetScreenS()->GetClientRect().Hgt;
791  if (iScreenX < 500) iDlgMarginX = 2; else iDlgMarginX = iScreenX/50;
792  if (iScreenY < 320) iDlgMarginY = 2; else iDlgMarginY = iScreenY*2/75;
793  // set size - calcs client rect as well
794  SetBounds(C4Rect(0,0,iScreenX,iScreenY));
795  // create title
796  SetTitle(szTitle);
797  // create subtitle (only with upperboard)
798  if (szSubtitle && *szSubtitle && HasUpperBoard())
799  {
801  pSubTitle->SetToolTip(szTitle);
802  }
803  else pSubTitle = nullptr;
804  }
805 
806  void FullscreenDialog::SetTitle(const char *szTitle)
807  {
808  if (pFullscreenTitle) { delete pFullscreenTitle; pFullscreenTitle=nullptr; }
809  // change title text; creates or removes title bar if necessary
810  if (szTitle && *szTitle)
811  {
812  // not using dlg label, which is a wooden label
813  if (HasUpperBoard())
815  else
816  // non-woodbar: Title is centered and in big font
819  pFullscreenTitle->SetToolTip(szTitle);
820  }
821  }
822 
824  {
825  // draw upper board
826  if (HasUpperBoard())
828  }
829 
831  {
832  // inherited to update client rect
834  }
835 
837  {
838  // draw across fullscreen bounds - zoom 1px border to prevent flashing borders by blit offsets
839  rFromFct.DrawFullScreen(cgo);
840  }
841 
842 // --------------------------------------------------
843 // MessageDialog
844 
845  MessageDialog::MessageDialog(const char *szMessage, const char *szCaption, DWORD dwButtons, Icons icoIcon, DlgSize eSize, int32_t *piConfigDontShowAgainSetting, bool fDefaultNo)
846  : Dialog(eSize, 100 /* will be resized */, szCaption, false), piConfigDontShowAgainSetting(piConfigDontShowAgainSetting), pKeyCopy(nullptr), sCopyText()
847  {
849  // get positions
851  // place icon
852  C4Rect rcIcon = caMain.GetFromLeft(C4GUI_IconWdt); rcIcon.Hgt = C4GUI_IconHgt;
853  Icon *pIcon = new Icon(rcIcon, icoIcon); AddElement(pIcon);
854  // centered text for small dialogs and/or dialogs w/o much text (i.e.: no linebreaks)
855  bool fTextCentered;
856  if (eSize != dsRegular)
857  fTextCentered = true;
858  else
859  {
860  int32_t iMsgWdt=0, iMsgHgt=0;
861  rUseFont.GetTextExtent(szMessage, iMsgWdt, iMsgHgt);
862  fTextCentered = ((iMsgWdt <= caMain.GetInnerWidth() - C4GUI_IconWdt - C4GUI_DefDlgIndent*2) && iMsgHgt<=rUseFont.GetLineHeight());
863  }
864  // centered text dialog: waste some icon space on the right to balance dialog
865  if (fTextCentered) caMain.GetFromRight(C4GUI_IconWdt);
866  // place message label
867  // use text with line breaks
868  StdStrBuf sMsgBroken;
869  int iMsgHeight = rUseFont.BreakMessage(szMessage, caMain.GetInnerWidth(), &sMsgBroken, true);
870  Label *pLblMessage = new Label("", caMain.GetFromTop(iMsgHeight), fTextCentered ? ACenter : ALeft, C4GUI_MessageFontClr, &rUseFont, false);
871  pLblMessage->SetText(sMsgBroken.getData(), false);
872  AddElement(pLblMessage);
873  // place do-not-show-again-checkbox
874  if (piConfigDontShowAgainSetting)
875  {
876  int w=100,h=20;
877  const char *szCheckText = LoadResStr("IDS_MSG_DONTSHOW");
878  CheckBox::GetStandardCheckBoxSize(&w, &h, szCheckText, nullptr);
879  CheckBox *pCheck = new C4GUI::CheckBox(caMain.GetFromTop(h, w), szCheckText, !!*piConfigDontShowAgainSetting);
881  AddElement(pCheck);
882  }
883  if (!fTextCentered) caMain.ExpandLeft(C4GUI_DefDlgIndent*2 + C4GUI_IconWdt);
884  // place button(s)
885  ComponentAligner caButtonArea(caMain.GetFromTop(C4GUI_ButtonAreaHgt), 0,0);
886  int32_t iButtonCount = 0;
887  int32_t i=1; while (i) { if (dwButtons & i) ++iButtonCount; i=i<<1; }
888  fHasOK = !!(dwButtons & btnOK) || !!(dwButtons & btnYes);
889  Button *btnFocus = nullptr;
890  if (iButtonCount)
891  {
892  C4Rect rcBtn = caButtonArea.GetCentered(iButtonCount*C4GUI_DefButton2Wdt+(iButtonCount-1)*C4GUI_DefButton2HSpace, C4GUI_ButtonHgt);
893  rcBtn.Wdt = C4GUI_DefButton2Wdt;
894  // OK
895  if (dwButtons & btnOK)
896  {
897  Button *pBtnOK = new OKButton(rcBtn);
898  AddElement(pBtnOK);
900  if (!fDefaultNo) btnFocus = pBtnOK;
901  }
902  // Retry
903  if (dwButtons & btnRetry)
904  {
905  Button *pBtnRetry = new RetryButton(rcBtn);
906  AddElement(pBtnRetry);
908  if (!btnFocus) btnFocus = pBtnRetry;
909 
910  }
911  // Cancel
912  if (dwButtons & btnAbort)
913  {
914  Button *pBtnAbort = new CancelButton(rcBtn);
915  AddElement(pBtnAbort);
917  if (!btnFocus) btnFocus = pBtnAbort;
918  }
919  // Yes
920  if (dwButtons & btnYes)
921  {
922  Button *pBtnYes = new YesButton(rcBtn);
923  AddElement(pBtnYes);
925  if (!btnFocus && !fDefaultNo) btnFocus = pBtnYes;
926  }
927  // No
928  if (dwButtons & btnNo)
929  {
930  Button *pBtnNo = new NoButton(rcBtn);
931  AddElement(pBtnNo);
932  if (!btnFocus) btnFocus = pBtnNo;
933  }
934  // Reset
935  if (dwButtons & btnReset)
936  {
937  Button *pBtnReset = new ResetButton(rcBtn);
938  AddElement(pBtnReset);
940  if (!btnFocus) btnFocus = pBtnReset;
941 
942  }
943  }
944  if (btnFocus) SetFocus(btnFocus, false);
945  // resize to actually needed size
946  SetClientSize(GetClientRect().Wdt, GetClientRect().Hgt - caMain.GetHeight());
947  // Control+C copies text to clipboard
948  sCopyText = strprintf("[%s] %s", szCaption ? szCaption : "", szMessage ? szMessage : "");
949  pKeyCopy = new C4KeyBinding(C4KeyCodeEx(K_C, KEYS_Control), "GUIEditCopy", KEYSCOPE_Gui,
951  }
952 
954 {
955  delete pKeyCopy;
956 }
957 
959 {
960  // Copy text to clipboard
961  ::Application.Copy(sCopyText);
962  return true;
963 }
964 
965 
966 // --------------------------------------------------
967 // ConfirmationDialog
968 
969  ConfirmationDialog::ConfirmationDialog(const char *szMessage, const char *szCaption, BaseCallbackHandler *pCB, DWORD dwButtons, bool fSmall, Icons icoIcon)
970  : MessageDialog(szMessage, szCaption, dwButtons, icoIcon, fSmall ? MessageDialog::dsSmall : MessageDialog::dsRegular)
971  {
972  if ((this->pCB=pCB)) pCB->Ref();
973  // always log confirmation messages
974  LogSilentF("[Cnf] %s: %s", szCaption, szMessage);
975  // confirmations always get deleted on close
976  SetDelOnClose();
977  }
978 
980  {
981  // confirmed only on OK
982  BaseCallbackHandler *pStackCB = fOK ? pCB : nullptr;
983  if (pStackCB) pStackCB->Ref();
984  // caution: this will usually delete the dlg (this)
985  // so the CB-interface is backed up
987  if (pStackCB)
988  {
989  pStackCB->DoCall(nullptr);
990  pStackCB->DeRef();
991  }
992  }
993 
994 
995 // --------------------------------------------------
996 // ProgressDialog
997 
998  ProgressDialog::ProgressDialog(const char *szMessage, const char *szCaption, int32_t iMaxProgress, int32_t iInitialProgress, Icons icoIcon)
999  : Dialog(C4GUI_ProgressDlgWdt, std::max(::GraphicsResource.TextFont.BreakMessage(szMessage, C4GUI_ProgressDlgWdt-3*C4GUI_DefDlgIndent-C4GUI_IconWdt, nullptr, 0, true), C4GUI_IconHgt) + C4GUI_ProgressDlgVRoom, szCaption, false)
1000  {
1001  // get positions
1003  ComponentAligner caButtonArea(caMain.GetFromBottom(C4GUI_ButtonAreaHgt), 0,0);
1004  C4Rect rtProgressBar = caMain.GetFromBottom(C4GUI_ProgressDlgPBHgt);
1005  // place icon
1006  C4Rect rcIcon = caMain.GetFromLeft(C4GUI_IconWdt); rcIcon.Hgt = C4GUI_IconHgt;
1007  Icon *pIcon = new Icon(rcIcon, icoIcon); AddElement(pIcon);
1008  // place message label
1009  // use text with line breaks
1010  StdStrBuf str;
1012  pLblMessage = new Label(str.getData(), caMain.GetAll().GetMiddleX(), caMain.GetAll().y, ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont);
1014  // place progress bar
1015  pBar = new ProgressBar(rtProgressBar, iMaxProgress);
1016  pBar->SetProgress(iInitialProgress);
1017  pBar->SetToolTip(LoadResStr("IDS_DLGTIP_PROGRESS"));
1018  AddElement(pBar);
1019  // place abort button
1020  Button *pBtnAbort = new CancelButton(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
1021  AddElement(pBtnAbort);
1022  }
1023 
1024  void ProgressDialog::SetMessage(const char *szMessage)
1025  {
1026  StdStrBuf str;
1028  pLblMessage->SetText(szMessage);
1029  }
1030 
1031 // --------------------------------------------------
1032 // Some dialog wrappers in Screen class
1033 
1034  bool Screen::ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting)
1035  {
1036  // always log messages
1037  LogSilentF("[Msg] %s: %s", szCaption, szMessage);
1038  if (piConfigDontShowAgainSetting && *piConfigDontShowAgainSetting) return true;
1039 #ifdef USE_CONSOLE
1040  // skip in console mode
1041  return true;
1042 #endif
1043  return ShowRemoveDlg(new MessageDialog(szMessage, szCaption, MessageDialog::btnOK, icoIcon, MessageDialog::dsRegular, piConfigDontShowAgainSetting));
1044  }
1045 
1046  bool Screen::ShowErrorMessage(const char *szMessage)
1047  {
1048  return ShowMessage(szMessage, LoadResStr("IDS_DLG_ERROR"), Ico_Error);
1049  }
1050 
1051  bool Screen::ShowMessageModal(const char *szMessage, const char *szCaption, DWORD dwButtons, Icons icoIcon, int32_t *piConfigDontShowAgainSetting)
1052  {
1053  // always log messages
1054  LogSilentF("[Modal] %s: %s", szCaption, szMessage);
1055  // skip if user doesn't want to see it
1056  if (piConfigDontShowAgainSetting && *piConfigDontShowAgainSetting) return true;
1057  // create message dlg and show modal
1058  return ShowModalDlg(new MessageDialog(szMessage, szCaption, dwButtons, icoIcon, MessageDialog::dsRegular, piConfigDontShowAgainSetting));
1059  }
1060 
1061  ProgressDialog *Screen::ShowProgressDlg(const char *szMessage, const char *szCaption, int32_t iMaxProgress, int32_t iInitialProgress, Icons icoIcon)
1062  {
1063  // create progress dlg
1064  ProgressDialog *pDlg = new ProgressDialog(szMessage, szCaption, iMaxProgress, iInitialProgress, icoIcon);
1065  // show it
1066  if (!pDlg->Show(this, true)) { delete pDlg; return nullptr; }
1067  // return dlg pointer
1068  return pDlg;
1069  }
1070 
1071  bool Screen::ShowModalDlg(Dialog *pDlg, bool fDestruct)
1072  {
1073 #ifdef USE_CONSOLE
1074  // no modal dialogs in console build
1075  // (there's most likely no way to close them!)
1076  if (fDestruct) delete pDlg;
1077  return true;
1078 #endif
1079  // safety
1080  if (!pDlg) return false;
1081  // show it
1082  if (!pDlg->Show(this, true)) { delete pDlg; return false; }
1083  // wait until it is closed
1084  bool fResult = pDlg->DoModal();
1085  if (fDestruct) delete pDlg;
1086  // return result
1087  return fResult;
1088  }
1089 
1091  {
1092  // safety
1093  if (!pDlg) return false;
1094  // mark removal when done
1095  pDlg->SetDelOnClose();
1096  // show it
1097  if (!pDlg->Show(this, true)) { delete pDlg; return false; }
1098  // done, success
1099  return true;
1100  }
1101 
1102 
1103 // --------------------------------------------------
1104 // InputDialog
1105 
1106  InputDialog::InputDialog(const char *szMessage, const char *szCaption, Icons icoIcon, BaseInputCallback *pCB, bool fChatLayout)
1107  : Dialog(fChatLayout ? C4GUI::GetScreenWdt()*4/5 : C4GUI_InputDlgWdt,
1108  fChatLayout ? C4GUI::Edit::GetDefaultEditHeight() + 2 :
1109  std::max(::GraphicsResource.TextFont.BreakMessage(szMessage, C4GUI_InputDlgWdt - 3 * C4GUI_DefDlgIndent - C4GUI_IconWdt, nullptr, 0, true),
1110  C4GUI_IconHgt) + C4GUI_InputDlgVRoom, szCaption, false),
1111  pEdit(nullptr), pCB(pCB), fChatLayout(fChatLayout), pChatLbl(nullptr)
1112  {
1113  if (fChatLayout)
1114  {
1115  // chat input layout
1117  // normal chatbox layout: Left chat label
1118  int32_t w=40,h;
1119  ::GraphicsResource.TextFont.GetTextExtent(szMessage, w,h, true);
1121  caChat.ExpandLeft(2); // undo margin
1122  rcEditBounds = caChat.GetAll();
1124  pChatLbl->SetToolTip(LoadResStr("IDS_DLGTIP_CHAT"));
1126  }
1127  else
1128  {
1129  // regular input dialog layout
1130  // get positions
1132  ComponentAligner caButtonArea(caMain.GetFromBottom(C4GUI_ButtonAreaHgt), 0,0);
1134  // place icon
1135  C4Rect rcIcon = caMain.GetFromLeft(C4GUI_IconWdt); rcIcon.Hgt = C4GUI_IconHgt;
1136  Icon *pIcon = new Icon(rcIcon, icoIcon); AddElement(pIcon);
1137  // place message label
1138  // use text with line breaks
1139  StdStrBuf str;
1141  Label *pLblMessage = new Label(str.getData(), caMain.GetAll().GetMiddleX(), caMain.GetAll().y, ACenter, C4GUI_MessageFontClr, &::GraphicsResource.TextFont);
1142  AddElement(pLblMessage);
1143  // place input edit
1145  // place buttons
1147  rcBtn.Wdt = C4GUI_DefButton2Wdt;
1148  // OK
1149  Button *pBtnOK = new OKButton(rcBtn);
1150  AddElement(pBtnOK);
1151  rcBtn.x += rcBtn.Wdt + C4GUI_DefButton2HSpace;
1152  // Cancel
1153  Button *pBtnAbort = new CancelButton(rcBtn);
1154  AddElement(pBtnAbort);
1155  rcBtn.x += rcBtn.Wdt + C4GUI_DefButton2HSpace;
1156  }
1157  // input dlg always closed in the end
1158  SetDelOnClose();
1159  }
1160 
1161  void InputDialog::SetInputText(const char *szToText)
1162  {
1164  if (szToText)
1165  {
1166  pEdit->InsertText(szToText, false);
1167  pEdit->SelectAll();
1168  }
1169  }
1170 
1172  {
1173  // del old
1174  if (pEdit) delete pEdit;
1175  // add new
1176  pEdit = pCustomEdit;
1178  if (fChatLayout)
1179  {
1180  pEdit->SetToolTip(LoadResStr("IDS_DLGTIP_CHAT"));
1181  pChatLbl->SetClickFocusControl(pEdit); // 2do: to all, to allies, etc.
1182  }
1183  AddElement(pEdit);
1184  SetFocus(pEdit, false);
1185  }
1186 
1187 
1188 // --------------------------------------------------
1189 // InfoDialog
1190 
1191  InfoDialog::InfoDialog(const char *szCaption, int32_t iLineCount)
1192  : Dialog(C4GUI_InfoDlgWdt, ::GraphicsResource.TextFont.GetLineHeight()*iLineCount + C4GUI_InfoDlgVRoom, szCaption, false), iScroll(0)
1193  {
1194  // timer
1195  Application.Add(this);
1197  }
1198 
1199  InfoDialog::InfoDialog(const char *szCaption, int iLineCount, const StdStrBuf &sText)
1200  : Dialog(C4GUI_InfoDlgWdt, ::GraphicsResource.TextFont.GetLineHeight()*iLineCount + C4GUI_InfoDlgVRoom, szCaption, false), iScroll(0)
1201  {
1202  // ctor - init w/o timer
1204  // fill in initial text
1205  for (size_t i=0; i < sText.getLength(); ++i)
1206  {
1207  size_t i0 = i;
1208  while (sText[i] != '|' && sText[i]) ++i;
1209  StdStrBuf sLine = sText.copyPart(i0, i-i0);
1211  }
1213  }
1215  {
1216  Application.Remove(this);
1217  }
1218 
1220  {
1221  // get positions
1223  ComponentAligner caButtonArea(caMain.GetFromBottom(C4GUI_ButtonAreaHgt), 0,0);
1224  // place info box
1225  pTextWin = new TextWindow(caMain.GetAll(), 0, 0, 0, 100, 4096, " ", true, nullptr, 0);
1227  // place close button
1228  Button *pBtnClose = new DlgCloseButton(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
1229  AddElement(pBtnClose); pBtnClose->SetToolTip(LoadResStr("IDS_MNU_CLOSE"));
1230  }
1231 
1232  void InfoDialog::AddLine(const char *szText)
1233  {
1234  // add line to text window
1235  if (!pTextWin) return;
1237  }
1238 
1239  void InfoDialog::AddLineFmt(const char *szFmtString, ...)
1240  {
1241  // compose formatted line
1242  va_list lst; va_start(lst, szFmtString);
1243  StdStrBuf buf;
1244  buf.FormatV(szFmtString, lst);
1245  // add it
1246  AddLine(buf.getData());
1247  }
1248 
1250  {
1251  // safety
1252  if (!pTextWin) return;
1253  // backup scrolling
1254  iScroll = pTextWin->GetScrollPos();
1255  // clear text window, so new text can be added
1256  pTextWin->ClearText(false);
1257  }
1258 
1260  {
1261  // safety
1262  if (!pTextWin) return;
1263  // update text height
1265  // restore scrolling
1266  pTextWin->SetScrollPos(iScroll);
1267  }
1268 
1270  {
1271  // always update
1272  UpdateText();
1273  }
1274 
1275 } // end of namespace
1276 
C4Config Config
Definition: C4Config.cpp:930
const int C4UpperBoardHeight
Definition: C4Constants.h:59
C4Def * C4Id2Def(C4ID id)
Definition: C4DefList.h:84
C4Draw * pDraw
Definition: C4Draw.cpp:42
CStdGL * pGL
Definition: C4DrawGL.cpp:907
C4GameControl Control
#define PSF_FrameDecoration
Definition: C4GameScript.h:90
C4Game Game
Definition: C4Globals.cpp:52
C4Application Application
Definition: C4Globals.cpp:44
C4GraphicsResource GraphicsResource
#define C4GUI_IconHgt
Definition: C4Gui.h:94
#define C4GUI_ProgressDlgPBHgt
Definition: C4Gui.h:137
#define C4GUI_FullscreenCaptionFontClr
Definition: C4Gui.h:161
#define C4GUI_StandardBGColor
Definition: C4Gui.h:66
#define C4GUI_ProgressDlgWdt
Definition: C4Gui.h:130
#define C4GUI_ProgressDlgVRoom
Definition: C4Gui.h:135
#define C4GUI_ButtonAreaHgt
Definition: C4Gui.h:113
#define C4GUI_TitleAutoScrollTime
Definition: C4Gui.h:146
#define C4GUI_InfoDlgVRoom
Definition: C4Gui.h:139
#define C4GUI_DefDlgIndent
Definition: C4Gui.h:132
#define C4GUI_DefButton2Wdt
Definition: C4Gui.h:115
#define C4GUI_CaptionFontClr
Definition: C4Gui.h:37
#define C4GUI_InputDlgWdt
Definition: C4Gui.h:131
#define C4GUI_MinWoodBarHgt
Definition: C4Gui.h:158
#define C4GUI_MessageFontClr
Definition: C4Gui.h:43
#define C4GUI_InfoDlgWdt
Definition: C4Gui.h:138
#define C4GUI_InputDlgVRoom
Definition: C4Gui.h:136
#define C4GUI_IconWdt
Definition: C4Gui.h:93
#define C4GUI_ButtonHgt
Definition: C4Gui.h:111
#define C4GUI_DefButtonWdt
Definition: C4Gui.h:114
#define C4GUI_DefButton2HSpace
Definition: C4Gui.h:116
const C4KeyCode KEY_Any
#define TOUPPERIFX11(key)
@ KEYSCOPE_Gui
C4KeyShiftState
@ KEYS_Shift
@ KEYS_Control
@ KEYS_Alt
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool LogSilentF(const char *strMessage,...)
Definition: C4Log.cpp:272
@ P_Wdt
@ P_Y
@ P_Hgt
@ P_OffX
@ P_OffY
@ P_X
const int ARight
Definition: C4Surface.h:41
const int ALeft
Definition: C4Surface.h:41
const int ACenter
Definition: C4Surface.h:41
uint16_t WORD
uint32_t DWORD
std::string strprintf(const char *format,...)
Definition: Standard.cpp:838
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool Copy(const std::string &text, bool fClipboard=true)
Definition: C4AppMac.mm:34
bool IsQuittingGame() const
Definition: C4Application.h:70
int32_t GamepadGuiControl
Definition: C4Config.h:233
const char * GetSubkeyPath(const char *subkey)
Definition: C4Config.cpp:806
C4ConfigControls Controls
Definition: C4Config.h:263
std::vector< C4KeyCodeEx > CodeList
C4Surface * GetBitmap(DWORD dwClr=0)
Definition: C4Def.h:99
C4DefScriptHost Script
Definition: C4Def.h:181
C4DefGraphics Graphics
Definition: C4Def.h:191
C4ID id
Definition: C4Def.h:101
C4PropList * GetActionByName(const char *actname)
Definition: C4Def.cpp:657
void DeactivateBlitModulation()
Definition: C4Draw.h:189
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:840
void ActivateBlitModulation(DWORD dwWithClr)
Definition: C4Draw.h:188
bool BlitSurfaceTile(C4Surface *sfcSurface, C4Surface *sfcTarget, float iToX, float iToY, float iToWdt, float iToHgt, float iOffsetX, float iOffsetY, C4ShaderCall *shader_call)
Definition: C4Draw.cpp:529
C4Surface * Surface
Definition: C4Facet.h:117
void DrawFullScreen(C4Facet &cgo)
Definition: C4Facet.cpp:184
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true)
Definition: C4Facet.cpp:154
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
virtual void DoCall(class Element *pElement)=0
void SetOnChecked(BaseCallbackHandler *pCB)
static bool GetStandardCheckBoxSize(int *piWdt, int *piHgt, const char *szForCaptionText, CStdFont *pUseFont)
bool GetFromLeft(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1076
void ExpandLeft(int32_t iByWdt)
Definition: C4Gui.h:2812
bool GetCentered(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1133
int32_t GetHeight() const
Definition: C4Gui.h:2804
int32_t GetInnerWidth() const
Definition: C4Gui.h:2808
bool GetFromRight(int32_t iWdt, int32_t iHgt, C4Rect &rcOut)
Definition: C4Gui.cpp:1093
bool GetFromTop(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1059
void GetAll(C4Rect &rcOut)
Definition: C4Gui.cpp:1125
bool GetFromBottom(int32_t iHgt, int32_t iWdt, C4Rect &rcOut)
Definition: C4Gui.cpp:1109
ConfirmationDialog(const char *szMessage, const char *szCaption, BaseCallbackHandler *pCB, DWORD dwButtons=MessageDialog::btnOKAbort, bool fSmall=false, Icons icoIcon=Ico_Confirm)
void OnClosed(bool fOK) override
void AddElement(Element *pChild)
void RemoveElement(Element *pChild) override
virtual bool IsSelectedChild(Element *pChild)
Definition: C4Gui.h:837
bool OnHotkey(uint32_t cHotkey) override
Element * GetNextNestedElement(Element *pPrevElement, bool fBackwards)
void Draw(C4TargetFacet &cgo) override
Definition: C4GuiMenu.cpp:460
Dialog * GetTargetDialog() const
Definition: C4Gui.h:1887
virtual void OnLooseFocus()
Definition: C4Gui.h:1057
virtual void OnGetFocus(bool fByMouse)
Definition: C4Gui.h:1056
virtual bool CharIn(const char *)
Definition: C4Gui.h:1051
bool KeyEnter()
Definition: C4Gui.h:2134
void SetFocus(Control *pCtrl, bool fByMouse)
void SetDelOnClose(bool fToVal=true)
Definition: C4Gui.h:2191
CallbackButton< Dialog, C4GUI::IconButton > * pCloseBtn
Definition: C4Gui.h:2080
virtual bool CharIn(const char *c)
void FadeOut(bool fCloseWithOK)
int32_t GetMarginTop() override
Definition: C4Gui.h:2141
void RemoveElement(Element *pChild) override
int32_t GetMarginBottom() override
Definition: C4Gui.h:2144
Control * pActiveCtrl
Definition: C4Gui.h:2081
bool IsViewportDialog()
Definition: C4Gui.h:2173
virtual void OnIdle()
Definition: C4Gui.h:2210
bool fDelOnClose
Definition: C4Gui.h:2086
virtual C4Viewport * GetViewport()
Definition: C4Gui.h:2172
bool KeyAdvanceFocus(bool fBackwards)
Definition: C4Gui.h:2139
void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override
bool fShow
Definition: C4Gui.h:2082
void OnUserClose(C4GUI::Control *btn)
Definition: C4Gui.h:2205
void Close(bool fOK)
int32_t GetMarginRight() override
Definition: C4Gui.h:2143
bool IsFading()
Definition: C4Gui.h:2152
int32_t iFade
Definition: C4Gui.h:2084
virtual class Control * GetDefaultControl()
Definition: C4Gui.h:2130
static int32_t GetDefaultTitleHeight()
bool KeyEscape()
Definition: C4Gui.h:2136
bool IsShown()
Definition: C4Gui.h:2148
bool IsActive(bool fForKeyboard)
bool fOK
Definition: C4Gui.h:2083
void UpdatePos() override
virtual const char * GetID()
Definition: C4Gui.h:2108
void SetClientSize(int32_t iToWdt, int32_t iToHgt)
bool FadeIn(Screen *pOnScreen)
void ApplyInvElementOffset(int32_t &riX, int32_t &riY) override
~Dialog() override
Fade eFade
Definition: C4Gui.h:2085
void AdvanceFocus(bool fBackwards)
void UpdateSize() override
DialogWindow * pWindow
Definition: C4Gui.h:2089
void Draw(C4TargetFacet &cgo) override
virtual void OnShown()
Definition: C4Gui.h:2209
Dialog(int32_t iWdt, int32_t iHgt, const char *szTitle, bool fViewportDlg)
void ApplyElementOffset(int32_t &riX, int32_t &riY) override
virtual void OnClosed(bool fOK)
bool CreateConsoleWindow()
int32_t GetMarginLeft() override
Definition: C4Gui.h:2142
void DestroyConsoleWindow()
WoodenLabel * pTitle
Definition: C4Gui.h:2079
void SetTitle(const char *szToTitle, bool fShowCloseButton=true)
bool Show(Screen *pOnScreen, bool fCB)
FrameDecoration * pFrameDeco
Definition: C4Gui.h:2090
StdStrBuf TitleString
Definition: C4Gui.h:2087
void DrawElement(C4TargetFacet &cgo) override
void PerformUpdate() override
virtual C4Window * Init(WindowKind windowKind, C4AbstractApp *pApp, const char *Title, const C4Rect *size)
Definition: C4AppT.cpp:109
C4Window * Init(C4AbstractApp *pApp, const char *Title, const C4Rect &rcBounds, const char *szID)
void Close() override
Dialog * pDialog
Definition: C4Gui.h:2033
static int32_t GetDefaultEditHeight()
Definition: C4GuiEdit.cpp:113
bool InsertText(const char *szText, bool fUser)
Definition: C4GuiEdit.cpp:163
void SelectAll()
Definition: C4GuiEdit.cpp:641
void DeleteSelection()
Definition: C4GuiEdit.cpp:149
void SetDragTarget(Window *pToWindow)
Definition: C4Gui.h:464
bool IsVisible()
Definition: C4Gui.cpp:201
C4Rect rcBounds
Definition: C4Gui.h:385
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:399
virtual Screen * GetScreen()
Definition: C4Gui.cpp:289
C4Rect GetContainedClientRect()
Definition: C4Gui.h:448
virtual void UpdateSize()
Definition: C4Gui.cpp:185
void SetBounds(const C4Rect &rcNewBound)
Definition: C4Gui.h:446
friend class TextWindow
Definition: C4Gui.h:472
Container * GetParent()
Definition: C4Gui.h:429
virtual void UpdatePos()
Definition: C4Gui.cpp:193
bool fVisible
Definition: C4Gui.h:383
void SetToolTip(const char *szNewTooltip, bool is_immediate=false)
Definition: C4Gui.cpp:409
virtual Control * IsFocusElement()
Definition: C4Gui.h:432
C4Rect & GetBounds()
Definition: C4Gui.h:445
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:291
bool SetByDef(C4Def *pSrcDef)
C4TargetFacet fctRight
Definition: C4Gui.h:2053
C4TargetFacet fctLeft
Definition: C4Gui.h:2053
C4TargetFacet fctTopRight
Definition: C4Gui.h:2053
uint32_t dwBackClr
Definition: C4Gui.h:2052
C4TargetFacet fctTop
Definition: C4Gui.h:2053
C4TargetFacet fctTopLeft
Definition: C4Gui.h:2053
C4TargetFacet fctBottom
Definition: C4Gui.h:2053
void Draw(C4TargetFacet &cgo, C4Rect &rcDrawArea)
bool fHasGfxOutsideClientArea
Definition: C4Gui.h:2055
C4TargetFacet fctBottomLeft
Definition: C4Gui.h:2053
C4TargetFacet fctBottomRight
Definition: C4Gui.h:2053
void DrawElement(C4TargetFacet &cgo) override
void UpdateOwnPos() override
virtual bool HasUpperBoard()
Definition: C4Gui.h:2242
void DrawBackground(C4TargetFacet &cgo, C4Facet &rFromFct)
void SetTitle(const char *szToTitle)
int32_t GetMarginTop() override
Definition: C4Gui.h:2247
FullscreenDialog(const char *szTitle, const char *szSubtitle)
Label * pFullscreenTitle
Definition: C4Gui.h:2224
void AddLine(const char *szText)
InfoDialog(const char *szCaption, int32_t iLineCount)
void AddLineFmt(const char *szFmtString,...) GNUC_FORMAT_ATTRIBUTE_O
virtual void UpdateText()
Definition: C4Gui.h:2446
~InfoDialog() override
void OnSec1Timer() override
TextWindow * pTextWin
Definition: C4Gui.h:2435
void SetInputText(const char *szToText)
C4Rect rcEditBounds
Definition: C4Gui.h:2411
InputDialog(const char *szMessage, const char *szCaption, Icons icoIcon, BaseInputCallback *pCB, bool fChatLayout=false)
void SetCustomEdit(Edit *pCustomEdit)
Label * pChatLbl
Definition: C4Gui.h:2413
void SetText(const char *szToText, bool fAllowHotkey=true)
Definition: C4GuiLabels.cpp:74
void SetClickFocusControl(Control *pToCtrl)
Definition: C4Gui.h:504
const char * GetText()
Definition: C4Gui.h:503
MessageDialog(const char *szMessage, const char *szCaption, DWORD dwButtons, Icons icoIcon, DlgSize eSize=dsRegular, int32_t *piConfigDontShowAgainSetting=nullptr, bool fDefaultNo=false)
void OnDontShowAgainCheck(C4GUI::Element *pCheckBox)
Definition: C4Gui.h:2345
void SetProgress(int32_t iToProgress)
Definition: C4Gui.h:578
Label * pLblMessage
Definition: C4Gui.h:2372
ProgressBar * pBar
Definition: C4Gui.h:2371
void SetMessage(const char *szMessage)
ProgressDialog(const char *szMessage, const char *szCaption, int32_t iMaxProgress, int32_t iInitialProgress, Icons icoIcon)
bool ShowModalDlg(Dialog *pDlg, bool fDestruct=true)
static Screen * GetScreenS()
Definition: C4Gui.h:2629
ProgressDialog * ShowProgressDlg(const char *szMessage, const char *szCaption, int32_t iMaxProgress=100, int32_t iInitialProgress=0, Icons icoIcon=Ico_Wait)
void ShowDialog(Dialog *pDlg, bool fFade)
Definition: C4Gui.cpp:611
void RecheckActiveDialog()
Definition: C4Gui.cpp:683
bool ShowErrorMessage(const char *szMessage)
bool HasContext()
Definition: C4Gui.h:2660
void ActivateDialog(Dialog *pDlg)
Definition: C4Gui.cpp:647
Dialog * pActiveDlg
Definition: C4Gui.h:2593
bool ShowRemoveDlg(Dialog *pDlg)
bool ShowMessageModal(const char *szMessage, const char *szCaption, DWORD dwButtons, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
bool ShowMessage(const char *szMessage, const char *szCaption, Icons icoIcon, int32_t *piConfigDontShowAgainSetting=nullptr)
void CloseDialog(Dialog *pDlg, bool fFade)
Definition: C4Gui.cpp:663
Dialog * GetTopDialog()
Definition: C4Gui.cpp:692
bool IsExclusive()
Definition: C4Gui.h:2670
int32_t GetScrollPos()
Definition: C4Gui.h:1747
void ClearText(bool fDoUpdate)
Definition: C4Gui.h:1745
void SetScrollPos(int32_t iPos)
Definition: C4Gui.h:1749
void AddTextLine(const char *szText, CStdFont *pFont, DWORD dwClr, bool fDoUpdate, bool fMakeReadableOnBlack, CStdFont *pCaptionFont=nullptr)
Definition: C4Gui.h:1741
void UpdateHeight()
Definition: C4Gui.h:1751
C4Rect rcClientRect
Definition: C4Gui.h:851
void UpdateOwnPos() override
void MouseInput(CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam) override
void Draw(C4TargetFacet &cgo) override
C4Rect & GetClientRect() override
Definition: C4Gui.h:864
void ApplyElementOffset(int32_t &riX, int32_t &riY) override
Definition: C4Gui.h:866
void ApplyInvElementOffset(int32_t &riX, int32_t &riY) override
Definition: C4Gui.h:868
static int32_t GetDefaultHeight(CStdFont *pUseFont=nullptr)
void SetRightIndent(int32_t iNewIndent)
Definition: C4Gui.h:540
void SetAutoScrollTime(uint32_t tDelay)
Definition: C4Gui.h:537
bool IsRunning
Definition: C4Game.h:140
Definition: C4Id.h:26
static const C4ID None
Definition: C4Id.h:39
int32_t GetPropertyInt(C4PropertyName k, int32_t default_val=0) const
Definition: C4PropList.cpp:855
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
Definition: C4Rect.h:28
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30
bool IsReady()
Definition: C4ScriptHost.h:54
int Wdt
Definition: C4Surface.h:65
bool PageFlip(C4Rect *pSrcRt=nullptr, C4Rect *pDstRt=nullptr)
Definition: C4Surface.cpp:310
int Hgt
Definition: C4Surface.h:65
float TargetY
Definition: C4Facet.h:165
float TargetX
Definition: C4Facet.h:165
void Default()
Definition: C4Facet.h:179
void Set(const C4Facet &cpy)
Definition: C4Facet.h:182
int32_t getInt() const
Definition: C4Value.h:112
C4Rect GetOutputRect()
Definition: C4Viewport.h:67
virtual C4Window * Init(WindowKind windowKind, C4AbstractApp *pApp, const char *Title, const C4Rect *size)
Definition: C4AppT.cpp:109
bool GetSize(C4Rect *pRect)
Definition: C4AppT.cpp:108
C4Surface * pSurface
Definition: C4Window.h:275
void SetTitle(const char *Title)
Definition: C4AppT.cpp:114
bool RestorePosition(const char *szWindowName, const char *szSubKey, bool fHidden=false)
Definition: C4AppT.cpp:111
virtual void Clear()
Definition: C4AppT.cpp:102
void SetSize(unsigned int cx, unsigned int cy)
Definition: C4AppT.cpp:113
@ W_GuiWindow
Definition: C4Window.h:265
int GetLineHeight() const
Definition: C4FontLoader.h:125
std::tuple< std::string, int > BreakMessage(const char *szMsg, int iWdt, bool fCheckMarkup, float fZoom=1.0f)
bool GetTextExtent(const char *szText, int32_t &rsx, int32_t &rsy, bool fCheckMarkup=true)
bool PrepareRendering(C4Surface *sfcToSurface) override
Definition: C4DrawGL.cpp:161
bool ScheduleProcs(int iTimeout=1000/36)
void Remove(StdSchedulerProc *pProc)
void Add(StdSchedulerProc *pProc)
void FormatV(const char *szFmt, va_list args)
Definition: StdBuf.cpp:182
const char * getData() const
Definition: StdBuf.h:442
StdStrBuf copyPart(size_t iStart, size_t inSize) const
Definition: StdBuf.h:635
void Copy()
Definition: StdBuf.h:467
size_t getLength() const
Definition: StdBuf.h:445
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174
int32_t GetScreenWdt()
Definition: C4Gui.h:2824
Icons
Definition: C4Gui.h:638
@ Ico_Close
Definition: C4Gui.h:678
@ Ico_Error
Definition: C4Gui.h:652
void Ok(T &keys)
void Left(T &keys)
void Cancel(T &keys)
void Right(T &keys)
static StdStrBuf KeyCode2String(C4KeyCode wCode, bool fHumanReadable, bool fShort)
C4KeyCode Key